aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--CREDITS17
-rw-r--r--Documentation/ABI/testing/debugfs-pktcdvd20
-rw-r--r--Documentation/ABI/testing/sysfs-class-pktcdvd72
-rw-r--r--Documentation/CodingStyle144
-rw-r--r--Documentation/DocBook/Makefile4
-rw-r--r--Documentation/DocBook/genericirq.tmpl4
-rw-r--r--Documentation/DocBook/kernel-api.tmpl8
-rw-r--r--Documentation/DocBook/libata.tmpl2
-rw-r--r--Documentation/SubmitChecklist10
-rw-r--r--Documentation/SubmittingPatches6
-rw-r--r--Documentation/accounting/getdelays.c64
-rw-r--r--Documentation/arm/Samsung-S3C24XX/Overview.txt30
-rw-r--r--Documentation/block/biodoc.txt7
-rw-r--r--Documentation/cachetlb.txt28
-rw-r--r--Documentation/cdrom/packet-writing.txt35
-rw-r--r--Documentation/cpu-freq/core.txt2
-rw-r--r--Documentation/dvb/cards.txt4
-rw-r--r--Documentation/fault-injection/failcmd.sh4
-rw-r--r--Documentation/fault-injection/failmodule.sh31
-rw-r--r--Documentation/fault-injection/fault-injection.txt225
-rw-r--r--Documentation/feature-removal-schedule.txt127
-rw-r--r--Documentation/filesystems/9p.txt20
-rw-r--r--Documentation/filesystems/Locking8
-rw-r--r--Documentation/filesystems/bfs.txt2
-rw-r--r--Documentation/filesystems/fuse.txt4
-rw-r--r--Documentation/filesystems/ntfs.txt2
-rw-r--r--Documentation/filesystems/ocfs2.txt3
-rw-r--r--Documentation/hwmon/f71805f56
-rw-r--r--Documentation/hwmon/it8715
-rw-r--r--Documentation/hwmon/k8temp2
-rw-r--r--Documentation/hwmon/pc8742738
-rw-r--r--Documentation/hwmon/sysfs-interface4
-rw-r--r--Documentation/hwmon/w83627ehf2
-rw-r--r--Documentation/hwmon/w83791d2
-rw-r--r--Documentation/hwmon/w83793106
-rw-r--r--Documentation/i2c/busses/i2c-amd81112
-rw-r--r--Documentation/i2c/busses/i2c-i8015
-rw-r--r--Documentation/i2c/busses/i2c-nforce26
-rw-r--r--Documentation/i386/boot.txt3
-rw-r--r--Documentation/ibm-acpi.txt151
-rw-r--r--Documentation/ioctl-number.txt2
-rw-r--r--Documentation/ioctl/ioctl-decoding.txt24
-rw-r--r--Documentation/kbuild/kconfig-language.txt8
-rw-r--r--Documentation/kdump/kdump.txt249
-rw-r--r--Documentation/kernel-parameters.txt21
-rw-r--r--Documentation/networking/dccp.txt6
-rw-r--r--Documentation/pci.txt702
-rw-r--r--Documentation/powerpc/booting-without-of.txt19
-rw-r--r--Documentation/powerpc/mpc52xx-device-tree-bindings.txt10
-rw-r--r--Documentation/s390/driver-model.txt7
-rw-r--r--Documentation/scsi/aacraid.txt66
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl8
-rw-r--r--Documentation/spi/pxa2xx16
-rw-r--r--Documentation/sysrq.txt66
-rw-r--r--Documentation/tty.txt111
-rw-r--r--Documentation/usb/CREDITS2
-rw-r--r--Documentation/usb/acm.txt4
-rw-r--r--Documentation/video4linux/CARDLIST.cx882
-rw-r--r--Documentation/video4linux/CARDLIST.saa71347
-rw-r--r--Documentation/video4linux/cafe_ccic54
-rw-r--r--Documentation/video4linux/zr36120.txt162
-rw-r--r--Documentation/x86_64/boot-options.txt4
-rw-r--r--MAINTAINERS359
-rw-r--r--Makefile50
-rw-r--r--README4
-rw-r--r--arch/alpha/Kconfig8
-rw-r--r--arch/alpha/kernel/osf_sys.c8
-rw-r--r--arch/alpha/kernel/process.c1
-rw-r--r--arch/arm/Kconfig21
-rw-r--r--arch/arm/configs/at91sam9260ek_defconfig1
-rw-r--r--arch/arm/configs/at91sam9261ek_defconfig1
-rw-r--r--arch/arm/configs/ep93xx_defconfig123
-rw-r--r--arch/arm/configs/iop13xx_defconfig99
-rw-r--r--arch/arm/configs/iop32x_defconfig213
-rw-r--r--arch/arm/configs/iop33x_defconfig110
-rw-r--r--arch/arm/configs/ixp2000_defconfig114
-rw-r--r--arch/arm/configs/ixp23xx_defconfig136
-rw-r--r--arch/arm/configs/lpd270_defconfig103
-rw-r--r--arch/arm/configs/onearm_defconfig126
-rw-r--r--arch/arm/kernel/apm.c2
-rw-r--r--arch/arm/kernel/calls.S37
-rw-r--r--arch/arm/kernel/ecard.c2
-rw-r--r--arch/arm/kernel/entry-armv.S12
-rw-r--r--arch/arm/kernel/head.S26
-rw-r--r--arch/arm/kernel/setup.c4
-rw-r--r--arch/arm/kernel/sys_arm.c13
-rw-r--r--arch/arm/kernel/time.c13
-rw-r--r--arch/arm/kernel/traps.c1
-rw-r--r--arch/arm/mach-at91rm9200/at91rm9200_devices.c2
-rw-r--r--arch/arm/mach-at91rm9200/at91sam9260.c3
-rw-r--r--arch/arm/mach-at91rm9200/at91sam9260_devices.c1
-rw-r--r--arch/arm/mach-at91rm9200/at91sam9261.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-sam9260ek.c1
-rw-r--r--arch/arm/mach-at91rm9200/gpio.c39
-rw-r--r--arch/arm/mach-ep93xx/core.c4
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/cpufreq.c299
-rw-r--r--arch/arm/mach-iop13xx/io.c19
-rw-r--r--arch/arm/mach-iop13xx/iq81340mc.c6
-rw-r--r--arch/arm/mach-iop13xx/iq81340sc.c6
-rw-r--r--arch/arm/mach-iop13xx/irq.c22
-rw-r--r--arch/arm/mach-iop13xx/setup.c2
-rw-r--r--arch/arm/mach-netx/time.c42
-rw-r--r--arch/arm/mach-omap1/Kconfig1
-rw-r--r--arch/arm/mach-omap1/board-osk.c1
-rw-r--r--arch/arm/mach-omap2/board-apollon.c1
-rw-r--r--arch/arm/mach-omap2/gpmc.c21
-rw-r--r--arch/arm/mach-pnx4008/Makefile2
-rw-r--r--arch/arm/mach-pnx4008/i2c.c167
-rw-r--r--arch/arm/mach-pxa/Kconfig16
-rw-r--r--arch/arm/mach-pxa/generic.c4
-rw-r--r--arch/arm/mach-pxa/time.c45
-rw-r--r--arch/arm/mach-pxa/trizeps4.c5
-rw-r--r--arch/arm/mach-realview/core.c13
-rw-r--r--arch/arm/mach-realview/core.h1
-rw-r--r--arch/arm/mach-realview/realview_eb.c1
-rw-r--r--arch/arm/mach-s3c2410/Kconfig25
-rw-r--r--arch/arm/mach-s3c2410/cpu.c1
-rw-r--r--arch/arm/mach-s3c2410/devs.c1
-rw-r--r--arch/arm/mach-s3c2410/dma.c6
-rw-r--r--arch/arm/mach-s3c2410/gpio.c12
-rw-r--r--arch/arm/mach-s3c2410/irq.h2
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-nexcoder.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-osiris.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2413.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-vstms.c1
-rw-r--r--arch/arm/mach-s3c2410/pm-simtec.c1
-rw-r--r--arch/arm/mach-s3c2410/pm.c8
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-clock.c5
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-dma.c9
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-pm.c8
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c3
-rw-r--r--arch/arm/mach-s3c2410/s3c2412-clock.c11
-rw-r--r--arch/arm/mach-s3c2410/s3c2412-dma.c7
-rw-r--r--arch/arm/mach-s3c2410/s3c2412.c2
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c24
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-dma.c3
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.c9
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.h18
-rw-r--r--arch/arm/mach-s3c2410/s3c2442-clock.c22
-rw-r--r--arch/arm/mach-s3c2410/s3c2442.c20
-rw-r--r--arch/arm/mach-s3c2410/s3c244x.c3
-rw-r--r--arch/arm/mach-s3c2410/usb-simtec.h3
-rw-r--r--arch/arm/mach-sa1100/jornada720.c229
-rw-r--r--arch/arm/mach-versatile/core.c14
-rw-r--r--arch/arm/mm/consistent.c2
-rw-r--r--arch/arm/mm/copypage-v4mc.c8
-rw-r--r--arch/arm/mm/copypage-v6.c10
-rw-r--r--arch/arm/mm/copypage-xscale.c8
-rw-r--r--arch/arm/mm/fault-armv.c2
-rw-r--r--arch/arm/mm/flush.c41
-rw-r--r--arch/arm/mm/init.c11
-rw-r--r--arch/arm/mm/ioremap.c105
-rw-r--r--arch/arm/mm/mmu.c28
-rw-r--r--arch/arm/mm/pgd.c2
-rw-r--r--arch/arm/mm/proc-arm1020.S4
-rw-r--r--arch/arm/mm/proc-arm1020e.S4
-rw-r--r--arch/arm/mm/proc-arm1022.S6
-rw-r--r--arch/arm/mm/proc-arm1026.S6
-rw-r--r--arch/arm/mm/proc-arm6_7.S10
-rw-r--r--arch/arm/mm/proc-arm720.S6
-rw-r--r--arch/arm/mm/proc-arm920.S6
-rw-r--r--arch/arm/mm/proc-arm922.S6
-rw-r--r--arch/arm/mm/proc-arm925.S6
-rw-r--r--arch/arm/mm/proc-arm926.S8
-rw-r--r--arch/arm/mm/proc-sa110.S6
-rw-r--r--arch/arm/mm/proc-sa1100.S6
-rw-r--r--arch/arm/mm/proc-syms.c2
-rw-r--r--arch/arm/mm/proc-v6.S39
-rw-r--r--arch/arm/mm/proc-xsc3.S8
-rw-r--r--arch/arm/mm/proc-xscale.S8
-rw-r--r--arch/arm/plat-omap/Kconfig2
-rw-r--r--arch/arm/tools/mach-types25
-rw-r--r--arch/arm/vfp/entry.S1
-rw-r--r--arch/arm/vfp/vfp.h4
-rw-r--r--arch/arm/vfp/vfphw.S26
-rw-r--r--arch/arm/vfp/vfpmodule.c71
-rw-r--r--arch/arm26/Kconfig8
-rw-r--r--arch/arm26/kernel/ecard.c2
-rw-r--r--arch/arm26/kernel/irq.c2
-rw-r--r--arch/avr32/Kconfig8
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c76
-rw-r--r--arch/avr32/configs/atstk1002_defconfig39
-rw-r--r--arch/avr32/kernel/avr32_ksyms.c3
-rw-r--r--arch/avr32/kernel/process.c7
-rw-r--r--arch/avr32/kernel/setup.c24
-rw-r--r--arch/avr32/lib/delay.c2
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c182
-rw-r--r--arch/avr32/mach-at32ap/extint.c22
-rw-r--r--arch/avr32/mach-at32ap/intc.c4
-rw-r--r--arch/avr32/mach-at32ap/pio.c85
-rw-r--r--arch/avr32/mach-at32ap/sm.c289
-rw-r--r--arch/cris/Kconfig8
-rw-r--r--arch/cris/arch-v10/drivers/axisflashmap.c2
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c2
-rw-r--r--arch/cris/arch-v32/drivers/axisflashmap.c2
-rw-r--r--arch/cris/arch-v32/drivers/gpio.c2
-rw-r--r--arch/cris/arch-v32/drivers/sync_serial.c8
-rw-r--r--arch/cris/arch-v32/kernel/signal.c2
-rw-r--r--arch/cris/arch-v32/kernel/smp.c2
-rw-r--r--arch/cris/kernel/profile.c2
-rw-r--r--arch/frv/Kconfig8
-rw-r--r--arch/frv/kernel/pm.c6
-rw-r--r--arch/frv/mm/elf-fdpic.c4
-rw-r--r--arch/h8300/Kconfig8
-rw-r--r--arch/h8300/kernel/ints.c2
-rw-r--r--arch/h8300/platform/h8s/ints.c2
-rw-r--r--arch/i386/Kconfig47
-rw-r--r--arch/i386/Kconfig.cpu8
-rw-r--r--arch/i386/boot/compressed/.gitignore1
-rw-r--r--arch/i386/boot/compressed/head.S2
-rw-r--r--arch/i386/boot/compressed/relocs.c2
-rw-r--r--arch/i386/defconfig38
-rw-r--r--arch/i386/kernel/acpi/boot.c24
-rw-r--r--arch/i386/kernel/acpi/cstate.c10
-rw-r--r--arch/i386/kernel/apm.c8
-rw-r--r--arch/i386/kernel/cpu/common.c15
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Makefile2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c810
-rw-r--r--arch/i386/kernel/cpu/cpufreq/gx-suspmod.c4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c128
-rw-r--r--arch/i386/kernel/cpu/cpufreq/p4-clockmod.c47
-rw-r--r--arch/i386/kernel/cpu/cpufreq/sc520_freq.c7
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c15
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c32
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.h1
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c3
-rw-r--r--arch/i386/kernel/cpuid.c4
-rw-r--r--arch/i386/kernel/e820.c2
-rw-r--r--arch/i386/kernel/efi.c89
-rw-r--r--arch/i386/kernel/entry.S36
-rw-r--r--arch/i386/kernel/io_apic.c34
-rw-r--r--arch/i386/kernel/microcode.c8
-rw-r--r--arch/i386/kernel/module.c4
-rw-r--r--arch/i386/kernel/mpparse.c8
-rw-r--r--arch/i386/kernel/msr.c6
-rw-r--r--arch/i386/kernel/nmi.c16
-rw-r--r--arch/i386/kernel/paravirt.c9
-rw-r--r--arch/i386/kernel/process.c7
-rw-r--r--arch/i386/kernel/ptrace.c21
-rw-r--r--arch/i386/kernel/quirks.c33
-rw-r--r--arch/i386/kernel/setup.c6
-rw-r--r--arch/i386/kernel/smpboot.c27
-rw-r--r--arch/i386/kernel/sysenter.c14
-rw-r--r--arch/i386/kernel/trampoline.S5
-rw-r--r--arch/i386/kernel/traps.c124
-rw-r--r--arch/i386/kernel/tsc.c2
-rw-r--r--arch/i386/kernel/vmlinux.lds.S3
-rw-r--r--arch/i386/mach-default/setup.c2
-rw-r--r--arch/i386/mach-generic/bigsmp.c2
-rw-r--r--arch/i386/mach-generic/default.c2
-rw-r--r--arch/i386/mach-generic/es7000.c2
-rw-r--r--arch/i386/mach-generic/summit.c2
-rw-r--r--arch/i386/mach-visws/setup.c3
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c6
-rw-r--r--arch/i386/mm/discontig.c28
-rw-r--r--arch/i386/mm/init.c14
-rw-r--r--arch/i386/pci/fixup.c13
-rw-r--r--arch/i386/pci/mmconfig.c6
-rw-r--r--arch/ia64/Kconfig8
-rw-r--r--arch/ia64/hp/sim/simserial.c2
-rw-r--r--arch/ia64/ia32/sys_ia32.c4
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/acpi.c6
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c4
-rw-r--r--arch/ia64/kernel/crash.c22
-rw-r--r--arch/ia64/kernel/crash_dump.c48
-rw-r--r--arch/ia64/kernel/irq.c3
-rw-r--r--arch/ia64/kernel/jprobes.S3
-rw-r--r--arch/ia64/kernel/kprobes.c226
-rw-r--r--arch/ia64/kernel/machine_kexec.c7
-rw-r--r--arch/ia64/kernel/mca.c2
-rw-r--r--arch/ia64/kernel/perfmon.c10
-rw-r--r--arch/ia64/kernel/process.c10
-rw-r--r--arch/ia64/kernel/salinfo.c6
-rw-r--r--arch/ia64/kernel/setup.c33
-rw-r--r--arch/ia64/kernel/smp.c4
-rw-r--r--arch/ia64/kernel/traps.c50
-rw-r--r--arch/ia64/mm/contig.c9
-rw-r--r--arch/ia64/mm/init.c14
-rw-r--r--arch/ia64/sn/kernel/io_acpi_init.c3
-rw-r--r--arch/ia64/sn/kernel/setup.c12
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c2
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c15
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c64
-rw-r--r--arch/m32r/Kconfig8
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c7
-rw-r--r--arch/m32r/kernel/entry.S67
-rw-r--r--arch/m32r/kernel/io_opsput.c71
-rw-r--r--arch/m32r/kernel/setup_opsput.c17
-rw-r--r--arch/m32r/kernel/smpboot.c2
-rw-r--r--arch/m32r/mm/fault.c4
-rw-r--r--arch/m68k/Kconfig8
-rw-r--r--arch/m68k/atari/stdma.c2
-rw-r--r--arch/m68k/kernel/sun3-head.S10
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds2
-rw-r--r--arch/m68k/mm/kmap.c2
-rw-r--r--arch/m68k/mm/memory.c4
-rw-r--r--arch/m68k/mm/sun3mmu.c7
-rw-r--r--arch/m68knommu/Kconfig8
-rw-r--r--arch/mips/Kconfig47
-rw-r--r--arch/mips/Makefile17
-rw-r--r--arch/mips/au1000/common/pci.c8
-rw-r--r--arch/mips/configs/atlas_defconfig2
-rw-r--r--arch/mips/configs/bigsur_defconfig2
-rw-r--r--arch/mips/configs/capcella_defconfig2
-rw-r--r--arch/mips/configs/cobalt_defconfig2
-rw-r--r--arch/mips/configs/db1000_defconfig2
-rw-r--r--arch/mips/configs/db1100_defconfig2
-rw-r--r--arch/mips/configs/db1200_defconfig2
-rw-r--r--arch/mips/configs/db1500_defconfig2
-rw-r--r--arch/mips/configs/db1550_defconfig2
-rw-r--r--arch/mips/configs/ddb5477_defconfig2
-rw-r--r--arch/mips/configs/decstation_defconfig2
-rw-r--r--arch/mips/configs/e55_defconfig2
-rw-r--r--arch/mips/configs/emma2rh_defconfig2
-rw-r--r--arch/mips/configs/ev64120_defconfig2
-rw-r--r--arch/mips/configs/excite_defconfig2
-rw-r--r--arch/mips/configs/ip22_defconfig2
-rw-r--r--arch/mips/configs/ip27_defconfig2
-rw-r--r--arch/mips/configs/ip32_defconfig2
-rw-r--r--arch/mips/configs/jaguar-atx_defconfig2
-rw-r--r--arch/mips/configs/jazz_defconfig2
-rw-r--r--arch/mips/configs/jmr3927_defconfig2
-rw-r--r--arch/mips/configs/lasat200_defconfig2
-rw-r--r--arch/mips/configs/malta_defconfig82
-rw-r--r--arch/mips/configs/mipssim_defconfig2
-rw-r--r--arch/mips/configs/mpc30x_defconfig2
-rw-r--r--arch/mips/configs/ocelot_3_defconfig2
-rw-r--r--arch/mips/configs/ocelot_c_defconfig2
-rw-r--r--arch/mips/configs/ocelot_defconfig2
-rw-r--r--arch/mips/configs/ocelot_g_defconfig2
-rw-r--r--arch/mips/configs/pb1100_defconfig2
-rw-r--r--arch/mips/configs/pb1500_defconfig2
-rw-r--r--arch/mips/configs/pb1550_defconfig2
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig2
-rw-r--r--arch/mips/configs/pnx8550-stb810_defconfig1229
-rw-r--r--arch/mips/configs/pnx8550-v2pci_defconfig2
-rw-r--r--arch/mips/configs/qemu_defconfig2
-rw-r--r--arch/mips/configs/rbhma4500_defconfig2
-rw-r--r--arch/mips/configs/rm200_defconfig2
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig2
-rw-r--r--arch/mips/configs/sead_defconfig2
-rw-r--r--arch/mips/configs/tb0226_defconfig2
-rw-r--r--arch/mips/configs/tb0229_defconfig2
-rw-r--r--arch/mips/configs/tb0287_defconfig2
-rw-r--r--arch/mips/configs/workpad_defconfig2
-rw-r--r--arch/mips/configs/wrppmc_defconfig2
-rw-r--r--arch/mips/configs/yosemite_defconfig2
-rw-r--r--arch/mips/dec/prom/memory.c2
-rw-r--r--arch/mips/defconfig2
-rw-r--r--arch/mips/kernel/apm.c2
-rw-r--r--arch/mips/kernel/head.S2
-rw-r--r--arch/mips/kernel/irixelf.c2
-rw-r--r--arch/mips/kernel/kspd.c2
-rw-r--r--arch/mips/kernel/linux32.c16
-rw-r--r--arch/mips/kernel/mips_ksyms.c2
-rw-r--r--arch/mips/kernel/reset.c2
-rw-r--r--arch/mips/kernel/rtlx.c6
-rw-r--r--arch/mips/kernel/scall64-n32.S4
-rw-r--r--arch/mips/kernel/smp.c2
-rw-r--r--arch/mips/kernel/smtc.c65
-rw-r--r--arch/mips/kernel/sysirix.c10
-rw-r--r--arch/mips/kernel/time.c2
-rw-r--r--arch/mips/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/kernel/vpe.c11
-rw-r--r--arch/mips/lasat/sysctl.c23
-rw-r--r--arch/mips/lib/Makefile2
-rw-r--r--arch/mips/lib/csum_partial.S735
-rw-r--r--arch/mips/lib/csum_partial_copy.c49
-rw-r--r--arch/mips/mips-boards/generic/time.c9
-rw-r--r--arch/mips/mips-boards/malta/Makefile1
-rw-r--r--arch/mips/mips-boards/malta/malta_mtd.c63
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c39
-rw-r--r--arch/mips/mips-boards/sead/sead_int.c4
-rw-r--r--arch/mips/mips-boards/sim/sim_setup.c2
-rw-r--r--arch/mips/mm/cache.c1
-rw-r--r--arch/mips/mm/init.c45
-rw-r--r--arch/mips/mm/ioremap.c96
-rw-r--r--arch/mips/mm/pg-r4k.c9
-rw-r--r--arch/mips/mm/tlb-r4k.c1
-rw-r--r--arch/mips/momentum/ocelot_g/prom.c4
-rw-r--r--arch/mips/momentum/ocelot_g/setup.c4
-rw-r--r--arch/mips/pci/Makefile2
-rw-r--r--arch/mips/pci/fixup-pnx8550.c4
-rw-r--r--arch/mips/pci/ops-pnx8550.c2
-rw-r--r--arch/mips/philips/pnx8550/common/prom.c20
-rw-r--r--arch/mips/philips/pnx8550/common/time.c45
-rw-r--r--arch/mips/philips/pnx8550/jbs/irqmap.c8
-rw-r--r--arch/mips/philips/pnx8550/stb810/Makefile4
-rw-r--r--arch/mips/philips/pnx8550/stb810/board_setup.c49
-rw-r--r--arch/mips/philips/pnx8550/stb810/irqmap.c23
-rw-r--r--arch/mips/philips/pnx8550/stb810/prom_init.c49
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c27
-rw-r--r--arch/mips/vr41xx/Kconfig5
-rw-r--r--arch/mips/vr41xx/common/irq.c12
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/irq.c9
-rw-r--r--arch/parisc/Kconfig8
-rw-r--r--arch/parisc/hpux/sys_hpux.c2
-rw-r--r--arch/parisc/kernel/smp.c2
-rw-r--r--arch/parisc/kernel/unwind.c2
-rw-r--r--arch/parisc/mm/ioremap.c111
-rw-r--r--arch/powerpc/Kconfig26
-rw-r--r--arch/powerpc/boot/Makefile3
-rw-r--r--arch/powerpc/boot/dts/lite5200.dts10
-rw-r--r--arch/powerpc/boot/dts/lite5200b.dts10
-rw-r--r--arch/powerpc/configs/cell_defconfig356
-rw-r--r--arch/powerpc/configs/chrp32_defconfig161
-rw-r--r--arch/powerpc/configs/g5_defconfig237
-rw-r--r--arch/powerpc/configs/iseries_defconfig132
-rw-r--r--arch/powerpc/configs/linkstation_defconfig111
-rw-r--r--arch/powerpc/configs/lite5200_defconfig39
-rw-r--r--arch/powerpc/configs/maple_defconfig91
-rw-r--r--arch/powerpc/configs/mpc7448_hpc2_defconfig175
-rw-r--r--arch/powerpc/configs/mpc834x_itx_defconfig187
-rw-r--r--arch/powerpc/configs/mpc834x_mds_defconfig97
-rw-r--r--arch/powerpc/configs/mpc8360emds_defconfig105
-rw-r--r--arch/powerpc/configs/mpc8540_ads_defconfig89
-rw-r--r--arch/powerpc/configs/mpc8560_ads_defconfig96
-rw-r--r--arch/powerpc/configs/mpc85xx_cds_defconfig96
-rw-r--r--arch/powerpc/configs/mpc8641_hpcn_defconfig98
-rw-r--r--arch/powerpc/configs/pmac32_defconfig202
-rw-r--r--arch/powerpc/configs/ppc64_defconfig250
-rw-r--r--arch/powerpc/configs/ps3_defconfig40
-rw-r--r--arch/powerpc/configs/pseries_defconfig224
-rw-r--r--arch/powerpc/kernel/Makefile1
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/cputable.c5
-rw-r--r--arch/powerpc/kernel/entry_64.S13
-rw-r--r--arch/powerpc/kernel/head_32.S7
-rw-r--r--arch/powerpc/kernel/module_32.c23
-rw-r--r--arch/powerpc/kernel/module_64.c23
-rw-r--r--arch/powerpc/kernel/nvram_64.c4
-rw-r--r--arch/powerpc/kernel/of_device.c4
-rw-r--r--arch/powerpc/kernel/of_platform.c3
-rw-r--r--arch/powerpc/kernel/pci_32.c140
-rw-r--r--arch/powerpc/kernel/pci_64.c45
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c2
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c6
-rw-r--r--arch/powerpc/kernel/prom.c55
-rw-r--r--arch/powerpc/kernel/prom_init.c2
-rw-r--r--arch/powerpc/kernel/prom_parse.c15
-rw-r--r--arch/powerpc/kernel/rtas.c35
-rw-r--r--arch/powerpc/kernel/rtas_flash.c16
-rw-r--r--arch/powerpc/kernel/signal_32.c16
-rw-r--r--arch/powerpc/kernel/smp.c2
-rw-r--r--arch/powerpc/kernel/sysfs.c16
-rw-r--r--arch/powerpc/kernel/traps.c56
-rw-r--r--arch/powerpc/kernel/vdso.c7
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S6
-rw-r--r--arch/powerpc/mm/hugetlbpage.c8
-rw-r--r--arch/powerpc/mm/imalloc.c6
-rw-r--r--arch/powerpc/mm/numa.c65
-rw-r--r--arch/powerpc/platforms/4xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c3
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c7
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc8360e_pb.c2
-rw-r--r--arch/powerpc/platforms/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c2
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c2
-rw-r--r--arch/powerpc/platforms/cell/pmu.c5
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1_mmio.c95
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig2
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c4
-rw-r--r--arch/powerpc/platforms/iseries/mf.c6
-rw-r--r--arch/powerpc/platforms/iseries/proc.c11
-rw-r--r--arch/powerpc/platforms/iseries/setup.c3
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c4
-rw-r--r--arch/powerpc/platforms/maple/pci.c2
-rw-r--r--arch/powerpc/platforms/maple/setup.c13
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c1
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig11
-rw-r--r--arch/powerpc/platforms/ps3/Makefile3
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c2
-rw-r--r--arch/powerpc/platforms/pseries/Makefile2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c1
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c13
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c275
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S9
-rw-r--r--arch/powerpc/platforms/pseries/hvCall_inst.c6
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c3
-rw-r--r--arch/powerpc/platforms/pseries/scanlog.c2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c30
-rw-r--r--arch/powerpc/platforms/pseries/smp.c200
-rw-r--r--arch/powerpc/platforms/pseries/xics.c5
-rw-r--r--arch/powerpc/sysdev/Makefile5
-rw-r--r--arch/powerpc/sysdev/dcr.S39
-rw-r--r--arch/powerpc/sysdev/mmio_nvram.c40
-rw-r--r--arch/powerpc/sysdev/mpic.c2
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.c40
-rw-r--r--arch/powerpc/sysdev/rom.c1
-rw-r--r--arch/powerpc/xmon/xmon.c10
-rw-r--r--arch/ppc/8260_io/fcc_enet.c4
-rw-r--r--arch/ppc/8xx_io/cs4218_tdm.c14
-rw-r--r--arch/ppc/Kconfig17
-rw-r--r--arch/ppc/kernel/pci.c41
-rw-r--r--arch/ppc/kernel/traps.c64
-rw-r--r--arch/ppc/platforms/4xx/Kconfig2
-rw-r--r--arch/ppc/platforms/ev64360.c3
-rw-r--r--arch/s390/Kconfig24
-rw-r--r--arch/s390/defconfig48
-rw-r--r--arch/s390/hypfs/hypfs_diag.c4
-rw-r--r--arch/s390/hypfs/inode.c4
-rw-r--r--arch/s390/kernel/debug.c12
-rw-r--r--arch/s390/kernel/head31.S12
-rw-r--r--arch/s390/kernel/head64.S12
-rw-r--r--arch/s390/kernel/ipl.c59
-rw-r--r--arch/s390/kernel/reipl.S6
-rw-r--r--arch/s390/kernel/reipl64.S5
-rw-r--r--arch/s390/kernel/reset.S42
-rw-r--r--arch/s390/kernel/s390_ext.c2
-rw-r--r--arch/s390/kernel/setup.c57
-rw-r--r--arch/s390/kernel/smp.c5
-rw-r--r--arch/s390/lib/uaccess_pt.c8
-rw-r--r--arch/s390/lib/uaccess_std.c3
-rw-r--r--arch/s390/mm/Makefile2
-rw-r--r--arch/s390/mm/extmem.c106
-rw-r--r--arch/s390/mm/init.c184
-rw-r--r--arch/s390/mm/ioremap.c84
-rw-r--r--arch/s390/mm/vmem.c382
-rw-r--r--arch/sh/Kconfig22
-rw-r--r--arch/sh/Kconfig.debug3
-rw-r--r--arch/sh/Makefile7
-rw-r--r--arch/sh/boards/landisk/irq.c4
-rw-r--r--arch/sh/boards/se/7206/irq.c16
-rw-r--r--arch/sh/boards/se/7619/Makefile2
-rw-r--r--arch/sh/boards/se/7619/io.c102
-rw-r--r--arch/sh/boards/se/7619/setup.c21
-rw-r--r--arch/sh/boot/Makefile40
-rw-r--r--arch/sh/boot/compressed/Makefile6
-rw-r--r--arch/sh/boot/compressed/head.S3
-rw-r--r--arch/sh/boot/compressed/misc.c3
-rw-r--r--arch/sh/configs/landisk_defconfig85
-rw-r--r--arch/sh/configs/se7206_defconfig142
-rw-r--r--arch/sh/configs/se7619_defconfig744
-rw-r--r--arch/sh/drivers/push-switch.c13
-rw-r--r--arch/sh/kernel/cpu/Makefile1
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S32
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c41
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c62
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile9
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c9
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c31
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c7
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile19
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh73180.c (renamed from arch/sh/kernel/cpu/sh4/clock-sh73180.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7343.c99
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7770.c (renamed from arch/sh/kernel/cpu/sh4/clock-sh7770.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7780.c (renamed from arch/sh/kernel/cpu/sh4/clock-sh7780.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh73180.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh73180.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh7343.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c80
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7770.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh7770.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh7780.c)0
-rw-r--r--arch/sh/kernel/early_printk.c20
-rw-r--r--arch/sh/kernel/entry-common.S15
-rw-r--r--arch/sh/kernel/head.S3
-rw-r--r--arch/sh/kernel/process.c15
-rw-r--r--arch/sh/kernel/setup.c41
-rw-r--r--arch/sh/kernel/sh_ksyms.c15
-rw-r--r--arch/sh/kernel/signal.c2
-rw-r--r--arch/sh/kernel/sys_sh.c8
-rw-r--r--arch/sh/kernel/traps.c35
-rw-r--r--arch/sh/kernel/vmlinux.lds.S2
-rw-r--r--arch/sh/mm/Kconfig12
-rw-r--r--arch/sh/mm/cache-sh4.c2
-rw-r--r--arch/sh/mm/init.c2
-rw-r--r--arch/sh/mm/ioremap.c90
-rw-r--r--arch/sh/oprofile/op_model_sh7750.c2
-rw-r--r--arch/sh64/Kconfig8
-rw-r--r--arch/sh64/mm/ioremap.c100
-rw-r--r--arch/sparc/Kconfig8
-rw-r--r--arch/sparc/defconfig711
-rw-r--r--arch/sparc/kernel/ioport.c11
-rw-r--r--arch/sparc/kernel/irq.c4
-rw-r--r--arch/sparc/kernel/of_device.c3
-rw-r--r--arch/sparc/kernel/process.c1
-rw-r--r--arch/sparc/kernel/ptrace.c5
-rw-r--r--arch/sparc/kernel/smp.c8
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c8
-rw-r--r--arch/sparc/kernel/sun4d_irq.c9
-rw-r--r--arch/sparc/kernel/sun4d_smp.c2
-rw-r--r--arch/sparc/kernel/sys_sunos.c6
-rw-r--r--arch/sparc/kernel/time.c5
-rw-r--r--arch/sparc/lib/Makefile4
-rw-r--r--arch/sparc/lib/atomic32.c39
-rw-r--r--arch/sparc/lib/bitops.S109
-rw-r--r--arch/sparc/mm/io-unit.c8
-rw-r--r--arch/sparc64/Kconfig16
-rw-r--r--arch/sparc64/Kconfig.debug4
-rw-r--r--arch/sparc64/defconfig82
-rw-r--r--arch/sparc64/kernel/Makefile1
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c4
-rw-r--r--arch/sparc64/kernel/chmc.c3
-rw-r--r--arch/sparc64/kernel/entry.S27
-rw-r--r--arch/sparc64/kernel/head.S15
-rw-r--r--arch/sparc64/kernel/irq.c24
-rw-r--r--arch/sparc64/kernel/isa.c32
-rw-r--r--arch/sparc64/kernel/kprobes.c91
-rw-r--r--arch/sparc64/kernel/of_device.c10
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c16
-rw-r--r--arch/sparc64/kernel/ptrace.c5
-rw-r--r--arch/sparc64/kernel/rtrap.S23
-rw-r--r--arch/sparc64/kernel/smp.c9
-rw-r--r--arch/sparc64/kernel/stacktrace.c41
-rw-r--r--arch/sparc64/kernel/sun4v_ivec.S20
-rw-r--r--arch/sparc64/kernel/sun4v_tlb_miss.S4
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c8
-rw-r--r--arch/sparc64/kernel/traps.c30
-rw-r--r--arch/sparc64/kernel/unaligned.c44
-rw-r--r--arch/sparc64/kernel/visemul.c6
-rw-r--r--arch/sparc64/mm/init.c147
-rw-r--r--arch/sparc64/mm/ultra.S8
-rw-r--r--arch/sparc64/solaris/fs.c4
-rw-r--r--arch/sparc64/solaris/ioctl.c6
-rw-r--r--arch/sparc64/solaris/misc.c6
-rw-r--r--arch/sparc64/solaris/socksys.c14
-rw-r--r--arch/sparc64/solaris/timod.c10
-rw-r--r--arch/um/Kconfig5
-rw-r--r--arch/um/Kconfig.i38658
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/drivers/net_kern.c18
-rw-r--r--arch/um/include/line.h2
-rw-r--r--arch/um/include/net_kern.h2
-rw-r--r--arch/um/kernel/exec.c7
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/bug.c20
-rw-r--r--arch/um/sys-i386/ldt.c4
-rw-r--r--arch/um/sys-i386/signal.c3
-rw-r--r--arch/um/sys-x86_64/Makefile2
-rw-r--r--arch/um/sys-x86_64/bug.c20
-rw-r--r--arch/um/sys-x86_64/signal.c5
-rw-r--r--arch/v850/Kconfig36
-rw-r--r--arch/x86_64/Kconfig15
-rw-r--r--arch/x86_64/Makefile2
-rw-r--r--arch/x86_64/defconfig41
-rw-r--r--arch/x86_64/ia32/ia32_aout.c12
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c49
-rw-r--r--arch/x86_64/ia32/syscall32.c15
-rw-r--r--arch/x86_64/kernel/cpufreq/Kconfig7
-rw-r--r--arch/x86_64/kernel/cpufreq/Makefile2
-rw-r--r--arch/x86_64/kernel/early-quirks.c5
-rw-r--r--arch/x86_64/kernel/entry.S33
-rw-r--r--arch/x86_64/kernel/io_apic.c124
-rw-r--r--arch/x86_64/kernel/module.c5
-rw-r--r--arch/x86_64/kernel/nmi.c11
-rw-r--r--arch/x86_64/kernel/pci-calgary.c22
-rw-r--r--arch/x86_64/kernel/process.c6
-rw-r--r--arch/x86_64/kernel/time.c25
-rw-r--r--arch/x86_64/kernel/traps.c122
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S5
-rw-r--r--arch/x86_64/kernel/vsyscall.c3
-rw-r--r--arch/xtensa/Kconfig29
-rw-r--r--arch/xtensa/Makefile25
-rw-r--r--arch/xtensa/boot/boot-elf/bootstrap.S3
-rw-r--r--arch/xtensa/boot/boot-redboot/bootstrap.S37
-rw-r--r--arch/xtensa/configs/iss_defconfig6
-rw-r--r--arch/xtensa/kernel/Makefile2
-rw-r--r--arch/xtensa/kernel/align.S42
-rw-r--r--arch/xtensa/kernel/asm-offsets.c5
-rw-r--r--arch/xtensa/kernel/coprocessor.S2
-rw-r--r--arch/xtensa/kernel/entry.S256
-rw-r--r--arch/xtensa/kernel/head.S53
-rw-r--r--arch/xtensa/kernel/irq.c107
-rw-r--r--arch/xtensa/kernel/pci-dma.c44
-rw-r--r--arch/xtensa/kernel/process.c108
-rw-r--r--arch/xtensa/kernel/ptrace.c28
-rw-r--r--arch/xtensa/kernel/setup.c41
-rw-r--r--arch/xtensa/kernel/signal.c28
-rw-r--r--arch/xtensa/kernel/syscall.c95
-rw-r--r--arch/xtensa/kernel/syscalls.c288
-rw-r--r--arch/xtensa/kernel/syscalls.h247
-rw-r--r--arch/xtensa/kernel/time.c8
-rw-r--r--arch/xtensa/kernel/traps.c56
-rw-r--r--arch/xtensa/kernel/vectors.S12
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S26
-rw-r--r--arch/xtensa/lib/checksum.S3
-rw-r--r--arch/xtensa/lib/memcopy.S2
-rw-r--r--arch/xtensa/lib/memset.S2
-rw-r--r--arch/xtensa/lib/strncpy_user.S2
-rw-r--r--arch/xtensa/lib/strnlen_user.S2
-rw-r--r--arch/xtensa/lib/usercopy.S2
-rw-r--r--arch/xtensa/mm/fault.c10
-rw-r--r--arch/xtensa/mm/init.c6
-rw-r--r--arch/xtensa/mm/misc.S265
-rw-r--r--arch/xtensa/mm/tlb.c445
-rw-r--r--arch/xtensa/platform-iss/console.c8
-rw-r--r--arch/xtensa/platform-iss/network.c2
-rw-r--r--block/as-iosched.c15
-rw-r--r--block/cfq-iosched.c46
-rw-r--r--block/elevator.c37
-rw-r--r--block/genhd.c31
-rw-r--r--block/ioctl.c6
-rw-r--r--block/ll_rw_blk.c155
-rw-r--r--block/scsi_ioctl.c16
-rw-r--r--crypto/blkcipher.c1
-rw-r--r--crypto/sha512.c2
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acorn/block/fd1772.c4
-rw-r--r--drivers/acorn/char/i2c.c2
-rw-r--r--drivers/acpi/Kconfig6
-rw-r--r--drivers/acpi/ac.c9
-rw-r--r--drivers/acpi/acpi_memhotplug.c5
-rw-r--r--drivers/acpi/asus_acpi.c70
-rw-r--r--drivers/acpi/battery.c31
-rw-r--r--drivers/acpi/bus.c3
-rw-r--r--drivers/acpi/button.c223
-rw-r--r--drivers/acpi/container.c5
-rw-r--r--drivers/acpi/dock.c153
-rw-r--r--drivers/acpi/ec.c354
-rw-r--r--drivers/acpi/events/evmisc.c1
-rw-r--r--drivers/acpi/executer/exmutex.c6
-rw-r--r--drivers/acpi/fan.c9
-rw-r--r--drivers/acpi/glue.c10
-rw-r--r--drivers/acpi/hotkey.c5
-rw-r--r--drivers/acpi/i2c_ec.c8
-rw-r--r--drivers/acpi/ibm_acpi.c1042
-rw-r--r--drivers/acpi/namespace/nsxfobj.c44
-rw-r--r--drivers/acpi/numa.c2
-rw-r--r--drivers/acpi/osl.c5
-rw-r--r--drivers/acpi/pci_bind.c16
-rw-r--r--drivers/acpi/pci_irq.c9
-rw-r--r--drivers/acpi/pci_link.c14
-rw-r--r--drivers/acpi/pci_root.c16
-rw-r--r--drivers/acpi/power.c9
-rw-r--r--drivers/acpi/processor_core.c20
-rw-r--r--drivers/acpi/processor_idle.c26
-rw-r--r--drivers/acpi/processor_perflib.c18
-rw-r--r--drivers/acpi/processor_thermal.c6
-rw-r--r--drivers/acpi/processor_throttling.c6
-rw-r--r--drivers/acpi/sbs.c27
-rw-r--r--drivers/acpi/scan.c3
-rw-r--r--drivers/acpi/sleep/wakeup.c6
-rw-r--r--drivers/acpi/tables.c2
-rw-r--r--drivers/acpi/tables/tbxface.c54
-rw-r--r--drivers/acpi/thermal.c37
-rw-r--r--drivers/acpi/toshiba_acpi.c86
-rw-r--r--drivers/acpi/utilities/utdebug.c5
-rw-r--r--drivers/acpi/utilities/utmutex.c16
-rw-r--r--drivers/acpi/utils.c10
-rw-r--r--drivers/acpi/video.c112
-rw-r--r--drivers/ata/Kconfig12
-rw-r--r--drivers/ata/ahci.c111
-rw-r--r--drivers/ata/ata_generic.c6
-rw-r--r--drivers/ata/ata_piix.c22
-rw-r--r--drivers/ata/libata-core.c31
-rw-r--r--drivers/ata/libata-eh.c6
-rw-r--r--drivers/ata/libata-scsi.c304
-rw-r--r--drivers/ata/libata-sff.c63
-rw-r--r--drivers/ata/pata_atiixp.c11
-rw-r--r--drivers/ata/pata_cmd64x.c23
-rw-r--r--drivers/ata/pata_cs5530.c3
-rw-r--r--drivers/ata/pata_hpt37x.c6
-rw-r--r--drivers/ata/pata_hpt3x2n.c6
-rw-r--r--drivers/ata/pata_it821x.c4
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c5
-rw-r--r--drivers/ata/pata_jmicron.c18
-rw-r--r--drivers/ata/pata_legacy.c8
-rw-r--r--drivers/ata/pata_platform.c3
-rw-r--r--drivers/ata/pata_qdi.c4
-rw-r--r--drivers/ata/pata_rz1000.c8
-rw-r--r--drivers/ata/pata_sil680.c2
-rw-r--r--drivers/ata/pata_via.c15
-rw-r--r--drivers/ata/pata_winbond.c4
-rw-r--r--drivers/ata/pdc_adma.c4
-rw-r--r--drivers/ata/sata_mv.c5
-rw-r--r--drivers/ata/sata_nv.c22
-rw-r--r--drivers/ata/sata_svw.c82
-rw-r--r--drivers/ata/sata_uli.c3
-rw-r--r--drivers/ata/sata_via.c13
-rw-r--r--drivers/ata/sata_vsc.c43
-rw-r--r--drivers/atm/.gitignore2
-rw-r--r--drivers/atm/Kconfig5
-rw-r--r--drivers/atm/ambassador.c17
-rw-r--r--drivers/atm/eni.c4
-rw-r--r--drivers/atm/fore200e.c166
-rw-r--r--drivers/atm/he.c2
-rw-r--r--drivers/atm/horizon.c2
-rw-r--r--drivers/atm/lanai.c2
-rw-r--r--drivers/atm/nicstar.c4
-rw-r--r--drivers/atm/zatm.c4
-rw-r--r--drivers/base/class.c2
-rw-r--r--drivers/base/dmapool.c2
-rw-r--r--drivers/base/firmware_class.c1
-rw-r--r--drivers/base/platform.c4
-rw-r--r--drivers/block/Kconfig21
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/acsi_slm.c4
-rw-r--r--drivers/block/aoe/aoecmd.c13
-rw-r--r--drivers/block/cciss.c33
-rw-r--r--drivers/block/cpqarray.c10
-rw-r--r--drivers/block/loop.c4
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/block/pktcdvd.c596
-rw-r--r--drivers/block/swim_iop.c578
-rw-r--r--drivers/block/viodasd.c6
-rw-r--r--drivers/bluetooth/hci_usb.c8
-rw-r--r--drivers/cdrom/cdrom.c19
-rw-r--r--drivers/cdrom/cm206.c2
-rw-r--r--drivers/cdrom/viocd.c4
-rw-r--r--drivers/char/Kconfig23
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/Kconfig4
-rw-r--r--drivers/char/agp/agp.h4
-rw-r--r--drivers/char/agp/amd-k7-agp.c5
-rw-r--r--drivers/char/agp/amd64-agp.c9
-rw-r--r--drivers/char/agp/ati-agp.c36
-rw-r--r--drivers/char/agp/generic.c36
-rw-r--r--drivers/char/agp/intel-agp.c181
-rw-r--r--drivers/char/agp/sgi-agp.c9
-rw-r--r--drivers/char/agp/via-agp.c21
-rw-r--r--drivers/char/amiserial.c6
-rw-r--r--drivers/char/consolemap.c2
-rw-r--r--drivers/char/cs5535_gpio.c4
-rw-r--r--drivers/char/cyclades.c7769
-rw-r--r--drivers/char/drm/drm.h33
-rw-r--r--drivers/char/drm/drmP.h30
-rw-r--r--drivers/char/drm/drm_bufs.c10
-rw-r--r--drivers/char/drm/drm_core.h8
-rw-r--r--drivers/char/drm/drm_drawable.c294
-rw-r--r--drivers/char/drm/drm_drv.c14
-rw-r--r--drivers/char/drm/drm_ioc32.c56
-rw-r--r--drivers/char/drm/drm_irq.c155
-rw-r--r--drivers/char/drm/drm_lock.c13
-rw-r--r--drivers/char/drm/drm_stub.c14
-rw-r--r--drivers/char/drm/drm_sysfs.c8
-rw-r--r--drivers/char/drm/drm_vm.c16
-rw-r--r--drivers/char/drm/i915_dma.c2
-rw-r--r--drivers/char/drm/i915_drm.h19
-rw-r--r--drivers/char/drm/i915_drv.c4
-rw-r--r--drivers/char/drm/i915_drv.h22
-rw-r--r--drivers/char/drm/i915_ioc32.c12
-rw-r--r--drivers/char/drm/i915_irq.c344
-rw-r--r--drivers/char/drm/mga_ioc32.c8
-rw-r--r--drivers/char/drm/r128_drm.h3
-rw-r--r--drivers/char/drm/r128_drv.h3
-rw-r--r--drivers/char/drm/r128_ioc32.c10
-rw-r--r--drivers/char/drm/r128_state.c3
-rw-r--r--drivers/char/drm/r300_cmdbuf.c32
-rw-r--r--drivers/char/drm/radeon_drv.h15
-rw-r--r--drivers/char/drm/radeon_ioc32.c20
-rw-r--r--drivers/char/drm/radeon_irq.c4
-rw-r--r--drivers/char/drm/radeon_mem.c4
-rw-r--r--drivers/char/drm/radeon_state.c13
-rw-r--r--drivers/char/drm/savage_bci.c4
-rw-r--r--drivers/char/dsp56k.c6
-rw-r--r--drivers/char/dtlk.c4
-rw-r--r--drivers/char/epca.c16
-rw-r--r--drivers/char/esp.c2
-rw-r--r--drivers/char/generic_serial.c4
-rw-r--r--drivers/char/hvcs.c6
-rw-r--r--drivers/char/hvsi.c2
-rw-r--r--drivers/char/hw_random/amd-rng.c2
-rw-r--r--drivers/char/hw_random/geode-rng.c2
-rw-r--r--drivers/char/hw_random/intel-rng.c34
-rw-r--r--drivers/char/hw_random/ixp4xx-rng.c2
-rw-r--r--drivers/char/hw_random/via-rng.c2
-rw-r--r--drivers/char/ip2/i2ellis.h4
-rw-r--r--drivers/char/ip2/ip2main.c12
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c4
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c6
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c15
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c6
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c132
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c29
-rw-r--r--drivers/char/isicom.c399
-rw-r--r--drivers/char/istallion.c1164
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/char/lcd.c2
-rw-r--r--drivers/char/lp.c6
-rw-r--r--drivers/char/mem.c20
-rw-r--r--drivers/char/moxa.c18
-rw-r--r--drivers/char/mxser.c33
-rw-r--r--drivers/char/mxser_new.c2813
-rw-r--r--drivers/char/mxser_new.h450
-rw-r--r--drivers/char/n_r3964.c41
-rw-r--r--drivers/char/n_tty.c3
-rw-r--r--drivers/char/nsc_gpio.c4
-rw-r--r--drivers/char/pcmcia/synclink_cs.c4
-rw-r--r--drivers/char/ppdev.c4
-rw-r--r--drivers/char/pty.c10
-rw-r--r--drivers/char/random.c4
-rw-r--r--drivers/char/raw.c2
-rw-r--r--drivers/char/rio/riocmd.c2
-rw-r--r--drivers/char/riscom8.c4
-rw-r--r--drivers/char/rocket.c10
-rw-r--r--drivers/char/rtc.c43
-rw-r--r--drivers/char/ser_a2232.c2
-rw-r--r--drivers/char/serial167.c2
-rw-r--r--drivers/char/sonypi.c2
-rw-r--r--drivers/char/specialix.c9
-rw-r--r--drivers/char/stallion.c2148
-rw-r--r--drivers/char/sx.c2236
-rw-r--r--drivers/char/sx.h1
-rw-r--r--drivers/char/synclink.c6
-rw-r--r--drivers/char/synclink_gt.c6
-rw-r--r--drivers/char/synclinkmp.c10
-rw-r--r--drivers/char/sysrq.c57
-rw-r--r--drivers/char/tb0219.c4
-rw-r--r--drivers/char/tipar.c4
-rw-r--r--drivers/char/tlclk.c45
-rw-r--r--drivers/char/tty_io.c404
-rw-r--r--drivers/char/tty_ioctl.c264
-rw-r--r--drivers/char/vc_screen.c6
-rw-r--r--drivers/char/viocons.c17
-rw-r--r--drivers/char/viotape.c15
-rw-r--r--drivers/char/vme_scc.c2
-rw-r--r--drivers/char/vr41xx_giu.c118
-rw-r--r--drivers/char/vt.c2
-rw-r--r--drivers/char/vt_ioctl.c10
-rw-r--r--drivers/char/watchdog/at91rm9200_wdt.c6
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c2
-rw-r--r--drivers/char/watchdog/omap_wdt.c2
-rw-r--r--drivers/char/watchdog/pcwd_usb.c5
-rw-r--r--drivers/char/watchdog/rm9k_wdt.c44
-rw-r--r--drivers/clocksource/acpi_pm.c42
-rw-r--r--drivers/connector/cn_proc.c11
-rw-r--r--drivers/connector/cn_queue.c5
-rw-r--r--drivers/connector/connector.c17
-rw-r--r--drivers/cpufreq/cpufreq.c172
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c33
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c33
-rw-r--r--drivers/cpufreq/cpufreq_performance.c9
-rw-r--r--drivers/cpufreq/cpufreq_powersave.c9
-rw-r--r--drivers/cpufreq/cpufreq_stats.c15
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c11
-rw-r--r--drivers/cpufreq/freq_table.c28
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/fc4/fc.c10
-rw-r--r--drivers/firmware/efivars.c29
-rw-r--r--drivers/hid/Kconfig26
-rw-r--r--drivers/hid/Makefile15
-rw-r--r--drivers/hid/hid-core.c1000
-rw-r--r--drivers/hid/hid-input.c (renamed from drivers/usb/input/hid-input.c)233
-rw-r--r--drivers/hwmon/Kconfig56
-rw-r--r--drivers/hwmon/Makefile3
-rw-r--r--drivers/hwmon/ams/Makefile8
-rw-r--r--drivers/hwmon/ams/ams-core.c265
-rw-r--r--drivers/hwmon/ams/ams-i2c.c299
-rw-r--r--drivers/hwmon/ams/ams-input.c160
-rw-r--r--drivers/hwmon/ams/ams-pmu.c207
-rw-r--r--drivers/hwmon/ams/ams.h72
-rw-r--r--drivers/hwmon/f71805f.c569
-rw-r--r--drivers/hwmon/hdaps.c68
-rw-r--r--drivers/hwmon/hwmon-vid.c6
-rw-r--r--drivers/hwmon/it87.c202
-rw-r--r--drivers/hwmon/k8temp.c4
-rw-r--r--drivers/hwmon/pc87360.c2
-rw-r--r--drivers/hwmon/pc87427.c627
-rw-r--r--drivers/hwmon/w83627ehf.c2
-rw-r--r--drivers/hwmon/w83792d.c2
-rw-r--r--drivers/hwmon/w83793.c1702
-rw-r--r--drivers/i2c/algos/Kconfig11
-rw-r--r--drivers/i2c/algos/Makefile1
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c8
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c806
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.h117
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c7
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c8
-rw-r--r--drivers/i2c/algos/i2c-algo-sgi.c8
-rw-r--r--drivers/i2c/busses/Kconfig40
-rw-r--r--drivers/i2c/busses/Makefile4
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c2
-rw-r--r--drivers/i2c/busses/i2c-at91.c325
-rw-r--r--drivers/i2c/busses/i2c-elektor.c2
-rw-r--r--drivers/i2c/busses/i2c-hydra.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c16
-rw-r--r--drivers/i2c/busses/i2c-i810.c6
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c9
-rw-r--r--drivers/i2c/busses/i2c-ite.c278
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c2
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c4
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c89
-rw-r--r--drivers/i2c/busses/i2c-omap.c4
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c2
-rw-r--r--drivers/i2c/busses/i2c-parport.c2
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c2
-rw-r--r--drivers/i2c/busses/i2c-pnx.c703
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c2
-rw-r--r--drivers/i2c/busses/i2c-savage4.c2
-rw-r--r--drivers/i2c/busses/i2c-versatile.c153
-rw-r--r--drivers/i2c/busses/i2c-via.c2
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c6
-rw-r--r--drivers/i2c/busses/scx200_i2c.c2
-rw-r--r--drivers/i2c/chips/ds1337.c8
-rw-r--r--drivers/i2c/chips/m41t00.c1
-rw-r--r--drivers/i2c/chips/tps65010.c21
-rw-r--r--drivers/i2c/i2c-core.c95
-rw-r--r--drivers/i2c/i2c-dev.c48
-rw-r--r--drivers/ide/Kconfig2
-rw-r--r--drivers/ide/ide-cd.c7
-rw-r--r--drivers/ide/ide-floppy.c2
-rw-r--r--drivers/ide/ide-pnp.c5
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide-tape.c8
-rw-r--r--drivers/ide/ide.c11
-rw-r--r--drivers/ide/pci/aec62xx.c2
-rw-r--r--drivers/ide/pci/alim15x3.c18
-rw-r--r--drivers/ide/pci/amd74xx.c2
-rw-r--r--drivers/ide/pci/atiixp.c61
-rw-r--r--drivers/ide/pci/cmd64x.c2
-rw-r--r--drivers/ide/pci/cs5520.c2
-rw-r--r--drivers/ide/pci/cs5530.c2
-rw-r--r--drivers/ide/pci/cy82c693.c2
-rw-r--r--drivers/ide/pci/generic.c37
-rw-r--r--drivers/ide/pci/hpt34x.c2
-rw-r--r--drivers/ide/pci/hpt366.c888
-rw-r--r--drivers/ide/pci/jmicron.c17
-rw-r--r--drivers/ide/pci/ns87415.c2
-rw-r--r--drivers/ide/pci/opti621.c2
-rw-r--r--drivers/ide/pci/pdc202xx_new.c505
-rw-r--r--drivers/ide/pci/pdc202xx_old.c2
-rw-r--r--drivers/ide/pci/piix.c70
-rw-r--r--drivers/ide/pci/rz1000.c2
-rw-r--r--drivers/ide/pci/sc1200.c2
-rw-r--r--drivers/ide/pci/serverworks.c2
-rw-r--r--drivers/ide/pci/sgiioc4.c3
-rw-r--r--drivers/ide/pci/siimage.c2
-rw-r--r--drivers/ide/pci/sis5513.c5
-rw-r--r--drivers/ide/pci/sl82c105.c33
-rw-r--r--drivers/ide/pci/slc90e66.c22
-rw-r--r--drivers/ide/pci/triflex.c2
-rw-r--r--drivers/ide/pci/trm290.c2
-rw-r--r--drivers/ide/pci/via82cxxx.c143
-rw-r--r--drivers/ide/setup-pci.c4
-rw-r--r--drivers/ieee1394/ieee1394_core.h2
-rw-r--r--drivers/ieee1394/pcilynx.c2
-rw-r--r--drivers/ieee1394/sbp2.c85
-rw-r--r--drivers/infiniband/core/Makefile6
-rw-r--r--drivers/infiniband/core/cm.c4
-rw-r--r--drivers/infiniband/core/cma.c431
-rw-r--r--drivers/infiniband/core/fmr_pool.c12
-rw-r--r--drivers/infiniband/core/mad.c90
-rw-r--r--drivers/infiniband/core/mad_priv.h6
-rw-r--r--drivers/infiniband/core/ucma.c885
-rw-r--r--drivers/infiniband/core/uverbs_main.c6
-rw-r--r--drivers/infiniband/core/uverbs_marshall.c5
-rw-r--r--drivers/infiniband/core/uverbs_mem.c12
-rw-r--r--drivers/infiniband/hw/amso1100/c2_qp.c13
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c5
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c8
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c5
-rw-r--r--drivers/infiniband/hw/ehca/ehca_iverbs.h4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c10
-rw-r--r--drivers/infiniband/hw/ehca/ehca_mrmw.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c4
-rw-r--r--drivers/infiniband/hw/ipath/Makefile1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_dma.c189
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c9
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c10
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6110.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6120.c8
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_keys.c8
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mr.c7
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sysfs.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c8
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c113
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c7
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c30
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c75
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c3
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c4
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h2
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c30
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c129
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c103
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h4
-rw-r--r--drivers/input/Makefile1
-rw-r--r--drivers/input/ff-core.c4
-rw-r--r--drivers/input/ff-memless.c2
-rw-r--r--drivers/input/gameport/gameport.c19
-rw-r--r--drivers/input/gameport/lightning.c4
-rw-r--r--drivers/input/input.c25
-rw-r--r--drivers/input/joystick/adi.c10
-rw-r--r--drivers/input/joystick/amijoy.c6
-rw-r--r--drivers/input/joystick/analog.c10
-rw-r--r--drivers/input/joystick/cobra.c7
-rw-r--r--drivers/input/joystick/gf2k.c4
-rw-r--r--drivers/input/joystick/grip_mp.c13
-rw-r--r--drivers/input/joystick/guillemot.c4
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c31
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c20
-rw-r--r--drivers/input/joystick/interact.c4
-rw-r--r--drivers/input/joystick/magellan.c17
-rw-r--r--drivers/input/joystick/spaceball.c17
-rw-r--r--drivers/input/joystick/spaceorb.c17
-rw-r--r--drivers/input/joystick/stinger.c17
-rw-r--r--drivers/input/joystick/twidjoy.c17
-rw-r--r--drivers/input/joystick/warrior.c17
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/aaed2000_kbd.c203
-rw-r--r--drivers/input/keyboard/amikbd.c24
-rw-r--r--drivers/input/keyboard/atkbd.c162
-rw-r--r--drivers/input/keyboard/corgikbd.c17
-rw-r--r--drivers/input/keyboard/hil_kbd.c3
-rw-r--r--drivers/input/keyboard/hilkbd.c5
-rw-r--r--drivers/input/keyboard/lkkbd.c17
-rw-r--r--drivers/input/keyboard/locomokbd.c28
-rw-r--r--drivers/input/keyboard/maple_keyb.c160
-rw-r--r--drivers/input/keyboard/newtonkbd.c17
-rw-r--r--drivers/input/keyboard/spitzkbd.c24
-rw-r--r--drivers/input/keyboard/stowaway.c3
-rw-r--r--drivers/input/keyboard/sunkbd.c25
-rw-r--r--drivers/input/keyboard/xtkbd.c17
-rw-r--r--drivers/input/mouse/amimouse.c11
-rw-r--r--drivers/input/mouse/hil_ptr.c3
-rw-r--r--drivers/input/mouse/inport.c23
-rw-r--r--drivers/input/mouse/lifebook.c82
-rw-r--r--drivers/input/mouse/logibm.c24
-rw-r--r--drivers/input/mouse/logips2pp.c11
-rw-r--r--drivers/input/mouse/pc110pad.c26
-rw-r--r--drivers/input/mouse/psmouse-base.c101
-rw-r--r--drivers/input/mouse/rpcmouse.c20
-rw-r--r--drivers/input/mouse/sermouse.c16
-rw-r--r--drivers/input/mouse/trackpoint.c12
-rw-r--r--drivers/input/mouse/vsxxxaa.c16
-rw-r--r--drivers/input/mousedev.c2
-rw-r--r--drivers/input/serio/i8042-sparcio.h6
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/serio/i8042.c39
-rw-r--r--drivers/input/serio/serio.c147
-rw-r--r--drivers/input/serio/serio_raw.c3
-rw-r--r--drivers/input/touchscreen/Kconfig15
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c95
-rw-r--r--drivers/input/touchscreen/corgi_ts.c30
-rw-r--r--drivers/input/touchscreen/elo.c3
-rw-r--r--drivers/input/touchscreen/gunze.c17
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c3
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c29
-rw-r--r--drivers/input/touchscreen/mk712.c26
-rw-r--r--drivers/input/touchscreen/mtouch.c16
-rw-r--r--drivers/input/touchscreen/penmount.c3
-rw-r--r--drivers/input/touchscreen/touchright.c3
-rw-r--r--drivers/input/touchscreen/touchwin.c3
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c579
-rw-r--r--drivers/isdn/act2000/act2000_isa.c2
-rw-r--r--drivers/isdn/act2000/module.c3
-rw-r--r--drivers/isdn/capi/capi.c13
-rw-r--r--drivers/isdn/capi/capidrv.c11
-rw-r--r--drivers/isdn/divert/divert_procfs.c2
-rw-r--r--drivers/isdn/divert/isdn_divert.c6
-rw-r--r--drivers/isdn/gigaset/Kconfig1
-rw-r--r--drivers/isdn/gigaset/asyncdata.c5
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c118
-rw-r--r--drivers/isdn/gigaset/common.c98
-rw-r--r--drivers/isdn/gigaset/gigaset.h4
-rw-r--r--drivers/isdn/gigaset/interface.c4
-rw-r--r--drivers/isdn/gigaset/isocdata.c5
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c3
-rw-r--r--drivers/isdn/hardware/avm/b1.c10
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c1
-rw-r--r--drivers/isdn/hardware/eicon/debug.c4
-rw-r--r--drivers/isdn/hardware/eicon/di.c8
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c2
-rw-r--r--drivers/isdn/hardware/eicon/io.c2
-rw-r--r--drivers/isdn/hardware/eicon/istream.c4
-rw-r--r--drivers/isdn/hardware/eicon/platform.h8
-rw-r--r--drivers/isdn/hisax/Kconfig18
-rw-r--r--drivers/isdn/hisax/avma1_cs.c3
-rw-r--r--drivers/isdn/hisax/config.c21
-rw-r--r--drivers/isdn/hisax/diva.c4
-rw-r--r--drivers/isdn/hisax/elsa_cs.c3
-rw-r--r--drivers/isdn/hisax/fsm.c4
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c3
-rw-r--r--drivers/isdn/hisax/hfc_pci.c10
-rw-r--r--drivers/isdn/hisax/hfc_usb.c3
-rw-r--r--drivers/isdn/hisax/hisax.h6
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c4
-rw-r--r--drivers/isdn/hisax/hisax_isac.c2
-rw-r--r--drivers/isdn/hisax/isdnhdlc.c25
-rw-r--r--drivers/isdn/hisax/isdnhdlc.h2
-rw-r--r--drivers/isdn/hisax/sedlbauer.c4
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c3
-rw-r--r--drivers/isdn/hisax/st5481_b.c3
-rw-r--r--drivers/isdn/hisax/st5481_d.c4
-rw-r--r--drivers/isdn/hisax/st5481_init.c4
-rw-r--r--drivers/isdn/hisax/teles_cs.c3
-rw-r--r--drivers/isdn/hysdn/hycapi.c3
-rw-r--r--drivers/isdn/hysdn/hysdn_boot.c3
-rw-r--r--drivers/isdn/hysdn/hysdn_init.c3
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c3
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c2
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c9
-rw-r--r--drivers/isdn/i4l/isdn_audio.c6
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c4
-rw-r--r--drivers/isdn/i4l/isdn_common.c15
-rw-r--r--drivers/isdn/i4l/isdn_net.c8
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c24
-rw-r--r--drivers/isdn/i4l/isdn_tty.c2
-rw-r--r--drivers/isdn/i4l/isdn_v110.c3
-rw-r--r--drivers/isdn/icn/icn.c3
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c3
-rw-r--r--drivers/isdn/pcbit/drv.c9
-rw-r--r--drivers/isdn/pcbit/layer2.c5
-rw-r--r--drivers/isdn/sc/init.c9
-rw-r--r--drivers/kvm/Kconfig37
-rw-r--r--drivers/kvm/Makefile10
-rw-r--r--drivers/kvm/kvm.h630
-rw-r--r--drivers/kvm/kvm_main.c2136
-rw-r--r--drivers/kvm/kvm_svm.h44
-rw-r--r--drivers/kvm/kvm_vmx.h14
-rw-r--r--drivers/kvm/mmu.c1454
-rw-r--r--drivers/kvm/paging_tmpl.h484
-rw-r--r--drivers/kvm/segment_descriptor.h17
-rw-r--r--drivers/kvm/svm.c1721
-rw-r--r--drivers/kvm/svm.h315
-rw-r--r--drivers/kvm/vmx.c2061
-rw-r--r--drivers/kvm/vmx.h296
-rw-r--r--drivers/kvm/x86_emulate.c1415
-rw-r--r--drivers/kvm/x86_emulate.h185
-rw-r--r--drivers/leds/Kconfig22
-rw-r--r--drivers/leds/leds-s3c24xx.c2
-rw-r--r--drivers/macintosh/Kconfig1
-rw-r--r--drivers/macintosh/adb.c2
-rw-r--r--drivers/macintosh/adbhid.c10
-rw-r--r--drivers/macintosh/apm_emu.c2
-rw-r--r--drivers/macintosh/mac_hid.c8
-rw-r--r--drivers/macintosh/smu.c2
-rw-r--r--drivers/macintosh/via-pmu-backlight.c2
-rw-r--r--drivers/macintosh/via-pmu.c1
-rw-r--r--drivers/macintosh/via-pmu68k.c2
-rw-r--r--drivers/md/Kconfig1
-rw-r--r--drivers/md/bitmap.c20
-rw-r--r--drivers/md/dm-bio-list.h14
-rw-r--r--drivers/md/dm-crypt.c4
-rw-r--r--drivers/md/dm-emc.c10
-rw-r--r--drivers/md/dm-hw-handler.h2
-rw-r--r--drivers/md/dm-io.c15
-rw-r--r--drivers/md/dm-ioctl.c16
-rw-r--r--drivers/md/dm-linear.c4
-rw-r--r--drivers/md/dm-log.c24
-rw-r--r--drivers/md/dm-log.h10
-rw-r--r--drivers/md/dm-mpath.c52
-rw-r--r--drivers/md/dm-mpath.h4
-rw-r--r--drivers/md/dm-path-selector.h12
-rw-r--r--drivers/md/dm-raid1.c25
-rw-r--r--drivers/md/dm-round-robin.c12
-rw-r--r--drivers/md/dm-snap.c33
-rw-r--r--drivers/md/dm-stripe.c2
-rw-r--r--drivers/md/dm-zero.c2
-rw-r--r--drivers/md/dm.c155
-rw-r--r--drivers/md/dm.h19
-rw-r--r--drivers/md/faulty.c2
-rw-r--r--drivers/md/md.c74
-rw-r--r--drivers/md/raid1.c23
-rw-r--r--drivers/md/raid10.c17
-rw-r--r--drivers/md/raid5.c370
-rw-r--r--drivers/media/Kconfig2
-rw-r--r--drivers/media/common/ir-functions.c1
-rw-r--r--drivers/media/common/ir-keymaps.c55
-rw-r--r--drivers/media/common/saa7146_i2c.c16
-rw-r--r--drivers/media/dvb/b2c2/Kconfig1
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c10
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig2
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c2
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c11
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c13
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c4
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig14
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c36
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c271
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700.h5
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c40
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c200
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c113
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c26
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c22
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c24
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h14
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c37
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c22
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c38
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.c270
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.h70
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c24
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c20
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c40
-rw-r--r--drivers/media/dvb/frontends/Kconfig24
-rw-r--r--drivers/media/dvb/frontends/Makefile3
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c7
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c1191
-rw-r--r--drivers/media/dvb/frontends/dib7000m.h51
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c1019
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h46
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.h13
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c67
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h7
-rw-r--r--drivers/media/dvb/frontends/lg_h06xf.h64
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c257
-rw-r--r--drivers/media/dvb/frontends/lgdt330x_priv.h15
-rw-r--r--drivers/media/dvb/frontends/lgh06xf.c134
-rw-r--r--drivers/media/dvb/frontends/lgh06xf.h35
-rw-r--r--drivers/media/dvb/frontends/or51132.c176
-rw-r--r--drivers/media/dvb/frontends/or51211.c124
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c10
-rw-r--r--drivers/media/dvb/frontends/tda1004x.h5
-rw-r--r--drivers/media/dvb/frontends/tda8083.c30
-rw-r--r--drivers/media/dvb/frontends/tda826x.c12
-rw-r--r--drivers/media/dvb/frontends/tua6100.c3
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c8
-rw-r--r--drivers/media/dvb/ttpci/Kconfig1
-rw-r--r--drivers/media/dvb/ttpci/av7110.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c25
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c26
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c334
-rw-r--r--drivers/media/dvb/ttpci/budget.c2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c11
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c4
-rw-r--r--drivers/media/video/Kconfig31
-rw-r--r--drivers/media/video/Makefile6
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c6
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c6
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c101
-rw-r--r--drivers/media/video/cafe_ccic-regs.h160
-rw-r--r--drivers/media/video/cafe_ccic.c2228
-rw-r--r--drivers/media/video/compat_ioctl32.c2
-rw-r--r--drivers/media/video/cpia2/cpia2_usb.c4
-rw-r--r--drivers/media/video/cx2341x.c21
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c9
-rw-r--r--drivers/media/video/cx88/Kconfig1
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c179
-rw-r--r--drivers/media/video/cx88/cx88-cards.c88
-rw-r--r--drivers/media/video/cx88/cx88-core.c37
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c333
-rw-r--r--drivers/media/video/cx88/cx88-input.c77
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c348
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c15
-rw-r--r--drivers/media/video/cx88/cx88-video.c32
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c2
-rw-r--r--drivers/media/video/cx88/cx88.h49
-rw-r--r--drivers/media/video/dabusb.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c4
-rw-r--r--drivers/media/video/ir-kbd-i2c.c46
-rw-r--r--drivers/media/video/ks0127.c8
-rw-r--r--drivers/media/video/meye.c4
-rw-r--r--drivers/media/video/msp3400-driver.c8
-rw-r--r--drivers/media/video/msp3400-kthreads.c11
-rw-r--r--drivers/media/video/mxb.c8
-rw-r--r--drivers/media/video/ov7670.c1333
-rw-r--r--drivers/media/video/planb.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c16
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c26
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c81
-rw-r--r--drivers/media/video/saa7115.c18
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c63
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c236
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c222
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c76
-rw-r--r--drivers/media/video/saa7134/saa7134.h8
-rw-r--r--drivers/media/video/stv680.c21
-rw-r--r--drivers/media/video/tda9887.c6
-rw-r--r--drivers/media/video/tuner-core.c8
-rw-r--r--drivers/media/video/tuner-simple.c4
-rw-r--r--drivers/media/video/tuner-types.c15
-rw-r--r--drivers/media/video/tveeprom.c11
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c9
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.h14
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c2
-rw-r--r--drivers/media/video/usbvision/Kconfig12
-rw-r--r--drivers/media/video/usbvision/Makefile5
-rw-r--r--drivers/media/video/usbvision/usbvision-cards.c156
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c2535
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c552
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c2088
-rw-r--r--drivers/media/video/usbvision/usbvision.h531
-rw-r--r--drivers/media/video/v4l1-compat.c18
-rw-r--r--drivers/media/video/v4l2-common.c92
-rw-r--r--drivers/media/video/video-buf.c3
-rw-r--r--drivers/media/video/videocodec.c2
-rw-r--r--drivers/media/video/videodev.c175
-rw-r--r--drivers/media/video/vino.c2
-rw-r--r--drivers/media/video/vivi.c31
-rw-r--r--drivers/media/video/w9966.c2
-rw-r--r--drivers/media/video/w9968cf.c24
-rw-r--r--drivers/media/video/zoran_card.c2
-rw-r--r--drivers/media/video/zoran_device.c3
-rw-r--r--drivers/media/video/zoran_procfs.c4
-rw-r--r--drivers/media/video/zr36120.c2079
-rw-r--r--drivers/media/video/zr36120.h279
-rw-r--r--drivers/media/video/zr36120_i2c.c132
-rw-r--r--drivers/media/video/zr36120_mem.c78
-rw-r--r--drivers/media/video/zr36120_mem.h3
-rw-r--r--drivers/message/fusion/mptbase.c3
-rw-r--r--drivers/message/fusion/mptbase.h10
-rw-r--r--drivers/message/fusion/mptctl.c5
-rw-r--r--drivers/message/fusion/mptctl.h2
-rw-r--r--drivers/message/fusion/mptfc.c3
-rw-r--r--drivers/message/fusion/mptlan.c4
-rw-r--r--drivers/message/fusion/mptlan.h2
-rw-r--r--drivers/message/fusion/mptsas.c38
-rw-r--r--drivers/message/fusion/mptscsih.c19
-rw-r--r--drivers/message/fusion/mptscsih.h2
-rw-r--r--drivers/message/fusion/mptspi.c3
-rw-r--r--drivers/message/i2o/core.h4
-rw-r--r--drivers/message/i2o/driver.c2
-rw-r--r--drivers/message/i2o/exec-osm.c4
-rw-r--r--drivers/message/i2o/i2o_config.c4
-rw-r--r--drivers/misc/msi-laptop.c3
-rw-r--r--drivers/mmc/at91_mci.c357
-rw-r--r--drivers/mmc/au1xmmc.c2
-rw-r--r--drivers/mmc/imxmmc.c3
-rw-r--r--drivers/mmc/mmc_queue.c4
-rw-r--r--drivers/mmc/mmci.c4
-rw-r--r--drivers/mmc/omap.c21
-rw-r--r--drivers/mmc/pxamci.c6
-rw-r--r--drivers/mmc/sdhci.c4
-rw-r--r--drivers/mmc/tifm_sd.c5
-rw-r--r--drivers/mtd/Kconfig15
-rw-r--r--drivers/mtd/Makefile15
-rw-r--r--drivers/mtd/afs.c3
-rw-r--r--drivers/mtd/chips/amd_flash.c3
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c5
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c11
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c3
-rw-r--r--drivers/mtd/chips/gen_probe.c5
-rw-r--r--drivers/mtd/chips/jedec.c3
-rw-r--r--drivers/mtd/chips/jedec_probe.c17
-rw-r--r--drivers/mtd/chips/map_absent.c4
-rw-r--r--drivers/mtd/chips/map_ram.c4
-rw-r--r--drivers/mtd/chips/map_rom.c4
-rw-r--r--drivers/mtd/chips/sharp.c7
-rw-r--r--drivers/mtd/cmdlinepart.c5
-rw-r--r--drivers/mtd/devices/block2mtd.c3
-rw-r--r--drivers/mtd/devices/m25p80.c4
-rw-r--r--drivers/mtd/devices/ms02-nv.c18
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c6
-rw-r--r--drivers/mtd/devices/phram.c4
-rw-r--r--drivers/mtd/devices/slram.c7
-rw-r--r--drivers/mtd/ftl.c7
-rw-r--r--drivers/mtd/inftlcore.c12
-rw-r--r--drivers/mtd/maps/Kconfig71
-rw-r--r--drivers/mtd/maps/Makefile4
-rw-r--r--drivers/mtd/maps/amd76xrom.c34
-rw-r--r--drivers/mtd/maps/bast-flash.c2
-rw-r--r--drivers/mtd/maps/ceiva.c3
-rw-r--r--drivers/mtd/maps/ck804xrom.c356
-rw-r--r--drivers/mtd/maps/cstm_mips_ixx.c283
-rw-r--r--drivers/mtd/maps/esb2rom.c450
-rw-r--r--drivers/mtd/maps/integrator-flash.c4
-rw-r--r--drivers/mtd/maps/nettel.c5
-rw-r--r--drivers/mtd/maps/omap_nor.c4
-rw-r--r--drivers/mtd/maps/pcmciamtd.c3
-rw-r--r--drivers/mtd/maps/physmap.c5
-rw-r--r--drivers/mtd/maps/physmap_of.c255
-rw-r--r--drivers/mtd/maps/plat-ram.c3
-rw-r--r--drivers/mtd/maps/sa1100-flash.c4
-rw-r--r--drivers/mtd/maps/tqm834x.c8
-rw-r--r--drivers/mtd/maps/tqm8xxl.c3
-rw-r--r--drivers/mtd/mtd_blkdevs.c19
-rw-r--r--drivers/mtd/mtdblock.c10
-rw-r--r--drivers/mtd/mtdblock_ro.c7
-rw-r--r--drivers/mtd/mtdchar.c23
-rw-r--r--drivers/mtd/mtdconcat.c43
-rw-r--r--drivers/mtd/mtdcore.c93
-rw-r--r--drivers/mtd/mtdpart.c8
-rw-r--r--drivers/mtd/nand/Kconfig16
-rw-r--r--drivers/mtd/nand/Makefile5
-rw-r--r--drivers/mtd/nand/at91_nand.c223
-rw-r--r--drivers/mtd/nand/cafe.c771
-rw-r--r--drivers/mtd/nand/cafe_ecc.c1381
-rw-r--r--drivers/mtd/nand/cs553x_nand.c4
-rw-r--r--drivers/mtd/nand/diskonchip.c3
-rw-r--r--drivers/mtd/nand/nand_base.c133
-rw-r--r--drivers/mtd/nand/nand_bbt.c11
-rw-r--r--drivers/mtd/nand/nand_ecc.c4
-rw-r--r--drivers/mtd/nand/nandsim.c243
-rw-r--r--drivers/mtd/nand/ndfc.c2
-rw-r--r--drivers/mtd/nand/rtc_from4.c46
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/nftlcore.c12
-rw-r--r--drivers/mtd/onenand/generic.c5
-rw-r--r--drivers/mtd/onenand/onenand_base.c374
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c14
-rw-r--r--drivers/mtd/redboot.c30
-rw-r--r--drivers/mtd/rfd_ftl.c5
-rw-r--r--drivers/mtd/ssfdc.c7
-rw-r--r--drivers/net/7990.c2
-rw-r--r--drivers/net/8139cp.c13
-rw-r--r--drivers/net/8139too.c5
-rw-r--r--drivers/net/82596.c7
-rw-r--r--drivers/net/Kconfig8
-rw-r--r--drivers/net/Space.c11
-rw-r--r--drivers/net/apne.c3
-rw-r--r--drivers/net/appletalk/ipddp.c2
-rw-r--r--drivers/net/arm/ep93xx_eth.c4
-rw-r--r--drivers/net/b44.c58
-rw-r--r--drivers/net/bnx2.c112
-rw-r--r--drivers/net/bnx2.h6
-rw-r--r--drivers/net/bonding/bonding.h7
-rw-r--r--drivers/net/bsd_comp.c2
-rw-r--r--drivers/net/chelsio/cxgb2.c23
-rw-r--r--drivers/net/chelsio/my3126.c5
-rw-r--r--drivers/net/chelsio/sge.c115
-rw-r--r--drivers/net/chelsio/sge.h4
-rw-r--r--drivers/net/e100.c10
-rw-r--r--drivers/net/e1000/e1000_ethtool.c3
-rw-r--r--drivers/net/e1000/e1000_hw.c296
-rw-r--r--drivers/net/e1000/e1000_hw.h310
-rw-r--r--drivers/net/e1000/e1000_main.c339
-rw-r--r--drivers/net/e1000/e1000_param.c4
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c87
-rw-r--r--drivers/net/ehea/ehea_phyp.c10
-rw-r--r--drivers/net/forcedeth.c127
-rw-r--r--drivers/net/fs_enet/mac-fec.c13
-rw-r--r--drivers/net/fs_enet/mac-scc.c6
-rw-r--r--drivers/net/hamradio/6pack.c9
-rw-r--r--drivers/net/hamradio/Kconfig6
-rw-r--r--drivers/net/hamradio/baycom_epp.c10
-rw-r--r--drivers/net/hamradio/bpqether.c9
-rw-r--r--drivers/net/hamradio/dmascc.c10
-rw-r--r--drivers/net/hamradio/hdlcdrv.c16
-rw-r--r--drivers/net/hamradio/mkiss.c9
-rw-r--r--drivers/net/hamradio/scc.c9
-rw-r--r--drivers/net/hamradio/yam.c9
-rw-r--r--drivers/net/hplance.c14
-rw-r--r--drivers/net/ibm_emac/ibm_emac_phy.c4
-rw-r--r--drivers/net/ifb.c4
-rw-r--r--drivers/net/irda/donauboe.c2
-rw-r--r--drivers/net/irda/irda-usb.c47
-rw-r--r--drivers/net/irda/irda-usb.h1
-rw-r--r--drivers/net/irda/irport.c2
-rw-r--r--drivers/net/irda/irtty-sir.c4
-rw-r--r--drivers/net/irda/stir4200.c2
-rw-r--r--drivers/net/irda/vlsi_ir.c16
-rw-r--r--drivers/net/irda/vlsi_ir.h33
-rw-r--r--drivers/net/iseries_veth.c9
-rw-r--r--drivers/net/ixgb/ixgb.h1
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c1
-rw-r--r--drivers/net/ixgb/ixgb_hw.c3
-rw-r--r--drivers/net/ixgb/ixgb_main.c57
-rw-r--r--drivers/net/loopback.c4
-rw-r--r--drivers/net/lp486e.c4
-rw-r--r--drivers/net/macb.c8
-rw-r--r--drivers/net/macb.h6
-rw-r--r--drivers/net/mv643xx_eth.c11
-rw-r--r--drivers/net/myri10ge/myri10ge.c674
-rw-r--r--drivers/net/netxen/netxen_nic.h166
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c27
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c342
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h74
-rw-r--r--drivers/net/netxen/netxen_nic_init.c260
-rw-r--r--drivers/net/netxen/netxen_nic_ioctl.h77
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c7
-rw-r--r--drivers/net/netxen/netxen_nic_main.c91
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c106
-rw-r--r--drivers/net/pcmcia/3c574_cs.c1
-rw-r--r--drivers/net/pcmcia/3c589_cs.c8
-rw-r--r--drivers/net/pcmcia/com20020_cs.c1
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c2
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c1
-rw-r--r--drivers/net/phy/fixed.c2
-rw-r--r--drivers/net/phy/phy.c3
-rw-r--r--drivers/net/phy/phy_device.c2
-rw-r--r--drivers/net/ppp_deflate.c4
-rw-r--r--drivers/net/ppp_mppe.c2
-rw-r--r--drivers/net/qla3xxx.c38
-rw-r--r--drivers/net/r8169.c6
-rw-r--r--drivers/net/s2io.c3
-rw-r--r--drivers/net/sis190.c2
-rw-r--r--drivers/net/skge.c9
-rw-r--r--drivers/net/sky2.c12
-rw-r--r--drivers/net/slip.c6
-rw-r--r--drivers/net/smc911x.c28
-rw-r--r--drivers/net/smc91x.h90
-rw-r--r--drivers/net/spider_net.c2
-rw-r--r--drivers/net/sungem.c3
-rw-r--r--drivers/net/sungem_phy.c179
-rw-r--r--drivers/net/sungem_phy.h7
-rw-r--r--drivers/net/tg3.c55
-rw-r--r--drivers/net/tg3.h5
-rw-r--r--drivers/net/ucc_geth.c24
-rw-r--r--drivers/net/ucc_geth_phy.c134
-rw-r--r--drivers/net/via-velocity.c20
-rw-r--r--drivers/net/wan/Kconfig5
-rw-r--r--drivers/net/wan/cosa.c4
-rw-r--r--drivers/net/wan/hostess_sv11.c2
-rw-r--r--drivers/net/wan/pc300_drv.c2
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/x25_asy.c8
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c11
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_download.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c2
-rw-r--r--drivers/net/wireless/ipw2100.c4
-rw-r--r--drivers/net/wireless/netwave_cs.c1
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/ray_cs.c1
-rw-r--r--drivers/net/wireless/strip.c2
-rw-r--r--drivers/net/wireless/wavelan_cs.c2
-rw-r--r--drivers/net/wireless/wl3501_cs.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c96
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c4
-rw-r--r--drivers/oprofile/buffer_sync.c8
-rw-r--r--drivers/parisc/iosapic.c2
-rw-r--r--drivers/parport/Kconfig6
-rw-r--r--drivers/pci/Kconfig2
-rw-r--r--drivers/pci/hotplug/Kconfig3
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c3
-rw-r--r--drivers/pci/hotplug/cpqphp_nvram.c8
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c47
-rw-r--r--drivers/pci/hotplug/shpchp.h238
-rw-r--r--drivers/pci/hotplug/shpchp_core.c116
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c21
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c223
-rw-r--r--drivers/pci/htirq.c9
-rw-r--r--drivers/pci/pci-driver.c15
-rw-r--r--drivers/pci/pci.c113
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c2
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pci/probe.c10
-rw-r--r--drivers/pci/proc.c8
-rw-r--r--drivers/pci/quirks.c254
-rw-r--r--drivers/pci/search.c56
-rw-r--r--drivers/pci/setup-bus.c2
-rw-r--r--drivers/pci/setup-res.c19
-rw-r--r--drivers/pcmcia/at91_cf.c2
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c6
-rw-r--r--drivers/pnp/isapnp/core.c22
-rw-r--r--drivers/pnp/isapnp/proc.c2
-rw-r--r--drivers/pnp/pnpacpi/core.c6
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c22
-rw-r--r--drivers/pnp/pnpbios/core.c16
-rw-r--r--drivers/pnp/pnpbios/proc.c8
-rw-r--r--drivers/pnp/pnpbios/rsparser.c16
-rw-r--r--drivers/ps3/Makefile1
-rw-r--r--drivers/ps3/vuart.c965
-rw-r--r--drivers/ps3/vuart.h94
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c (renamed from drivers/rtc/rtc-at91.c)7
-rw-r--r--drivers/rtc/rtc-dev.c2
-rw-r--r--drivers/rtc/rtc-ds1672.c2
-rw-r--r--drivers/rtc/rtc-lib.c81
-rw-r--r--drivers/rtc/rtc-omap.c3
-rw-r--r--drivers/rtc/rtc-pcf8563.c6
-rw-r--r--drivers/rtc/rtc-proc.c4
-rw-r--r--drivers/rtc/rtc-rs5c372.c537
-rw-r--r--drivers/rtc/rtc-s3c.c6
-rw-r--r--drivers/rtc/rtc-sa1100.c4
-rw-r--r--drivers/rtc/rtc-sh.c251
-rw-r--r--drivers/rtc/rtc-sysfs.c4
-rw-r--r--drivers/rtc/rtc-x1205.c10
-rw-r--r--drivers/s390/block/dasd.c8
-rw-r--r--drivers/s390/block/dasd_3990_erp.c23
-rw-r--r--drivers/s390/block/dasd_devmap.c49
-rw-r--r--drivers/s390/block/dasd_int.h4
-rw-r--r--drivers/s390/block/dasd_ioctl.c2
-rw-r--r--drivers/s390/char/con3215.c2
-rw-r--r--drivers/s390/char/ctrlchar.c9
-rw-r--r--drivers/s390/char/fs3270.c16
-rw-r--r--drivers/s390/char/keyboard.c2
-rw-r--r--drivers/s390/char/monwriter.c2
-rw-r--r--drivers/s390/char/sclp_cpi.c4
-rw-r--r--drivers/s390/char/sclp_tty.c2
-rw-r--r--drivers/s390/char/tape.h3
-rw-r--r--drivers/s390/char/tape_34xx.c23
-rw-r--r--drivers/s390/char/tape_3590.c7
-rw-r--r--drivers/s390/char/tape_block.c14
-rw-r--r--drivers/s390/char/tape_char.c8
-rw-r--r--drivers/s390/char/tape_core.c14
-rw-r--r--drivers/s390/char/tty3270.c2
-rw-r--r--drivers/s390/char/vmcp.c2
-rw-r--r--drivers/s390/cio/chsc.c28
-rw-r--r--drivers/s390/cio/cio.c94
-rw-r--r--drivers/s390/cio/cio.h6
-rw-r--r--drivers/s390/cio/css.c70
-rw-r--r--drivers/s390/cio/css.h9
-rw-r--r--drivers/s390/cio/device.c456
-rw-r--r--drivers/s390/cio/device.h6
-rw-r--r--drivers/s390/cio/device_fsm.c58
-rw-r--r--drivers/s390/cio/device_ops.c28
-rw-r--r--drivers/s390/cio/qdio.c247
-rw-r--r--drivers/s390/cio/qdio.h28
-rw-r--r--drivers/s390/crypto/ap_bus.c27
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c4
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c4
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c2
-rw-r--r--drivers/s390/net/Kconfig5
-rw-r--r--drivers/s390/net/ctcmain.c6
-rw-r--r--drivers/s390/net/iucv.c2
-rw-r--r--drivers/s390/net/qeth.h2
-rw-r--r--drivers/s390/net/qeth_main.c217
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/sbus/char/bpp.c4
-rw-r--r--drivers/sbus/char/cpwatchdog.c2
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/sbus/char/openprom.c2
-rw-r--r--drivers/sbus/char/vfc_dev.c4
-rw-r--r--drivers/scsi/3w-xxxx.c60
-rw-r--r--drivers/scsi/3w-xxxx.h2
-rw-r--r--drivers/scsi/Kconfig4
-rw-r--r--drivers/scsi/aacraid/aachba.c2
-rw-r--r--drivers/scsi/aacraid/comminit.c2
-rw-r--r--drivers/scsi/aacraid/linit.c20
-rw-r--r--drivers/scsi/advansys.c3
-rw-r--r--drivers/scsi/aha1542.c2
-rw-r--r--drivers/scsi/aic7xxx_old.c2
-rw-r--r--drivers/scsi/dc395x.c2
-rw-r--r--drivers/scsi/dpt_i2o.c10
-rw-r--r--drivers/scsi/ibmvscsi/Makefile2
-rw-r--r--drivers/scsi/initio.c2
-rw-r--r--drivers/scsi/iscsi_tcp.c12
-rw-r--r--drivers/scsi/libiscsi.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c6
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c6
-rw-r--r--drivers/scsi/osst.c2
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c1
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c3
-rw-r--r--drivers/scsi/pluto.c2
-rw-r--r--drivers/scsi/qla1280.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c24
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c76
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c15
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c59
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c18
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c35
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c64
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
-rw-r--r--drivers/scsi/scsi_lib.c4
-rw-r--r--drivers/scsi/scsi_scan.c39
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c2
-rw-r--r--drivers/scsi/scsi_transport_spi.c2
-rw-r--r--drivers/scsi/sd.c22
-rw-r--r--drivers/scsi/seagate.c5
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--drivers/scsi/sr_ioctl.c2
-rw-r--r--drivers/scsi/sr_vendor.c4
-rw-r--r--drivers/scsi/st.c21
-rw-r--r--drivers/scsi/sun3_NCR5380.c10
-rw-r--r--drivers/scsi/sun3_scsi.c2
-rw-r--r--drivers/scsi/sun3_scsi.h2
-rw-r--r--drivers/scsi/sun3_scsi_vme.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c2
-rw-r--r--drivers/serial/21285.c4
-rw-r--r--drivers/serial/68328serial.c2
-rw-r--r--drivers/serial/68360serial.c2
-rw-r--r--drivers/serial/8250.c6
-rw-r--r--drivers/serial/8250_pci.c24
-rw-r--r--drivers/serial/Kconfig57
-rw-r--r--drivers/serial/amba-pl010.c6
-rw-r--r--drivers/serial/amba-pl011.c6
-rw-r--r--drivers/serial/atmel_serial.c9
-rw-r--r--drivers/serial/atmel_serial.h2
-rw-r--r--drivers/serial/clps711x.c4
-rw-r--r--drivers/serial/crisv10.c8
-rw-r--r--drivers/serial/crisv10.h4
-rw-r--r--drivers/serial/dz.c4
-rw-r--r--drivers/serial/icom.c6
-rw-r--r--drivers/serial/imx.c4
-rw-r--r--drivers/serial/ioc3_serial.c4
-rw-r--r--drivers/serial/ioc4_serial.c6
-rw-r--r--drivers/serial/ip22zilog.c4
-rw-r--r--drivers/serial/jsm/jsm_tty.c10
-rw-r--r--drivers/serial/m32r_sio.c2
-rw-r--r--drivers/serial/mcfserial.c2
-rw-r--r--drivers/serial/mpc52xx_uart.c6
-rw-r--r--drivers/serial/mpsc.c4
-rw-r--r--drivers/serial/mux.c4
-rw-r--r--drivers/serial/netx-serial.c4
-rw-r--r--drivers/serial/pmac_zilog.c10
-rw-r--r--drivers/serial/pmac_zilog.h2
-rw-r--r--drivers/serial/pxa.c4
-rw-r--r--drivers/serial/s3c2410.c4
-rw-r--r--drivers/serial/sa1100.c4
-rw-r--r--drivers/serial/serial_core.c21
-rw-r--r--drivers/serial/serial_lh7a40x.c4
-rw-r--r--drivers/serial/serial_txx9.c4
-rw-r--r--drivers/serial/sh-sci.c26
-rw-r--r--drivers/serial/sh-sci.h19
-rw-r--r--drivers/serial/sn_console.c4
-rw-r--r--drivers/serial/sunhv.c4
-rw-r--r--drivers/serial/sunsab.c15
-rw-r--r--drivers/serial/sunsu.c14
-rw-r--r--drivers/serial/sunzilog.c18
-rw-r--r--drivers/serial/uartlite.c8
-rw-r--r--drivers/serial/v850e_uart.c4
-rw-r--r--drivers/serial/vr41xx_siu.c4
-rw-r--r--drivers/spi/pxa2xx_spi.c738
-rw-r--r--drivers/spi/spi.c23
-rw-r--r--drivers/spi/spi_mpc83xx.c2
-rw-r--r--drivers/spi/spi_s3c24xx.c30
-rw-r--r--drivers/spi/spi_s3c24xx_gpio.c3
-rw-r--r--drivers/tc/zs.c2
-rw-r--r--drivers/telephony/ixj.c10
-rw-r--r--drivers/usb/class/cdc-acm.c4
-rw-r--r--drivers/usb/class/usblp.c55
-rw-r--r--drivers/usb/core/Kconfig16
-rw-r--r--drivers/usb/core/devio.c6
-rw-r--r--drivers/usb/core/endpoint.c2
-rw-r--r--drivers/usb/core/hub.c9
-rw-r--r--drivers/usb/core/inode.c4
-rw-r--r--drivers/usb/gadget/at91_udc.c238
-rw-r--r--drivers/usb/gadget/at91_udc.h7
-rw-r--r--drivers/usb/gadget/dummy_hcd.c7
-rw-r--r--drivers/usb/gadget/file_storage.c18
-rw-r--r--drivers/usb/gadget/gmidi.c12
-rw-r--r--drivers/usb/gadget/goku_udc.c12
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c13
-rw-r--r--drivers/usb/gadget/net2280.c11
-rw-r--r--drivers/usb/gadget/omap_udc.c258
-rw-r--r--drivers/usb/gadget/omap_udc.h3
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c7
-rw-r--r--drivers/usb/gadget/serial.c8
-rw-r--r--drivers/usb/host/hc_crisv10.c2
-rw-r--r--drivers/usb/host/ohci-at91.c3
-rw-r--r--drivers/usb/host/ohci-au1xxx.c4
-rw-r--r--drivers/usb/host/ohci-dbg.c8
-rw-r--r--drivers/usb/host/ohci-ep93xx.c4
-rw-r--r--drivers/usb/host/ohci-hcd.c110
-rw-r--r--drivers/usb/host/ohci-hub.c21
-rw-r--r--drivers/usb/host/ohci-lh7a404.c8
-rw-r--r--drivers/usb/host/ohci-mem.c10
-rw-r--r--drivers/usb/host/ohci-omap.c4
-rw-r--r--drivers/usb/host/ohci-pci.c16
-rw-r--r--drivers/usb/host/ohci-pnx4008.c4
-rw-r--r--drivers/usb/host/ohci-pnx8550.c258
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c8
-rw-r--r--drivers/usb/host/ohci-pxa27x.c10
-rw-r--r--drivers/usb/host/ohci-q.c103
-rw-r--r--drivers/usb/host/ohci-s3c2410.c4
-rw-r--r--drivers/usb/host/ohci-sa1111.c8
-rw-r--r--drivers/usb/host/ohci.h92
-rw-r--r--drivers/usb/host/u132-hcd.c92
-rw-r--r--drivers/usb/host/uhci-hcd.c33
-rw-r--r--drivers/usb/host/uhci-hub.c14
-rw-r--r--drivers/usb/input/Kconfig26
-rw-r--r--drivers/usb/input/Makefile3
-rw-r--r--drivers/usb/input/appletouch.c95
-rw-r--r--drivers/usb/input/hid-core.c1428
-rw-r--r--drivers/usb/input/hid-ff.c9
-rw-r--r--drivers/usb/input/hid-lgff.c7
-rw-r--r--drivers/usb/input/hid-pidff.c58
-rw-r--r--drivers/usb/input/hid-tmff.c5
-rw-r--r--drivers/usb/input/hid-zpff.c7
-rw-r--r--drivers/usb/input/hiddev.c37
-rw-r--r--drivers/usb/input/usbhid.h87
-rw-r--r--drivers/usb/input/usbtouchscreen.c98
-rw-r--r--drivers/usb/input/wacom_sys.c4
-rw-r--r--drivers/usb/input/wacom_wac.c26
-rw-r--r--drivers/usb/misc/appledisplay.c2
-rw-r--r--drivers/usb/misc/auerswald.c10
-rw-r--r--drivers/usb/misc/ftdi-elan.c592
-rw-r--r--drivers/usb/misc/phidgetservo.c1
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c2
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c12
-rw-r--r--drivers/usb/misc/trancevibrator.c2
-rw-r--r--drivers/usb/misc/uss720.c2
-rw-r--r--drivers/usb/net/asix.c18
-rw-r--r--drivers/usb/net/gl620a.c154
-rw-r--r--drivers/usb/net/rndis_host.c25
-rw-r--r--drivers/usb/net/rtl8150.c9
-rw-r--r--drivers/usb/serial/airprime.c3
-rw-r--r--drivers/usb/serial/ark3116.c4
-rw-r--r--drivers/usb/serial/belkin_sa.c4
-rw-r--r--drivers/usb/serial/console.c2
-rw-r--r--drivers/usb/serial/cp2101.c5
-rw-r--r--drivers/usb/serial/cypress_m8.c27
-rw-r--r--drivers/usb/serial/digi_acceleport.c10
-rw-r--r--drivers/usb/serial/empeg.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c5
-rw-r--r--drivers/usb/serial/ftdi_sio.h5
-rw-r--r--drivers/usb/serial/funsoft.c27
-rw-r--r--drivers/usb/serial/io_edgeport.c8
-rw-r--r--drivers/usb/serial/io_ti.c8
-rw-r--r--drivers/usb/serial/ipaq.c2
-rw-r--r--drivers/usb/serial/ir-usb.c4
-rw-r--r--drivers/usb/serial/keyspan.c2
-rw-r--r--drivers/usb/serial/keyspan.h2
-rw-r--r--drivers/usb/serial/keyspan_pda.c2
-rw-r--r--drivers/usb/serial/kl5kusb105.c74
-rw-r--r--drivers/usb/serial/kobil_sct.c14
-rw-r--r--drivers/usb/serial/mct_u232.c4
-rw-r--r--drivers/usb/serial/mos7720.c4
-rw-r--r--drivers/usb/serial/mos7840.c10
-rw-r--r--drivers/usb/serial/option.c13
-rw-r--r--drivers/usb/serial/pl2303.c6
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c6
-rw-r--r--drivers/usb/serial/usb-serial.c2
-rw-r--r--drivers/usb/serial/visor.c4
-rw-r--r--drivers/usb/serial/whiteheat.c10
-rw-r--r--drivers/usb/storage/sddr09.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h52
-rw-r--r--drivers/video/Kconfig14
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/S3triofb.c7
-rw-r--r--drivers/video/amba-clcd.c2
-rw-r--r--drivers/video/amifb.c16
-rw-r--r--drivers/video/arcfb.c2
-rw-r--r--drivers/video/atafb.c13
-rw-r--r--drivers/video/aty/aty128fb.c7
-rw-r--r--drivers/video/aty/atyfb.h9
-rw-r--r--drivers/video/aty/atyfb_base.c199
-rw-r--r--drivers/video/aty/mach64_ct.c47
-rw-r--r--drivers/video/aty/radeon_backlight.c2
-rw-r--r--drivers/video/aty/radeon_i2c.c8
-rw-r--r--drivers/video/aty/radeon_monitor.c3
-rw-r--r--drivers/video/au1100fb.h2
-rw-r--r--drivers/video/backlight/backlight.c102
-rw-r--r--drivers/video/backlight/corgi_bl.c6
-rw-r--r--drivers/video/backlight/hp680_bl.c6
-rw-r--r--drivers/video/backlight/lcd.c80
-rw-r--r--drivers/video/backlight/locomolcd.c6
-rw-r--r--drivers/video/bw2.c18
-rw-r--r--drivers/video/cfbimgblt.c8
-rw-r--r--drivers/video/cg14.c28
-rw-r--r--drivers/video/cg3.c22
-rw-r--r--drivers/video/cg6.c33
-rw-r--r--drivers/video/cirrusfb.c15
-rw-r--r--drivers/video/console/softcursor.c26
-rw-r--r--drivers/video/console/sticon.c2
-rw-r--r--drivers/video/console/vgacon.c30
-rw-r--r--drivers/video/cyberfb.c4
-rw-r--r--drivers/video/epson1355fb.c4
-rw-r--r--drivers/video/fbcmap.c55
-rw-r--r--drivers/video/fbcvt.c2
-rw-r--r--drivers/video/fbmem.c22
-rw-r--r--drivers/video/fbmon.c2
-rw-r--r--drivers/video/ffb.c21
-rw-r--r--drivers/video/fm2fb.c1
-rw-r--r--drivers/video/geode/Kconfig20
-rw-r--r--drivers/video/geode/display_gx.c23
-rw-r--r--drivers/video/geode/display_gx.h7
-rw-r--r--drivers/video/geode/gxfb_core.c53
-rw-r--r--drivers/video/geode/video_gx.c107
-rw-r--r--drivers/video/geode/video_gx.h25
-rw-r--r--drivers/video/gxt4500.c774
-rw-r--r--drivers/video/hpfb.c2
-rw-r--r--drivers/video/i810/i810-i2c.c10
-rw-r--r--drivers/video/igafb.c6
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c4
-rw-r--r--drivers/video/intelfb/intelfbdrv.c3
-rw-r--r--drivers/video/leo.c29
-rw-r--r--drivers/video/macfb.c20
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c4
-rw-r--r--drivers/video/matrox/matroxfb_base.c2
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c2
-rw-r--r--drivers/video/mbx/mbxdebugfs.c188
-rw-r--r--drivers/video/mbx/mbxfb.c359
-rw-r--r--drivers/video/mbx/reg_bits.h114
-rw-r--r--drivers/video/mbx/regs.h2
-rw-r--r--drivers/video/modedb.c6
-rw-r--r--drivers/video/neofb.c2
-rw-r--r--drivers/video/nvidia/nv_accel.c35
-rw-r--r--drivers/video/nvidia/nv_backlight.c2
-rw-r--r--drivers/video/nvidia/nv_i2c.c13
-rw-r--r--drivers/video/nvidia/nv_local.h11
-rw-r--r--drivers/video/nvidia/nv_of.c3
-rw-r--r--drivers/video/nvidia/nv_proto.h1
-rw-r--r--drivers/video/offb.c3
-rw-r--r--drivers/video/p9100.c25
-rw-r--r--drivers/video/platinumfb.c3
-rw-r--r--drivers/video/pmagb-b-fb.c2
-rw-r--r--drivers/video/pvr2fb.c18
-rw-r--r--drivers/video/pxafb.c40
-rw-r--r--drivers/video/retz3fb.c4
-rw-r--r--drivers/video/riva/fbdev.c68
-rw-r--r--drivers/video/riva/riva_hw.c10
-rw-r--r--drivers/video/riva/riva_hw.h17
-rw-r--r--drivers/video/riva/rivafb-i2c.c6
-rw-r--r--drivers/video/s3c2410fb.c213
-rw-r--r--drivers/video/sa1100fb.c6
-rw-r--r--drivers/video/savage/savagefb-i2c.c9
-rw-r--r--drivers/video/sis/init301.c7
-rw-r--r--drivers/video/sstfb.c335
-rw-r--r--drivers/video/stifb.c3
-rw-r--r--drivers/video/tcx.c33
-rw-r--r--drivers/video/tgafb.c58
-rw-r--r--drivers/video/tridentfb.c22
-rw-r--r--drivers/video/vesafb.c24
-rw-r--r--drivers/video/vga16fb.c28
-rw-r--r--drivers/video/virgefb.c17
-rw-r--r--drivers/w1/slaves/Kconfig4
-rw-r--r--drivers/zorro/proc.c2
-rw-r--r--fs/9p/error.c1
-rw-r--r--fs/9p/fid.c69
-rw-r--r--fs/9p/fid.h5
-rw-r--r--fs/9p/mux.c4
-rw-r--r--fs/9p/v9fs.c11
-rw-r--r--fs/9p/vfs_addr.c2
-rw-r--r--fs/9p/vfs_dir.c4
-rw-r--r--fs/9p/vfs_file.c53
-rw-r--r--fs/9p/vfs_inode.c206
-rw-r--r--fs/Kconfig19
-rw-r--r--fs/Makefile3
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/dir_f.c2
-rw-r--r--fs/affs/dir.c4
-rw-r--r--fs/afs/dir.c4
-rw-r--r--fs/afs/mntpt.c10
-rw-r--r--fs/aio.c29
-rw-r--r--fs/autofs/root.c4
-rw-r--r--fs/autofs4/autofs_i.h3
-rw-r--r--fs/autofs4/inode.c2
-rw-r--r--fs/autofs4/root.c16
-rw-r--r--fs/bad_inode.c330
-rw-r--r--fs/befs/btree.c2
-rw-r--r--fs/befs/debug.c6
-rw-r--r--fs/befs/linuxvfs.c4
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/inode.c4
-rw-r--r--fs/binfmt_aout.c8
-rw-r--r--fs/binfmt_elf.c65
-rw-r--r--fs/binfmt_elf_fdpic.c19
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/binfmt_misc.c12
-rw-r--r--fs/bio.c2
-rw-r--r--fs/block_dev.c403
-rw-r--r--fs/buffer.c60
-rw-r--r--fs/cifs/CHANGES7
-rw-r--r--fs/cifs/cifs_debug.c4
-rw-r--r--fs/cifs/cifsencrypt.c4
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifssmb.c2
-rw-r--r--fs/cifs/fcntl.c4
-rw-r--r--fs/cifs/file.c142
-rw-r--r--fs/cifs/misc.c8
-rw-r--r--fs/cifs/readdir.c32
-rw-r--r--fs/cifs/sess.c13
-rw-r--r--fs/coda/dir.c8
-rw-r--r--fs/coda/file.c14
-rw-r--r--fs/coda/inode.c2
-rw-r--r--fs/compat.c22
-rw-r--r--fs/compat_ioctl.c2
-rw-r--r--fs/configfs/dir.c10
-rw-r--r--fs/configfs/file.c12
-rw-r--r--fs/cramfs/inode.c2
-rw-r--r--fs/debugfs/inode.c39
-rw-r--r--fs/direct-io.c323
-rw-r--r--fs/dlm/lowcomms-tcp.c2
-rw-r--r--fs/dnotify.c4
-rw-r--r--fs/dquot.c18
-rw-r--r--fs/ecryptfs/dentry.c3
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h16
-rw-r--r--fs/ecryptfs/file.c15
-rw-r--r--fs/ecryptfs/inode.c79
-rw-r--r--fs/ecryptfs/main.c5
-rw-r--r--fs/ecryptfs/mmap.c16
-rw-r--r--fs/efs/dir.c2
-rw-r--r--fs/eventpoll.c4
-rw-r--r--fs/exec.c17
-rw-r--r--fs/ext2/dir.c2
-rw-r--r--fs/ext2/ioctl.c2
-rw-r--r--fs/ext2/super.c6
-rw-r--r--fs/ext3/dir.c8
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/ioctl.c2
-rw-r--r--fs/ext3/namei.c4
-rw-r--r--fs/ext3/super.c6
-rw-r--r--fs/ext4/dir.c8
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/inode.c2
-rw-r--r--fs/ext4/ioctl.c2
-rw-r--r--fs/ext4/namei.c4
-rw-r--r--fs/fat/dir.c6
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fcntl.c7
-rw-r--r--fs/file.c255
-rw-r--r--fs/file_table.c10
-rw-r--r--fs/freevxfs/vxfs_lookup.c2
-rw-r--r--fs/fs-writeback.c13
-rw-r--r--fs/fuse/control.c6
-rw-r--r--fs/fuse/dir.c2
-rw-r--r--fs/fuse/file.c22
-rw-r--r--fs/gfs2/Kconfig4
-rw-r--r--fs/gfs2/ops_file.c6
-rw-r--r--fs/gfs2/ops_fstype.c4
-rw-r--r--fs/hfs/dir.c2
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfsplus/dir.c2
-rw-r--r--fs/hfsplus/inode.c2
-rw-r--r--fs/hostfs/hostfs.h2
-rw-r--r--fs/hostfs/hostfs_kern.c8
-rw-r--r--fs/hostfs/hostfs_user.c4
-rw-r--r--fs/hpfs/dir.c4
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/hppfs/hppfs_kern.c12
-rw-r--r--fs/hugetlbfs/inode.c8
-rw-r--r--fs/inode.c45
-rw-r--r--fs/inotify_user.c6
-rw-r--r--fs/ioctl.c14
-rw-r--r--fs/isofs/compress.c2
-rw-r--r--fs/isofs/dir.c5
-rw-r--r--fs/jbd/commit.c8
-rw-r--r--fs/jbd/transaction.c2
-rw-r--r--fs/jffs/inode-v23.c10
-rw-r--r--fs/jffs/intrep.c14
-rw-r--r--fs/jffs/jffs_fm.c3
-rw-r--r--fs/jffs2/debug.c4
-rw-r--r--fs/jffs2/debug.h1
-rw-r--r--fs/jffs2/dir.c6
-rw-r--r--fs/jffs2/fs.c3
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/jffs2/nodelist.h10
-rw-r--r--fs/jffs2/readinode.c3
-rw-r--r--fs/jffs2/scan.c6
-rw-r--r--fs/jffs2/summary.c6
-rw-r--r--fs/jffs2/super.c7
-rw-r--r--fs/jffs2/symlink.c2
-rw-r--r--fs/jffs2/wbuf.c21
-rw-r--r--fs/jffs2/xattr.c5
-rw-r--r--fs/jfs/jfs_dtree.c6
-rw-r--r--fs/jfs/jfs_filsys.h42
-rw-r--r--fs/jfs/jfs_imap.c2
-rw-r--r--fs/jfs/jfs_metapage.c15
-rw-r--r--fs/libfs.c14
-rw-r--r--fs/lockd/clntlock.c16
-rw-r--r--fs/lockd/clntproc.c41
-rw-r--r--fs/lockd/svclock.c20
-rw-r--r--fs/lockd/svcshare.c2
-rw-r--r--fs/lockd/svcsubs.c2
-rw-r--r--fs/lockd/xdr.c8
-rw-r--r--fs/lockd/xdr4.c8
-rw-r--r--fs/locks.c32
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/namei.c15
-rw-r--r--fs/namespace.c118
-rw-r--r--fs/ncpfs/dir.c8
-rw-r--r--fs/ncpfs/file.c4
-rw-r--r--fs/ncpfs/inode.c38
-rw-r--r--fs/ncpfs/ioctl.c8
-rw-r--r--fs/ncpfs/mmap.c4
-rw-r--r--fs/nfs/dir.c20
-rw-r--r--fs/nfs/direct.c10
-rw-r--r--fs/nfs/file.c35
-rw-r--r--fs/nfs/getroot.c2
-rw-r--r--fs/nfs/idmap.c2
-rw-r--r--fs/nfs/inode.c103
-rw-r--r--fs/nfs/nfs3proc.c2
-rw-r--r--fs/nfs/nfs4proc.c2
-rw-r--r--fs/nfs/proc.c2
-rw-r--r--fs/nfs/symlink.c4
-rw-r--r--fs/nfs/write.c4
-rw-r--r--fs/nfsd/export.c34
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs2acl.c8
-rw-r--r--fs/nfsd/nfs3acl.c8
-rw-r--r--fs/nfsd/nfs3xdr.c9
-rw-r--r--fs/nfsd/nfs4proc.c625
-rw-r--r--fs/nfsd/nfs4recover.c2
-rw-r--r--fs/nfsd/nfs4state.c99
-rw-r--r--fs/nfsd/nfs4xdr.c19
-rw-r--r--fs/nfsd/nfscache.c3
-rw-r--r--fs/nfsd/nfsctl.c2
-rw-r--r--fs/nfsd/nfsfh.c20
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/nfsd/nfsxdr.c5
-rw-r--r--fs/nfsd/vfs.c84
-rw-r--r--fs/ntfs/ChangeLog7
-rw-r--r--fs/ntfs/Makefile2
-rw-r--r--fs/ntfs/aops.c4
-rw-r--r--fs/ntfs/dir.c51
-rw-r--r--fs/ntfs/file.c2
-rw-r--r--fs/ntfs/inode.c69
-rw-r--r--fs/ntfs/inode.h6
-rw-r--r--fs/ntfs/super.c7
-rw-r--r--fs/ocfs2/alloc.c2
-rw-r--r--fs/ocfs2/aops.c28
-rw-r--r--fs/ocfs2/cluster/heartbeat.c21
-rw-r--r--fs/ocfs2/cluster/nodemanager.c198
-rw-r--r--fs/ocfs2/cluster/nodemanager.h17
-rw-r--r--fs/ocfs2/cluster/tcp.c162
-rw-r--r--fs/ocfs2/cluster/tcp.h8
-rw-r--r--fs/ocfs2/cluster/tcp_internal.h15
-rw-r--r--fs/ocfs2/dir.c2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c4
-rw-r--r--fs/ocfs2/dlm/dlmfs.c4
-rw-r--r--fs/ocfs2/dlm/dlmlock.c4
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c2
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c6
-rw-r--r--fs/ocfs2/dlmglue.c89
-rw-r--r--fs/ocfs2/export.c5
-rw-r--r--fs/ocfs2/file.c55
-rw-r--r--fs/ocfs2/heartbeat.c9
-rw-r--r--fs/ocfs2/inode.c14
-rw-r--r--fs/ocfs2/journal.c46
-rw-r--r--fs/ocfs2/journal.h5
-rw-r--r--fs/ocfs2/localalloc.c2
-rw-r--r--fs/ocfs2/mmap.c6
-rw-r--r--fs/ocfs2/namei.c77
-rw-r--r--fs/ocfs2/ocfs2.h5
-rw-r--r--fs/ocfs2/ocfs2_fs.h57
-rw-r--r--fs/ocfs2/slot_map.c2
-rw-r--r--fs/ocfs2/suballoc.c6
-rw-r--r--fs/ocfs2/super.c96
-rw-r--r--fs/ocfs2/symlink.c3
-rw-r--r--fs/ocfs2/vote.c7
-rw-r--r--fs/open.c30
-rw-r--r--fs/openpromfs/inode.c2
-rw-r--r--fs/partitions/Kconfig2
-rw-r--r--fs/partitions/check.c27
-rw-r--r--fs/pipe.c43
-rw-r--r--fs/pnode.c2
-rw-r--r--fs/pnode.h2
-rw-r--r--fs/proc/array.c18
-rw-r--r--fs/proc/base.c175
-rw-r--r--fs/proc/generic.c10
-rw-r--r--fs/proc/nommu.c4
-rw-r--r--fs/proc/proc_misc.c11
-rw-r--r--fs/proc/task_mmu.c8
-rw-r--r--fs/proc/task_nommu.c4
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/ramfs/file-mmu.c4
-rw-r--r--fs/ramfs/file-nommu.c6
-rw-r--r--fs/read_write.c22
-rw-r--r--fs/readdir.c2
-rw-r--r--fs/reiserfs/bitmap.c2
-rw-r--r--fs/reiserfs/dir.c4
-rw-r--r--fs/reiserfs/file.c24
-rw-r--r--fs/reiserfs/fix_node.c6
-rw-r--r--fs/reiserfs/inode.c14
-rw-r--r--fs/reiserfs/ioctl.c2
-rw-r--r--fs/reiserfs/namei.c6
-rw-r--r--fs/reiserfs/procfs.c2
-rw-r--r--fs/reiserfs/stree.c44
-rw-r--r--fs/reiserfs/super.c2
-rw-r--r--fs/reiserfs/tail_conversion.c4
-rw-r--r--fs/reiserfs/xattr.c10
-rw-r--r--fs/reiserfs/xattr_acl.c2
-rw-r--r--fs/romfs/inode.c2
-rw-r--r--fs/select.c10
-rw-r--r--fs/seq_file.c2
-rw-r--r--fs/smbfs/cache.c2
-rw-r--r--fs/smbfs/dir.c6
-rw-r--r--fs/smbfs/file.c14
-rw-r--r--fs/smbfs/inode.c5
-rw-r--r--fs/smbfs/proc.c16
-rw-r--r--fs/smbfs/smbiod.c5
-rw-r--r--fs/smbfs/sock.c4
-rw-r--r--fs/splice.c26
-rw-r--r--fs/stack.c38
-rw-r--r--fs/stat.c2
-rw-r--r--fs/super.c6
-rw-r--r--fs/sync.c4
-rw-r--r--fs/sysfs/bin.c14
-rw-r--r--fs/sysfs/dir.c10
-rw-r--r--fs/sysfs/file.c16
-rw-r--r--fs/sysv/dir.c2
-rw-r--r--fs/sysv/super.c3
-rw-r--r--fs/sysv/sysv.h3
-rw-r--r--fs/udf/dir.c4
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/ufs/balloc.c67
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/inode.c53
-rw-r--r--fs/ufs/truncate.c4
-rw-r--r--fs/xattr.c8
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c28
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c10
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c2
-rw-r--r--fs/xfs/xfs_dfrag.c4
-rw-r--r--include/acpi/acconfig.h2
-rw-r--r--include/acpi/acpixf.h7
-rw-r--r--include/asm-alpha/cacheflush.h1
-rw-r--r--include/asm-alpha/dma-mapping.h20
-rw-r--r--include/asm-alpha/posix_types.h2
-rw-r--r--include/asm-alpha/termbits.h13
-rw-r--r--include/asm-alpha/unistd.h11
-rw-r--r--include/asm-arm/arch-at91rm9200/at91_ecc.h8
-rw-r--r--include/asm-arm/arch-at91rm9200/at91_pmc.h2
-rw-r--r--include/asm-arm/arch-at91rm9200/at91_rstc.h2
-rw-r--r--include/asm-arm/arch-at91rm9200/at91_rtc.h16
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200.h2
-rw-r--r--include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h2
-rw-r--r--include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h6
-rw-r--r--include/asm-arm/arch-at91rm9200/at91sam926x_mc.h16
-rw-r--r--include/asm-arm/arch-ep93xx/irqs.h6
-rw-r--r--include/asm-arm/arch-imx/imx-regs.h10
-rw-r--r--include/asm-arm/arch-iop13xx/io.h3
-rw-r--r--include/asm-arm/arch-iop13xx/iq81340.h5
-rw-r--r--include/asm-arm/arch-iop32x/iop32x.h2
-rw-r--r--include/asm-arm/arch-ixp23xx/memory.h16
-rw-r--r--include/asm-arm/arch-pnx4008/i2c.h67
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h3
-rw-r--r--include/asm-arm/arch-pxa/pxa2xx_spi.h5
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-cpld.h2
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-irq.h2
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-map.h2
-rw-r--r--include/asm-arm/arch-s3c2410/audio.h2
-rw-r--r--include/asm-arm/arch-s3c2410/bast-cpld.h4
-rw-r--r--include/asm-arm/arch-s3c2410/bast-irq.h4
-rw-r--r--include/asm-arm/arch-s3c2410/bast-map.h4
-rw-r--r--include/asm-arm/arch-s3c2410/bast-pmu.h2
-rw-r--r--include/asm-arm/arch-s3c2410/dma.h2
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S2
-rw-r--r--include/asm-arm/arch-s3c2410/fb.h3
-rw-r--r--include/asm-arm/arch-s3c2410/h1940-latch.h4
-rw-r--r--include/asm-arm/arch-s3c2410/hardware.h8
-rw-r--r--include/asm-arm/arch-s3c2410/iic.h2
-rw-r--r--include/asm-arm/arch-s3c2410/irqs.h3
-rw-r--r--include/asm-arm/arch-s3c2410/leds-gpio.h2
-rw-r--r--include/asm-arm/arch-s3c2410/map.h30
-rw-r--r--include/asm-arm/arch-s3c2410/nand.h4
-rw-r--r--include/asm-arm/arch-s3c2410/osiris-cpld.h2
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h4
-rw-r--r--include/asm-arm/arch-s3c2410/regs-mem.h14
-rw-r--r--include/asm-arm/arch-s3c2410/regs-serial.h2
-rw-r--r--include/asm-arm/arch-s3c2410/regs-udc.h7
-rw-r--r--include/asm-arm/arch-s3c2410/system.h4
-rw-r--r--include/asm-arm/arch-s3c2410/timex.h4
-rw-r--r--include/asm-arm/arch-s3c2410/uncompress.h5
-rw-r--r--include/asm-arm/arch-s3c2410/usb-control.h4
-rw-r--r--include/asm-arm/arch-s3c2410/vr1000-cpld.h4
-rw-r--r--include/asm-arm/arch-s3c2410/vr1000-irq.h4
-rw-r--r--include/asm-arm/arch-s3c2410/vr1000-map.h4
-rw-r--r--include/asm-arm/cacheflush.h14
-rw-r--r--include/asm-arm/cpu-multi32.h7
-rw-r--r--include/asm-arm/cpu-single.h4
-rw-r--r--include/asm-arm/elf.h1
-rw-r--r--include/asm-arm/flat.h4
-rw-r--r--include/asm-arm/fpstate.h3
-rw-r--r--include/asm-arm/hardware/iop3xx.h6
-rw-r--r--include/asm-arm/irq.h5
-rw-r--r--include/asm-arm/pgtable.h11
-rw-r--r--include/asm-arm/processor.h16
-rw-r--r--include/asm-arm/system.h52
-rw-r--r--include/asm-arm/termbits.h12
-rw-r--r--include/asm-arm/thread_info.h2
-rw-r--r--include/asm-arm/unistd.h25
-rw-r--r--include/asm-arm26/cacheflush.h1
-rw-r--r--include/asm-arm26/termbits.h12
-rw-r--r--include/asm-avr32/arch-at32ap/at32ap7000.h33
-rw-r--r--include/asm-avr32/arch-at32ap/board.h3
-rw-r--r--include/asm-avr32/arch-at32ap/portmux.h20
-rw-r--r--include/asm-avr32/cacheflush.h1
-rw-r--r--include/asm-avr32/dma-mapping.h12
-rw-r--r--include/asm-avr32/pgalloc.h2
-rw-r--r--include/asm-avr32/termbits.h11
-rw-r--r--include/asm-cris/cacheflush.h1
-rw-r--r--include/asm-cris/termbits.h11
-rw-r--r--include/asm-frv/Kbuild6
-rw-r--r--include/asm-frv/bitops.h44
-rw-r--r--include/asm-frv/cacheflush.h1
-rw-r--r--include/asm-frv/page.h4
-rw-r--r--include/asm-frv/ptrace.h4
-rw-r--r--include/asm-frv/termbits.h11
-rw-r--r--include/asm-frv/termios.h2
-rw-r--r--include/asm-frv/thread_info.h2
-rw-r--r--include/asm-generic/bug.h18
-rw-r--r--include/asm-generic/libata-portmap.h4
-rw-r--r--include/asm-generic/page.h38
-rw-r--r--include/asm-generic/termios.h4
-rw-r--r--include/asm-generic/vmlinux.lds.h34
-rw-r--r--include/asm-h8300/cacheflush.h1
-rw-r--r--include/asm-h8300/termbits.h11
-rw-r--r--include/asm-i386/acpi.h26
-rw-r--r--include/asm-i386/boot.h3
-rw-r--r--include/asm-i386/bug.h28
-rw-r--r--include/asm-i386/cacheflush.h1
-rw-r--r--include/asm-i386/e820.h2
-rw-r--r--include/asm-i386/elf.h51
-rw-r--r--include/asm-i386/fixmap.h2
-rw-r--r--include/asm-i386/ide.h4
-rw-r--r--include/asm-i386/msr.h5
-rw-r--r--include/asm-i386/page.h2
-rw-r--r--include/asm-i386/processor.h1
-rw-r--r--include/asm-i386/termbits.h11
-rw-r--r--include/asm-i386/thread_info.h2
-rw-r--r--include/asm-i386/topology.h1
-rw-r--r--include/asm-i386/unwind.h91
-rw-r--r--include/asm-ia64/break.h4
-rw-r--r--include/asm-ia64/cacheflush.h1
-rw-r--r--include/asm-ia64/checksum.h6
-rw-r--r--include/asm-ia64/kprobes.h1
-rw-r--r--include/asm-ia64/pci.h9
-rw-r--r--include/asm-ia64/posix_types.h2
-rw-r--r--include/asm-ia64/scatterlist.h3
-rw-r--r--include/asm-ia64/sn/xpc.h2
-rw-r--r--include/asm-ia64/termbits.h11
-rw-r--r--include/asm-ia64/thread_info.h2
-rw-r--r--include/asm-ia64/topology.h1
-rw-r--r--include/asm-m32r/cacheflush.h3
-rw-r--r--include/asm-m32r/ide.h3
-rw-r--r--include/asm-m32r/m32102.h7
-rw-r--r--include/asm-m32r/ptrace.h28
-rw-r--r--include/asm-m32r/sigcontext.h13
-rw-r--r--include/asm-m32r/termbits.h11
-rw-r--r--include/asm-m68k/cacheflush.h2
-rw-r--r--include/asm-m68k/sun3-head.h1
-rw-r--r--include/asm-m68k/sun3ints.h1
-rw-r--r--include/asm-m68k/swim_iop.h221
-rw-r--r--include/asm-m68k/termbits.h11
-rw-r--r--include/asm-m68k/uaccess.h1
-rw-r--r--include/asm-m68knommu/cacheflush.h1
-rw-r--r--include/asm-mips/bootinfo.h1
-rw-r--r--include/asm-mips/cacheflush.h2
-rw-r--r--include/asm-mips/checksum.h34
-rw-r--r--include/asm-mips/compat.h1
-rw-r--r--include/asm-mips/hazards.h2
-rw-r--r--include/asm-mips/irq.h6
-rw-r--r--include/asm-mips/irqflags.h22
-rw-r--r--include/asm-mips/mach-ip27/irq.h2
-rw-r--r--include/asm-mips/mach-ip27/topology.h1
-rw-r--r--include/asm-mips/mach-rm/cpu-feature-overrides.h (renamed from include/asm-mips/mach-rm200/cpu-feature-overrides.h)0
-rw-r--r--include/asm-mips/mach-rm/mc146818rtc.h (renamed from include/asm-mips/mach-rm200/mc146818rtc.h)0
-rw-r--r--include/asm-mips/mach-rm/timex.h (renamed from include/asm-mips/mach-rm200/timex.h)0
-rw-r--r--include/asm-mips/page.h16
-rw-r--r--include/asm-mips/pci.h6
-rw-r--r--include/asm-mips/pgtable.h10
-rw-r--r--include/asm-mips/ptrace.h8
-rw-r--r--include/asm-mips/sn/arch.h1
-rw-r--r--include/asm-mips/sn/klconfig.h2
-rw-r--r--include/asm-mips/system.h9
-rw-r--r--include/asm-mips/termbits.h11
-rw-r--r--include/asm-mips/thread_info.h2
-rw-r--r--include/asm-mips/war.h2
-rw-r--r--include/asm-parisc/cacheflush.h4
-rw-r--r--include/asm-parisc/termbits.h11
-rw-r--r--include/asm-powerpc/Kbuild2
-rw-r--r--include/asm-powerpc/atomic.h8
-rw-r--r--include/asm-powerpc/bitops.h21
-rw-r--r--include/asm-powerpc/bug.h105
-rw-r--r--include/asm-powerpc/cacheflush.h1
-rw-r--r--include/asm-powerpc/cputable.h16
-rw-r--r--include/asm-powerpc/dcr-native.h37
-rw-r--r--include/asm-powerpc/dcr.h2
-rw-r--r--include/asm-powerpc/dma-mapping.h12
-rw-r--r--include/asm-powerpc/hvcall.h2
-rw-r--r--include/asm-powerpc/hw_irq.h19
-rw-r--r--include/asm-powerpc/libata-portmap.h12
-rw-r--r--include/asm-powerpc/module.h2
-rw-r--r--include/asm-powerpc/mpc52xx.h1
-rw-r--r--include/asm-powerpc/page_32.h10
-rw-r--r--include/asm-powerpc/pci-bridge.h4
-rw-r--r--include/asm-powerpc/pci.h33
-rw-r--r--include/asm-powerpc/posix_types.h2
-rw-r--r--include/asm-powerpc/reg.h2
-rw-r--r--include/asm-powerpc/rtas.h3
-rw-r--r--include/asm-powerpc/spu.h2
-rw-r--r--include/asm-powerpc/termbits.h13
-rw-r--r--include/asm-powerpc/thread_info.h2
-rw-r--r--include/asm-powerpc/topology.h1
-rw-r--r--include/asm-ppc/pci-bridge.h8
-rw-r--r--include/asm-ppc/pci.h23
-rw-r--r--include/asm-ppc/reg_booke.h36
-rw-r--r--include/asm-s390/cacheflush.h1
-rw-r--r--include/asm-s390/dasd.h2
-rw-r--r--include/asm-s390/futex.h4
-rw-r--r--include/asm-s390/page.h22
-rw-r--r--include/asm-s390/pgalloc.h3
-rw-r--r--include/asm-s390/pgtable.h16
-rw-r--r--include/asm-s390/posix_types.h2
-rw-r--r--include/asm-s390/qdio.h1
-rw-r--r--include/asm-s390/reset.h1
-rw-r--r--include/asm-s390/termbits.h11
-rw-r--r--include/asm-sh/atomic-irq.h71
-rw-r--r--include/asm-sh/atomic-llsc.h107
-rw-r--r--include/asm-sh/atomic.h153
-rw-r--r--include/asm-sh/bug.h53
-rw-r--r--include/asm-sh/bugs.h12
-rw-r--r--include/asm-sh/checksum.h69
-rw-r--r--include/asm-sh/cpu-sh2/cacheflush.h2
-rw-r--r--include/asm-sh/cpu-sh3/cacheflush.h3
-rw-r--r--include/asm-sh/cpu-sh4/cache.h2
-rw-r--r--include/asm-sh/cpu-sh4/cacheflush.h1
-rw-r--r--include/asm-sh/cpu-sh4/freq.h2
-rw-r--r--include/asm-sh/dma-mapping.h10
-rw-r--r--include/asm-sh/irq.h5
-rw-r--r--include/asm-sh/pgtable.h47
-rw-r--r--include/asm-sh/processor.h8
-rw-r--r--include/asm-sh/push-switch.h3
-rw-r--r--include/asm-sh/termbits.h11
-rw-r--r--include/asm-sh/thread_info.h2
-rw-r--r--include/asm-sh64/cacheflush.h2
-rw-r--r--include/asm-sh64/pgalloc.h2
-rw-r--r--include/asm-sparc/bitops.h100
-rw-r--r--include/asm-sparc/cacheflush.h1
-rw-r--r--include/asm-sparc/checksum.h2
-rw-r--r--include/asm-sparc/of_device.h2
-rw-r--r--include/asm-sparc/termbits.h12
-rw-r--r--include/asm-sparc64/cacheflush.h1
-rw-r--r--include/asm-sparc64/dma.h6
-rw-r--r--include/asm-sparc64/hw_irq.h2
-rw-r--r--include/asm-sparc64/irqflags.h89
-rw-r--r--include/asm-sparc64/kprobes.h11
-rw-r--r--include/asm-sparc64/of_device.h2
-rw-r--r--include/asm-sparc64/percpu.h10
-rw-r--r--include/asm-sparc64/rwsem.h32
-rw-r--r--include/asm-sparc64/system.h49
-rw-r--r--include/asm-sparc64/termbits.h12
-rw-r--r--include/asm-sparc64/ttable.h45
-rw-r--r--include/asm-um/bug.h4
-rw-r--r--include/asm-um/pgtable.h9
-rw-r--r--include/asm-v850/cacheflush.h1
-rw-r--r--include/asm-v850/termbits.h11
-rw-r--r--include/asm-x86_64/acpi.h26
-rw-r--r--include/asm-x86_64/bitops.h34
-rw-r--r--include/asm-x86_64/bug.h44
-rw-r--r--include/asm-x86_64/cacheflush.h1
-rw-r--r--include/asm-x86_64/dma-mapping.h3
-rw-r--r--include/asm-x86_64/ioctls.h4
-rw-r--r--include/asm-x86_64/msr.h4
-rw-r--r--include/asm-x86_64/termbits.h27
-rw-r--r--include/asm-x86_64/termios.h6
-rw-r--r--include/asm-x86_64/thread_info.h2
-rw-r--r--include/asm-x86_64/topology.h1
-rw-r--r--include/asm-x86_64/uaccess.h2
-rw-r--r--include/asm-x86_64/unwind.h96
-rw-r--r--include/asm-xtensa/asmmacro.h153
-rw-r--r--include/asm-xtensa/bug.h25
-rw-r--r--include/asm-xtensa/byteorder.h5
-rw-r--r--include/asm-xtensa/cache.h20
-rw-r--r--include/asm-xtensa/cacheasm.h177
-rw-r--r--include/asm-xtensa/cacheflush.h4
-rw-r--r--include/asm-xtensa/checksum.h2
-rw-r--r--include/asm-xtensa/coprocessor.h13
-rw-r--r--include/asm-xtensa/dma.h5
-rw-r--r--include/asm-xtensa/elf.h9
-rw-r--r--include/asm-xtensa/fcntl.h98
-rw-r--r--include/asm-xtensa/fixmap.h252
-rw-r--r--include/asm-xtensa/io.h64
-rw-r--r--include/asm-xtensa/irq.h8
-rw-r--r--include/asm-xtensa/irq_regs.h1
-rw-r--r--include/asm-xtensa/mmu_context.h269
-rw-r--r--include/asm-xtensa/page.h10
-rw-r--r--include/asm-xtensa/param.h2
-rw-r--r--include/asm-xtensa/pgtable.h41
-rw-r--r--include/asm-xtensa/platform-iss/hardware.h10
-rw-r--r--include/asm-xtensa/platform-iss/simcall.h62
-rw-r--r--include/asm-xtensa/posix_types.h4
-rw-r--r--include/asm-xtensa/processor.h24
-rw-r--r--include/asm-xtensa/ptrace.h2
-rw-r--r--include/asm-xtensa/regs.h138
-rw-r--r--include/asm-xtensa/sembuf.h2
-rw-r--r--include/asm-xtensa/shmbuf.h21
-rw-r--r--include/asm-xtensa/stat.h112
-rw-r--r--include/asm-xtensa/syscall.h20
-rw-r--r--include/asm-xtensa/system.h2
-rw-r--r--include/asm-xtensa/termbits.h11
-rw-r--r--include/asm-xtensa/timex.h17
-rw-r--r--include/asm-xtensa/tlbflush.h42
-rw-r--r--include/asm-xtensa/uaccess.h1
-rw-r--r--include/asm-xtensa/unistd.h798
-rw-r--r--include/asm-xtensa/variant-fsf/core.h359
-rw-r--r--include/asm-xtensa/variant-fsf/tie.h22
-rw-r--r--include/asm-xtensa/xtensa/cacheasm.h708
-rw-r--r--include/asm-xtensa/xtensa/cacheattrasm.h432
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/core.h1270
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/defs.h270
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/specreg.h99
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/system.h198
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/tie.h275
-rw-r--r--include/asm-xtensa/xtensa/coreasm.h526
-rw-r--r--include/asm-xtensa/xtensa/corebits.h77
-rw-r--r--include/asm-xtensa/xtensa/hal.h822
-rw-r--r--include/asm-xtensa/xtensa/simcall.h130
-rw-r--r--include/asm-xtensa/xtensa/xt2000-uart.h155
-rw-r--r--include/asm-xtensa/xtensa/xt2000.h408
-rw-r--r--include/asm-xtensa/xtensa/xtboard.h120
-rw-r--r--include/linux/Kbuild10
-rw-r--r--include/linux/acpi.h1
-rw-r--r--include/linux/aio.h1
-rw-r--r--include/linux/backlight.h2
-rw-r--r--include/linux/bio.h1
-rw-r--r--include/linux/bitops.h6
-rw-r--r--include/linux/bitrev.h15
-rw-r--r--include/linux/blkdev.h19
-rw-r--r--include/linux/bug.h47
-rw-r--r--include/linux/cdev.h4
-rw-r--r--include/linux/clocksource.h2
-rw-r--r--include/linux/coda_linux.h2
-rw-r--r--include/linux/compiler.h2
-rw-r--r--include/linux/configfs.h25
-rw-r--r--include/linux/connector.h2
-rw-r--r--include/linux/cpufreq.h3
-rw-r--r--include/linux/cpuset.h24
-rw-r--r--include/linux/crc32.h4
-rw-r--r--include/linux/dccp.h26
-rw-r--r--include/linux/debug_locks.h2
-rw-r--r--include/linux/device-mapper.h7
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/dm-ioctl.h9
-rw-r--r--include/linux/efi.h2
-rw-r--r--include/linux/elevator.h3
-rw-r--r--include/linux/fault-inject.h84
-rw-r--r--include/linux/fb.h8
-rw-r--r--include/linux/file.h20
-rw-r--r--include/linux/freezer.h13
-rw-r--r--include/linux/fs.h31
-rw-r--r--include/linux/fs_stack.h31
-rw-r--r--include/linux/fsl_devices.h1
-rw-r--r--include/linux/fsnotify.h2
-rw-r--r--include/linux/futex.h2
-rw-r--r--include/linux/gameport.h2
-rw-r--r--include/linux/generic_serial.h2
-rw-r--r--include/linux/genhd.h4
-rw-r--r--include/linux/hdreg.h8
-rw-r--r--include/linux/hid-debug.h (renamed from drivers/usb/input/hid-debug.h)7
-rw-r--r--include/linux/hid.h (renamed from drivers/usb/input/hid.h)86
-rw-r--r--include/linux/highmem.h9
-rw-r--r--include/linux/i2c-algo-bit.h5
-rw-r--r--include/linux/i2c-algo-ite.h72
-rw-r--r--include/linux/i2c-algo-pca.h1
-rw-r--r--include/linux/i2c-algo-pcf.h3
-rw-r--r--include/linux/i2c-algo-sgi.h1
-rw-r--r--include/linux/i2c-id.h20
-rw-r--r--include/linux/i2c-pnx.h43
-rw-r--r--include/linux/i2c.h75
-rw-r--r--include/linux/i2o-dev.h5
-rw-r--r--include/linux/ide.h3
-rw-r--r--include/linux/if_addr.h6
-rw-r--r--include/linux/if_fddi.h2
-rw-r--r--include/linux/if_link.h6
-rw-r--r--include/linux/if_tunnel.h2
-rw-r--r--include/linux/init.h1
-rw-r--r--include/linux/init_task.h17
-rw-r--r--include/linux/input.h33
-rw-r--r--include/linux/interrupt.h3
-rw-r--r--include/linux/ioport.h3
-rw-r--r--include/linux/isdn.h8
-rw-r--r--include/linux/istallion.h36
-rw-r--r--include/linux/kernel.h16
-rw-r--r--include/linux/kobject.h11
-rw-r--r--include/linux/kvm.h240
-rw-r--r--include/linux/libata.h10
-rw-r--r--include/linux/list.h10
-rw-r--r--include/linux/lockd/bind.h2
-rw-r--r--include/linux/lockd/lockd.h4
-rw-r--r--include/linux/lockd/sm_inter.h2
-rw-r--r--include/linux/lockd/xdr.h8
-rw-r--r--include/linux/lockdep.h16
-rw-r--r--include/linux/log2.h157
-rw-r--r--include/linux/magic.h1
-rw-r--r--include/linux/mm.h4
-rw-r--r--include/linux/mmc/mmc.h2
-rw-r--r--include/linux/mmzone.h8
-rw-r--r--include/linux/mnt_namespace.h42
-rw-r--r--include/linux/module.h7
-rw-r--r--include/linux/mount.h5
-rw-r--r--include/linux/mtd/blktrans.h3
-rw-r--r--include/linux/mtd/mtd.h24
-rw-r--r--include/linux/mtd/nand.h15
-rw-r--r--include/linux/mtd/onenand.h8
-rw-r--r--include/linux/mtd/onenand_regs.h1
-rw-r--r--include/linux/mtio.h146
-rw-r--r--include/linux/mutex.h4
-rw-r--r--include/linux/n_r3964.h2
-rw-r--r--include/linux/namei.h5
-rw-r--r--include/linux/namespace.h42
-rw-r--r--include/linux/ncp_mount.h2
-rw-r--r--include/linux/net.h2
-rw-r--r--include/linux/netdevice.h12
-rw-r--r--include/linux/netfilter/nf_conntrack_tcp.h2
-rw-r--r--include/linux/netfilter_arp/arp_tables.h1
-rw-r--r--include/linux/netfilter_bridge.h1
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h2
-rw-r--r--include/linux/netfilter_ipv6.h2
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--include/linux/nfsd/nfsd.h8
-rw-r--r--include/linux/nfsd/nfsfh.h15
-rw-r--r--include/linux/nfsd/state.h1
-rw-r--r--include/linux/nfsd/xdr.h4
-rw-r--r--include/linux/nfsd/xdr3.h8
-rw-r--r--include/linux/nfsd/xdr4.h40
-rw-r--r--include/linux/nsproxy.h6
-rw-r--r--include/linux/page-flags.h8
-rw-r--r--include/linux/pci.h29
-rw-r--r--include/linux/pci_ids.h16
-rw-r--r--include/linux/pci_regs.h19
-rw-r--r--include/linux/pid.h5
-rw-r--r--include/linux/pid_namespace.h45
-rw-r--r--include/linux/pipe_fs_i.h5
-rw-r--r--include/linux/pktcdvd.h25
-rw-r--r--include/linux/platform_device.h2
-rw-r--r--include/linux/profile.h1
-rw-r--r--include/linux/pspace.h23
-rw-r--r--include/linux/qic117.h290
-rw-r--r--include/linux/raid/md.h2
-rw-r--r--include/linux/raid/raid5.h3
-rw-r--r--include/linux/reciprocal_div.h32
-rw-r--r--include/linux/reiserfs_fs.h44
-rw-r--r--include/linux/reiserfs_fs_i.h2
-rw-r--r--include/linux/rmap.h2
-rw-r--r--include/linux/rtc.h1
-rw-r--r--include/linux/rtmutex.h4
-rw-r--r--include/linux/rtnetlink.h2
-rw-r--r--include/linux/sched.h31
-rw-r--r--include/linux/sctp.h10
-rw-r--r--include/linux/seqlock.h7
-rw-r--r--include/linux/serial_core.h8
-rw-r--r--include/linux/serio.h12
-rw-r--r--include/linux/slab.h306
-rw-r--r--include/linux/slab_def.h100
-rw-r--r--include/linux/smb_fs_sb.h2
-rw-r--r--include/linux/spi/spi.h2
-rw-r--r--include/linux/stallion.h52
-rw-r--r--include/linux/sunrpc/sched.h1
-rw-r--r--include/linux/sunrpc/svc.h5
-rw-r--r--include/linux/swap.h2
-rw-r--r--include/linux/sysctl.h7
-rw-r--r--include/linux/sysrq.h22
-rw-r--r--include/linux/task_io_accounting.h37
-rw-r--r--include/linux/task_io_accounting_ops.h47
-rw-r--r--include/linux/taskstats.h28
-rw-r--r--include/linux/tfrc.h8
-rw-r--r--include/linux/timer.h10
-rw-r--r--include/linux/topology.h5
-rw-r--r--include/linux/tty.h20
-rw-r--r--include/linux/tty_driver.h12
-rw-r--r--include/linux/tty_ldisc.h4
-rw-r--r--include/linux/unwind.h63
-rw-r--r--include/linux/usb/serial.h2
-rw-r--r--include/linux/videodev2.h10
-rw-r--r--include/linux/vmstat.h11
-rw-r--r--include/linux/workqueue.h36
-rw-r--r--include/linux/xfrm.h2
-rw-r--r--include/media/cx2341x.h2
-rw-r--r--include/media/ir-common.h2
-rw-r--r--include/media/saa7146.h20
-rw-r--r--include/media/tuner-types.h4
-rw-r--r--include/media/tuner.h1
-rw-r--r--include/media/tveeprom.h2
-rw-r--r--include/media/v4l2-common.h7
-rw-r--r--include/media/v4l2-dev.h14
-rw-r--r--include/net/ax25.h48
-rw-r--r--include/net/bluetooth/hci.h4
-rw-r--r--include/net/ieee80211.h2
-rw-r--r--include/net/inet6_connection_sock.h2
-rw-r--r--include/net/inet_connection_sock.h3
-rw-r--r--include/net/ip.h5
-rw-r--r--include/net/ip6_checksum.h2
-rw-r--r--include/net/ip6_fib.h4
-rw-r--r--include/net/irda/ircomm_tty.h2
-rw-r--r--include/net/neighbour.h18
-rw-r--r--include/net/netfilter/nf_conntrack_compat.h11
-rw-r--r--include/net/rose.h6
-rw-r--r--include/net/sctp/sctp.h4
-rw-r--r--include/net/sctp/sm.h1
-rw-r--r--include/net/sctp/structs.h18
-rw-r--r--include/net/sctp/ulpevent.h2
-rw-r--r--include/net/sctp/user.h30
-rw-r--r--include/net/tcp.h7
-rw-r--r--include/net/x25.h1
-rw-r--r--include/rdma/ib_marshall.h5
-rw-r--r--include/rdma/ib_verbs.h268
-rw-r--r--include/rdma/rdma_cm.h62
-rw-r--r--include/rdma/rdma_cm_ib.h3
-rw-r--r--include/rdma/rdma_user_cm.h206
-rw-r--r--include/sound/core.h18
-rw-r--r--include/sound/pcm_oss.h1
-rw-r--r--include/sound/version.h4
-rw-r--r--include/sound/ymfpci.h5
-rw-r--r--include/video/mbxfb.h31
-rw-r--r--include/video/pm3fb.h24
-rw-r--r--include/video/sstfb.h13
-rw-r--r--init/Kconfig21
-rw-r--r--init/initramfs.c6
-rw-r--r--init/main.c21
-rw-r--r--init/version.c6
-rw-r--r--ipc/mqueue.c16
-rw-r--r--ipc/msgutil.c4
-rw-r--r--ipc/shm.c18
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/acct.c26
-rw-r--r--kernel/auditfilter.c4
-rw-r--r--kernel/auditsc.c6
-rw-r--r--kernel/cpu.c8
-rw-r--r--kernel/cpuset.c106
-rw-r--r--kernel/exit.c104
-rw-r--r--kernel/fork.c85
-rw-r--r--kernel/futex.c10
-rw-r--r--kernel/irq/chip.c5
-rw-r--r--kernel/irq/manage.c3
-rw-r--r--kernel/irq/proc.c3
-rw-r--r--kernel/irq/spurious.c2
-rw-r--r--kernel/kallsyms.c16
-rw-r--r--kernel/kmod.c2
-rw-r--r--kernel/kprobes.c20
-rw-r--r--kernel/lockdep.c207
-rw-r--r--kernel/module.c67
-rw-r--r--kernel/mutex.c9
-rw-r--r--kernel/nsproxy.c38
-rw-r--r--kernel/params.c6
-rw-r--r--kernel/pid.c75
-rw-r--r--kernel/power/Kconfig9
-rw-r--r--kernel/power/disk.c8
-rw-r--r--kernel/power/main.c2
-rw-r--r--kernel/power/process.c21
-rw-r--r--kernel/power/swap.c9
-rw-r--r--kernel/power/user.c7
-rw-r--r--kernel/printk.c2
-rw-r--r--kernel/profile.c17
-rw-r--r--kernel/rcutorture.c3
-rw-r--r--kernel/relay.c25
-rw-r--r--kernel/sched.c538
-rw-r--r--kernel/signal.c17
-rw-r--r--kernel/sys.c38
-rw-r--r--kernel/sysctl.c390
-rw-r--r--kernel/time/clocksource.c8
-rw-r--r--kernel/timer.c169
-rw-r--r--kernel/tsacct.c9
-rw-r--r--kernel/unwind.c1305
-rw-r--r--kernel/workqueue.c45
-rw-r--r--lib/Kconfig9
-rw-r--r--lib/Kconfig.debug102
-rw-r--r--lib/Makefile9
-rw-r--r--lib/bitrev.c58
-rw-r--r--lib/bug.c163
-rw-r--r--lib/crc32.c28
-rw-r--r--lib/fault-inject.c306
-rw-r--r--lib/ioremap.c1
-rw-r--r--lib/kobject_uevent.c44
-rw-r--r--lib/kref.c7
-rw-r--r--lib/reciprocal_div.c9
-rw-r--r--mm/bounce.c4
-rw-r--r--mm/fadvise.c2
-rw-r--r--mm/filemap.c11
-rw-r--r--mm/filemap_xip.c8
-rw-r--r--mm/fremap.c2
-rw-r--r--mm/hugetlb.c8
-rw-r--r--mm/memory.c59
-rw-r--r--mm/memory_hotplug.c6
-rw-r--r--mm/mempolicy.c6
-rw-r--r--mm/mincore.c183
-rw-r--r--mm/mmap.c17
-rw-r--r--mm/mremap.c1
-rw-r--r--mm/nommu.c12
-rw-r--r--mm/oom_kill.c21
-rw-r--r--mm/page-writeback.c147
-rw-r--r--mm/page_alloc.c130
-rw-r--r--mm/readahead.c4
-rw-r--r--mm/rmap.c36
-rw-r--r--mm/shmem.c27
-rw-r--r--mm/slab.c119
-rw-r--r--mm/slob.c27
-rw-r--r--mm/swapfile.c12
-rw-r--r--mm/tiny-shmem.c4
-rw-r--r--mm/truncate.c49
-rw-r--r--mm/vmscan.c47
-rw-r--r--net/atm/proc.c2
-rw-r--r--net/ax25/af_ax25.c4
-rw-r--r--net/ax25/ax25_addr.c36
-rw-r--r--net/ax25/ax25_iface.c103
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/bluetooth/cmtp/capi.c39
-rw-r--r--net/bluetooth/hci_sock.c4
-rw-r--r--net/bluetooth/hci_sysfs.c7
-rw-r--r--net/bluetooth/l2cap.c10
-rw-r--r--net/bluetooth/rfcomm/sock.c9
-rw-r--r--net/bluetooth/rfcomm/tty.c26
-rw-r--r--net/bridge/br_netfilter.c188
-rw-r--r--net/bridge/netfilter/ebtables.c3
-rw-r--r--net/core/flow.c26
-rw-r--r--net/core/neighbour.c11
-rw-r--r--net/core/netpoll.c53
-rw-r--r--net/core/pktgen.c156
-rw-r--r--net/dccp/ackvec.c4
-rw-r--r--net/dccp/ccid.h10
-rw-r--r--net/dccp/ccids/ccid2.c12
-rw-r--r--net/dccp/ccids/ccid3.c517
-rw-r--r--net/dccp/ccids/ccid3.h46
-rw-r--r--net/dccp/ccids/lib/packet_history.c219
-rw-r--r--net/dccp/ccids/lib/packet_history.h128
-rw-r--r--net/dccp/ccids/lib/tfrc.h23
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c28
-rw-r--r--net/dccp/dccp.h3
-rw-r--r--net/dccp/feat.c6
-rw-r--r--net/dccp/input.c47
-rw-r--r--net/dccp/ipv4.c26
-rw-r--r--net/dccp/ipv6.c24
-rw-r--r--net/dccp/minisocks.c2
-rw-r--r--net/dccp/options.c5
-rw-r--r--net/dccp/output.c43
-rw-r--r--net/dccp/proto.c6
-rw-r--r--net/dccp/timer.c14
-rw-r--r--net/decnet/dn_dev.c17
-rw-r--r--net/decnet/sysctl_net_decnet.c6
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c6
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c2
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/devinet.c9
-rw-r--r--net/ipv4/fib_trie.c34
-rw-r--r--net/ipv4/ip_fragment.c2
-rw-r--r--net/ipv4/ip_output.c17
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c17
-rw-r--r--net/ipv4/netfilter.c7
-rw-r--r--net/ipv4/netfilter/Kconfig6
-rw-r--r--net/ipv4/netfilter/Makefile20
-rw-r--r--net/ipv4/netfilter/arp_tables.c5
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c10
-rw-r--r--net/ipv4/netfilter/ip_tables.c191
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c10
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c5
-rw-r--r--net/ipv4/netfilter/ipt_recent.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c2
-rw-r--r--net/ipv4/route.c6
-rw-r--r--net/ipv4/sysctl_net_ipv4.c16
-rw-r--r--net/ipv4/tcp.c5
-rw-r--r--net/ipv4/tcp_input.c15
-rw-r--r--net/ipv4/tcp_ipv4.c5
-rw-r--r--net/ipv4/tcp_output.c6
-rw-r--r--net/ipv4/tcp_probe.c2
-rw-r--r--net/ipv4/udp.c13
-rw-r--r--net/ipv6/addrconf.c17
-rw-r--r--net/ipv6/af_inet6.c2
-rw-r--r--net/ipv6/inet6_connection_sock.c3
-rw-r--r--net/ipv6/ip6_output.c17
-rw-r--r--net/ipv6/ipv6_sockglue.c23
-rw-r--r--net/ipv6/mcast.c6
-rw-r--r--net/ipv6/ndisc.c16
-rw-r--r--net/ipv6/netfilter/Kconfig5
-rw-r--r--net/ipv6/netfilter/ip6_tables.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c2
-rw-r--r--net/ipv6/route.c3
-rw-r--r--net/irda/ircomm/ircomm_tty_ioctl.c2
-rw-r--r--net/netfilter/Kconfig31
-rw-r--r--net/netfilter/nf_conntrack_netbios_ns.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c4
-rw-r--r--net/netfilter/nf_conntrack_pptp.c2
-rw-r--r--net/netfilter/nf_conntrack_sip.c10
-rw-r--r--net/netfilter/xt_CONNMARK.c14
-rw-r--r--net/netfilter/xt_CONNSECMARK.c14
-rw-r--r--net/netfilter/xt_connbytes.c43
-rw-r--r--net/netfilter/xt_connmark.c7
-rw-r--r--net/netfilter/xt_conntrack.c8
-rw-r--r--net/netfilter/xt_hashlimit.c2
-rw-r--r--net/netfilter/xt_helper.c8
-rw-r--r--net/netfilter/xt_physdev.c12
-rw-r--r--net/netfilter/xt_state.c7
-rw-r--r--net/netlabel/netlabel_cipso_v4.c43
-rw-r--r--net/netlink/af_netlink.c5
-rw-r--r--net/netrom/af_netrom.c15
-rw-r--r--net/netrom/nr_dev.c24
-rw-r--r--net/netrom/nr_route.c19
-rw-r--r--net/packet/af_packet.c46
-rw-r--r--net/rose/af_rose.c18
-rw-r--r--net/rose/rose_dev.c22
-rw-r--r--net/rose/rose_loopback.c5
-rw-r--r--net/rose/rose_route.c47
-rw-r--r--net/sched/act_ipt.c8
-rw-r--r--net/sched/sch_cbq.c21
-rw-r--r--net/sched/sch_htb.c51
-rw-r--r--net/sctp/associola.c1
-rw-r--r--net/sctp/ipv6.c38
-rw-r--r--net/sctp/protocol.c76
-rw-r--r--net/sctp/sm_make_chunk.c34
-rw-r--r--net/sctp/sm_sideeffect.c8
-rw-r--r--net/sctp/sm_statefuns.c76
-rw-r--r--net/sctp/sm_statetable.c2
-rw-r--r--net/sctp/socket.c152
-rw-r--r--net/sctp/ulpevent.c24
-rw-r--r--net/socket.c16
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c2
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c11
-rw-r--r--net/sunrpc/cache.c41
-rw-r--r--net/sunrpc/clnt.c8
-rw-r--r--net/sunrpc/rpc_pipe.c8
-rw-r--r--net/sunrpc/sched.c3
-rw-r--r--net/sunrpc/svc.c34
-rw-r--r--net/sunrpc/svcauth_unix.c5
-rw-r--r--net/sunrpc/svcsock.c14
-rw-r--r--net/tipc/config.c2
-rw-r--r--net/unix/garbage.c2
-rw-r--r--net/x25/af_x25.c2
-rw-r--r--net/x25/x25_dev.c1
-rw-r--r--net/x25/x25_facilities.c12
-rw-r--r--net/xfrm/xfrm_algo.c3
-rw-r--r--net/xfrm/xfrm_policy.c16
-rw-r--r--net/xfrm/xfrm_user.c73
-rw-r--r--scripts/Kbuild.include19
-rw-r--r--scripts/Makefile.headersinst2
-rw-r--r--scripts/kallsyms.c2
-rw-r--r--scripts/kconfig/conf.c2
-rw-r--r--scripts/kconfig/confdata.c37
-rw-r--r--scripts/kconfig/gconf.c35
-rw-r--r--scripts/kconfig/gconf.glade4
-rw-r--r--scripts/kconfig/lkc.h2
-rw-r--r--scripts/kconfig/lkc_proto.h3
-rw-r--r--scripts/kconfig/mconf.c21
-rw-r--r--scripts/kconfig/qconf.cc18
-rw-r--r--scripts/kconfig/qconf.h3
-rw-r--r--scripts/kconfig/symbol.c3
-rw-r--r--scripts/kconfig/zconf.tab.c_shipped2
-rw-r--r--scripts/kconfig/zconf.y2
-rwxr-xr-xscripts/kernel-doc17
-rw-r--r--scripts/mod/modpost.c28
-rw-r--r--security/selinux/hooks.c33
-rw-r--r--security/selinux/include/xfrm.h9
-rw-r--r--security/selinux/selinuxfs.c8
-rw-r--r--security/selinux/ss/context.h23
-rw-r--r--security/selinux/ss/mls.c30
-rw-r--r--security/selinux/ss/mls.h20
-rw-r--r--security/selinux/ss/services.c16
-rw-r--r--sound/Kconfig8
-rw-r--r--sound/Makefile3
-rw-r--r--sound/ac97_bus.c (renamed from sound/pci/ac97/ac97_bus.c)0
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.h1
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c1
-rw-r--r--sound/aoa/fabrics/Kconfig2
-rw-r--r--sound/core/control.c2
-rw-r--r--sound/core/info.c2
-rw-r--r--sound/core/init.c18
-rw-r--r--sound/core/oss/mixer_oss.c2
-rw-r--r--sound/core/oss/pcm_oss.c52
-rw-r--r--sound/core/pcm.c4
-rw-r--r--sound/core/pcm_lib.c8
-rw-r--r--sound/core/pcm_native.c2
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/seq/seq_memory.c2
-rw-r--r--sound/core/sgbuf.c2
-rw-r--r--sound/core/sound.c4
-rw-r--r--sound/core/sound_oss.c4
-rw-r--r--sound/drivers/Kconfig6
-rw-r--r--sound/isa/gus/gus_mem.c7
-rw-r--r--sound/isa/sb/sb_common.c2
-rw-r--r--sound/isa/wavefront/wavefront_synth.c2
-rw-r--r--sound/oss/ad1848.c2
-rw-r--r--sound/oss/cs4232.c2
-rw-r--r--sound/oss/dmasound/dmasound_core.c4
-rw-r--r--sound/oss/dmasound/tas3001c.c14
-rw-r--r--sound/oss/dmasound/tas3004.c15
-rw-r--r--sound/oss/emu10k1/audio.c6
-rw-r--r--sound/oss/emu10k1/cardmi.c2
-rw-r--r--sound/oss/emu10k1/cardmo.c2
-rw-r--r--sound/oss/emu10k1/midi.c10
-rw-r--r--sound/oss/emu10k1/mixer.c2
-rw-r--r--sound/oss/hal2.c2
-rw-r--r--sound/oss/mpu401.c2
-rw-r--r--sound/oss/msnd_pinnacle.c4
-rw-r--r--sound/oss/opl3.c2
-rw-r--r--sound/oss/sb_common.c2
-rw-r--r--sound/oss/sb_midi.c4
-rw-r--r--sound/oss/sb_mixer.c2
-rw-r--r--sound/oss/soundcard.c8
-rw-r--r--sound/oss/v_midi.c2
-rw-r--r--sound/oss/waveartist.c2
-rw-r--r--sound/pci/ac97/Makefile2
-rw-r--r--sound/pci/ac97/ac97_codec.c10
-rw-r--r--sound/pci/ac97/ac97_patch.c7
-rw-r--r--sound/pci/ad1889.c4
-rw-r--r--sound/pci/ali5451/ali5451.c5
-rw-r--r--sound/pci/als300.c6
-rw-r--r--sound/pci/atiixp.c2
-rw-r--r--sound/pci/atiixp_modem.c2
-rw-r--r--sound/pci/au88x0/au88x0.c2
-rw-r--r--sound/pci/azt3328.c5
-rw-r--r--sound/pci/bt87x.c4
-rw-r--r--sound/pci/ca0106/ca0106.h2
-rw-r--r--sound/pci/ca0106/ca0106_main.c37
-rw-r--r--sound/pci/cmipci.c5
-rw-r--r--sound/pci/cs4281.c2
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c6
-rw-r--r--sound/pci/echoaudio/midi.c6
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c5
-rw-r--r--sound/pci/emu10k1/emu10k1x.c9
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c4
-rw-r--r--sound/pci/es1968.c8
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/hda_codec.c3
-rw-r--r--sound/pci/hda/hda_generic.c5
-rw-r--r--sound/pci/hda/hda_intel.c17
-rw-r--r--sound/pci/hda/hda_proc.c53
-rw-r--r--sound/pci/hda/patch_analog.c8
-rw-r--r--sound/pci/hda/patch_realtek.c6
-rw-r--r--sound/pci/hda/patch_si3054.c3
-rw-r--r--sound/pci/ice1712/ice1712.c2
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/intel8x0.c4
-rw-r--r--sound/pci/intel8x0m.c4
-rw-r--r--sound/pci/korg1212/korg1212.c2
-rw-r--r--sound/pci/maestro3.c4
-rw-r--r--sound/pci/mixart/mixart.c5
-rw-r--r--sound/pci/nm256/nm256.c2
-rw-r--r--sound/pci/pcxhr/pcxhr.c2
-rw-r--r--sound/pci/riptide/riptide.c5
-rw-r--r--sound/pci/rme32.c3
-rw-r--r--sound/pci/rme96.c3
-rw-r--r--sound/pci/rme9652/hdsp.c9
-rw-r--r--sound/pci/rme9652/hdspm.c3
-rw-r--r--sound/pci/rme9652/rme9652.c7
-rw-r--r--sound/pci/sonicvibes.c5
-rw-r--r--sound/pci/trident/trident_main.c6
-rw-r--r--sound/pci/via82xx.c6
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/vx222/vx222.c4
-rw-r--r--sound/pci/ymfpci/ymfpci.c5
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c39
-rw-r--r--sound/sound_firmware.c2
-rw-r--r--sound/sparc/cs4231.c26
-rw-r--r--sound/usb/usbaudio.c13
-rw-r--r--sound/usb/usbmixer.c2
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c2
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
3141 files changed, 101611 insertions, 52396 deletions
diff --git a/.gitignore b/.gitignore
index 9eb4b771149..060a71d41ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,6 @@ patches-*
# quilt's files
patches
series
+
+# cscope files
+cscope.*
diff --git a/CREDITS b/CREDITS
index d0880082c19..ae08e4c10ed 100644
--- a/CREDITS
+++ b/CREDITS
@@ -516,9 +516,10 @@ S: Orlando, Florida
S: USA
N: Lennert Buytenhek
-E: buytenh@gnu.org
-D: Rewrite of the ethernet bridging code
-S: Ravenhorst 58B
+E: kernel@wantstofly.org
+D: Original (2.4) rewrite of the ethernet bridging code
+D: Various ARM bits and pieces
+S: Ravenhorst 58
S: 2317 AK Leiden
S: The Netherlands
@@ -1808,6 +1809,14 @@ S: Kruislaan 419
S: 1098 VA Amsterdam
S: The Netherlands
+N: Jiri Kosina
+E: jikos@jikos.cz
+E: jkosina@suse.cz
+D: Generic HID layer - original code split, fixes
+D: Various ACPI fixes, keeping correct battery state through suspend
+D: various lockdep annotations, autofs and other random bugfixes
+S: Prague, Czech Republic
+
N: Gene Kozin
E: 74604.152@compuserve.com
W: http://www.sangoma.com
@@ -3270,7 +3279,7 @@ S: Sevilla 41005
S: Spain
N: Linus Torvalds
-E: torvalds@osdl.org
+E: torvalds@linux-foundation.org
D: Original kernel hacker
S: 12725 SW Millikan Way, Suite 400
S: Beaverton, Oregon 97005
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd
new file mode 100644
index 00000000000..03dbd883cc4
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-pktcdvd
@@ -0,0 +1,20 @@
+What: /debug/pktcdvd/pktcdvd[0-7]
+Date: Oct. 2006
+KernelVersion: 2.6.19
+Contact: Thomas Maier <balagi@justmail.de>
+Description:
+
+debugfs interface
+-----------------
+
+The pktcdvd module (packet writing driver) creates
+these files in debugfs:
+
+/debug/pktcdvd/pktcdvd[0-7]/
+ info (0444) Lots of human readable driver
+ statistics and infos. Multiple lines!
+
+Example:
+-------
+
+cat /debug/pktcdvd/pktcdvd0/info
diff --git a/Documentation/ABI/testing/sysfs-class-pktcdvd b/Documentation/ABI/testing/sysfs-class-pktcdvd
new file mode 100644
index 00000000000..c4c55edc9a5
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-pktcdvd
@@ -0,0 +1,72 @@
+What: /sys/class/pktcdvd/
+Date: Oct. 2006
+KernelVersion: 2.6.19
+Contact: Thomas Maier <balagi@justmail.de>
+Description:
+
+sysfs interface
+---------------
+
+The pktcdvd module (packet writing driver) creates
+these files in the sysfs:
+(<devid> is in format major:minor )
+
+/sys/class/pktcdvd/
+ add (0200) Write a block device id (major:minor)
+ to create a new pktcdvd device and map
+ it to the block device.
+
+ remove (0200) Write the pktcdvd device id (major:minor)
+ to it to remove the pktcdvd device.
+
+ device_map (0444) Shows the device mapping in format:
+ pktcdvd[0-7] <pktdevid> <blkdevid>
+
+/sys/class/pktcdvd/pktcdvd[0-7]/
+ dev (0444) Device id
+ uevent (0200) To send an uevent.
+
+/sys/class/pktcdvd/pktcdvd[0-7]/stat/
+ packets_started (0444) Number of started packets.
+ packets_finished (0444) Number of finished packets.
+
+ kb_written (0444) kBytes written.
+ kb_read (0444) kBytes read.
+ kb_read_gather (0444) kBytes read to fill write packets.
+
+ reset (0200) Write any value to it to reset
+ pktcdvd device statistic values, like
+ bytes read/written.
+
+/sys/class/pktcdvd/pktcdvd[0-7]/write_queue/
+ size (0444) Contains the size of the bio write
+ queue.
+
+ congestion_off (0644) If bio write queue size is below
+ this mark, accept new bio requests
+ from the block layer.
+
+ congestion_on (0644) If bio write queue size is higher
+ as this mark, do no longer accept
+ bio write requests from the block
+ layer and wait till the pktcdvd
+ device has processed enough bio's
+ so that bio write queue size is
+ below congestion off mark.
+ A value of <= 0 disables congestion
+ control.
+
+
+Example:
+--------
+To use the pktcdvd sysfs interface directly, you can do:
+
+# create a new pktcdvd device mapped to /dev/hdc
+echo "22:0" >/sys/class/pktcdvd/add
+cat /sys/class/pktcdvd/device_map
+# assuming device pktcdvd0 was created, look at stat's
+cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written
+# print the device id of the mapped block device
+fgrep pktcdvd0 /sys/class/pktcdvd/device_map
+# remove device, using pktcdvd0 device id 253:0
+echo "253:0" >/sys/class/pktcdvd/remove
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 29c18966b05..9069189e78e 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -35,12 +35,37 @@ In short, 8-char indents make things easier to read, and have the added
benefit of warning you when you're nesting your functions too deep.
Heed that warning.
+The preferred way to ease multiple indentation levels in a switch statement is
+to align the "switch" and its subordinate "case" labels in the same column
+instead of "double-indenting" the "case" labels. E.g.:
+
+ switch (suffix) {
+ case 'G':
+ case 'g':
+ mem <<= 30;
+ break;
+ case 'M':
+ case 'm':
+ mem <<= 20;
+ break;
+ case 'K':
+ case 'k':
+ mem <<= 10;
+ /* fall through */
+ default:
+ break;
+ }
+
+
Don't put multiple statements on a single line unless you have
something to hide:
if (condition) do_this;
do_something_everytime;
+Don't put multiple assignments on a single line either. Kernel coding style
+is super simple. Avoid tricky expressions.
+
Outside of comments, documentation and except in Kconfig, spaces are never
used for indentation, and the above example is deliberately broken.
@@ -69,7 +94,7 @@ void fun(int a, int b, int c)
next_statement;
}
- Chapter 3: Placing Braces
+ Chapter 3: Placing Braces and Spaces
The other issue that always comes up in C styling is the placement of
braces. Unlike the indent size, there are few technical reasons to
@@ -81,6 +106,20 @@ brace last on the line, and put the closing brace first, thusly:
we do y
}
+This applies to all non-function statement blocks (if, switch, for,
+while, do). E.g.:
+
+ switch (action) {
+ case KOBJ_ADD:
+ return "add";
+ case KOBJ_REMOVE:
+ return "remove";
+ case KOBJ_CHANGE:
+ return "change";
+ default:
+ return NULL;
+ }
+
However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:
@@ -121,6 +160,49 @@ supply of new-lines on your screen is not a renewable resource (think
25-line terminal screens here), you have more empty lines to put
comments on.
+ 3.1: Spaces
+
+Linux kernel style for use of spaces depends (mostly) on
+function-versus-keyword usage. Use a space after (most) keywords. The
+notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
+somewhat like functions (and are usually used with parentheses in Linux,
+although they are not required in the language, as in: "sizeof info" after
+"struct fileinfo info;" is declared).
+
+So use a space after these keywords:
+ if, switch, case, for, do, while
+but not with sizeof, typeof, alignof, or __attribute__. E.g.,
+ s = sizeof(struct file);
+
+Do not add spaces around (inside) parenthesized expressions. This example is
+*bad*:
+
+ s = sizeof( struct file );
+
+When declaring pointer data or a function that returns a pointer type, the
+preferred use of '*' is adjacent to the data name or function name and not
+adjacent to the type name. Examples:
+
+ char *linux_banner;
+ unsigned long long memparse(char *ptr, char **retptr);
+ char *match_strdup(substring_t *s);
+
+Use one space around (on each side of) most binary and ternary operators,
+such as any of these:
+
+ = + - < > * / % | & ^ <= >= == != ? :
+
+but no space after unary operators:
+ & * + - ~ ! sizeof typeof alignof __attribute__ defined
+
+no space before the postfix increment & decrement unary operators:
+ ++ --
+
+no space after the prefix increment & decrement unary operators:
+ ++ --
+
+and no space around the '.' and "->" structure member operators.
+
Chapter 4: Naming
@@ -152,7 +234,7 @@ variable that is used to hold a temporary value.
If you are afraid to mix up your local variable names, you have another
problem, which is called the function-growth-hormone-imbalance syndrome.
-See next chapter.
+See chapter 6 (Functions).
Chapter 5: Typedefs
@@ -258,6 +340,20 @@ generally easily keep track of about 7 different things, anything more
and it gets confused. You know you're brilliant, but maybe you'd like
to understand what you did 2 weeks from now.
+In source files, separate functions with one blank line. If the function is
+exported, the EXPORT* macro for it should follow immediately after the closing
+function brace line. E.g.:
+
+int system_is_up(void)
+{
+ return system_state == SYSTEM_RUNNING;
+}
+EXPORT_SYMBOL(system_is_up);
+
+In function prototypes, include parameter names with their data types.
+Although this is not required by the C language, it is preferred in Linux
+because it is a simple way to add valuable information for the reader.
+
Chapter 7: Centralized exiting of functions
@@ -306,16 +402,36 @@ time to explain badly written code.
Generally, you want your comments to tell WHAT your code does, not HOW.
Also, try to avoid putting comments inside a function body: if the
function is so complex that you need to separately comment parts of it,
-you should probably go back to chapter 5 for a while. You can make
+you should probably go back to chapter 6 for a while. You can make
small comments to note or warn about something particularly clever (or
ugly), but try to avoid excess. Instead, put the comments at the head
of the function, telling people what it does, and possibly WHY it does
it.
-When commenting the kernel API functions, please use the kerneldoc format.
+When commenting the kernel API functions, please use the kernel-doc format.
See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc
for details.
+Linux style for comments is the C89 "/* ... */" style.
+Don't use C99-style "// ..." comments.
+
+The preferred style for long (multi-line) comments is:
+
+ /*
+ * This is the preferred style for multi-line
+ * comments in the Linux kernel source code.
+ * Please use it consistently.
+ *
+ * Description: A column of asterisks on the left side,
+ * with beginning and ending almost-blank lines.
+ */
+
+It's also important to comment data, whether they are basic types or derived
+types. To this end, use just one data declaration per line (no commas for
+multiple data declarations). This leaves you room for a small comment on each
+item, explaining its use.
+
+
Chapter 9: You've made a mess of it
That's OK, we all do. You've probably been told by your long-time Unix
@@ -566,6 +682,24 @@ result. Typical examples would be functions that return pointers; they use
NULL or the ERR_PTR mechanism to report failure.
+ Chapter 17: Don't re-invent the kernel macros
+
+The header file include/linux/kernel.h contains a number of macros that
+you should use, rather than explicitly coding some variant of them yourself.
+For example, if you need to calculate the length of an array, take advantage
+of the macro
+
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+Similarly, if you need to calculate the size of some structure member, use
+
+ #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+There are also min() and max() macros that do strict type checking if you
+need them. Feel free to peruse that header file to see what else is already
+defined that you shouldn't reproduce in your code.
+
+
Appendix I: References
@@ -591,4 +725,4 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
--
-Last updated on 30 April 2006.
+Last updated on 2006-December-06.
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 36526a1e76d..867608ab3ca 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -53,8 +53,8 @@ installmandocs: mandocs
###
#External programs used
-KERNELDOC = scripts/kernel-doc
-DOCPROC = scripts/basic/docproc
+KERNELDOC = $(srctree)/scripts/kernel-doc
+DOCPROC = $(objtree)/scripts/basic/docproc
XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl
#XMLTOFLAGS += --skip-validation
diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl
index 0f4a4b6321e..4215f69ce7e 100644
--- a/Documentation/DocBook/genericirq.tmpl
+++ b/Documentation/DocBook/genericirq.tmpl
@@ -303,10 +303,10 @@ desc->status |= running;
do {
if (desc->status &amp; masked)
desc->chip->enable();
- desc-status &amp;= ~pending;
+ desc->status &amp;= ~pending;
handle_IRQ_event(desc->action);
} while (status &amp; pending);
-desc-status &amp;= ~running;
+desc->status &amp;= ~running;
desc->chip->end();
</programlisting>
</para>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index ca094913c55..3fa0c4b4541 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -559,4 +559,12 @@ X!Idrivers/video/console/fonts.c
-->
</sect1>
</chapter>
+
+ <chapter id="input_subsystem">
+ <title>Input Subsystem</title>
+!Iinclude/linux/input.h
+!Edrivers/input/input.c
+!Edrivers/input/ff-core.c
+!Edrivers/input/ff-memless.c
+ </chapter>
</book>
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 07a635590b3..e2e24b4778d 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -883,7 +883,7 @@ and other resources, etc.
</chapter>
<chapter id="ataExceptions">
- <title>ATA errors &amp; exceptions</title>
+ <title>ATA errors and exceptions</title>
<para>
This chapter tries to identify what error/exception conditions exist
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 7ac61f60037..bfbb2718a27 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -66,3 +66,13 @@ kernel patches.
See Documentation/ABI/README for more information.
20: Check that it all passes `make headers_check'.
+
+21: Has been checked with injection of at least slab and page-allocation
+ fauilures. See Documentation/fault-injection/.
+
+ If the new code is substantial, addition of subsystem-specific fault
+ injection might be appropriate.
+
+22: Newly-added code has been compiled with `gcc -W'. This will generate
+ lots of noise, but is good for finding bugs like "warning: comparison
+ between signed and unsigned".
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 302d148c2e1..b0d0043f7c4 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -134,9 +134,9 @@ Do not send more than 15 patches at once to the vger mailing lists!!!
Linus Torvalds is the final arbiter of all changes accepted into the
-Linux kernel. His e-mail address is <torvalds@osdl.org>. He gets
-a lot of e-mail, so typically you should do your best to -avoid- sending
-him e-mail.
+Linux kernel. His e-mail address is <torvalds@linux-foundation.org>.
+He gets a lot of e-mail, so typically you should do your best to -avoid-
+sending him e-mail.
Patches which are bug fixes, are "obvious" changes, or similarly
require little discussion should be sent or CC'd to Linus. Patches
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index bf2b0e2f87e..e9126e794ed 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -7,6 +7,8 @@
* Copyright (C) Balbir Singh, IBM Corp. 2006
* Copyright (c) Jay Lan, SGI. 2006
*
+ * Compile with
+ * gcc -I/usr/src/linux/include getdelays.c -o getdelays
*/
#include <stdio.h>
@@ -35,13 +37,20 @@
#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
#define NLA_PAYLOAD(len) (len - NLA_HDRLEN)
-#define err(code, fmt, arg...) do { printf(fmt, ##arg); exit(code); } while (0)
-int done = 0;
-int rcvbufsz=0;
-
- char name[100];
-int dbg=0, print_delays=0;
+#define err(code, fmt, arg...) \
+ do { \
+ fprintf(stderr, fmt, ##arg); \
+ exit(code); \
+ } while (0)
+
+int done;
+int rcvbufsz;
+char name[100];
+int dbg;
+int print_delays;
+int print_io_accounting;
__u64 stime, utime;
+
#define PRINTF(fmt, arg...) { \
if (dbg) { \
printf(fmt, ##arg); \
@@ -78,8 +87,9 @@ static int create_nl_socket(int protocol)
if (rcvbufsz)
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
&rcvbufsz, sizeof(rcvbufsz)) < 0) {
- printf("Unable to set socket rcv buf size to %d\n",
- rcvbufsz);
+ fprintf(stderr, "Unable to set socket rcv buf size "
+ "to %d\n",
+ rcvbufsz);
return -1;
}
@@ -186,6 +196,15 @@ void print_delayacct(struct taskstats *t)
"count", "delay total", t->swapin_count, t->swapin_delay_total);
}
+void print_ioacct(struct taskstats *t)
+{
+ printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
+ t->ac_comm,
+ (unsigned long long)t->read_bytes,
+ (unsigned long long)t->write_bytes,
+ (unsigned long long)t->cancelled_write_bytes);
+}
+
int main(int argc, char *argv[])
{
int c, rc, rep_len, aggr_len, len2, cmd_type;
@@ -208,7 +227,7 @@ int main(int argc, char *argv[])
struct msgtemplate msg;
while (1) {
- c = getopt(argc, argv, "dw:r:m:t:p:v:l");
+ c = getopt(argc, argv, "diw:r:m:t:p:v:l");
if (c < 0)
break;
@@ -217,6 +236,10 @@ int main(int argc, char *argv[])
printf("print delayacct stats ON\n");
print_delays = 1;
break;
+ case 'i':
+ printf("printing IO accounting\n");
+ print_io_accounting = 1;
+ break;
case 'w':
strncpy(logfile, optarg, MAX_FILENAME);
printf("write to file %s\n", logfile);
@@ -238,14 +261,12 @@ int main(int argc, char *argv[])
if (!tid)
err(1, "Invalid tgid\n");
cmd_type = TASKSTATS_CMD_ATTR_TGID;
- print_delays = 1;
break;
case 'p':
tid = atoi(optarg);
if (!tid)
err(1, "Invalid pid\n");
cmd_type = TASKSTATS_CMD_ATTR_PID;
- print_delays = 1;
break;
case 'v':
printf("debug on\n");
@@ -277,7 +298,7 @@ int main(int argc, char *argv[])
mypid = getpid();
id = get_family_id(nl_sd);
if (!id) {
- printf("Error getting family id, errno %d", errno);
+ fprintf(stderr, "Error getting family id, errno %d\n", errno);
goto err;
}
PRINTF("family id %d\n", id);
@@ -288,7 +309,7 @@ int main(int argc, char *argv[])
&cpumask, strlen(cpumask) + 1);
PRINTF("Sent register cpumask, retval %d\n", rc);
if (rc < 0) {
- printf("error sending register cpumask\n");
+ fprintf(stderr, "error sending register cpumask\n");
goto err;
}
}
@@ -298,7 +319,7 @@ int main(int argc, char *argv[])
cmd_type, &tid, sizeof(__u32));
PRINTF("Sent pid/tgid, retval %d\n", rc);
if (rc < 0) {
- printf("error sending tid/tgid cmd\n");
+ fprintf(stderr, "error sending tid/tgid cmd\n");
goto done;
}
}
@@ -310,13 +331,15 @@ int main(int argc, char *argv[])
PRINTF("received %d bytes\n", rep_len);
if (rep_len < 0) {
- printf("nonfatal reply error: errno %d\n", errno);
+ fprintf(stderr, "nonfatal reply error: errno %d\n",
+ errno);
continue;
}
if (msg.n.nlmsg_type == NLMSG_ERROR ||
!NLMSG_OK((&msg.n), rep_len)) {
struct nlmsgerr *err = NLMSG_DATA(&msg);
- printf("fatal reply error, errno %d\n", err->error);
+ fprintf(stderr, "fatal reply error, errno %d\n",
+ err->error);
goto done;
}
@@ -356,6 +379,8 @@ int main(int argc, char *argv[])
count++;
if (print_delays)
print_delayacct((struct taskstats *) NLA_DATA(na));
+ if (print_io_accounting)
+ print_ioacct((struct taskstats *) NLA_DATA(na));
if (fd) {
if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
err(1,"write error\n");
@@ -365,7 +390,9 @@ int main(int argc, char *argv[])
goto done;
break;
default:
- printf("Unknown nested nla_type %d\n", na->nla_type);
+ fprintf(stderr, "Unknown nested"
+ " nla_type %d\n",
+ na->nla_type);
break;
}
len2 += NLA_ALIGN(na->nla_len);
@@ -374,7 +401,8 @@ int main(int argc, char *argv[])
break;
default:
- printf("Unknown nla_type %d\n", na->nla_type);
+ fprintf(stderr, "Unknown nla_type %d\n",
+ na->nla_type);
break;
}
na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index dda7ecdde87..28d014714ab 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -76,6 +76,15 @@ Machines
A S3C2410 based PDA from Acer. There is a Wiki page at
http://handhelds.org/moin/moin.cgi/AcerN30Documentation .
+ AML M5900
+
+ American Microsystems' M5900
+
+ Nex Vision Nexcoder
+ Nex Vision Otom
+
+ Two machines by Nex Vision
+
Adding New Machines
-------------------
@@ -115,6 +124,10 @@ RTC
Support for the onboard RTC unit, including alarm function.
+ This has recently been upgraded to use the new RTC core,
+ and the module has been renamed to rtc-s3c to fit in with
+ the new rtc naming scheme.
+
Watchdog
--------
@@ -128,7 +141,7 @@ NAND
The current kernels now have support for the s3c2410 NAND
controller. If there are any problems the latest linux-mtd
- CVS can be found from http://www.linux-mtd.infradead.org/
+ code can be found from http://www.linux-mtd.infradead.org/
Serial
@@ -168,6 +181,21 @@ Suspend to RAM
See Suspend.txt for more information.
+SPI
+---
+
+ SPI drivers are available for both the in-built hardware
+ (although there is no DMA support yet) and a generic
+ GPIO based solution.
+
+
+LEDs
+----
+
+ There is support for GPIO based LEDs via a platform driver
+ in the LED subsystem.
+
+
Platform Data
-------------
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index c6c9a9c10d7..3adaace328a 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -946,6 +946,13 @@ elevator_merged_fn called when a request in the scheduler has been
scheduler for example, to reposition the request
if its sorting order has changed.
+elevator_allow_merge_fn called whenever the block layer determines
+ that a bio can be merged into an existing
+ request safely. The io scheduler may still
+ want to stop a merge at this point if it
+ results in some sort of conflict internally,
+ this hook allows it to do that.
+
elevator_dispatch_fn fills the dispatch queue with ready requests.
I/O schedulers are free to postpone requests by
not filling the dispatch queue unless @force
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 53245c429f7..debf6813934 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -179,10 +179,21 @@ Here are the routines, one by one:
lines associated with 'mm'.
This interface is used to handle whole address space
- page table operations such as what happens during
- fork, exit, and exec.
+ page table operations such as what happens during exit and exec.
+
+2) void flush_cache_dup_mm(struct mm_struct *mm)
+
+ This interface flushes an entire user address space from
+ the caches. That is, after running, there will be no cache
+ lines associated with 'mm'.
+
+ This interface is used to handle whole address space
+ page table operations such as what happens during fork.
+
+ This option is separate from flush_cache_mm to allow some
+ optimizations for VIPT caches.
-2) void flush_cache_range(struct vm_area_struct *vma,
+3) void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
Here we are flushing a specific range of (user) virtual
@@ -199,7 +210,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, unsigned long pfn)
+4) 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
@@ -220,7 +231,7 @@ Here are the routines, one by one:
This is used primarily during fault processing.
-4) void flush_cache_kmaps(void)
+5) void flush_cache_kmaps(void)
This routine need only be implemented if the platform utilizes
highmem. It will be called right before all of the kmaps
@@ -232,7 +243,7 @@ Here are the routines, one by one:
This routing should be implemented in asm/highmem.h
-5) void flush_cache_vmap(unsigned long start, unsigned long end)
+6) void flush_cache_vmap(unsigned long start, unsigned long end)
void flush_cache_vunmap(unsigned long start, unsigned long end)
Here in these two interfaces we are flushing a specific range
@@ -362,14 +373,15 @@ maps this page at its virtual address.
likely that you will need to flush the instruction cache
for copy_to_user_page().
- void flush_anon_page(struct page *page, unsigned long vmaddr)
+ void flush_anon_page(struct vm_area_struct *vma, struct page *page,
+ unsigned long vmaddr)
When the kernel needs to access the contents of an anonymous
page, it calls this function (currently only
get_user_pages()). Note: flush_dcache_page() deliberately
doesn't work for an anonymous page. The default
implementation is a nop (and should remain so for all coherent
architectures). For incoherent architectures, it should flush
- the cache of the page at vmaddr in the current user process.
+ the cache of the page at vmaddr.
void flush_kernel_dcache_page(struct page *page)
When the kernel needs to modify a user page is has obtained
diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt
index 3d44c561fe6..7715d2247c4 100644
--- a/Documentation/cdrom/packet-writing.txt
+++ b/Documentation/cdrom/packet-writing.txt
@@ -90,6 +90,41 @@ Notes
to create an ext2 filesystem on the disc.
+Using the pktcdvd sysfs interface
+---------------------------------
+
+Since Linux 2.6.19, the pktcdvd module has a sysfs interface
+and can be controlled by it. For example the "pktcdvd" tool uses
+this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
+
+"pktcdvd" works similar to "pktsetup", e.g.:
+
+ # pktcdvd -a dev_name /dev/hdc
+ # mkudffs /dev/pktcdvd/dev_name
+ # mount -t udf -o rw,noatime /dev/pktcdvd/dev_name /dvdram
+ # cp files /dvdram
+ # umount /dvdram
+ # pktcdvd -r dev_name
+
+
+For a description of the sysfs interface look into the file:
+
+ Documentation/ABI/testing/sysfs-block-pktcdvd
+
+
+Using the pktcdvd debugfs interface
+-----------------------------------
+
+To read pktcdvd device infos in human readable form, do:
+
+ # cat /debug/pktcdvd/pktcdvd[0-7]/info
+
+For a description of the debugfs interface look into the file:
+
+ Documentation/ABI/testing/debugfs-pktcdvd
+
+
+
Links
-----
diff --git a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
index 29b3f9ffc66..ce0666e5103 100644
--- a/Documentation/cpu-freq/core.txt
+++ b/Documentation/cpu-freq/core.txt
@@ -24,7 +24,7 @@ Contents:
1. General Information
=======================
-The CPUFreq core code is located in linux/kernel/cpufreq.c. This
+The CPUFreq core code is located in drivers/cpufreq/cpufreq.c. This
cpufreq code offers a standardized interface for the CPUFreq
architecture drivers (those pieces of code that do actual
frequency transitions), as well as to "notifiers". These are device
diff --git a/Documentation/dvb/cards.txt b/Documentation/dvb/cards.txt
index ca58e339d85..cc09187a5db 100644
--- a/Documentation/dvb/cards.txt
+++ b/Documentation/dvb/cards.txt
@@ -22,10 +22,10 @@ o Frontends drivers:
- ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993)
- cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL)
- grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL
- - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL
+ - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLLi, Technisat Sky2Pc with bios Rev. 2.3
- stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL),
LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL),
- Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB
+ Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB, Technisat Sky2Pc with bios Rev. 2.6
DVB-C:
- ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL)
- at76c651 : Atmel AT76c651(B) with DAT7021 PLL
diff --git a/Documentation/fault-injection/failcmd.sh b/Documentation/fault-injection/failcmd.sh
new file mode 100644
index 00000000000..63177aba810
--- /dev/null
+++ b/Documentation/fault-injection/failcmd.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo 1 > /proc/self/make-it-fail
+exec $*
diff --git a/Documentation/fault-injection/failmodule.sh b/Documentation/fault-injection/failmodule.sh
new file mode 100644
index 00000000000..474a8b971f9
--- /dev/null
+++ b/Documentation/fault-injection/failmodule.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+#
+# Usage: failmodule <failname> <modulename> [stacktrace-depth]
+#
+# <failname>: "failslab", "fail_alloc_page", or "fail_make_request"
+#
+# <modulename>: module name that you want to inject faults.
+#
+# [stacktrace-depth]: the maximum number of stacktrace walking allowed
+#
+
+STACKTRACE_DEPTH=5
+if [ $# -gt 2 ]; then
+ STACKTRACE_DEPTH=$3
+fi
+
+if [ ! -d /debug/$1 ]; then
+ echo "Fault-injection $1 does not exist" >&2
+ exit 1
+fi
+if [ ! -d /sys/module/$2 ]; then
+ echo "Module $2 does not exist" >&2
+ exit 1
+fi
+
+# Disable any fault injection
+echo 0 > /debug/$1/stacktrace-depth
+
+echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start
+echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end
+echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth
diff --git a/Documentation/fault-injection/fault-injection.txt b/Documentation/fault-injection/fault-injection.txt
new file mode 100644
index 00000000000..b7ca560b934
--- /dev/null
+++ b/Documentation/fault-injection/fault-injection.txt
@@ -0,0 +1,225 @@
+Fault injection capabilities infrastructure
+===========================================
+
+See also drivers/md/faulty.c and "every_nth" module option for scsi_debug.
+
+
+Available fault injection capabilities
+--------------------------------------
+
+o failslab
+
+ injects slab allocation failures. (kmalloc(), kmem_cache_alloc(), ...)
+
+o fail_page_alloc
+
+ injects page allocation failures. (alloc_pages(), get_free_pages(), ...)
+
+o fail_make_request
+
+ injects disk IO errors on devices permitted by setting
+ /sys/block/<device>/make-it-fail or
+ /sys/block/<device>/<partition>/make-it-fail. (generic_make_request())
+
+Configure fault-injection capabilities behavior
+-----------------------------------------------
+
+o debugfs entries
+
+fault-inject-debugfs kernel module provides some debugfs entries for runtime
+configuration of fault-injection capabilities.
+
+- /debug/fail*/probability:
+
+ likelihood of failure injection, in percent.
+ Format: <percent>
+
+ Note that one-failure-per-hundred is a very high error rate
+ for some testcases. Consider setting probability=100 and configure
+ /debug/fail*/interval for such testcases.
+
+- /debug/fail*/interval:
+
+ specifies the interval between failures, for calls to
+ should_fail() that pass all the other tests.
+
+ Note that if you enable this, by setting interval>1, you will
+ probably want to set probability=100.
+
+- /debug/fail*/times:
+
+ specifies how many times failures may happen at most.
+ A value of -1 means "no limit".
+
+- /debug/fail*/space:
+
+ specifies an initial resource "budget", decremented by "size"
+ on each call to should_fail(,size). Failure injection is
+ suppressed until "space" reaches zero.
+
+- /debug/fail*/verbose
+
+ Format: { 0 | 1 | 2 }
+ specifies the verbosity of the messages when failure is
+ injected. '0' means no messages; '1' will print only a single
+ log line per failure; '2' will print a call trace too -- useful
+ to debug the problems revealed by fault injection.
+
+- /debug/fail*/task-filter:
+
+ Format: { 'Y' | 'N' }
+ A value of 'N' disables filtering by process (default).
+ Any positive value limits failures to only processes indicated by
+ /proc/<pid>/make-it-fail==1.
+
+- /debug/fail*/require-start:
+- /debug/fail*/require-end:
+- /debug/fail*/reject-start:
+- /debug/fail*/reject-end:
+
+ specifies the range of virtual addresses tested during
+ stacktrace walking. Failure is injected only if some caller
+ in the walked stacktrace lies within the required range, and
+ none lies within the rejected range.
+ Default required range is [0,ULONG_MAX) (whole of virtual address space).
+ Default rejected range is [0,0).
+
+- /debug/fail*/stacktrace-depth:
+
+ specifies the maximum stacktrace depth walked during search
+ for a caller within [require-start,require-end) OR
+ [reject-start,reject-end).
+
+- /debug/fail_page_alloc/ignore-gfp-highmem:
+
+ Format: { 'Y' | 'N' }
+ default is 'N', setting it to 'Y' won't inject failures into
+ highmem/user allocations.
+
+- /debug/failslab/ignore-gfp-wait:
+- /debug/fail_page_alloc/ignore-gfp-wait:
+
+ Format: { 'Y' | 'N' }
+ default is 'N', setting it to 'Y' will inject failures
+ only into non-sleep allocations (GFP_ATOMIC allocations).
+
+o Boot option
+
+In order to inject faults while debugfs is not available (early boot time),
+use the boot option:
+
+ failslab=
+ fail_page_alloc=
+ fail_make_request=<interval>,<probability>,<space>,<times>
+
+How to add new fault injection capability
+-----------------------------------------
+
+o #include <linux/fault-inject.h>
+
+o define the fault attributes
+
+ DECLARE_FAULT_INJECTION(name);
+
+ Please see the definition of struct fault_attr in fault-inject.h
+ for details.
+
+o provide a way to configure fault attributes
+
+- boot option
+
+ If you need to enable the fault injection capability from boot time, you can
+ provide boot option to configure it. There is a helper function for it:
+
+ setup_fault_attr(attr, str);
+
+- debugfs entries
+
+ failslab, fail_page_alloc, and fail_make_request use this way.
+ Helper functions:
+
+ init_fault_attr_entries(entries, attr, name);
+ void cleanup_fault_attr_entries(entries);
+
+- module parameters
+
+ If the scope of the fault injection capability is limited to a
+ single kernel module, it is better to provide module parameters to
+ configure the fault attributes.
+
+o add a hook to insert failures
+
+ Upon should_fail() returning true, client code should inject a failure.
+
+ should_fail(attr, size);
+
+Application Examples
+--------------------
+
+o inject slab allocation failures into module init/cleanup code
+
+------------------------------------------------------------------------------
+#!/bin/bash
+
+FAILCMD=Documentation/fault-injection/failcmd.sh
+BLACKLIST="root_plug evbug"
+
+FAILNAME=failslab
+echo Y > /debug/$FAILNAME/task-filter
+echo 10 > /debug/$FAILNAME/probability
+echo 100 > /debug/$FAILNAME/interval
+echo -1 > /debug/$FAILNAME/times
+echo 2 > /debug/$FAILNAME/verbose
+echo 1 > /debug/$FAILNAME/ignore-gfp-wait
+
+blacklist()
+{
+ echo $BLACKLIST | grep $1 > /dev/null 2>&1
+}
+
+oops()
+{
+ dmesg | grep BUG > /dev/null 2>&1
+}
+
+find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; |
+ while read i
+ do
+ oops && exit 1
+
+ if ! blacklist $i
+ then
+ echo inserting $i...
+ bash $FAILCMD modprobe $i
+ fi
+ done
+
+lsmod | awk '{ if ($3 == 0) { print $1 } }' |
+ while read i
+ do
+ oops && exit 1
+
+ if ! blacklist $i
+ then
+ echo removing $i...
+ bash $FAILCMD modprobe -r $i
+ fi
+ done
+
+------------------------------------------------------------------------------
+
+o inject slab allocation failures only for a specific module
+
+------------------------------------------------------------------------------
+#!/bin/bash
+
+FAILMOD=Documentation/fault-injection/failmodule.sh
+
+echo injecting errors into the module $1...
+
+modprobe $1
+bash $FAILMOD failslab $1 10
+echo 25 > /debug/failslab/probability
+
+------------------------------------------------------------------------------
+
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 46f2a559b27..0ba6af02cda 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -151,15 +151,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
---------------------------
-What: I2C interface of the it87 driver
-When: January 2007
-Why: The ISA interface is faster and should be always available. The I2C
- probing is also known to cause trouble in at least one case (see
- bug #5889.)
-Who: Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
(temporary transition config option provided until then)
The transition config option will also be removed at the same time.
@@ -216,33 +207,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
---------------------------
-What: i2c-ite and i2c-algo-ite drivers
-When: September 2006
-Why: These drivers never compiled since they were added to the kernel
- tree 5 years ago. This feature removal can be reevaluated if
- someone shows interest in the drivers, fixes them and takes over
- maintenance.
- http://marc.theaimsgroup.com/?l=linux-mips&m=115040510817448
-Who: Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
-What: Bridge netfilter deferred IPv4/IPv6 output hook calling
-When: January 2007
-Why: The deferred output hooks are a layering violation causing unusual
- and broken behaviour on bridge devices. Examples of things they
- break include QoS classifation using the MARK or CLASSIFY targets,
- the IPsec policy match and connection tracking with VLANs on a
- bridge. Their only use is to enable bridge output port filtering
- within iptables with the physdev match, which can also be done by
- combining iptables and ebtables using netfilter marks. Until it
- will get removed the hook deferral is disabled by default and is
- only enabled when needed.
-
-Who: Patrick McHardy <kaber@trash.net>
-
----------------------------
-
What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
When: October 2008
Why: The stacking of class devices makes these values misleading and
@@ -262,6 +226,23 @@ Who: Jean Delvare <khali@linux-fr.org>
---------------------------
+What: i2c_adapter.dev
+ i2c_adapter.list
+When: July 2007
+Why: Superfluous, given i2c_adapter.class_dev:
+ * The "dev" was a stand-in for the physical device node that legacy
+ drivers would not have; but now it's almost always present. Any
+ remaining legacy drivers must upgrade (they now trigger warnings).
+ * The "list" duplicates class device children.
+ The delay in removing this is so upgraded lm_sensors and libsensors
+ can get deployed. (Removal causes minor changes in the sysfs layout,
+ notably the location of the adapter type name and parenting the i2c
+ client hardware directly from their controller.)
+Who: Jean Delvare <khali@linux-fr.org>,
+ David Brownell <dbrownell@users.sourceforge.net>
+
+---------------------------
+
What: IPv4 only connection tracking/NAT/helpers
When: 2.6.22
Why: The new layer 3 independant connection tracking replaces the old
@@ -270,3 +251,77 @@ Why: The new layer 3 independant connection tracking replaces the old
Who: Patrick McHardy <kaber@trash.net>
---------------------------
+
+What: ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
+When: December 2006
+Why: Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
+ functionally very much similar. They talk to ACPI in same way. Only
+ difference between them is the way they do frequency transitions.
+ One uses MSRs and the other one uses IO ports. Functionaliy of
+ speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq.
+ That means one common driver will support all Intel Enhanced Speedstep
+ capable CPUs. That means less confusion over name of
+ speedstep-centrino driver (with that driver supposed to be used on
+ non-centrino platforms). That means less duplication of code and
+ less maintenance effort and no possibility of these two drivers
+ going out of sync.
+ Current users of speedstep_centrino with ACPI hooks are requested to
+ switch over to acpi-cpufreq driver. speedstep-centrino will continue
+ to work using older non-ACPI static table based scheme even after this
+ date.
+
+Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+---------------------------
+
+What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
+When: 2.6.21
+Why: hotkey.c was an attempt to consolidate multiple drivers that use
+ ACPI to implement hotkeys. However, hotkeys are not documented
+ in the ACPI specification, so the drivers used undocumented
+ vendor-specific hooks and turned out to be more different than
+ the same.
+
+ Further, the keys and the features supplied by each platform
+ are different, so there will always be a need for
+ platform-specific drivers.
+
+ So the new plan is to delete hotkey.c and instead, work on the
+ platform specific drivers to try to make them look the same
+ to the user when they supply the same features.
+
+ hotkey.c has always depended on CONFIG_EXPERIMENTAL
+
+Who: Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What: /sys/firmware/acpi/namespace
+When: 2.6.21
+Why: The ACPI namespace is effectively the symbol list for
+ the BIOS. The device names are completely arbitrary
+ and have no place being exposed to user-space.
+
+ For those interested in the BIOS ACPI namespace,
+ the BIOS can be extracted and disassembled with acpidump
+ and iasl as documented in the pmtools package here:
+ http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils
+
+Who: Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What: /proc/acpi/button
+When: August 2007
+Why: /proc/acpi/button has been replaced by events to the input layer
+ since 2.6.20.
+Who: Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What: JFFS (version 1)
+When: 2.6.21
+Why: Unmaintained for years, superceded by JFFS2 for years.
+Who: Jeff Garzik <jeff@garzik.org>
+
+---------------------------
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index 43b89c214d2..4d075a4558f 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -73,8 +73,22 @@ OPTIONS
RESOURCES
=========
-The Linux version of the 9p server is now maintained under the npfs project
-on sourceforge (http://sourceforge.net/projects/npfs).
+Our current recommendation is to use Inferno (http://www.vitanuova.com/inferno)
+as the 9p server. You can start a 9p server under Inferno by issuing the
+following command:
+ ; styxlisten -A tcp!*!564 export '#U*'
+
+The -A specifies an unauthenticated export. The 564 is the port # (you may
+have to choose a higher port number if running as a normal user). The '#U*'
+specifies exporting the root of the Linux name space. You may specify a
+subset of the namespace by extending the path: '#U*'/tmp would just export
+/tmp. For more information, see the Inferno manual pages covering styxlisten
+and export.
+
+A Linux version of the 9p server is now maintained under the npfs project
+on sourceforge (http://sourceforge.net/projects/npfs). There is also a
+more stable single-threaded version of the server (named spfs) available from
+the same CVS repository.
There are user and developer mailing lists available through the v9fs project
on sourceforge (http://sourceforge.net/projects/v9fs).
@@ -96,5 +110,5 @@ STATUS
The 2.6 kernel support is working on PPC and x86.
-PLEASE USE THE SOURCEFORGE BUG-TRACKER TO REPORT PROBLEMS.
+PLEASE USE THE KERNEL BUGZILLA TO REPORT PROBLEMS. (http://bugzilla.kernel.org)
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 790ef6fbe49..28bfea75bcf 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -171,6 +171,7 @@ prototypes:
int (*releasepage) (struct page *, int);
int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs);
+ int (*launder_page) (struct page *);
locking rules:
All except set_page_dirty may block
@@ -188,6 +189,7 @@ bmap: yes
invalidatepage: no yes
releasepage: no yes
direct_IO: no
+launder_page: no yes
->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
may be called from the request handler (/dev/loop).
@@ -281,6 +283,12 @@ buffers from the page in preparation for freeing it. It returns zero to
indicate that the buffers are (or may be) freeable. If ->releasepage is zero,
the kernel assumes that the fs has no private interest in the buffers.
+ ->launder_page() may be called prior to releasing a page if
+it is still found to be dirty. It returns zero if the page was successfully
+cleaned, or an error value if not. Note that in order to prevent the page
+getting mapped back in and redirtied, it needs to be kept locked
+across the entire operation.
+
Note: currently almost all instances of address_space methods are
using BKL for internal serialization and that's one of the worst sources
of contention. Normally they are calling library functions (in fs/buffer.c)
diff --git a/Documentation/filesystems/bfs.txt b/Documentation/filesystems/bfs.txt
index d2841e0bcf0..ea825e178e7 100644
--- a/Documentation/filesystems/bfs.txt
+++ b/Documentation/filesystems/bfs.txt
@@ -54,4 +54,4 @@ The first 4 bytes should be 0x1badface.
If you have any patches, questions or suggestions regarding this BFS
implementation please contact the author:
-Tigran A. Aivazian <tigran@veritas.com>
+Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
index 345392c4cae..397a41adb4c 100644
--- a/Documentation/filesystems/fuse.txt
+++ b/Documentation/filesystems/fuse.txt
@@ -94,8 +94,8 @@ Mount options
filesystem is free to implement it's access policy or leave it to
the underlying file access mechanism (e.g. in case of network
filesystems). This option enables permission checking, restricting
- access based on file mode. This is option is usually useful
- together with the 'allow_other' mount option.
+ access based on file mode. It is usually useful together with the
+ 'allow_other' mount option.
'allow_other'
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index 13ba649bda7..81779068b09 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -457,6 +457,8 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
+2.1.28:
+ - Fix a deadlock.
2.1.27:
- Implement page migration support so the kernel can move memory used
by NTFS files and directories around for management purposes.
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index af6defd10cb..8ccf0c1b58e 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -54,3 +54,6 @@ errors=panic Panic and halt the machine if an error occurs.
intr (*) Allow signals to interrupt cluster operations.
nointr Do not allow signals to interrupt cluster
operations.
+atime_quantum=60(*) OCFS2 will not update atime unless this number
+ of seconds has passed since the last update.
+ Set to zero to always update atime.
diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f
index 2ca69df669c..bfd0f154959 100644
--- a/Documentation/hwmon/f71805f
+++ b/Documentation/hwmon/f71805f
@@ -6,6 +6,10 @@ Supported chips:
Prefix: 'f71805f'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Provided by Fintek on request
+ * Fintek F71872F/FG
+ Prefix: 'f71872f'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: Provided by Fintek on request
Author: Jean Delvare <khali@linux-fr.org>
@@ -13,8 +17,8 @@ Thanks to Denis Kieft from Barracuda Networks for the donation of a
test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
for providing initial documentation.
-Thanks to Kris Chen from Fintek for answering technical questions and
-providing additional documentation.
+Thanks to Kris Chen and Aaron Huang from Fintek for answering technical
+questions and providing additional documentation.
Thanks to Chris Lin from Jetway for providing wiring schematics and
answering technical questions.
@@ -28,8 +32,11 @@ capabilities. It can monitor up to 9 voltages (counting its own power
source), 3 fans and 3 temperature sensors.
This chip also has fan controlling features, using either DC or PWM, in
-three different modes (one manual, two automatic). The driver doesn't
-support these features yet.
+three different modes (one manual, two automatic).
+
+The Fintek F71872F/FG Super I/O chip is almost the same, with two
+additional internal voltages monitored (VSB and battery). It also features
+6 VID inputs. The VID inputs are not yet supported by this driver.
The driver assumes that no more than one chip is present, which seems
reasonable.
@@ -42,7 +49,8 @@ Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported
range is thus from 0 to 2.040 V. Voltage values outside of this range
need external resistors. An exception is in0, which is used to monitor
the chip's own power source (+3.3V), and is divided internally by a
-factor 2.
+factor 2. For the F71872F/FG, in9 (VSB) and in10 (battery) are also
+divided internally by a factor 2.
The two LSB of the voltage limit registers are not used (always 0), so
you can only set the limits in steps of 32 mV (before scaling).
@@ -61,9 +69,12 @@ in5 VIN5 +12V 200K 20K 11.00 1.05 V
in6 VIN6 VCC1.5V 10K - 1.00 1.50 V
in7 VIN7 VCORE 10K - 1.00 ~1.40 V (1)
in8 VIN8 VSB5V 200K 47K 1.00 0.95 V
+in10 VSB VSB3.3V int. int. 2.00 1.65 V (3)
+in9 VBAT VBATTERY int. int. 2.00 1.50 V (3)
(1) Depends on your hardware setup.
(2) Obviously not correct, swapping R1 and R2 would make more sense.
+(3) F71872F/FG only.
These values can be used as hints at best, as motherboard manufacturers
are free to use a completely different setup. As a matter of fact, the
@@ -103,3 +114,38 @@ sensor. Each channel can be used for connecting either a thermal diode
or a thermistor. The driver reports the currently selected mode, but
doesn't allow changing it. In theory, the BIOS should have configured
everything properly.
+
+
+Fan Control
+-----------
+
+Both PWM (pulse-width modulation) and DC fan speed control methods are
+supported. The right one to use depends on external circuitry on the
+motherboard, so the driver assumes that the BIOS set the method
+properly. The driver will report the method, but won't let you change
+it.
+
+When the PWM method is used, you can select the operating frequency,
+from 187.5 kHz (default) to 31 Hz. The best frequency depends on the
+fan model. As a rule of thumb, lower frequencies seem to give better
+control, but may generate annoying high-pitch noise. Fintek recommends
+not going below 1 kHz, as the fan tachometers get confused by lower
+frequencies as well.
+
+When the DC method is used, Fintek recommends not going below 5 V, which
+corresponds to a pwm value of 106 for the driver. The driver doesn't
+enforce this limit though.
+
+Three different fan control modes are supported:
+
+* Manual mode
+ You ask for a specific PWM duty cycle or DC voltage.
+
+* Fan speed mode
+ You ask for a specific fan speed. This mode assumes that pwm1
+ corresponds to fan1, pwm2 to fan2 and pwm3 to fan3.
+
+* Temperature mode
+ You define 3 temperature/fan speed trip points, and the fan speed is
+ adjusted depending on the measured temperature, using interpolation.
+ This mode is not yet supported by the driver.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index e783fd62e30..74a80992d23 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -9,8 +9,7 @@ Supported chips:
http://www.ite.com.tw/
* IT8712F
Prefix: 'it8712'
- Addresses scanned: I2C 0x2d
- from Super I/O config space (8 I/O ports)
+ Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Publicly available at the ITE website
http://www.ite.com.tw/
* IT8716F
@@ -53,6 +52,18 @@ Module Parameters
misconfigured by BIOS - PWM values would be inverted. This option tries
to fix this. Please contact your BIOS manufacturer and ask him for fix.
+
+Hardware Interfaces
+-------------------
+
+All the chips suported by this driver are LPC Super-I/O chips, accessed
+through the LPC bus (ISA-like I/O ports). The IT8712F additionally has an
+SMBus interface to the hardware monitoring functions. This driver no
+longer supports this interface though, as it is slower and less reliable
+than the ISA access, and was only available on a small number of
+motherboard models.
+
+
Description
-----------
diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp
index 30d123b8d92..0005c716614 100644
--- a/Documentation/hwmon/k8temp
+++ b/Documentation/hwmon/k8temp
@@ -8,7 +8,7 @@ Supported chips:
Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
Author: Rudolf Marek
-Contact: Rudolf Marek <r.marek@sh.cvut.cz>
+Contact: Rudolf Marek <r.marek@assembler.cz>
Description
-----------
diff --git a/Documentation/hwmon/pc87427 b/Documentation/hwmon/pc87427
new file mode 100644
index 00000000000..9a0708f9f49
--- /dev/null
+++ b/Documentation/hwmon/pc87427
@@ -0,0 +1,38 @@
+Kernel driver pc87427
+=====================
+
+Supported chips:
+ * National Semiconductor PC87427
+ Prefix: 'pc87427'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/apc_007.html
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Amir Habibi at Candelis for setting up a test system, and to
+Michael Kress for testing several iterations of this driver.
+
+
+Description
+-----------
+
+The National Semiconductor Super I/O chip includes complete hardware
+monitoring capabilities. It can monitor up to 18 voltages, 8 fans and
+6 temperature sensors. Only the fans are supported at the moment.
+
+This chip also has fan controlling features, which are not yet supported
+by this driver either.
+
+The driver assumes that no more than one chip is present, which seems
+reasonable.
+
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported as 14-bit values from a gated clock
+signal. Speeds down to 83 RPM can be measured.
+
+An alarm is triggered if the rotation speed drops below a programmable
+limit. Another alarm is triggered if the speed is too low to to be measured
+(including stalled or missing fan).
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index d1d390aaf62..efef3b962cd 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -208,12 +208,14 @@ temp[1-*]_auto_point[1-*]_temp_hyst
****************
temp[1-*]_type Sensor type selection.
- Integers 1 to 4 or thermistor Beta value (typically 3435)
+ Integers 1 to 6 or thermistor Beta value (typically 3435)
RW
1: PII/Celeron Diode
2: 3904 transistor
3: thermal diode
4: thermistor (default/unknown Beta)
+ 5: AMD AMDSI
+ 6: Intel PECI
Not all types are supported by all chips
temp[1-*]_max Temperature max value.
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index caa610a297e..8a15a740875 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -10,7 +10,7 @@ Supported chips:
Authors:
Jean Delvare <khali@linux-fr.org>
Yuan Mu (Winbond)
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
Description
-----------
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
index 19b2ed739fa..db9881df88a 100644
--- a/Documentation/hwmon/w83791d
+++ b/Documentation/hwmon/w83791d
@@ -18,7 +18,7 @@ Credits:
and Mark Studebaker <mdsxyz123@yahoo.com>
w83792d.c:
Chunhao Huang <DZShen@Winbond.com.tw>,
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
Additional contributors:
Sven Anders <anders@anduras.de>
diff --git a/Documentation/hwmon/w83793 b/Documentation/hwmon/w83793
new file mode 100644
index 00000000000..51171a83165
--- /dev/null
+++ b/Documentation/hwmon/w83793
@@ -0,0 +1,106 @@
+Kernel driver w83793
+====================
+
+Supported chips:
+ * Winbond W83793G/W83793R
+ Prefix: 'w83793'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: Still not published
+
+Authors:
+ Yuan Mu (Winbond Electronics)
+ Rudolf Marek <r.marek@assembler.cz>
+
+
+Module parameters
+-----------------
+
+* reset int
+ (default 0)
+ This parameter is not recommended, it will lose motherboard specific
+ settings. Use 'reset=1' to reset the chip when loading this module.
+
+* force_subclients=bus,caddr,saddr1,saddr2
+ This is used to force the i2c addresses for subclients of
+ a certain chip. Typical usage is `force_subclients=0,0x2f,0x4a,0x4b'
+ to force the subclients of chip 0x2f on bus 0 to i2c addresses
+ 0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for Winbond W83793G/W83793R chips.
+
+* Exported features
+ This driver exports 10 voltage sensors, up to 12 fan tachometer inputs,
+ 6 remote temperatures, up to 8 sets of PWM fan controls, SmartFan
+ (automatic fan speed control) on all temperature/PWM combinations, 2
+ sets of 6-pin CPU VID input.
+
+* Sensor resolutions
+ If your motherboard maker used the reference design, the resolution of
+ voltage0-2 is 2mV, resolution of voltage3/4/5 is 16mV, 8mV for voltage6,
+ 24mV for voltage7/8. Temp1-4 have a 0.25 degree Celsius resolution,
+ temp5-6 have a 1 degree Celsiis resolution.
+
+* Temperature sensor types
+ Temp1-4 have 2 possible types. It can be read from (and written to)
+ temp[1-4]_type.
+ - If the value is 3, it starts monitoring using a remote termal diode
+ (default).
+ - If the value is 6, it starts monitoring using the temperature sensor
+ in Intel CPU and get result by PECI.
+ Temp5-6 can be connected to external thermistors (value of
+ temp[5-6]_type is 4).
+
+* Alarm mechanism
+ For voltage sensors, an alarm triggers if the measured value is below
+ the low voltage limit or over the high voltage limit.
+ For temperature sensors, an alarm triggers if the measured value goes
+ above the high temperature limit, and wears off only after the measured
+ value drops below the hysteresis value.
+ For fan sensors, an alarm triggers if the measured value is below the
+ low speed limit.
+
+* SmartFan/PWM control
+ If you want to set a pwm fan to manual mode, you just need to make sure it
+ is not controlled by any temp channel, for example, you want to set fan1
+ to manual mode, you need to check the value of temp[1-6]_fan_map, make
+ sure bit 0 is cleared in the 6 values. And then set the pwm1 value to
+ control the fan.
+
+ Each temperature channel can control all the 8 PWM outputs (by setting the
+ corresponding bit in tempX_fan_map), you can set the temperature channel
+ mode using temp[1-6]_pwm_enable, 2 is Thermal Cruise mode and 3
+ is the SmartFanII mode. Temperature channels will try to speed up or
+ slow down all controlled fans, this means one fan can receive different
+ PWM value requests from different temperature channels, but the chip
+ will always pick the safest (max) PWM value for each fan.
+
+ In Thermal Cruise mode, the chip attempts to keep the temperature at a
+ predefined value, within a tolerance margin. So if tempX_input >
+ thermal_cruiseX + toleranceX, the chip will increase the PWM value,
+ if tempX_input < thermal_cruiseX - toleranceX, the chip will decrease
+ the PWM value. If the temperature is within the tolerance range, the PWM
+ value is left unchanged.
+
+ SmartFanII works differently, you have to define up to 7 PWM, temperature
+ trip points, defining a PWM/temperature curve which the chip will follow.
+ While not fundamentally different from the Thermal Cruise mode, the
+ implementation is quite different, giving you a finer-grained control.
+
+* Chassis
+ If the case open alarm triggers, it will stay in this state unless cleared
+ by any write to the sysfs file "chassis".
+
+* VID and VRM
+ The VRM version is detected automatically, don't modify the it unless you
+ *do* know the cpu VRM version and it's not properly detected.
+
+
+Notes
+-----
+
+ Only Fan1-5 and PWM1-3 are guaranteed to always exist, other fan inputs and
+ PWM outputs may or may not exist depending on the chip pin configuration.
diff --git a/Documentation/i2c/busses/i2c-amd8111 b/Documentation/i2c/busses/i2c-amd8111
index db294ee7455..460dd6635fd 100644
--- a/Documentation/i2c/busses/i2c-amd8111
+++ b/Documentation/i2c/busses/i2c-amd8111
@@ -5,7 +5,7 @@ Supported adapters:
Datasheets:
AMD datasheet not yet available, but almost everything can be found
- in publically available ACPI 2.0 specification, which the adapter
+ in the publicly available ACPI 2.0 specification, which the adapter
follows.
Author: Vojtech Pavlik <vojtech@suse.cz>
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index e46c2345824..3db69a086c4 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -9,7 +9,10 @@ Supported adapters:
* Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
* Intel 6300ESB
* Intel 82801FB/FR/FW/FRW (ICH6)
- * Intel ICH7
+ * Intel 82801G (ICH7)
+ * Intel 631xESB/632xESB (ESB2)
+ * Intel 82801H (ICH8)
+ * Intel ICH9
Datasheets: Publicly available at the Intel website
Authors:
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index cd49c428a3a..7f61fbc03f7 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -10,11 +10,11 @@ Supported adapters:
* nForce4 MCP51 10de:0264
* nForce4 MCP55 10de:0368
-Datasheet: not publically available, but seems to be similar to the
+Datasheet: not publicly available, but seems to be similar to the
AMD-8111 SMBus 2.0 adapter.
Authors:
- Hans-Frieder Vogt <hfvogt@arcor.de>,
+ Hans-Frieder Vogt <hfvogt@gmx.net>,
Thomas Leibold <thomas@plx.com>,
Patrick Dreker <patrick@dreker.de>
@@ -38,7 +38,7 @@ Notes
-----
The SMBus adapter in the nForce2 chipset seems to be very similar to the
-SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get
+SMBus 2.0 adapter in the AMD-8111 south bridge. However, I could only get
the driver to work with direct I/O access, which is different to the EC
interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the
Asus A7N8X lists two SMBuses, both of which are supported by this driver.
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
index 9575de300a6..38fe1f03fb1 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
@@ -2,7 +2,7 @@
----------------------------
H. Peter Anvin <hpa@zytor.com>
- Last update 2006-11-17
+ Last update 2007-01-26
On the i386 platform, the Linux kernel uses a rather complicated boot
convention. This has evolved partially due to historical aspects, as
@@ -186,6 +186,7 @@ filled out, however:
7 GRuB
8 U-BOOT
9 Xen
+ A Gujin
Please contact <hpa@zytor.com> if you need a bootloader ID
value assigned.
diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt
index e50595bfd8e..0132d363feb 100644
--- a/Documentation/ibm-acpi.txt
+++ b/Documentation/ibm-acpi.txt
@@ -398,25 +398,67 @@ Temperature sensors -- /proc/acpi/ibm/thermal
Most ThinkPads include six or more separate temperature sensors but
only expose the CPU temperature through the standard ACPI methods.
-This feature shows readings from up to eight different sensors. Some
-readings may not be valid, e.g. may show large negative values. For
-example, on the X40, a typical output may be:
+This feature shows readings from up to eight different sensors on older
+ThinkPads, and it has experimental support for up to sixteen different
+sensors on newer ThinkPads. Readings from sensors that are not available
+return -128.
+No commands can be written to this file.
+
+EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
+implementation directly accesses hardware registers and may not work as
+expected. USE WITH CAUTION! To use this feature, you need to supply the
+experimental=1 parameter when loading the module. When EXPERIMENTAL
+mode is enabled, reading the first 8 sensors on newer ThinkPads will
+also use an new experimental thermal sensor access mode.
+
+For example, on the X40, a typical output may be:
temperatures: 42 42 45 41 36 -128 33 -128
-Thomas Gruber took his R51 apart and traced all six active sensors in
-his laptop (the location of sensors may vary on other models):
+EXPERIMENTAL: On the T43/p, a typical output may be:
+temperatures: 48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128
+
+The mapping of thermal sensors to physical locations varies depending on
+system-board model (and thus, on ThinkPad model).
+
+http://thinkwiki.org/wiki/Thermal_Sensors is a public wiki page that
+tries to track down these locations for various models.
+
+Most (newer?) models seem to follow this pattern:
1: CPU
-2: Mini PCI Module
-3: HDD
+2: (depends on model)
+3: (depends on model)
4: GPU
-5: Battery
-6: N/A
-7: Battery
-8: N/A
+5: Main battery: main sensor
+6: Bay battery: main sensor
+7: Main battery: secondary sensor
+8: Bay battery: secondary sensor
+9-15: (depends on model)
+
+For the R51 (source: Thomas Gruber):
+2: Mini-PCI
+3: Internal HDD
+
+For the T43, T43/p (source: Shmidoax/Thinkwiki.org)
+http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p
+2: System board, left side (near PCMCIA slot), reported as HDAPS temp
+3: PCMCIA slot
+9: MCH (northbridge) to DRAM Bus
+10: ICH (southbridge), under Mini-PCI card, under touchpad
+11: Power regulator, underside of system board, below F2 key
+
+The A31 has a very atypical layout for the thermal sensors
+(source: Milos Popovic, http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_A31)
+1: CPU
+2: Main Battery: main sensor
+3: Power Converter
+4: Bay Battery: main sensor
+5: MCH (northbridge)
+6: PCMCIA/ambient
+7: Main Battery: secondary sensor
+8: Bay Battery: secondary sensor
-No commands can be written to this file.
EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
------------------------------------------------------------------------
@@ -529,27 +571,57 @@ directly accesses hardware registers and may not work as expected. USE
WITH CAUTION! To use this feature, you need to supply the
experimental=1 parameter when loading the module.
-This feature attempts to show the current fan speed. The speed is read
-directly from the hardware registers of the embedded controller. This
-is known to work on later R, T and X series ThinkPads but may show a
-bogus value on other models.
+This feature attempts to show the current fan speed, control mode and
+other fan data that might be available. The speed is read directly
+from the hardware registers of the embedded controller. This is known
+to work on later R, T and X series ThinkPads but may show a bogus
+value on other models.
+
+Most ThinkPad fans work in "levels". Level 0 stops the fan. The higher
+the level, the higher the fan speed, although adjacent levels often map
+to the same fan speed. 7 is the highest level, where the fan reaches
+the maximum recommended speed. Level "auto" means the EC changes the
+fan level according to some internal algorithm, usually based on
+readings from the thermal sensors. Level "disengaged" means the EC
+disables the speed-locked closed-loop fan control, and drives the fan as
+fast as it can go, which might exceed hardware limits, so use this level
+with caution.
+
+The fan usually ramps up or down slowly from one speed to another,
+and it is normal for the EC to take several seconds to react to fan
+commands.
The fan may be enabled or disabled with the following commands:
echo enable >/proc/acpi/ibm/fan
echo disable >/proc/acpi/ibm/fan
+Placing a fan on level 0 is the same as disabling it. Enabling a fan
+will try to place it in a safe level if it is too slow or disabled.
+
WARNING WARNING WARNING: do not leave the fan disabled unless you are
-monitoring the temperature sensor readings and you are ready to enable
-it if necessary to avoid overheating.
+monitoring all of the temperature sensor readings and you are ready to
+enable it if necessary to avoid overheating.
-The fan only runs if it's enabled *and* the various temperature
-sensors which control it read high enough. On the X40, this seems to
-depend on the CPU and HDD temperatures. Specifically, the fan is
-turned on when either the CPU temperature climbs to 56 degrees or the
-HDD temperature climbs to 46 degrees. The fan is turned off when the
-CPU temperature drops to 49 degrees and the HDD temperature drops to
-41 degrees. These thresholds cannot currently be controlled.
+An enabled fan in level "auto" may stop spinning if the EC decides the
+ThinkPad is cool enough and doesn't need the extra airflow. This is
+normal, and the EC will spin the fan up if the varios thermal readings
+rise too much.
+
+On the X40, this seems to depend on the CPU and HDD temperatures.
+Specifically, the fan is turned on when either the CPU temperature
+climbs to 56 degrees or the HDD temperature climbs to 46 degrees. The
+fan is turned off when the CPU temperature drops to 49 degrees and the
+HDD temperature drops to 41 degrees. These thresholds cannot
+currently be controlled.
+
+The fan level can be controlled with the command:
+
+ echo 'level <level>' > /proc/acpi/ibm/thermal
+
+Where <level> is an integer from 0 to 7, or one of the words "auto"
+or "disengaged" (without the quotes). Not all ThinkPads support the
+"auto" and "disengaged" levels.
On the X31 and X40 (and ONLY on those models), the fan speed can be
controlled to a certain degree. Once the fan is running, it can be
@@ -562,12 +634,9 @@ about 3700 to about 7350. Values outside this range either do not have
any effect or the fan speed eventually settles somewhere in that
range. The fan cannot be stopped or started with this command.
-On the 570, temperature readings are not available through this
-feature and the fan control works a little differently. The fan speed
-is reported in levels from 0 (off) to 7 (max) and can be controlled
-with the following command:
-
- echo 'level <level>' > /proc/acpi/ibm/thermal
+The ThinkPad's ACPI DSDT code will reprogram the fan on its own when
+certain conditions are met. It will override any fan programming done
+through ibm-acpi.
EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
---------------------------------------
@@ -601,6 +670,26 @@ example:
modprobe ibm_acpi hotkey=enable,0xffff video=auto_disable
+The ibm-acpi kernel driver can be programmed to revert the fan level
+to a safe setting if userspace does not issue one of the fan commands:
+"enable", "disable", "level" or "watchdog" within a configurable
+ammount of time. To do this, use the "watchdog" command.
+
+ echo 'watchdog <interval>' > /proc/acpi/ibm/fan
+
+Interval is the ammount of time in seconds to wait for one of the
+above mentioned fan commands before reseting the fan level to a safe
+one. If set to zero, the watchdog is disabled (default). When the
+watchdog timer runs out, it does the exact equivalent of the "enable"
+fan command.
+
+Note that the watchdog timer stops after it enables the fan. It will
+be rearmed again automatically (using the same interval) when one of
+the above mentioned fan commands is received. The fan watchdog is,
+therefore, not suitable to protect against fan mode changes made
+through means other than the "enable", "disable", and "level" fan
+commands.
+
Example Configuration
---------------------
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index edc04d74ae2..5a8bd5bd88e 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -191,3 +191,5 @@ Code Seq# Include File Comments
<mailto:aherrman@de.ibm.com>
0xF3 00-3F video/sisfb.h sisfb (in development)
<mailto:thomas@winischhofer.net>
+0xF4 00-1F video/mbxfb.h mbxfb
+ <mailto:raph@8d.com>
diff --git a/Documentation/ioctl/ioctl-decoding.txt b/Documentation/ioctl/ioctl-decoding.txt
new file mode 100644
index 00000000000..bfdf7f3ee4f
--- /dev/null
+++ b/Documentation/ioctl/ioctl-decoding.txt
@@ -0,0 +1,24 @@
+To decode a hex IOCTL code:
+
+Most architecures use this generic format, but check
+include/ARCH/ioctl.h for specifics, e.g. powerpc
+uses 3 bits to encode read/write and 13 bits for size.
+
+ bits meaning
+ 31-30 00 - no parameters: uses _IO macro
+ 10 - read: _IOR
+ 01 - write: _IOW
+ 11 - read/write: _IOWR
+
+ 29-16 size of arguments
+
+ 15-8 ascii character supposedly
+ unique to each driver
+
+ 7-0 function #
+
+
+ So for example 0x82187201 is a read with arg length of 0x218,
+character 'r' function 1. Grepping the source reveals this is:
+
+#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index 125093c3ef7..536d5bfbdb8 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -29,7 +29,7 @@ them. A single configuration option is defined like this:
config MODVERSIONS
bool "Set version information on all module symbols"
- depends MODULES
+ depends on MODULES
help
Usually, modules have to be recompiled whenever you switch to a new
kernel. ...
@@ -163,7 +163,7 @@ The position of a menu entry in the tree is determined in two ways. First
it can be specified explicitly:
menu "Network device support"
- depends NET
+ depends on NET
config NETDEVICES
...
@@ -188,10 +188,10 @@ config MODULES
config MODVERSIONS
bool "Set version information on all module symbols"
- depends MODULES
+ depends on MODULES
comment "module support disabled"
- depends !MODULES
+ depends on !MODULES
MODVERSIONS directly depends on MODULES, this means it's only visible if
MODULES is different from 'n'. The comment on the other hand is always
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 99f2d4d4bf7..07330681834 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -17,7 +17,7 @@ You can use common Linux commands, such as cp and scp, to copy the
memory image to a dump file on the local disk, or across the network to
a remote system.
-Kdump and kexec are currently supported on the x86, x86_64, and ppc64
+Kdump and kexec are currently supported on the x86, x86_64, ppc64 and ia64
architectures.
When the system kernel boots, it reserves a small section of memory for
@@ -54,59 +54,69 @@ memory," in two ways:
Setup and Installation
======================
-Install kexec-tools and the Kdump patch
----------------------------------------
+Install kexec-tools
+-------------------
1) Login as the root user.
2) Download the kexec-tools user-space package from the following URL:
- http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
+http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools-testing.tar.gz
-3) Unpack the tarball with the tar command, as follows:
-
- tar xvpzf kexec-tools-1.101.tar.gz
-
-4) Download the latest consolidated Kdump patch from the following URL:
+This is a symlink to the latest version, which at the time of writing is
+20061214, the only release of kexec-tools-testing so far. As other versions
+are made released, the older onese will remain available at
+http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
- http://lse.sourceforge.net/kdump/
+Note: Latest kexec-tools-testing git tree is available at
- (This location is being used until all the user-space Kdump patches
- are integrated with the kexec-tools package.)
+git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools-testing.git
+or
+http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools-testing.git;a=summary
-5) Change to the kexec-tools-1.101 directory, as follows:
+3) Unpack the tarball with the tar command, as follows:
- cd kexec-tools-1.101
+ tar xvpzf kexec-tools-testing.tar.gz
-6) Apply the consolidated patch to the kexec-tools-1.101 source tree
- with the patch command, as follows. (Modify the path to the downloaded
- patch as necessary.)
+4) Change to the kexec-tools directory, as follows:
- patch -p1 < /path-to-kdump-patch/kexec-tools-1.101-kdump.patch
+ cd kexec-tools-testing-VERSION
-7) Configure the package, as follows:
+5) Configure the package, as follows:
./configure
-8) Compile the package, as follows:
+6) Compile the package, as follows:
make
-9) Install the package, as follows:
+7) Install the package, as follows:
make install
-Download and build the system and dump-capture kernels
-------------------------------------------------------
+Build the system and dump-capture kernels
+-----------------------------------------
+There are two possible methods of using Kdump.
+
+1) Build a separate custom dump-capture kernel for capturing the
+ kernel core dump.
-Download the mainline (vanilla) kernel source code (2.6.13-rc1 or newer)
-from http://www.kernel.org. Two kernels must be built: a system kernel
-and a dump-capture kernel. Use the following steps to configure these
-kernels with the necessary kexec and Kdump features:
+2) Or use the system kernel binary itself as dump-capture kernel and there is
+ no need to build a separate dump-capture kernel. This is possible
+ only with the architecutres which support a relocatable kernel. As
+ of today i386 and ia64 architectures support relocatable kernel.
-System kernel
--------------
+Building a relocatable kernel is advantageous from the point of view that
+one does not have to build a second kernel for capturing the dump. But
+at the same time one might want to build a custom dump capture kernel
+suitable to his needs.
+
+Following are the configuration setting required for system and
+dump-capture kernels for enabling kdump support.
+
+System kernel config options
+----------------------------
1) Enable "kexec system call" in "Processor type and features."
@@ -132,88 +142,182 @@ System kernel
analysis tools require a vmlinux with debug symbols in order to read
and analyze a dump file.
-4) Make and install the kernel and its modules. Update the boot loader
- (such as grub, yaboot, or lilo) configuration files as necessary.
+Dump-capture kernel config options (Arch Independent)
+-----------------------------------------------------
-5) Boot the system kernel with the boot parameter "crashkernel=Y@X",
- where Y specifies how much memory to reserve for the dump-capture kernel
- and X specifies the beginning of this reserved memory. For example,
- "crashkernel=64M@16M" tells the system kernel to reserve 64 MB of memory
- starting at physical address 0x01000000 for the dump-capture kernel.
-
- On x86 and x86_64, use "crashkernel=64M@16M".
-
- On ppc64, use "crashkernel=128M@32M".
+1) Enable "kernel crash dumps" support under "Processor type and
+ features":
+ CONFIG_CRASH_DUMP=y
-The dump-capture kernel
------------------------
+2) Enable "/proc/vmcore support" under "Filesystems" -> "Pseudo filesystems".
-1) Under "General setup," append "-kdump" to the current string in
- "Local version."
+ CONFIG_PROC_VMCORE=y
+ (CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.)
-2) On x86, enable high memory support under "Processor type and
+Dump-capture kernel config options (Arch Dependent, i386)
+--------------------------------------------------------
+1) On x86, enable high memory support under "Processor type and
features":
CONFIG_HIGHMEM64G=y
or
CONFIG_HIGHMEM4G
-3) On x86 and x86_64, disable symmetric multi-processing support
+2) On x86 and x86_64, disable symmetric multi-processing support
under "Processor type and features":
CONFIG_SMP=n
+
(If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
when loading the dump-capture kernel, see section "Load the Dump-capture
Kernel".)
-4) On ppc64, disable NUMA support and enable EMBEDDED support:
+3) If one wants to build and use a relocatable kernel,
+ Enable "Build a relocatable kernel" support under "Processor type and
+ features"
- CONFIG_NUMA=n
- CONFIG_EMBEDDED=y
- CONFIG_EEH=N for the dump-capture kernel
+ CONFIG_RELOCATABLE=y
-5) Enable "kernel crash dumps" support under "Processor type and
- features":
+4) Use a suitable value for "Physical address where the kernel is
+ loaded" (under "Processor type and features"). This only appears when
+ "kernel crash dumps" is enabled. A suitable value depends upon
+ whether kernel is relocatable or not.
+
+ If you are using a relocatable kernel use CONFIG_PHYSICAL_START=0x100000
+ This will compile the kernel for physical address 1MB, but given the fact
+ kernel is relocatable, it can be run from any physical address hence
+ kexec boot loader will load it in memory region reserved for dump-capture
+ kernel.
+
+ Otherwise it should be the start of memory region reserved for
+ second kernel using boot parameter "crashkernel=Y@X". Here X is
+ start of memory region reserved for dump-capture kernel.
+ Generally X is 16MB (0x1000000). So you can set
+ CONFIG_PHYSICAL_START=0x1000000
+
+5) Make and install the kernel and its modules. DO NOT add this kernel
+ to the boot loader configuration files.
- CONFIG_CRASH_DUMP=y
+Dump-capture kernel config options (Arch Dependent, x86_64)
+----------------------------------------------------------
+1) On x86 and x86_64, disable symmetric multi-processing support
+ under "Processor type and features":
-6) Use a suitable value for "Physical address where the kernel is
+ CONFIG_SMP=n
+
+ (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
+ when loading the dump-capture kernel, see section "Load the Dump-capture
+ Kernel".)
+
+2) Use a suitable value for "Physical address where the kernel is
loaded" (under "Processor type and features"). This only appears when
"kernel crash dumps" is enabled. By default this value is 0x1000000
(16MB). It should be the same as X in the "crashkernel=Y@X" boot
- parameter discussed above.
+ parameter.
- On x86 and x86_64, use "CONFIG_PHYSICAL_START=0x1000000".
+ For x86_64, normally "CONFIG_PHYSICAL_START=0x1000000".
- On ppc64 the value is automatically set at 32MB when
- CONFIG_CRASH_DUMP is set.
+3) Make and install the kernel and its modules. DO NOT add this kernel
+ to the boot loader configuration files.
-6) Optionally enable "/proc/vmcore support" under "Filesystems" ->
- "Pseudo filesystems".
+Dump-capture kernel config options (Arch Dependent, ppc64)
+----------------------------------------------------------
- CONFIG_PROC_VMCORE=y
- (CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.)
-
-7) Make and install the kernel and its modules. DO NOT add this kernel
+- Make and install the kernel and its modules. DO NOT add this kernel
to the boot loader configuration files.
+Dump-capture kernel config options (Arch Dependent, ia64)
+----------------------------------------------------------
+
+- No specific options are required to create a dump-capture kernel
+ for ia64, other than those specified in the arch idependent section
+ above. This means that it is possible to use the system kernel
+ as a dump-capture kernel if desired.
+
+ The crashkernel region can be automatically placed by the system
+ kernel at run time. This is done by specifying the base address as 0,
+ or omitting it all together.
+
+ crashkernel=256M@0
+ or
+ crashkernel=256M
+
+ If the start address is specified, note that the start address of the
+ kernel will be aligned to 64Mb, so if the start address is not then
+ any space below the alignment point will be wasted.
+
+
+Boot into System Kernel
+=======================
+
+1) Make and install the kernel and its modules. Update the boot loader
+ (such as grub, yaboot, or lilo) configuration files as necessary.
+
+2) Boot the system kernel with the boot parameter "crashkernel=Y@X",
+ where Y specifies how much memory to reserve for the dump-capture kernel
+ and X specifies the beginning of this reserved memory. For example,
+ "crashkernel=64M@16M" tells the system kernel to reserve 64 MB of memory
+ starting at physical address 0x01000000 (16MB) for the dump-capture kernel.
+
+ On x86 and x86_64, use "crashkernel=64M@16M".
+
+ On ppc64, use "crashkernel=128M@32M".
+
+ On ia64, 256M@256M is a generous value that typically works.
+ The region may be automatically placed on ia64, see the
+ dump-capture kernel config option notes above.
Load the Dump-capture Kernel
============================
-After booting to the system kernel, load the dump-capture kernel using
-the following command:
+After booting to the system kernel, dump-capture kernel needs to be
+loaded.
+
+Based on the architecture and type of image (relocatable or not), one
+can choose to load the uncompressed vmlinux or compressed bzImage/vmlinuz
+of dump-capture kernel. Following is the summary.
+
+For i386:
+ - Use vmlinux if kernel is not relocatable.
+ - Use bzImage/vmlinuz if kernel is relocatable.
+For x86_64:
+ - Use vmlinux
+For ppc64:
+ - Use vmlinux
+For ia64:
+ - Use vmlinux or vmlinuz.gz
+
- kexec -p <dump-capture-kernel> \
+If you are using a uncompressed vmlinux image then use following command
+to load dump-capture kernel.
+
+ kexec -p <dump-capture-kernel-vmlinux-image> \
--initrd=<initrd-for-dump-capture-kernel> --args-linux \
- --append="root=<root-dev> init 1 irqpoll"
+ --append="root=<root-dev> <arch-specific-options>"
+If you are using a compressed bzImage/vmlinuz, then use following command
+to load dump-capture kernel.
-Notes on loading the dump-capture kernel:
+ kexec -p <dump-capture-kernel-bzImage> \
+ --initrd=<initrd-for-dump-capture-kernel> \
+ --append="root=<root-dev> <arch-specific-options>"
+
+Please note, that --args-linux does not need to be specified for ia64.
+It is planned to make this a no-op on that architecture, but for now
+it should be omitted
+
+Following are the arch specific command line options to be used while
+loading dump-capture kernel.
-* <dump-capture-kernel> must be a vmlinux image (that is, an
- uncompressed ELF image). bzImage does not work at this time.
+For i386, x86_64 and ia64:
+ "init 1 irqpoll maxcpus=1"
+
+For ppc64:
+ "init 1 maxcpus=1 noirqdistrib"
+
+
+Notes on loading the dump-capture kernel:
* By default, the ELF headers are stored in ELF64 format to support
systems with more than 4GB memory. The --elf32-core-headers option can
@@ -231,6 +335,9 @@ Notes on loading the dump-capture kernel:
* "init 1" boots the dump-capture kernel into single-user mode without
networking. If you want networking, use "init 3."
+* We generally don' have to bring up a SMP kernel just to capture the
+ dump. Hence generally it is useful either to build a UP dump-capture
+ kernel or specify maxcpus=1 option while loading dump-capture kernel.
Kernel Panic
============
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b79bcdf1631..25d29851710 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -548,6 +548,13 @@ and is between 256 and 4096 characters. It is defined in the file
eurwdt= [HW,WDT] Eurotech CPU-1220/1410 onboard watchdog.
Format: <io>[,<irq>]
+ failslab=
+ fail_page_alloc=
+ fail_make_request=[KNL]
+ General fault injection mechanism.
+ Format: <interval>,<probability>,<space>,<times>
+ See also /Documentation/fault-injection/.
+
fd_mcs= [HW,SCSI]
See header of drivers/scsi/fd_mcs.c.
@@ -1649,6 +1656,12 @@ and is between 256 and 4096 characters. It is defined in the file
sym53c416= [HW,SCSI]
See header of drivers/scsi/sym53c416.c.
+ sysrq_always_enabled
+ [KNL]
+ Ignore sysrq setting - this boot parameter will
+ neutralize any effect of /proc/sys/kernel/sysrq.
+ Useful for debugging.
+
t128= [HW,SCSI]
See header of drivers/scsi/t128.c.
@@ -1701,6 +1714,14 @@ and is between 256 and 4096 characters. It is defined in the file
uart6850= [HW,OSS]
Format: <io>,<irq>
+ uhci-hcd.ignore_oc=
+ [USB] Ignore overcurrent events (default N).
+ Some badly-designed motherboards generate lots of
+ bogus events, for ports that aren't wired to
+ anything. Set this parameter to avoid log spamming.
+ Note that genuine overcurrent events won't be
+ reported either.
+
usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index dda15886bcb..387482e46c4 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -19,7 +19,8 @@ for real time and multimedia traffic.
It has a base protocol and pluggable congestion control IDs (CCIDs).
-It is at experimental RFC status and the homepage for DCCP as a protocol is at:
+It is at proposed standard RFC status and the homepage for DCCP as a protocol
+is at:
http://www.read.cs.ucla.edu/dccp/
Missing features
@@ -34,9 +35,6 @@ The known bugs are at:
Socket options
==============
-DCCP_SOCKOPT_PACKET_SIZE is used for CCID3 to set default packet size for
-calculations.
-
DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of
service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,
the socket will fall back to 0 (which means that no meaningful service code
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 2b395e47896..fd5028eca13 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -1,142 +1,231 @@
- How To Write Linux PCI Drivers
- by Martin Mares <mj@ucw.cz> on 07-Feb-2000
+ How To Write Linux PCI Drivers
+
+ by Martin Mares <mj@ucw.cz> on 07-Feb-2000
+ updated by Grant Grundler <grundler@parisc-linux.org> on 23-Dec-2006
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The world of PCI is vast and it's full of (mostly unpleasant) surprises.
-Different PCI devices have different requirements and different bugs --
-because of this, the PCI support layer in Linux kernel is not as trivial
-as one would wish. This short pamphlet tries to help all potential driver
-authors find their way through the deep forests of PCI handling.
+The world of PCI is vast and full of (mostly unpleasant) surprises.
+Since each CPU architecture implements different chip-sets and PCI devices
+have different requirements (erm, "features"), the result is the PCI support
+in the Linux kernel is not as trivial as one would wish. This short paper
+tries to introduce all potential driver authors to Linux APIs for
+PCI device drivers.
+
+A more complete resource is the third edition of "Linux Device Drivers"
+by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
+LDD3 is available for free (under Creative Commons License) from:
+
+ http://lwn.net/Kernel/LDD3/
+
+However, keep in mind that all documents are subject to "bit rot".
+Refer to the source code if things are not working as described here.
+
+Please send questions/comments/patches about Linux PCI API to the
+"Linux PCI" <linux-pci@atrey.karlin.mff.cuni.cz> mailing list.
+
0. Structure of PCI drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There exist two kinds of PCI drivers: new-style ones (which leave most of
-probing for devices to the PCI layer and support online insertion and removal
-of devices [thus supporting PCI, hot-pluggable PCI and CardBus in a single
-driver]) and old-style ones which just do all the probing themselves. Unless
-you have a very good reason to do so, please don't use the old way of probing
-in any new code. After the driver finds the devices it wishes to operate
-on (either the old or the new way), it needs to perform the following steps:
+PCI drivers "discover" PCI devices in a system via pci_register_driver().
+Actually, it's the other way around. When the PCI generic code discovers
+a new device, the driver with a matching "description" will be notified.
+Details on this below.
+
+pci_register_driver() leaves most of the probing for devices to
+the PCI layer and supports online insertion/removal of devices [thus
+supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
+pci_register_driver() call requires passing in a table of function
+pointers and thus dictates the high level structure of a driver.
+
+Once the driver knows about a PCI device and takes ownership, the
+driver generally needs to perform the following initialization:
Enable the device
- Access device configuration space
- Discover resources (addresses and IRQ numbers) provided by the device
- Allocate these resources
- Communicate with the device
+ Request MMIO/IOP resources
+ Set the DMA mask size (for both coherent and streaming DMA)
+ Allocate and initialize shared control data (pci_allocate_coherent())
+ Access device configuration space (if needed)
+ Register IRQ handler (request_irq())
+ Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+ Enable DMA/processing engines
+
+When done using the device, and perhaps the module needs to be unloaded,
+the driver needs to take the follow steps:
+ Disable the device from generating IRQs
+ Release the IRQ (free_irq())
+ Stop all DMA activity
+ Release DMA buffers (both streaming and coherent)
+ Unregister from other subsystems (e.g. scsi or netdev)
+ Release MMIO/IOP resources
Disable the device
-Most of these topics are covered by the following sections, for the rest
-look at <linux/pci.h>, it's hopefully well commented.
+Most of these topics are covered in the following sections.
+For the rest look at LDD3 or <linux/pci.h> .
If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
-the functions described below are defined as inline functions either completely
-empty or just returning an appropriate error codes to avoid lots of ifdefs
-in the drivers.
+the PCI functions described below are defined as inline functions either
+completely empty or just returning an appropriate error codes to avoid
+lots of ifdefs in the drivers.
+
-1. New-style drivers
-~~~~~~~~~~~~~~~~~~~~
-The new-style drivers just call pci_register_driver during their initialization
-with a pointer to a structure describing the driver (struct pci_driver) which
-contains:
+1. pci_register_driver() call
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- name Name of the driver
+PCI device drivers call pci_register_driver() during their
+initialization with a pointer to a structure describing the driver
+(struct pci_driver):
+
+ field name Description
+ ---------- ------------------------------------------------------
id_table Pointer to table of device ID's the driver is
interested in. Most drivers should export this
table using MODULE_DEVICE_TABLE(pci,...).
- probe Pointer to a probing function which gets called (during
- execution of pci_register_driver for already existing
- devices or later if a new device gets inserted) for all
- PCI devices which match the ID table and are not handled
- by the other drivers yet. This function gets passed a
- pointer to the pci_dev structure representing the device
- and also which entry in the ID table did the device
- match. It returns zero when the driver has accepted the
- device or an error code (negative number) otherwise.
- This function always gets called from process context,
- so it can sleep.
- remove Pointer to a function which gets called whenever a
- device being handled by this driver is removed (either
- during deregistration of the driver or when it's
- manually pulled out of a hot-pluggable slot). This
- function always gets called from process context, so it
- can sleep.
- save_state Save a device's state before it's suspend.
+
+ probe This probing function gets called (during execution
+ of pci_register_driver() for already existing
+ devices or later if a new device gets inserted) for
+ all PCI devices which match the ID table and are not
+ "owned" by the other drivers yet. This function gets
+ passed a "struct pci_dev *" for each device whose
+ entry in the ID table matches the device. The probe
+ function returns zero when the driver chooses to
+ take "ownership" of the device or an error code
+ (negative number) otherwise.
+ The probe function always gets called from process
+ context, so it can sleep.
+
+ remove The remove() function gets called whenever a device
+ being handled by this driver is removed (either during
+ deregistration of the driver or when it's manually
+ pulled out of a hot-pluggable slot).
+ The remove function always gets called from process
+ context, so it can sleep.
+
suspend Put device into low power state.
+ suspend_late Put device into low power state.
+
+ resume_early Wake device from low power state.
resume Wake device from low power state.
+
+ (Please see Documentation/power/pci.txt for descriptions
+ of PCI Power Management and the related functions.)
+
enable_wake Enable device to generate wake events from a low power
state.
- (Please see Documentation/power/pci.txt for descriptions
- of PCI Power Management and the related functions)
+ shutdown Hook into reboot_notifier_list (kernel/sys.c).
+ Intended to stop any idling DMA operations.
+ Useful for enabling wake-on-lan (NIC) or changing
+ the power state of a device before reboot.
+ e.g. drivers/net/e100.c.
+
+ err_handler See Documentation/pci-error-recovery.txt
+
+ multithread_probe Enable multi-threaded probe/scan. Driver must
+ provide its own locking/syncronization for init
+ operations if this is enabled.
+
-The ID table is an array of struct pci_device_id ending with a all-zero entry.
-Each entry consists of:
+The ID table is an array of struct pci_device_id entries ending with an
+all-zero entry. Each entry consists of:
+
+ vendor,device Vendor and device ID to match (or PCI_ANY_ID)
- vendor, device Vendor and device ID to match (or PCI_ANY_ID)
subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
- subdevice
- class, Device class to match. The class_mask tells which bits
- class_mask of the class are honored during the comparison.
+ subdevice,
+
+ class Device class, subclass, and "interface" to match.
+ See Appendix D of the PCI Local Bus Spec or
+ include/linux/pci_ids.h for a full list of classes.
+ Most drivers do not need to specify class/class_mask
+ as vendor/device is normally sufficient.
+
+ class_mask limit which sub-fields of the class field are compared.
+ See drivers/scsi/sym53c8xx_2/ for example of usage.
+
driver_data Data private to the driver.
+ Most drivers don't need to use driver_data field.
+ Best practice is to use driver_data as an index
+ into a static list of equivalent device types,
+ instead of using it as a pointer.
-Most drivers don't need to use the driver_data field. Best practice
-for use of driver_data is to use it as an index into a static list of
-equivalent device types, not to use it as a pointer.
-Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}
-to have probe() called for every PCI device known to the system.
+Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
+a pci_device_id table.
-New PCI IDs may be added to a device driver at runtime by writing
-to the file /sys/bus/pci/drivers/{driver}/new_id. When added, the
-driver will probe for all devices it can support.
+New PCI IDs may be added to a device driver pci_ids table at runtime
+as shown below:
echo "vendor device subvendor subdevice class class_mask driver_data" > \
- /sys/bus/pci/drivers/{driver}/new_id
-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 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.
+/sys/bus/pci/drivers/{driver}/new_id
+
+All fields are passed in as hexadecimal values (no leading 0x).
+Users need pass only as many fields as necessary:
+ o vendor, device, subvendor, and subdevice fields default
+ to PCI_ANY_ID (FFFFFFFF),
+ o class and classmask fields default to 0
+ o driver_data defaults to 0UL.
+
+Once added, the driver probe routine will be invoked for any unclaimed
+PCI devices listed in its (newly updated) pci_ids list.
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.
+
+1.1 "Attributes" for driver functions/data
+
Please mark the initialization and cleanup functions where appropriate
(the corresponding macros are defined in <linux/init.h>):
__init Initialization code. Thrown away after the driver
initializes.
__exit Exit code. Ignored for non-modular drivers.
- __devinit Device initialization code. Identical to __init if
- the kernel is not compiled with CONFIG_HOTPLUG, normal
- function otherwise.
+
+
+ __devinit Device initialization code.
+ Identical to __init if the kernel is not compiled
+ with CONFIG_HOTPLUG, normal function otherwise.
__devexit The same for __exit.
-Tips:
- The module_init()/module_exit() functions (and all initialization
- functions called only from these) should be marked __init/exit.
- The struct pci_driver shouldn't be marked with any of these tags.
- The ID table array should be marked __devinitdata.
- The probe() and remove() functions (and all initialization
- functions called only from these) should be marked __devinit/exit.
- If you are sure the driver is not a hotplug driver then use only
- __init/exit __initdata/exitdata.
+Tips on when/where to use the above attributes:
+ o The module_init()/module_exit() functions (and all
+ initialization functions called _only_ from these)
+ should be marked __init/__exit.
- Pointers to functions marked as __devexit must be created using
- __devexit_p(function_name). That will generate the function
- name or NULL if the __devexit function will be discarded.
+ o Do not mark the struct pci_driver.
+ o The ID table array should be marked __devinitdata.
-2. How to find PCI devices manually (the old style)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-PCI drivers not using the pci_register_driver() interface search
-for PCI devices manually using the following constructs:
+ o The probe() and remove() functions should be marked __devinit
+ and __devexit respectively. All initialization functions
+ exclusively called by the probe() routine, can be marked __devinit.
+ Ditto for remove() and __devexit.
+
+ o If mydriver_probe() is marked with __devinit(), then all address
+ references to mydriver_probe must use __devexit_p(mydriver_probe)
+ (in the struct pci_driver declaration for example).
+ __devexit_p() will generate the function name _or_ NULL if the
+ function will be discarded. For an example, see drivers/net/tg3.c.
+
+ o Do NOT mark a function if you are not sure which mark to use.
+ Better to not mark the function than mark the function wrong.
+
+
+
+2. How to find PCI devices manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+PCI drivers should have a really good reason for not using the
+pci_register_driver() interface to search for PCI devices.
+The main reason PCI devices are controlled by multiple drivers
+is because one PCI device implements several different HW services.
+E.g. combined serial/parallel port/floppy controller.
+
+A manual search may be performed using the following constructs:
Searching by vendor and device ID:
@@ -150,87 +239,311 @@ Searching by class ID (iterate in a similar way):
Searching by both vendor/device and subsystem vendor/device ID:
- pci_get_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+ pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
- You can use the constant PCI_ANY_ID as a wildcard replacement for
+You can use the constant PCI_ANY_ID as a wildcard replacement for
VENDOR_ID or DEVICE_ID. This allows searching for any device from a
specific vendor, for example.
- These functions are hotplug-safe. They increment the reference count on
+These functions are hotplug-safe. They increment the reference count on
the pci_dev that they return. You must eventually (possibly at module unload)
decrement the reference count on these devices by calling pci_dev_put().
-3. Enabling and disabling devices
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Before you do anything with the device you've found, you need to enable
-it by calling pci_enable_device() which enables I/O and memory regions of
-the device, allocates an IRQ if necessary, assigns missing resources if
-needed and wakes up the device if it was in suspended state. Please note
-that this function can fail.
- If you want to use the device in bus mastering mode, call pci_set_master()
-which enables the bus master bit in PCI_COMMAND register and also fixes
-the latency timer value if it's set to something bogus by the BIOS.
+3. Device Initialization Steps
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As noted in the introduction, most PCI drivers need the following steps
+for device initialization:
- If you want to use the PCI Memory-Write-Invalidate transaction,
+ Enable the device
+ Request MMIO/IOP resources
+ Set the DMA mask size (for both coherent and streaming DMA)
+ Allocate and initialize shared control data (pci_allocate_coherent())
+ Access device configuration space (if needed)
+ Register IRQ handler (request_irq())
+ Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+ Enable DMA/processing engines.
+
+The driver can access PCI config space registers at any time.
+(Well, almost. When running BIST, config space can go away...but
+that will just result in a PCI Bus Master Abort and config reads
+will return garbage).
+
+
+3.1 Enable the PCI device
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Before touching any device registers, the driver needs to enable
+the PCI device by calling pci_enable_device(). This will:
+ o wake up the device if it was in suspended state,
+ o allocate I/O and memory regions of the device (if BIOS did not),
+ o allocate an IRQ (if BIOS did not).
+
+NOTE: pci_enable_device() can fail! Check the return value.
+NOTE2: Also see pci_enable_device_bars() below. Drivers can
+ attempt to enable only a subset of BARs they need.
+
+[ OS BUG: we don't check resource allocations before enabling those
+ resources. The sequence would make more sense if we called
+ pci_request_resources() before calling pci_enable_device().
+ Currently, the device drivers can't detect the bug when when two
+ devices have been allocated the same range. This is not a common
+ problem and unlikely to get fixed soon.
+
+ This has been discussed before but not changed as of 2.6.19:
+ http://lkml.org/lkml/2006/3/2/194
+]
+
+pci_set_master() will enable DMA by setting the bus master bit
+in the PCI_COMMAND register. It also fixes the latency timer value if
+it's set to something bogus by the BIOS.
+
+If the PCI device can use the PCI Memory-Write-Invalidate transaction,
call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
and also ensures that the cache line size register is set correctly.
-Make sure to check the return value of pci_set_mwi(), not all architectures
-may support Memory-Write-Invalidate.
+Check the return value of pci_set_mwi() as not all architectures
+or chip-sets may support Memory-Write-Invalidate.
+
+
+3.2 Request MMIO/IOP resources
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Memory (MMIO), and I/O port addresses should NOT be read directly
+from the PCI device config space. Use the values in the pci_dev structure
+as the PCI "bus address" might have been remapped to a "host physical"
+address by the arch/chip-set specific kernel support.
- If your driver decides to stop using the device (e.g., there was an
-error while setting it up or the driver module is being unloaded), it
-should call pci_disable_device() to deallocate any IRQ resources, disable
-PCI bus-mastering, etc. You should not do anything with the device after
+See Documentation/IO-mapping.txt for how to access device registers
+or device memory.
+
+The device driver needs to call pci_request_region() to verify
+no other device is already using the same address resource.
+Conversely, drivers should call pci_release_region() AFTER
calling pci_disable_device().
+The idea is to prevent two devices colliding on the same address range.
+
+[ See OS BUG comment above. Currently (2.6.19), The driver can only
+ determine MMIO and IO Port resource availability _after_ calling
+ pci_enable_device(). ]
+
+Generic flavors of pci_request_region() are request_mem_region()
+(for MMIO ranges) and request_region() (for IO Port ranges).
+Use these for address resources that are not described by "normal" PCI
+BARs.
+
+Also see pci_request_selected_regions() below.
+
+
+3.3 Set the DMA mask size
+~~~~~~~~~~~~~~~~~~~~~~~~~
+[ If anything below doesn't make sense, please refer to
+ Documentation/DMA-API.txt. This section is just a reminder that
+ drivers need to indicate DMA capabilities of the device and is not
+ an authoritative source for DMA interfaces. ]
+
+While all drivers should explicitly indicate the DMA capability
+(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
+32-bit bus master capability for streaming data need the driver
+to "register" this capability by calling pci_set_dma_mask() with
+appropriate parameters. In general this allows more efficient DMA
+on systems where System RAM exists above 4G _physical_ address.
+
+Drivers for all PCI-X and PCIe compliant devices must call
+pci_set_dma_mask() as they are 64-bit DMA devices.
+
+Similarly, drivers must also "register" this capability if the device
+can directly address "consistent memory" in System RAM above 4G physical
+address by calling pci_set_consistent_dma_mask().
+Again, this includes drivers for all PCI-X and PCIe compliant devices.
+Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
+64-bit DMA capable for payload ("streaming") data but not control
+("consistent") data.
+
+
+3.4 Setup shared control data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
+memory. See Documentation/DMA-API.txt for a full description of
+the DMA APIs. This section is just a reminder that it needs to be done
+before enabling DMA on the device.
+
+
+3.5 Initialize device registers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some drivers will need specific "capability" fields programmed
+or other "vendor specific" register initialized or reset.
+E.g. clearing pending interrupts.
+
+
+3.6 Register IRQ handler
+~~~~~~~~~~~~~~~~~~~~~~~~
+While calling request_irq() is the the last step described here,
+this is often just another intermediate step to initialize a device.
+This step can often be deferred until the device is opened for use.
+
+All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
+and use the devid to map IRQs to devices (remember that all PCI IRQ lines
+can be shared).
+
+request_irq() will associate an interrupt handler and device handle
+with an interrupt number. Historically interrupt numbers represent
+IRQ lines which run from the PCI device to the Interrupt controller.
+With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
+
+request_irq() also enables the interrupt. Make sure the device is
+quiesced and does not have any interrupts pending before registering
+the interrupt handler.
+
+MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
+which deliver interrupts to the CPU via a DMA write to a Local APIC.
+The fundamental difference between MSI and MSI-X is how multiple
+"vectors" get allocated. MSI requires contiguous blocks of vectors
+while MSI-X can allocate several individual ones.
+
+MSI capability can be enabled by calling pci_enable_msi() or
+pci_enable_msix() before calling request_irq(). This causes
+the PCI support to program CPU vector data into the PCI device
+capability registers.
+
+If your PCI device supports both, try to enable MSI-X first.
+Only one can be enabled at a time. Many architectures, chip-sets,
+or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
+will fail. This is important to note since many drivers have
+two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
+They choose which handler to register with request_irq() based on the
+return value from pci_enable_msi/msix().
+
+There are (at least) two really good reasons for using MSI:
+1) MSI is an exclusive interrupt vector by definition.
+ This means the interrupt handler doesn't have to verify
+ its device caused the interrupt.
+
+2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
+ to be visible to the host CPU(s) when the MSI is delivered. This
+ is important for both data coherency and avoiding stale control data.
+ This guarantee allows the driver to omit MMIO reads to flush
+ the DMA stream.
+
+See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
+of MSI/MSI-X usage.
+
+
+
+4. PCI device shutdown
+~~~~~~~~~~~~~~~~~~~~~~~
+
+When a PCI device driver is being unloaded, most of the following
+steps need to be performed:
+
+ Disable the device from generating IRQs
+ Release the IRQ (free_irq())
+ Stop all DMA activity
+ Release DMA buffers (both streaming and consistent)
+ Unregister from other subsystems (e.g. scsi or netdev)
+ Disable device from responding to MMIO/IO Port addresses
+ Release MMIO/IO Port resource(s)
+
+
+4.1 Stop IRQs on the device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+How to do this is chip/device specific. If it's not done, it opens
+the possibility of a "screaming interrupt" if (and only if)
+the IRQ is shared with another device.
+
+When the shared IRQ handler is "unhooked", the remaining devices
+using the same IRQ line will still need the IRQ enabled. Thus if the
+"unhooked" device asserts IRQ line, the system will respond assuming
+it was one of the remaining devices asserted the IRQ line. Since none
+of the other devices will handle the IRQ, the system will "hang" until
+it decides the IRQ isn't going to get handled and masks the IRQ (100,000
+iterations later). Once the shared IRQ is masked, the remaining devices
+will stop functioning properly. Not a nice situation.
+
+This is another reason to use MSI or MSI-X if it's available.
+MSI and MSI-X are defined to be exclusive interrupts and thus
+are not susceptible to the "screaming interrupt" problem.
+
+
+4.2 Release the IRQ
+~~~~~~~~~~~~~~~~~~~
+Once the device is quiesced (no more IRQs), one can call free_irq().
+This function will return control once any pending IRQs are handled,
+"unhook" the drivers IRQ handler from that IRQ, and finally release
+the IRQ if no one else is using it.
+
+
+4.3 Stop all DMA activity
+~~~~~~~~~~~~~~~~~~~~~~~~~
+It's extremely important to stop all DMA operations BEFORE attempting
+to deallocate DMA control data. Failure to do so can result in memory
+corruption, hangs, and on some chip-sets a hard crash.
-4. How to access PCI config space
+Stopping DMA after stopping the IRQs can avoid races where the
+IRQ handler might restart DMA engines.
+
+While this step sounds obvious and trivial, several "mature" drivers
+didn't get this step right in the past.
+
+
+4.4 Release DMA buffers
+~~~~~~~~~~~~~~~~~~~~~~~
+Once DMA is stopped, clean up streaming DMA first.
+I.e. unmap data buffers and return buffers to "upstream"
+owners if there is one.
+
+Then clean up "consistent" buffers which contain the control data.
+
+See Documentation/DMA-API.txt for details on unmapping interfaces.
+
+
+4.5 Unregister from other subsystems
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Most low level PCI device drivers support some other subsystem
+like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
+driver isn't losing resources from that other subsystem.
+If this happens, typically the symptom is an Oops (panic) when
+the subsystem attempts to call into a driver that has been unloaded.
+
+
+4.6 Disable Device from responding to MMIO/IO Port addresses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+io_unmap() MMIO or IO Port resources and then call pci_disable_device().
+This is the symmetric opposite of pci_enable_device().
+Do not access device registers after calling pci_disable_device().
+
+
+4.7 Release MMIO/IO Port Resource(s)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Call pci_release_region() to mark the MMIO or IO Port range as available.
+Failure to do so usually results in the inability to reload the driver.
+
+
+
+5. How to access PCI config space
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- You can use pci_(read|write)_config_(byte|word|dword) to access the config
+
+You can use pci_(read|write)_config_(byte|word|dword) to access the config
space of a device represented by struct pci_dev *. All these functions return 0
when successful or an error code (PCIBIOS_...) which can be translated to a text
string by pcibios_strerror. Most drivers expect that accesses to valid PCI
devices don't fail.
- If you don't have a struct pci_dev available, you can call
+If you don't have a struct pci_dev available, you can call
pci_bus_(read|write)_config_(byte|word|dword) to access a given device
and function on that bus.
- If you access fields in the standard portion of the config header, please
+If you access fields in the standard portion of the config header, please
use symbolic names of locations and bits declared in <linux/pci.h>.
- If you need to access Extended PCI Capability registers, just call
+If you need to access Extended PCI Capability registers, just call
pci_find_capability() for the particular capability and it will find the
corresponding register block for you.
-5. Addresses and interrupts
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Memory and port addresses and interrupt numbers should NOT be read from the
-config space. You should use the values in the pci_dev structure as they might
-have been remapped by the kernel.
-
- See Documentation/IO-mapping.txt for how to access device memory.
-
- The device driver needs to call pci_request_region() to make sure
-no other device is already using the same resource. The driver is expected
-to determine MMIO and IO Port resource availability _before_ calling
-pci_enable_device(). Conversely, drivers should call pci_release_region()
-_after_ calling pci_disable_device(). The idea is to prevent two devices
-colliding on the same address range.
-
-Generic flavors of pci_request_region() are request_mem_region()
-(for MMIO ranges) and request_region() (for IO Port ranges).
-Use these for address resources that are not described by "normal" PCI
-interfaces (e.g. BAR).
-
- All interrupt handlers should be registered with IRQF_SHARED and use the devid
-to map IRQs to devices (remember that all PCI interrupts are shared).
-
6. Other interesting functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
pci_find_slot() Find pci_dev corresponding to given bus and
slot numbers.
pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
@@ -247,11 +560,12 @@ pci_set_mwi() Enable Memory-Write-Invalidate transactions.
pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
+
7. Miscellaneous hints
~~~~~~~~~~~~~~~~~~~~~~
-When displaying PCI slot names to the user (for example when a driver wants
-to tell the user what card has it found), please use pci_name(pci_dev)
-for this purpose.
+
+When displaying PCI device names to the user (for example when a driver wants
+to tell the user what card has it found), please use pci_name(pci_dev).
Always refer to the PCI devices by a pointer to the pci_dev structure.
All PCI layer functions use this identification and it's the only
@@ -259,31 +573,113 @@ reasonable one. Don't use bus/slot/function numbers except for very
special purposes -- on systems with multiple primary buses their semantics
can be pretty complex.
-If you're going to use PCI bus mastering DMA, take a look at
-Documentation/DMA-mapping.txt.
-
Don't try to turn on Fast Back to Back writes in your driver. All devices
on the bus need to be capable of doing it, so this is something which needs
to be handled by platform and generic code, not individual drivers.
+
8. Vendor and device identifications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-For the future, let's avoid adding device ids to include/linux/pci_ids.h.
-PCI_VENDOR_ID_xxx for vendors, and a hex constant for device ids.
+One is not not required to add new device ids to include/linux/pci_ids.h.
+Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
+
+PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
+hex numbers (vendor controlled) and normally used only in a single
+location, the pci_device_id table.
+
+Please DO submit new vendor/device ids to pciids.sourceforge.net project.
+
-Rationale: PCI_VENDOR_ID_xxx constants are re-used, but device ids are not.
- Further, device ids are arbitrary hex numbers, normally used only in a
- single location, the pci_device_id table.
9. Obsolete functions
~~~~~~~~~~~~~~~~~~~~~
+
There are several functions which you might come across when trying to
port an old driver to the new PCI interface. They are no longer present
in the kernel as they aren't compatible with hotplug or PCI domains or
having sane locking.
-pci_find_device() Superseded by pci_get_device()
-pci_find_subsys() Superseded by pci_get_subsys()
-pci_find_slot() Superseded by pci_get_slot()
+pci_find_device() Superseded by pci_get_device()
+pci_find_subsys() Superseded by pci_get_subsys()
+pci_find_slot() Superseded by pci_get_slot()
+
+
+The alternative is the traditional PCI device driver that walks PCI
+device lists. This is still possible but discouraged.
+
+
+
+10. pci_enable_device_bars() and Legacy I/O Port space
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Large servers may not be able to provide I/O port resources to all PCI
+devices. I/O Port space is only 64KB on Intel Architecture[1] and is
+likely also fragmented since the I/O base register of PCI-to-PCI
+bridge will usually be aligned to a 4KB boundary[2]. On such systems,
+pci_enable_device() and pci_request_region() will fail when
+attempting to enable I/O Port regions that don't have I/O Port
+resources assigned.
+
+Fortunately, many PCI devices which request I/O Port resources also
+provide access to the same registers via MMIO BARs. These devices can
+be handled without using I/O port space and the drivers typically
+offer a CONFIG_ option to only use MMIO regions
+(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port
+interface for legacy OSes and will work when I/O port resources are not
+assigned. The "PCI Local Bus Specification Revision 3.0" discusses
+this on p.44, "IMPLEMENTATION NOTE".
+
+If your PCI device driver doesn't need I/O port resources assigned to
+I/O Port BARs, you should use pci_enable_device_bars() instead of
+pci_enable_device() in order not to enable I/O port regions for the
+corresponding devices. In addition, you should use
+pci_request_selected_regions() and pci_release_selected_regions()
+instead of pci_request_regions()/pci_release_regions() in order not to
+request/release I/O port regions for the corresponding devices.
+
+[1] Some systems support 64KB I/O port space per PCI segment.
+[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base.
+
+
+
+11. MMIO Space and "Write Posting"
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Converting a driver from using I/O Port space to using MMIO space
+often requires some additional changes. Specifically, "write posting"
+needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
+already do this. I/O Port space guarantees write transactions reach the PCI
+device before the CPU can continue. Writes to MMIO space allow the CPU
+to continue before the transaction reaches the PCI device. HW weenies
+call this "Write Posting" because the write completion is "posted" to
+the CPU before the transaction has reached its destination.
+
+Thus, timing sensitive code should add readl() where the CPU is
+expected to wait before doing other work. The classic "bit banging"
+sequence works fine for I/O Port space:
+
+ for (i = 8; --i; val >>= 1) {
+ outb(val & 1, ioport_reg); /* write bit */
+ udelay(10);
+ }
+
+The same sequence for MMIO space should be:
+
+ for (i = 8; --i; val >>= 1) {
+ writeb(val & 1, mmio_reg); /* write bit */
+ readb(safe_mmio_reg); /* flush posted write */
+ udelay(10);
+ }
+
+It is important that "safe_mmio_reg" not have any side effects that
+interferes with the correct operation of the device.
+
+Another case to watch out for is when resetting a PCI device. Use PCI
+Configuration space reads to flush the writel(). This will gracefully
+handle the PCI master abort on all platforms if the PCI device is
+expected to not respond to a readl(). Most x86 platforms will allow
+MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
+(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
+
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index b3bd36668db..33994271cb3 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1703,29 +1703,32 @@ platforms are moved over to use the flattened-device-tree model.
Required properties:
- device_type : has to be "rom"
- - compatible : Should specify what this ROM device is compatible with
- (i.e. "onenand"). Currently, this is most likely to be "direct-mapped"
- (which corresponds to the MTD physmap mapping driver).
- - regs : Offset and length of the register set (or memory mapping) for
+ - compatible : Should specify what this flash device is compatible with.
+ Currently, this is most likely to be "direct-mapped" (which
+ corresponds to the MTD physmap mapping driver).
+ - reg : Offset and length of the register set (or memory mapping) for
the device.
+ - bank-width : Width of the flash data bus in bytes. Required
+ for the NOR flashes (compatible == "direct-mapped" and others) ONLY.
Recommended properties :
- - bank-width : Width of the flash data bus in bytes. Required
- for the NOR flashes (compatible == "direct-mapped" and others) ONLY.
- partitions : Several pairs of 32-bit values where the first value is
partition's offset from the start of the device and the second one is
partition size in bytes with LSB used to signify a read only
- partititon (so, the parition size should always be an even number).
+ partition (so, the parition size should always be an even number).
- partition-names : The list of concatenated zero terminated strings
representing the partition names.
+ - probe-type : The type of probe which should be done for the chip
+ (JEDEC vs CFI actually). Valid ONLY for NOR flashes.
Example:
flash@ff000000 {
device_type = "rom";
compatible = "direct-mapped";
- regs = <ff000000 01000000>;
+ probe-type = "CFI";
+ reg = <ff000000 01000000>;
bank-width = <4>;
partitions = <00000000 00f80000
00f80000 00080001>;
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
index d077d764f82..69f016f02bb 100644
--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
@@ -4,6 +4,12 @@ MPC52xx Device Tree Bindings
(c) 2006 Secret Lab Technologies Ltd
Grant Likely <grant.likely at secretlab.ca>
+********** DRAFT ***********
+* WARNING: Do not depend on the stability of these bindings just yet.
+* The MPC5200 device tree conventions are still in flux
+* Keep an eye on the linuxppc-dev mailing list for more details
+********** DRAFT ***********
+
I - Introduction
================
Boards supported by the arch/powerpc architecture require device tree be
@@ -157,8 +163,8 @@ rtc@<addr> rtc *-rtc Real time clock
mscan@<addr> mscan *-mscan CAN bus controller
pci@<addr> pci *-pci PCI bridge
serial@<addr> serial *-psc-uart PSC in serial mode
-i2s@<addr> i2s *-psc-i2s PSC in i2s mode
-ac97@<addr> ac97 *-psc-ac97 PSC in ac97 mode
+i2s@<addr> sound *-psc-i2s PSC in i2s mode
+ac97@<addr> sound *-psc-ac97 PSC in ac97 mode
spi@<addr> spi *-psc-spi PSC in spi mode
irda@<addr> irda *-psc-irda PSC in IrDA mode
spi@<addr> spi *-spi MPC52xx spi device
diff --git a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt
index 77bf450ec39..e938c442277 100644
--- a/Documentation/s390/driver-model.txt
+++ b/Documentation/s390/driver-model.txt
@@ -18,11 +18,18 @@ devices/
- 0.0.0002/
- 0.1.0000/0.1.1234/
...
+ - defunct/
In this example, device 0815 is accessed via subchannel 0 in subchannel set 0,
device 4711 via subchannel 1 in subchannel set 0, and subchannel 2 is a non-I/O
subchannel. Device 1234 is accessed via subchannel 0 in subchannel set 1.
+The subchannel named 'defunct' does not represent any real subchannel on the
+system; it is a pseudo subchannel where disconnnected ccw devices are moved to
+if they are displaced by another ccw device becoming operational on their
+former subchannel. The ccw devices will be moved again to a proper subchannel
+if they become operational again on that subchannel.
+
You should address a ccw device via its bus id (e.g. 0.0.4711); the device can
be found under bus/ccw/devices/.
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
index 3367130e64f..dc8e44fc650 100644
--- a/Documentation/scsi/aacraid.txt
+++ b/Documentation/scsi/aacraid.txt
@@ -11,43 +11,42 @@ the original).
Supported Cards/Chipsets
-------------------------
PCI ID (pci.ids) OEM Product
- 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware)
- 9005:0284:9005:0284 Adaptec Tomcat (3410S with arc firmware)
9005:0285:9005:0285 Adaptec 2200S (Vulcan)
9005:0285:9005:0286 Adaptec 2120S (Crusader)
9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m)
9005:0285:9005:0288 Adaptec 3230S (Harrier)
9005:0285:9005:0289 Adaptec 3240S (Tornado)
9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk)
- 9005:0285:9005:028b Adaptec 2025ZCR (Terminator)
+ 9005:0285:9005:028b Adaptec 2025ZCR (Terminator)
9005:0286:9005:028c Adaptec 2230S (Lancer)
9005:0286:9005:028c Adaptec 2230SLP (Lancer)
9005:0286:9005:028d Adaptec 2130S (Lancer)
9005:0285:9005:028e Adaptec 2020SA (Skyhawk)
- 9005:0285:9005:028f Adaptec 2025SA (Terminator)
+ 9005:0285:9005:028f Adaptec 2025SA (Terminator)
9005:0285:9005:0290 Adaptec 2410SA (Jaguar)
- 9005:0285:103c:3227 Adaptec 2610SA (Bearcat HP release)
- 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)
+ 9005:0285:103c:3227 Adaptec 2610SA (Bearcat HP release)
+ 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)
9005:0285:9005:0296 Adaptec 2240S (SabreExpress)
9005:0285:9005:0292 Adaptec 2810SA (Corsair-8)
- 9005:0285:9005:0294 Adaptec Prowler
- 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark)
- 9005:0285:9005:0298 Adaptec 4000SAS (BlackBird)
+ 9005:0285:9005:0297 Adaptec 4005 (AvonPark)
+ 9005:0285:9005:0298 Adaptec 4000 (BlackBird)
9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X)
9005:0285:9005:029a Adaptec 4805SAS (Marauder-E)
9005:0286:9005:029b Adaptec 2820SA (Intruder)
9005:0286:9005:029c Adaptec 2620SA (Intruder)
9005:0286:9005:029d Adaptec 2420SA (Intruder HP release)
- 9005:0286:9005:02a2 Adaptec 3800SAS (Hurricane44)
- 9005:0286:9005:02a7 Adaptec 3805SAS (Hurricane80)
- 9005:0286:9005:02a8 Adaptec 3400SAS (Hurricane40)
- 9005:0286:9005:02ac Adaptec 1800SAS (Typhoon44)
- 9005:0286:9005:02b3 Adaptec 2400SAS (Hurricane40lm)
- 9005:0285:9005:02b5 Adaptec ASR5800 (Voodoo44)
- 9005:0285:9005:02b6 Adaptec ASR5805 (Voodoo80)
- 9005:0285:9005:02b7 Adaptec ASR5808 (Voodoo08)
+ 9005:0286:9005:02ac Adaptec 1800 (Typhoon44)
+ 9005:0285:9005:02b5 Adaptec 5445 (Voodoo44)
+ 9005:0285:9005:02b6 Adaptec 5805 (Voodoo80)
+ 9005:0285:9005:02b7 Adaptec 5085 (Voodoo08)
+ 9005:0285:9005:02bb Adaptec 3405 (Marauder40LP)
+ 9005:0285:9005:02bc Adaptec 3805 (Marauder80LP)
+ 9005:0285:9005:02c7 Adaptec 3085 (Marauder08ELP)
+ 9005:0285:9005:02bd Adaptec 31205 (Marauder120)
+ 9005:0285:9005:02be Adaptec 31605 (Marauder160)
+ 9005:0285:9005:02c3 Adaptec 51205 (Voodoo120)
+ 9005:0285:9005:02c4 Adaptec 51605 (Voodoo160)
1011:0046:9005:0364 Adaptec 5400S (Mustang)
- 1011:0046:9005:0365 Adaptec 5400S (Mustang)
9005:0287:9005:0800 Adaptec Themisto (Jupiter)
9005:0200:9005:0200 Adaptec Themisto (Jupiter)
9005:0286:9005:0800 Adaptec Callisto (Jupiter)
@@ -68,21 +67,32 @@ Supported Cards/Chipsets
9005:0285:17aa:0287 Legend S230 (Vulcan)
9005:0285:9005:0290 IBM ServeRAID 7t (Jaguar)
9005:0285:1014:02F2 IBM ServeRAID 8i (AvonPark)
- 9005:0285:1014:0312 IBM ServeRAID 8i (AvonParkLite)
9005:0286:1014:9540 IBM ServeRAID 8k/8k-l4 (AuroraLite)
9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora)
- 9005:0286:1014:034d IBM ServeRAID 8s (Hurricane)
- 9005:0286:9005:029e ICP ICP9024R0 (Lancer)
- 9005:0286:9005:029f ICP ICP9014R0 (Lancer)
+ 9005:0285:1014:034d IBM ServeRAID 8s (Marauder-E)
+ 9005:0286:9005:029e ICP ICP9024RO (Lancer)
+ 9005:0286:9005:029f ICP ICP9014RO (Lancer)
9005:0286:9005:02a0 ICP ICP9047MA (Lancer)
9005:0286:9005:02a1 ICP ICP9087MA (Lancer)
- 9005:0286:9005:02a3 ICP ICP5445AU (Hurricane44)
- 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X)
- 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E)
+ 9005:0285:9005:02a4 ICP ICP9085LI (Marauder-X)
+ 9005:0285:9005:02a5 ICP ICP5085BR (Marauder-E)
9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6)
- 9005:0286:9005:02a9 ICP ICP5085AU (Hurricane80)
- 9005:0286:9005:02aa ICP ICP5045AU (Hurricane40)
- 9005:0286:9005:02b4 ICP ICP5045AL (Hurricane40lm)
+ 9005:0285:9005:02b2 ICP (Voodoo 8 internal 8 external)
+ 9005:0285:9005:02b8 ICP ICP5445SL (Voodoo44)
+ 9005:0285:9005:02b9 ICP ICP5085SL (Voodoo80)
+ 9005:0285:9005:02ba ICP ICP5805SL (Voodoo08)
+ 9005:0285:9005:02bf ICP ICP5045BL (Marauder40LP)
+ 9005:0285:9005:02c0 ICP ICP5085BL (Marauder80LP)
+ 9005:0285:9005:02c8 ICP ICP5805BL (Marauder08ELP)
+ 9005:0285:9005:02c1 ICP ICP5125BR (Marauder120)
+ 9005:0285:9005:02c2 ICP ICP5165BR (Marauder160)
+ 9005:0285:9005:02c5 ICP ICP5125SL (Voodoo120)
+ 9005:0285:9005:02c6 ICP ICP5165SL (Voodoo160)
+ 9005:0286:9005:02ab (Typhoon40)
+ 9005:0286:9005:02ad (Aurora ARK)
+ 9005:0286:9005:02ae (Aurora Lite ARK)
+ 9005:0285:9005:02b0 (Sunrise Lake ARK)
+ 9005:0285:9005:02b1 Adaptec (Voodoo 8 internal 8 external)
People
-------------------------
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 077fbe25ebf..ccd0a953953 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -927,7 +927,7 @@
<informalexample>
<programlisting>
<![CDATA[
- struct mychip *chip = (struct mychip *)card->private_data;
+ struct mychip *chip = card->private_data;
]]>
</programlisting>
</informalexample>
@@ -1095,7 +1095,7 @@
/* release the irq */
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
/* release the i/o ports & memory */
pci_release_regions(chip->pci);
/* disable the PCI entry */
@@ -1148,7 +1148,7 @@
}
chip->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_mychip_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "My Chip", chip)) {
+ IRQF_SHARED, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1387,7 +1387,7 @@
<programlisting>
<![CDATA[
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
]]>
</programlisting>
</informalexample>
diff --git a/Documentation/spi/pxa2xx b/Documentation/spi/pxa2xx
index a1e0ee20f59..f9717fe9bd8 100644
--- a/Documentation/spi/pxa2xx
+++ b/Documentation/spi/pxa2xx
@@ -102,7 +102,7 @@ struct pxa2xx_spi_chip {
u8 tx_threshold;
u8 rx_threshold;
u8 dma_burst_size;
- u32 timeout_microsecs;
+ u32 timeout;
u8 enable_loopback;
void (*cs_control)(u32 command);
};
@@ -121,7 +121,7 @@ the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
to determine the correct value. An SSP configured for byte-wide transfers would
use a value of 8.
-The "pxa2xx_spi_chip.timeout_microsecs" fields is used to efficiently handle
+The "pxa2xx_spi_chip.timeout" fields is used to efficiently handle
trailing bytes in the SSP receiver fifo. The correct value for this field is
dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
slave device. Please note that the PXA2xx SSP 1 does not support trailing byte
@@ -162,18 +162,18 @@ static void cs8405a_cs_control(u32 command)
}
static struct pxa2xx_spi_chip cs8415a_chip_info = {
- .tx_threshold = 12, /* SSP hardward FIFO threshold */
- .rx_threshold = 4, /* SSP hardward FIFO threshold */
+ .tx_threshold = 8, /* SSP hardward FIFO threshold */
+ .rx_threshold = 8, /* SSP hardward FIFO threshold */
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
- .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+ .timeout = 235, /* See Intel documentation */
.cs_control = cs8415a_cs_control, /* Use external chip select */
};
static struct pxa2xx_spi_chip cs8405a_chip_info = {
- .tx_threshold = 12, /* SSP hardward FIFO threshold */
- .rx_threshold = 4, /* SSP hardward FIFO threshold */
+ .tx_threshold = 8, /* SSP hardward FIFO threshold */
+ .rx_threshold = 8, /* SSP hardward FIFO threshold */
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
- .timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
+ .timeout = 235, /* See Intel documentation */
.cs_control = cs8405a_cs_control, /* Use external chip select */
};
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index e0188a23fd5..61613166981 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -1,6 +1,6 @@
Linux Magic System Request Key Hacks
-Documentation for sysrq.c version 1.15
-Last update: $Date: 2001/01/28 10:15:59 $
+Documentation for sysrq.c
+Last update: 2007-JAN-06
* What is the magic SysRq key?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -35,7 +35,7 @@ You can set the value in the file by the following command:
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.
+allowed (by a user with admin privileges).
* How do I use the magic SysRq key?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -58,7 +58,7 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,
On other - If you know of the key combos for other architectures, please
let me know so I can add them to this section.
-On all - write a character to /proc/sysrq-trigger. eg:
+On all - write a character to /proc/sysrq-trigger. e.g.:
echo t > /proc/sysrq-trigger
@@ -74,6 +74,8 @@ On all - write a character to /proc/sysrq-trigger. eg:
'c' - Will perform a kexec reboot in order to take a crashdump.
+'d' - Shows all locks that are held.
+
'o' - Will shut your system off (if configured and supported).
's' - Will attempt to sync all mounted filesystems.
@@ -87,38 +89,43 @@ On all - write a character to /proc/sysrq-trigger. eg:
'm' - Will dump current memory info to your console.
+'n' - Used to make RT tasks nice-able
+
'v' - Dumps Voyager SMP processor info to your console.
+'w' - Dumps tasks that are in uninterruptable (blocked) state.
+
+'x' - Used by xmon interface on ppc/powerpc platforms.
+
'0'-'9' - Sets the console log level, controlling which kernel messages
will be printed to your console. ('0', for example would make
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
+'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.
+'g' - Used by kgdb on ppc platforms.
-'l' - Send a SIGKILL to all processes, INCLUDING init. (Your system
- will be non-functional after this.)
+'i' - Send a SIGKILL to all processes, except for init.
-'h' - Will display help ( actually any other key than those listed
+'h' - Will display help (actually any other key than those listed
above will display help. but 'h' is easy to remember :-)
* Okay, so what can I use them for?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Well, un'R'aw is very handy when your X server or a svgalib program crashes.
-sa'K' (Secure Access Key) is useful when you want to be sure there are no
-trojan program is running at console and which could grab your password
-when you would try to login. It will kill all programs on given console
-and thus letting you make sure that the login prompt you see is actually
+sa'K' (Secure Access Key) is useful when you want to be sure there is no
+trojan program running at console which could grab your password
+when you would try to login. It will kill all programs on given console,
+thus letting you make sure that the login prompt you see is actually
the one from init, not some trojan program.
IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
IMPORTANT: c2 compliant system, and it should not be mistaken as :IMPORTANT
IMPORTANT: such. :IMPORTANT
- It seems other find it useful as (System Attention Key) which is
+ It seems others find it useful as (System Attention Key) which is
useful when you want to exit a program that will not let you switch consoles.
(For example, X or a svgalib program.)
@@ -139,8 +146,8 @@ OK or Done message...)
Again, the unmount (remount read-only) hasn't taken place until you see the
"OK" and "Done" message appear on the screen.
-The loglevel'0'-'9' is useful when your console is being flooded with
-kernel messages you do not want to see. Setting '0' will prevent all but
+The loglevels '0'-'9' are useful when your console is being flooded with
+kernel messages you do not want to see. Selecting '0' will prevent all but
the most urgent kernel messages from reaching your console. (They will
still be logged if syslogd/klogd are alive, though.)
@@ -152,7 +159,7 @@ processes.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
That happens to me, also. I've found that tapping shift, alt, and control
on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (ie, something like alt-sysrq-z). Switching to another
+will fix the problem. (i.e., something like alt-sysrq-z). Switching to another
virtual console (ALT+Fn) and then back again should also help.
* I hit SysRq, but nothing seems to happen, what's wrong?
@@ -174,11 +181,11 @@ handler function you will use, B) a help_msg string, that will print when SysRQ
prints help, and C) an action_msg string, that will print right before your
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
-After the sysrq_key_op is created, you can call the macro
-register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
-sysrq.h, this will register the operation pointed to by 'op_p' at table
-key 'key', if that slot in the table is blank. At module unload time, you must
-call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
+After the sysrq_key_op is created, you can call the kernel function
+register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
+register the operation pointed to by 'op_p' at table key 'key',
+if that slot in the table is blank. At module unload time, you must call
+the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
it is currently registered in that slot. This is in case the slot has been
overwritten since you registered it.
@@ -186,15 +193,12 @@ overwritten since you registered it.
The Magic SysRQ system works by registering key operations against a key op
lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
a number of operations registered into it at compile time, but is mutable,
-and 4 functions are exported for interface to it: __sysrq_lock_table,
-__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The
-functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined
-in the header itself, and the REGISTER and UNREGISTER macros are built from
-these. More complex (and dangerous!) manipulations of the table are possible
-using these functions, but you must be careful to always lock the table before
-you read or write from it, and to unlock it again when you are done. (And of
-course, to never ever leave an invalid pointer in the table). Null pointers in
-the table are always safe :)
+and 2 functions are exported for interface to it:
+ register_sysrq_key and unregister_sysrq_key.
+Of course, never ever leave an invalid pointer in the table. I.e., when
+your module that called register_sysrq_key() exits, it must call
+unregister_sysrq_key() to clean up the sysrq key table entry that it used.
+Null pointers in the table are always safe. :)
If for some reason you feel the need to call the handle_sysrq function from
within a function called by handle_sysrq, you must be aware that you are in
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
index dab56604745..5f799e612e0 100644
--- a/Documentation/tty.txt
+++ b/Documentation/tty.txt
@@ -39,28 +39,37 @@ Line Discipline Methods
TTY side interfaces:
+open() - Called when the line discipline is attached to
+ the terminal. No other call into the line
+ discipline for this tty will occur until it
+ completes successfully. Can sleep.
+
close() - This is called on a terminal when the line
discipline is being unplugged. At the point of
execution no further users will enter the
ldisc code for this tty. Can sleep.
-open() - Called when the line discipline is attached to
- the terminal. No other call into the line
- discipline for this tty will occur until it
- completes successfully. Can sleep.
+hangup() - Called when the tty line is hung up.
+ The line discipline should cease I/O to the tty.
+ No further calls into the ldisc code will occur.
+ Can sleep.
write() - A process is writing data through the line
discipline. Multiple write calls are serialized
by the tty layer for the ldisc. May sleep.
-flush_buffer() - May be called at any point between open and close.
+flush_buffer() - (optional) May be called at any point between
+ open and close, and instructs the line discipline
+ to empty its input buffer.
-chars_in_buffer() - Report the number of bytes in the buffer.
+chars_in_buffer() - (optional) Report the number of bytes in the input
+ buffer.
-set_termios() - Called on termios structure changes. The caller
- passes the old termios data and the current data
- is in the tty. Called under the termios semaphore so
- allowed to sleep. Serialized against itself only.
+set_termios() - (optional) Called on termios structure changes.
+ The caller passes the old termios data and the
+ current data is in the tty. Called under the
+ termios semaphore so allowed to sleep. Serialized
+ against itself only.
read() - Move data from the line discipline to the user.
Multiple read calls may occur in parallel and the
@@ -92,6 +101,88 @@ write_wakeup() - May be called at any point between open and close.
this function. In such a situation defer it.
+Driver Access
+
+Line discipline methods can call the following methods of the underlying
+hardware driver through the function pointers within the tty->driver
+structure:
+
+write() Write a block of characters to the tty device.
+ Returns the number of characters accepted.
+
+put_char() Queues a character for writing to the tty device.
+ If there is no room in the queue, the character is
+ ignored.
+
+flush_chars() (Optional) If defined, must be called after
+ queueing characters with put_char() in order to
+ start transmission.
+
+write_room() Returns the numbers of characters the tty driver
+ will accept for queueing to be written.
+
+ioctl() Invoke device specific ioctl.
+ Expects data pointers to refer to userspace.
+ Returns ENOIOCTLCMD for unrecognized ioctl numbers.
+
+set_termios() Notify the tty driver that the device's termios
+ settings have changed. New settings are in
+ tty->termios. Previous settings should be passed in
+ the "old" argument.
+
+throttle() Notify the tty driver that input buffers for the
+ line discipline are close to full, and it should
+ somehow signal that no more characters should be
+ sent to the tty.
+
+unthrottle() Notify the tty driver that characters can now be
+ sent to the tty without fear of overrunning the
+ input buffers of the line disciplines.
+
+stop() Ask the tty driver to stop outputting characters
+ to the tty device.
+
+start() Ask the tty driver to resume sending characters
+ to the tty device.
+
+hangup() Ask the tty driver to hang up the tty device.
+
+break_ctl() (Optional) Ask the tty driver to turn on or off
+ BREAK status on the RS-232 port. If state is -1,
+ then the BREAK status should be turned on; if
+ state is 0, then BREAK should be turned off.
+ If this routine is not implemented, use ioctls
+ TIOCSBRK / TIOCCBRK instead.
+
+wait_until_sent() Waits until the device has written out all of the
+ characters in its transmitter FIFO.
+
+send_xchar() Send a high-priority XON/XOFF character to the device.
+
+
+Flags
+
+Line discipline methods have access to tty->flags field containing the
+following interesting flags:
+
+TTY_THROTTLED Driver input is throttled. The ldisc should call
+ tty->driver->unthrottle() in order to resume
+ reception when it is ready to process more data.
+
+TTY_DO_WRITE_WAKEUP If set, causes the driver to call the ldisc's
+ write_wakeup() method in order to resume
+ transmission when it can accept more data
+ to transmit.
+
+TTY_IO_ERROR If set, causes all subsequent userspace read/write
+ calls on the tty to fail, returning -EIO.
+
+TTY_OTHER_CLOSED Device is a pty and the other side has closed.
+
+TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
+ smaller chunks.
+
+
Locking
Callers to the line discipline functions from the tty layer are required to
diff --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS
index 01e7f857ef3..27a721635f9 100644
--- a/Documentation/usb/CREDITS
+++ b/Documentation/usb/CREDITS
@@ -21,7 +21,7 @@ difficult to maintain, add yourself with a patch if desired.
Bill Ryder <bryder@sgi.com>
Thomas Sailer <sailer@ife.ee.ethz.ch>
Gregory P. Smith <greg@electricrain.com>
- Linus Torvalds <torvalds@osdl.org>
+ Linus Torvalds <torvalds@linux-foundation.org>
Roman Weissgaerber <weissg@vienna.at>
<Kazuki.Yasumatsu@fujixerox.co.jp>
diff --git a/Documentation/usb/acm.txt b/Documentation/usb/acm.txt
index 737d6104c3f..17f5c2e1a57 100644
--- a/Documentation/usb/acm.txt
+++ b/Documentation/usb/acm.txt
@@ -46,6 +46,10 @@ Abstract Control Model (USB CDC ACM) specification.
3Com USR ISDN Pro TA
+ Some cell phones also connect via USB. I know the following phones work:
+
+ SonyEricsson K800i
+
Unfortunately many modems and most ISDN TAs use proprietary interfaces and
thus won't work with this drivers. Check for ACM compliance before buying.
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 8755b3e7b09..62e32b49cec 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -43,7 +43,7 @@
42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019]
43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1,12ab:2300]
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54]
- 45 -> KWorld HardwareMpegTV XPert [17de:0840]
+ 45 -> KWorld HardwareMpegTV XPert [17de:0840,1421:0305]
46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44]
47 -> pcHDTV HD5500 HDTV [7063:5500]
48 -> Kworld MCE 200 Deluxe [17de:0841]
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 53ce6a39083..f6201cc37ec 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -76,7 +76,7 @@
75 -> AVerMedia AVerTVHD MCE A180 [1461:1044]
76 -> SKNet MonsterTV Mobile [1131:4ee9]
77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e]
- 78 -> ASUSTeK P7131 Dual [1043:4862]
+ 78 -> ASUSTeK P7131 Dual [1043:4862,1043:4876]
79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
80 -> ASUS Digimatrix TV [1043:0210]
81 -> Philips Tiger reference design [1131:2018]
@@ -99,3 +99,8 @@
98 -> Proteus Pro 2309 [0919:2003]
99 -> AVerMedia TV Hybrid A16AR [1461:2c00]
100 -> Asus Europa2 OEM [1043:4860]
+101 -> Pinnacle PCTV 310i [11bd:002f]
+102 -> Avermedia AVerTV Studio 507 [1461:9715]
+103 -> Compro Videomate DVB-T200A
+104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701]
+105 -> Terratec Cinergy HT PCMCIA [153b:1172]
diff --git a/Documentation/video4linux/cafe_ccic b/Documentation/video4linux/cafe_ccic
new file mode 100644
index 00000000000..88821022a5d
--- /dev/null
+++ b/Documentation/video4linux/cafe_ccic
@@ -0,0 +1,54 @@
+"cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera
+controller. This is the controller found in first-generation OLPC systems,
+and this driver was written with support from the OLPC project.
+
+Current status: the core driver works. It can generate data in YUV422,
+RGB565, and RGB444 formats. (Anybody looking at the code will see RGB32 as
+well, but that is a debugging aid which will be removed shortly). VGA and
+QVGA modes work; CIF is there but the colors remain funky. Only the OV7670
+sensor is known to work with this controller at this time.
+
+To try it out: either of these commands will work:
+
+ mplayer tv:// -tv driver=v4l2:width=640:height=480 -nosound
+ mplayer tv:// -tv driver=v4l2:width=640:height=480:outfmt=bgr16 -nosound
+
+The "xawtv" utility also works; gqcam does not, for unknown reasons.
+
+There are a few load-time options, most of which can be changed after
+loading via sysfs as well:
+
+ - alloc_bufs_at_load: Normally, the driver will not allocate any DMA
+ buffers until the time comes to transfer data. If this option is set,
+ then worst-case-sized buffers will be allocated at module load time.
+ This option nails down the memory for the life of the module, but
+ perhaps decreases the chances of an allocation failure later on.
+
+ - dma_buf_size: The size of DMA buffers to allocate. Note that this
+ option is only consulted for load-time allocation; when buffers are
+ allocated at run time, they will be sized appropriately for the current
+ camera settings.
+
+ - n_dma_bufs: The controller can cycle through either two or three DMA
+ buffers. Normally, the driver tries to use three buffers; on faster
+ systems, however, it will work well with only two.
+
+ - min_buffers: The minimum number of streaming I/O buffers that the driver
+ will consent to work with. Default is one, but, on slower systems,
+ better behavior with mplayer can be achieved by setting to a higher
+ value (like six).
+
+ - max_buffers: The maximum number of streaming I/O buffers; default is
+ ten. That number was carefully picked out of a hat and should not be
+ assumed to actually mean much of anything.
+
+ - flip: If this boolean parameter is set, the sensor will be instructed to
+ invert the video image. Whether it makes sense is determined by how
+ your particular camera is mounted.
+
+Work is ongoing with this driver, stay tuned.
+
+jon
+
+Jonathan Corbet
+corbet@lwn.net
diff --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt
deleted file mode 100644
index 1a1c2d03a5c..00000000000
--- a/Documentation/video4linux/zr36120.txt
+++ /dev/null
@@ -1,162 +0,0 @@
-Driver for Trust Computer Products Framegrabber, version 0.6.1
------- --- ----- -------- -------- ------------ ------- - - -
-
-- ZORAN ------------------------------------------------------
- Author: Pauline Middelink <middelin@polyware.nl>
- Date: 18 September 1999
-Version: 0.6.1
-
-- Description ------------------------------------------------
-
-Video4Linux compatible driver for an unknown brand framegrabber
-(Sold in the Netherlands by TRUST Computer Products) and various
-other zoran zr36120 based framegrabbers.
-
-The card contains a ZR36120 Multimedia PCI Interface and a Philips
-SAA7110 Onechip Frontend videodecoder. There is also an DSP of
-which I have forgotten the number, since i will never get that thing
-to work without specs from the vendor itself.
-
-The SAA711x are capable of processing 6 different video inputs,
-CVBS1..6 and Y1+C1, Y2+C2, Y3+C3. All in 50/60Hz, NTSC, PAL or
-SECAM and delivering a YUV datastream. On my card the input
-'CVBS-0' corresponds to channel CVBS2 and 'S-Video' to Y2+C2.
-
-I have some reports of other cards working with the mentioned
-chip sets. For a list of other working cards please have a look
-at the cards named in the tvcards struct in the beginning of
-zr36120.c
-
-After some testing, I discovered that the carddesigner messed up
-on the I2C interface. The Zoran chip includes 2 lines SDA and SCL
-which (s)he connected reversely. So we have to clock on the SDA
-and r/w data on the SCL pin. Life is fun... Each cardtype now has
-a bit which signifies if you have a card with the same deficiency.
-
-Oh, for the completeness of this story I must mention that my
-card delivers the VSYNC pulse of the SAA chip to GIRQ1, not
-GIRQ0 as some other cards have. This is also incorporated in
-the driver be clearing/setting the 'useirq1' bit in the tvcard
-description.
-
-Another problems of continuous capturing data with a Zoran chip
-is something nasty inside the chip. It effectively halves the
-fps we ought to get... Here is the scenario: capturing frames
-to memory is done in the so-called snapshot mode. In this mode
-the Zoran stops after capturing a frame worth of data and wait
-till the application set GRAB bit to indicate readiness for the
-next frame. After detecting a set bit, the chip neatly waits
-till the start of a frame, captures it and it goes back to off.
-Smart ppl will notice the problem here. Its the waiting on the
-_next_ frame each time we set the GRAB bit... Oh well, 12,5 fps
-is still plenty fast for me.
--- update 28/7/1999 --
-Don't believe a word I just said... Proof is the output
-of `streamer -t 300 -r 25 -f avi15 -o /dev/null`
- ++--+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
- +-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+-
- syncer: done
- writer: done
-(note the /dev/null is prudent here, my system is not able to
- grab /and/ write 25 fps to a file... gifts welcome :) )
-The technical reasoning follows: The zoran completed the last
-frame, the VSYNC goes low, and GRAB is cleared. The interrupt
-routine starts to work since its VSYNC driven, and again
-activates the GRAB bit. A few ms later the VSYNC (re-)rises and
-the zoran starts to work on a new and freshly broadcasted frame....
-
-For pointers I used the specs of both chips. Below are the URLs:
- http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf
- http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf
-Some alternatives for the Philips SAA 7110 datasheet are:
- http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml
- http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part
-
-The documentation has very little on absolute numbers or timings
-needed for the various modes/resolutions, but there are other
-programs you can borrow those from.
-
------- Install --------------------------------------------
-Read the file called TODO. Note its long list of limitations.
-
-Build a kernel with VIDEO4LINUX enabled. Activate the
-BT848 driver; we need this because we have need for the
-other modules (i2c and videodev) it enables.
-
-To install this software, extract it into a suitable directory.
-Examine the makefile and change anything you don't like. Type "make".
-
-After making the modules check if you have the much needed
-/dev/video devices. If not, execute the following 4 lines:
- mknod /dev/video c 81 0
- mknod /dev/video1 c 81 1
- mknod /dev/video2 c 81 2
- mknod /dev/video3 c 81 3
- mknod /dev/video4 c 81 4
-
-After making/checking the devices do:
- modprobe i2c
- modprobe videodev
- modprobe saa7110 (optional)
- modprobe saa7111 (optional)
- modprobe tuner (optional)
- insmod zoran cardtype=<n>
-
-<n> is the cardtype of the card you have. The cardnumber can
-be found in the source of zr36120. Look for tvcards. If your
-card is not there, please try if any other card gives some
-response, and mail me if you got a working tvcard addition.
-
-PS. <TVCard editors behold!)
- Don't forget to set video_input to the number of inputs
- you defined in the video_mux part of the tvcard definition.
- It's a common error to add a channel but not incrementing
- video_input and getting angry with me/v4l/linux/linus :(
-
-You are now ready to test the framegrabber with your favorite
-video4linux compatible tool
-
------- Application ----------------------------------------
-
-This device works with all Video4Linux compatible applications,
-given the limitations in the TODO file.
-
------- API ------------------------------------------------
-
-This uses the V4L interface as of kernel release 2.1.116, and in
-fact has not been tested on any lower version. There are a couple
-of minor differences due to the fact that the amount of data returned
-with each frame varies, and no doubt there are discrepancies due to my
-misunderstanding of the API. I intend to convert this driver to the
-new V4L2 API when it has stabilized more.
-
------- Current state --------------------------------------
-
-The driver is capable of overlaying a video image in screen, and
-even capable of grabbing frames. It uses the BIGPHYSAREA patch
-to allocate lots of large memory blocks when tis patch is
-found in the kernel, but it doesn't need it.
-The consequence is that, when loading the driver as a module,
-the module may tell you it's out of memory, but 'free' says
-otherwise. The reason is simple; the modules wants its memory
-contiguous, not fragmented, and after a long uptime there
-probably isn't a fragment of memory large enough...
-
-The driver uses a double buffering scheme, which should really
-be an n-way buffer, depending on the size of allocated framebuffer
-and the requested grab-size/format.
-This current version also fixes a dead-lock situation during irq
-time, which really, really froze my system... :)
-
-Good luck.
- Pauline
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index dbdcaf68e3e..5c86ed6f044 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -52,6 +52,10 @@ APICs
apicmaintimer. Useful when your PIT timer is totally
broken.
+ disable_8254_timer / enable_8254_timer
+ Enable interrupt 0 timer routing over the 8254 in addition to over
+ the IO-APIC. The kernel tries to set a sensible default.
+
Early Console
syntax: earlyprintk=vga
diff --git a/MAINTAINERS b/MAINTAINERS
index 89ef018cc4b..0ad8803a0c7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -207,16 +207,45 @@ S: Supported
ACPI
P: Len Brown
M: len.brown@intel.com
+M: lenb@kernel.org
L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
-S: Maintained
+S: Supported
+
+ACPI BATTERY DRIVERS
+P: Vladimir P. Lebedev
+M: vladimir.p.lebedev@intel.com
+L: linux-acpi@vger.kernel.org
+W: http://acpi.sourceforge.net/
+S: Supported
+
+ACPI EC DRIVER
+P: Alexey Starikovskiy
+M: alexey.y.starikovskiy@linux.intel.com
+L: linux-acpi@vger.kernel.org
+W: http://acpi.sourceforge.net/
+S: Supported
+
+ACPI FAN DRIVER
+P: Konstantin A. Karasyov
+M: konstantin.a.karasyov@intel.com
+L: linux-acpi@vger.kernel.org
+W: http://acpi.sourceforge.net/
+S: Supported
ACPI PCI HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net
-S: Maintained
+S: Supported
+
+ACPI THERMAL DRIVER
+P: Konstantin A. Karasyov
+M: konstantin.a.karasyov@intel.com
+L: linux-acpi@vger.kernel.org
+W: http://acpi.sourceforge.net/
+S: Supported
AD1816 SOUND DRIVER
P: Thorsten Knabe
@@ -277,7 +306,7 @@ S: Maintained
ALI1563 I2C DRIVER
P: Rudolf Marek
-M: r.marek@sh.cvut.cz
+M: r.marek@assembler.cz
L: i2c@lm-sensors.org
S: Maintained
@@ -296,6 +325,13 @@ L: info-linux@geode.amd.com
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
+AMS (Apple Motion Sensor) DRIVER
+P: Stelian Pop
+M: stelian@popies.net
+P: Michael Hanselmann
+M: linux-kernel@hansmi.ch
+S: Supported
+
AMSO1100 RNIC DRIVER
P: Tom Tucker
M: tom@opengridcomputing.com
@@ -348,6 +384,24 @@ P: Ian Molton
M: spyro@f2s.com
S: Maintained
+ARM/ADI ROADRUNNER MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/ADS SPHERE MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/AJECO 1ARM MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARM/ATMEL AT91RM9200 ARM ARCHITECTURE
P: Andrew Victor
M: andrew@sanpeople.com
@@ -355,17 +409,103 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://maxim.org.za/at91_26.html
S: Maintained
+ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARM/CORGI MACHINE SUPPORT
P: Richard Purdie
M: rpurdie@rpsys.net
S: Maintained
+ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARM/HP JORNADA 7XX MACHINE SUPPORT
P: Kristoffer Ericson
M: kristoffer_e1@hotmail.com
W: www.jlime.com
S: Maintained
+ARM/INTEL IOP32X ARM ARCHITECTURE
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+P: Dan Williams
+M: dan.j.williams@intel.com
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Supported
+
+ARM/INTEL IOP33X ARM ARCHITECTURE
+P: Dan Williams
+M: dan.j.williams@intel.com
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Supported
+
+ARM/INTEL IOP13XX ARM ARCHITECTURE
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+P: Dan Williams
+M: dan.j.williams@intel.com
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Supported
+
+ARM/INTEL IQ81342EX MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+P: Dan Williams
+M: dan.j.williams@intel.com
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Supported
+
+ARM/INTEL IXP2000 ARM ARCHITECTURE
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/INTEL IXDP2850 MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/INTEL IXP23XX ARM ARCHITECTURE
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/INTEL XSC3 (MANZANO) ARM CORE
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+P: Dan Williams
+M: dan.j.williams@intel.com
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Supported
+
+ARM/IP FABRICS DOUBLE ESPRESSO MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/LOGICPD PXA270 MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARM/TOSA MACHINE SUPPORT
P: Dirk Opfer
M: dirk@opfer-online.de
@@ -384,6 +524,12 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.arm.linux.org.uk/
S: Maintained
+ARM/RADISYS ENP2611 MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARM/SHARK MACHINE SUPPORT
P: Alexander Schulz
M: alex@shark-linux.de
@@ -399,31 +545,43 @@ S: Maintained
ARM/S3C2410 ARM ARCHITECTURE
P: Ben Dooks
-M: ben-s3c2410@fluff.org
+M: ben-linux@fluff.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.fluff.org/ben/linux/
S: Maintained
ARM/S3C2440 ARM ARCHITECTURE
P: Ben Dooks
-M: ben-s3c2440@fluff.org
+M: ben-linux@fluff.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.fluff.org/ben/linux/
S: Maintained
+ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
+ARM/THECUS N2100 MACHINE SUPPORT
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARPD SUPPORT
P: Jonathan Layes
L: netdev@vger.kernel.org
S: Maintained
ASUS ACPI EXTRAS DRIVER
+P: Corentin Chary
+M: corentincj@iksaif.net
P: Karol Kozimor
M: sziwan@users.sourceforge.net
-P: Julien Lerouge
-M: julien.lerouge@free.fr
L: acpi4asus-user@lists.sourceforge.net
W: http://sourceforge.net/projects/acpi4asus
-W: http://julien.lerouge.free.fr
+W: http://xf.iksaif.net/acpi4asus
S: Maintained
ATA OVER ETHERNET DRIVER
@@ -440,8 +598,6 @@ W: http://linux-atm.sourceforge.net
S: Maintained
ATMEL MACB ETHERNET DRIVER
-P: Atmel AVR32 Support Team
-M: avr32@atmel.com
P: Haavard Skinnemoen
M: hskinnemoen@atmel.com
S: Supported
@@ -462,8 +618,6 @@ T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
S: Maintained
AVR32 ARCHITECTURE
-P: Atmel AVR32 Support Team
-M: avr32@atmel.com
P: Haavard Skinnemoen
M: hskinnemoen@atmel.com
W: http://www.atmel.com/products/AVR32/
@@ -472,8 +626,6 @@ W: http://avrfreaks.net/
S: Supported
AVR32/AT32AP MACHINE SUPPORT
-P: Atmel AVR32 Support Team
-M: avr32@atmel.com
P: Haavard Skinnemoen
M: hskinnemoen@atmel.com
S: Supported
@@ -681,12 +833,24 @@ M: joel.becker@oracle.com
L: linux-kernel@vger.kernel.org
S: Supported
+CIRRUS LOGIC EP93XX ETHERNET DRIVER
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: netdev@vger.kernel.org
+S: Maintained
+
CIRRUS LOGIC GENERIC FBDEV DRIVER
P: Jeff Garzik
M: jgarzik@pobox.com
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Odd Fixes
+CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: linux-usb-devel@lists.sourceforge.net
+S: Maintained
+
CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
P: Cirrus Logic Corporation (kernel 2.2 driver)
M: Cirrus Logic Corporation, Thomas Woller <twoller@crystal.cirrus.com>
@@ -740,7 +904,7 @@ P: Dave Jones
M: davej@codemonkey.org.uk
L: cpufreq@lists.linux.org.uk
W: http://www.codemonkey.org.uk/projects/cpufreq/
-T: git kernel.org/pub/scm/linux/kernel/davej/cpufreq.git
+T: git kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
S: Maintained
CPUID/MSR DRIVER
@@ -791,7 +955,7 @@ S: Maintained
CYBLAFB FRAMEBUFFER DRIVER
P: Knut Petersen
M: Knut_Petersen@t-online.de
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
CYCLADES 2X SYNC CARD DRIVER
@@ -936,18 +1100,15 @@ L: linux-kernel@vger.kernel.org
S: Maintained
DOCBOOK FOR DOCUMENTATION
-P: Martin Waitz
-M: tali@admingilde.org
P: Randy Dunlap
M: rdunlap@xenotime.net
-T: git http://tali.admingilde.org/git/linux-docbook.git
S: Maintained
DOCKING STATION DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: linux-acpi@vger.kernel.org
-S: Maintained
+S: Supported
DOUBLETALK DRIVER
P: James R. Van Zandt
@@ -970,9 +1131,9 @@ T: git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
S: Maintained
DSCC4 DRIVER
-P: François Romieu
-M: romieu@cogenit.fr
-M: romieu@ensta.fr
+P: Francois Romieu
+M: romieu@fr.zoreil.com
+L: netdev@vger.kernel.org
S: Maintained
DVB SUBSYSTEM AND DRIVERS
@@ -1087,7 +1248,7 @@ S: Maintained
ETHERNET BRIDGE
P: Stephen Hemminger
-M: shemminger@osdl.org
+M: shemminger@linux-foundation.org
L: bridge@osdl.org
W: http://bridge.sourceforge.net/
S: Maintained
@@ -1128,7 +1289,7 @@ S: Supported
FRAMEBUFFER LAYER
P: Antonino Daplas
M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
W: http://linux-fbdev.sourceforge.net/
S: Maintained
@@ -1270,6 +1431,12 @@ L: linux-nvidia@lists.surfsouth.com
W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
S: Maintained
+HID CORE LAYER
+P: Jiri Kosina
+M: jkosina@suse.cz
+L: linux-input@atrey.karlin.mff.cuni.cz
+S: Maintained
+
HIGH-SPEED SCC DRIVER FOR AX.25
P: Klaus Kudielka
M: klaus.kudielka@ieee.org
@@ -1390,6 +1557,15 @@ W: http://www.ia64-linux.org/
T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
S: Maintained
+IBM ACPI EXTRAS DRIVER
+P: Henrique de Moraes Holschuh
+M: ibm-acpi@hmh.eng.br
+L: ibm-acpi-devel@lists.sourceforge.net
+W: http://ibm-acpi.sourceforge.net
+W: http://thinkwiki.org/wiki/Ibm-acpi
+T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
+S: Maintained
+
SN-IA64 (Itanium) SUB-PLATFORM
P: Jes Sorensen
M: jes@sgi.com
@@ -1416,19 +1592,17 @@ M: ipslinux@adaptec.com
W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html
S: Supported
-IDE DRIVER [GENERAL]
+IDE SUBSYSTEM
P: Bartlomiej Zolnierkiewicz
-M: B.Zolnierkiewicz@elka.pw.edu.pl
-L: linux-kernel@vger.kernel.org
+M: bzolnier@gmail.com
L: linux-ide@vger.kernel.org
-T: git kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git
+T: quilt kernel.org/pub/linux/kernel/people/bart/pata-2.6/
S: Maintained
IDE/ATAPI CDROM DRIVER
-P: Jens Axboe
-M: axboe@kernel.dk
-L: linux-kernel@vger.kernel.org
-W: http://www.kernel.dk
+P: Alan Cox
+M: alan@lxorguk.ukuu.org.uk
+L: linux-ide@vger.kernel.org
S: Maintained
IDE/ATAPI FLOPPY DRIVERS
@@ -1479,7 +1653,7 @@ S: Maintained
IMS TWINTURBO FRAMEBUFFER DRIVER
P: Paul Mundt
M: lethal@chaoticdreams.org
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
INFINIBAND SUBSYSTEM
@@ -1504,21 +1678,23 @@ T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
S: Maintained
INOTIFY
-P: John McCutchan and Robert Love
-M: ttb@tentacle.dhs.org and rml@novell.com
+P: John McCutchan
+M: ttb@tentacle.dhs.org
+P: Robert Love
+M: rml@novell.com
L: linux-kernel@vger.kernel.org
S: Maintained
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
P: Sylvain Meyer
M: sylvain.meyer@worldonline.fr
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
INTEL 810/815 FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
@@ -1542,6 +1718,12 @@ P: Deepak Saxena
M: dsaxena@plexity.net
S: Maintained
+INTEL IXP2000 ETHERNET DRIVER
+P: Lennert Buytenhek
+M: kernel@wantstofly.org
+L: netdev@vger.kernel.org
+S: Maintained
+
INTEL PRO/100 ETHERNET SUPPORT
P: John Ronciak
M: john.ronciak@intel.com
@@ -1739,11 +1921,17 @@ S: Maintained
KERNEL NFSD
P: Neil Brown
-M: neilb@cse.unsw.edu.au
+M: neilb@suse.de
L: nfs@lists.sourceforge.net
W: http://nfs.sourceforge.net/
-W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
-S: Maintained
+S: Supported
+
+KERNEL VIRTUAL MACHINE (KVM)
+P: Avi Kivity
+M: avi@qumranet.com
+L: kvm-devel@lists.sourceforge.net
+W: kvm.sourceforge.net
+S: Supported
KEXEC
P: Eric Biederman
@@ -1903,9 +2091,9 @@ S: Maintained
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
P: Eric Moore
-M: Eric.Moore@lsil.com
-M: support@lsil.com
-L: mpt_linux_developer@lsil.com
+M: Eric.Moore@lsi.com
+M: support@lsi.com
+L: mpt_linux_developer@lsi.com
L: linux-scsi@vger.kernel.org
W: http://www.lsilogic.com/support
S: Supported
@@ -1964,7 +2152,7 @@ S: Odd Fixes for 2.4; Maintained for 2.6.
MATROX FRAMEBUFFER DRIVER
P: Petr Vandrovec
M: vandrove@vc.cvut.cz
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
MEGARAID SCSI DRIVERS
@@ -2025,6 +2213,12 @@ M: rubini@ipvvis.unipv.it
L: linux-kernel@vger.kernel.org
S: Maintained
+MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0)
+P: Jiri Slaby
+M: jirislaby@gmail.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
MSI LAPTOP SUPPORT
P: Lennart Poettering
M: mzxreary@0pointer.de
@@ -2050,6 +2244,12 @@ P: Andrew Veliath
M: andrewtv@usa.net
S: Maintained
+MULTITECH MULTIPORT CARD (ISICOM)
+P: Jiri Slaby
+M: jirislaby@gmail.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
NATSEMI ETHERNET DRIVER (DP8381x)
P: Tim Hockin
M: thockin@hockin.org
@@ -2069,7 +2269,7 @@ S: Maintained
NETEM NETWORK EMULATOR
P: Stephen Hemminger
-M: shemminger@osdl.org
+M: shemminger@linux-foundation.org
L: netem@osdl.org
S: Maintained
@@ -2082,7 +2282,7 @@ P: Jozsef Kadlecsik
P: Patrick McHardy
M: kaber@trash.net
L: netfilter-devel@lists.netfilter.org
-L: netfilter@lists.netfilter.org
+L: netfilter@lists.netfilter.org (subscribers-only)
L: coreteam@netfilter.org
W: http://www.netfilter.org/
W: http://www.iptables.org/
@@ -2210,7 +2410,7 @@ S: Maintained
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
OPENCORES I2C BUS DRIVER
@@ -2356,7 +2556,7 @@ PCIE HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net
-S: Maintained
+S: Supported
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
@@ -2414,6 +2614,12 @@ P: Adam Belay
M: ambx1@neo.rr.com
S: Maintained
+PNXxxxx I2C DRIVER
+P: Vitaly Wool
+M: vitalywool@gmail.com
+L: i2c@lm-sensors.org
+S: Maintained
+
PPP PROTOCOL DRIVERS AND COMPRESSORS
P: Paul Mackerras
M: paulus@samba.org
@@ -2451,6 +2657,12 @@ M: promise@pnd-pc.demon.co.uk
W: http://www.pnd-pc.demon.co.uk/promise/
S: Maintained
+PROMISE SATA TX2/TX4 CONTROLLER LIBATA DRIVER
+P: Mikael Pettersson
+M: mikpe@it.uu.se
+L: linux-ide@vger.kernel.org
+S: Maintained
+
PS3 PLATFORM SUPPORT
P: Geoff Levand
M: geoffrey.levand@am.sony.com
@@ -2494,13 +2706,13 @@ S: Maintained
RADEON FRAMEBUFFER DISPLAY DRIVER
P: Benjamin Herrenschmidt
M: benh@kernel.crashing.org
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
RAGE128 FRAMEBUFFER DISPLAY DRIVER
P: Paul Mackerras
M: paulus@samba.org
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
@@ -2542,7 +2754,7 @@ S: Maintained
REAL TIME CLOCK (RTC) SUBSYSTEM
P: Alessandro Zummo
M: a.zummo@towertech.it
-L: linux-kernel@vger.kernel.org
+L: rtc-linux@googlegroups.com
S: Maintained
REISERFS FILE SYSTEM
@@ -2570,7 +2782,7 @@ S: Orphan
S3 SAVAGE FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@pol.net
-L: linux-fbdev-devel@lists.sourceforge.net
+L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only)
S: Maintained
S390
@@ -2773,9 +2985,9 @@ SOFTWARE RAID (Multiple Disks) SUPPORT
P: Ingo Molnar
M: mingo@redhat.com
P: Neil Brown
-M: neilb@cse.unsw.edu.au
+M: neilb@suse.de
L: linux-raid@vger.kernel.org
-S: Maintained
+S: Supported
SOFTWARE SUSPEND:
P: Pavel Machek
@@ -2850,7 +3062,7 @@ SHPC HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net
-S: Maintained
+S: Supported
SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
P: Pierre Ossman
@@ -2861,7 +3073,7 @@ S: Maintained
SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
P: Stephen Hemminger
-M: shemminger@osdl.org
+M: shemminger@linux-foundation.org
L: netdev@vger.kernel.org
S: Maintained
@@ -3096,7 +3308,7 @@ USB EHCI DRIVER
P: David Brownell
M: dbrownell@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
-S: Maintained
+S: Odd Fixes
USB ET61X[12]51 DRIVER
P: Luca Risolia
@@ -3114,9 +3326,8 @@ W: http://www.linux-usb.org/gadget
S: Maintained
USB HID/HIDBP DRIVERS
-P: Vojtech Pavlik
-M: vojtech@suse.cz
-L: linux-usb-users@lists.sourceforge.net
+P: Jiri Kosina
+M: jkosina@suse.cz
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
@@ -3149,11 +3360,11 @@ S: Maintained
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
USB OHCI DRIVER
-P: Roman Weissgaerber
-M: weissg@vienna.at
+P: David Brownell
+M: dbrownell@users.sourceforge.net
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
-S: Maintained
+S: Odd Fixes
USB OPTION-CARD DRIVER
P: Matthias Urlichs
@@ -3356,6 +3567,12 @@ M: khali@linux-fr.org
L: i2c@lm-sensors.org
S: Maintained
+VIA VELOCITY NETWORK DRIVER
+P: Francois Romieu
+M: romieu@fr.zoreil.com
+L: netdev@vger.kernel.org
+S: Maintained
+
UCLINUX (AND M68KNOMMU)
P: Greg Ungerer
M: gerg@uclinux.org
@@ -3376,6 +3593,12 @@ M: ysato@users.sourceforge.jp
W: http://uclinux-h8.sourceforge.jp/
S: Supported
+UFS FILESYSTEM
+P: Evgeniy Dushistov
+M: dushistov@mail.ru
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
USB DIAMOND RIO500 DRIVER
P: Cesar Miquel
M: miquel@df.uba.ar
@@ -3415,6 +3638,12 @@ M: bezaur@gmail.com
L: lm-sensors@lm-sensors.org
S: Maintained
+W83793 HARDWARE MONITORING DRIVER
+P: Rudolf Marek
+M: r.marek@assembler.cz
+L: lm-sensors@lm-sensors.org
+S: Maintained
+
W83L51xD SD/MMC CARD INTERFACE DRIVER
P: Pierre Ossman
M: drzeus-wbsd@drzeus.cx
diff --git a/Makefile b/Makefile
index aef96259051..7e2750f4ca7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 19
+SUBLEVEL = 20
EXTRAVERSION =
-NAME=Avast! A bilge rat!
+NAME = Homicidal Dwarf Hamster
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
@@ -10,8 +10,11 @@ NAME=Avast! A bilge rat!
# Comments in this file are targeted only to the developer, do not
# expect to learn how to build the kernel reading this file.
-# Do not print "Entering directory ..."
-MAKEFLAGS += --no-print-directory
+# Do not:
+# o use make's built-in rules and variables
+# (this increases performance and avoid hard-to-debug behavour);
+# o print "Entering directory ...";
+MAKEFLAGS += -rR --no-print-directory
# We are using a recursive build, so we need to do a little thinking
# to get the ordering right.
@@ -271,12 +274,8 @@ export quiet Q KBUILD_VERBOSE
# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
-# We need some generic definitions
-include $(srctree)/scripts/Kbuild.include
-
-# Do not use make's built-in rules and variables
-# This increases performance and avoid hard-to-debug behavour
-MAKEFLAGS += -rR
+# We need some generic definitions.
+include $(srctree)/scripts/Kbuild.include
# Make variables (CC, etc...)
@@ -497,11 +496,6 @@ else
CFLAGS += -fomit-frame-pointer
endif
-ifdef CONFIG_UNWIND_INFO
-CFLAGS += -fasynchronous-unwind-tables
-LDFLAGS_vmlinux += --eh-frame-hdr
-endif
-
ifdef CONFIG_DEBUG_INFO
CFLAGS += -g
endif
@@ -1101,9 +1095,9 @@ boards := $(notdir $(boards))
help:
@echo 'Cleaning targets:'
- @echo ' clean - remove most generated files but keep the config and'
+ @echo ' clean - Remove most generated files but keep the config and'
@echo ' enough build support to build external modules'
- @echo ' mrproper - remove all generated files + config + various backup files'
+ @echo ' mrproper - Remove all generated files + config + various backup files'
@echo ' distclean - mrproper + remove editor backup and patch files'
@echo ''
@echo 'Configuration targets:'
@@ -1122,15 +1116,15 @@ help:
@echo ' cscope - Generate cscope index'
@echo ' kernelrelease - Output the release version string'
@echo ' kernelversion - Output the version stored in Makefile'
- @if [ -r include/asm-$(ARCH)/Kbuild ]; then \
+ @if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
+ echo ' (default: $(INSTALL_HDR_PATH))'; \
fi
- @echo ' (default: $(INSTALL_HDR_PATH))'
@echo ''
@echo 'Static analysers'
@echo ' checkstack - Generate a list of stack hogs'
@echo ' namespacecheck - Name space analysis on compiled kernel'
- @if [ -r include/asm-$(ARCH)/Kbuild ]; then \
+ @if [ -r $(srctree)/include/asm-$(ARCH)/Kbuild ]; then \
echo ' headers_check - Sanity check on exported headers'; \
fi
@echo ''
@@ -1391,12 +1385,18 @@ endif #ifeq ($(mixed-targets),1)
PHONY += checkstack kernelrelease kernelversion
-# Use $(SUBARCH) here instead of $(ARCH) so that this works for UML.
-# In the UML case, $(SUBARCH) is the name of the underlying
-# architecture, while for all other arches, it is the same as $(ARCH).
+# UML needs a little special treatment here. It wants to use the host
+# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone
+# else wants $(ARCH), including people doing cross-builds, which means
+# that $(SUBARCH) doesn't work here.
+ifeq ($(ARCH), um)
+CHECKSTACK_ARCH := $(SUBARCH)
+else
+CHECKSTACK_ARCH := $(ARCH)
+endif
checkstack:
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
- $(PERL) $(src)/scripts/checkstack.pl $(SUBARCH)
+ $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
kernelrelease:
$(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
@@ -1484,6 +1484,8 @@ endif # skip-makefile
PHONY += FORCE
FORCE:
+# Cancel implicit rules on top Makefile, `-rR' will apply to sub-makes.
+Makefile: ;
# Declare the contents of the .PHONY variable as phony. We keep that
# information in a variable se we can use it in if_changed and friends.
diff --git a/README b/README
index c0556152302..46a66c6e76d 100644
--- a/README
+++ b/README
@@ -278,8 +278,8 @@ IF SOMETHING GOES WRONG:
the file MAINTAINERS to see if there is a particular person associated
with the part of the kernel that you are having trouble with. If there
isn't anyone listed there, then the second best thing is to mail
- them to me (torvalds@osdl.org), and possibly to any other relevant
- mailing-list or to the newsgroup.
+ them to me (torvalds@linux-foundation.org), and possibly to any other
+ relevant mailing-list or to the newsgroup.
- In all bug-reports, *please* tell what kernel you are talking about,
how to duplicate the problem, and what your setup is (use your common
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 7e55ea66c6d..84caf50725b 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index ad617365199..be133f1f75a 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -277,7 +277,7 @@ osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bu
retval = -EBADF;
file = fget(fd);
if (file) {
- retval = do_osf_statfs(file->f_dentry, buffer, bufsiz);
+ retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz);
fput(file);
}
return retval;
@@ -979,7 +979,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
long timeout;
int ret = -EINVAL;
struct fdtable *fdt;
- int max_fdset;
+ int max_fds;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
@@ -1003,9 +1003,9 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
rcu_read_lock();
fdt = files_fdtable(current->files);
- max_fdset = fdt->max_fdset;
+ max_fds = fdt->max_fds;
rcu_read_unlock();
- if (n < 0 || n > max_fdset)
+ if (n < 0 || n > max_fds)
goto out_nofds;
/*
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 3370e6faeae..c1518639069 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -47,6 +47,7 @@
* Power off function, if any
*/
void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
void
cpu_idle(void)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8c05d4321ae..6783c2e5512 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -74,6 +74,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_HWEIGHT
bool
default y
@@ -732,7 +740,7 @@ config XIP_PHYS_ADDR
endmenu
-if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP)
+if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
menu "CPU Frequency scaling"
@@ -759,6 +767,15 @@ config CPU_FREQ_INTEGRATOR
If in doubt, say Y.
+config CPU_FREQ_IMX
+ tristate "CPUfreq driver for i.MX CPUs"
+ depends on ARCH_IMX && CPU_FREQ
+ default n
+ help
+ This enables the CPUfreq driver for i.MX CPUs.
+
+ If in doubt, say N.
+
endmenu
endif
@@ -937,6 +954,8 @@ source "drivers/video/Kconfig"
source "sound/Kconfig"
+source "drivers/hid/Kconfig"
+
source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
index 79049206dfa..46b0c734aeb 100644
--- a/arch/arm/configs/at91sam9260ek_defconfig
+++ b/arch/arm/configs/at91sam9260ek_defconfig
@@ -923,7 +923,6 @@ CONFIG_FORCED_INLINING=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
# CONFIG_DEBUG_ERRORS is not set
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
index 784ad7c0186..fcd8fa091e9 100644
--- a/arch/arm/configs/at91sam9261ek_defconfig
+++ b/arch/arm/configs/at91sam9261ek_defconfig
@@ -1079,7 +1079,6 @@ CONFIG_FORCED_INLINING=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_WAITQ is not set
# CONFIG_DEBUG_ERRORS is not set
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index f8a66b72ad5..24a701ab33e 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,14 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1-git9
-# Sat Jul 15 15:08:10 2006
+# Linux kernel version: 2.6.20-rc1
+# Sat Dec 16 06:05:24 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -28,18 +32,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -48,12 +56,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -71,7 +79,10 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -103,7 +114,9 @@ CONFIG_ARCH_EP93XX=y
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
@@ -127,6 +140,7 @@ CONFIG_CRUNCH=y
#
CONFIG_MACH_ADSSPHERE=y
CONFIG_MACH_EDB9302=y
+CONFIG_MACH_EDB9302A=y
CONFIG_MACH_EDB9312=y
CONFIG_MACH_EDB9315=y
CONFIG_MACH_EDB9315A=y
@@ -138,12 +152,14 @@ CONFIG_MACH_TS72XX=y
#
CONFIG_CPU_32=y
CONFIG_CPU_ARM920T=y
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32v4T=y
CONFIG_CPU_ABRT_EV4T=y
CONFIG_CPU_CACHE_V4WT=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
@@ -230,6 +246,7 @@ CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_NET_KEY=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -250,13 +267,29 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -283,7 +316,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -330,7 +362,7 @@ 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_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
#
@@ -342,6 +374,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -430,7 +463,7 @@ CONFIG_MTD_NAND_IDS=y
#
# 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_NBD=y
# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -442,6 +475,8 @@ CONFIG_MTD_NAND_IDS=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
# CONFIG_SCSI_PROC_FS is not set
#
@@ -460,23 +495,29 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_DEBUG is not set
#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
@@ -513,6 +554,7 @@ CONFIG_NETDEVICES=y
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+CONFIG_EP93XX_ETH=y
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
@@ -607,17 +649,12 @@ CONFIG_EP93XX_WATCHDOG=y
# CONFIG_NVRAM is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -645,7 +682,7 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -664,6 +701,7 @@ CONFIG_I2C_DEBUG_CHIP=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -697,12 +735,15 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -711,6 +752,7 @@ CONFIG_HWMON=y
#
# Misc devices
#
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -729,7 +771,6 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -742,6 +783,7 @@ CONFIG_VIDEO_V4L2=y
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -763,6 +805,7 @@ CONFIG_USB_DEBUG=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -797,12 +840,12 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
-# CONFIG_USB_HID is not set
#
# USB HID Boot Protocol drivers
@@ -821,6 +864,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
CONFIG_USB_RTL8150=y
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
# CONFIG_USB_MON is not set
@@ -834,8 +878,8 @@ CONFIG_USB_RTL8150=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
# CONFIG_USB_SERIAL_AIRPRIME is not set
-# CONFIG_USB_SERIAL_ANYDATA is not set
# CONFIG_USB_SERIAL_ARK3116 is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_WHITEHEAT is not set
@@ -857,6 +901,8 @@ CONFIG_USB_SERIAL_CONSOLE=y
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_SERIAL_HP4X is not set
@@ -867,12 +913,14 @@ CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
#
# USB Miscellaneous drivers
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -880,11 +928,12 @@ CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -908,6 +957,7 @@ CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
#
# RTC interfaces
@@ -921,7 +971,7 @@ CONFIG_RTC_INTF_DEV=y
# RTC drivers
#
# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_DS1307 is not set
+CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_DS1672 is not set
@@ -943,12 +993,14 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -980,8 +1032,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1102,6 +1156,11 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1110,8 +1169,11 @@ CONFIG_NLS_ISO8859_1=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1128,10 +1190,9 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -1151,12 +1212,9 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1164,3 +1222,4 @@ CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/iop13xx_defconfig b/arch/arm/configs/iop13xx_defconfig
index f6e46193fd2..43c4a37e924 100644
--- a/arch/arm/configs/iop13xx_defconfig
+++ b/arch/arm/configs/iop13xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19
-# Fri Dec 1 10:51:01 2006
+# Linux kernel version: 2.6.20-rc1-git5
+# Tue Dec 19 21:38:01 2006
#
CONFIG_ARM=y
# CONFIG_GENERIC_TIME is not set
@@ -11,6 +11,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -39,6 +41,7 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -77,7 +80,9 @@ CONFIG_KMOD=y
# Block layer
#
CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -154,11 +159,13 @@ CONFIG_IO_36=y
CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_IWMMXT is not set
#
# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -259,9 +266,23 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_IPV6 is not set
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -433,7 +454,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# 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_NBD=y
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=2
@@ -448,6 +469,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
@@ -467,6 +489,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -510,6 +533,7 @@ CONFIG_SCSI_SAS_ATTRS=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -605,6 +629,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -711,10 +736,6 @@ CONFIG_HW_RANDOM=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
@@ -820,6 +841,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -830,6 +852,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -883,6 +906,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -970,6 +998,7 @@ CONFIG_RAMFS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=y
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -1092,6 +1121,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1103,28 +1137,68 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_USER=y
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1132,3 +1206,4 @@ CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/iop32x_defconfig b/arch/arm/configs/iop32x_defconfig
index b275c53728e..7909a555706 100644
--- a/arch/arm/configs/iop32x_defconfig
+++ b/arch/arm/configs/iop32x_defconfig
@@ -1,15 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc7
-# Tue Sep 19 00:30:18 2006
+# Linux kernel version: 2.6.20-rc1-git5
+# Tue Dec 19 21:37:52 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -29,18 +32,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -49,12 +56,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -72,7 +79,10 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -106,6 +116,7 @@ CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_ARCH_IMX is not set
CONFIG_ARCH_IOP32X=y
# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
@@ -141,17 +152,22 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
#
# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_IWMMXT is not set
CONFIG_XSCALE_PMU=y
#
# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -225,6 +241,7 @@ CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -246,13 +263,29 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -279,7 +312,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -338,6 +370,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -419,9 +452,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# 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_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
# 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
@@ -440,6 +475,8 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -458,14 +495,16 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -478,26 +517,84 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
#
# Multi-device support (RAID and LVM)
@@ -512,6 +609,7 @@ CONFIG_MD_RAID1=y
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
# CONFIG_DM_CRYPT is not set
# CONFIG_DM_SNAPSHOT is not set
# CONFIG_DM_MIRROR is not set
@@ -612,6 +710,7 @@ CONFIG_R8169=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -620,6 +719,7 @@ CONFIG_R8169=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -654,6 +754,7 @@ CONFIG_R8169=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -725,10 +826,6 @@ CONFIG_HW_RANDOM=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
@@ -736,7 +833,6 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -801,6 +897,7 @@ CONFIG_I2C_IOP3XX=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -834,15 +931,18 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -851,6 +951,8 @@ CONFIG_HWMON=y
#
# Misc devices
#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -869,12 +971,12 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -895,6 +997,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -909,6 +1016,7 @@ CONFIG_USB=y
# CONFIG_USB_DEVICEFS is not set
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -946,6 +1054,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -984,6 +1093,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1001,6 +1111,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1008,12 +1119,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
#
# USB DSL modem support
@@ -1045,6 +1157,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1056,6 +1169,7 @@ CONFIG_XFS_FS=y
CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1084,8 +1198,10 @@ CONFIG_DNOTIFY=y
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1095,6 +1211,7 @@ CONFIG_RAMFS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=y
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -1129,7 +1246,7 @@ CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
@@ -1172,6 +1289,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1180,8 +1302,11 @@ CONFIG_MSDOS_PARTITION=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1197,10 +1322,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -1211,13 +1335,48 @@ CONFIG_DEBUG_LL=y
#
# Security options
#
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
#
# Hardware crypto devices
@@ -1226,10 +1385,12 @@ CONFIG_DEBUG_LL=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/iop33x_defconfig b/arch/arm/configs/iop33x_defconfig
index 848e3ace906..fa271bce8ff 100644
--- a/arch/arm/configs/iop33x_defconfig
+++ b/arch/arm/configs/iop33x_defconfig
@@ -1,15 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc7
-# Tue Sep 19 00:30:42 2006
+# Linux kernel version: 2.6.20-rc1
+# Sat Dec 16 06:05:34 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -29,18 +32,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -49,12 +56,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -72,7 +79,10 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -106,6 +116,7 @@ CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_IOP32X is not set
CONFIG_ARCH_IOP33X=y
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
@@ -139,17 +150,22 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
#
# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_IWMMXT is not set
CONFIG_XSCALE_PMU=y
#
# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -223,6 +239,7 @@ CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -244,13 +261,29 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -277,7 +310,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -336,6 +368,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -423,7 +456,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# 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_NBD=y
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
@@ -443,6 +476,8 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -461,14 +496,16 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -481,26 +518,34 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -515,6 +560,7 @@ CONFIG_MD_RAID1=y
# CONFIG_MD_MULTIPATH is not set
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
# CONFIG_DM_CRYPT is not set
# CONFIG_DM_SNAPSHOT is not set
# CONFIG_DM_MIRROR is not set
@@ -580,6 +626,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -588,6 +635,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -622,6 +670,7 @@ CONFIG_E1000_NAPI=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -693,10 +742,6 @@ CONFIG_HW_RANDOM=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
@@ -704,7 +749,6 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -769,6 +813,7 @@ CONFIG_I2C_IOP3XX=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -802,15 +847,18 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -819,6 +867,8 @@ CONFIG_HWMON=y
#
# Misc devices
#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -837,7 +887,6 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -863,6 +912,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -900,6 +954,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -911,6 +966,7 @@ CONFIG_XFS_FS=y
CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -939,8 +995,10 @@ CONFIG_DNOTIFY=y
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1019,6 +1077,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1027,8 +1090,11 @@ CONFIG_MSDOS_PARTITION=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1044,10 +1110,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -1067,10 +1132,6 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
# CONFIG_CRC_CCITT is not set
@@ -1078,3 +1139,4 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
index bbd2dcf91e5..f8f9793b526 100644
--- a/arch/arm/configs/ixp2000_defconfig
+++ b/arch/arm/configs/ixp2000_defconfig
@@ -1,14 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Sun Jul 9 15:28:50 2006
+# Linux kernel version: 2.6.20-rc1
+# Sat Dec 16 06:05:39 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -28,17 +32,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -47,12 +56,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -70,7 +79,10 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -102,7 +114,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_IXP23XX is not set
@@ -143,24 +157,28 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
#
# CONFIG_ARM_THUMB is not set
CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_IWMMXT is not set
CONFIG_XSCALE_PMU=y
#
# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
#
# Kernel Features
@@ -228,6 +246,7 @@ CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -248,13 +267,29 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -281,7 +316,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -308,7 +342,6 @@ CONFIG_TCP_CONG_BIC=y
#
CONFIG_STANDALONE=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_SYS_HYPERVISOR is not set
@@ -340,6 +373,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -422,11 +456,12 @@ CONFIG_MTD_IXP2000=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD 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=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -436,6 +471,12 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -501,8 +542,8 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
CONFIG_CS89x0=y
# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -532,6 +573,7 @@ CONFIG_ENP2611_MSF_NET=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -540,6 +582,7 @@ CONFIG_ENP2611_MSF_NET=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -555,7 +598,6 @@ CONFIG_ENP2611_MSF_NET=y
# Wan interfaces
#
CONFIG_WAN=y
-# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
CONFIG_HDLC=y
CONFIG_HDLC_RAW=y
@@ -571,6 +613,7 @@ CONFIG_HDLC_PPP=y
# CONFIG_WANXL is not set
# CONFIG_PC300 is not set
# CONFIG_FARSYNC is not set
+# CONFIG_DSCC4 is not set
CONFIG_DLCI=y
CONFIG_DLCI_COUNT=24
CONFIG_DLCI_MAX=8
@@ -592,6 +635,7 @@ CONFIG_DLCI_MAX=8
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -673,10 +717,6 @@ CONFIG_IXP2000_WATCHDOG=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
@@ -684,7 +724,6 @@ CONFIG_IXP2000_WATCHDOG=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -749,6 +788,7 @@ CONFIG_SENSORS_EEPROM=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -782,15 +822,18 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -799,6 +842,8 @@ CONFIG_HWMON=y
#
# Misc devices
#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -817,7 +862,6 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -829,6 +873,7 @@ CONFIG_VIDEO_V4L2=y
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -836,6 +881,11 @@ CONFIG_VIDEO_V4L2=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -875,6 +925,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -882,6 +933,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -910,8 +962,10 @@ CONFIG_DNOTIFY=y
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -961,7 +1015,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -994,6 +1047,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1002,8 +1060,11 @@ CONFIG_MSDOS_PARTITION=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1019,10 +1080,9 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -1042,12 +1102,9 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1055,3 +1112,4 @@ CONFIG_CRC32=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
index 06deefaec1d..27cf022dd80 100644
--- a/arch/arm/configs/ixp23xx_defconfig
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -1,14 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Sun Jul 9 14:13:35 2006
+# Linux kernel version: 2.6.20-rc1
+# Sat Dec 16 06:05:45 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -28,17 +32,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -47,12 +56,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -70,7 +79,10 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -102,7 +114,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
CONFIG_ARCH_IXP23XX=y
@@ -137,6 +151,8 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
CONFIG_IO_36=y
#
@@ -144,11 +160,15 @@ CONFIG_IO_36=y
#
# CONFIG_ARM_THUMB is not set
CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_IWMMXT is not set
#
# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -222,6 +242,7 @@ CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -242,13 +263,29 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -275,7 +312,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -334,6 +370,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -418,12 +455,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_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_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -432,6 +470,7 @@ CONFIG_BLK_DEV_INITRD=y
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
CONFIG_BLK_DEV_IDE=y
#
@@ -455,7 +494,6 @@ CONFIG_BLK_DEV_IDEPCI=y
# 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
@@ -469,6 +507,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -477,6 +516,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
# CONFIG_BLK_DEV_SVWKS is not set
CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -491,6 +531,8 @@ CONFIG_BLK_DEV_IDEDMA=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -509,14 +551,16 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -529,26 +573,34 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -649,6 +701,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -657,6 +710,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -672,7 +726,6 @@ CONFIG_E1000_NAPI=y
# Wan interfaces
#
CONFIG_WAN=y
-# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
CONFIG_HDLC=y
CONFIG_HDLC_RAW=y
@@ -688,6 +741,7 @@ CONFIG_HDLC_PPP=y
# CONFIG_WANXL is not set
# CONFIG_PC300 is not set
# CONFIG_FARSYNC is not set
+# CONFIG_DSCC4 is not set
CONFIG_DLCI=y
CONFIG_DLCI_COUNT=24
CONFIG_DLCI_MAX=8
@@ -710,6 +764,7 @@ CONFIG_DLCI_MAX=8
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -795,10 +850,6 @@ CONFIG_WATCHDOG=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
@@ -806,7 +857,6 @@ CONFIG_WATCHDOG=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -870,6 +920,7 @@ CONFIG_SENSORS_EEPROM=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -903,15 +954,18 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -920,6 +974,8 @@ CONFIG_HWMON=y
#
# Misc devices
#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -938,7 +994,6 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -951,6 +1006,7 @@ CONFIG_VIDEO_V4L2=y
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -958,6 +1014,11 @@ CONFIG_VIDEO_V4L2=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -972,6 +1033,7 @@ CONFIG_USB=y
# CONFIG_USB_DEVICEFS is not set
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1012,6 +1074,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -1050,6 +1113,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1067,19 +1131,21 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
#
# USB DSL modem support
@@ -1113,6 +1179,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1120,6 +1187,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1150,8 +1218,10 @@ CONFIG_FAT_DEFAULT_CODEPAGE=437
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1201,7 +1271,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1273,6 +1342,11 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1281,8 +1355,11 @@ CONFIG_NLS_CODEPAGE_437=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1298,10 +1375,9 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -1321,12 +1397,9 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1334,3 +1407,4 @@ CONFIG_CRC32=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
index e146189ab54..a3bf5833b87 100644
--- a/arch/arm/configs/lpd270_defconfig
+++ b/arch/arm/configs/lpd270_defconfig
@@ -1,14 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Sun Jul 9 14:15:23 2006
+# Linux kernel version: 2.6.20-rc1
+# Sat Dec 16 06:05:51 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_MTD_XIP=y
@@ -29,16 +33,21 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -47,12 +56,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -69,7 +78,10 @@ CONFIG_MODULES=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -101,7 +113,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
@@ -125,7 +139,6 @@ CONFIG_MACH_LOGICPD_PXA270=y
# CONFIG_PXA_SHARPSL is not set
# CONFIG_MACH_TRIZEPS4 is not set
CONFIG_PXA27x=y
-CONFIG_IWMMXT=y
#
# Processor Type
@@ -136,11 +149,15 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
#
# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_IWMMXT=y
CONFIG_XSCALE_PMU=y
#
@@ -217,6 +234,7 @@ CONFIG_NET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -237,13 +255,29 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -270,7 +304,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -329,6 +362,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -410,7 +444,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# 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_NBD=y
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
@@ -447,6 +481,12 @@ CONFIG_BLK_DEV_IDEDISK=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -526,6 +566,7 @@ CONFIG_SMC91X=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -548,6 +589,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
@@ -600,17 +642,12 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_NVRAM is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -626,6 +663,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -634,11 +672,14 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
#
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -657,7 +698,6 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -679,6 +719,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_PXA=y
# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -725,7 +766,6 @@ CONFIG_SND_VERBOSE_PROCFS=y
# Generic devices
#
CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
@@ -741,6 +781,12 @@ CONFIG_SND_PXA2XX_AC97=y
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+
+#
+# HID Devices
+#
+CONFIG_HID=y
#
# USB support
@@ -777,10 +823,12 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -811,6 +859,7 @@ CONFIG_FAT_DEFAULT_CODEPAGE=437
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
@@ -860,7 +909,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -917,6 +965,11 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -925,8 +978,11 @@ CONFIG_NLS_ISO8859_1=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -942,10 +998,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -965,12 +1020,9 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -978,3 +1030,4 @@ CONFIG_CRC32=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig
index 0498ebd7d5d..650a248613e 100644
--- a/arch/arm/configs/onearm_defconfig
+++ b/arch/arm/configs/onearm_defconfig
@@ -1,14 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Sun Jul 9 14:16:20 2006
+# Linux kernel version: 2.6.20-rc1
+# Sat Dec 16 06:05:18 2006
#
CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -28,16 +32,21 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -46,12 +55,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -69,7 +78,10 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -101,7 +113,9 @@ CONFIG_ARCH_AT91=y
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
@@ -118,10 +132,6 @@ CONFIG_ARCH_AT91=y
#
# Atmel AT91 System-on-Chip
#
-
-#
-# Atmel AT91 Processors
-#
CONFIG_ARCH_AT91RM9200=y
# CONFIG_ARCH_AT91SAM9260 is not set
# CONFIG_ARCH_AT91SAM9261 is not set
@@ -140,6 +150,10 @@ CONFIG_MACH_ONEARM=y
# CONFIG_MACH_KAFA is not set
#
+# AT91 Board Options
+#
+
+#
# AT91 Feature Selections
#
CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
@@ -149,12 +163,14 @@ CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
#
CONFIG_CPU_32=y
CONFIG_CPU_ARM920T=y
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32v4T=y
CONFIG_CPU_ABRT_EV4T=y
CONFIG_CPU_CACHE_V4WT=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
#
# Processor Features
@@ -251,6 +267,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -271,13 +288,29 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -304,7 +337,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -360,6 +392,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
#
# RAM/ROM/Flash chip drivers
@@ -438,11 +471,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
#
# 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_NBD=y
# 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_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -457,6 +491,12 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -541,6 +581,7 @@ CONFIG_ARM_AT91_ETHER=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -619,10 +660,6 @@ CONFIG_AT91RM9200_WATCHDOG=y
# CONFIG_R3964 is not set
#
-# Ftape, the floppy tape device driver
-#
-
-#
# PCMCIA character devices
#
# CONFIG_SYNCLINK_CS is not set
@@ -634,7 +671,6 @@ CONFIG_AT91RM9200_WATCHDOG=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -652,6 +688,7 @@ CONFIG_I2C_CHARDEV=y
#
# I2C Hardware Bus support
#
+# CONFIG_I2C_AT91 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_STUB is not set
@@ -681,6 +718,7 @@ CONFIG_I2C_CHARDEV=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -714,12 +752,15 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -728,6 +769,7 @@ CONFIG_HWMON=y
#
# Misc devices
#
+# CONFIG_TIFM_CORE is not set
#
# LED devices
@@ -746,7 +788,6 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -759,6 +800,7 @@ CONFIG_VIDEO_V4L2=y
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -766,6 +808,11 @@ CONFIG_VIDEO_V4L2=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -780,6 +827,7 @@ CONFIG_USB_DEBUG=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -804,7 +852,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# may also be needed; see USB_STORAGE Help for more information
#
-# CONFIG_USB_STORAGE is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -842,6 +889,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -859,18 +907,20 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX 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_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -897,6 +947,7 @@ CONFIG_USB_AT91=y
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_FILE_STORAGE is not set
# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
#
# MMC/SD Card support
@@ -904,7 +955,8 @@ CONFIG_USB_AT91=y
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_BLOCK=y
-CONFIG_MMC_AT91RM9200=y
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_TIFM_SD is not set
#
# Real Time Clock
@@ -919,10 +971,12 @@ CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -951,8 +1005,10 @@ CONFIG_DNOTIFY=y
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -995,7 +1051,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1013,6 +1068,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1021,8 +1081,11 @@ CONFIG_MSDOS_PARTITION=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1038,10 +1101,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
@@ -1061,15 +1123,13 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-#
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
index a11fb9a40c0..2c37b70b17a 100644
--- a/arch/arm/kernel/apm.c
+++ b/arch/arm/kernel/apm.c
@@ -423,7 +423,7 @@ static int apm_open(struct inode * inode, struct file * filp)
{
struct apm_user *as;
- as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
* XXX - this is a tiny bit broken, when we consider BSD
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 3173924a9b6..f7598cbc7ec 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -110,7 +110,7 @@
CALL(sys_ni_syscall) /* was sys_profil */
CALL(sys_statfs)
/* 100 */ CALL(sys_fstatfs)
- CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall) /* sys_ioperm */
CALL(OBSOLETE(ABI(sys_socketcall, sys_oabi_socketcall)))
CALL(sys_syslog)
CALL(sys_setitimer)
@@ -132,7 +132,7 @@
/* 120 */ CALL(sys_clone_wrapper)
CALL(sys_setdomainname)
CALL(sys_newuname)
- CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall) /* modify_ldt */
CALL(sys_adjtimex)
/* 125 */ CALL(sys_mprotect)
CALL(sys_sigprocmask)
@@ -146,7 +146,7 @@
CALL(sys_bdflush)
/* 135 */ CALL(sys_sysfs)
CALL(sys_personality)
- CALL(sys_ni_syscall) /* CALL(_sys_afs_syscall) */
+ CALL(sys_ni_syscall) /* reserved for afs_syscall */
CALL(sys_setfsuid16)
CALL(sys_setfsgid16)
/* 140 */ CALL(sys_llseek)
@@ -175,7 +175,7 @@
CALL(sys_arm_mremap)
CALL(sys_setresuid16)
/* 165 */ CALL(sys_getresuid16)
- CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall) /* vm86 */
CALL(sys_ni_syscall) /* was sys_query_module */
CALL(sys_poll)
CALL(sys_nfsservctl)
@@ -197,8 +197,8 @@
/* 185 */ CALL(sys_capset)
CALL(sys_sigaltstack_wrapper)
CALL(sys_sendfile)
- CALL(sys_ni_syscall)
- CALL(sys_ni_syscall)
+ CALL(sys_ni_syscall) /* getpmsg */
+ CALL(sys_ni_syscall) /* putpmsg */
/* 190 */ CALL(sys_vfork_wrapper)
CALL(sys_getrlimit)
CALL(sys_mmap2)
@@ -331,6 +331,31 @@
CALL(sys_mbind)
/* 320 */ CALL(sys_get_mempolicy)
CALL(sys_set_mempolicy)
+ CALL(sys_openat)
+ CALL(sys_mkdirat)
+ CALL(sys_mknodat)
+/* 325 */ CALL(sys_fchownat)
+ CALL(sys_futimesat)
+ CALL(sys_fstatat64)
+ CALL(sys_unlinkat)
+ CALL(sys_renameat)
+/* 330 */ CALL(sys_linkat)
+ CALL(sys_symlinkat)
+ CALL(sys_readlinkat)
+ CALL(sys_fchmodat)
+ CALL(sys_faccessat)
+/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
+ CALL(sys_ni_syscall) /* eventually ppoll */
+ CALL(sys_unshare)
+ CALL(sys_set_robust_list)
+ CALL(sys_get_robust_list)
+/* 340 */ CALL(sys_splice)
+ CALL(sys_arm_sync_file_range)
+ CALL(sys_tee)
+ CALL(sys_vmsplice)
+ CALL(sys_move_pages)
+/* 345 */ CALL(sys_getcpu)
+ CALL(sys_ni_syscall) /* eventually epoll_pwait */
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index a786f769035..71257e3d513 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -353,7 +353,7 @@ int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
}
if (c_id(&excd) == 0x80) { /* loader */
if (!ec->loader) {
- ec->loader = (loader_t)kmalloc(c_len(&excd),
+ ec->loader = kmalloc(c_len(&excd),
GFP_KERNEL);
if (ec->loader)
ecard_readbytes(ec->loader, ec,
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2db42b18f53..8517c3c3eb3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -436,7 +436,7 @@ __und_usr:
usr_entry
tst r3, #PSR_T_BIT @ Thumb mode?
- bne fpundefinstr @ ignore FP
+ bne __und_usr_unknown @ ignore FP
sub r4, r2, #4
@
@@ -448,7 +448,7 @@ __und_usr:
@
1: ldrt r0, [r4]
adr r9, ret_from_exception
- adr lr, fpundefinstr
+ adr lr, __und_usr_unknown
@
@ fallthrough to call_fpe
@
@@ -476,7 +476,9 @@ __und_usr:
* Emulators may wish to make use of the following registers:
* r0 = instruction opcode.
* r2 = PC+4
+ * r9 = normal "successful" return address
* r10 = this threads thread_info structure.
+ * lr = unrecognised instruction return address
*/
call_fpe:
tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
@@ -545,10 +547,12 @@ do_fpe:
.data
ENTRY(fp_enter)
- .word fpundefinstr
+ .word no_fp
.text
-fpundefinstr:
+no_fp: mov pc, lr
+
+__und_usr_unknown:
mov r0, sp
adr lr, ret_from_exception
b do_undefinstr
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index bda0748ffb0..cf495a3084b 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -22,30 +22,35 @@
#include <asm/thread_info.h>
#include <asm/system.h>
-#define KERNEL_RAM_ADDR (PAGE_OFFSET + TEXT_OFFSET)
+#if (PHYS_OFFSET & 0x001fffff)
+#error "PHYS_OFFSET must be at an even 2MiB boundary!"
+#endif
+
+#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
+#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET)
/*
* swapper_pg_dir is the virtual address of the initial page table.
- * We place the page tables 16K below KERNEL_RAM_ADDR. Therefore, we must
- * make sure that KERNEL_RAM_ADDR is correctly set. Currently, we expect
+ * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must
+ * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect
* the least significant 16 bits to be 0x8000, but we could probably
- * relax this restriction to KERNEL_RAM_ADDR >= PAGE_OFFSET + 0x4000.
+ * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000.
*/
-#if (KERNEL_RAM_ADDR & 0xffff) != 0x8000
-#error KERNEL_RAM_ADDR must start at 0xXXXX8000
+#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
+#error KERNEL_RAM_VADDR must start at 0xXXXX8000
#endif
.globl swapper_pg_dir
- .equ swapper_pg_dir, KERNEL_RAM_ADDR - 0x4000
+ .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
.macro pgtbl, rd
- ldr \rd, =(__virt_to_phys(KERNEL_RAM_ADDR - 0x4000))
+ ldr \rd, =(KERNEL_RAM_PADDR - 0x4000)
.endm
#ifdef CONFIG_XIP_KERNEL
#define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
#else
-#define TEXTADDR KERNEL_RAM_ADDR
+#define TEXTADDR KERNEL_RAM_VADDR
#endif
/*
@@ -250,7 +255,8 @@ __create_page_tables:
* Then map first 1MB of ram in case it contains our boot params.
*/
add r0, r4, #PAGE_OFFSET >> 18
- orr r6, r7, #PHYS_OFFSET
+ orr r6, r7, #(PHYS_OFFSET & 0xff000000)
+ orr r6, r6, #(PHYS_OFFSET & 0x00e00000)
str r6, [r0]
#ifdef CONFIG_XIP_KERNEL
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 238dd9b6db8..bbab134cd82 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -354,9 +354,6 @@ static void __init setup_processor(void)
#ifndef CONFIG_ARM_THUMB
elf_hwcap &= ~HWCAP_THUMB;
#endif
-#ifndef CONFIG_VFP
- elf_hwcap &= ~HWCAP_VFP;
-#endif
cpu_proc_init();
}
@@ -858,6 +855,7 @@ static const char *hwcap_str[] = {
"edsp",
"java",
"iwmmxt",
+ "crunch",
NULL
};
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 00c18d35913..3d4fcbc1627 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -328,3 +328,16 @@ asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
{
return sys_fadvise64_64(fd, offset, len, advice);
}
+
+/*
+ * Yet more syscall fsckage - we can't fit sys_sync_file_range's
+ * arguments into the available registers with EABI. So, let's
+ * create an ARM specific syscall for this which has _sane_
+ * arguments. (This incidentally also has an ABI-independent
+ * argument layout.)
+ */
+asmlinkage long sys_arm_sync_file_range(int fd, unsigned int flags,
+ loff_t offset, loff_t nbytes)
+{
+ return sys_sync_file_range(fd, offset, nbytes, flags);
+}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 6ff5e3ff6cb..3c8cdcfe8d4 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -29,6 +29,8 @@
#include <linux/timer.h>
#include <linux/irq.h>
+#include <linux/mc146818rtc.h>
+
#include <asm/leds.h>
#include <asm/thread_info.h>
#include <asm/mach/time.h>
@@ -85,6 +87,17 @@ unsigned long long __attribute__((weak)) sched_clock(void)
return (unsigned long long)jiffies * (1000000000 / HZ);
}
+/*
+ * An implementation of printk_clock() independent from
+ * sched_clock(). This avoids non-bootable kernels when
+ * printk_clock is enabled.
+ */
+unsigned long long printk_clock(void)
+{
+ return (unsigned long long)(jiffies - INITIAL_JIFFIES) *
+ (1000000000 / HZ);
+}
+
static unsigned long next_rtc_update;
/*
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 042a12982e9..908915675ed 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -27,6 +27,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/traps.h>
+#include <asm/io.h>
#include "ptrace.h"
#include "signal.h"
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c
index 4641b99db0e..57fac7203fe 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c
+++ b/arch/arm/mach-at91rm9200/at91rm9200_devices.c
@@ -272,7 +272,7 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */
/* nWAIT is _not_ a default setting */
- at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */
+ at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */
cf_data = *data;
platform_device_register(&at91rm9200_cf_device);
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c
index 203f073a53e..b14871adc30 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260.c
+++ b/arch/arm/mach-at91rm9200/at91sam9260.c
@@ -16,6 +16,7 @@
#include <asm/mach/map.h>
#include <asm/arch/at91sam9260.h>
#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
#include "generic.h"
#include "clock.h"
@@ -212,7 +213,7 @@ static struct at91_gpio_bank at91sam9260_gpio[] = {
static void at91sam9260_reset(void)
{
-#warning "Implement CPU reset"
+ at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
}
diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91rm9200/at91sam9260_devices.c
index a6c596dc451..f42d3a40ec3 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260_devices.c
+++ b/arch/arm/mach-at91rm9200/at91sam9260_devices.c
@@ -18,6 +18,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/at91sam9260.h>
#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9260_matrix.h>
#include "generic.h"
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c
index 5a82f35da2e..d242bb885c6 100644
--- a/arch/arm/mach-at91rm9200/at91sam9261.c
+++ b/arch/arm/mach-at91rm9200/at91sam9261.c
@@ -16,6 +16,7 @@
#include <asm/mach/map.h>
#include <asm/arch/at91sam9261.h>
#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
#include "generic.h"
#include "clock.h"
@@ -207,7 +208,7 @@ static struct at91_gpio_bank at91sam9261_gpio[] = {
static void at91sam9261_reset(void)
{
-#warning "Implement CPU reset"
+ at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
}
diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91rm9200/board-sam9260ek.c
index ffca9bdec37..da5d58ac870 100644
--- a/arch/arm/mach-at91rm9200/board-sam9260ek.c
+++ b/arch/arm/mach-at91rm9200/board-sam9260ek.c
@@ -119,6 +119,7 @@ static struct spi_board_info ek_spi_devices[] = {
* MACB Ethernet device
*/
static struct __initdata eth_platform_data ek_macb_data = {
+ .phy_irq_pin = AT91_PIN_PA7,
.is_rmii = 1,
};
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 3f188508c39..af22659c8a2 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -20,7 +20,6 @@
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/at91_pio.h>
-#include <asm/arch/at91_pmc.h>
#include <asm/arch/gpio.h>
#include "generic.h"
@@ -224,17 +223,17 @@ static u32 backups[MAX_GPIO_BANKS];
static int gpio_irq_set_wake(unsigned pin, unsigned state)
{
unsigned mask = pin_to_mask(pin);
+ unsigned bank = (pin - PIN_BASE) / 32;
- pin -= PIN_BASE;
- pin /= 32;
-
- if (unlikely(pin >= MAX_GPIO_BANKS))
+ if (unlikely(bank >= MAX_GPIO_BANKS))
return -EINVAL;
if (state)
- wakeups[pin] |= mask;
+ wakeups[bank] |= mask;
else
- wakeups[pin] &= ~mask;
+ wakeups[bank] &= ~mask;
+
+ set_irq_wake(gpio[bank].id, state);
return 0;
}
@@ -246,29 +245,15 @@ void at91_gpio_suspend(void)
for (i = 0; i < gpio_banks; i++) {
u32 pio = gpio[i].offset;
- /*
- * Note: drivers should have disabled GPIO interrupts that
- * aren't supposed to be wakeup sources.
- * But that is not much good on ARM..... disable_irq() does
- * not update the hardware immediately, so the hardware mask
- * (IMR) has the wrong value (not current, too much is
- * permitted).
- *
- * Our workaround is to disable all non-wakeup IRQs ...
- * which is exactly what correct drivers asked for in the
- * first place!
- */
backups[i] = at91_sys_read(pio + PIO_IMR);
at91_sys_write(pio + PIO_IDR, backups[i]);
at91_sys_write(pio + PIO_IER, wakeups[i]);
- if (!wakeups[i]) {
- disable_irq_wake(gpio[i].id);
- at91_sys_write(AT91_PMC_PCDR, 1 << gpio[i].id);
- } else {
- enable_irq_wake(gpio[i].id);
+ if (!wakeups[i])
+ clk_disable(gpio[i].clock);
+ else {
#ifdef CONFIG_PM_DEBUG
- printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]);
+ printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
#endif
}
}
@@ -281,9 +266,11 @@ void at91_gpio_resume(void)
for (i = 0; i < gpio_banks; i++) {
u32 pio = gpio[i].offset;
+ if (!wakeups[i])
+ clk_enable(gpio[i].clock);
+
at91_sys_write(pio + PIO_IDR, wakeups[i]);
at91_sys_write(pio + PIO_IER, backups[i]);
- at91_sys_write(AT91_PMC_PCER, 1 << gpio[i].id);
}
}
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index d649b39711d..6b26346191c 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -477,4 +477,8 @@ void __init ep93xx_init_devices(void)
platform_device_register(&ep93xx_rtc_device);
platform_device_register(&ep93xx_ohci_device);
+
+#ifdef CONFIG_CRUNCH
+ elf_hwcap |= HWCAP_CRUNCH;
+#endif
}
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0b27d79f2ef..02272aa36e9 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -9,6 +9,8 @@
obj-y += irq.o time.o dma.o generic.o
+obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
+
# Specific board support
obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c
new file mode 100644
index 00000000000..4f66e90db74
--- /dev/null
+++ b/arch/arm/mach-imx/cpufreq.c
@@ -0,0 +1,299 @@
+/*
+ * cpu.c: clock scaling for the iMX
+ *
+ * Copyright (C) 2000 2001, The Delft University of Technology
+ * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ * Copyright (C) 2006 Inky Lung <ilung@cwlinux.com>
+ * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ * Based on SA1100 version written by:
+ * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version
+ * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*#define DEBUG*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/system.h>
+
+#include <asm/hardware.h>
+
+#include "generic.h"
+
+#ifndef __val2mfld
+#define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask))
+#endif
+#ifndef __mfld2val
+#define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1)))
+#endif
+
+#define CR_920T_CLOCK_MODE 0xC0000000
+#define CR_920T_FASTBUS_MODE 0x00000000
+#define CR_920T_ASYNC_MODE 0xC0000000
+
+static u32 mpctl0_at_boot;
+
+static void imx_set_async_mode(void)
+{
+ adjust_cr(CR_920T_CLOCK_MODE, CR_920T_ASYNC_MODE);
+}
+
+static void imx_set_fastbus_mode(void)
+{
+ adjust_cr(CR_920T_CLOCK_MODE, CR_920T_FASTBUS_MODE);
+}
+
+static void imx_set_mpctl0(u32 mpctl0)
+{
+ unsigned long flags;
+
+ if (mpctl0 == 0) {
+ local_irq_save(flags);
+ CSCR &= ~CSCR_MPEN;
+ local_irq_restore(flags);
+ return;
+ }
+
+ local_irq_save(flags);
+ MPCTL0 = mpctl0;
+ CSCR |= CSCR_MPEN;
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_compute_mpctl - compute new PLL parameters
+ * @new_mpctl: pointer to location assigned by new PLL control register value
+ * @cur_mpctl: current PLL control register parameters
+ * @freq: required frequency in Hz
+ * @relation: is one of %CPUFREQ_RELATION_L (supremum)
+ * and %CPUFREQ_RELATION_H (infimum)
+ */
+long imx_compute_mpctl(u32 *new_mpctl, u32 cur_mpctl, unsigned long freq, int relation)
+{
+ u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
+ u32 mfi;
+ u32 mfn;
+ u32 mfd;
+ u32 pd;
+ unsigned long long ll;
+ long l;
+ long quot;
+
+ /* Fdppl=2*Fref*(MFI+MFN/(MFD+1))/(PD+1) */
+ /* PD=<0,15>, MFD=<1,1023>, MFI=<5,15> MFN=<0,1022> */
+
+ if (cur_mpctl) {
+ mfd = ((cur_mpctl >> 16) & 0x3ff) + 1;
+ pd = ((cur_mpctl >> 26) & 0xf) + 1;
+ } else {
+ pd=2; mfd=313;
+ }
+
+ /* pd=2; mfd=313; mfi=8; mfn=183; */
+ /* (MFI+MFN/(MFD)) = Fdppl / (2*Fref) * (PD); */
+
+ quot = (f_ref + (1 << 9)) >> 10;
+ l = (freq * pd + quot) / (2 * quot);
+ mfi = l >> 10;
+ mfn = ((l & ((1 << 10) - 1)) * mfd + (1 << 9)) >> 10;
+
+ mfd -= 1;
+ pd -= 1;
+
+ *new_mpctl = ((mfi & 0xf) << 10) | (mfn & 0x3ff) | ((mfd & 0x3ff) << 16)
+ | ((pd & 0xf) << 26);
+
+ ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
+ quot = (pd+1) * (1<<16);
+ ll += quot / 2;
+ do_div(ll, quot);
+ freq = ll;
+
+ pr_debug(KERN_DEBUG "imx: new PLL parameters pd=%d mfd=%d mfi=%d mfn=%d, freq=%ld\n",
+ pd, mfd, mfi, mfn, freq);
+
+ return freq;
+}
+
+
+static int imx_verify_speed(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+ return 0;
+}
+
+static unsigned int imx_get_speed(unsigned int cpu)
+{
+ unsigned int freq;
+ unsigned int cr;
+ unsigned int cscr;
+ unsigned int bclk_div;
+
+ if (cpu)
+ return 0;
+
+ cscr = CSCR;
+ bclk_div = __mfld2val(CSCR_BCLK_DIV, cscr) + 1;
+ cr = get_cr();
+
+ if((cr & CR_920T_CLOCK_MODE) == CR_920T_FASTBUS_MODE) {
+ freq = imx_get_system_clk();
+ freq = (freq + bclk_div/2) / bclk_div;
+ } else {
+ freq = imx_get_mcu_clk();
+ if (cscr & CSCR_MPU_PRESC)
+ freq /= 2;
+ }
+
+ freq = (freq + 500) / 1000;
+
+ return freq;
+}
+
+static int imx_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ u32 mpctl0 = 0;
+ u32 cscr;
+ unsigned long flags;
+ long freq;
+ long sysclk;
+ unsigned int bclk_div = 1;
+
+ /*
+ * Some governors do not respects CPU and policy lower limits
+ * which leads to bad things (division by zero etc), ensure
+ * that such things do not happen.
+ */
+ if(target_freq < policy->cpuinfo.min_freq)
+ target_freq = policy->cpuinfo.min_freq;
+
+ if(target_freq < policy->min)
+ target_freq = policy->min;
+
+ freq = target_freq * 1000;
+
+ pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n",
+ freq, mpctl0_at_boot);
+
+ sysclk = imx_get_system_clk();
+
+ if (freq > sysclk + 1000000) {
+ freq = imx_compute_mpctl(&mpctl0, mpctl0_at_boot, freq, relation);
+ if (freq < 0) {
+ printk(KERN_WARNING "imx: target frequency %ld Hz cannot be set\n", freq);
+ return -EINVAL;
+ }
+ } else {
+ if(freq + 1000 < sysclk) {
+ if (relation == CPUFREQ_RELATION_L)
+ bclk_div = (sysclk - 1000) / freq;
+ else
+ bclk_div = (sysclk + freq + 1000) / freq;
+
+ if(bclk_div > 16)
+ bclk_div = 16;
+ }
+ freq = (sysclk + bclk_div / 2) / bclk_div;
+ }
+
+ freqs.old = imx_get_speed(0);
+ freqs.new = (freq + 500) / 1000;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ local_irq_save(flags);
+
+ imx_set_fastbus_mode();
+
+ imx_set_mpctl0(mpctl0);
+
+ cscr = CSCR;
+ cscr &= ~CSCR_BCLK_DIV;
+ cscr |= __val2mfld(CSCR_BCLK_DIV, bclk_div - 1);
+ CSCR = cscr;
+
+ if(mpctl0) {
+ CSCR |= CSCR_MPLL_RESTART;
+
+ /* Wait until MPLL is stablized */
+ while( CSCR & CSCR_MPLL_RESTART );
+
+ imx_set_async_mode();
+ }
+
+ local_irq_restore(flags);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ pr_debug(KERN_INFO "imx: set frequency %ld Hz, running from %s\n",
+ freq, mpctl0? "MPLL": "SPLL");
+
+ return 0;
+}
+
+static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+ printk(KERN_INFO "i.MX cpu freq change driver v1.0\n");
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ policy->cur = policy->min = policy->max = imx_get_speed(0);
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.min_freq = 8000;
+ policy->cpuinfo.max_freq = 200000;
+ /* Manual states, that PLL stabilizes in two CLK32 periods */
+ policy->cpuinfo.transition_latency = 4 * 1000000000LL / CLK32;
+ return 0;
+}
+
+static struct cpufreq_driver imx_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = imx_verify_speed,
+ .target = imx_set_target,
+ .get = imx_get_speed,
+ .init = imx_cpufreq_driver_init,
+ .name = "imx",
+};
+
+static int __init imx_cpufreq_init(void)
+{
+
+ mpctl0_at_boot = 0;
+
+ if((CSCR & CSCR_MPEN) &&
+ ((get_cr() & CR_920T_CLOCK_MODE) != CR_920T_FASTBUS_MODE))
+ mpctl0_at_boot = MPCTL0;
+
+ return cpufreq_register_driver(&imx_driver);
+}
+
+arch_initcall(imx_cpufreq_init);
+
diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c
index fbf9f88e46e..e79a1b62600 100644
--- a/arch/arm/mach-iop13xx/io.c
+++ b/arch/arm/mach-iop13xx/io.c
@@ -21,6 +21,25 @@
#include <asm/hardware.h>
#include <asm/io.h>
+void * __iomem __iop13xx_io(unsigned long io_addr)
+{
+ void __iomem * io_virt;
+
+ switch (io_addr) {
+ case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
+ io_virt = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(io_addr);
+ break;
+ case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA:
+ io_virt = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(io_addr);
+ break;
+ default:
+ BUG();
+ }
+
+ return io_virt;
+}
+EXPORT_SYMBOL(__iop13xx_io);
+
void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
unsigned long flags)
{
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index ee595786cd2..2a1bbfe9896 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -88,11 +88,11 @@ static struct sys_timer iq81340mc_timer = {
MACHINE_START(IQ81340MC, "Intel IQ81340MC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .phys_io = PHYS_IO,
- .io_pg_offst = IO_PG_OFFSET,
+ .phys_io = IOP13XX_PMMR_PHYS_MEM_BASE,
+ .io_pg_offst = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
.timer = &iq81340mc_timer,
- .boot_params = BOOT_PARAM_OFFSET,
.init_machine = iq81340mc_init,
MACHINE_END
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index 6677e14b61b..5ad2b62c9bf 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -90,11 +90,11 @@ static struct sys_timer iq81340sc_timer = {
MACHINE_START(IQ81340SC, "Intel IQ81340SC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .phys_io = PHYS_IO,
- .io_pg_offst = IO_PG_OFFSET,
+ .phys_io = IOP13XX_PMMR_PHYS_MEM_BASE,
+ .io_pg_offst = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
.timer = &iq81340sc_timer,
- .boot_params = BOOT_PARAM_OFFSET,
.init_machine = iq81340sc_init,
MACHINE_END
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c
index c4d9c8c5579..dbbc07c38b1 100644
--- a/arch/arm/mach-iop13xx/irq.c
+++ b/arch/arm/mach-iop13xx/irq.c
@@ -222,25 +222,29 @@ iop13xx_irq_unmask3(unsigned int irq)
iop13xx_cp6_restore(cp_flags);
}
-static struct irqchip iop13xx_irqchip0 = {
+static struct irq_chip iop13xx_irqchip1 = {
+ .name = "IOP13xx-1",
.ack = iop13xx_irq_mask0,
.mask = iop13xx_irq_mask0,
.unmask = iop13xx_irq_unmask0,
};
-static struct irqchip iop13xx_irqchip1 = {
+static struct irq_chip iop13xx_irqchip2 = {
+ .name = "IOP13xx-2",
.ack = iop13xx_irq_mask1,
.mask = iop13xx_irq_mask1,
.unmask = iop13xx_irq_unmask1,
};
-static struct irqchip iop13xx_irqchip2 = {
+static struct irq_chip iop13xx_irqchip3 = {
+ .name = "IOP13xx-3",
.ack = iop13xx_irq_mask2,
.mask = iop13xx_irq_mask2,
.unmask = iop13xx_irq_unmask2,
};
-static struct irqchip iop13xx_irqchip3 = {
+static struct irq_chip iop13xx_irqchip4 = {
+ .name = "IOP13xx-4",
.ack = iop13xx_irq_mask3,
.mask = iop13xx_irq_mask3,
.unmask = iop13xx_irq_unmask3,
@@ -270,15 +274,15 @@ void __init iop13xx_init_irq(void)
for(i = 0; i < NR_IOP13XX_IRQS; i++) {
if (i < 32)
- set_irq_chip(i, &iop13xx_irqchip0);
- else if (i < 64)
set_irq_chip(i, &iop13xx_irqchip1);
- else if (i < 96)
+ else if (i < 64)
set_irq_chip(i, &iop13xx_irqchip2);
- else
+ else if (i < 96)
set_irq_chip(i, &iop13xx_irqchip3);
+ else
+ set_irq_chip(i, &iop13xx_irqchip4);
- set_irq_handler(i, do_level_IRQ);
+ set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index 3756d2ccb1a..5fbeb28d04b 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -337,7 +337,7 @@ void __init iop13xx_platform_init(void)
#ifdef CONFIG_MTD_PHYSMAP
iq8134x_flash_resource.end = iq8134x_flash_resource.start +
- iq8134x_probe_flash_size();
+ iq8134x_probe_flash_size() - 1;
if (iq8134x_flash_resource.end > iq8134x_flash_resource.start)
iop13xx_devices[plat_idx++] = &iq8134x_flash;
else
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index 0993336c0b5..5773b55ef4a 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -19,6 +19,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -26,15 +28,6 @@
#include <asm/arch/netx-regs.h>
/*
- * Returns number of us since last clock interrupt. Note that interrupts
- * will have been disabled by do_gettimeoffset()
- */
-static unsigned long netx_gettimeoffset(void)
-{
- return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100;
-}
-
-/*
* IRQ handler for the timer
*/
static irqreturn_t
@@ -43,6 +36,7 @@ netx_timer_interrupt(int irq, void *dev_id)
write_seqlock(&xtime_lock);
timer_tick();
+
write_sequnlock(&xtime_lock);
/* acknowledge interrupt */
@@ -51,13 +45,26 @@ netx_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-
static struct irqaction netx_timer_irq = {
.name = "NetX Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = netx_timer_interrupt,
};
+cycle_t netx_get_cycles(void)
+{
+ return readl(NETX_GPIO_COUNTER_CURRENT(1));
+}
+
+static struct clocksource clocksource_netx = {
+ .name = "netx_timer",
+ .rating = 200,
+ .read = netx_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .is_continuous = 1,
+};
+
/*
* Set up timer interrupt
*/
@@ -80,9 +87,20 @@ static void __init netx_timer_init(void)
NETX_GPIO_COUNTER_CTRL(0));
setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq);
+
+ /* Setup timer one for clocksource */
+ writel(0, NETX_GPIO_COUNTER_CTRL(1));
+ writel(0, NETX_GPIO_COUNTER_CURRENT(1));
+ writel(0xFFFFFFFF, NETX_GPIO_COUNTER_MAX(1));
+
+ writel(NETX_GPIO_COUNTER_CTRL_RUN,
+ NETX_GPIO_COUNTER_CTRL(1));
+
+ clocksource_netx.mult =
+ clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift);
+ clocksource_register(&clocksource_netx);
}
struct sys_timer netx_timer = {
- .init = netx_timer_init,
- .offset = netx_gettimeoffset,
+ .init = netx_timer_init,
};
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index d135568dc9e..8781aaeb576 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -43,6 +43,7 @@ config MACH_OMAP_H3
config MACH_OMAP_OSK
bool "TI OSK Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ select TPS65010
help
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 3a622801d7b..7d0cf7af88c 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 03d6905ba49..878ff9181d0 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -22,6 +22,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/onenand.h>
+#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index f4f04d87df3..d8f57824423 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -17,6 +17,7 @@
#include <linux/spinlock.h>
#include <asm/io.h>
+#include <asm/mach-types.h>
#include <asm/arch/gpmc.h>
#undef DEBUG
@@ -338,19 +339,13 @@ void __init gpmc_mem_init(void)
int cs;
unsigned long boot_rom_space = 0;
- if (cpu_is_omap242x()) {
- u32 l;
- l = omap_readl(OMAP242X_CONTROL_STATUS);
- /* In case of internal boot the 1st MB is redirected to the
- * boot ROM memory space.
- */
- if (l & (1 << 3))
- boot_rom_space = BOOT_ROM_SPACE;
- } else
- /* We assume internal boot if the mode can't be
- * determined.
- */
- boot_rom_space = BOOT_ROM_SPACE;
+ /* never allocate the first page, to facilitate bug detection;
+ * even if we didn't boot from ROM.
+ */
+ boot_rom_space = BOOT_ROM_SPACE;
+ /* In apollon the CS0 is mapped as 0x0000 0000 */
+ if (machine_is_omap_apollon())
+ boot_rom_space = 0;
gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
gpmc_mem_root.end = GPMC_MEM_END;
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
index b457ca0a431..777564c90a1 100644
--- a/arch/arm/mach-pnx4008/Makefile
+++ b/arch/arm/mach-pnx4008/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
new file mode 100644
index 00000000000..6f308827c4f
--- /dev/null
+++ b/arch/arm/mach-pnx4008/i2c.c
@@ -0,0 +1,167 @@
+/*
+ * I2C initialization for PNX4008.
+ *
+ * Author: Vitaly Wool <vitalywool@gmail.com>
+ *
+ * 2005-2006 (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/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c-pnx.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/i2c.h>
+
+static int set_clock_run(struct platform_device *pdev)
+{
+ struct clk *clk;
+ char name[10];
+ int retval = 0;
+
+ snprintf(name, 10, "i2c%d_ck", pdev->id);
+ clk = clk_get(&pdev->dev, name);
+ if (!IS_ERR(clk)) {
+ clk_set_rate(clk, 1);
+ clk_put(clk);
+ } else
+ retval = -ENOENT;
+
+ return retval;
+}
+
+static int set_clock_stop(struct platform_device *pdev)
+{
+ struct clk *clk;
+ char name[10];
+ int retval = 0;
+
+ snprintf(name, 10, "i2c%d_ck", pdev->id);
+ clk = clk_get(&pdev->dev, name);
+ if (!IS_ERR(clk)) {
+ clk_set_rate(clk, 0);
+ clk_put(clk);
+ } else
+ retval = -ENOENT;
+
+ return retval;
+}
+
+static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int retval = 0;
+#ifdef CONFIG_PM
+ retval = set_clock_run(pdev);
+#endif
+ return retval;
+}
+
+static int i2c_pnx_resume(struct platform_device *pdev)
+{
+ int retval = 0;
+#ifdef CONFIG_PM
+ retval = set_clock_run(pdev);
+#endif
+ return retval;
+}
+
+static u32 calculate_input_freq(struct platform_device *pdev)
+{
+ return HCLK_MHZ;
+}
+
+
+static struct i2c_pnx_algo_data pnx_algo_data0 = {
+ .base = PNX4008_I2C1_BASE,
+ .irq = I2C_1_INT,
+};
+
+static struct i2c_pnx_algo_data pnx_algo_data1 = {
+ .base = PNX4008_I2C2_BASE,
+ .irq = I2C_2_INT,
+};
+
+static struct i2c_pnx_algo_data pnx_algo_data2 = {
+ .base = (PNX4008_USB_CONFIG_BASE + 0x300),
+ .irq = USB_I2C_INT,
+};
+
+static struct i2c_adapter pnx_adapter0 = {
+ .name = I2C_CHIP_NAME "0",
+ .algo_data = &pnx_algo_data0,
+};
+static struct i2c_adapter pnx_adapter1 = {
+ .name = I2C_CHIP_NAME "1",
+ .algo_data = &pnx_algo_data1,
+};
+
+static struct i2c_adapter pnx_adapter2 = {
+ .name = "USB-I2C",
+ .algo_data = &pnx_algo_data2,
+};
+
+static struct i2c_pnx_data i2c0_data = {
+ .suspend = i2c_pnx_suspend,
+ .resume = i2c_pnx_resume,
+ .calculate_input_freq = calculate_input_freq,
+ .set_clock_run = set_clock_run,
+ .set_clock_stop = set_clock_stop,
+ .adapter = &pnx_adapter0,
+};
+
+static struct i2c_pnx_data i2c1_data = {
+ .suspend = i2c_pnx_suspend,
+ .resume = i2c_pnx_resume,
+ .calculate_input_freq = calculate_input_freq,
+ .set_clock_run = set_clock_run,
+ .set_clock_stop = set_clock_stop,
+ .adapter = &pnx_adapter1,
+};
+
+static struct i2c_pnx_data i2c2_data = {
+ .suspend = i2c_pnx_suspend,
+ .resume = i2c_pnx_resume,
+ .calculate_input_freq = calculate_input_freq,
+ .set_clock_run = set_clock_run,
+ .set_clock_stop = set_clock_stop,
+ .adapter = &pnx_adapter2,
+};
+
+static struct platform_device i2c0_device = {
+ .name = "pnx-i2c",
+ .id = 0,
+ .dev = {
+ .platform_data = &i2c0_data,
+ },
+};
+
+static struct platform_device i2c1_device = {
+ .name = "pnx-i2c",
+ .id = 1,
+ .dev = {
+ .platform_data = &i2c1_data,
+ },
+};
+
+static struct platform_device i2c2_device = {
+ .name = "pnx-i2c",
+ .id = 2,
+ .dev = {
+ .platform_data = &i2c2_data,
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &i2c0_device,
+ &i2c1_device,
+ &i2c2_device,
+};
+
+void __init pnx4008_register_i2c_devices(void)
+{
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 9e3d0bdcba0..5c0a10041cd 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -75,28 +75,28 @@ endmenu
config MACH_POODLE
bool "Enable Sharp SL-5600 (Poodle) Support"
- depends PXA_SHARPSL_25x
+ depends on PXA_SHARPSL_25x
select SHARP_LOCOMO
select PXA_SSP
config MACH_CORGI
bool "Enable Sharp SL-C700 (Corgi) Support"
- depends PXA_SHARPSL_25x
+ depends on PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_SHEPHERD
bool "Enable Sharp SL-C750 (Shepherd) Support"
- depends PXA_SHARPSL_25x
+ depends on PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_HUSKY
bool "Enable Sharp SL-C760 (Husky) Support"
- depends PXA_SHARPSL_25x
+ depends on PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_AKITA
bool "Enable Sharp SL-1000 (Akita) Support"
- depends PXA_SHARPSL_27x
+ depends on PXA_SHARPSL_27x
select PXA_SHARP_Cxx00
select MACH_SPITZ
select I2C
@@ -104,17 +104,17 @@ config MACH_AKITA
config MACH_SPITZ
bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
- depends PXA_SHARPSL_27x
+ depends on PXA_SHARPSL_27x
select PXA_SHARP_Cxx00
config MACH_BORZOI
bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
- depends PXA_SHARPSL_27x
+ depends on PXA_SHARPSL_27x
select PXA_SHARP_Cxx00
config MACH_TOSA
bool "Enable Sharp SL-6000x (Tosa) Support"
- depends PXA_SHARPSL_25x
+ depends on PXA_SHARPSL_25x
config PXA25x
bool
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 6ae605857ca..9de1278d234 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -76,7 +76,9 @@ unsigned long long sched_clock(void)
/*
* 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
* any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
- * years range which is nice, but with higher computation cost.
+ * years range and truncation to unsigned long long limits it to
+ * sched_clock's max range of ~584 years. This is nice but with
+ * higher computation cost.
*/
{
union {
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index b9146686102..ee2beb40041 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -18,6 +18,7 @@
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/clocksource.h>
#include <asm/system.h>
#include <asm/hardware.h>
@@ -48,27 +49,6 @@ static int pxa_set_rtc(void)
return 0;
}
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long pxa_gettimeoffset (void)
-{
- long ticks_to_match, elapsed, usec;
-
- /* Get ticks before next timer match */
- ticks_to_match = OSMR0 - OSCR;
-
- /* We need elapsed ticks since last match */
- elapsed = LATCH - ticks_to_match;
-
- /* don't get fooled by the workaround in pxa_timer_interrupt() */
- if (elapsed <= 0)
- return 0;
-
- /* Now convert them to usec */
- usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
-
- return usec;
-}
-
#ifdef CONFIG_NO_IDLE_HZ
static unsigned long initial_match;
static int match_posponed;
@@ -121,6 +101,20 @@ static struct irqaction pxa_timer_irq = {
.handler = pxa_timer_interrupt,
};
+static cycle_t pxa_get_cycles(void)
+{
+ return OSCR;
+}
+
+static struct clocksource clocksource_pxa = {
+ .name = "pxa_timer",
+ .rating = 200,
+ .read = pxa_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .is_continuous = 1,
+};
+
static void __init pxa_timer_init(void)
{
struct timespec tv;
@@ -139,6 +133,14 @@ static void __init pxa_timer_init(void)
OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */
OSMR0 = OSCR + LATCH; /* set initial match */
local_irq_restore(flags);
+
+ /*
+ * OSCR runs continuously on PXA and is not written to,
+ * so we can use it as clock source directly.
+ */
+ clocksource_pxa.mult =
+ clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_pxa.shift);
+ clocksource_register(&clocksource_pxa);
}
#ifdef CONFIG_NO_IDLE_HZ
@@ -211,7 +213,6 @@ struct sys_timer pxa_timer = {
.init = pxa_timer_init,
.suspend = pxa_timer_suspend,
.resume = pxa_timer_resume,
- .offset = pxa_gettimeoffset,
#ifdef CONFIG_NO_IDLE_HZ
.dyn_tick = &pxa_dyn_tick,
#endif
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index c1827d021ba..119c64b7223 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -393,10 +393,6 @@ static struct pxafb_mach_info sharp_lcd = {
.pxafb_backlight_power = board_backlight_power,
};
-static void __init trizeps4_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi)
-{
-}
-
static void __init trizeps4_init(void)
{
platform_add_devices(trizeps4_devices, ARRAY_SIZE(trizeps4_devices));
@@ -469,7 +465,6 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
- .fixup = trizeps4_fixup,
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
.init_irq = pxa_init_irq,
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 68c67053f47..84d3fe76e94 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -141,6 +141,19 @@ struct platform_device realview_smc91x_device = {
.resource = realview_smc91x_resources,
};
+static struct resource realview_i2c_resource = {
+ .start = REALVIEW_I2C_BASE,
+ .end = REALVIEW_I2C_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+struct platform_device realview_i2c_device = {
+ .name = "versatile-i2c",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &realview_i2c_resource,
+};
+
#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
static unsigned int realview_mmc_status(struct device *dev)
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 93e86d9f439..2b53420f9c1 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -108,6 +108,7 @@ static struct amba_device name##_device = { \
extern struct platform_device realview_flash_device;
extern struct platform_device realview_smc91x_device;
+extern struct platform_device realview_i2c_device;
extern struct mmc_platform_data realview_mmc0_plat_data;
extern struct mmc_platform_data realview_mmc1_plat_data;
extern struct clk realview_clcd_clk;
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 84a959530fb..9741b4d3c9c 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -155,6 +155,7 @@ static void __init realview_eb_init(void)
platform_device_register(&realview_flash_device);
platform_device_register(&realview_smc91x_device);
+ platform_device_register(&realview_i2c_device);
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 9f46bf330bc..eb4ec411312 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -5,6 +5,7 @@ menu "S3C24XX Implementations"
config MACH_AML_M5900
bool "AML M5900 Series"
select CPU_S3C2410
+ select PM_SIMTEC if PM
help
Say Y here if you are using the American Microsystems M5900 Series
<http://www.amltd.com>
@@ -12,6 +13,7 @@ config MACH_AML_M5900
config MACH_ANUBIS
bool "Simtec Electronics ANUBIS"
select CPU_S3C2440
+ select PM_SIMTEC if PM
help
Say Y here if you are using the Simtec Electronics ANUBIS
development system
@@ -19,6 +21,7 @@ config MACH_ANUBIS
config MACH_OSIRIS
bool "Simtec IM2440D20 (OSIRIS) module"
select CPU_S3C2440
+ select PM_SIMTEC if PM
help
Say Y here if you are using the Simtec IM2440D20 module, also
known as the Osiris.
@@ -26,6 +29,7 @@ config MACH_OSIRIS
config ARCH_BAST
bool "Simtec Electronics BAST (EB2410ITX)"
select CPU_S3C2410
+ select PM_SIMTEC if PM
select ISA
help
Say Y here if you are using the Simtec Electronics EB2410ITX
@@ -43,14 +47,13 @@ config BAST_PC104_IRQ
config PM_H1940
bool
- depends on PM
help
Internal node for H1940 and related PM
config ARCH_H1940
bool "IPAQ H1940"
select CPU_S3C2410
- select PM_H1940
+ select PM_H1940 if PM
help
Say Y here if you are using the HP IPAQ H1940
@@ -112,6 +115,7 @@ config MACH_SMDK2413
config MACH_VR1000
bool "Thorcom VR1000"
+ select PM_SIMTEC if PM
select CPU_S3C2410
help
Say Y here if you are using the Thorcom VR1000 board.
@@ -122,7 +126,7 @@ config MACH_VR1000
config MACH_RX3715
bool "HP iPAQ rx3715"
select CPU_S3C2440
- select PM_H1940
+ select PM_H1940 if PM
help
Say Y here if you are using the HP iPAQ rx3715.
@@ -156,7 +160,6 @@ config S3C2410_CLOCK
config S3C2410_PM
bool
- depends on CONFIG_PM
help
Power Management code common to S3C2410 and better
@@ -171,7 +174,7 @@ config CPU_S3C2410
bool
depends on ARCH_S3C2410
select S3C2410_CLOCK
- select S3C2410_PM
+ select S3C2410_PM if PM
help
Support for S3C2410 and S3C2410A family from the S3C24XX line
of Samsung Mobile CPUs.
@@ -186,14 +189,13 @@ config CPU_S3C2412_ONLY
config S3C2412_PM
bool
- default y if PM
- depends on CPU_S3C2412
help
Internal config node to apply S3C2412 power management
config CPU_S3C2412
bool
depends on ARCH_S3C2410
+ select S3C2412_PM if PM
help
Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
@@ -207,7 +209,7 @@ config CPU_S3C2440
bool
depends on ARCH_S3C2410
select S3C2410_CLOCK
- select S3C2410_PM
+ select S3C2410_PM if PM
select CPU_S3C244X
help
Support for S3C2440 Samsung Mobile CPU based systems.
@@ -216,7 +218,7 @@ config CPU_S3C2442
bool
depends on ARCH_S3C2420
select S3C2410_CLOCK
- select S3C2410_PM
+ select S3C2410_PM if PM
select CPU_S3C244X
help
Support for S3C2442 Samsung Mobile CPU based systems.
@@ -300,8 +302,9 @@ config S3C2410_PM_CHECK_CHUNKSIZE
config PM_SIMTEC
bool
- depends on PM && (ARCH_BAST || MACH_VR1000 || MACH_AML_M5900)
- default y
+ help
+ Common power management code for systems that are
+ compatible with the Simtec style of power management
config S3C2410_LOWLEVEL_UART_PORT
int "S3C2410 UART to use for low-level messages"
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 9d4899eddf1..ae1f5bb63f7 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index cae35ff76f3..faccde2092d 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 01abb0ace23..fa860e716b4 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/dma.c
*
- * (c) 2003-2005,2006 Simtec Electronics
+ * Copyright (c) 2003-2005,2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 DMA core
@@ -1053,11 +1053,11 @@ int s3c2410_dma_config(dmach_t channel,
if (chan == NULL)
return -EINVAL;
- printk("Initial dcon is %08x\n", dcon);
+ pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
dcon |= chan->dcon & dma_sel.dcon_mask;
- printk("New dcon is %08x\n", dcon);
+ pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
switch (xferunit) {
case 1:
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index ba346546150..f6fb215bb48 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -57,6 +57,7 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
case S3C2410_GPIO_SFN2:
case S3C2410_GPIO_SFN3:
if (pin < S3C2410_GPIO_BANKB) {
+ function -= 1;
function &= 1;
function <<= S3C2410_GPIO_OFFSET(pin);
} else {
@@ -83,15 +84,18 @@ EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
unsigned int s3c2410_gpio_getcfg(unsigned int pin)
{
void __iomem *base = S3C24XX_GPIO_BASE(pin);
- unsigned long mask;
+ unsigned long val = __raw_readl(base);
if (pin < S3C2410_GPIO_BANKB) {
- mask = 1 << S3C2410_GPIO_OFFSET(pin);
+ val >>= S3C2410_GPIO_OFFSET(pin);
+ val &= 1;
+ val += 1;
} else {
- mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+ val >>= S3C2410_GPIO_OFFSET(pin)*2;
+ val &= 3;
}
- return __raw_readl(base) & mask;
+ return val | S3C2410_GPIO_INPUT;
}
EXPORT_SYMBOL(s3c2410_gpio_getcfg);
diff --git a/arch/arm/mach-s3c2410/irq.h b/arch/arm/mach-s3c2410/irq.h
index 3686a008224..e5913da3b91 100644
--- a/arch/arm/mach-s3c2410/irq.h
+++ b/arch/arm/mach-s3c2410/irq.h
@@ -8,8 +8,6 @@
* 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:
*/
#define irqdbf(x...)
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index e94cdcd9659..0fad0c2fe07 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 2968fb235f9..b8b76757ec5 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/dm9000.h>
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index f5b98099a5d..15b625eae49 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
@@ -37,8 +38,6 @@
#include <asm/arch/h1940-latch.h>
#include <asm/arch/fb.h>
-#include <linux/serial_core.h>
-
#include "clock.h"
#include "devs.h"
#include "cpu.h"
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 116ac316996..0411e9adb54 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -20,6 +20,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
@@ -37,8 +38,6 @@
#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"
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
index 065a1d4e860..d6dfdad8c90 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
@@ -19,6 +19,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/mtd/map.h>
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c
index a4ab144e729..37b40850c9b 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2410/mach-osiris.c
@@ -16,6 +16,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/serial_core.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index c71673fd995..2c738b375e4 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index b3b0171d505..01c0c986d82 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -35,6 +35,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
index 3a4ca7f6f7b..4f89abd7a6d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2413.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index e2205ff1b0e..2b61f4ed1da 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index e2eda3937ab..a382fc09511 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -352,7 +352,7 @@ static struct platform_device vr1000_led2 = {
static struct platform_device vr1000_led3 = {
.name = "s3c24xx_led",
- .id = 1,
+ .id = 3,
.dev = {
.platform_data = &vr1000_led3_pdata,
},
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2410/mach-vstms.c
index ea554e7c006..0360e1055bc 100644
--- a/arch/arm/mach-s3c2410/mach-vstms.c
+++ b/arch/arm/mach-s3c2410/mach-vstms.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
index 42cd05e298f..619133eb716 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/mach-s3c2410/pm-simtec.c
@@ -27,7 +27,6 @@
#include <asm/io.h>
#include <asm/arch/map.h>
-#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index b49a0b3b72b..ebf294dd31d 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -34,6 +34,7 @@
#include <linux/crc32.h>
#include <linux/ioport.h>
#include <linux/delay.h>
+#include <linux/serial_core.h>
#include <asm/cacheflush.h>
#include <asm/hardware.h>
@@ -450,15 +451,14 @@ static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
pinstate = s3c2410_gpio_getcfg(pin);
- pinstate >>= S3C2410_GPIO_OFFSET(pin)*2;
if (!irqstate) {
- if (pinstate == 0x02)
+ if (pinstate == S3C2410_GPIO_IRQ)
DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
} else {
- if (pinstate == 0x02) {
+ if (pinstate == S3C2410_GPIO_IRQ) {
DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
- s3c2410_gpio_cfgpin(pin, 0x00);
+ s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
}
}
}
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
index 00abe199a08..992cc6af230 100644
--- a/arch/arm/mach-s3c2410/s3c2410-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2410-clock.c
@@ -30,13 +30,18 @@
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
#include <asm/hardware.h>
#include <asm/io.h>
+#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
+#include "s3c2410.h"
#include "clock.h"
#include "cpu.h"
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
index 51e5098b32e..e67ba3911f1 100644
--- a/arch/arm/mach-s3c2410/s3c2410-dma.c
+++ b/arch/arm/mach-s3c2410/s3c2410-dma.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
*
- * (c) 2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 DMA selection
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/serial_core.h>
#include <asm/dma.h>
#include <asm/arch/dma.h>
@@ -131,6 +132,7 @@ static int s3c2410_dma_add(struct sys_device *sysdev)
return s3c24xx_dma_init_map(&s3c2410_dma_sel);
}
+#if defined(CONFIG_CPU_S3C2410)
static struct sysdev_driver s3c2410_dma_driver = {
.add = s3c2410_dma_add,
};
@@ -141,9 +143,10 @@ static int __init s3c2410_dma_init(void)
}
arch_initcall(s3c2410_dma_init);
+#endif
+#if defined(CONFIG_CPU_S3C2442)
/* S3C2442 DMA contains the same selection table as the S3C2410 */
-
static struct sysdev_driver s3c2442_dma_driver = {
.add = s3c2410_dma_add,
};
@@ -154,5 +157,5 @@ static int __init s3c2442_dma_init(void)
}
arch_initcall(s3c2442_dma_init);
-
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
index 77c6814c0f0..8bb6e5e21f5 100644
--- a/arch/arm/mach-s3c2410/s3c2410-pm.c
+++ b/arch/arm/mach-s3c2410/s3c2410-pm.c
@@ -87,7 +87,7 @@ static void s3c2410_pm_prepare(void)
}
-int s3c2410_pm_resume(struct sys_device *dev)
+static int s3c2410_pm_resume(struct sys_device *dev)
{
unsigned long tmp;
@@ -111,6 +111,7 @@ static int s3c2410_pm_add(struct sys_device *dev)
return 0;
}
+#if defined(CONFIG_CPU_S3C2410)
static struct sysdev_driver s3c2410_pm_driver = {
.add = s3c2410_pm_add,
.resume = s3c2410_pm_resume,
@@ -124,7 +125,9 @@ static int __init s3c2410_pm_drvinit(void)
}
arch_initcall(s3c2410_pm_drvinit);
+#endif
+#if defined(CONFIG_CPU_S3C2440)
static struct sysdev_driver s3c2440_pm_driver = {
.add = s3c2410_pm_add,
.resume = s3c2410_pm_resume,
@@ -136,7 +139,9 @@ static int __init s3c2440_pm_drvinit(void)
}
arch_initcall(s3c2440_pm_drvinit);
+#endif
+#if defined(CONFIG_CPU_S3C2442)
static struct sysdev_driver s3c2442_pm_driver = {
.add = s3c2410_pm_add,
.resume = s3c2410_pm_resume,
@@ -148,3 +153,4 @@ static int __init s3c2442_pm_drvinit(void)
}
arch_initcall(s3c2442_pm_drvinit);
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 183e4033ce6..4cdc0d70c19 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -17,6 +17,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
@@ -38,11 +39,9 @@
/* Initial IO mappings */
static struct map_desc s3c2410_iodesc[] __initdata = {
- IODESC_ENT(USBHOST),
IODESC_ENT(CLKPWR),
IODESC_ENT(LCD),
IODESC_ENT(TIMER),
- IODESC_ENT(ADC),
IODESC_ENT(WATCHDOG),
};
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c
index c95ed3e1858..8f94ad83901 100644
--- a/arch/arm/mach-s3c2410/s3c2412-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2412-clock.c
@@ -30,13 +30,18 @@
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
#include <asm/hardware.h>
#include <asm/io.h>
+#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
+#include "s3c2412.h"
#include "clock.h"
#include "cpu.h"
@@ -49,7 +54,7 @@
* set the correct muxing at initialisation
*/
-int s3c2412_clkcon_enable(struct clk *clk, int enable)
+static int s3c2412_clkcon_enable(struct clk *clk, int enable)
{
unsigned int clocks = clk->ctrlbit;
unsigned long clkcon;
@@ -556,7 +561,7 @@ struct clk_init {
struct clk *src_1;
};
-struct clk_init clks_src[] __initdata = {
+static struct clk_init clks_src[] __initdata = {
{
.clk = &clk_usysclk,
.bit = S3C2412_CLKSRC_USBCLK_HCLK,
@@ -619,7 +624,7 @@ static void __init s3c2412_clk_initparents(void)
/* clocks to add straight away */
-struct clk *clks[] __initdata = {
+static struct clk *clks[] __initdata = {
&clk_ext,
&clk_usb_bus,
&clk_erefclk,
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2410/s3c2412-dma.c
index 171f3706d36..138f726ac6b 100644
--- a/arch/arm/mach-s3c2410/s3c2412-dma.c
+++ b/arch/arm/mach-s3c2410/s3c2412-dma.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
*
- * (c) 2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2412 DMA selection
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/serial_core.h>
#include <asm/dma.h>
#include <asm/arch/dma.h>
@@ -132,8 +133,8 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
struct s3c24xx_dma_map *map)
{
- writel(chan->regs + S3C2412_DMA_DMAREQSEL,
- map->channels[0] | S3C2412_DMAREQSEL_HW);
+ writel(map->channels[0] | S3C2412_DMAREQSEL_HW,
+ chan->regs + S3C2412_DMA_DMAREQSEL);
}
static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
index e76431c4146..2f651a811ec 100644
--- a/arch/arm/mach-s3c2410/s3c2412.c
+++ b/arch/arm/mach-s3c2410/s3c2412.c
@@ -17,6 +17,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
@@ -60,7 +61,6 @@ static struct map_desc s3c2412_iodesc[] __initdata = {
IODESC_ENT(CLKPWR),
IODESC_ENT(LCD),
IODESC_ENT(TIMER),
- IODESC_ENT(ADC),
IODESC_ENT(WATCHDOG),
};
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index 15796864d01..ba13c1d079d 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -113,18 +113,18 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
{
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
unsigned long clkdivn;
- struct clk *clk_h;
- struct clk *clk_p;
- struct clk *clk_upll;
+ struct clk *clock_h;
+ struct clk *clock_p;
+ struct clk *clock_upll;
printk("S3C2440: Clock Support, DVS %s\n",
(camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
- clk_p = clk_get(NULL, "pclk");
- clk_h = clk_get(NULL, "hclk");
- clk_upll = clk_get(NULL, "upll");
+ clock_p = clk_get(NULL, "pclk");
+ clock_h = clk_get(NULL, "hclk");
+ clock_upll = clk_get(NULL, "upll");
- if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
+ if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
return -EINVAL;
}
@@ -132,8 +132,8 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
/* check rate of UPLL, and if it is near 96MHz, then change
* to using half the UPLL rate for the system */
- if (clk_get_rate(clk_upll) > (94 * MHZ)) {
- clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+ if (clk_get_rate(clock_upll) > (94 * MHZ)) {
+ clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
mutex_lock(&clocks_mutex);
@@ -144,9 +144,9 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
mutex_unlock(&clocks_mutex);
}
- s3c2440_clk_cam.parent = clk_h;
- s3c2440_clk_ac97.parent = clk_p;
- s3c2440_clk_cam_upll.parent = clk_upll;
+ s3c2440_clk_cam.parent = clock_h;
+ s3c2440_clk_ac97.parent = clock_p;
+ s3c2440_clk_cam_upll.parent = clock_upll;
s3c24xx_register_clock(&s3c2440_clk_ac97);
s3c24xx_register_clock(&s3c2440_clk_cam);
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2410/s3c2440-dma.c
index 11e109c84a1..47b861b9443 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dma.c
+++ b/arch/arm/mach-s3c2410/s3c2440-dma.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
*
- * (c) 2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2440 DMA selection
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/serial_core.h>
#include <asm/dma.h>
#include <asm/arch/dma.h>
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index 0ab50f44f31..344eb27cca4 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -17,6 +17,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/serial_core.h>
#include <linux/sysdev.h>
#include <linux/clk.h>
@@ -28,17 +29,9 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-gpioj.h>
-#include <asm/arch/regs-dsc.h>
-
#include "s3c2440.h"
-#include "clock.h"
#include "devs.h"
#include "cpu.h"
-#include "pm.h"
static struct sys_device s3c2440_sysdev = {
.cls = &s3c2440_sysclass,
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h
index 29cb6df65a4..dcd316076c5 100644
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ b/arch/arm/mach-s3c2410/s3c2440.h
@@ -8,28 +8,10 @@
* 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:
- * 24-Aug-2004 BJD Start of S3C2440 CPU support
- * 04-Nov-2004 BJD Added s3c2440_init_uarts()
- * 04-Jan-2005 BJD Moved uart init to cpu code
- * 10-Jan-2005 BJD Moved 2440 specific init here
- * 14-Jan-2005 BJD Split the clock initialisation code
*/
#ifdef CONFIG_CPU_S3C2440
-
extern int s3c2440_init(void);
-
-extern void s3c2440_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2440_init_clocks(int xtal);
-
#else
-#define s3c2440_init_clocks NULL
-#define s3c2440_init_uarts NULL
-#define s3c2440_map_io NULL
#define s3c2440_init NULL
#endif
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c
index d9f54b5cab7..4e292ca7c9b 100644
--- a/arch/arm/mach-s3c2410/s3c2442-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2442-clock.c
@@ -117,18 +117,18 @@ static int s3c2442_clk_add(struct sys_device *sysdev)
{
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
unsigned long clkdivn;
- struct clk *clk_h;
- struct clk *clk_p;
- struct clk *clk_upll;
+ struct clk *clock_h;
+ struct clk *clock_p;
+ struct clk *clock_upll;
printk("S3C2442: Clock Support, DVS %s\n",
(camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
- clk_p = clk_get(NULL, "pclk");
- clk_h = clk_get(NULL, "hclk");
- clk_upll = clk_get(NULL, "upll");
+ clock_p = clk_get(NULL, "pclk");
+ clock_h = clk_get(NULL, "hclk");
+ clock_upll = clk_get(NULL, "upll");
- if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
+ if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
return -EINVAL;
}
@@ -136,8 +136,8 @@ static int s3c2442_clk_add(struct sys_device *sysdev)
/* check rate of UPLL, and if it is near 96MHz, then change
* to using half the UPLL rate for the system */
- if (clk_get_rate(clk_upll) > (94 * MHZ)) {
- clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+ if (clk_get_rate(clock_upll) > (94 * MHZ)) {
+ clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
mutex_lock(&clocks_mutex);
@@ -148,8 +148,8 @@ static int s3c2442_clk_add(struct sys_device *sysdev)
mutex_unlock(&clocks_mutex);
}
- s3c2442_clk_cam.parent = clk_h;
- s3c2442_clk_cam_upll.parent = clk_upll;
+ s3c2442_clk_cam.parent = clock_h;
+ s3c2442_clk_cam_upll.parent = clock_upll;
s3c24xx_register_clock(&s3c2442_clk_cam);
s3c24xx_register_clock(&s3c2442_clk_cam_upll);
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c
index 581667efd13..428732ee68c 100644
--- a/arch/arm/mach-s3c2410/s3c2442.c
+++ b/arch/arm/mach-s3c2410/s3c2442.c
@@ -16,29 +16,11 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
-#include <linux/platform_device.h>
+#include <linux/serial_core.h>
#include <linux/sysdev.h>
-#include <linux/clk.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-gpioj.h>
-#include <asm/arch/regs-dsc.h>
#include "s3c2442.h"
-#include "clock.h"
-#include "devs.h"
#include "cpu.h"
-#include "pm.h"
static struct sys_device s3c2442_sysdev = {
.cls = &s3c2442_sysclass,
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c
index 9a2258270de..23c7494ad10 100644
--- a/arch/arm/mach-s3c2410/s3c244x.c
+++ b/arch/arm/mach-s3c2410/s3c244x.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
#include <linux/clk.h>
@@ -47,8 +48,6 @@ static struct map_desc s3c244x_iodesc[] __initdata = {
IODESC_ENT(TIMER),
IODESC_ENT(WATCHDOG),
IODESC_ENT(LCD),
- IODESC_ENT(ADC),
- IODESC_ENT(USBHOST),
};
/* uart initialisation */
diff --git a/arch/arm/mach-s3c2410/usb-simtec.h b/arch/arm/mach-s3c2410/usb-simtec.h
index d8aa6127ded..03842ede9e7 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.h
+++ b/arch/arm/mach-s3c2410/usb-simtec.h
@@ -10,9 +10,6 @@
* 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:
- * 20-Aug-2004 BJD Created
*/
extern int usb_simtec_init(void);
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 17f5a43acdb..54ecdaa373d 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -1,5 +1,15 @@
/*
* linux/arch/arm/mach-sa1100/jornada720.c
+ *
+ * HP Jornada720 init code
+ *
+ * Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl>
+ * Copyright (C) 2005 Michael Gernoth <michael@gernoth.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
*/
#include <linux/init.h>
@@ -10,13 +20,13 @@
#include <linux/ioport.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <video/s1d13xxxfb.h>
#include <asm/hardware.h>
#include <asm/hardware/sa1111.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
-
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
@@ -24,13 +34,170 @@
#include "generic.h"
+/*
+ * HP Documentation referred in this file:
+ * http://www.jlime.com/downloads/development/docs/jornada7xx/jornada720.txt
+ */
+
+/* line 110 of HP's doc */
+#define TUCR_VAL 0x20000400
+
+/* memory space (line 52 of HP's doc) */
+#define SA1111REGSTART 0x40000000
+#define SA1111REGLEN 0x00001fff
+#define EPSONREGSTART 0x48000000
+#define EPSONREGLEN 0x00100000
+#define EPSONFBSTART 0x48200000
+/* 512kB framebuffer */
+#define EPSONFBLEN 512*1024
+
+static struct s1d13xxxfb_regval s1d13xxxfb_initregs[] = {
+ /* line 344 of HP's doc */
+ {0x0001,0x00}, // Miscellaneous Register
+ {0x01FC,0x00}, // Display Mode Register
+ {0x0004,0x00}, // General IO Pins Configuration Register 0
+ {0x0005,0x00}, // General IO Pins Configuration Register 1
+ {0x0008,0x00}, // General IO Pins Control Register 0
+ {0x0009,0x00}, // General IO Pins Control Register 1
+ {0x0010,0x01}, // Memory Clock Configuration Register
+ {0x0014,0x11}, // LCD Pixel Clock Configuration Register
+ {0x0018,0x01}, // CRT/TV Pixel Clock Configuration Register
+ {0x001C,0x01}, // MediaPlug Clock Configuration Register
+ {0x001E,0x01}, // CPU To Memory Wait State Select Register
+ {0x0020,0x00}, // Memory Configuration Register
+ {0x0021,0x45}, // DRAM Refresh Rate Register
+ {0x002A,0x01}, // DRAM Timings Control Register 0
+ {0x002B,0x03}, // DRAM Timings Control Register 1
+ {0x0030,0x1c}, // Panel Type Register
+ {0x0031,0x00}, // MOD Rate Register
+ {0x0032,0x4F}, // LCD Horizontal Display Width Register
+ {0x0034,0x07}, // LCD Horizontal Non-Display Period Register
+ {0x0035,0x01}, // TFT FPLINE Start Position Register
+ {0x0036,0x0B}, // TFT FPLINE Pulse Width Register
+ {0x0038,0xEF}, // LCD Vertical Display Height Register 0
+ {0x0039,0x00}, // LCD Vertical Display Height Register 1
+ {0x003A,0x13}, // LCD Vertical Non-Display Period Register
+ {0x003B,0x0B}, // TFT FPFRAME Start Position Register
+ {0x003C,0x01}, // TFT FPFRAME Pulse Width Register
+ {0x0040,0x05}, // LCD Display Mode Register (2:4bpp,3:8bpp,5:16bpp)
+ {0x0041,0x00}, // LCD Miscellaneous Register
+ {0x0042,0x00}, // LCD Display Start Address Register 0
+ {0x0043,0x00}, // LCD Display Start Address Register 1
+ {0x0044,0x00}, // LCD Display Start Address Register 2
+ {0x0046,0x80}, // LCD Memory Address Offset Register 0
+ {0x0047,0x02}, // LCD Memory Address Offset Register 1
+ {0x0048,0x00}, // LCD Pixel Panning Register
+ {0x004A,0x00}, // LCD Display FIFO High Threshold Control Register
+ {0x004B,0x00}, // LCD Display FIFO Low Threshold Control Register
+ {0x0050,0x4F}, // CRT/TV Horizontal Display Width Register
+ {0x0052,0x13}, // CRT/TV Horizontal Non-Display Period Register
+ {0x0053,0x01}, // CRT/TV HRTC Start Position Register
+ {0x0054,0x0B}, // CRT/TV HRTC Pulse Width Register
+ {0x0056,0xDF}, // CRT/TV Vertical Display Height Register 0
+ {0x0057,0x01}, // CRT/TV Vertical Display Height Register 1
+ {0x0058,0x2B}, // CRT/TV Vertical Non-Display Period Register
+ {0x0059,0x09}, // CRT/TV VRTC Start Position Register
+ {0x005A,0x01}, // CRT/TV VRTC Pulse Width Register
+ {0x005B,0x10}, // TV Output Control Register
+ {0x0060,0x03}, // CRT/TV Display Mode Register (2:4bpp,3:8bpp,5:16bpp)
+ {0x0062,0x00}, // CRT/TV Display Start Address Register 0
+ {0x0063,0x00}, // CRT/TV Display Start Address Register 1
+ {0x0064,0x00}, // CRT/TV Display Start Address Register 2
+ {0x0066,0x40}, // CRT/TV Memory Address Offset Register 0
+ {0x0067,0x01}, // CRT/TV Memory Address Offset Register 1
+ {0x0068,0x00}, // CRT/TV Pixel Panning Register
+ {0x006A,0x00}, // CRT/TV Display FIFO High Threshold Control Register
+ {0x006B,0x00}, // CRT/TV Display FIFO Low Threshold Control Register
+ {0x0070,0x00}, // LCD Ink/Cursor Control Register
+ {0x0071,0x01}, // LCD Ink/Cursor Start Address Register
+ {0x0072,0x00}, // LCD Cursor X Position Register 0
+ {0x0073,0x00}, // LCD Cursor X Position Register 1
+ {0x0074,0x00}, // LCD Cursor Y Position Register 0
+ {0x0075,0x00}, // LCD Cursor Y Position Register 1
+ {0x0076,0x00}, // LCD Ink/Cursor Blue Color 0 Register
+ {0x0077,0x00}, // LCD Ink/Cursor Green Color 0 Register
+ {0x0078,0x00}, // LCD Ink/Cursor Red Color 0 Register
+ {0x007A,0x1F}, // LCD Ink/Cursor Blue Color 1 Register
+ {0x007B,0x3F}, // LCD Ink/Cursor Green Color 1 Register
+ {0x007C,0x1F}, // LCD Ink/Cursor Red Color 1 Register
+ {0x007E,0x00}, // LCD Ink/Cursor FIFO Threshold Register
+ {0x0080,0x00}, // CRT/TV Ink/Cursor Control Register
+ {0x0081,0x01}, // CRT/TV Ink/Cursor Start Address Register
+ {0x0082,0x00}, // CRT/TV Cursor X Position Register 0
+ {0x0083,0x00}, // CRT/TV Cursor X Position Register 1
+ {0x0084,0x00}, // CRT/TV Cursor Y Position Register 0
+ {0x0085,0x00}, // CRT/TV Cursor Y Position Register 1
+ {0x0086,0x00}, // CRT/TV Ink/Cursor Blue Color 0 Register
+ {0x0087,0x00}, // CRT/TV Ink/Cursor Green Color 0 Register
+ {0x0088,0x00}, // CRT/TV Ink/Cursor Red Color 0 Register
+ {0x008A,0x1F}, // CRT/TV Ink/Cursor Blue Color 1 Register
+ {0x008B,0x3F}, // CRT/TV Ink/Cursor Green Color 1 Register
+ {0x008C,0x1F}, // CRT/TV Ink/Cursor Red Color 1 Register
+ {0x008E,0x00}, // CRT/TV Ink/Cursor FIFO Threshold Register
+ {0x0100,0x00}, // BitBlt Control Register 0
+ {0x0101,0x00}, // BitBlt Control Register 1
+ {0x0102,0x00}, // BitBlt ROP Code/Color Expansion Register
+ {0x0103,0x00}, // BitBlt Operation Register
+ {0x0104,0x00}, // BitBlt Source Start Address Register 0
+ {0x0105,0x00}, // BitBlt Source Start Address Register 1
+ {0x0106,0x00}, // BitBlt Source Start Address Register 2
+ {0x0108,0x00}, // BitBlt Destination Start Address Register 0
+ {0x0109,0x00}, // BitBlt Destination Start Address Register 1
+ {0x010A,0x00}, // BitBlt Destination Start Address Register 2
+ {0x010C,0x00}, // BitBlt Memory Address Offset Register 0
+ {0x010D,0x00}, // BitBlt Memory Address Offset Register 1
+ {0x0110,0x00}, // BitBlt Width Register 0
+ {0x0111,0x00}, // BitBlt Width Register 1
+ {0x0112,0x00}, // BitBlt Height Register 0
+ {0x0113,0x00}, // BitBlt Height Register 1
+ {0x0114,0x00}, // BitBlt Background Color Register 0
+ {0x0115,0x00}, // BitBlt Background Color Register 1
+ {0x0118,0x00}, // BitBlt Foreground Color Register 0
+ {0x0119,0x00}, // BitBlt Foreground Color Register 1
+ {0x01E0,0x00}, // Look-Up Table Mode Register
+ {0x01E2,0x00}, // Look-Up Table Address Register
+ /* not sure, wouldn't like to mess with the driver */
+ {0x01E4,0x00}, // Look-Up Table Data Register
+ /* jornada doc says 0x00, but I trust the driver */
+ {0x01F0,0x10}, // Power Save Configuration Register
+ {0x01F1,0x00}, // Power Save Status Register
+ {0x01F4,0x00}, // CPU-to-Memory Access Watchdog Timer Register
+ {0x01FC,0x01}, // Display Mode Register(0x01:LCD, 0x02:CRT, 0x03:LCD&CRT)
+};
+
+static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
+ .initregs = s1d13xxxfb_initregs,
+ .initregssize = ARRAY_SIZE(s1d13xxxfb_initregs),
+ .platform_init_video = NULL
+};
-#define JORTUCR_VAL 0x20000400
+static struct resource s1d13xxxfb_resources[] = {
+ [0] = {
+ .start = EPSONFBSTART,
+ .end = EPSONFBSTART + EPSONFBLEN,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = EPSONREGSTART,
+ .end = EPSONREGSTART + EPSONREGLEN,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device s1d13xxxfb_device = {
+ .name = S1D_DEVICENAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &s1d13xxxfb_data,
+ },
+ .num_resources = ARRAY_SIZE(s1d13xxxfb_resources),
+ .resource = s1d13xxxfb_resources,
+};
static struct resource sa1111_resources[] = {
[0] = {
- .start = 0x40000000,
- .end = 0x40001fff,
+ .start = SA1111REGSTART,
+ .end = SA1111REGSTART + SA1111REGLEN,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -53,18 +220,32 @@ static struct platform_device sa1111_device = {
.resource = sa1111_resources,
};
+static struct platform_device jornada720_mcu_device = {
+ .name = "jornada720_mcu",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
&sa1111_device,
+ &jornada720_mcu_device,
+ &s1d13xxxfb_device,
};
+/* a stub for now, we theoretically cannot suspend without a flashboard */
+int pm_suspend(suspend_state_t state)
+{
+ return -1;
+}
+
static int __init jornada720_init(void)
{
int ret = -ENODEV;
if (machine_is_jornada720()) {
GPDR |= GPIO_GPIO20;
- TUCR = JORTUCR_VAL; /* set the oscillator out to the SA-1101 */
-
+ /* oscillator setup (line 116 of HP's doc) */
+ TUCR = TUCR_VAL;
+ /* resetting SA1111 (line 118 of HP's doc) */
GPSR = GPIO_GPIO20;
udelay(1);
GPCR = GPIO_GPIO20;
@@ -72,10 +253,6 @@ static int __init jornada720_init(void)
GPSR = GPIO_GPIO20;
udelay(20);
- /* LDD4 is speaker, LDD3 is microphone */
- PPSR &= ~(PPC_LDD3 | PPC_LDD4);
- PPDR |= PPC_LDD3 | PPC_LDD4;
-
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
return ret;
@@ -85,19 +262,19 @@ arch_initcall(jornada720_init);
static struct map_desc jornada720_io_desc[] __initdata = {
{ /* Epson registers */
- .virtual = 0xf0000000,
- .pfn = __phys_to_pfn(0x48000000),
- .length = 0x00100000,
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(EPSONREGSTART),
+ .length = EPSONREGLEN,
.type = MT_DEVICE
}, { /* Epson frame buffer */
- .virtual = 0xf1000000,
- .pfn = __phys_to_pfn(0x48200000),
- .length = 0x00100000,
+ .virtual = 0xf1000000,
+ .pfn = __phys_to_pfn(EPSONFBSTART),
+ .length = EPSONFBLEN,
.type = MT_DEVICE
}, { /* SA-1111 */
- .virtual = 0xf4000000,
- .pfn = __phys_to_pfn(0x40000000),
- .length = 0x00100000,
+ .virtual = 0xf4000000,
+ .pfn = __phys_to_pfn(SA1111REGSTART),
+ .length = SA1111REGLEN,
.type = MT_DEVICE
}
};
@@ -106,7 +283,7 @@ static void __init jornada720_map_io(void)
{
sa1100_map_io();
iotable_init(jornada720_io_desc, ARRAY_SIZE(jornada720_io_desc));
-
+
sa1100_register_uart(0, 3);
sa1100_register_uart(1, 1);
}
@@ -116,7 +293,7 @@ static struct mtd_partition jornada720_partitions[] = {
.name = "JORNADA720 boot firmware",
.size = 0x00040000,
.offset = 0,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
}, {
.name = "JORNADA720 kernel",
.size = 0x000c0000,
@@ -139,7 +316,7 @@ static struct mtd_partition jornada720_partitions[] = {
.offset = 0x00540000,
}, {
.name = "JORNADA720 usr local",
- .size = 0, /* will expand to the end of the flash */
+ .size = 0, /* will expand to the end of the flash */
.offset = 0x00d00000,
}
};
@@ -147,10 +324,12 @@ static struct mtd_partition jornada720_partitions[] = {
static void jornada720_set_vpp(int vpp)
{
if (vpp)
- PPSR |= 0x80;
+ /* enabling flash write (line 470 of HP's doc) */
+ PPSR |= PPC_LDD7;
else
- PPSR &= ~0x80;
- PPDR |= 0x80;
+ /* disabling flash write (line 470 of HP's doc) */
+ PPSR &= ~PPC_LDD7;
+ PPDR |= PPC_LDD7;
}
static struct flash_platform_data jornada720_flash_data = {
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 57196947559..bf71507c76f 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -325,6 +325,19 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+static struct resource versatile_i2c_resource = {
+ .start = VERSATILE_I2C_BASE,
+ .end = VERSATILE_I2C_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device versatile_i2c_device = {
+ .name = "versatile-i2c",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &versatile_i2c_resource,
+};
+
#define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
unsigned int mmc_status(struct device *dev)
@@ -775,6 +788,7 @@ void __init versatile_init(void)
clk_register(&versatile_clcd_clk);
platform_device_register(&versatile_flash_device);
+ platform_device_register(&versatile_i2c_device);
platform_device_register(&smc91x_device);
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index b797217e82b..6a9c362fef5 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -238,7 +238,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
* x86 does not mark the pages reserved...
*/
SetPageReserved(page);
- set_pte(pte, mk_pte(page, prot));
+ set_pte_ext(pte, mk_pte(page, prot), 0);
page++;
pte++;
off++;
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index df1645e14b4..ded0e96d069 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -19,6 +19,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
#include "mm.h"
@@ -69,9 +70,14 @@ mc_copy_user_page(void *from, void *to)
void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
{
+ struct page *page = virt_to_page(kfrom);
+
+ if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+ __flush_dcache_page(page_mapping(page), page);
+
spin_lock(&minicache_lock);
- set_pte(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
+ set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot), 0);
flush_tlb_kernel_page(0xffff8000);
mc_copy_user_page((void *)0xffff8000, kto);
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 3d0d3a963d2..3adb79257f4 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -53,6 +53,10 @@ static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned lo
{
unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long from, to;
+ struct page *page = virt_to_page(kfrom);
+
+ if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+ __flush_dcache_page(page_mapping(page), page);
/*
* Discard data in the kernel mapping for the new page.
@@ -70,8 +74,8 @@ static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned lo
*/
spin_lock(&v6_lock);
- set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, PAGE_KERNEL));
- set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, PAGE_KERNEL));
+ set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, PAGE_KERNEL), 0);
+ set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, PAGE_KERNEL), 0);
from = from_address + (offset << PAGE_SHIFT);
to = to_address + (offset << PAGE_SHIFT);
@@ -110,7 +114,7 @@ static void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
*/
spin_lock(&v6_lock);
- set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, PAGE_KERNEL));
+ set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, PAGE_KERNEL), 0);
flush_tlb_kernel_page(to);
clear_page((void *)to);
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 84ebe0aa379..2e455f82a4d 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -19,6 +19,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
#include "mm.h"
@@ -91,9 +92,14 @@ mc_copy_user_page(void *from, void *to)
void xscale_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
{
+ struct page *page = virt_to_page(kfrom);
+
+ if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+ __flush_dcache_page(page_mapping(page), page);
+
spin_lock(&minicache_lock);
- set_pte(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
+ set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot), 0);
flush_tlb_kernel_page(COPYPAGE_MINICACHE);
mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 7fc1b35a674..cf95c5d0ce4 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -61,7 +61,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
flush_cache_page(vma, address, pte_pfn(entry));
pte_val(entry) &= ~shared_pte_mask;
- set_pte(pte, entry);
+ set_pte_at(vma->vm_mm, address, pte, entry);
flush_tlb_page(vma, address);
ret = 1;
}
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 454205b789d..9df507d36e0 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -26,7 +26,7 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
const int zero = 0;
- set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
+ set_pte_ext(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL), 0);
flush_tlb_kernel_page(to);
asm( "mcrr p15, 0, %1, %0, c14\n"
@@ -202,3 +202,42 @@ void flush_dcache_page(struct page *page)
}
}
EXPORT_SYMBOL(flush_dcache_page);
+
+/*
+ * Flush an anonymous page so that users of get_user_pages()
+ * can safely access the data. The expected sequence is:
+ *
+ * get_user_pages()
+ * -> flush_anon_page
+ * memcpy() to/from page
+ * if written to page, flush_dcache_page()
+ */
+void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
+{
+ unsigned long pfn;
+
+ /* VIPT non-aliasing caches need do nothing */
+ if (cache_is_vipt_nonaliasing())
+ return;
+
+ /*
+ * Write back and invalidate userspace mapping.
+ */
+ pfn = page_to_pfn(page);
+ if (cache_is_vivt()) {
+ flush_cache_page(vma, vmaddr, pfn);
+ } else {
+ /*
+ * For aliasing VIPT, we can flush an alias of the
+ * userspace address only.
+ */
+ flush_pfn_alias(pfn, vmaddr);
+ }
+
+ /*
+ * Invalidate kernel mapping. No data should be contained
+ * in this mapping of the page. FIXME: this is overkill
+ * since we actually ask for a write-back and invalidate.
+ */
+ __cpuc_flush_dcache_page(page_address(page));
+}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b5814b4b6f3..7760193e74c 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -52,15 +52,18 @@ void show_mem(void)
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
for_each_online_node(node) {
+ pg_data_t *n = NODE_DATA(node);
+ struct page *map = n->node_mem_map - n->node_start_pfn;
+
for_each_nodebank (i,mi,node) {
unsigned int pfn1, pfn2;
struct page *page, *end;
- pfn1 = mi->bank[i].start >> PAGE_SHIFT;
- pfn2 = (mi->bank[i].size + mi->bank[i].start) >> PAGE_SHIFT;
+ pfn1 = __phys_to_pfn(mi->bank[i].start);
+ pfn2 = __phys_to_pfn(mi->bank[i].size + mi->bank[i].start);
- page = NODE_MEM_MAP(node) + pfn1;
- end = NODE_MEM_MAP(node) + pfn2;
+ page = map + pfn1;
+ end = map + pfn2;
do {
total++;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 46544059279..0ac615c0f79 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -38,89 +38,71 @@
*/
#define VM_ARM_SECTION_MAPPING 0x80000000
-static inline void
-remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, pgprot_t pgprot)
+static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end,
+ unsigned long phys_addr, pgprot_t prot)
{
- unsigned long end;
+ pte_t *pte;
+
+ pte = pte_alloc_kernel(pmd, addr);
+ if (!pte)
+ return -ENOMEM;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- BUG_ON(address >= end);
do {
if (!pte_none(*pte))
goto bad;
- set_pte(pte, pfn_pte(phys_addr >> PAGE_SHIFT, pgprot));
- address += PAGE_SIZE;
+ set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot), 0);
phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
- return;
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ return 0;
bad:
- printk("remap_area_pte: page already exists\n");
+ printk(KERN_CRIT "remap_area_pte: page already exists\n");
BUG();
}
-static inline int
-remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
+static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr,
+ unsigned long end, unsigned long phys_addr,
+ pgprot_t prot)
{
- unsigned long end;
- pgprot_t pgprot;
-
- address &= ~PGDIR_MASK;
- end = address + size;
-
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
+ unsigned long next;
+ pmd_t *pmd;
+ int ret = 0;
- phys_addr -= address;
- BUG_ON(address >= end);
+ pmd = pmd_alloc(&init_mm, pgd, addr);
+ if (!pmd)
+ return -ENOMEM;
- pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
+ next = pmd_addr_end(addr, end);
+ ret = remap_area_pte(pmd, addr, next, phys_addr, prot);
+ if (ret)
+ return ret;
+ phys_addr += next - addr;
+ } while (pmd++, addr = next, addr != end);
+ return ret;
}
-static int
-remap_area_pages(unsigned long start, unsigned long pfn,
- unsigned long size, unsigned long flags)
+static int remap_area_pages(unsigned long start, unsigned long pfn,
+ unsigned long size, unsigned long flags)
{
- unsigned long address = start;
- unsigned long end = start + size;
+ unsigned long addr = start;
+ unsigned long next, end = start + size;
unsigned long phys_addr = __pfn_to_phys(pfn);
+ pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
+ L_PTE_DIRTY | L_PTE_WRITE | flags);
+ pgd_t *pgd;
int err = 0;
- pgd_t * dir;
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- BUG_ON(address >= end);
+ BUG_ON(addr >= end);
+ pgd = pgd_offset_k(addr);
do {
- pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
- if (!pmd) {
- err = -ENOMEM;
- break;
- }
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags)) {
- err = -ENOMEM;
+ next = pgd_addr_end(addr, end);
+ err = remap_area_pmd(pgd, addr, next, phys_addr, prot);
+ if (err)
break;
- }
-
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
+ phys_addr += next - addr;
+ } while (pgd++, addr = next, addr != end);
return err;
}
@@ -310,13 +292,16 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
return NULL;
+ size = PAGE_ALIGN(size);
+
area = get_vm_area(size, VM_IOREMAP);
if (!area)
return NULL;
addr = (unsigned long)area->addr;
#ifndef CONFIG_SMP
- if ((((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
+ if (DOMAIN_IO == 0 &&
+ (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
cpu_is_xsc3()) &&
!((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) {
area->flags |= VM_ARM_SECTION_MAPPING;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index b7f194af20b..655c8376f0b 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -154,6 +154,26 @@ static int __init noalign_setup(char *__unused)
}
__setup("noalign", noalign_setup);
+#ifndef CONFIG_SMP
+void adjust_cr(unsigned long mask, unsigned long set)
+{
+ unsigned long flags;
+
+ mask &= ~CR_A;
+
+ set &= mask;
+
+ local_irq_save(flags);
+
+ cr_no_alignment = (cr_no_alignment & ~mask) | set;
+ cr_alignment = (cr_alignment & ~mask) | set;
+
+ set_cr((get_cr() & ~mask) | set);
+
+ local_irq_restore(flags);
+}
+#endif
+
struct mem_types {
unsigned int prot_pte;
unsigned int prot_l1;
@@ -294,12 +314,6 @@ static void __init build_mem_type_table(void)
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
- /*
- * User pages need to be mapped with the ASID
- * (iow, non-global)
- */
- user_pgprot |= L_PTE_ASID;
-
#ifdef CONFIG_SMP
/*
* Mark memory with the "shared" attribute for SMP systems
@@ -408,7 +422,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
}
ptep = pte_offset_kernel(pmdp, virt);
- set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
+ set_pte_ext(ptep, pfn_pte(phys >> PAGE_SHIFT, prot), 0);
}
/*
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 20c1b0df75f..50b9aed6000 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -57,7 +57,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
init_pmd = pmd_offset(init_pgd, 0);
init_pte = pte_offset_map_nested(init_pmd, 0);
- set_pte(new_pte, *init_pte);
+ set_pte_ext(new_pte, *init_pte, 0);
pte_unmap_nested(init_pte);
pte_unmap(new_pte);
}
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 289b8e6f504..700c04d6996 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -397,7 +397,7 @@ ENTRY(cpu_arm1020_switch_mm)
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm1020_set_pte)
+ENTRY(cpu_arm1020_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -477,7 +477,7 @@ arm1020_processor_functions:
.word cpu_arm1020_do_idle
.word cpu_arm1020_dcache_clean_area
.word cpu_arm1020_switch_mm
- .word cpu_arm1020_set_pte
+ .word cpu_arm1020_set_pte_ext
.size arm1020_processor_functions, . - arm1020_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index bed9db6ba58..1cc206ab5ea 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -381,7 +381,7 @@ ENTRY(cpu_arm1020e_switch_mm)
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm1020e_set_pte)
+ENTRY(cpu_arm1020e_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -458,7 +458,7 @@ arm1020e_processor_functions:
.word cpu_arm1020e_do_idle
.word cpu_arm1020e_dcache_clean_area
.word cpu_arm1020e_switch_mm
- .word cpu_arm1020e_set_pte
+ .word cpu_arm1020e_set_pte_ext
.size arm1020e_processor_functions, . - arm1020e_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index d2a7c1b9cab..aff0ea08e2f 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -358,12 +358,12 @@ ENTRY(cpu_arm1022_switch_mm)
mov pc, lr
/*
- * cpu_arm1022_set_pte(ptep, pte)
+ * cpu_arm1022_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm1022_set_pte)
+ENTRY(cpu_arm1022_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -441,7 +441,7 @@ arm1022_processor_functions:
.word cpu_arm1022_do_idle
.word cpu_arm1022_dcache_clean_area
.word cpu_arm1022_switch_mm
- .word cpu_arm1022_set_pte
+ .word cpu_arm1022_set_pte_ext
.size arm1022_processor_functions, . - arm1022_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 3247ce5c017..65e43a10908 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -347,12 +347,12 @@ ENTRY(cpu_arm1026_switch_mm)
mov pc, lr
/*
- * cpu_arm1026_set_pte(ptep, pte)
+ * cpu_arm1026_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm1026_set_pte)
+ENTRY(cpu_arm1026_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -436,7 +436,7 @@ arm1026_processor_functions:
.word cpu_arm1026_do_idle
.word cpu_arm1026_dcache_clean_area
.word cpu_arm1026_switch_mm
- .word cpu_arm1026_set_pte
+ .word cpu_arm1026_set_pte_ext
.size arm1026_processor_functions, . - arm1026_processor_functions
.section .rodata
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index ce4f9eef763..123a7dc7a43 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -209,14 +209,14 @@ ENTRY(cpu_arm7_switch_mm)
mov pc, lr
/*
- * Function: arm6_7_set_pte(pte_t *ptep, pte_t pte)
+ * Function: arm6_7_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext)
* Params : r0 = Address to set
* : r1 = value to set
* Purpose : Set a PTE and flush it out of any WB cache
*/
.align 5
-ENTRY(cpu_arm6_set_pte)
-ENTRY(cpu_arm7_set_pte)
+ENTRY(cpu_arm6_set_pte_ext)
+ENTRY(cpu_arm7_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -299,7 +299,7 @@ ENTRY(arm6_processor_functions)
.word cpu_arm6_do_idle
.word cpu_arm6_dcache_clean_area
.word cpu_arm6_switch_mm
- .word cpu_arm6_set_pte
+ .word cpu_arm6_set_pte_ext
.size arm6_processor_functions, . - arm6_processor_functions
/*
@@ -315,7 +315,7 @@ ENTRY(arm7_processor_functions)
.word cpu_arm7_do_idle
.word cpu_arm7_dcache_clean_area
.word cpu_arm7_switch_mm
- .word cpu_arm7_set_pte
+ .word cpu_arm7_set_pte_ext
.size arm7_processor_functions, . - arm7_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index c04c194da78..dc763be4336 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -88,13 +88,13 @@ ENTRY(cpu_arm720_switch_mm)
mov pc, lr
/*
- * Function: arm720_set_pte(pte_t *ptep, pte_t pte)
+ * Function: arm720_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext)
* Params : r0 = Address to set
* : r1 = value to set
* Purpose : Set a PTE and flush it out of any WB cache
*/
.align 5
-ENTRY(cpu_arm720_set_pte)
+ENTRY(cpu_arm720_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -204,7 +204,7 @@ ENTRY(arm720_processor_functions)
.word cpu_arm720_do_idle
.word cpu_arm720_dcache_clean_area
.word cpu_arm720_switch_mm
- .word cpu_arm720_set_pte
+ .word cpu_arm720_set_pte_ext
.size arm720_processor_functions, . - arm720_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 65cbb2851bf..75c945ed6c4 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -344,12 +344,12 @@ ENTRY(cpu_arm920_switch_mm)
mov pc, lr
/*
- * cpu_arm920_set_pte(ptep, pte)
+ * cpu_arm920_set_pte(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm920_set_pte)
+ENTRY(cpu_arm920_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -423,7 +423,7 @@ arm920_processor_functions:
.word cpu_arm920_do_idle
.word cpu_arm920_dcache_clean_area
.word cpu_arm920_switch_mm
- .word cpu_arm920_set_pte
+ .word cpu_arm920_set_pte_ext
.size arm920_processor_functions, . - arm920_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 52761b70d73..ffb751b877f 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -348,12 +348,12 @@ ENTRY(cpu_arm922_switch_mm)
mov pc, lr
/*
- * cpu_arm922_set_pte(ptep, pte)
+ * cpu_arm922_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm922_set_pte)
+ENTRY(cpu_arm922_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -427,7 +427,7 @@ arm922_processor_functions:
.word cpu_arm922_do_idle
.word cpu_arm922_dcache_clean_area
.word cpu_arm922_switch_mm
- .word cpu_arm922_set_pte
+ .word cpu_arm922_set_pte_ext
.size arm922_processor_functions, . - arm922_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 5b74339d158..44c2c997819 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -391,12 +391,12 @@ ENTRY(cpu_arm925_switch_mm)
mov pc, lr
/*
- * cpu_arm925_set_pte(ptep, pte)
+ * cpu_arm925_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm925_set_pte)
+ENTRY(cpu_arm925_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -490,7 +490,7 @@ arm925_processor_functions:
.word cpu_arm925_do_idle
.word cpu_arm925_dcache_clean_area
.word cpu_arm925_switch_mm
- .word cpu_arm925_set_pte
+ .word cpu_arm925_set_pte_ext
.size arm925_processor_functions, . - arm925_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 8628ed29a95..5b80b6bdd0c 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -348,12 +348,12 @@ ENTRY(cpu_arm926_switch_mm)
mov pc, lr
/*
- * cpu_arm926_set_pte(ptep, pte)
+ * cpu_arm926_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_arm926_set_pte)
+ENTRY(cpu_arm926_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -439,7 +439,7 @@ arm926_processor_functions:
.word cpu_arm926_do_idle
.word cpu_arm926_dcache_clean_area
.word cpu_arm926_switch_mm
- .word cpu_arm926_set_pte
+ .word cpu_arm926_set_pte_ext
.size arm926_processor_functions, . - arm926_processor_functions
.section ".rodata"
@@ -480,7 +480,7 @@ __arm926_proc_info:
b __arm926_setup
.long cpu_arch_name
.long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
.long cpu_arm926_name
.long arm926_processor_functions
.long v4wbi_tlb_fns
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index cd7d865c9d1..6e226e12989 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -146,12 +146,12 @@ ENTRY(cpu_sa110_switch_mm)
#endif
/*
- * cpu_sa110_set_pte(ptep, pte)
+ * cpu_sa110_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_sa110_set_pte)
+ENTRY(cpu_sa110_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -222,7 +222,7 @@ ENTRY(sa110_processor_functions)
.word cpu_sa110_do_idle
.word cpu_sa110_dcache_clean_area
.word cpu_sa110_switch_mm
- .word cpu_sa110_set_pte
+ .word cpu_sa110_set_pte_ext
.size sa110_processor_functions, . - sa110_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index b776653cc31..9afb11d089f 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -159,12 +159,12 @@ ENTRY(cpu_sa1100_switch_mm)
#endif
/*
- * cpu_sa1100_set_pte(ptep, pte)
+ * cpu_sa1100_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*/
.align 5
-ENTRY(cpu_sa1100_set_pte)
+ENTRY(cpu_sa1100_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
@@ -237,7 +237,7 @@ ENTRY(sa1100_processor_functions)
.word cpu_sa1100_do_idle
.word cpu_sa1100_dcache_clean_area
.word cpu_sa1100_switch_mm
- .word cpu_sa1100_set_pte
+ .word cpu_sa1100_set_pte_ext
.size sa1100_processor_functions, . - sa1100_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index ab143557e68..9f396b4fa0b 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -17,7 +17,7 @@
#ifndef MULTI_CPU
EXPORT_SYMBOL(cpu_dcache_clean_area);
-EXPORT_SYMBOL(cpu_set_pte);
+EXPORT_SYMBOL(cpu_set_pte_ext);
#else
EXPORT_SYMBOL(processor);
#endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index b440c8a1d34..7b1843befb9 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -103,13 +103,14 @@ ENTRY(cpu_v6_switch_mm)
mov pc, lr
/*
- * cpu_v6_set_pte(ptep, pte)
+ * cpu_v6_set_pte_ext(ptep, pte, ext)
*
* Set a level 2 translation table entry.
*
* - ptep - pointer to level 2 translation table entry
* (hardware version is stored at -1024 bytes)
* - pte - PTE value to store
+ * - ext - value for extended PTE bits
*
* Permissions:
* YUWD APX AP1 AP0 SVC User
@@ -121,33 +122,34 @@ ENTRY(cpu_v6_switch_mm)
* 11x0 0 1 0 r/w r/o
* 1111 0 1 1 r/w r/w
*/
-ENTRY(cpu_v6_set_pte)
+ENTRY(cpu_v6_set_pte_ext)
#ifdef CONFIG_MMU
str r1, [r0], #-2048 @ linux version
- bic r2, r1, #0x000003f0
- bic r2, r2, #0x00000003
- orr r2, r2, #PTE_EXT_AP0 | 2
+ bic r3, r1, #0x000003f0
+ bic r3, r3, #0x00000003
+ orr r3, r3, r2
+ orr r3, r3, #PTE_EXT_AP0 | 2
tst r1, #L_PTE_WRITE
tstne r1, #L_PTE_DIRTY
- orreq r2, r2, #PTE_EXT_APX
+ orreq r3, r3, #PTE_EXT_APX
tst r1, #L_PTE_USER
- orrne r2, r2, #PTE_EXT_AP1
- tstne r2, #PTE_EXT_APX
- bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
+ orrne r3, r3, #PTE_EXT_AP1
+ tstne r3, #PTE_EXT_APX
+ bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
tst r1, #L_PTE_YOUNG
- biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
+ biceq r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK
tst r1, #L_PTE_EXEC
- orreq r2, r2, #PTE_EXT_XN
+ orreq r3, r3, #PTE_EXT_XN
tst r1, #L_PTE_PRESENT
- moveq r2, #0
+ moveq r3, #0
- str r2, [r0]
+ str r3, [r0]
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
#endif
mov pc, lr
@@ -156,7 +158,7 @@ ENTRY(cpu_v6_set_pte)
cpu_v6_name:
- .asciz "Some Random V6 Processor"
+ .asciz "ARMv6-compatible processor"
.align
.section ".text.init", #alloc, #execinstr
@@ -207,11 +209,6 @@ __v6_setup:
#endif
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
#endif /* CONFIG_MMU */
-#ifdef CONFIG_VFP
- mrc p15, 0, r0, c1, c0, 2
- orr r0, r0, #(0xf << 20)
- mcr p15, 0, r0, c1, c0, 2 @ Enable full access to VFP
-#endif
adr r5, v6_crval
ldmia r5, {r5, r6}
mrc p15, 0, r0, c1, c0, 0 @ read control register
@@ -238,7 +235,7 @@ ENTRY(v6_processor_functions)
.word cpu_v6_do_idle
.word cpu_v6_dcache_clean_area
.word cpu_v6_switch_mm
- .word cpu_v6_set_pte
+ .word cpu_v6_set_pte_ext
.size v6_processor_functions, . - v6_processor_functions
.type cpu_arch_name, #object
@@ -273,7 +270,7 @@ __v6_proc_info:
b __v6_setup
.long cpu_arch_name
.long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
.long cpu_v6_name
.long v6_processor_functions
.long v6wbi_tlb_fns
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 1ef564d0957..94a58455f34 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -2,7 +2,7 @@
* linux/arch/arm/mm/proc-xsc3.S
*
* Original Author: Matthew Gilbert
- * Current Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
*
* Copyright 2004 (C) Intel Corp.
* Copyright 2005 (c) MontaVista Software, Inc.
@@ -357,13 +357,13 @@ ENTRY(cpu_xsc3_switch_mm)
cpwait_ret lr, ip
/*
- * cpu_xsc3_set_pte(ptep, pte)
+ * cpu_xsc3_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*
*/
.align 5
-ENTRY(cpu_xsc3_set_pte)
+ENTRY(cpu_xsc3_set_pte_ext)
str r1, [r0], #-2048 @ linux version
bic r2, r1, #0xff0 @ Keep C, B bits
@@ -457,7 +457,7 @@ ENTRY(xsc3_processor_functions)
.word cpu_xsc3_do_idle
.word cpu_xsc3_dcache_clean_area
.word cpu_xsc3_switch_mm
- .word cpu_xsc3_set_pte
+ .word cpu_xsc3_set_pte_ext
.size xsc3_processor_functions, . - xsc3_processor_functions
.section ".rodata"
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index cc1004b3e51..d29fe927ee9 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -421,14 +421,14 @@ ENTRY(cpu_xscale_switch_mm)
cpwait_ret lr, ip
/*
- * cpu_xscale_set_pte(ptep, pte)
+ * cpu_xscale_set_pte_ext(ptep, pte, ext)
*
* Set a PTE and flush it out
*
* Errata 40: must set memory to write-through for user read-only pages.
*/
.align 5
-ENTRY(cpu_xscale_set_pte)
+ENTRY(cpu_xscale_set_pte_ext)
str r1, [r0], #-2048 @ linux version
bic r2, r1, #0xff0
@@ -529,7 +529,7 @@ ENTRY(xscale_processor_functions)
.word cpu_xscale_do_idle
.word cpu_xscale_dcache_clean_area
.word cpu_xscale_switch_mm
- .word cpu_xscale_set_pte
+ .word cpu_xscale_set_pte_ext
.size xscale_processor_functions, . - xscale_processor_functions
.section ".rodata"
@@ -708,7 +708,7 @@ __8032x_proc_info:
.type __8033x_proc_info,#object
__8033x_proc_info:
.long 0x69054010
- .long 0xffffff30
+ .long 0xfffffd30
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index ec752e16d61..f2dc363de66 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -113,7 +113,7 @@ endchoice
config OMAP_SERIAL_WAKE
bool "Enable wake-up events for serial ports"
- depends OMAP_MUX
+ depends on OMAP_MUX
default y
help
Select this option if you want to have your system wake up
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8bcb838e544..bd78058b717 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Thu Dec 7 17:19:20 2006
+# Last update: Tue Jan 16 16:52:56 2007
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -1219,3 +1219,26 @@ zevio_1020 MACH_ZEVIO_1020 ZEVIO_1020 1207
hitrack MACH_HITRACK HITRACK 1208
syme1 MACH_SYME1 SYME1 1209
syhl1 MACH_SYHL1 SYHL1 1210
+empca400 MACH_EMPCA400 EMPCA400 1211
+em7210 MACH_EM7210 EM7210 1212
+htchermes MACH_HTCHERMES HTCHERMES 1213
+eti_c1 MACH_ETI_C1 ETI_C1 1214
+mach_dep2410 MACH_MACH_DEP2410 MACH_DEP2410 1215
+ac100 MACH_AC100 AC100 1216
+sneetch MACH_SNEETCH SNEETCH 1217
+studentmate MACH_STUDENTMATE STUDENTMATE 1218
+zir2410 MACH_ZIR2410 ZIR2410 1219
+zir2413 MACH_ZIR2413 ZIR2413 1220
+dlonip3 MACH_DLONIP3 DLONIP3 1221
+instream MACH_INSTREAM INSTREAM 1222
+ambarella MACH_AMBARELLA AMBARELLA 1223
+nevis MACH_NEVIS NEVIS 1224
+htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225
+ql202b MACH_QL202B QL202B 1226
+vpac270 MACH_VPAC270 VPAC270 1227
+rd129 MACH_RD129 RD129 1228
+htcwizard MACH_HTCWIZARD HTCWIZARD 1229
+xscale_treo680 MACH_XSCALE_TREO680 XSCALE_TREO680 1230
+tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231
+zylonite MACH_ZYLONITE ZYLONITE 1233
+gene1270 MACH_GENE1270 GENE1270 1234
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index 7b595547c1c..ca2a5ad19ea 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -25,6 +25,7 @@
do_vfp:
enable_irq
ldr r4, .LCvfp
+ ldr r11, [r10, #TI_CPU] @ CPU number
add r10, r10, #TI_VFPSTATE @ r10 = workspace
ldr pc, [r4] @ call VFP entry point
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index f2797896e6d..54a2ad6d9ca 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -370,3 +370,7 @@ struct op {
u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
u32 flags;
};
+
+#ifdef CONFIG_SMP
+extern void vfp_save_state(void *location, u32 fpexc);
+#endif
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index e51e6679c40..d4b7b229631 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -65,6 +65,7 @@
@ r2 = faulted PC+4
@ r9 = successful return
@ r10 = vfp_state union
+@ r11 = CPU number
@ lr = failure return
.globl vfp_support_entry
@@ -79,7 +80,7 @@ vfp_support_entry:
DBGSTR1 "enable %x", r10
ldr r3, last_VFP_context_address
orr r1, r1, #FPEXC_ENABLE @ user FPEXC has the enable bit set
- ldr r4, [r3] @ last_VFP_context pointer
+ ldr r4, [r3, r11, lsl #2] @ last_VFP_context pointer
bic r5, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled
cmp r4, r10
beq check_for_exception @ we are returning to the same
@@ -91,7 +92,9 @@ vfp_support_entry:
@ exceptions, so we can get at the
@ rest of it
+#ifndef CONFIG_SMP
@ Save out the current registers to the old thread state
+ @ No need for SMP since this is not done lazily
DBGSTR1 "save old state %p", r4
cmp r4, #0
@@ -105,10 +108,11 @@ vfp_support_entry:
stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2
@ and point r4 at the word at the
@ start of the register dump
+#endif
no_old_VFP_process:
DBGSTR1 "load state %p", r10
- str r10, [r3] @ update the last_VFP_context pointer
+ str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer
@ Load the saved state back into the VFP
VFPFLDMIA r10 @ reload the working registers while
@ FPEXC is in a safe state
@@ -162,6 +166,24 @@ process_exception:
@ required. If not, the user code will
@ retry the faulted instruction
+#ifdef CONFIG_SMP
+ .globl vfp_save_state
+ .type vfp_save_state, %function
+vfp_save_state:
+ @ Save the current VFP state
+ @ r0 - save location
+ @ r1 - FPEXC
+ DBGSTR1 "save VFP state %p", r0
+ VFPFMRX r2, FPSCR @ current status
+ VFPFMRX r3, FPINST @ FPINST (always there, rev0 onwards)
+ tst r1, #FPEXC_FPV2 @ is there an FPINST2 to read?
+ VFPFMRX r12, FPINST2, NE @ FPINST2 if needed - avoids reading
+ @ nonexistant reg on rev0
+ VFPFSTMIA r0 @ save the working registers
+ stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2
+ mov pc, lr
+#endif
+
last_VFP_context_address:
.word last_VFP_context
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f08eafbddcc..f1e5951dc72 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -28,7 +28,7 @@ void vfp_testing_entry(void);
void vfp_support_entry(void);
void (*vfp_vector)(void) = vfp_testing_entry;
-union vfp_state *last_VFP_context;
+union vfp_state *last_VFP_context[NR_CPUS];
/*
* Dual-use variable.
@@ -41,13 +41,35 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
{
struct thread_info *thread = v;
union vfp_state *vfp;
+ __u32 cpu = thread->cpu;
if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
+ u32 fpexc = fmrx(FPEXC);
+
+#ifdef CONFIG_SMP
+ /*
+ * On SMP, if VFP is enabled, save the old state in
+ * case the thread migrates to a different CPU. The
+ * restoring is done lazily.
+ */
+ if ((fpexc & FPEXC_ENABLE) && last_VFP_context[cpu]) {
+ vfp_save_state(last_VFP_context[cpu], fpexc);
+ last_VFP_context[cpu]->hard.cpu = cpu;
+ }
+ /*
+ * Thread migration, just force the reloading of the
+ * state on the new CPU in case the VFP registers
+ * contain stale data.
+ */
+ if (thread->vfpstate.hard.cpu != cpu)
+ last_VFP_context[cpu] = NULL;
+#endif
+
/*
* Always disable VFP so we can lazily save/restore the
* old state.
*/
- fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+ fmxr(FPEXC, fpexc & ~FPEXC_ENABLE);
return NOTIFY_DONE;
}
@@ -68,8 +90,8 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
}
/* flush and release case: Per-thread VFP cleanup. */
- if (last_VFP_context == vfp)
- last_VFP_context = NULL;
+ if (last_VFP_context[cpu] == vfp)
+ last_VFP_context[cpu] = NULL;
return NOTIFY_DONE;
}
@@ -263,13 +285,36 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
if (exceptions)
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
}
-
+
+static void vfp_enable(void *unused)
+{
+ u32 access = get_copro_access();
+
+ /*
+ * Enable full access to VFP (cp10 and cp11)
+ */
+ set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
+}
+
+#include <linux/smp.h>
+
/*
* VFP support code initialisation.
*/
static int __init vfp_init(void)
{
unsigned int vfpsid;
+ unsigned int cpu_arch = cpu_architecture();
+ u32 access = 0;
+
+ if (cpu_arch >= CPU_ARCH_ARMv6) {
+ access = get_copro_access();
+
+ /*
+ * Enable full access to VFP (cp10 and cp11)
+ */
+ set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));
+ }
/*
* First check that there is a VFP that we can use.
@@ -277,13 +322,22 @@ static int __init vfp_init(void)
* we just need to read the VFPSID register.
*/
vfpsid = fmrx(FPSID);
+ barrier();
printk(KERN_INFO "VFP support v0.3: ");
if (VFP_arch) {
printk("not present\n");
+
+ /*
+ * Restore the copro access register.
+ */
+ if (cpu_arch >= CPU_ARCH_ARMv6)
+ set_copro_access(access);
} else if (vfpsid & FPSID_NODOUBLE) {
printk("no double precision support\n");
} else {
+ smp_call_function(vfp_enable, NULL, 1, 1);
+
VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */
printk("implementor %02x architecture %d part %02x variant %x rev %x\n",
(vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT,
@@ -291,9 +345,16 @@ static int __init vfp_init(void)
(vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT,
(vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
(vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
+
vfp_vector = vfp_support_entry;
thread_register_notifier(&vfp_notifier_block);
+
+ /*
+ * We detected VFP, and the support code is
+ * in place; report VFP support to userspace.
+ */
+ elf_hwcap |= HWCAP_VFP;
}
return 0;
}
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index c14fe918bc4..74eba8b5a8c 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -41,6 +41,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_HWEIGHT
bool
default y
diff --git a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
index 43dd41be71f..9dbc17247c6 100644
--- a/arch/arm26/kernel/ecard.c
+++ b/arch/arm26/kernel/ecard.c
@@ -215,7 +215,7 @@ int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
}
if (c_id(&excd) == 0x80) { /* loader */
if (!ec->loader) {
- ec->loader = (loader_t)kmalloc(c_len(&excd),
+ ec->loader = kmalloc(c_len(&excd),
GFP_KERNEL);
if (ec->loader)
ecard_readbytes(ec->loader, ec,
diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
index d87d68b77d6..d53382c83bf 100644
--- a/arch/arm26/kernel/irq.c
+++ b/arch/arm26/kernel/irq.c
@@ -545,7 +545,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_
(irq_flags & IRQF_SHARED && !dev_id))
return -EINVAL;
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return -ENOMEM;
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 5f1694eea84..bb059a4e1df 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -45,6 +45,14 @@ config GENERIC_TIME
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_BUST_SPINLOCK
bool
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index cced73c5811..32b361f31c2 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -7,20 +7,83 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/setup.h>
#include <asm/arch/board.h>
#include <asm/arch/init.h>
-struct eth_platform_data __initdata eth0_data = {
- .valid = 1,
- .mii_phy_addr = 0x10,
- .is_rmii = 0,
- .hw_addr = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
+struct eth_addr {
+ u8 addr[6];
};
+static struct eth_addr __initdata hw_addr[2];
+
+static struct eth_platform_data __initdata eth_data[2];
extern struct lcdc_platform_data atstk1000_fb0_data;
+/*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+ * ethernet address. But we need to keep it around for a while until
+ * we can be reasonably sure the boot loader does this.
+ *
+ * The phy_id is ignored as the driver will probe for it.
+ */
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+ int i;
+
+ i = tag->u.ethernet.mac_index;
+ if (i < ARRAY_SIZE(hw_addr))
+ memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
+ sizeof(hw_addr[i].addr));
+
+ return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+static void __init set_hw_addr(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ const u8 *addr;
+ void __iomem *regs;
+ struct clk *pclk;
+
+ if (!res)
+ return;
+ if (pdev->id >= ARRAY_SIZE(hw_addr))
+ return;
+
+ addr = hw_addr[pdev->id].addr;
+ if (!is_valid_ether_addr(addr))
+ return;
+
+ /*
+ * Since this is board-specific code, we'll cheat and use the
+ * physical address directly as we happen to know that it's
+ * the same as the virtual address.
+ */
+ regs = (void __iomem __force *)res->start;
+ pclk = clk_get(&pdev->dev, "pclk");
+ if (!pclk)
+ return;
+
+ clk_enable(pclk);
+ __raw_writel((addr[3] << 24) | (addr[2] << 16)
+ | (addr[1] << 8) | addr[0], regs + 0x98);
+ __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
+ clk_disable(pclk);
+ clk_put(pclk);
+}
+
void __init setup_board(void)
{
at32_map_usart(1, 0); /* /dev/ttyS0 */
@@ -38,7 +101,8 @@ static int __init atstk1002_init(void)
at32_add_device_usart(1);
at32_add_device_usart(2);
- at32_add_device_eth(0, &eth0_data);
+ set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
+
at32_add_device_spi(0);
at32_add_device_lcdc(0, &atstk1000_fb0_data);
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index ae92a14ef9a..77dace9d54b 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Fri Oct 20 11:52:37 2006
+# Linux kernel version: 2.6.20-rc6
+# Fri Jan 26 13:12:59 2007
#
CONFIG_AVR32=y
CONFIG_GENERIC_HARDIRQS=y
@@ -9,6 +9,8 @@ CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -36,6 +38,7 @@ CONFIG_TASK_DELAY_ACCT=y
# CONFIG_UTS_NS is not set
CONFIG_AUDIT=y
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -75,7 +78,9 @@ CONFIG_MODULE_UNLOAD=y
# Block layer
#
CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -125,6 +130,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_OWNERSHIP_TRACE is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_CMDLINE=""
@@ -182,6 +188,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -260,6 +267,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
@@ -355,7 +363,6 @@ CONFIG_BLK_DEV_INITRD=y
#
# Misc devices
#
-# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
#
@@ -405,11 +412,14 @@ CONFIG_TUN=m
#
# PHY device support
#
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACB=y
#
# Ethernet (1000 Mbit)
@@ -505,10 +515,6 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
@@ -621,6 +627,10 @@ CONFIG_UNIX98_PTYS=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=m
@@ -683,7 +693,6 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -763,6 +772,11 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
@@ -770,6 +784,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -785,13 +801,10 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_KPROBES is not set
@@ -809,6 +822,7 @@ CONFIG_FORCED_INLINING=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -817,3 +831,4 @@ CONFIG_AUDIT_GENERIC=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
index 372e3f8b241..80f55f8dbf1 100644
--- a/arch/avr32/kernel/avr32_ksyms.c
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -7,12 +7,12 @@
* 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/io.h>
#include <linux/module.h>
#include <asm/checksum.h>
#include <asm/uaccess.h>
-#include <asm/delay.h>
/*
* GCC functions
@@ -29,6 +29,7 @@ EXPORT_SYMBOL(__avr32_asr64);
*/
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(clear_page);
/*
* Userspace access stuff.
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 317dc50945f..0b4325946a4 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -38,6 +38,13 @@ void cpu_idle(void)
void machine_halt(void)
{
+ /*
+ * Enter Stop mode. The 32 kHz oscillator will keep running so
+ * the RTC will keep the time properly and the system will
+ * boot quickly.
+ */
+ asm volatile("sleep 3\n\t"
+ "sub pc, -2");
}
void machine_power_off(void)
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index ea2d1ffee47..a3421160100 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -229,30 +229,6 @@ static int __init parse_tag_rsvd_mem(struct tag *tag)
}
__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
-static int __init parse_tag_ethernet(struct tag *tag)
-{
-#if 0
- const struct platform_device *pdev;
-
- /*
- * We really need a bus type that supports "classes"...this
- * will do for now (until we must handle other kinds of
- * ethernet controllers)
- */
- pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
- if (pdev && pdev->dev.platform_data) {
- struct eth_platform_data *data = pdev->dev.platform_data;
-
- data->valid = 1;
- data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
- memcpy(data->hw_addr, tag->u.ethernet.hw_address,
- sizeof(data->hw_addr));
- }
-#endif
- return 0;
-}
-__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
-
/*
* Scan the tag table for this tag, and call its parse function. The
* tag table is built by the linker from all the __tagtable
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
index 462c8307b68..b3bc0b56e2c 100644
--- a/arch/avr32/lib/delay.c
+++ b/arch/avr32/lib/delay.c
@@ -12,9 +12,9 @@
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/param.h>
#include <linux/types.h>
-#include <asm/delay.h>
#include <asm/processor.h>
#include <asm/sysreg.h>
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 7ff6ad8bab5..48f4ef38c70 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -11,6 +11,7 @@
#include <asm/io.h>
+#include <asm/arch/at32ap7000.h>
#include <asm/arch/board.h>
#include <asm/arch/portmux.h>
#include <asm/arch/sm.h>
@@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = { \
.num_resources = ARRAY_SIZE(_name##_id##_resource), \
}
+#define select_peripheral(pin, periph, flags) \
+ at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
+
#define DEV_CLK(_name, devname, bus, _index) \
static struct clk devname##_##_name = { \
.name = #_name, \
@@ -67,18 +71,6 @@ static struct clk devname##_##_name = { \
.index = _index, \
}
-enum {
- PIOA,
- PIOB,
- PIOC,
- PIOD,
-};
-
-enum {
- FUNC_A,
- FUNC_B,
-};
-
unsigned long at32ap7000_osc_rates[3] = {
[0] = 32768,
/* FIXME: these are ATSTK1002-specific */
@@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
static inline void configure_usart0_pins(void)
{
- portmux_set_func(PIOA, 8, FUNC_B); /* RXD */
- portmux_set_func(PIOA, 9, FUNC_B); /* TXD */
+ select_peripheral(PA(8), PERIPH_B, 0); /* RXD */
+ select_peripheral(PA(9), PERIPH_B, 0); /* TXD */
}
static inline void configure_usart1_pins(void)
{
- portmux_set_func(PIOA, 17, FUNC_A); /* RXD */
- portmux_set_func(PIOA, 18, FUNC_A); /* TXD */
+ select_peripheral(PA(17), PERIPH_A, 0); /* RXD */
+ select_peripheral(PA(18), PERIPH_A, 0); /* TXD */
}
static inline void configure_usart2_pins(void)
{
- portmux_set_func(PIOB, 26, FUNC_B); /* RXD */
- portmux_set_func(PIOB, 27, FUNC_B); /* TXD */
+ select_peripheral(PB(26), PERIPH_B, 0); /* RXD */
+ select_peripheral(PB(27), PERIPH_B, 0); /* TXD */
}
static inline void configure_usart3_pins(void)
{
- portmux_set_func(PIOB, 18, FUNC_B); /* RXD */
- portmux_set_func(PIOB, 17, FUNC_B); /* TXD */
+ select_peripheral(PB(18), PERIPH_B, 0); /* RXD */
+ select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
}
static struct platform_device *at32_usarts[4];
@@ -654,6 +646,15 @@ DEFINE_DEV_DATA(macb, 0);
DEV_CLK(hclk, macb0, hsb, 8);
DEV_CLK(pclk, macb0, pbb, 6);
+static struct eth_platform_data macb1_data;
+static struct resource macb1_resource[] = {
+ PBMEM(0xfff01c00),
+ IRQ(26),
+};
+DEFINE_DEV_DATA(macb, 1);
+DEV_CLK(hclk, macb1, hsb, 9);
+DEV_CLK(pclk, macb1, pbb, 7);
+
struct platform_device *__init
at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
{
@@ -663,27 +664,54 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
case 0:
pdev = &macb0_device;
- portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */
- portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */
- portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */
- portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */
- portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */
- portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */
- portmux_set_func(PIOC, 13, FUNC_A); /* RXER */
- portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */
- portmux_set_func(PIOC, 16, FUNC_A); /* MDC */
- portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */
+ select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */
+ select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */
+ select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */
+ select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */
+ select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */
+ select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
+ select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
+ select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
+ select_peripheral(PC(16), PERIPH_A, 0); /* MDC */
+ select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
+
+ if (!data->is_rmii) {
+ select_peripheral(PC(0), PERIPH_A, 0); /* COL */
+ select_peripheral(PC(1), PERIPH_A, 0); /* CRS */
+ select_peripheral(PC(2), PERIPH_A, 0); /* TXER */
+ select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */
+ select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */
+ select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
+ select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
+ select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
+ select_peripheral(PC(18), PERIPH_A, 0); /* SPD */
+ }
+ break;
+
+ case 1:
+ pdev = &macb1_device;
+
+ select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */
+ select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */
+ select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */
+ select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */
+ select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */
+ select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */
+ select_peripheral(PD(5), PERIPH_B, 0); /* RXER */
+ select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */
+ select_peripheral(PD(3), PERIPH_B, 0); /* MDC */
+ select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */
if (!data->is_rmii) {
- portmux_set_func(PIOC, 0, FUNC_A); /* COL */
- portmux_set_func(PIOC, 1, FUNC_A); /* CRS */
- portmux_set_func(PIOC, 2, FUNC_A); /* TXER */
- portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */
- portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */
- portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */
- portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */
- portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */
- portmux_set_func(PIOC, 18, FUNC_A); /* SPD */
+ select_peripheral(PC(19), PERIPH_B, 0); /* COL */
+ select_peripheral(PC(23), PERIPH_B, 0); /* CRS */
+ select_peripheral(PC(26), PERIPH_B, 0); /* TXER */
+ select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */
+ select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */
+ select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */
+ select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */
+ select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */
+ select_peripheral(PD(15), PERIPH_B, 0); /* SPD */
}
break;
@@ -714,12 +742,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
switch (id) {
case 0:
pdev = &spi0_device;
- portmux_set_func(PIOA, 0, FUNC_A); /* MISO */
- portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */
- portmux_set_func(PIOA, 2, FUNC_A); /* SCK */
- portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */
- portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */
- portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */
+ select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
+ select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
+ select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
+ select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */
+ select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */
+ select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */
break;
default:
@@ -762,37 +790,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
switch (id) {
case 0:
pdev = &lcdc0_device;
- portmux_set_func(PIOC, 19, FUNC_A); /* CC */
- portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */
- portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */
- portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */
- portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */
- portmux_set_func(PIOC, 24, FUNC_A); /* MODE */
- portmux_set_func(PIOC, 25, FUNC_A); /* PWR */
- portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */
- portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */
- portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */
- portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */
- portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */
- portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */
- portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */
- portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */
- portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */
- portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */
- portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */
- portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */
- portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */
- portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */
- portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */
- portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */
- portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */
- portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */
- portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */
- portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */
- portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */
- portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */
- portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */
- portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */
+ select_peripheral(PC(19), PERIPH_A, 0); /* CC */
+ select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */
+ select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */
+ select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */
+ select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */
+ select_peripheral(PC(24), PERIPH_A, 0); /* MODE */
+ select_peripheral(PC(25), PERIPH_A, 0); /* PWR */
+ select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */
+ select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */
+ select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */
+ select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */
+ select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */
+ select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */
+ select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */
+ select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */
+ select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */
+ select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */
+ select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */
+ select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */
+ select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */
+ select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */
+ select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */
+ select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */
+ select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
+ select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
+ select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
+ select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
+ select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
+ select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
+ select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+ select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
clk_set_parent(&lcdc0_pixclk, &pll0);
clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
@@ -838,6 +866,8 @@ struct clk *at32_clock_list[] = {
&atmel_usart3_usart,
&macb0_hclk,
&macb0_pclk,
+ &macb1_hclk,
+ &macb1_pclk,
&spi0_mck,
&lcdc0_hclk,
&lcdc0_pixclk,
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index 4dff1f98890..b59272e81b9 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -49,12 +49,25 @@ static void eim_unmask_irq(unsigned int irq)
static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
{
struct at32_sm *sm = get_irq_chip_data(irq);
+ struct irq_desc *desc;
unsigned int i = irq - sm->eim_first_irq;
u32 mode, edge, level;
unsigned long flags;
int ret = 0;
- flow_type &= IRQ_TYPE_SENSE_MASK;
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+
+ desc = &irq_desc[irq];
+ desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+ desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+
+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
+ desc->status |= IRQ_LEVEL;
+ set_irq_handler(irq, handle_level_irq);
+ } else {
+ set_irq_handler(irq, handle_edge_irq);
+ }
spin_lock_irqsave(&sm->lock, flags);
@@ -148,10 +161,15 @@ static int __init eim_init(void)
pattern = sm_readl(sm, EIM_MODE);
nr_irqs = fls(pattern);
+ /* Trigger on falling edge unless overridden by driver */
+ sm_writel(sm, EIM_MODE, 0UL);
+ sm_writel(sm, EIM_EDGE, 0UL);
+
sm->eim_chip = &eim_chip;
for (i = 0; i < nr_irqs; i++) {
- set_irq_chip(sm->eim_first_irq + i, &eim_chip);
+ set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
+ handle_edge_irq);
set_irq_chip_data(sm->eim_first_irq + i, sm);
}
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index eb87a18ad7b..dd5c009cf22 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -136,3 +136,7 @@ fail:
panic("Interrupt controller initialization failed!\n");
}
+unsigned long intc_get_pending(int group)
+{
+ return intc_readl(&intc0, INTREQ0 + 4 * group);
+}
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d3aabfca859..f1280ed8ed6 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -25,27 +25,98 @@ struct pio_device {
void __iomem *regs;
const struct platform_device *pdev;
struct clk *clk;
- u32 alloc_mask;
+ u32 pinmux_mask;
char name[32];
};
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
- unsigned int function_id)
+static struct pio_device *gpio_to_pio(unsigned int gpio)
{
struct pio_device *pio;
- u32 mask = 1 << pin_id;
+ unsigned int index;
- BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
+ index = gpio >> 5;
+ if (index >= MAX_NR_PIO_DEVICES)
+ return NULL;
+ pio = &pio_dev[index];
+ if (!pio->regs)
+ return NULL;
- pio = &pio_dev[portmux_id];
+ return pio;
+}
+
+/* Pin multiplexing API */
+
+void __init at32_select_periph(unsigned int pin, unsigned int periph,
+ unsigned long flags)
+{
+ struct pio_device *pio;
+ unsigned int pin_index = pin & 0x1f;
+ u32 mask = 1 << pin_index;
+
+ pio = gpio_to_pio(pin);
+ if (unlikely(!pio)) {
+ printk("pio: invalid pin %u\n", pin);
+ goto fail;
+ }
- if (function_id)
+ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+ printk("%s: pin %u is busy\n", pio->name, pin_index);
+ goto fail;
+ }
+
+ pio_writel(pio, PUER, mask);
+ if (periph)
pio_writel(pio, BSR, mask);
else
pio_writel(pio, ASR, mask);
+
pio_writel(pio, PDR, mask);
+ if (!(flags & AT32_GPIOF_PULLUP))
+ pio_writel(pio, PUDR, mask);
+
+ return;
+
+fail:
+ dump_stack();
+}
+
+void __init at32_select_gpio(unsigned int pin, unsigned long flags)
+{
+ struct pio_device *pio;
+ unsigned int pin_index = pin & 0x1f;
+ u32 mask = 1 << pin_index;
+
+ pio = gpio_to_pio(pin);
+ if (unlikely(!pio)) {
+ printk("pio: invalid pin %u\n", pin);
+ goto fail;
+ }
+
+ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+ printk("%s: pin %u is busy\n", pio->name, pin_index);
+ goto fail;
+ }
+
+ pio_writel(pio, PUER, mask);
+ if (flags & AT32_GPIOF_HIGH)
+ pio_writel(pio, SODR, mask);
+ else
+ pio_writel(pio, CODR, mask);
+ if (flags & AT32_GPIOF_OUTPUT)
+ pio_writel(pio, OER, mask);
+ else
+ pio_writel(pio, ODR, mask);
+
+ pio_writel(pio, PER, mask);
+ if (!(flags & AT32_GPIOF_PULLUP))
+ pio_writel(pio, PUDR, mask);
+
+ return;
+
+fail:
+ dump_stack();
}
static int __init pio_probe(struct platform_device *pdev)
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
deleted file mode 100644
index 03306eb0345..00000000000
--- a/arch/avr32/mach-at32ap/sm.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * System Manager driver for AT32AP CPUs
- *
- * Copyright (C) 2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-
-#include <asm/intc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/sm.h>
-
-#include "sm.h"
-
-#define SM_EIM_IRQ_RESOURCE 1
-#define SM_PM_IRQ_RESOURCE 2
-#define SM_RTC_IRQ_RESOURCE 3
-
-#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
-
-struct at32_sm system_manager;
-
-int __init at32_sm_init(void)
-{
- struct resource *regs;
- struct at32_sm *sm = &system_manager;
- int ret = -ENXIO;
-
- regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
- if (!regs)
- goto fail;
-
- spin_lock_init(&sm->lock);
- sm->pdev = &at32_sm_device;
-
- ret = -ENOMEM;
- sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
- if (!sm->regs)
- goto fail;
-
- return 0;
-
-fail:
- printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
- return ret;
-}
-
-/*
- * External Interrupt Module (EIM).
- *
- * EIM gets level- or edge-triggered interrupts of either polarity
- * from the outside and converts it to active-high level-triggered
- * interrupts that the internal interrupt controller can handle. EIM
- * also provides masking/unmasking of interrupts, as well as
- * acknowledging of edge-triggered interrupts.
- */
-
-static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
- disable_irq(irq);
- return IRQ_NONE;
-}
-
-static struct irqaction eim_spurious_action = {
- .handler = spurious_eim_interrupt,
-};
-
-static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct irq_controller * irqc = dev_id;
- struct at32_sm *sm = to_eim(irqc);
- unsigned long pending;
-
- /*
- * No need to disable interrupts globally. The interrupt
- * level relevant to this group must be masked all the time,
- * so we know that this particular EIM instance will not be
- * re-entered.
- */
- spin_lock(&sm->lock);
-
- pending = intc_get_pending(sm->irqc.irq_group);
- if (unlikely(!pending)) {
- printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
- sm->irqc.irq_group);
- goto unlock;
- }
-
- do {
- struct irqaction *action;
- unsigned int i;
-
- i = fls(pending) - 1;
- pending &= ~(1 << i);
- action = sm->action[i];
-
- /* Acknowledge the interrupt */
- sm_writel(sm, EIM_ICR, 1 << i);
-
- spin_unlock(&sm->lock);
-
- if (action->flags & SA_INTERRUPT)
- local_irq_disable();
- action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
- local_irq_enable();
- spin_lock(&sm->lock);
- if (action->flags & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(sm->irqc.first_irq + i);
- } while (pending);
-
-unlock:
- spin_unlock(&sm->lock);
- return IRQ_HANDLED;
-}
-
-static void eim_mask(struct irq_controller *irqc, unsigned int irq)
-{
- struct at32_sm *sm = to_eim(irqc);
- unsigned int i;
-
- i = irq - sm->irqc.first_irq;
- sm_writel(sm, EIM_IDR, 1 << i);
-}
-
-static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
-{
- struct at32_sm *sm = to_eim(irqc);
- unsigned int i;
-
- i = irq - sm->irqc.first_irq;
- sm_writel(sm, EIM_IER, 1 << i);
-}
-
-static int eim_setup(struct irq_controller *irqc, unsigned int irq,
- struct irqaction *action)
-{
- struct at32_sm *sm = to_eim(irqc);
- sm->action[irq - sm->irqc.first_irq] = action;
- /* Acknowledge earlier interrupts */
- sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
- eim_unmask(irqc, irq);
- return 0;
-}
-
-static void eim_free(struct irq_controller *irqc, unsigned int irq,
- void *dev)
-{
- struct at32_sm *sm = to_eim(irqc);
- eim_mask(irqc, irq);
- sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
-}
-
-static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
- unsigned int type)
-{
- struct at32_sm *sm = to_eim(irqc);
- unsigned long flags;
- u32 value, pattern;
-
- spin_lock_irqsave(&sm->lock, flags);
-
- pattern = 1 << (irq - sm->irqc.first_irq);
-
- value = sm_readl(sm, EIM_MODE);
- if (type & IRQ_TYPE_LEVEL)
- value |= pattern;
- else
- value &= ~pattern;
- sm_writel(sm, EIM_MODE, value);
- value = sm_readl(sm, EIM_EDGE);
- if (type & IRQ_EDGE_RISING)
- value |= pattern;
- else
- value &= ~pattern;
- sm_writel(sm, EIM_EDGE, value);
- value = sm_readl(sm, EIM_LEVEL);
- if (type & IRQ_LEVEL_HIGH)
- value |= pattern;
- else
- value &= ~pattern;
- sm_writel(sm, EIM_LEVEL, value);
-
- spin_unlock_irqrestore(&sm->lock, flags);
-
- return 0;
-}
-
-static unsigned int eim_get_type(struct irq_controller *irqc,
- unsigned int irq)
-{
- struct at32_sm *sm = to_eim(irqc);
- unsigned long flags;
- unsigned int type = 0;
- u32 mode, edge, level, pattern;
-
- pattern = 1 << (irq - sm->irqc.first_irq);
-
- spin_lock_irqsave(&sm->lock, flags);
- mode = sm_readl(sm, EIM_MODE);
- edge = sm_readl(sm, EIM_EDGE);
- level = sm_readl(sm, EIM_LEVEL);
- spin_unlock_irqrestore(&sm->lock, flags);
-
- if (mode & pattern)
- type |= IRQ_TYPE_LEVEL;
- if (edge & pattern)
- type |= IRQ_EDGE_RISING;
- if (level & pattern)
- type |= IRQ_LEVEL_HIGH;
-
- return type;
-}
-
-static struct irq_controller_class eim_irq_class = {
- .typename = "EIM",
- .handle = eim_handle_irq,
- .setup = eim_setup,
- .free = eim_free,
- .mask = eim_mask,
- .unmask = eim_unmask,
- .set_type = eim_set_type,
- .get_type = eim_get_type,
-};
-
-static int __init eim_init(void)
-{
- struct at32_sm *sm = &system_manager;
- unsigned int i;
- u32 pattern;
- int ret;
-
- /*
- * The EIM is really the same module as SM, so register
- * mapping, etc. has been taken care of already.
- */
-
- /*
- * Find out how many interrupt lines that are actually
- * implemented in hardware.
- */
- sm_writel(sm, EIM_IDR, ~0UL);
- sm_writel(sm, EIM_MODE, ~0UL);
- pattern = sm_readl(sm, EIM_MODE);
- sm->irqc.nr_irqs = fls(pattern);
-
- ret = -ENOMEM;
- sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
- GFP_KERNEL);
- if (!sm->action)
- goto out;
-
- for (i = 0; i < sm->irqc.nr_irqs; i++)
- sm->action[i] = &eim_spurious_action;
-
- spin_lock_init(&sm->lock);
- sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
- sm->irqc.class = &eim_irq_class;
-
- ret = intc_register_controller(&sm->irqc);
- if (ret < 0)
- goto out_free_actions;
-
- printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
- sm->regs, sm->irqc.irq_group);
- printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
- sm->irqc.nr_irqs, sm->irqc.first_irq);
-
- return 0;
-
-out_free_actions:
- kfree(sm->action);
-out:
- return ret;
-}
-arch_initcall(eim_init);
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 6a1238a29d6..3474309e049 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -16,6 +16,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index 4fa81abab0c..ffade19a14e 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -516,7 +516,7 @@ static int __init init_axis_flash(void)
#else
struct mtd_info *mtd_ram;
- mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+ mtd_ram = kmalloc(sizeof(struct mtd_info),
GFP_KERNEL);
if (!mtd_ram) {
panic("axisflashmap couldn't allocate memory for "
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index fcba6632ed7..9aba18b931d 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -440,7 +440,7 @@ gpio_open(struct inode *inode, struct file *filp)
if (p > GPIO_MINOR_LAST)
return -EINVAL;
- priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
+ priv = kmalloc(sizeof(struct gpio_private),
GFP_KERNEL);
if (!priv)
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 41952320e00..5180d45412f 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -427,7 +427,7 @@ static int __init init_axis_flash(void)
#else
struct mtd_info *mtd_ram;
- mtd_ram = (struct mtd_info *)kmalloc(sizeof(struct mtd_info),
+ mtd_ram = kmalloc(sizeof(struct mtd_info),
GFP_KERNEL);
if (!mtd_ram) {
panic("axisflashmap couldn't allocate memory for "
diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/gpio.c
index c3f876b4da6..08d36f0955c 100644
--- a/arch/cris/arch-v32/drivers/gpio.c
+++ b/arch/cris/arch-v32/drivers/gpio.c
@@ -423,7 +423,7 @@ gpio_open(struct inode *inode, struct file *filp)
if (p > GPIO_MINOR_LAST)
return -EINVAL;
- priv = (struct gpio_private *)kmalloc(sizeof(struct gpio_private),
+ priv = kmalloc(sizeof(struct gpio_private),
GFP_KERNEL);
if (!priv)
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index e067806b220..424eb0eb1cd 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -504,7 +504,7 @@ static int sync_serial_release(struct inode *inode, struct file *file)
static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
{
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
unsigned int mask = 0;
sync_port* port;
DEBUGPOLL( static unsigned int prev_mask = 0; );
@@ -531,7 +531,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int return_val = 0;
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
sync_port* port;
reg_sser_rw_tr_cfg tr_cfg;
reg_sser_rw_rec_cfg rec_cfg;
@@ -789,7 +789,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
static ssize_t sync_serial_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
DECLARE_WAITQUEUE(wait, current);
sync_port *port;
unsigned long c, c1;
@@ -919,7 +919,7 @@ static ssize_t sync_serial_write(struct file * file, const char * buf,
static ssize_t sync_serial_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
int avail;
sync_port *port;
unsigned char* start;
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 99e59b3eacf..7cd6ac80340 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -686,7 +686,7 @@ keep_debug_flags(unsigned long oldccs, unsigned long oldspc,
int __init
cris_init_signal(void)
{
- u16* data = (u16*)kmalloc(PAGE_SIZE, GFP_KERNEL);
+ u16* data = kmalloc(PAGE_SIZE, GFP_KERNEL);
/* This is movu.w __NR_sigreturn, r9; break 13; */
data[0] = 0x9c5f;
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 2d0023f2d49..77e655f2656 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -195,7 +195,7 @@ int setup_profiling_timer(unsigned int multiplier)
*/
unsigned long cache_decay_ticks = 1;
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
smp_boot_one_cpu(cpu);
return cpu_online(cpu) ? 0 : -ENOSYS;
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index 69c52189f04..f60ab785f23 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -59,7 +59,7 @@ static int
__init init_cris_profile(void)
{
struct proc_dir_entry *entry;
- sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
+ sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
sample_buffer_pos = sample_buffer;
entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
if (entry) {
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index cf1c446e003..7561d7b72e7 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -41,6 +41,14 @@ config TIME_LOW_RES
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default y
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default y
+
mainmenu "Fujitsu FR-V Kernel Configuration"
source "init/Kconfig"
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index c1d9fc8f1a8..ee677ced7b6 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -223,7 +223,7 @@ static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
static int cmode_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
if (oldval && oldlenp) {
size_t oldlen;
@@ -326,7 +326,7 @@ static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
static int p0_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
if (oldval && oldlenp) {
size_t oldlen;
@@ -370,7 +370,7 @@ static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
static int cm_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
if (oldval && oldlenp) {
size_t oldlen;
diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c
index f5a653033fe..9477ccce070 100644
--- a/arch/frv/mm/elf-fdpic.c
+++ b/arch/frv/mm/elf-fdpic.c
@@ -110,14 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
#if 0
printk("[area] l=%lx (ENOMEM) f='%s'\n",
- len, filp ? filp->f_dentry->d_name.name : "");
+ len, filp ? filp->f_path.dentry->d_name.name : "");
#endif
return -ENOMEM;
success:
#if 0
printk("[area] l=%lx ad=%lx f='%s'\n",
- len, addr, filp ? filp->f_dentry->d_name.name : "");
+ len, addr, filp ? filp->f_path.dentry->d_name.name : "");
#endif
return addr;
} /* end arch_get_unmapped_area() */
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index cabf0bfffc5..34a84bc4baf 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -29,6 +29,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
index 1bfc77e391d..587ef7f4fcc 100644
--- a/arch/h8300/kernel/ints.c
+++ b/arch/h8300/kernel/ints.c
@@ -141,7 +141,7 @@ int request_irq(unsigned int irq,
return -EBUSY;
if (use_kmalloc)
- irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+ irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
else {
/* use bootmem allocater */
irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index 270440de461..567f681ddfe 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -176,7 +176,7 @@ int request_irq(unsigned int irq,
}
if (use_kmalloc)
- irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
+ irq_handle = kmalloc(sizeof(irq_handler_t), GFP_ATOMIC);
else {
/* use bootmem allocater */
irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t));
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index ea70359b02d..0dfee812811 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -49,6 +49,11 @@ config GENERIC_IOMAP
bool
default y
+config GENERIC_BUG
+ bool
+ default y
+ depends on BUG
+
config GENERIC_HWEIGHT
bool
default y
@@ -185,6 +190,7 @@ endchoice
config PARAVIRT
bool "Paravirtualization support (EXPERIMENTAL)"
depends on EXPERIMENTAL
+ depends on !(X86_VISWS || X86_VOYAGER)
help
Paravirtualization is a way of running multiple instances of
Linux on the same machine, under a hypervisor. This option
@@ -771,6 +777,47 @@ config CRASH_DUMP
PHYSICAL_START.
For more details see Documentation/kdump/kdump.txt
+config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+ default "0x100000"
+ help
+ This gives the physical address where the kernel is loaded.
+
+ If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then
+ bzImage will decompress itself to above physical address and
+ run from there. Otherwise, bzImage will run from the address where
+ it has been loaded by the boot loader and will ignore above physical
+ address.
+
+ In normal kdump cases one does not have to set/change this option
+ as now bzImage can be compiled as a completely relocatable image
+ (CONFIG_RELOCATABLE=y) and be used to load and run from a different
+ address. This option is mainly useful for the folks who don't want
+ to use a bzImage for capturing the crash dump and want to use a
+ vmlinux instead. vmlinux is not relocatable hence a kernel needs
+ to be specifically compiled to run from a specific memory area
+ (normally a reserved region) and this option comes handy.
+
+ So if you are using bzImage for capturing the crash dump, leave
+ the value here unchanged to 0x100000 and set CONFIG_RELOCATABLE=y.
+ Otherwise if you plan to use vmlinux for capturing the crash dump
+ change this value to start of the reserved region (Typically 16MB
+ 0x1000000). In other words, it can be set based on the "X" value as
+ specified in the "crashkernel=YM@XM" command line boot parameter
+ passed to the panic-ed kernel. Typically this parameter is set as
+ crashkernel=64M@16M. Please take a look at
+ Documentation/kdump/kdump.txt for more details about crash dumps.
+
+ Usage of bzImage for capturing the crash dump is recommended as
+ one does not have to build two kernels. Same kernel can be used
+ as production kernel and capture kernel. Above option should have
+ gone away after relocatable bzImage support is introduced. But it
+ is present because there are users out there who continue to use
+ vmlinux for dump capture. This option should go away down the
+ line.
+
+ Don't change this unless you know what you are doing.
+
config RELOCATABLE
bool "Build a relocatable kernel(EXPERIMENTAL)"
depends on EXPERIMENTAL
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 821fd269ca5..2aecfba4ac4 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -248,6 +248,14 @@ config RWSEM_XCHGADD_ALGORITHM
depends on !M386
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/i386/boot/compressed/.gitignore b/arch/i386/boot/compressed/.gitignore
new file mode 100644
index 00000000000..be0ed065249
--- /dev/null
+++ b/arch/i386/boot/compressed/.gitignore
@@ -0,0 +1 @@
+relocs
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index f395a4bb38b..3517a32aaf4 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -28,7 +28,7 @@
#include <asm/page.h>
#include <asm/boot.h>
-.section ".text.head"
+.section ".text.head","ax",@progbits
.globl startup_32
startup_32:
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c
index 468da89153c..881951ca03e 100644
--- a/arch/i386/boot/compressed/relocs.c
+++ b/arch/i386/boot/compressed/relocs.c
@@ -43,6 +43,8 @@ static int is_safe_abs_reloc(const char* sym_name)
/* Match found */
return 1;
}
+ if (strncmp(sym_name, "__crc_", 6) == 0)
+ return 1;
return 0;
}
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 65891f11ace..5d80edfc61b 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-git7
-# Wed Dec 6 23:50:49 2006
+# Linux kernel version: 2.6.20-rc3
+# Fri Jan 5 11:54:46 2007
#
CONFIG_X86_32=y
CONFIG_GENERIC_TIME=y
@@ -12,6 +12,7 @@ CONFIG_X86=y
CONFIG_MMU=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_DMI=y
@@ -141,6 +142,8 @@ CONFIG_X86_CMPXCHG=y
CONFIG_X86_XADD=y
CONFIG_X86_L1_CACHE_SHIFT=7
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INVLPG=y
@@ -203,6 +206,7 @@ CONFIG_MTRR=y
CONFIG_SECCOMP=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
# CONFIG_KEXEC is not set
@@ -563,6 +567,7 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_PROC_FS is not set
@@ -583,6 +588,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -642,6 +648,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -1082,10 +1089,7 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-CONFIG_OSS_OBSOLETE_DRIVER=y
# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_ES1371 is not set
CONFIG_SOUND_ICH=y
# CONFIG_SOUND_TRIDENT is not set
@@ -1095,6 +1099,11 @@ CONFIG_SOUND_ICH=y
# CONFIG_SOUND_OSS is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1158,7 +1167,6 @@ CONFIG_USB_STORAGE=y
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
@@ -1279,6 +1287,11 @@ CONFIG_USB_MON=y
#
#
+# Virtualization
+#
+# CONFIG_KVM is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1444,6 +1457,11 @@ CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_UTF8=y
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Instrumentation Support
#
CONFIG_PROFILING=y
@@ -1458,6 +1476,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_UNUSED_SYMBOLS=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1476,14 +1496,10 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_HIGHMEM is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
-CONFIG_UNWIND_INFO=y
-CONFIG_STACK_UNWIND=y
# CONFIG_FORCED_INLINING is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
CONFIG_EARLY_PRINTK=y
@@ -1509,12 +1525,14 @@ CONFIG_DOUBLEFAULT=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_PENDING_IRQ=y
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index c8f96cff07c..cbcb2c27f48 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -333,7 +333,7 @@ acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
/*
* Parse Interrupt Source Override for the ACPI SCI
*/
-static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
{
if (trigger == 0) /* compatible SCI trigger is level */
trigger = 3;
@@ -1327,3 +1327,25 @@ static int __init setup_acpi_sci(char *s)
return 0;
}
early_param("acpi_sci", setup_acpi_sci);
+
+int __acpi_acquire_global_lock(unsigned int *lock)
+{
+ unsigned int old, new, val;
+ do {
+ old = *lock;
+ new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
+ val = cmpxchg(lock, old, new);
+ } while (unlikely (val != old));
+ return (new < 3) ? -1 : 0;
+}
+
+int __acpi_release_global_lock(unsigned int *lock)
+{
+ unsigned int old, new, val;
+ do {
+ old = *lock;
+ new = old & ~0x3;
+ val = cmpxchg(lock, old, new);
+ } while (unlikely (val != old));
+ return old & 0x1;
+}
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 12e937c1ce4..2d39f55d29a 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -47,13 +47,13 @@ EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
/* The code below handles cstate entry with monitor-mwait pair on Intel*/
-struct cstate_entry_s {
+struct cstate_entry {
struct {
unsigned int eax;
unsigned int ecx;
} states[ACPI_PROCESSOR_MAX_POWER];
};
-static struct cstate_entry_s *cpu_cstate_entry; /* per CPU ptr */
+static struct cstate_entry *cpu_cstate_entry; /* per CPU ptr */
static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
@@ -71,7 +71,7 @@ static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
int acpi_processor_ffh_cstate_probe(unsigned int cpu,
struct acpi_processor_cx *cx, struct acpi_power_register *reg)
{
- struct cstate_entry_s *percpu_entry;
+ struct cstate_entry *percpu_entry;
struct cpuinfo_x86 *c = cpu_data + cpu;
cpumask_t saved_mask;
@@ -136,7 +136,7 @@ EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
{
unsigned int cpu = smp_processor_id();
- struct cstate_entry_s *percpu_entry;
+ struct cstate_entry *percpu_entry;
percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
@@ -150,7 +150,7 @@ static int __init ffh_cstate_init(void)
if (c->x86_vendor != X86_VENDOR_INTEL)
return -1;
- cpu_cstate_entry = alloc_percpu(struct cstate_entry_s);
+ cpu_cstate_entry = alloc_percpu(struct cstate_entry);
return 0;
}
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index a97847da9ed..19901692754 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -785,7 +785,11 @@ static int apm_do_idle(void)
polling = !!(current_thread_info()->status & TS_POLLING);
if (polling) {
current_thread_info()->status &= ~TS_POLLING;
- smp_mb__after_clear_bit();
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
}
if (!need_resched()) {
idled = 1;
@@ -1604,7 +1608,7 @@ static int do_open(struct inode * inode, struct file * filp)
{
struct apm_user * as;
- as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
sizeof(*as));
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 1b34c56f812..8a8bbdaaf38 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -54,7 +54,7 @@ static struct cpu_dev __cpuinitdata default_cpu = {
.c_init = default_init,
.c_vendor = "Unknown",
};
-static struct cpu_dev * this_cpu = &default_cpu;
+static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;
static int __init cachesize_setup(char *str)
{
@@ -710,11 +710,8 @@ __cpuinit int init_gdt(int cpu, struct task_struct *idle)
return 1;
}
-/* Common CPU init for both boot and secondary CPUs */
-static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+void __cpuinit cpu_set_gdt(int cpu)
{
- struct tss_struct * t = &per_cpu(init_tss, cpu);
- struct thread_struct *thread = &curr->thread;
struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
/* Reinit these anyway, even if they've already been done (on
@@ -722,6 +719,13 @@ static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
the real ones). */
load_gdt(cpu_gdt_descr);
set_kernel_gs();
+}
+
+/* Common CPU init for both boot and secondary CPUs */
+static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
+{
+ struct tss_struct * t = &per_cpu(init_tss, cpu);
+ struct thread_struct *thread = &curr->thread;
if (cpu_test_and_set(cpu, cpu_initialized)) {
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -807,6 +811,7 @@ void __cpuinit cpu_init(void)
local_irq_enable();
}
+ cpu_set_gdt(cpu);
_cpu_init(cpu, curr);
}
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index ccc1edff5c9..5299c5bf445 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -17,6 +17,7 @@ config X86_ACPI_CPUFREQ
help
This driver adds a CPUFreq driver which utilizes the ACPI
Processor Performance States.
+ This driver also supports Intel Enhanced Speedstep.
For details, take a look at <file:Documentation/cpu-freq/>.
@@ -121,11 +122,14 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO_ACPI
- bool "Use ACPI tables to decode valid frequency/voltage pairs"
+ bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
default y
help
+ This is deprecated and this functionality is now merged into
+ acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
+ speedstep_centrino.
Use primarily the information provided in the BIOS ACPI tables
to determine valid CPU frequency and voltage pairings. It is
required for the driver to work on non-Banias CPUs.
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
index 2e894f1c891..8de3abe322a 100644
--- a/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -7,9 +7,9 @@ obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
obj-$(CONFIG_X86_LONGRUN) += longrun.o
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
-obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o
obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 57c880bf0bd..10baa3501ed 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -1,9 +1,10 @@
/*
- * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.3 $)
+ * acpi-cpufreq.c - ACPI Processor P-States Driver ($Revision: 1.4 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
+ * Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -27,202 +28,370 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
#include <linux/cpufreq.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
#include <linux/compiler.h>
-#include <linux/sched.h> /* current */
#include <linux/dmi.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/uaccess.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
MODULE_DESCRIPTION("ACPI Processor P-States Driver");
MODULE_LICENSE("GPL");
+enum {
+ UNDEFINED_CAPABLE = 0,
+ SYSTEM_INTEL_MSR_CAPABLE,
+ SYSTEM_IO_CAPABLE,
+};
+
+#define INTEL_MSR_RANGE (0xffff)
+#define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1)
-struct cpufreq_acpi_io {
- struct acpi_processor_performance *acpi_data;
- struct cpufreq_frequency_table *freq_table;
- unsigned int resume;
+struct acpi_cpufreq_data {
+ struct acpi_processor_performance *acpi_data;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int max_freq;
+ unsigned int resume;
+ unsigned int cpu_feature;
};
-static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
-static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
+static struct acpi_cpufreq_data *drv_data[NR_CPUS];
+static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
static struct cpufreq_driver acpi_cpufreq_driver;
static unsigned int acpi_pstate_strict;
-static int
-acpi_processor_write_port(
- u16 port,
- u8 bit_width,
- u32 value)
+static int check_est_cpu(unsigned int cpuid)
{
- if (bit_width <= 8) {
- outb(value, port);
- } else if (bit_width <= 16) {
- outw(value, port);
- } else if (bit_width <= 32) {
- outl(value, port);
- } else {
- return -ENODEV;
+ struct cpuinfo_x86 *cpu = &cpu_data[cpuid];
+
+ if (cpu->x86_vendor != X86_VENDOR_INTEL ||
+ !cpu_has(cpu, X86_FEATURE_EST))
+ return 0;
+
+ return 1;
+}
+
+static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
+{
+ struct acpi_processor_performance *perf;
+ int i;
+
+ perf = data->acpi_data;
+
+ for (i=0; i<perf->state_count; i++) {
+ if (value == perf->states[i].status)
+ return data->freq_table[i].frequency;
}
return 0;
}
-static int
-acpi_processor_read_port(
- u16 port,
- u8 bit_width,
- u32 *ret)
+static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
{
- *ret = 0;
- if (bit_width <= 8) {
- *ret = inb(port);
- } else if (bit_width <= 16) {
- *ret = inw(port);
- } else if (bit_width <= 32) {
- *ret = inl(port);
- } else {
- return -ENODEV;
+ int i;
+ struct acpi_processor_performance *perf;
+
+ msr &= INTEL_MSR_RANGE;
+ perf = data->acpi_data;
+
+ for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ if (msr == perf->states[data->freq_table[i].index].status)
+ return data->freq_table[i].frequency;
}
- return 0;
+ return data->freq_table[0].frequency;
}
-static int
-acpi_processor_set_performance (
- struct cpufreq_acpi_io *data,
- unsigned int cpu,
- int state)
+static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
{
- u16 port = 0;
- u8 bit_width = 0;
- int i = 0;
- int ret = 0;
- u32 value = 0;
- int retval;
- struct acpi_processor_performance *perf;
-
- dprintk("acpi_processor_set_performance\n");
-
- retval = 0;
- perf = data->acpi_data;
- if (state == perf->state) {
- if (unlikely(data->resume)) {
- dprintk("Called after resume, resetting to P%d\n", state);
- data->resume = 0;
- } else {
- dprintk("Already at target state (P%d)\n", state);
- return (retval);
- }
+ switch (data->cpu_feature) {
+ case SYSTEM_INTEL_MSR_CAPABLE:
+ return extract_msr(val, data);
+ case SYSTEM_IO_CAPABLE:
+ return extract_io(val, data);
+ default:
+ return 0;
}
+}
+
+struct msr_addr {
+ u32 reg;
+};
- dprintk("Transitioning from P%d to P%d\n", perf->state, state);
+struct io_addr {
+ u16 port;
+ u8 bit_width;
+};
- /*
- * First we write the target state's 'control' value to the
- * control_register.
- */
+typedef union {
+ struct msr_addr msr;
+ struct io_addr io;
+} drv_addr_union;
- port = perf->control_register.address;
- bit_width = perf->control_register.bit_width;
- value = (u32) perf->states[state].control;
+struct drv_cmd {
+ unsigned int type;
+ cpumask_t mask;
+ drv_addr_union addr;
+ u32 val;
+};
- dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
+static void do_drv_read(struct drv_cmd *cmd)
+{
+ u32 h;
+
+ switch (cmd->type) {
+ case SYSTEM_INTEL_MSR_CAPABLE:
+ rdmsr(cmd->addr.msr.reg, cmd->val, h);
+ break;
+ case SYSTEM_IO_CAPABLE:
+ acpi_os_read_port((acpi_io_address)cmd->addr.io.port,
+ &cmd->val,
+ (u32)cmd->addr.io.bit_width);
+ break;
+ default:
+ break;
+ }
+}
- ret = acpi_processor_write_port(port, bit_width, value);
- if (ret) {
- dprintk("Invalid port width 0x%04x\n", bit_width);
- return (ret);
+static void do_drv_write(struct drv_cmd *cmd)
+{
+ u32 h = 0;
+
+ switch (cmd->type) {
+ case SYSTEM_INTEL_MSR_CAPABLE:
+ wrmsr(cmd->addr.msr.reg, cmd->val, h);
+ break;
+ case SYSTEM_IO_CAPABLE:
+ acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
+ cmd->val,
+ (u32)cmd->addr.io.bit_width);
+ break;
+ default:
+ break;
}
+}
+static void drv_read(struct drv_cmd *cmd)
+{
+ cpumask_t saved_mask = current->cpus_allowed;
+ cmd->val = 0;
+
+ set_cpus_allowed(current, cmd->mask);
+ do_drv_read(cmd);
+ set_cpus_allowed(current, saved_mask);
+}
+
+static void drv_write(struct drv_cmd *cmd)
+{
+ cpumask_t saved_mask = current->cpus_allowed;
+ unsigned int i;
+
+ for_each_cpu_mask(i, cmd->mask) {
+ set_cpus_allowed(current, cpumask_of_cpu(i));
+ do_drv_write(cmd);
+ }
+
+ set_cpus_allowed(current, saved_mask);
+ return;
+}
+
+static u32 get_cur_val(cpumask_t mask)
+{
+ struct acpi_processor_performance *perf;
+ struct drv_cmd cmd;
+
+ if (unlikely(cpus_empty(mask)))
+ return 0;
+
+ switch (drv_data[first_cpu(mask)]->cpu_feature) {
+ case SYSTEM_INTEL_MSR_CAPABLE:
+ cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
+ cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
+ break;
+ case SYSTEM_IO_CAPABLE:
+ cmd.type = SYSTEM_IO_CAPABLE;
+ perf = drv_data[first_cpu(mask)]->acpi_data;
+ cmd.addr.io.port = perf->control_register.address;
+ cmd.addr.io.bit_width = perf->control_register.bit_width;
+ break;
+ default:
+ return 0;
+ }
+
+ cmd.mask = mask;
+
+ drv_read(&cmd);
+
+ dprintk("get_cur_val = %u\n", cmd.val);
+
+ return cmd.val;
+}
+
+/*
+ * Return the measured active (C0) frequency on this CPU since last call
+ * to this function.
+ * Input: cpu number
+ * Return: Average CPU frequency in terms of max frequency (zero on error)
+ *
+ * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
+ * over a period of time, while CPU is in C0 state.
+ * IA32_MPERF counts at the rate of max advertised frequency
+ * IA32_APERF counts at the rate of actual CPU frequency
+ * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
+ * no meaning should be associated with absolute values of these MSRs.
+ */
+static unsigned int get_measured_perf(unsigned int cpu)
+{
+ union {
+ struct {
+ u32 lo;
+ u32 hi;
+ } split;
+ u64 whole;
+ } aperf_cur, mperf_cur;
+
+ cpumask_t saved_mask;
+ unsigned int perf_percent;
+ unsigned int retval;
+
+ saved_mask = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ if (get_cpu() != cpu) {
+ /* We were not able to run on requested processor */
+ put_cpu();
+ return 0;
+ }
+
+ rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
+ rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
+
+ wrmsr(MSR_IA32_APERF, 0,0);
+ wrmsr(MSR_IA32_MPERF, 0,0);
+
+#ifdef __i386__
/*
- * Assume the write went through when acpi_pstate_strict is not used.
- * As read status_register is an expensive operation and there
- * are no specific error cases where an IO port write will fail.
+ * We dont want to do 64 bit divide with 32 bit kernel
+ * Get an approximate value. Return failure in case we cannot get
+ * an approximate value.
*/
- if (acpi_pstate_strict) {
- /* Then we read the 'status_register' and compare the value
- * with the target state's 'status' to make sure the
- * transition was successful.
- * Note that we'll poll for up to 1ms (100 cycles of 10us)
- * before giving up.
- */
-
- port = perf->status_register.address;
- bit_width = perf->status_register.bit_width;
-
- dprintk("Looking for 0x%08x from port 0x%04x\n",
- (u32) perf->states[state].status, port);
-
- for (i = 0; i < 100; i++) {
- ret = acpi_processor_read_port(port, bit_width, &value);
- if (ret) {
- dprintk("Invalid port width 0x%04x\n", bit_width);
- return (ret);
- }
- if (value == (u32) perf->states[state].status)
- break;
- udelay(10);
- }
- } else {
- value = (u32) perf->states[state].status;
+ if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) {
+ int shift_count;
+ u32 h;
+
+ h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi);
+ shift_count = fls(h);
+
+ aperf_cur.whole >>= shift_count;
+ mperf_cur.whole >>= shift_count;
+ }
+
+ if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) {
+ int shift_count = 7;
+ aperf_cur.split.lo >>= shift_count;
+ mperf_cur.split.lo >>= shift_count;
+ }
+
+ if (aperf_cur.split.lo && mperf_cur.split.lo)
+ perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo;
+ else
+ perf_percent = 0;
+
+#else
+ if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
+ int shift_count = 7;
+ aperf_cur.whole >>= shift_count;
+ mperf_cur.whole >>= shift_count;
}
- if (unlikely(value != (u32) perf->states[state].status)) {
- printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
- retval = -ENODEV;
- return (retval);
+ if (aperf_cur.whole && mperf_cur.whole)
+ perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole;
+ else
+ perf_percent = 0;
+
+#endif
+
+ retval = drv_data[cpu]->max_freq * perf_percent / 100;
+
+ put_cpu();
+ set_cpus_allowed(current, saved_mask);
+
+ dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
+ return retval;
+}
+
+static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
+{
+ struct acpi_cpufreq_data *data = drv_data[cpu];
+ unsigned int freq;
+
+ dprintk("get_cur_freq_on_cpu (%d)\n", cpu);
+
+ if (unlikely(data == NULL ||
+ data->acpi_data == NULL || data->freq_table == NULL)) {
+ return 0;
}
- dprintk("Transition successful after %d microseconds\n", i * 10);
+ freq = extract_freq(get_cur_val(cpumask_of_cpu(cpu)), data);
+ dprintk("cur freq = %u\n", freq);
- perf->state = state;
- return (retval);
+ return freq;
}
+static unsigned int check_freqs(cpumask_t mask, unsigned int freq,
+ struct acpi_cpufreq_data *data)
+{
+ unsigned int cur_freq;
+ unsigned int i;
+
+ for (i=0; i<100; i++) {
+ cur_freq = extract_freq(get_cur_val(mask), data);
+ if (cur_freq == freq)
+ return 1;
+ udelay(10);
+ }
+ return 0;
+}
-static int
-acpi_cpufreq_target (
- struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
+static int acpi_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
{
- struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+ struct acpi_cpufreq_data *data = drv_data[policy->cpu];
struct acpi_processor_performance *perf;
struct cpufreq_freqs freqs;
cpumask_t online_policy_cpus;
- cpumask_t saved_mask;
- cpumask_t set_mask;
- cpumask_t covered_cpus;
- unsigned int cur_state = 0;
- unsigned int next_state = 0;
- unsigned int result = 0;
- unsigned int j;
- unsigned int tmp;
+ struct drv_cmd cmd;
+ unsigned int msr;
+ unsigned int next_state = 0; /* Index into freq_table */
+ unsigned int next_perf_state = 0; /* Index into perf table */
+ unsigned int i;
+ int result = 0;
- dprintk("acpi_cpufreq_setpolicy\n");
+ dprintk("acpi_cpufreq_target %d (%d)\n", target_freq, policy->cpu);
- result = cpufreq_frequency_table_target(policy,
- data->freq_table,
- target_freq,
- relation,
- &next_state);
- if (unlikely(result))
- return (result);
+ if (unlikely(data == NULL ||
+ data->acpi_data == NULL || data->freq_table == NULL)) {
+ return -ENODEV;
+ }
perf = data->acpi_data;
- cur_state = perf->state;
- freqs.old = data->freq_table[cur_state].frequency;
- freqs.new = data->freq_table[next_state].frequency;
+ result = cpufreq_frequency_table_target(policy,
+ data->freq_table,
+ target_freq,
+ relation, &next_state);
+ if (unlikely(result))
+ return -ENODEV;
#ifdef CONFIG_HOTPLUG_CPU
/* cpufreq holds the hotplug lock, so we are safe from here on */
@@ -231,106 +400,85 @@ acpi_cpufreq_target (
online_policy_cpus = policy->cpus;
#endif
- for_each_cpu_mask(j, online_policy_cpus) {
- freqs.cpu = j;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ next_perf_state = data->freq_table[next_state].index;
+ if (perf->state == next_perf_state) {
+ if (unlikely(data->resume)) {
+ dprintk("Called after resume, resetting to P%d\n",
+ next_perf_state);
+ data->resume = 0;
+ } else {
+ dprintk("Already at target state (P%d)\n",
+ next_perf_state);
+ return 0;
+ }
}
- /*
- * We need to call driver->target() on all or any CPU in
- * policy->cpus, depending on policy->shared_type.
- */
- saved_mask = current->cpus_allowed;
- cpus_clear(covered_cpus);
- for_each_cpu_mask(j, online_policy_cpus) {
- /*
- * Support for SMP systems.
- * Make sure we are running on CPU that wants to change freq
- */
- cpus_clear(set_mask);
- if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
- cpus_or(set_mask, set_mask, online_policy_cpus);
- else
- cpu_set(j, set_mask);
-
- set_cpus_allowed(current, set_mask);
- if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
- dprintk("couldn't limit to CPUs in this domain\n");
- result = -EAGAIN;
- break;
- }
+ switch (data->cpu_feature) {
+ case SYSTEM_INTEL_MSR_CAPABLE:
+ cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
+ cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
+ msr =
+ (u32) perf->states[next_perf_state].
+ control & INTEL_MSR_RANGE;
+ cmd.val = get_cur_val(online_policy_cpus);
+ cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr;
+ break;
+ case SYSTEM_IO_CAPABLE:
+ cmd.type = SYSTEM_IO_CAPABLE;
+ cmd.addr.io.port = perf->control_register.address;
+ cmd.addr.io.bit_width = perf->control_register.bit_width;
+ cmd.val = (u32) perf->states[next_perf_state].control;
+ break;
+ default:
+ return -ENODEV;
+ }
- result = acpi_processor_set_performance (data, j, next_state);
- if (result) {
- result = -EAGAIN;
- break;
- }
+ cpus_clear(cmd.mask);
- if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
- break;
-
- cpu_set(j, covered_cpus);
- }
+ if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY)
+ cmd.mask = online_policy_cpus;
+ else
+ cpu_set(policy->cpu, cmd.mask);
- for_each_cpu_mask(j, online_policy_cpus) {
- freqs.cpu = j;
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ freqs.old = perf->states[perf->state].core_frequency * 1000;
+ freqs.new = data->freq_table[next_state].frequency;
+ for_each_cpu_mask(i, cmd.mask) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
- if (unlikely(result)) {
- /*
- * We have failed halfway through the frequency change.
- * We have sent callbacks to online_policy_cpus and
- * acpi_processor_set_performance() has been called on
- * coverd_cpus. Best effort undo..
- */
-
- if (!cpus_empty(covered_cpus)) {
- for_each_cpu_mask(j, covered_cpus) {
- policy->cpu = j;
- acpi_processor_set_performance (data,
- j,
- cur_state);
- }
- }
+ drv_write(&cmd);
- tmp = freqs.new;
- freqs.new = freqs.old;
- freqs.old = tmp;
- for_each_cpu_mask(j, online_policy_cpus) {
- freqs.cpu = j;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ if (acpi_pstate_strict) {
+ if (!check_freqs(cmd.mask, freqs.new, data)) {
+ dprintk("acpi_cpufreq_target failed (%d)\n",
+ policy->cpu);
+ return -EAGAIN;
}
}
- set_cpus_allowed(current, saved_mask);
- return (result);
-}
+ for_each_cpu_mask(i, cmd.mask) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+ perf->state = next_perf_state;
+ return result;
+}
-static int
-acpi_cpufreq_verify (
- struct cpufreq_policy *policy)
+static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
{
- unsigned int result = 0;
- struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+ struct acpi_cpufreq_data *data = drv_data[policy->cpu];
dprintk("acpi_cpufreq_verify\n");
- result = cpufreq_frequency_table_verify(policy,
- data->freq_table);
-
- return (result);
+ return cpufreq_frequency_table_verify(policy, data->freq_table);
}
-
static unsigned long
-acpi_cpufreq_guess_freq (
- struct cpufreq_acpi_io *data,
- unsigned int cpu)
+acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
{
- struct acpi_processor_performance *perf = data->acpi_data;
+ struct acpi_processor_performance *perf = data->acpi_data;
if (cpu_khz) {
/* search the closest match to cpu_khz */
@@ -338,16 +486,16 @@ acpi_cpufreq_guess_freq (
unsigned long freq;
unsigned long freqn = perf->states[0].core_frequency * 1000;
- for (i = 0; i < (perf->state_count - 1); i++) {
+ for (i=0; i<(perf->state_count-1); i++) {
freq = freqn;
freqn = perf->states[i+1].core_frequency * 1000;
if ((2 * cpu_khz) > (freqn + freq)) {
perf->state = i;
- return (freq);
+ return freq;
}
}
- perf->state = perf->state_count - 1;
- return (freqn);
+ perf->state = perf->state_count-1;
+ return freqn;
} else {
/* assume CPU is at P0... */
perf->state = 0;
@@ -355,7 +503,6 @@ acpi_cpufreq_guess_freq (
}
}
-
/*
* acpi_cpufreq_early_init - initialize ACPI P-States library
*
@@ -364,30 +511,34 @@ acpi_cpufreq_guess_freq (
* do _PDC and _PSD and find out the processor dependency for the
* actual init that will happen later...
*/
-static int acpi_cpufreq_early_init_acpi(void)
+static int acpi_cpufreq_early_init(void)
{
- struct acpi_processor_performance *data;
- unsigned int i, j;
+ struct acpi_processor_performance *data;
+ cpumask_t covered;
+ unsigned int i, j;
dprintk("acpi_cpufreq_early_init\n");
for_each_possible_cpu(i) {
- data = kzalloc(sizeof(struct acpi_processor_performance),
- GFP_KERNEL);
+ data = kzalloc(sizeof(struct acpi_processor_performance),
+ GFP_KERNEL);
if (!data) {
- for_each_possible_cpu(j) {
+ for_each_cpu_mask(j, covered) {
kfree(acpi_perf_data[j]);
acpi_perf_data[j] = NULL;
}
- return (-ENOMEM);
+ return -ENOMEM;
}
acpi_perf_data[i] = data;
+ cpu_set(i, covered);
}
/* Do initialization in ACPI core */
- return acpi_processor_preregister_performance(acpi_perf_data);
+ acpi_processor_preregister_performance(acpi_perf_data);
+ return 0;
}
+#ifdef CONFIG_SMP
/*
* Some BIOSes do SW_ANY coordination internally, either set it up in hw
* or do it in BIOS firmware and won't inform about it to OS. If not
@@ -414,39 +565,42 @@ static struct dmi_system_id sw_any_bug_dmi_table[] = {
},
{ }
};
+#endif
-static int
-acpi_cpufreq_cpu_init (
- struct cpufreq_policy *policy)
+static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
- unsigned int i;
- unsigned int cpu = policy->cpu;
- struct cpufreq_acpi_io *data;
- unsigned int result = 0;
+ unsigned int i;
+ unsigned int valid_states = 0;
+ unsigned int cpu = policy->cpu;
+ struct acpi_cpufreq_data *data;
+ unsigned int result = 0;
struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
- struct acpi_processor_performance *perf;
+ struct acpi_processor_performance *perf;
dprintk("acpi_cpufreq_cpu_init\n");
if (!acpi_perf_data[cpu])
- return (-ENODEV);
+ return -ENODEV;
- data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
+ data = kzalloc(sizeof(struct acpi_cpufreq_data), GFP_KERNEL);
if (!data)
- return (-ENOMEM);
+ return -ENOMEM;
data->acpi_data = acpi_perf_data[cpu];
- acpi_io_data[cpu] = data;
+ drv_data[cpu] = data;
- result = acpi_processor_register_performance(data->acpi_data, cpu);
+ if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))
+ acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
+ result = acpi_processor_register_performance(data->acpi_data, cpu);
if (result)
goto err_free;
perf = data->acpi_data;
policy->shared_type = perf->shared_type;
+
/*
- * Will let policy->cpus know about dependency only when software
+ * Will let policy->cpus know about dependency only when software
* coordination is required.
*/
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
@@ -462,10 +616,6 @@ acpi_cpufreq_cpu_init (
}
#endif
- if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
- acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
- }
-
/* capability check */
if (perf->state_count <= 1) {
dprintk("No P-States\n");
@@ -473,17 +623,33 @@ acpi_cpufreq_cpu_init (
goto err_unreg;
}
- if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
- (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
- dprintk("Unsupported address space [%d, %d]\n",
- (u32) (perf->control_register.space_id),
- (u32) (perf->status_register.space_id));
+ if (perf->control_register.space_id != perf->status_register.space_id) {
result = -ENODEV;
goto err_unreg;
}
- /* alloc freq_table */
- data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL);
+ switch (perf->control_register.space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ dprintk("SYSTEM IO addr space\n");
+ data->cpu_feature = SYSTEM_IO_CAPABLE;
+ break;
+ case ACPI_ADR_SPACE_FIXED_HARDWARE:
+ dprintk("HARDWARE addr space\n");
+ if (!check_est_cpu(cpu)) {
+ result = -ENODEV;
+ goto err_unreg;
+ }
+ data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
+ break;
+ default:
+ dprintk("Unknown addr space %d\n",
+ (u32) (perf->control_register.space_id));
+ result = -ENODEV;
+ goto err_unreg;
+ }
+
+ data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+ (perf->state_count+1), GFP_KERNEL);
if (!data->freq_table) {
result = -ENOMEM;
goto err_unreg;
@@ -492,129 +658,141 @@ acpi_cpufreq_cpu_init (
/* detect transition latency */
policy->cpuinfo.transition_latency = 0;
for (i=0; i<perf->state_count; i++) {
- if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
- policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
+ if ((perf->states[i].transition_latency * 1000) >
+ policy->cpuinfo.transition_latency)
+ policy->cpuinfo.transition_latency =
+ perf->states[i].transition_latency * 1000;
}
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- /* The current speed is unknown and not detectable by ACPI... */
- policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
-
+ data->max_freq = perf->states[0].core_frequency * 1000;
/* table init */
- for (i=0; i<=perf->state_count; i++)
- {
- data->freq_table[i].index = i;
- if (i<perf->state_count)
- data->freq_table[i].frequency = perf->states[i].core_frequency * 1000;
- else
- data->freq_table[i].frequency = CPUFREQ_TABLE_END;
+ for (i=0; i<perf->state_count; i++) {
+ if (i>0 && perf->states[i].core_frequency ==
+ perf->states[i-1].core_frequency)
+ continue;
+
+ data->freq_table[valid_states].index = i;
+ data->freq_table[valid_states].frequency =
+ perf->states[i].core_frequency * 1000;
+ valid_states++;
}
+ data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
+ perf->state = 0;
result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
- if (result) {
+ if (result)
goto err_freqfree;
+
+ switch (perf->control_register.space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ /* Current speed is unknown and not detectable by IO port */
+ policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
+ break;
+ case ACPI_ADR_SPACE_FIXED_HARDWARE:
+ acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
+ policy->cur = get_cur_freq_on_cpu(cpu);
+ break;
+ default:
+ break;
}
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
- printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
- cpu);
+ /* Check for APERF/MPERF support in hardware */
+ if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) {
+ unsigned int ecx;
+ ecx = cpuid_ecx(6);
+ if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY)
+ acpi_cpufreq_driver.getavg = get_measured_perf;
+ }
+
+ dprintk("CPU%u - ACPI performance management activated.\n", cpu);
for (i = 0; i < perf->state_count; i++)
dprintk(" %cP%d: %d MHz, %d mW, %d uS\n",
- (i == perf->state?'*':' '), i,
+ (i == perf->state ? '*' : ' '), i,
(u32) perf->states[i].core_frequency,
(u32) perf->states[i].power,
(u32) perf->states[i].transition_latency);
cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-
+
/*
* the first call to ->target() should result in us actually
* writing something to the appropriate registers.
*/
data->resume = 1;
-
- return (result);
- err_freqfree:
+ return result;
+
+err_freqfree:
kfree(data->freq_table);
- err_unreg:
+err_unreg:
acpi_processor_unregister_performance(perf, cpu);
- err_free:
+err_free:
kfree(data);
- acpi_io_data[cpu] = NULL;
+ drv_data[cpu] = NULL;
- return (result);
+ return result;
}
-
-static int
-acpi_cpufreq_cpu_exit (
- struct cpufreq_policy *policy)
+static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
{
- struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
+ struct acpi_cpufreq_data *data = drv_data[policy->cpu];
dprintk("acpi_cpufreq_cpu_exit\n");
if (data) {
cpufreq_frequency_table_put_attr(policy->cpu);
- acpi_io_data[policy->cpu] = NULL;
- acpi_processor_unregister_performance(data->acpi_data, policy->cpu);
+ drv_data[policy->cpu] = NULL;
+ acpi_processor_unregister_performance(data->acpi_data,
+ policy->cpu);
kfree(data);
}
- return (0);
+ return 0;
}
-static int
-acpi_cpufreq_resume (
- struct cpufreq_policy *policy)
+static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
{
- struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
+ struct acpi_cpufreq_data *data = drv_data[policy->cpu];
dprintk("acpi_cpufreq_resume\n");
data->resume = 1;
- return (0);
+ return 0;
}
-
-static struct freq_attr* acpi_cpufreq_attr[] = {
+static struct freq_attr *acpi_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
};
static struct cpufreq_driver acpi_cpufreq_driver = {
- .verify = acpi_cpufreq_verify,
- .target = acpi_cpufreq_target,
- .init = acpi_cpufreq_cpu_init,
- .exit = acpi_cpufreq_cpu_exit,
- .resume = acpi_cpufreq_resume,
- .name = "acpi-cpufreq",
- .owner = THIS_MODULE,
- .attr = acpi_cpufreq_attr,
+ .verify = acpi_cpufreq_verify,
+ .target = acpi_cpufreq_target,
+ .init = acpi_cpufreq_cpu_init,
+ .exit = acpi_cpufreq_cpu_exit,
+ .resume = acpi_cpufreq_resume,
+ .name = "acpi-cpufreq",
+ .owner = THIS_MODULE,
+ .attr = acpi_cpufreq_attr,
};
-
-static int __init
-acpi_cpufreq_init (void)
+static int __init acpi_cpufreq_init(void)
{
dprintk("acpi_cpufreq_init\n");
- acpi_cpufreq_early_init_acpi();
+ acpi_cpufreq_early_init();
return cpufreq_register_driver(&acpi_cpufreq_driver);
}
-
-static void __exit
-acpi_cpufreq_exit (void)
+static void __exit acpi_cpufreq_exit(void)
{
- unsigned int i;
+ unsigned int i;
dprintk("acpi_cpufreq_exit\n");
cpufreq_unregister_driver(&acpi_cpufreq_driver);
@@ -627,7 +805,9 @@ acpi_cpufreq_exit (void)
}
module_param(acpi_pstate_strict, uint, 0644);
-MODULE_PARM_DESC(acpi_pstate_strict, "value 0 or non-zero. non-zero -> strict ACPI checks are performed during frequency changes.");
+MODULE_PARM_DESC(acpi_pstate_strict,
+ "value 0 or non-zero. non-zero -> strict ACPI checks are "
+ "performed during frequency changes.");
late_initcall(acpi_cpufreq_init);
module_exit(acpi_cpufreq_exit);
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
index 92afa3bc84f..6667e9cceb9 100644
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -447,7 +447,6 @@ static int __init cpufreq_gx_init(void)
int ret;
struct gxfreq_params *params;
struct pci_dev *gx_pci;
- u32 class_rev;
/* Test if we have the right hardware */
if ((gx_pci = gx_detect_chipset()) == NULL)
@@ -472,8 +471,7 @@ static int __init cpufreq_gx_init(void)
pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
- pci_read_config_dword(params->cs55x0, PCI_CLASS_REVISION, &class_rev);
- params->pci_rev = class_rev && 0xff;
+ pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, &params->pci_rev);
if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
kfree(params);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 7233abe5d69..e940e00b96c 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -52,6 +52,10 @@
#define CPU_EZRA_T 4
#define CPU_NEHEMIAH 5
+/* Flags */
+#define USE_ACPI_C3 (1 << 1)
+#define USE_NORTHBRIDGE (1 << 2)
+
static int cpu_model;
static unsigned int numscales=16;
static unsigned int fsb;
@@ -68,7 +72,7 @@ static unsigned int minmult, maxmult;
static int can_scale_voltage;
static struct acpi_processor *pr = NULL;
static struct acpi_processor_cx *cx = NULL;
-static int port22_en;
+static u8 longhaul_flags;
/* Module parameters */
static int scale_voltage;
@@ -80,7 +84,6 @@ static int ignore_latency;
/* Clock ratios multiplied by 10 */
static int clock_ratio[32];
static int eblcr_table[32];
-static unsigned int highest_speed, lowest_speed; /* kHz */
static int longhaul_version;
static struct cpufreq_frequency_table *longhaul_table;
@@ -178,7 +181,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
safe_halt();
/* Change frequency on next halt or sleep */
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
- if (port22_en) {
+ if (!cx_address) {
ACPI_FLUSH_CPU_CACHE();
/* Invoke C1 */
halt();
@@ -189,7 +192,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
/* Dummy op - must do something useless after P_LVL3 read */
t = inl(acpi_fadt.xpm_tmr_blk.address);
}
-
/* Disable bus ratio bit */
local_irq_disable();
longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
@@ -243,15 +245,14 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
outb(0xFF,0xA1); /* Overkill */
outb(0xFE,0x21); /* TMR0 only */
- if (pr->flags.bm_control) {
+ if (longhaul_flags & USE_NORTHBRIDGE) {
+ /* Disable AGP and PCI arbiters */
+ outb(3, 0x22);
+ } else if ((pr != NULL) && pr->flags.bm_control) {
/* Disable bus master arbitration */
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
ACPI_MTX_DO_NOT_LOCK);
- } else if (port22_en) {
- /* Disable AGP and PCI arbiters */
- outb(3, 0x22);
}
-
switch (longhaul_version) {
/*
@@ -278,22 +279,25 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
* to work in practice.
*/
case TYPE_POWERSAVER:
- /* Don't allow wakeup */
- acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
- ACPI_MTX_DO_NOT_LOCK);
- do_powersaver(cx->address, clock_ratio_index);
+ if (longhaul_flags & USE_ACPI_C3) {
+ /* Don't allow wakeup */
+ acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
+ ACPI_MTX_DO_NOT_LOCK);
+ do_powersaver(cx->address, clock_ratio_index);
+ } else {
+ do_powersaver(0, clock_ratio_index);
+ }
break;
}
- if (pr->flags.bm_control) {
+ if (longhaul_flags & USE_NORTHBRIDGE) {
+ /* Enable arbiters */
+ outb(0, 0x22);
+ } else if ((pr != NULL) && pr->flags.bm_control) {
/* Enable bus master arbitration */
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
ACPI_MTX_DO_NOT_LOCK);
- } else if (port22_en) {
- /* Enable arbiters */
- outb(0, 0x22);
}
-
outb(pic2_mask,0xA1); /* restore mask */
outb(pic1_mask,0x21);
@@ -314,12 +318,12 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
#define ROUNDING 0xf
-static int _guess(int guess)
+static int _guess(int guess, int mult)
{
int target;
- target = ((maxmult/10)*guess);
- if (maxmult%10 != 0)
+ target = ((mult/10)*guess);
+ if (mult%10 != 0)
target += (guess/2);
target += ROUNDING/2;
target &= ~ROUNDING;
@@ -327,17 +331,17 @@ static int _guess(int guess)
}
-static int guess_fsb(void)
+static int guess_fsb(int mult)
{
int speed = (cpu_khz/1000);
int i;
- int speeds[3] = { 66, 100, 133 };
+ int speeds[] = { 66, 100, 133, 200 };
speed += ROUNDING/2;
speed &= ~ROUNDING;
- for (i=0; i<3; i++) {
- if (_guess(speeds[i]) == speed)
+ for (i=0; i<4; i++) {
+ if (_guess(speeds[i], mult) == speed)
return speeds[i];
}
return 0;
@@ -354,9 +358,7 @@ static int __init longhaul_get_ranges(void)
130, 150, 160, 140, -1, 155, -1, 145 };
unsigned int j, k = 0;
union msr_longhaul longhaul;
- unsigned long lo, hi;
- unsigned int eblcr_fsb_table_v1[] = { 66, 133, 100, -1 };
- unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
+ int mult = 0;
switch (longhaul_version) {
case TYPE_LONGHAUL_V1:
@@ -364,30 +366,18 @@ static int __init longhaul_get_ranges(void)
/* Ugh, Longhaul v1 didn't have the min/max MSRs.
Assume min=3.0x & max = whatever we booted at. */
minmult = 30;
- maxmult = longhaul_get_cpu_mult();
- rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
- invalue = (lo & (1<<18|1<<19)) >>18;
- if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2)
- fsb = eblcr_fsb_table_v1[invalue];
- else
- fsb = guess_fsb();
+ maxmult = mult = longhaul_get_cpu_mult();
break;
case TYPE_POWERSAVER:
/* Ezra-T */
if (cpu_model==CPU_EZRA_T) {
+ minmult = 30;
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
invalue = longhaul.bits.MaxMHzBR;
if (longhaul.bits.MaxMHzBR4)
invalue += 16;
- maxmult=ezra_t_multipliers[invalue];
-
- invalue = longhaul.bits.MinMHzBR;
- if (longhaul.bits.MinMHzBR4 == 1)
- minmult = 30;
- else
- minmult = ezra_t_multipliers[invalue];
- fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
+ maxmult = mult = ezra_t_multipliers[invalue];
break;
}
@@ -407,21 +397,16 @@ static int __init longhaul_get_ranges(void)
* But it works, so we don't grumble.
*/
minmult=40;
- maxmult=longhaul_get_cpu_mult();
-
- /* Starting with the 1.2GHz parts, theres a 200MHz bus. */
- if ((cpu_khz/1000) > 1200)
- fsb = 200;
- else
- fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
+ maxmult = mult = longhaul_get_cpu_mult();
break;
}
}
+ fsb = guess_fsb(mult);
dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
minmult/10, minmult%10, maxmult/10, maxmult%10);
- if (fsb == -1) {
+ if (fsb == 0) {
printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
return -EINVAL;
}
@@ -583,6 +568,10 @@ static int enable_arbiter_disable(void)
if (dev == NULL) {
reg = 0x76;
dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_862X_0, NULL);
+ /* Find CN400 V-Link host bridge */
+ if (dev == NULL)
+ dev = pci_find_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
+
}
if (dev != NULL) {
/* Enable access to port 0x22 */
@@ -687,27 +676,32 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
/* Find ACPI data for processor */
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
&longhaul_walk_callback, NULL, (void *)&pr);
- if (pr == NULL)
- goto err_acpi;
- if (longhaul_version == TYPE_POWERSAVER) {
- /* Check ACPI support for C3 state */
+ /* Check ACPI support for C3 state */
+ if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) {
cx = &pr->power.states[ACPI_STATE_C3];
if (cx->address > 0 &&
(cx->latency <= 1000 || ignore_latency != 0) ) {
+ longhaul_flags |= USE_ACPI_C3;
goto print_support_type;
}
}
+ /* Check if northbridge is friendly */
+ if (enable_arbiter_disable()) {
+ longhaul_flags |= USE_NORTHBRIDGE;
+ goto print_support_type;
+ }
+
+ /* No ACPI C3 or we can't use it */
/* Check ACPI support for bus master arbiter disable */
- if (!pr->flags.bm_control) {
- if (enable_arbiter_disable()) {
- port22_en = 1;
- } else {
- goto err_acpi;
- }
+ if ((pr == NULL) || !(pr->flags.bm_control)) {
+ printk(KERN_ERR PFX
+ "No ACPI support. Unsupported northbridge.\n");
+ return -ENODEV;
}
+
print_support_type:
- if (!port22_en) {
+ if (!(longhaul_flags & USE_NORTHBRIDGE)) {
printk (KERN_INFO PFX "Using ACPI support.\n");
} else {
printk (KERN_INFO PFX "Using northbridge support.\n");
@@ -732,10 +726,6 @@ print_support_type:
cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
return 0;
-
-err_acpi:
- printk(KERN_ERR PFX "No ACPI support. No VT8601 or VT8623 northbridge. Aborting.\n");
- return -ENODEV;
}
static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
@@ -770,8 +760,8 @@ static int __init longhaul_init(void)
#ifdef CONFIG_SMP
if (num_online_cpus() > 1) {
- return -ENODEV;
printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n");
+ return -ENODEV;
}
#endif
#ifdef CONFIG_X86_IO_APIC
@@ -783,8 +773,10 @@ static int __init longhaul_init(void)
switch (c->x86_model) {
case 6 ... 9:
return cpufreq_register_driver(&longhaul_driver);
+ case 10:
+ printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n");
default:
- printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n");
+ ;;
}
return -ENODEV;
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index 304d2eaa4a1..4786fedca6e 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -51,7 +51,6 @@ enum {
static int has_N44_O17_errata[NR_CPUS];
-static int has_N60_errata[NR_CPUS];
static unsigned int stock_freq;
static struct cpufreq_driver p4clockmod_driver;
static unsigned int cpufreq_p4_get(unsigned int cpu);
@@ -163,29 +162,27 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy)
static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
{
- if ((c->x86 == 0x06) && (c->x86_model == 0x09)) {
- /* Pentium M (Banias) */
- printk(KERN_WARNING PFX "Warning: Pentium M detected. "
- "The speedstep_centrino module offers voltage scaling"
- " in addition of frequency scaling. You should use "
- "that instead of p4-clockmod, if possible.\n");
- return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
- }
-
- if ((c->x86 == 0x06) && (c->x86_model == 0x0D)) {
- /* Pentium M (Dothan) */
- printk(KERN_WARNING PFX "Warning: Pentium M detected. "
- "The speedstep_centrino module offers voltage scaling"
- " in addition of frequency scaling. You should use "
- "that instead of p4-clockmod, if possible.\n");
- /* on P-4s, the TSC runs with constant frequency independent whether
- * throttling is active or not. */
- p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
- return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
+ if (c->x86 == 0x06) {
+ if (cpu_has(c, X86_FEATURE_EST))
+ printk(KERN_WARNING PFX "Warning: EST-capable CPU detected. "
+ "The acpi-cpufreq module offers voltage scaling"
+ " in addition of frequency scaling. You should use "
+ "that instead of p4-clockmod, if possible.\n");
+ switch (c->x86_model) {
+ case 0x0E: /* Core */
+ case 0x0F: /* Core Duo */
+ p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
+ return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
+ case 0x0D: /* Pentium M (Dothan) */
+ p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
+ /* fall through */
+ case 0x09: /* Pentium M (Banias) */
+ return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
+ }
}
if (c->x86 != 0xF) {
- printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <linux@brodo.de>\n");
+ printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <cpufreq@lists.linux.org.uk>\n");
return 0;
}
@@ -226,12 +223,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
case 0x0f12:
has_N44_O17_errata[policy->cpu] = 1;
dprintk("has errata -- disabling low frequencies\n");
- break;
-
- case 0x0f29:
- has_N60_errata[policy->cpu] = 1;
- dprintk("has errata -- disabling frequencies lower than 2ghz\n");
- break;
}
/* get max frequency */
@@ -243,8 +234,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
if ((i<2) && (has_N44_O17_errata[policy->cpu]))
p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
- else if (has_N60_errata[policy->cpu] && ((stock_freq * i)/8) < 2000000)
- p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
else
p4clockmod_table[i].frequency = (stock_freq * i)/8;
}
diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
index ef457d50f4a..b8fb4b521c6 100644
--- a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
+++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
@@ -153,6 +153,7 @@ static struct cpufreq_driver sc520_freq_driver = {
static int __init sc520_freq_init(void)
{
struct cpuinfo_x86 *c = cpu_data;
+ int err;
/* Test if we have the right hardware */
if(c->x86_vendor != X86_VENDOR_AMD ||
@@ -166,7 +167,11 @@ static int __init sc520_freq_init(void)
return -ENOMEM;
}
- return cpufreq_register_driver(&sc520_freq_driver);
+ err = cpufreq_register_driver(&sc520_freq_driver);
+ if (err)
+ iounmap(cpuctl);
+
+ return err;
}
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index e8993baf3d1..f43b987f952 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -36,6 +36,7 @@
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
+#define INTEL_MSR_RANGE (0xffff)
struct cpu_id
{
@@ -379,6 +380,7 @@ static int centrino_cpu_early_init_acpi(void)
}
+#ifdef CONFIG_SMP
/*
* Some BIOSes do SW_ANY coordination internally, either set it up in hw
* or do it in BIOS firmware and won't inform about it to OS. If not
@@ -392,7 +394,6 @@ static int sw_any_bug_found(struct dmi_system_id *d)
return 0;
}
-
static struct dmi_system_id sw_any_bug_dmi_table[] = {
{
.callback = sw_any_bug_found,
@@ -405,7 +406,7 @@ static struct dmi_system_id sw_any_bug_dmi_table[] = {
},
{ }
};
-
+#endif
/*
* centrino_cpu_init_acpi - register with ACPI P-States library
@@ -463,8 +464,9 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
}
for (i=0; i<p->state_count; i++) {
- if (p->states[i].control != p->states[i].status) {
- dprintk("Different control (%llu) and status values (%llu)\n",
+ if ((p->states[i].control & INTEL_MSR_RANGE) !=
+ (p->states[i].status & INTEL_MSR_RANGE)) {
+ dprintk("Different MSR bits in control (%llu) and status (%llu)\n",
p->states[i].control, p->states[i].status);
result = -EINVAL;
goto err_unreg;
@@ -500,7 +502,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
}
for (i=0; i<p->state_count; i++) {
- centrino_model[cpu]->op_points[i].index = p->states[i].control;
+ centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE;
centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
dprintk("adding state %i with frequency %u and control value %04x\n",
i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
@@ -531,6 +533,9 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
+ printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI "
+ "config is deprecated.\n "
+ "Use X86_ACPI_CPUFREQ (acpi-cpufreq) instead.\n" );
return 0;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index 4f46cac155c..d59277c0091 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -123,6 +123,36 @@ static unsigned int pentiumM_get_frequency(void)
return (msr_tmp * 100 * 1000);
}
+static unsigned int pentium_core_get_frequency(void)
+{
+ u32 fsb = 0;
+ u32 msr_lo, msr_tmp;
+
+ rdmsr(MSR_FSB_FREQ, msr_lo, msr_tmp);
+ /* see table B-2 of 25366920.pdf */
+ switch (msr_lo & 0x07) {
+ case 5:
+ fsb = 100000;
+ break;
+ case 1:
+ fsb = 133333;
+ break;
+ case 3:
+ fsb = 166667;
+ break;
+ default:
+ printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
+ }
+
+ rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
+ dprintk("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
+
+ msr_tmp = (msr_lo >> 22) & 0x1f;
+ dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * fsb));
+
+ return (msr_tmp * fsb);
+}
+
static unsigned int pentium4_get_frequency(void)
{
@@ -174,6 +204,8 @@ static unsigned int pentium4_get_frequency(void)
unsigned int speedstep_get_processor_frequency(unsigned int processor)
{
switch (processor) {
+ case SPEEDSTEP_PROCESSOR_PCORE:
+ return pentium_core_get_frequency();
case SPEEDSTEP_PROCESSOR_PM:
return pentiumM_get_frequency();
case SPEEDSTEP_PROCESSOR_P4D:
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
index b735429c50b..b11bcc608ca 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
@@ -22,6 +22,7 @@
* the speedstep_get_processor_frequency() call. */
#define SPEEDSTEP_PROCESSOR_PM 0xFFFFFF03 /* Pentium M */
#define SPEEDSTEP_PROCESSOR_P4D 0xFFFFFF04 /* desktop P4 */
+#define SPEEDSTEP_PROCESSOR_PCORE 0xFFFFFF05 /* Core */
/* speedstep states -- only two of them */
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index c28333d5364..ff0d8980611 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -360,9 +360,6 @@ static int __init speedstep_init(void)
case SPEEDSTEP_PROCESSOR_PIII_C:
case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
break;
- case SPEEDSTEP_PROCESSOR_P4M:
- printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n");
- break;
default:
speedstep_processor = 0;
}
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index db6dd20c358..51130b39cd2 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -116,7 +116,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
char __user *tmp = buf;
u32 data[4];
u32 reg = *ppos;
- int cpu = iminor(file->f_dentry->d_inode);
+ int cpu = iminor(file->f_path.dentry->d_inode);
if (count % 16)
return -EINVAL; /* Invalid chunk size */
@@ -134,7 +134,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
static int cpuid_open(struct inode *inode, struct file *file)
{
- unsigned int cpu = iminor(file->f_dentry->d_inode);
+ unsigned int cpu = iminor(file->f_path.dentry->d_inode);
struct cpuinfo_x86 *c = &(cpu_data)[cpu];
if (cpu >= NR_CPUS || !cpu_online(cpu))
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c
index 2f7d0a92fd7..f391abcf7da 100644
--- a/arch/i386/kernel/e820.c
+++ b/arch/i386/kernel/e820.c
@@ -668,7 +668,7 @@ void __init register_bootmem_low_pages(unsigned long max_low_pfn)
}
}
-void __init register_memory(void)
+void __init e820_register_memory(void)
{
unsigned long gapstart, gapsize, round;
unsigned long long last;
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index b92c7f0a358..8f9c624ace6 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -473,6 +473,70 @@ static inline void __init check_range_for_systab(efi_memory_desc_t *md)
}
/*
+ * Wrap all the virtual calls in a way that forces the parameters on the stack.
+ */
+
+#define efi_call_virt(f, args...) \
+ ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
+
+static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+ return efi_call_virt(get_time, tm, tc);
+}
+
+static efi_status_t virt_efi_set_time (efi_time_t *tm)
+{
+ return efi_call_virt(set_time, tm);
+}
+
+static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled,
+ efi_bool_t *pending,
+ efi_time_t *tm)
+{
+ return efi_call_virt(get_wakeup_time, enabled, pending, tm);
+}
+
+static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled,
+ efi_time_t *tm)
+{
+ return efi_call_virt(set_wakeup_time, enabled, tm);
+}
+
+static efi_status_t virt_efi_get_variable (efi_char16_t *name,
+ efi_guid_t *vendor, u32 *attr,
+ unsigned long *data_size, void *data)
+{
+ return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_variable (unsigned long *name_size,
+ efi_char16_t *name,
+ efi_guid_t *vendor)
+{
+ return efi_call_virt(get_next_variable, name_size, name, vendor);
+}
+
+static efi_status_t virt_efi_set_variable (efi_char16_t *name,
+ efi_guid_t *vendor,
+ unsigned long attr,
+ unsigned long data_size, void *data)
+{
+ return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_high_mono_count (u32 *count)
+{
+ return efi_call_virt(get_next_high_mono_count, count);
+}
+
+static void virt_efi_reset_system (int reset_type, efi_status_t status,
+ unsigned long data_size,
+ efi_char16_t *data)
+{
+ efi_call_virt(reset_system, reset_type, status, data_size, data);
+}
+
+/*
* This function will switch the EFI runtime services to virtual mode.
* Essentially, look through the EFI memmap and map every region that
* has the runtime attribute bit set in its memory descriptor and update
@@ -525,22 +589,15 @@ void __init efi_enter_virtual_mode(void)
* pointers in the runtime service table to the new virtual addresses.
*/
- efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time;
- efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time;
- efi.get_wakeup_time = (efi_get_wakeup_time_t *)
- efi.systab->runtime->get_wakeup_time;
- efi.set_wakeup_time = (efi_set_wakeup_time_t *)
- efi.systab->runtime->set_wakeup_time;
- efi.get_variable = (efi_get_variable_t *)
- efi.systab->runtime->get_variable;
- efi.get_next_variable = (efi_get_next_variable_t *)
- efi.systab->runtime->get_next_variable;
- efi.set_variable = (efi_set_variable_t *)
- efi.systab->runtime->set_variable;
- efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *)
- efi.systab->runtime->get_next_high_mono_count;
- efi.reset_system = (efi_reset_system_t *)
- efi.systab->runtime->reset_system;
+ efi.get_time = virt_efi_get_time;
+ efi.set_time = virt_efi_set_time;
+ efi.get_wakeup_time = virt_efi_get_wakeup_time;
+ efi.set_wakeup_time = virt_efi_set_wakeup_time;
+ efi.get_variable = virt_efi_get_variable;
+ efi.get_next_variable = virt_efi_get_next_variable;
+ efi.set_variable = virt_efi_set_variable;
+ efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
+ efi.reset_system = virt_efi_reset_system;
}
void __init
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index de34b7fed3c..5e47683fc63 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -302,12 +302,16 @@ sysenter_past_esp:
pushl $(__USER_CS)
CFI_ADJUST_CFA_OFFSET 4
/*CFI_REL_OFFSET cs, 0*/
+#ifndef CONFIG_COMPAT_VDSO
/*
* Push current_thread_info()->sysenter_return to the stack.
* A tiny bit of offset fixup is necessary - 4*4 means the 4 words
* pushed above; +8 corresponds to copy_thread's esp0 setting.
*/
pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
+#else
+ pushl $SYSENTER_RETURN
+#endif
CFI_ADJUST_CFA_OFFSET 4
CFI_REL_OFFSET eip, 0
@@ -979,38 +983,6 @@ ENTRY(spurious_interrupt_bug)
jmp error_code
CFI_ENDPROC
-#ifdef CONFIG_STACK_UNWIND
-ENTRY(arch_unwind_init_running)
- CFI_STARTPROC
- movl 4(%esp), %edx
- movl (%esp), %ecx
- leal 4(%esp), %eax
- movl %ebx, PT_EBX(%edx)
- xorl %ebx, %ebx
- movl %ebx, PT_ECX(%edx)
- movl %ebx, PT_EDX(%edx)
- movl %esi, PT_ESI(%edx)
- movl %edi, PT_EDI(%edx)
- movl %ebp, PT_EBP(%edx)
- movl %ebx, PT_EAX(%edx)
- movl $__USER_DS, PT_DS(%edx)
- movl $__USER_DS, PT_ES(%edx)
- movl $0, PT_GS(%edx)
- movl %ebx, PT_ORIG_EAX(%edx)
- movl %ecx, PT_EIP(%edx)
- movl 12(%esp), %ecx
- movl $__KERNEL_CS, PT_CS(%edx)
- movl %ebx, PT_EFLAGS(%edx)
- movl %eax, PT_OLDESP(%edx)
- movl 8(%esp), %eax
- movl %ecx, 8(%esp)
- movl PT_EBX(%edx), %ebx
- movl $__KERNEL_DS, PT_OLDSS(%edx)
- jmpl *%eax
- CFI_ENDPROC
-ENDPROC(arch_unwind_init_running)
-#endif
-
ENTRY(kernel_thread_helper)
pushl $0 # fake return address for unwinder
CFI_STARTPROC
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index e21dcde0790..6a3875f81a0 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1227,26 +1227,32 @@ static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }
static int __assign_irq_vector(int irq)
{
- static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
- int vector;
+ static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+ int vector, offset, i;
BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
if (irq_vector[irq] > 0)
return irq_vector[irq];
- current_vector += 8;
- if (current_vector == SYSCALL_VECTOR)
- current_vector += 8;
-
- if (current_vector >= FIRST_SYSTEM_VECTOR) {
- offset++;
- if (!(offset % 8))
- return -ENOSPC;
- current_vector = FIRST_DEVICE_VECTOR + offset;
- }
-
vector = current_vector;
+ offset = current_offset;
+next:
+ vector += 8;
+ if (vector >= FIRST_SYSTEM_VECTOR) {
+ offset = (offset + 1) % 8;
+ vector = FIRST_DEVICE_VECTOR + offset;
+ }
+ if (vector == current_vector)
+ return -ENOSPC;
+ if (vector == SYSCALL_VECTOR)
+ goto next;
+ for (i = 0; i < NR_IRQ_VECTORS; i++)
+ if (irq_vector[i] == vector)
+ goto next;
+
+ current_vector = vector;
+ current_offset = offset;
irq_vector[irq] = vector;
return vector;
@@ -2485,7 +2491,7 @@ device_initcall(ioapic_init_sysfs);
int create_irq(void)
{
/* Allocate an unused irq */
- int irq, new, vector;
+ int irq, new, vector = 0;
unsigned long flags;
irq = -ENOSPC;
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 972346604f9..c8fa13721bc 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -1,7 +1,7 @@
/*
* Intel CPU Microcode Update Driver for Linux
*
- * Copyright (C) 2000-2004 Tigran Aivazian
+ * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
* 2006 Shaohua Li <shaohua.li@intel.com>
*
* This driver allows to upgrade microcode on Intel processors
@@ -92,7 +92,7 @@
#include <asm/processor.h>
MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
-MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
MODULE_LICENSE("GPL");
#define MICROCODE_VERSION "1.14a"
@@ -722,7 +722,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
return NOTIFY_OK;
}
-static struct notifier_block mc_cpu_notifier = {
+static struct notifier_block __cpuinitdata mc_cpu_notifier = {
.notifier_call = mc_cpu_callback,
};
@@ -752,7 +752,7 @@ static int __init microcode_init (void)
register_hotcpu_notifier(&mc_cpu_notifier);
printk(KERN_INFO
- "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
+ "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
return 0;
}
diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c
index d7d9c8b23f7..3db0a5442eb 100644
--- a/arch/i386/kernel/module.c
+++ b/arch/i386/kernel/module.c
@@ -21,6 +21,7 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/bug.h>
#if 0
#define DEBUGP printk
@@ -141,10 +142,11 @@ int module_finalize(const Elf_Ehdr *hdr,
apply_paravirt(pseg, pseg + para->sh_size);
}
- return 0;
+ return module_bug_finalize(hdr, sechdrs, me);
}
void module_arch_cleanup(struct module *mod)
{
alternatives_smp_module_del(mod);
+ module_bug_cleanup(mod);
}
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 2ce67228dff..49bff3596bf 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -36,7 +36,7 @@
/* Have we found an MP table */
int smp_found_config;
-unsigned int __initdata maxcpus = NR_CPUS;
+unsigned int __cpuinitdata maxcpus = NR_CPUS;
/*
* Various Linux-internal data structures created from the
@@ -102,9 +102,9 @@ static int __init mpf_checksum(unsigned char *mp, int len)
*/
static int mpc_record;
-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
+static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
-static void __devinit MP_processor_info (struct mpc_config_processor *m)
+static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
physid_mask_t phys_cpu;
@@ -822,7 +822,7 @@ void __init mp_register_lapic_address(u64 address)
Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
}
-void __devinit mp_register_lapic (u8 id, u8 enabled)
+void __cpuinit mp_register_lapic (u8 id, u8 enabled)
{
struct mpc_config_processor processor;
int boot_cpu = 0;
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 1d1a56cae34..4a472a17d1c 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -172,7 +172,7 @@ static ssize_t msr_read(struct file *file, char __user * buf,
u32 __user *tmp = (u32 __user *) buf;
u32 data[2];
u32 reg = *ppos;
- int cpu = iminor(file->f_dentry->d_inode);
+ int cpu = iminor(file->f_path.dentry->d_inode);
int err;
if (count % 8)
@@ -196,7 +196,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
const u32 __user *tmp = (const u32 __user *)buf;
u32 data[2];
u32 reg = *ppos;
- int cpu = iminor(file->f_dentry->d_inode);
+ int cpu = iminor(file->f_path.dentry->d_inode);
int err;
if (count % 8)
@@ -216,7 +216,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
static int msr_open(struct inode *inode, struct file *file)
{
- unsigned int cpu = iminor(file->f_dentry->d_inode);
+ unsigned int cpu = iminor(file->f_path.dentry->d_inode);
struct cpuinfo_x86 *c = &(cpu_data)[cpu];
if (cpu >= NR_CPUS || !cpu_online(cpu))
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index f5bc7e1be80..1a6f8bb8881 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -195,6 +195,8 @@ static __cpuinit inline int nmi_known_cpu(void)
return 0;
}
+static int endflag __initdata = 0;
+
#ifdef CONFIG_SMP
/* The performance counters used by NMI_LOCAL_APIC don't trigger when
* the CPU is idle. To make sure the NMI watchdog really ticks on all
@@ -202,7 +204,6 @@ static __cpuinit inline int nmi_known_cpu(void)
*/
static __init void nmi_cpu_busy(void *data)
{
- volatile int *endflag = data;
local_irq_enable_in_hardirq();
/* Intentionally don't use cpu_relax here. This is
to make sure that the performance counter really ticks,
@@ -210,14 +211,13 @@ static __init void nmi_cpu_busy(void *data)
pause instruction. On a real HT machine this is fine because
all other CPUs are busy with "useless" delay loops and don't
care if they get somewhat less cycles. */
- while (*endflag == 0)
- barrier();
+ while (endflag == 0)
+ mb();
}
#endif
static int __init check_nmi_watchdog(void)
{
- volatile int endflag = 0;
unsigned int *prev_nmi_count;
int cpu;
@@ -310,13 +310,7 @@ static int __init setup_nmi_watchdog(char *str)
if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
return 0;
- /*
- * If any other x86 CPU has a local APIC, then
- * please test the NMI stuff there and send me the
- * missing bits. Right now Intel P6/P4 and AMD K7 only.
- */
- if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
- return 0; /* no lapic support */
+
nmi_watchdog = nmi;
return 1;
}
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
index 3dceab5828f..e55fd05da0f 100644
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -566,4 +566,11 @@ struct paravirt_ops paravirt_ops = {
.irq_enable_sysexit = native_irq_enable_sysexit,
.iret = native_iret,
};
-EXPORT_SYMBOL(paravirt_ops);
+
+/*
+ * NOTE: CONFIG_PARAVIRT is experimental and the paravirt_ops
+ * semantics are subject to change. Hence we only do this
+ * internal-only export of this, until it gets sorted out and
+ * all lowlevel CPU ops used by modules are separately exported.
+ */
+EXPORT_SYMBOL_GPL(paravirt_ops);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 99308510a17..c641056233a 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -102,7 +102,12 @@ void default_idle(void)
{
if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
current_thread_info()->status &= ~TS_POLLING;
- smp_mb__after_clear_bit();
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
+
local_irq_disable();
if (!need_resched())
safe_halt(); /* enables interrupts racelessly */
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index f3f94ac5736..af8aabe8580 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -45,7 +45,7 @@
/*
* Offset of eflags on child stack..
*/
-#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
+#define EFL_OFFSET offsetof(struct pt_regs, eflags)
static inline struct pt_regs *get_child_regs(struct task_struct *task)
{
@@ -54,24 +54,24 @@ static inline struct pt_regs *get_child_regs(struct task_struct *task)
}
/*
- * this routine will get a word off of the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
- * this routine assumes that all the privileged stacks are in our
+ * This routine will get a word off of the processes privileged stack.
+ * the offset is bytes into the pt_regs structure on the stack.
+ * This routine assumes that all the privileged stacks are in our
* data space.
*/
static inline int get_stack_long(struct task_struct *task, int offset)
{
unsigned char *stack;
- stack = (unsigned char *)task->thread.esp0;
+ stack = (unsigned char *)task->thread.esp0 - sizeof(struct pt_regs);
stack += offset;
return (*((int *)stack));
}
/*
- * this routine will put a word on the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
- * this routine assumes that all the privileged stacks are in our
+ * This routine will put a word on the processes privileged stack.
+ * the offset is bytes into the pt_regs structure on the stack.
+ * This routine assumes that all the privileged stacks are in our
* data space.
*/
static inline int put_stack_long(struct task_struct *task, int offset,
@@ -79,7 +79,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
{
unsigned char * stack;
- stack = (unsigned char *) task->thread.esp0;
+ stack = (unsigned char *)task->thread.esp0 - sizeof(struct pt_regs);
stack += offset;
*(unsigned long *) stack = data;
return 0;
@@ -114,7 +114,7 @@ static int putreg(struct task_struct *child,
}
if (regno > ES*4)
regno -= 1*4;
- put_stack_long(child, regno - sizeof(struct pt_regs), value);
+ put_stack_long(child, regno, value);
return 0;
}
@@ -137,7 +137,6 @@ static unsigned long getreg(struct task_struct *child,
default:
if (regno > ES*4)
regno -= 1*4;
- regno = regno - sizeof(struct pt_regs);
retval &= get_stack_long(child, regno);
}
return retval;
diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
index a01320a7b63..34874c398b4 100644
--- a/arch/i386/kernel/quirks.c
+++ b/arch/i386/kernel/quirks.c
@@ -10,13 +10,38 @@
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
{
+ u8 config, rev;
+ u32 word;
+
+ /* BIOS may enable hardware IRQ balancing for
+ * E7520/E7320/E7525(revision ID 0x9 and below)
+ * based platforms.
+ * For those platforms, make sure that the genapic is set to 'flat'
+ */
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+ if (rev > 0x9)
+ return;
+
+ /* enable access to config space*/
+ pci_read_config_byte(dev, 0xf4, &config);
+ pci_write_config_byte(dev, 0xf4, config|0x2);
+
+ /* read xTPR register */
+ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+
+ if (!(word & (1 << 13))) {
#ifdef CONFIG_X86_64
- if (genapic != &apic_flat)
- panic("APIC mode must be flat on this system\n");
+ if (genapic != &apic_flat)
+ panic("APIC mode must be flat on this system\n");
#elif defined(CONFIG_X86_GENERICARCH)
- if (genapic != &apic_default)
- panic("APIC mode must be default(flat) on this system. Use apic=default\n");
+ if (genapic != &apic_default)
+ panic("APIC mode must be default(flat) on this system. Use apic=default\n");
#endif
+ }
+
+ /* put back the original value for config space*/
+ if (!(config & 0x2))
+ pci_write_config_byte(dev, 0xf4, config);
}
void __init quirk_intel_irqbalance(void)
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 79df6e612db..4b31ad70c1a 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -77,7 +77,7 @@ extern struct resource code_resource;
extern struct resource data_resource;
/* cpu data as detected by the assembly code in head.S */
-struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
/* common cpu data for all cpus */
struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
EXPORT_SYMBOL(boot_cpu_data);
@@ -495,7 +495,7 @@ static void set_mca_bus(int x) { }
#endif
/* Overridden in paravirt.c if CONFIG_PARAVIRT */
-char * __attribute__((weak)) memory_setup(void)
+char * __init __attribute__((weak)) memory_setup(void)
{
return machine_specific_memory_setup();
}
@@ -639,7 +639,7 @@ void __init setup_arch(char **cmdline_p)
get_smp_config();
#endif
- register_memory();
+ e820_register_memory();
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 4bf0e3c83b8..8c6c8c52b95 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -69,9 +69,7 @@ static int __devinitdata smp_b_stepping;
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
-#ifdef CONFIG_X86_HT
EXPORT_SYMBOL(smp_num_siblings);
-#endif
/* Last level cache ID of each logical CPU */
int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
@@ -161,7 +159,7 @@ void __init smp_alloc_memory(void)
* a given CPU
*/
-static void __devinit smp_store_cpu_info(int id)
+static void __cpuinit smp_store_cpu_info(int id)
{
struct cpuinfo_x86 *c = cpu_data + id;
@@ -229,7 +227,7 @@ static struct {
atomic_t count_start;
atomic_t count_stop;
unsigned long long values[NR_CPUS];
-} tsc __initdata = {
+} tsc __cpuinitdata = {
.start_flag = ATOMIC_INIT(0),
.count_start = ATOMIC_INIT(0),
.count_stop = ATOMIC_INIT(0),
@@ -334,7 +332,7 @@ static void __init synchronize_tsc_bp(void)
printk("passed.\n");
}
-static void __init synchronize_tsc_ap(void)
+static void __cpuinit synchronize_tsc_ap(void)
{
int i;
@@ -366,7 +364,7 @@ extern void calibrate_delay(void);
static atomic_t init_deasserted;
-static void __devinit smp_callin(void)
+static void __cpuinit smp_callin(void)
{
int cpuid, phys_id;
unsigned long timeout;
@@ -540,7 +538,7 @@ set_cpu_sibling_map(int cpu)
/*
* Activate a secondary processor.
*/
-static void __devinit start_secondary(void *unused)
+static void __cpuinit start_secondary(void *unused)
{
/*
* Don't put *anything* before secondary_cpu_init(), SMP
@@ -598,6 +596,12 @@ static void __devinit start_secondary(void *unused)
void __devinit initialize_secondary(void)
{
/*
+ * switch to the per CPU GDT we already set up
+ * in do_boot_cpu()
+ */
+ cpu_set_gdt(current_thread_info()->cpu);
+
+ /*
* We don't actually need to load the full TSS,
* basically just the stack pointer and the eip.
*/
@@ -933,7 +937,7 @@ static inline struct task_struct * alloc_idle_task(int cpu)
#define alloc_idle_task(cpu) fork_idle(cpu)
#endif
-static int __devinit do_boot_cpu(int apicid, int cpu)
+static int __cpuinit do_boot_cpu(int apicid, int cpu)
/*
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -974,9 +978,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
/* Stack for startup_32 can be just as for start_secondary onwards */
stack_start.esp = (void *) idle->thread.esp;
- start_pda = cpu_pda(cpu);
- cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu);
-
irq_ctx_init(cpu);
x86_cpu_to_apicid[cpu] = apicid;
@@ -1118,7 +1119,7 @@ static int __cpuinit __smp_prepare_cpu(int cpu)
/* init low mem mapping */
clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
- KERNEL_PGD_PTRS);
+ min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
flush_tlb_all();
schedule_work(&info.task);
wait_for_completion(&done);
@@ -1434,7 +1435,7 @@ void __cpu_die(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
#ifdef CONFIG_HOTPLUG_CPU
int ret=0;
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 7de9117b5a3..5da744204d1 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -79,11 +79,6 @@ int __init sysenter_setup(void)
#ifdef CONFIG_COMPAT_VDSO
__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
-#else
- /*
- * In the non-compat case the ELF coredumping code needs the fixmap:
- */
- __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_KERNEL_RO);
#endif
if (!boot_cpu_has(X86_FEATURE_SEP)) {
@@ -100,6 +95,7 @@ int __init sysenter_setup(void)
return 0;
}
+#ifndef CONFIG_COMPAT_VDSO
static struct page *syscall_nopage(struct vm_area_struct *vma,
unsigned long adr, int *type)
{
@@ -146,6 +142,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
vma->vm_end = addr + PAGE_SIZE;
/* MAYWRITE to allow gdb to COW and set breakpoints */
vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+ * without matching up the same kernel and hardware config to see
+ * what PC values meant.
+ */
+ vma->vm_flags |= VM_ALWAYSDUMP;
vma->vm_flags |= mm->def_flags;
vma->vm_page_prot = protection_map[vma->vm_flags & 7];
vma->vm_ops = &syscall_vm_ops;
@@ -187,3 +190,4 @@ int in_gate_area_no_task(unsigned long addr)
{
return 0;
}
+#endif
diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S
index fcce0e61b0e..2f1814c5cfd 100644
--- a/arch/i386/kernel/trampoline.S
+++ b/arch/i386/kernel/trampoline.S
@@ -38,6 +38,11 @@
.data
+/* We can free up trampoline after bootup if cpu hotplug is not supported. */
+#ifndef CONFIG_HOTPLUG_CPU
+.section ".init.data","aw",@progbits
+#endif
+
.code16
ENTRY(trampoline_data)
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 68de48e498c..0efad8aeb41 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/unwind.h>
#include <linux/uaccess.h>
#include <linux/nmi.h>
+#include <linux/bug.h>
#ifdef CONFIG_EISA
#include <linux/ioport.h>
@@ -93,11 +94,6 @@ asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);
int kstack_depth_to_print = 24;
-#ifdef CONFIG_STACK_UNWIND
-static int call_trace = 1;
-#else
-#define call_trace (-1)
-#endif
ATOMIC_NOTIFIER_HEAD(i386die_chain);
int register_die_notifier(struct notifier_block *nb)
@@ -151,33 +147,6 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
return ebp;
}
-struct ops_and_data {
- struct stacktrace_ops *ops;
- void *data;
-};
-
-static asmlinkage int
-dump_trace_unwind(struct unwind_frame_info *info, void *data)
-{
- struct ops_and_data *oad = (struct ops_and_data *)data;
- int n = 0;
- unsigned long sp = UNW_SP(info);
-
- if (arch_unw_user_mode(info))
- return -1;
- while (unwind(info) == 0 && UNW_PC(info)) {
- n++;
- oad->ops->address(oad->data, UNW_PC(info));
- if (arch_unw_user_mode(info))
- break;
- if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
- && sp > UNW_SP(info))
- break;
- sp = UNW_SP(info);
- }
- return n;
-}
-
#define MSG(msg) ops->warning(data, msg)
void dump_trace(struct task_struct *task, struct pt_regs *regs,
@@ -189,41 +158,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
if (!task)
task = current;
- if (call_trace >= 0) {
- int unw_ret = 0;
- struct unwind_frame_info info;
- struct ops_and_data oad = { .ops = ops, .data = data };
-
- if (regs) {
- if (unwind_init_frame_info(&info, task, regs) == 0)
- unw_ret = dump_trace_unwind(&info, &oad);
- } else if (task == current)
- unw_ret = unwind_init_running(&info, dump_trace_unwind,
- &oad);
- else {
- if (unwind_init_blocked(&info, task) == 0)
- unw_ret = dump_trace_unwind(&info, &oad);
- }
- if (unw_ret > 0) {
- if (call_trace == 1 && !arch_unw_user_mode(&info)) {
- ops->warning_symbol(data,
- "DWARF2 unwinder stuck at %s",
- UNW_PC(&info));
- if (UNW_SP(&info) >= PAGE_OFFSET) {
- MSG("Leftover inexact backtrace:");
- stack = (void *)UNW_SP(&info);
- if (!stack)
- return;
- ebp = UNW_FP(&info);
- } else
- MSG("Full inexact backtrace again:");
- } else if (call_trace >= 1)
- return;
- else
- MSG("Full inexact backtrace again:");
- } else
- MSG("Inexact backtrace:");
- }
if (!stack) {
unsigned long dummy;
stack = &dummy;
@@ -420,43 +354,22 @@ void show_registers(struct pt_regs *regs)
printk("\n");
}
-static void handle_BUG(struct pt_regs *regs)
+int is_valid_bugaddr(unsigned long eip)
{
- unsigned long eip = regs->eip;
unsigned short ud2;
if (eip < PAGE_OFFSET)
- return;
+ return 0;
if (probe_kernel_address((unsigned short *)eip, ud2))
- return;
- if (ud2 != 0x0b0f)
- return;
-
- printk(KERN_EMERG "------------[ cut here ]------------\n");
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
- do {
- unsigned short line;
- char *file;
- char c;
-
- if (probe_kernel_address((unsigned short *)(eip + 2), line))
- break;
- if (probe_kernel_address((char **)(eip + 4), file) ||
- (unsigned long)file < PAGE_OFFSET ||
- probe_kernel_address(file, c))
- file = "<bad filename>";
+ return 0;
- printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
- return;
- } while (0);
-#endif
- printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n");
+ return ud2 == 0x0b0f;
}
-/* This is gone through when something in the kernel
- * has done something bad and is about to be terminated.
-*/
+/*
+ * This is gone through when something in the kernel has done something bad and
+ * is about to be terminated.
+ */
void die(const char * str, struct pt_regs * regs, long err)
{
static struct {
@@ -488,7 +401,8 @@ void die(const char * str, struct pt_regs * regs, long err)
unsigned long esp;
unsigned short ss;
- handle_BUG(regs);
+ report_bug(regs->eip);
+
printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
printk(KERN_EMERG "PREEMPT ");
@@ -1277,19 +1191,3 @@ static int __init kstack_setup(char *s)
return 1;
}
__setup("kstack=", kstack_setup);
-
-#ifdef CONFIG_STACK_UNWIND
-static int __init call_trace_setup(char *s)
-{
- if (strcmp(s, "old") == 0)
- call_trace = -1;
- else if (strcmp(s, "both") == 0)
- call_trace = 0;
- else if (strcmp(s, "newfallback") == 0)
- call_trace = 1;
- else if (strcmp(s, "new") == 2)
- call_trace = 2;
- return 1;
-}
-__setup("call_trace=", call_trace_setup);
-#endif
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index 1bbe45dca7a..2cfc7b09b92 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -24,7 +24,7 @@
*/
unsigned int tsc_khz;
-int tsc_disable __cpuinitdata = 0;
+int tsc_disable;
#ifdef CONFIG_X86_TSC
static int __init tsc_setup(char *str)
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 56e6ad5cb04..a53c8b1854b 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -26,6 +26,7 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(phys_startup_32)
jiffies = jiffies_64;
+_proxy_pda = 0;
PHDRS {
text PT_LOAD FLAGS(5); /* R_E */
@@ -57,6 +58,8 @@ SECTIONS
RODATA
+ BUG_TABLE
+
. = ALIGN(4);
.tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
__tracedata_start = .;
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c
index c511705c386..cc2f519b2f7 100644
--- a/arch/i386/mach-default/setup.c
+++ b/arch/i386/mach-default/setup.c
@@ -102,7 +102,7 @@ void __init time_init_hook(void)
* along the MCA bus. Use this to hook into that chain if you will need
* it.
**/
-void __init mca_nmi_hook(void)
+void mca_nmi_hook(void)
{
/* If I recall correctly, there's a whole bunch of other things that
* we can do to check for NMI problems, but that's all I know about
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
index 33d9f93557b..8a210fa915b 100644
--- a/arch/i386/mach-generic/bigsmp.c
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -45,7 +45,7 @@ static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
};
-static __init int probe_bigsmp(void)
+static int probe_bigsmp(void)
{
if (def_to_bigsmp)
dmi_bigsmp = 1;
diff --git a/arch/i386/mach-generic/default.c b/arch/i386/mach-generic/default.c
index 96c19821e47..8685208d851 100644
--- a/arch/i386/mach-generic/default.c
+++ b/arch/i386/mach-generic/default.c
@@ -18,7 +18,7 @@
#include <asm/mach-default/mach_mpparse.h>
/* should be called last. */
-static __init int probe_default(void)
+static int probe_default(void)
{
return 1;
}
diff --git a/arch/i386/mach-generic/es7000.c b/arch/i386/mach-generic/es7000.c
index aa144d82334..b8963a5a3b2 100644
--- a/arch/i386/mach-generic/es7000.c
+++ b/arch/i386/mach-generic/es7000.c
@@ -19,7 +19,7 @@
#include <asm/mach-es7000/mach_mpparse.h>
#include <asm/mach-es7000/mach_wakecpu.h>
-static __init int probe_es7000(void)
+static int probe_es7000(void)
{
/* probed later in mptable/ACPI hooks */
return 0;
diff --git a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c
index f7e5d66648d..74883ccb8f7 100644
--- a/arch/i386/mach-generic/summit.c
+++ b/arch/i386/mach-generic/summit.c
@@ -18,7 +18,7 @@
#include <asm/mach-summit/mach_ipi.h>
#include <asm/mach-summit/mach_mpparse.h>
-static __init int probe_summit(void)
+static int probe_summit(void)
{
/* probed later in mptable/ACPI hooks */
return 0;
diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c
index 885c7cbfd47..233ee20907b 100644
--- a/arch/i386/mach-visws/setup.c
+++ b/arch/i386/mach-visws/setup.c
@@ -6,6 +6,7 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/fixmap.h>
#include <asm/arch_hooks.h>
@@ -142,6 +143,8 @@ void __init time_init_hook(void)
unsigned long sgivwfb_mem_phys;
unsigned long sgivwfb_mem_size;
+EXPORT_SYMBOL(sgivwfb_mem_phys);
+EXPORT_SYMBOL(sgivwfb_mem_size);
long long mem_size __initdata = 0;
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 55428e656a3..74aeedf277f 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -773,6 +773,12 @@ initialize_secondary(void)
#endif
/*
+ * switch to the per CPU GDT we already set up
+ * in do_boot_cpu()
+ */
+ cpu_set_gdt(current_thread_info()->cpu);
+
+ /*
* We don't actually need to load the full TSS,
* basically just the stack pointer and the eip.
*/
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 103b76e56a9..e0c390d6ceb 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -405,3 +405,31 @@ void __init set_highmem_pages_init(int bad_ppro)
totalram_pages += totalhigh_pages;
#endif
}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int paddr_to_nid(u64 addr)
+{
+ int nid;
+ unsigned long pfn = PFN_DOWN(addr);
+
+ for_each_node(nid)
+ if (node_start_pfn[nid] <= pfn &&
+ pfn < node_end_pfn[nid])
+ return nid;
+
+ return -1;
+}
+
+/*
+ * This function is used to ask node id BEFORE memmap and mem_section's
+ * initialization (pfn_to_nid() can't be used yet).
+ * If _PXM is not defined on ACPI's DSDT, node id must be found by this.
+ */
+int memory_add_physaddr_to_nid(u64 addr)
+{
+ int nid = paddr_to_nid(addr);
+ return (nid >= 0) ? nid : 0;
+}
+
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 84697dfc734..c5c5ea700cc 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -283,7 +283,7 @@ void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
SetPageReserved(page);
}
-static int add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long pfn)
{
free_new_highpage(page);
totalram_pages++;
@@ -300,7 +300,7 @@ static int add_one_highpage_hotplug(struct page *page, unsigned long pfn)
* has been added dynamically that would be
* onlined here is in HIGHMEM
*/
-void online_page(struct page *page)
+void __meminit online_page(struct page *page)
{
ClearPageReserved(page);
add_one_highpage_hotplug(page, page_to_pfn(page));
@@ -673,16 +673,10 @@ void __init mem_init(void)
#endif
}
-/*
- * this is for the non-NUMA, single node SMP system case.
- * Specifically, in the case of x86, we will always add
- * memory to the highmem for now.
- */
#ifdef CONFIG_MEMORY_HOTPLUG
-#ifndef CONFIG_NEED_MULTIPLE_NODES
int arch_add_memory(int nid, u64 start, u64 size)
{
- struct pglist_data *pgdata = &contig_page_data;
+ struct pglist_data *pgdata = NODE_DATA(nid);
struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
@@ -694,7 +688,7 @@ int remove_memory(u64 start, u64 size)
{
return -EINVAL;
}
-#endif
+EXPORT_SYMBOL_GPL(remove_memory);
#endif
struct kmem_cache *pgd_cache;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index cde1170b01a..8053b17ab64 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -115,7 +115,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci
#define VIA_8363_KL133_REVISION_ID 0x81
#define VIA_8363_KM133_REVISION_ID 0x84
-static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d)
+static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
{
u8 v;
u8 revision;
@@ -151,6 +151,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
/*
* For some reasons Intel decided that certain parts of their
@@ -181,7 +185,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_
* issue another HALT within 80 ns of the initial HALT, the failure condition
* is avoided.
*/
-static void __init pci_fixup_nforce2(struct pci_dev *dev)
+static void pci_fixup_nforce2(struct pci_dev *dev)
{
u32 val;
@@ -204,6 +208,7 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
/* Max PCI Express root ports */
#define MAX_PCIEROOT 6
@@ -419,7 +424,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
* Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
* configuration space.
*/
-static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
+static void pci_early_fixup_cyrix_5530(struct pci_dev *dev)
{
u8 r;
/* clear 'F4 Video Configuration Trap' bit */
@@ -429,3 +434,5 @@ static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
pci_early_fixup_cyrix_5530);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
+ pci_early_fixup_cyrix_5530);
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index c6b6d9bbc45..e2616a266e1 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -26,6 +26,7 @@
/* The base address of the last MMCONFIG device accessed */
static u32 mmcfg_last_accessed_device;
+static int mmcfg_last_accessed_cpu;
static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
@@ -73,8 +74,11 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
{
u32 dev_base = base | (bus << 20) | (devfn << 12);
- if (dev_base != mmcfg_last_accessed_device) {
+ int cpu = smp_processor_id();
+ if (dev_base != mmcfg_last_accessed_device ||
+ cpu != mmcfg_last_accessed_cpu) {
mmcfg_last_accessed_device = dev_base;
+ mmcfg_last_accessed_cpu = cpu;
set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
}
}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 75d839715b2..fcacfe291b9 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -34,6 +34,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 1f16ebb9a80..324ea7565e2 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -488,7 +488,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
unsigned int cflag = tty->termios->c_cflag;
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index a4a6e1463af..957681c39ad 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -235,7 +235,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
if (!(flags & MAP_ANONYMOUS)) {
/* read the file contents */
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (!inode->i_fop || !file->f_op->read
|| ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0))
{
@@ -837,7 +837,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
if (!is_congruent) {
/* read the file contents */
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (!inode->i_fop || !file->f_op->read
|| ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff)
< 0))
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 8ae384eb535..098ee605bf5 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
obj-$(CONFIG_AUDIT) += audit.o
obj-$(CONFIG_PCI_MSI) += msi_ia64.o
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 73ef4a85b86..29f05d4b68c 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -590,6 +590,9 @@ void __init acpi_numa_arch_fixup(void)
*/
int acpi_register_gsi(u32 gsi, int triggering, int polarity)
{
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+ return gsi;
+
if (has_8259 && gsi < 16)
return isa_irq_to_vector(gsi);
@@ -606,6 +609,9 @@ EXPORT_SYMBOL(acpi_register_gsi);
void acpi_unregister_gsi(u32 gsi)
{
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+ return;
+
iosapic_unregister_intr(gsi);
}
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index 088f130197a..15c08d52f09 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -276,12 +276,10 @@ acpi_cpufreq_cpu_init (
dprintk("acpi_cpufreq_cpu_init\n");
- data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
+ data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
if (!data)
return (-ENOMEM);
- memset(data, 0, sizeof(struct cpufreq_acpi_io));
-
acpi_io_data[cpu] = data;
result = acpi_processor_register_performance(&data->acpi_data, cpu);
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
index 0aabedf95da..bc2f64d7224 100644
--- a/arch/ia64/kernel/crash.c
+++ b/arch/ia64/kernel/crash.c
@@ -19,29 +19,11 @@
#include <asm/kdebug.h>
#include <asm/mca.h>
-#include <asm/uaccess.h>
int kdump_status[NR_CPUS];
atomic_t kdump_cpu_freezed;
atomic_t kdump_in_progress;
int kdump_on_init = 1;
-ssize_t
-copy_oldmem_page(unsigned long pfn, char *buf,
- size_t csize, unsigned long offset, int userbuf)
-{
- void *vaddr;
-
- if (!csize)
- return 0;
- vaddr = __va(pfn<<PAGE_SHIFT);
- if (userbuf) {
- if (copy_to_user(buf, (vaddr + offset), csize)) {
- return -EFAULT;
- }
- } else
- memcpy(buf, (vaddr + offset), csize);
- return csize;
-}
static inline Elf64_Word
*append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
@@ -225,14 +207,10 @@ static ctl_table sys_table[] = {
static int
machine_crash_setup(void)
{
- char *from = strstr(saved_command_line, "elfcorehdr=");
static struct notifier_block kdump_init_notifier_nb = {
.notifier_call = kdump_init_notifier,
};
int ret;
- if (from)
- elfcorehdr_addr = memparse(from+11, &from);
- saved_max_pfn = (unsigned long)-1;
if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
return ret;
#ifdef CONFIG_SYSCTL
diff --git a/arch/ia64/kernel/crash_dump.c b/arch/ia64/kernel/crash_dump.c
new file mode 100644
index 00000000000..83b8c91c140
--- /dev/null
+++ b/arch/ia64/kernel/crash_dump.c
@@ -0,0 +1,48 @@
+/*
+ * kernel/crash_dump.c - Memory preserving reboot related code.
+ *
+ * Created by: Simon Horman <horms@verge.net.au>
+ * Original code moved from kernel/crash.c
+ * Original code comment copied from the i386 version of this file
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#include <linux/uaccess.h>
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ * space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ * otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t
+copy_oldmem_page(unsigned long pfn, char *buf,
+ size_t csize, unsigned long offset, int userbuf)
+{
+ void *vaddr;
+
+ if (!csize)
+ return 0;
+ vaddr = __va(pfn<<PAGE_SHIFT);
+ if (userbuf) {
+ if (copy_to_user(buf, (vaddr + offset), csize)) {
+ return -EFAULT;
+ }
+ } else
+ memcpy(buf, (vaddr + offset), csize);
+ return csize;
+}
+
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 54d55e4d64f..ce49c85c928 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -122,6 +122,9 @@ static void migrate_irqs(void)
for (irq=0; irq < NR_IRQS; irq++) {
desc = irq_desc + irq;
+ if (desc->status == IRQ_DISABLED)
+ continue;
+
/*
* No handling for now.
* TBD: Implement a disable function so we can now
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index 5cd6226f44f..621630256c4 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -45,13 +45,14 @@
* to the correct location.
*/
#include <asm/asmmacro.h>
+#include <asm-ia64/break.h>
/*
* void jprobe_break(void)
*/
.section .kprobes.text, "ax"
ENTRY(jprobe_break)
- break.m 0x80300
+ break.m __IA64_BREAK_JPROBE
END(jprobe_break)
/*
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 76e778951e2..6cb56dd4056 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -88,6 +88,7 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
{
p->ainsn.inst_flag = 0;
p->ainsn.target_br_reg = 0;
+ p->ainsn.slot = slot;
/* Check for Break instruction
* Bits 37:40 Major opcode to be zero
@@ -129,48 +130,6 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
/*
* In this function we check to see if the instruction
- * on which we are inserting kprobe is supported.
- * Returns 0 if supported
- * Returns -EINVAL if unsupported
- */
-static int __kprobes unsupported_inst(uint template, uint slot,
- uint major_opcode,
- unsigned long kprobe_inst,
- unsigned long addr)
-{
- if (bundle_encoding[template][slot] == I) {
- switch (major_opcode) {
- case 0x0: //I_UNIT_MISC_OPCODE:
- /*
- * Check for Integer speculation instruction
- * - Bit 33-35 to be equal to 0x1
- */
- if (((kprobe_inst >> 33) & 0x7) == 1) {
- printk(KERN_WARNING
- "Kprobes on speculation inst at <0x%lx> not supported\n",
- addr);
- return -EINVAL;
- }
-
- /*
- * IP relative mov instruction
- * - Bit 27-35 to be equal to 0x30
- */
- if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
- printk(KERN_WARNING
- "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
- addr);
- return -EINVAL;
-
- }
- }
- }
- return 0;
-}
-
-
-/*
- * In this function we check to see if the instruction
* (qp) cmpx.crel.ctype p1,p2=r2,r3
* on which we are inserting kprobe is cmp instruction
* with ctype as unc.
@@ -206,26 +165,136 @@ out:
}
/*
+ * In this function we check to see if the instruction
+ * on which we are inserting kprobe is supported.
+ * Returns qp value if supported
+ * Returns -EINVAL if unsupported
+ */
+static int __kprobes unsupported_inst(uint template, uint slot,
+ uint major_opcode,
+ unsigned long kprobe_inst,
+ unsigned long addr)
+{
+ int qp;
+
+ qp = kprobe_inst & 0x3f;
+ if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
+ if (slot == 1 && qp) {
+ printk(KERN_WARNING "Kprobes on cmp unc"
+ "instruction on slot 1 at <0x%lx>"
+ "is not supported\n", addr);
+ return -EINVAL;
+
+ }
+ qp = 0;
+ }
+ else if (bundle_encoding[template][slot] == I) {
+ if (major_opcode == 0) {
+ /*
+ * Check for Integer speculation instruction
+ * - Bit 33-35 to be equal to 0x1
+ */
+ if (((kprobe_inst >> 33) & 0x7) == 1) {
+ printk(KERN_WARNING
+ "Kprobes on speculation inst at <0x%lx> not supported\n",
+ addr);
+ return -EINVAL;
+ }
+ /*
+ * IP relative mov instruction
+ * - Bit 27-35 to be equal to 0x30
+ */
+ if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
+ printk(KERN_WARNING
+ "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
+ addr);
+ return -EINVAL;
+
+ }
+ }
+ else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) &&
+ (kprobe_inst & (0x1UL << 12))) {
+ /* test bit instructions, tbit,tnat,tf
+ * bit 33-36 to be equal to 0
+ * bit 12 to be equal to 1
+ */
+ if (slot == 1 && qp) {
+ printk(KERN_WARNING "Kprobes on test bit"
+ "instruction on slot at <0x%lx>"
+ "is not supported\n", addr);
+ return -EINVAL;
+ }
+ qp = 0;
+ }
+ }
+ else if (bundle_encoding[template][slot] == B) {
+ if (major_opcode == 7) {
+ /* IP-Relative Predict major code is 7 */
+ printk(KERN_WARNING "Kprobes on IP-Relative"
+ "Predict is not supported\n");
+ return -EINVAL;
+ }
+ else if (major_opcode == 2) {
+ /* Indirect Predict, major code is 2
+ * bit 27-32 to be equal to 10 or 11
+ */
+ int x6=(kprobe_inst >> 27) & 0x3F;
+ if ((x6 == 0x10) || (x6 == 0x11)) {
+ printk(KERN_WARNING "Kprobes on"
+ "Indirect Predict is not supported\n");
+ return -EINVAL;
+ }
+ }
+ }
+ /* kernel does not use float instruction, here for safety kprobe
+ * will judge whether it is fcmp/flass/float approximation instruction
+ */
+ else if (unlikely(bundle_encoding[template][slot] == F)) {
+ if ((major_opcode == 4 || major_opcode == 5) &&
+ (kprobe_inst & (0x1 << 12))) {
+ /* fcmp/fclass unc instruction */
+ if (slot == 1 && qp) {
+ printk(KERN_WARNING "Kprobes on fcmp/fclass "
+ "instruction on slot at <0x%lx> "
+ "is not supported\n", addr);
+ return -EINVAL;
+
+ }
+ qp = 0;
+ }
+ if ((major_opcode == 0 || major_opcode == 1) &&
+ (kprobe_inst & (0x1UL << 33))) {
+ /* float Approximation instruction */
+ if (slot == 1 && qp) {
+ printk(KERN_WARNING "Kprobes on float Approx "
+ "instr at <0x%lx> is not supported\n",
+ addr);
+ return -EINVAL;
+ }
+ qp = 0;
+ }
+ }
+ return qp;
+}
+
+/*
* In this function we override the bundle with
* the break instruction at the given slot.
*/
static void __kprobes prepare_break_inst(uint template, uint slot,
uint major_opcode,
unsigned long kprobe_inst,
- struct kprobe *p)
+ struct kprobe *p,
+ int qp)
{
unsigned long break_inst = BREAK_INST;
bundle_t *bundle = &p->opcode.bundle;
/*
* Copy the original kprobe_inst qualifying predicate(qp)
- * to the break instruction iff !is_cmp_ctype_unc_inst
- * because for cmp instruction with ctype equal to unc,
- * which is a special instruction always needs to be
- * executed regradless of qp
+ * to the break instruction
*/
- if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
- break_inst |= (0x3f & kprobe_inst);
+ break_inst |= qp;
switch (slot) {
case 0:
@@ -296,12 +365,6 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
return -EINVAL;
}
- if (slot == 1 && bundle_encoding[template][1] != L) {
- printk(KERN_WARNING "Inserting kprobes on slot #1 "
- "is not supported\n");
- return -EINVAL;
- }
-
return 0;
}
@@ -427,6 +490,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
unsigned long kprobe_inst=0;
unsigned int slot = addr & 0xf, template, major_opcode = 0;
bundle_t *bundle;
+ int qp;
bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
template = bundle->quad0.template;
@@ -441,9 +505,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
/* Get kprobe_inst and major_opcode from the bundle */
get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
- if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
- return -EINVAL;
-
+ qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr);
+ if (qp < 0)
+ return -EINVAL;
p->ainsn.insn = get_insn_slot();
if (!p->ainsn.insn)
@@ -451,30 +515,56 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
- prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
+ prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
return 0;
}
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
- unsigned long addr = (unsigned long)p->addr;
- unsigned long arm_addr = addr & ~0xFULL;
+ unsigned long arm_addr;
+ bundle_t *src, *dest;
+
+ arm_addr = ((unsigned long)p->addr) & ~0xFUL;
+ dest = &((kprobe_opcode_t *)arm_addr)->bundle;
+ src = &p->opcode.bundle;
flush_icache_range((unsigned long)p->ainsn.insn,
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
- memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
+ switch (p->ainsn.slot) {
+ case 0:
+ dest->quad0.slot0 = src->quad0.slot0;
+ break;
+ case 1:
+ dest->quad1.slot1_p1 = src->quad1.slot1_p1;
+ break;
+ case 2:
+ dest->quad1.slot2 = src->quad1.slot2;
+ break;
+ }
flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
}
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
- unsigned long addr = (unsigned long)p->addr;
- unsigned long arm_addr = addr & ~0xFULL;
+ unsigned long arm_addr;
+ bundle_t *src, *dest;
+ arm_addr = ((unsigned long)p->addr) & ~0xFUL;
+ dest = &((kprobe_opcode_t *)arm_addr)->bundle;
/* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
- memcpy((char *) arm_addr, (char *) p->ainsn.insn,
- sizeof(kprobe_opcode_t));
+ src = &p->ainsn.insn->bundle;
+ switch (p->ainsn.slot) {
+ case 0:
+ dest->quad0.slot0 = src->quad0.slot0;
+ break;
+ case 1:
+ dest->quad1.slot1_p1 = src->quad1.slot1_p1;
+ break;
+ case 2:
+ dest->quad1.slot2 = src->quad1.slot2;
+ break;
+ }
flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
}
@@ -807,7 +897,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
switch(val) {
case DIE_BREAK:
/* err is break number from ia64_bad_break() */
- if (args->err == 0x80200 || args->err == 0x80300 || args->err == 0)
+ if ((args->err >> 12) == (__IA64_BREAK_KPROBE >> 12)
+ || args->err == __IA64_BREAK_JPROBE
+ || args->err == 0)
if (pre_kprobes_handler(args))
ret = NOTIFY_STOP;
break;
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index 468233fa2ce..e2ccc9f660c 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -19,8 +19,11 @@
#include <asm/delay.h>
#include <asm/meminit.h>
-typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long,
- struct ia64_boot_param *, unsigned long);
+typedef NORET_TYPE void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long start_address,
+ struct ia64_boot_param *boot_param,
+ unsigned long pal_addr) ATTRIB_NORET;
struct kimage *ia64_kimage;
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 87c1c4f4287..a76add3e76a 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1239,7 +1239,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
} else {
/* Dump buffered message to console */
ia64_mlogbuf_finish(1);
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_KEXEC
atomic_set(&kdump_in_progress, 1);
monarch_cpu = -1;
#endif
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index dbb28164b19..aa94f60fa8e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2188,13 +2188,13 @@ pfm_alloc_fd(struct file **cfile)
/*
* allocate a new dcache entry
*/
- file->f_dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
- if (!file->f_dentry) goto out;
+ file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
+ if (!file->f_path.dentry) goto out;
- file->f_dentry->d_op = &pfmfs_dentry_operations;
+ file->f_path.dentry->d_op = &pfmfs_dentry_operations;
- d_add(file->f_dentry, inode);
- file->f_vfsmnt = mntget(pfmfs_mnt);
+ d_add(file->f_path.dentry, inode);
+ file->f_path.mnt = mntget(pfmfs_mnt);
file->f_mapping = inode->i_mapping;
file->f_op = &pfm_file_ops;
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 51922b98086..17685abaf49 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -268,10 +268,16 @@ cpu_idle (void)
/* endless idle loop with no priority at all */
while (1) {
- if (can_do_pal_halt)
+ if (can_do_pal_halt) {
current_thread_info()->status &= ~TS_POLLING;
- else
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
+ } else {
current_thread_info()->status |= TS_POLLING;
+ }
if (!need_resched()) {
void (*idle)(void);
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index fd607ca51a8..e375a2f0f2c 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -302,7 +302,7 @@ salinfo_event_open(struct inode *inode, struct file *file)
static ssize_t
salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct proc_dir_entry *entry = PDE(inode);
struct salinfo_data *data = entry->data;
char cmd[32];
@@ -464,7 +464,7 @@ retry:
static ssize_t
salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct proc_dir_entry *entry = PDE(inode);
struct salinfo_data *data = entry->data;
u8 *buf;
@@ -525,7 +525,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
static ssize_t
salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct proc_dir_entry *entry = PDE(inode);
struct salinfo_data *data = entry->data;
char cmd[32];
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 14e1200376a..ad567b8d432 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -256,7 +256,7 @@ reserve_memory (void)
#ifdef CONFIG_KEXEC
/* crashkernel=size@offset specifies the size to reserve for a crash
- * kernel.(offset is ingored for keep compatibility with other archs)
+ * kernel. If offset is 0, then it is determined automatically.
* By reserving this memory we guarantee that linux never set's it
* up as a DMA target.Useful for holding code to do something
* appropriate after a kernel panic.
@@ -266,10 +266,16 @@ reserve_memory (void)
unsigned long base, size;
if (from) {
size = memparse(from + 12, &from);
+ if (*from == '@')
+ base = memparse(from+1, &from);
+ else
+ base = 0;
if (size) {
- sort_regions(rsvd_region, n);
- base = kdump_find_rsvd_region(size,
- rsvd_region, n);
+ if (!base) {
+ sort_regions(rsvd_region, n);
+ base = kdump_find_rsvd_region(size,
+ rsvd_region, n);
+ }
if (base != ~0UL) {
rsvd_region[n].start =
(unsigned long)__va(base);
@@ -434,6 +440,21 @@ static __init int setup_nomca(char *s)
}
early_param("nomca", setup_nomca);
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel.
+ */
+static int __init parse_elfcorehdr(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+
+ elfcorehdr_addr = memparse(arg, &arg);
+ return 0;
+}
+early_param("elfcorehdr", parse_elfcorehdr);
+#endif /* CONFIG_PROC_VMCORE */
+
void __init
setup_arch (char **cmdline_p)
{
@@ -653,6 +674,7 @@ get_model_name(__u8 family, __u8 model)
{
char brand[128];
+ memcpy(brand, "Unknown", 8);
if (ia64_pal_get_brand_info(brand)) {
if (family == 0x7)
memcpy(brand, "Merced", 7);
@@ -660,8 +682,7 @@ get_model_name(__u8 family, __u8 model)
case 0: memcpy(brand, "McKinley", 9); break;
case 1: memcpy(brand, "Madison", 8); break;
case 2: memcpy(brand, "Madison up to 9M cache", 23); break;
- } else
- memcpy(brand, "Unknown", 8);
+ }
}
if (brandname[0] == '\0')
return strcpy(brandname, brand);
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index b1b9aa4364b..f4c7f7769cf 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -157,7 +157,7 @@ handle_IPI (int irq, void *dev_id)
case IPI_CPU_STOP:
stop_this_cpu();
break;
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_KEXEC
case IPI_KDUMP_CPU_STOP:
unw_init_running(kdump_cpu_freeze, NULL);
break;
@@ -219,7 +219,7 @@ send_IPI_self (int op)
send_IPI_single(smp_processor_id(), op);
}
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_KEXEC
void
kdump_smp_send_stop()
{
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index fffa9e0826b..ab684747036 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -307,6 +307,15 @@ fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long
return ret.status;
}
+struct fpu_swa_msg {
+ unsigned long count;
+ unsigned long time;
+};
+static DEFINE_PER_CPU(struct fpu_swa_msg, cpulast);
+DECLARE_PER_CPU(struct fpu_swa_msg, cpulast);
+static struct fpu_swa_msg last __cacheline_aligned;
+
+
/*
* Handle floating-point assist faults and traps.
*/
@@ -316,8 +325,6 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
long exception, bundle[2];
unsigned long fault_ip;
struct siginfo siginfo;
- static int fpu_swa_count = 0;
- static unsigned long last_time;
fault_ip = regs->cr_iip;
if (!fp_fault && (ia64_psr(regs)->ri == 0))
@@ -325,14 +332,37 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
return -1;
- if (jiffies - last_time > 5*HZ)
- fpu_swa_count = 0;
- if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
- last_time = jiffies;
- ++fpu_swa_count;
- printk(KERN_WARNING
- "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
- current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
+ if (!(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
+ unsigned long count, current_jiffies = jiffies;
+ struct fpu_swa_msg *cp = &__get_cpu_var(cpulast);
+
+ if (unlikely(current_jiffies > cp->time))
+ cp->count = 0;
+ if (unlikely(cp->count < 5)) {
+ cp->count++;
+ cp->time = current_jiffies + 5 * HZ;
+
+ /* minimize races by grabbing a copy of count BEFORE checking last.time. */
+ count = last.count;
+ barrier();
+
+ /*
+ * Lower 4 bits are used as a count. Upper bits are a sequence
+ * number that is updated when count is reset. The cmpxchg will
+ * fail is seqno has changed. This minimizes mutiple cpus
+ * reseting the count.
+ */
+ if (current_jiffies > last.time)
+ (void) cmpxchg_acq(&last.count, count, 16 + (count & ~15));
+
+ /* used fetchadd to atomically update the count */
+ if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) {
+ last.time = current_jiffies + 5 * HZ;
+ printk(KERN_WARNING
+ "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
+ current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
+ }
+ }
}
exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 82deaa3a7c4..1e79551231b 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -174,6 +174,12 @@ find_memory (void)
reserve_bootmem(bootmap_start, bootmap_size);
find_initrd();
+
+#ifdef CONFIG_CRASH_DUMP
+ /* If we are doing a crash dump, we still need to know the real mem
+ * size before original memory map is * reset. */
+ saved_max_pfn = max_pfn;
+#endif
}
#ifdef CONFIG_SMP
@@ -226,7 +232,6 @@ void __init
paging_init (void)
{
unsigned long max_dma;
- unsigned long nid = 0;
unsigned long max_zone_pfns[MAX_NR_ZONES];
num_physpages = 0;
@@ -238,7 +243,7 @@ paging_init (void)
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_VIRTUAL_MEM_MAP
- efi_memmap_walk(register_active_ranges, &nid);
+ efi_memmap_walk(register_active_ranges, NULL);
efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
if (max_gap < LARGE_GAP) {
vmem_map = (struct page *) 0;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 56dc2024220..1373fae7657 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -543,7 +543,8 @@ virtual_memmap_init (u64 start, u64 end, void *arg)
if (map_start < map_end)
memmap_init_zone((unsigned long)(map_end - map_start),
- args->nid, args->zone, page_to_pfn(map_start));
+ args->nid, args->zone, page_to_pfn(map_start),
+ MEMMAP_EARLY);
return 0;
}
@@ -552,7 +553,7 @@ memmap_init (unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn)
{
if (!vmem_map)
- memmap_init_zone(size, nid, zone, start_pfn);
+ memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY);
else {
struct page *start;
struct memmap_init_callback_data args;
@@ -595,14 +596,9 @@ find_largest_hole (u64 start, u64 end, void *arg)
}
int __init
-register_active_ranges(u64 start, u64 end, void *nid)
+register_active_ranges(u64 start, u64 end, void *arg)
{
- BUG_ON(nid == NULL);
- BUG_ON(*(unsigned long *)nid >= MAX_NUMNODES);
-
- add_active_range(*(unsigned long *)nid,
- __pa(start) >> PAGE_SHIFT,
- __pa(end) >> PAGE_SHIFT);
+ add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT);
return 0;
}
#endif /* CONFIG_VIRTUAL_MEM_MAP */
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
index 99d7f278612..cb96b4ea7df 100644
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -223,6 +223,9 @@ sn_io_acpi_init(void)
u64 result;
s64 status;
+ /* SN Altix does not follow the IOSAPIC IRQ routing model */
+ acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
+
acpi_bus_register_driver(&acpi_sn_hubdev_driver);
status = sal_ioif_init(&result);
if (status || result)
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index a934ad06942..8571e52c2ef 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -580,7 +580,7 @@ void __cpuinit sn_cpu_init(void)
int slice;
int cnode;
int i;
- static int wars_have_been_checked;
+ static int wars_have_been_checked, set_cpu0_number;
cpuid = smp_processor_id();
if (cpuid == 0 && IS_MEDUSA()) {
@@ -605,8 +605,16 @@ void __cpuinit sn_cpu_init(void)
/*
* Don't check status. The SAL call is not supported on all PROMs
* but a failure is harmless.
+ * Architechtuallly, cpu_init is always called twice on cpu 0. We
+ * should set cpu_number on cpu 0 once.
*/
- (void) ia64_sn_set_cpu_number(cpuid);
+ if (cpuid == 0) {
+ if (!set_cpu0_number) {
+ (void) ia64_sn_set_cpu_number(cpuid);
+ set_cpu0_number = 1;
+ }
+ } else
+ (void) ia64_sn_set_cpu_number(cpuid);
/*
* The boot cpu makes this call again after platform initialization is
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 462ea178f49..33367996d72 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -189,7 +189,7 @@ static void print_pci_topology(struct seq_file *s)
int e;
for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
- if (!(p = (char *)kmalloc(sz, GFP_KERNEL)))
+ if (!(p = kmalloc(sz, GFP_KERNEL)))
break;
e = ia64_sn_ioif_get_pci_topology(__pa(p), sz);
if (e == SALRET_OK)
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 1f3540826e6..c08db9c2375 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -632,7 +632,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
ch->number, ch->partid);
spin_unlock_irqrestore(&ch->lock, *irq_flags);
- xpc_create_kthreads(ch, 1);
+ xpc_create_kthreads(ch, 1, 0);
spin_lock_irqsave(&ch->lock, *irq_flags);
}
@@ -754,12 +754,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
/* make sure all activity has settled down first */
- if (atomic_read(&ch->references) > 0 ||
- ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
- !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) {
+ if (atomic_read(&ch->kthreads_assigned) > 0 ||
+ atomic_read(&ch->references) > 0) {
return;
}
- DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+ DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+ !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
if (part->act_state == XPC_P_DEACTIVATING) {
/* can't proceed until the other side disengages from us */
@@ -1651,6 +1651,11 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
/* wake all idle kthreads so they can exit */
if (atomic_read(&ch->kthreads_idle) > 0) {
wake_up_all(&ch->idle_wq);
+
+ } else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+ !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+ /* start a kthread that will do the xpcDisconnecting callout */
+ xpc_create_kthreads(ch, 1, 1);
}
/* wake those waiting to allocate an entry from the local msg queue */
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index fa96dfc0e1a..7a387d23736 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -681,7 +681,7 @@ xpc_activate_kthreads(struct xpc_channel *ch, int needed)
dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
needed, ch->partid, ch->number);
- xpc_create_kthreads(ch, needed);
+ xpc_create_kthreads(ch, needed, 0);
}
@@ -775,26 +775,28 @@ xpc_daemonize_kthread(void *args)
xpc_kthread_waitmsgs(part, ch);
}
- if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
- spin_lock_irqsave(&ch->lock, irq_flags);
- if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
- !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
- ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
- spin_unlock_irqrestore(&ch->lock, irq_flags);
+ /* let registerer know that connection is disconnecting */
- xpc_disconnect_callout(ch, xpcDisconnecting);
-
- spin_lock_irqsave(&ch->lock, irq_flags);
- ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
- }
+ spin_lock_irqsave(&ch->lock, irq_flags);
+ if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+ !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+ ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+ xpc_disconnect_callout(ch, xpcDisconnecting);
+
+ spin_lock_irqsave(&ch->lock, irq_flags);
+ ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
+ }
+ spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+ if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
if (atomic_dec_return(&part->nchannels_engaged) == 0) {
xpc_mark_partition_disengaged(part);
xpc_IPI_send_disengage(part);
}
}
-
xpc_msgqueue_deref(ch);
dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
@@ -818,7 +820,8 @@ xpc_daemonize_kthread(void *args)
* partition.
*/
void
-xpc_create_kthreads(struct xpc_channel *ch, int needed)
+xpc_create_kthreads(struct xpc_channel *ch, int needed,
+ int ignore_disconnecting)
{
unsigned long irq_flags;
pid_t pid;
@@ -833,16 +836,38 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
* kthread. That kthread is responsible for doing the
* counterpart to the following before it exits.
*/
+ if (ignore_disconnecting) {
+ if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
+ /* kthreads assigned had gone to zero */
+ BUG_ON(!(ch->flags &
+ XPC_C_DISCONNECTINGCALLOUT_MADE));
+ break;
+ }
+
+ } else if (ch->flags & XPC_C_DISCONNECTING) {
+ break;
+
+ } else if (atomic_inc_return(&ch->kthreads_assigned) == 1) {
+ if (atomic_inc_return(&part->nchannels_engaged) == 1)
+ xpc_mark_partition_engaged(part);
+ }
(void) xpc_part_ref(part);
xpc_msgqueue_ref(ch);
- if (atomic_inc_return(&ch->kthreads_assigned) == 1 &&
- atomic_inc_return(&part->nchannels_engaged) == 1) {
- xpc_mark_partition_engaged(part);
- }
pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
if (pid < 0) {
/* the fork failed */
+
+ /*
+ * NOTE: if (ignore_disconnecting &&
+ * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
+ * then we'll deadlock if all other kthreads assigned
+ * to this channel are blocked in the channel's
+ * registerer, because the only thing that will unblock
+ * them is the xpcDisconnecting callout that this
+ * failed kernel_thread would have made.
+ */
+
if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
atomic_dec_return(&part->nchannels_engaged) == 0) {
xpc_mark_partition_disengaged(part);
@@ -857,9 +882,6 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
* Flag this as an error only if we have an
* insufficient #of kthreads for the channel
* to function.
- *
- * No xpc_msgqueue_ref() is needed here since
- * the channel mgr is doing this.
*/
spin_lock_irqsave(&ch->lock, irq_flags);
XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 41fd490af3b..f383dab973f 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -214,6 +214,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index bce8af5e3bb..ee3c8be12fa 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -2,6 +2,7 @@
* arch/m32r/boot/compressed/m32r_sio.c
*
* 2003-02-12: Takeo Takahashi
+ * 2006-11-30: OPSPUT support by Kazuhiro Inaoka
*
*/
@@ -16,7 +17,7 @@ static int puts(const char *s)
return 0;
}
-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT)
+#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
#include <asm/m32r.h>
#include <asm/io.h>
@@ -31,7 +32,11 @@ static int puts(const char *s)
#define BOOT_SIO0TXB (volatile unsigned short *)(0x02c00000 + 0x2000c)
#else
#undef PLD_BASE
+#if defined(CONFIG_PLAT_OPSPUT)
+#define PLD_BASE 0x1cc00000
+#else
#define PLD_BASE 0xa4c00000
+#endif
#define BOOT_SIO0STS PLD_ESIO0STS
#define BOOT_SIO0TXB PLD_ESIO0TXB
#endif
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index ac6d840b382..a2c472c0549 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -23,35 +23,35 @@
* updated in fork.c:copy_thread, signal.c:do_signal,
* ptrace.c and ptrace.h
*
- * M32Rx/M32R2 M32R
- * @(sp) - r4 ditto
- * @(0x04,sp) - r5 ditto
- * @(0x08,sp) - r6 ditto
- * @(0x0c,sp) - *pt_regs ditto
- * @(0x10,sp) - r0 ditto
- * @(0x14,sp) - r1 ditto
- * @(0x18,sp) - r2 ditto
- * @(0x1c,sp) - r3 ditto
- * @(0x20,sp) - r7 ditto
- * @(0x24,sp) - r8 ditto
- * @(0x28,sp) - r9 ditto
- * @(0x2c,sp) - r10 ditto
- * @(0x30,sp) - r11 ditto
- * @(0x34,sp) - r12 ditto
- * @(0x38,sp) - syscall_nr ditto
- * @(0x3c,sp) - acc0h @(0x3c,sp) - acch
- * @(0x40,sp) - acc0l @(0x40,sp) - accl
- * @(0x44,sp) - acc1h @(0x44,sp) - dummy_acc1h
- * @(0x48,sp) - acc1l @(0x48,sp) - dummy_acc1l
- * @(0x4c,sp) - psw ditto
- * @(0x50,sp) - bpc ditto
- * @(0x54,sp) - bbpsw ditto
- * @(0x58,sp) - bbpc ditto
- * @(0x5c,sp) - spu (cr3) ditto
- * @(0x60,sp) - fp (r13) ditto
- * @(0x64,sp) - lr (r14) ditto
- * @(0x68,sp) - spi (cr2) ditto
- * @(0x6c,sp) - orig_r0 ditto
+ * M32R/M32Rx/M32R2
+ * @(sp) - r4
+ * @(0x04,sp) - r5
+ * @(0x08,sp) - r6
+ * @(0x0c,sp) - *pt_regs
+ * @(0x10,sp) - r0
+ * @(0x14,sp) - r1
+ * @(0x18,sp) - r2
+ * @(0x1c,sp) - r3
+ * @(0x20,sp) - r7
+ * @(0x24,sp) - r8
+ * @(0x28,sp) - r9
+ * @(0x2c,sp) - r10
+ * @(0x30,sp) - r11
+ * @(0x34,sp) - r12
+ * @(0x38,sp) - syscall_nr
+ * @(0x3c,sp) - acc0h
+ * @(0x40,sp) - acc0l
+ * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only
+ * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only
+ * @(0x4c,sp) - psw
+ * @(0x50,sp) - bpc
+ * @(0x54,sp) - bbpsw
+ * @(0x58,sp) - bbpc
+ * @(0x5c,sp) - spu (cr3)
+ * @(0x60,sp) - fp (r13)
+ * @(0x64,sp) - lr (r14)
+ * @(0x68,sp) - spi (cr2)
+ * @(0x6c,sp) - orig_r0
*/
#include <linux/linkage.h>
@@ -95,17 +95,10 @@
#define R11(reg) @(0x30,reg)
#define R12(reg) @(0x34,reg)
#define SYSCALL_NR(reg) @(0x38,reg)
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
#define ACC0H(reg) @(0x3C,reg)
#define ACC0L(reg) @(0x40,reg)
#define ACC1H(reg) @(0x44,reg)
#define ACC1L(reg) @(0x48,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg) @(0x3C,reg)
-#define ACCL(reg) @(0x40,reg)
-#else
-#error unknown isa configuration
-#endif
#define PSW(reg) @(0x4C,reg)
#define BPC(reg) @(0x50,reg)
#define BBPSW(reg) @(0x54,reg)
@@ -603,8 +596,6 @@ ENTRY(ace_handler)
beqz r1, inst
oprand:
ld r2, @(low(MDEVA_offset),r2) ; set address
- srli r2, #12
- slli r2, #12
srli r1, #1
bra 1f
inst:
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
index da6c5f5c1f8..3cbb1f717e5 100644
--- a/arch/m32r/kernel/io_opsput.c
+++ b/arch/m32r/kernel/io_opsput.c
@@ -30,14 +30,34 @@ extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
-#define PORT2ADDR(port) _port2addr(port)
-#define PORT2ADDR_USB(port) _port2addr_usb(port)
+#define PORT2ADDR(port) _port2addr(port)
+#define PORT2ADDR_USB(port) _port2addr_usb(port)
static inline void *_port2addr(unsigned long port)
{
return (void *)(port | NONCACHE_OFFSET);
}
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static inline void *__port2addr_ata(unsigned long port)
+{
+ static int dummy_reg;
+
+ switch (port) {
+ case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
+ case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
+ case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
+ case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
+ case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
+ case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
+ case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
+ case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
+ case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
+ default: return (void *)&dummy_reg;
+ }
+}
+#endif
+
/*
* OPSPUT-LAN is located in the extended bus space
* from 0x10000000 to 0x13ffffff on physical address.
@@ -97,6 +117,12 @@ unsigned char _inb(unsigned long port)
{
if (port >= LAN_IOSTART && port < LAN_IOEND)
return _ne_inb(PORT2ADDR_NE(port));
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ return *(volatile unsigned char *)__port2addr_ata(port);
+ }
+#endif
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned char b;
@@ -112,6 +138,11 @@ unsigned short _inw(unsigned long port)
{
if (port >= LAN_IOSTART && port < LAN_IOEND)
return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ return *(volatile unsigned short *)__port2addr_ata(port);
+ }
+#endif
#if defined(CONFIG_USB)
else if(port >= 0x340 && port < 0x3a0)
return *(volatile unsigned short *)PORT2ADDR_USB(port);
@@ -164,6 +195,11 @@ void _outb(unsigned char b, unsigned long port)
if (port >= LAN_IOSTART && port < LAN_IOEND)
_ne_outb(b, PORT2ADDR_NE(port));
else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ *(volatile unsigned char *)__port2addr_ata(port) = b;
+ } else
+#endif
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
@@ -177,6 +213,11 @@ void _outw(unsigned short w, unsigned long port)
if (port >= LAN_IOSTART && port < LAN_IOEND)
_ne_outw(w, PORT2ADDR_NE(port));
else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ *(volatile unsigned short *)__port2addr_ata(port) = w;
+ } else
+#endif
#if defined(CONFIG_USB)
if(port >= 0x340 && port < 0x3a0)
*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
@@ -222,6 +263,14 @@ void _insb(unsigned int port, void *addr, unsigned long count)
{
if (port >= LAN_IOSTART && port < LAN_IOEND)
_ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ unsigned char *buf = addr;
+ unsigned char *portp = __port2addr_ata(port);
+ while (count--)
+ *buf++ = *(volatile unsigned char *)portp;
+ }
+#endif
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
@@ -254,6 +303,12 @@ void _insw(unsigned int port, void *addr, unsigned long count)
pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
count, 1);
#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+#endif
} else {
portp = PORT2ADDR(port);
while (count--)
@@ -280,6 +335,12 @@ void _outsb(unsigned int port, const void *addr, unsigned long count)
portp = PORT2ADDR_NE(port);
while (count--)
_ne_outb(*buf++, portp);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *(volatile unsigned char *)portp = *buf++;
+#endif
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
@@ -305,6 +366,12 @@ void _outsw(unsigned int port, const void *addr, unsigned long count)
portp = PORT2ADDR_NE(port);
while (count--)
*(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+#endif
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
index 61d3b01cbe0..62d6b71de45 100644
--- a/arch/m32r/kernel/setup_opsput.c
+++ b/arch/m32r/kernel/setup_opsput.c
@@ -218,13 +218,13 @@ static void shutdown_opsput_lanpld_irq(unsigned int irq)
static struct hw_interrupt_type opsput_lanpld_irq_type =
{
- "OPSPUT-PLD-LAN-IRQ",
- startup_opsput_lanpld_irq,
- shutdown_opsput_lanpld_irq,
- enable_opsput_lanpld_irq,
- disable_opsput_lanpld_irq,
- mask_and_ack_opsput_lanpld,
- end_opsput_lanpld_irq
+ .typename = "OPSPUT-PLD-LAN-IRQ",
+ .startup = startup_opsput_lanpld_irq,
+ .shutdown = shutdown_opsput_lanpld_irq,
+ .enable = enable_opsput_lanpld_irq,
+ .disable = disable_opsput_lanpld_irq,
+ .ack = mask_and_ack_opsput_lanpld,
+ .end = end_opsput_lanpld_irq
};
/*
@@ -374,7 +374,6 @@ void __init init_IRQ(void)
disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
#endif /* CONFIG_SERIAL_M32R_PLDSIO */
-#if defined(CONFIG_M32R_CFC)
/* INT#1: CFC IREQ on PLD */
irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
irq_desc[PLD_IRQ_CFIREQ].chip = &opsput_pld_irq_type;
@@ -398,8 +397,6 @@ void __init init_IRQ(void)
irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */
pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* 'H' edge sense */
disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
-#endif /* CONFIG_M32R_CFC */
-
/*
* INT0# is used for LAN, DIO
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index fa786560949..48d376f47e1 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -351,7 +351,7 @@ static void __init do_boot_cpu(int phys_id)
}
}
-int __devinit __cpu_up(unsigned int cpu_id)
+int __cpuinit __cpu_up(unsigned int cpu_id)
{
int timeout;
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
index 8d5f551b575..9b9feb0f161 100644
--- a/arch/m32r/mm/fault.c
+++ b/arch/m32r/mm/fault.c
@@ -173,7 +173,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
-#if 0
+
if (error_code & ACE_USERMODE) {
/*
* accessing the stack below "spu" is always a bug.
@@ -184,7 +184,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
if (address + 4 < regs->spu)
goto bad_area;
}
-#endif
+
if (expand_stack(vma, address))
goto bad_area;
/*
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 7bc14461a6a..70a577c89c7 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -17,6 +17,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_HWEIGHT
bool
default y
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index d64b5804e98..d01deb46ebb 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -174,7 +174,7 @@ int stdma_islocked(void)
void __init stdma_init(void)
{
stdma_isr = NULL;
- request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW,
+ request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | SA_SHIRQ,
"ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
}
diff --git a/arch/m68k/kernel/sun3-head.S b/arch/m68k/kernel/sun3-head.S
index bffd69a4a1a..4b5f050204e 100644
--- a/arch/m68k/kernel/sun3-head.S
+++ b/arch/m68k/kernel/sun3-head.S
@@ -67,16 +67,6 @@ ENTRY(_start)
1: lea init_task,%curptr | get initial thread...
lea init_thread_union+THREAD_SIZE,%sp | ...and its stack.
-/* copy bootinfo records from the loader to _end */
- lea _end, %a1
- lea BI_START, %a0
- /* number of longs to copy */
- movel %a0@, %d0
-1: addl #4, %a0
- movel %a0@, %a1@
- addl #4, %a1
- dbf %d0, 1b
-
/* Point MSP at an invalid page to trap if it's used. --m */
movl #(PAGESIZE),%d0
movc %d0,%msp
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 2550b4ae273..8c7eccbfc98 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -8,7 +8,7 @@ ENTRY(_start)
jiffies = jiffies_64 + 4;
SECTIONS
{
- . = 0xE004000;
+ . = 0xE002000;
_text = .; /* Text and read-only data */
.text : {
*(.head)
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index b54ef1726c5..46b7d6035aa 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -59,7 +59,7 @@ static struct vm_struct *get_io_area(unsigned long size)
unsigned long addr;
struct vm_struct **p, *tmp, *area;
- area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL);
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
addr = KMAP_START;
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 0f88812822b..13c0b4ad01e 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -299,7 +299,7 @@ void cache_clear (unsigned long paddr, int len)
mach_l2_flush(0);
#endif
}
-EXPORT_SYMBOL(cache_clear); /* probably can be unexported */
+EXPORT_SYMBOL(cache_clear);
/*
@@ -352,7 +352,7 @@ void cache_push (unsigned long paddr, int len)
mach_l2_flush(1);
#endif
}
-EXPORT_SYMBOL(cache_push); /* probably can be unexported */
+EXPORT_SYMBOL(cache_push);
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
int mm_end_of_chunk (unsigned long addr, int len)
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index ac6640ade0b..6a6513aa1ce 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -49,7 +49,6 @@ void __init paging_init(void)
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
unsigned long size;
-
#ifdef TEST_VERIFY_AREA
wp_works_ok = 0;
#endif
@@ -94,7 +93,11 @@ void __init paging_init(void)
/* memory sizing is a hack stolen from motorola.c.. hope it works for us */
zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
- free_area_init(zones_size);
+ /* I really wish I knew why the following change made things better... -- Sam */
+/* free_area_init(zones_size); */
+ free_area_init_node(0, NODE_DATA(0), zones_size,
+ (__pa(PAGE_OFFSET) >> PAGE_SHIFT) + 1, NULL);
+
}
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index aa70dde5422..25993c2a8fb 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d8af858fe3f..bbd386f572d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -165,6 +165,7 @@ config MIPS_COBALT
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select GENERIC_HARDIRQS_NO__DO_IRQ
config MACH_DECSTATION
bool "DECstations"
@@ -225,6 +226,7 @@ config MACH_JAZZ
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
select SYS_SUPPORTS_100HZ
+ select GENERIC_HARDIRQS_NO__DO_IRQ
help
This a family of machines based on the MIPS R4030 chipset which was
used by several vendors to build RISC/os and Windows NT workstations.
@@ -459,6 +461,11 @@ config PNX8550_JBS
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
+config PNX8550_STB810
+ bool "Support for Philips PNX8550 based STB810 board"
+ select PNX8550
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
config DDB5477
bool "NEC DDB Vrc-5477"
select DDB5XXX_COMMON
@@ -482,6 +489,7 @@ config MACH_VR41XX
select SYS_HAS_CPU_VR41XX
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+ select GENERIC_HARDIRQS_NO__DO_IRQ
config PMC_YOSEMITE
bool "PMC-Sierra Yosemite eval board"
@@ -515,6 +523,7 @@ config QEMU
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
select ARCH_SPARSEMEM_ENABLE
+ select GENERIC_HARDIRQS_NO__DO_IRQ
help
Qemu is a software emulator which among other architectures also
can simulate a MIPS32 4Kc system. This patch adds support for the
@@ -701,8 +710,8 @@ config SIBYTE_CRHONE
select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN
-config SNI_RM200_PCI
- bool "SNI RM200 PCI"
+config SNI_RM
+ bool "SNI RM200/300/400"
select ARC if CPU_LITTLE_ENDIAN
select ARC32 if CPU_LITTLE_ENDIAN
select ARCH_MAY_HAVE_PC_FDC
@@ -725,8 +734,8 @@ config SNI_RM200_PCI
select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN
help
- The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
- Nixdorf Informationssysteme (SNI), parent company of Pyramid
+ The SNI RM200/300/400 are MIPS-based machines manufactured by
+ Siemens Nixdorf Informationssysteme (SNI), parent company of Pyramid
Technology and now in turn merged with Fujitsu. Say Y here to
support this machine type.
@@ -754,6 +763,7 @@ config TOSHIBA_RBTX4927
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select TOSHIBA_BOARDS
+ select GENERIC_HARDIRQS_NO__DO_IRQ
help
This Toshiba board is based on the TX4927 processor. Say Y here to
support this machine type
@@ -773,6 +783,7 @@ config TOSHIBA_RBTX4938
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
select TOSHIBA_BOARDS
+ select GENERIC_HARDIRQS_NO__DO_IRQ
help
This Toshiba board is based on the TX4938 processor. Say Y here to
support this machine type
@@ -819,6 +830,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
@@ -1062,16 +1081,16 @@ config HAVE_STD_PC_SERIAL_PORT
config ARC_CONSOLE
bool "ARC console support"
- depends on SGI_IP22 || SNI_RM200_PCI
+ depends on SGI_IP22 || SNI_RM
config ARC_MEMORY
bool
- depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32
+ depends on MACH_JAZZ || SNI_RM || SGI_IP32
default y
config ARC_PROMLIB
bool
- depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
+ depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP32
default y
config ARC64
@@ -1549,6 +1568,20 @@ config MIPS_MT_FPAFF
depends on MIPS_MT
default y
+config MIPS_MT_SMTC_INSTANT_REPLAY
+ bool "Low-latency Dispatch of Deferred SMTC IPIs"
+ depends on MIPS_MT_SMTC
+ default y
+ help
+ SMTC pseudo-interrupts between TCs are deferred and queued
+ if the target TC is interrupt-inhibited (IXMT). In the first
+ SMTC prototypes, these queued IPIs were serviced on return
+ to user mode, or on entry into the kernel idle loop. The
+ INSTANT_REPLAY option dispatches them as part of local_irq_restore()
+ processing, which adds runtime overhead (hence the option to turn
+ it off), but ensures that IPIs are handled promptly even under
+ heavy I/O interrupt load.
+
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
depends on MIPS_VPE_LOADER
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 641aa30b363..c68b5d3e5d1 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -463,6 +463,11 @@ libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/
#cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550
load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000
+# Philips PNX8550 STB810 board
+#
+libs-$(CONFIG_PNX8550_STB810) += arch/mips/philips/pnx8550/stb810/
+load-$(CONFIG_PNX8550_STB810) += 0xffffffff80060000
+
# NEC EMMA2RH boards
#
core-$(CONFIG_EMMA2RH) += arch/mips/emma2rh/common/
@@ -569,11 +574,11 @@ libs-$(CONFIG_SIBYTE_BIGSUR) += arch/mips/sibyte/swarm/
load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
#
-# SNI RM200 PCI
+# SNI RM
#
-core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/
-cflags-$(CONFIG_SNI_RM200_PCI) += -Iinclude/asm-mips/mach-rm200
-load-$(CONFIG_SNI_RM200_PCI) += 0xffffffff80600000
+core-$(CONFIG_SNI_RM) += arch/mips/sni/
+cflags-$(CONFIG_SNI_RM) += -Iinclude/asm-mips/mach-rm
+load-$(CONFIG_SNI_RM) += 0xffffffff80600000
#
# Toshiba JMR-TX3927 board
@@ -618,7 +623,7 @@ LDFLAGS += -m $(ld-emul)
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \
- egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \
+ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
ifdef CONFIG_64BIT
CHECKFLAGS += -m64
@@ -695,7 +700,7 @@ ifdef CONFIG_QEMU
all: vmlinux.bin
endif
-ifdef CONFIG_SNI_RM200_PCI
+ifdef CONFIG_SNI_RM
all: vmlinux.ecoff
endif
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
index da591f67489..9f8ce08e173 100644
--- a/arch/mips/au1000/common/pci.c
+++ b/arch/mips/au1000/common/pci.c
@@ -39,15 +39,15 @@
/* TBD */
static struct resource pci_io_resource = {
- .start = PCI_IO_START,
- .end = PCI_IO_END,
+ .start = (resource_size_t)PCI_IO_START,
+ .end = (resource_size_t)PCI_IO_END,
.name = "PCI IO space",
.flags = IORESOURCE_IO
};
static struct resource pci_mem_resource = {
- .start = PCI_MEM_START,
- .end = PCI_MEM_END,
+ .start = (resource_size_t)PCI_MEM_START,
+ .end = (resource_size_t)PCI_MEM_END,
.name = "PCI memory space",
.flags = IORESOURCE_MEM
};
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 35931bedc3d..ac189168752 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index ba3bf733d27..9554257c6f3 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -57,7 +57,7 @@ CONFIG_SIBYTE_BIGSUR=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index e5358121d2d..49590d44371 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index adf1e8c98c6..0607fc23908 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_COBALT=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 4fd29ffdfb8..1a57b337548 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1000=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 025b960ba99..0055ec41f20 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1100=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 80c9dd98f89..c41823b81be 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1200=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 6caa90b0e17..7d6d9218788 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1500=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index c6cae86c6ab..c681c91763a 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_DB1550=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 72f24001c99..dd4bb008021 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -59,7 +59,7 @@ CONFIG_DDB5477=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index fe1387eb83c..8a31ce4be12 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_DECSTATION=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 6133c28beb8..6fa4f914f6e 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index a484b7d396f..4c9d0405a5d 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -59,7 +59,7 @@ CONFIG_MARKEINS=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index 21bfcdebf8f..d5b49735683 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_EV64120=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 1a5b06cfb4d..697140c6562 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -60,7 +60,7 @@ CONFIG_BASLER_EXCITE=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 21d53e0c9ee..f9812d1e457 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -59,7 +59,7 @@ CONFIG_SGI_IP22=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index e3e94c7e5ee..96090f28373 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -59,7 +59,7 @@ CONFIG_SGI_IP27=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index b4ab2bea972..61e069a0f1a 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -59,7 +59,7 @@ CONFIG_SGI_IP32=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 9d4d17ace12..88966666f4c 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_JAGUAR_ATX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 382083ebea0..835764d834f 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -57,7 +57,7 @@ CONFIG_MACH_JAZZ=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index d03746667a9..50fd9557e64 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
CONFIG_TOSHIBA_JMR3927=y
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index 1db8249b4c0..05f539f84f5 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -59,7 +59,7 @@ CONFIG_LASAT=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 101e80347dc..96e941084c0 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -57,7 +57,7 @@ CONFIG_MIPS_MALTA=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
@@ -644,7 +644,85 @@ CONFIG_CONNECTOR=m
#
# Memory Technology Devices (MTD)
#
-# CONFIG_MTD is not set
+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
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+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=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
#
# Parallel port support
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index a3cbd23bf21..03efcfd0503 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_SIM=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 6570b47426c..e4221aafbc4 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 440d65f93a9..32b1afdd1c2 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT_3=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index c2c7ae77da3..ebe75c1c71a 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT_C=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 67efe270e0c..5a9603c1290 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index a10f34de5f7..46a942c253c 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -59,7 +59,7 @@ CONFIG_MOMENCO_OCELOT_G=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 9e672f63a0a..7d3c688181d 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_PB1100=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index d0c0f4af1bf..a77805af081 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_PB1500=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 3db7427d1b5..8318d74d6ad 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_PB1550=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index 280a8001eac..fcb8fea3052 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -57,7 +57,7 @@ CONFIG_PNX8550_JBS=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
new file mode 100644
index 00000000000..f38a2c12303
--- /dev/null
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -0,0 +1,1229 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19
+# Thu Dec 7 16:35:12 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+CONFIG_PNX8550_STB810=y
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_KEXEC is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_PNX8550=y
+CONFIG_SOC_PNX8550=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# 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_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=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=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_PNX8XXX is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# 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_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
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=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_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII 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_ADUTUX 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_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=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_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=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_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+CONFIG_HEADERS_CHECK=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
+# 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_ECB=m
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_PLIST=y
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index 64b9fbf44a6..5bc3248e50e 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -57,7 +57,7 @@ CONFIG_PNX8550_V2PCI=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 9b0dab822bd..aa61f0f030a 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -59,7 +59,7 @@ CONFIG_QEMU=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index dd029603602..f9e8f41d17f 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
CONFIG_TOSHIBA_RBTX4938=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index d8a498d64d6..496aa67b9f8 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-CONFIG_SNI_RM200_PCI=y
+CONFIG_SNI_RM=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 805a4fe450f..e33c17200b3 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -59,7 +59,7 @@ CONFIG_SIBYTE_SWARM=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 6fcb656d8d8..83fb932f9d4 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -59,7 +59,7 @@ CONFIG_MIPS_SEAD=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index dc312f19ada..e9d4eae45bf 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index 85615d99b01..c19597fb0c3 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index f7e8194809a..97d94f96990 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -57,7 +57,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 863f6a7cadf..553734a47b6 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -59,7 +59,7 @@ CONFIG_MACH_VR41XX=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index c10267d61cc..d3dfb702bb7 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -59,7 +59,7 @@ CONFIG_WR_PPMC=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 4d3c1329f3c..b9f74d6745e 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -59,7 +59,7 @@ CONFIG_PMC_YOSEMITE=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
index 3027ce78279..3aa01d268f2 100644
--- a/arch/mips/dec/prom/memory.c
+++ b/arch/mips/dec/prom/memory.c
@@ -122,7 +122,7 @@ unsigned long __init prom_free_prom_memory(void)
addr += PAGE_SIZE;
}
- printk("Freeing unused PROM memory: %ldk freed\n",
+ printk("Freeing unused PROM memory: %ldkb freed\n",
(end - PAGE_SIZE) >> 10);
return end - PAGE_SIZE;
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 21d53e0c9ee..f9812d1e457 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -59,7 +59,7 @@ CONFIG_SGI_IP22=y
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
index 528e731049c..ba16d07588c 100644
--- a/arch/mips/kernel/apm.c
+++ b/arch/mips/kernel/apm.c
@@ -356,7 +356,7 @@ static int apm_open(struct inode * inode, struct file * filp)
{
struct apm_user *as;
- as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
* XXX - this is a tiny bit broken, when we consider BSD
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index a2e095adaa3..9a7811d13db 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -138,7 +138,7 @@
EXPORT(stext) # used for profiling
EXPORT(_stext)
-#if defined(CONFIG_QEMU) || defined(CONFIG_MIPS_SIM)
+#ifdef CONFIG_MIPS_SIM
/*
* Give us a fighting chance of running if execution beings at the
* kernel load address. This is needed because this platform does
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 1bbefbf4337..37cad5de515 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -1145,7 +1145,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
psinfo.pr_pid = prstatus.pr_pid = current->pid;
psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current);
- psinfo.pr_sid = prstatus.pr_sid = current->signal->session;
+ psinfo.pr_sid = prstatus.pr_sid = process_session(current);
if (current->pid == current->tgid) {
/*
* This is the record for the group leader. Add in the
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index 2c82412b9ef..5929f883e46 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -301,7 +301,7 @@ static void sp_cleanup(void)
for (;;) {
unsigned long set;
i = j * __NFDBITS;
- if (i >= fdt->max_fdset || i >= fdt->max_fds)
+ if (i >= fdt->max_fds)
break;
set = fdt->open_fds->fds_bits[j++];
while (set) {
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index b061c9aa630..de3fae260ff 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -440,14 +440,26 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
}
#ifdef CONFIG_MIPS32_N32
-asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, union semun arg)
+asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
{
/* compat_sys_semctl expects a pointer to union semun */
u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
- if (put_user(ptr_to_compat(arg.__pad), uptr))
+ if (put_user(arg, uptr))
return -EFAULT;
return compat_sys_semctl(semid, semnum, cmd, uptr);
}
+
+asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
+{
+ return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
+}
+
+asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
+ int msgflg)
+{
+ return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
+ compat_ptr(msgp));
+}
#endif
struct sysctl_args32
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index f44a01357ad..2ef857c3ee5 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -46,5 +46,7 @@ EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+EXPORT_SYMBOL(__csum_partial_copy_user);
EXPORT_SYMBOL(invalid_pte_table);
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 621037db229..060563a712b 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -23,6 +23,8 @@ void (*_machine_restart)(char *command);
void (*_machine_halt)(void);
void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
void machine_restart(char *command)
{
if (_machine_restart)
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 8c8c8324f77..5a99e3e0c96 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -415,7 +415,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
int minor;
unsigned int mask = 0;
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
poll_wait(file, &channel_wqs[minor].rt_queue, wait);
poll_wait(file, &channel_wqs[minor].lx_queue, wait);
@@ -437,7 +437,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait)
static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
loff_t * ppos)
{
- int minor = iminor(file->f_dentry->d_inode);
+ int minor = iminor(file->f_path.dentry->d_inode);
/* data available? */
if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
@@ -454,7 +454,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
struct rtlx_channel *rt;
DECLARE_WAITQUEUE(wait, current);
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
rt = &rtlx->channel[minor];
/* any space left... */
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 34567d81f94..a7bff2a5472 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -187,8 +187,8 @@ EXPORT(sysn32_call_table)
PTR sysn32_semctl
PTR sys_shmdt /* 6065 */
PTR sys_msgget
- PTR compat_sys_msgsnd
- PTR compat_sys_msgrcv
+ PTR sysn32_msgsnd
+ PTR sysn32_msgrcv
PTR compat_sys_msgctl
PTR compat_sys_fcntl /* 6070 */
PTR sys_flock
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index f2a8701e414..0555fc554f6 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -271,7 +271,7 @@ void __devinit smp_prepare_boot_cpu(void)
* and keep control until "cpu_online(cpu)" is set. Note: cpu is
* physical, not logical.
*/
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 802febed7df..6a857bf030b 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -4,6 +4,7 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/cpu.h>
#include <asm/processor.h>
@@ -261,6 +262,7 @@ void smtc_configure_tlb(void)
}
}
write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
+ ehb();
/*
* Setup kernel data structures to use software total,
@@ -269,9 +271,12 @@ void smtc_configure_tlb(void)
* of their initialization in smtc_cpu_setup().
*/
- tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */
- cpu_data[0].tlbsize = tlbsiz;
+ /* MIPS32 limits TLB indices to 64 */
+ if (tlbsiz > 64)
+ tlbsiz = 64;
+ cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz;
smtc_status |= SMTC_TLB_SHARED;
+ local_flush_tlb_all();
printk("TLB of %d entry pairs shared by %d VPEs\n",
tlbsiz, vpes);
@@ -1016,6 +1021,35 @@ void setup_cross_vpe_interrupts(void)
* SMTC-specific hacks invoked from elsewhere in the kernel.
*/
+void smtc_ipi_replay(void)
+{
+ /*
+ * To the extent that we've ever turned interrupts off,
+ * we may have accumulated deferred IPIs. This is subtle.
+ * If we use the smtc_ipi_qdepth() macro, we'll get an
+ * exact number - but we'll also disable interrupts
+ * and create a window of failure where a new IPI gets
+ * queued after we test the depth but before we re-enable
+ * interrupts. So long as IXMT never gets set, however,
+ * we should be OK: If we pick up something and dispatch
+ * it here, that's great. If we see nothing, but concurrent
+ * with this operation, another TC sends us an IPI, IXMT
+ * is clear, and we'll handle it as a real pseudo-interrupt
+ * and not a pseudo-pseudo interrupt.
+ */
+ if (IPIQ[smp_processor_id()].depth > 0) {
+ struct smtc_ipi *pipi;
+ extern void self_ipi(struct smtc_ipi *);
+
+ while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) {
+ self_ipi(pipi);
+ smtc_cpu_stats[smp_processor_id()].selfipis++;
+ }
+ }
+}
+
+EXPORT_SYMBOL(smtc_ipi_replay);
+
void smtc_idle_loop_hook(void)
{
#ifdef SMTC_IDLE_HOOK_DEBUG
@@ -1112,29 +1146,14 @@ void smtc_idle_loop_hook(void)
if (pdb_msg != &id_ho_db_msg[0])
printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
#endif /* SMTC_IDLE_HOOK_DEBUG */
+
/*
- * To the extent that we've ever turned interrupts off,
- * we may have accumulated deferred IPIs. This is subtle.
- * If we use the smtc_ipi_qdepth() macro, we'll get an
- * exact number - but we'll also disable interrupts
- * and create a window of failure where a new IPI gets
- * queued after we test the depth but before we re-enable
- * interrupts. So long as IXMT never gets set, however,
- * we should be OK: If we pick up something and dispatch
- * it here, that's great. If we see nothing, but concurrent
- * with this operation, another TC sends us an IPI, IXMT
- * is clear, and we'll handle it as a real pseudo-interrupt
- * and not a pseudo-pseudo interrupt.
+ * Replay any accumulated deferred IPIs. If "Instant Replay"
+ * is in use, there should never be any.
*/
- if (IPIQ[smp_processor_id()].depth > 0) {
- struct smtc_ipi *pipi;
- extern void self_ipi(struct smtc_ipi *);
-
- if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
- self_ipi(pipi);
- smtc_cpu_stats[smp_processor_id()].selfipis++;
- }
- }
+#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
+ smtc_ipi_replay();
+#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
}
void smtc_soft_dump(void)
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 93c74fefff7..6c2406a93f2 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf)
goto out;
}
- error = vfs_statfs(file->f_dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, &kbuf);
if (error)
goto out_f;
@@ -1041,7 +1041,7 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
unsigned long old_pos;
long max_size = offset + len;
- if (max_size > file->f_dentry->d_inode->i_size) {
+ if (max_size > file->f_path.dentry->d_inode->i_size) {
old_pos = sys_lseek (fd, max_size - 1, 0);
sys_write (fd, (void __user *) "", 1);
sys_lseek (fd, old_pos, 0);
@@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf)
error = -EBADF;
goto out;
}
- error = vfs_statfs(file->f_dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, &kbuf);
if (error)
goto out_f;
@@ -1526,7 +1526,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
unsigned long old_pos;
long max_size = off2 + len;
- if (max_size > file->f_dentry->d_inode->i_size) {
+ if (max_size > file->f_path.dentry->d_inode->i_size) {
old_pos = sys_lseek (fd, max_size - 1, 0);
sys_write (fd, (void __user *) "", 1);
sys_lseek (fd, old_pos, 0);
@@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf)
error = -EBADF;
goto out;
}
- error = vfs_statfs(file->f_dentry, &kbuf);
+ error = vfs_statfs(file->f_path.dentry, &kbuf);
if (error)
goto out_f;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 11aab6d6bfe..8aa544f73a5 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -94,10 +94,8 @@ static void c0_timer_ack(void)
{
unsigned int count;
-#ifndef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
/* Ack this timer interrupt and set the next one. */
expirelo += cycles_per_jiffy;
-#endif
write_c0_compare(expirelo);
/* Check to see if we have missed any timer interrupts. */
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 79f0317d84a..cecff24cc97 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -112,6 +112,7 @@ SECTIONS
/* .exit.text is discarded at runtime, not link time, to deal with
references from .rodata */
.exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
. = ALIGN(_PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
@@ -139,7 +140,6 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.data)
*(.exitcall.exit)
/* ABI crap starts here */
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 51ddd216689..458fccf87c5 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -139,13 +139,16 @@ struct tc {
struct list_head list;
};
-struct vpecontrol_ {
+struct {
/* Virtual processing elements */
struct list_head vpe_list;
/* Thread contexts */
struct list_head tc_list;
-} vpecontrol;
+} vpecontrol = {
+ .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list),
+ .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list)
+};
static void release_progmem(void *ptr);
/* static __attribute_used__ void dump_vpe(struct vpe * v); */
@@ -1179,7 +1182,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
size_t ret = count;
struct vpe *v;
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
if ((v = get_vpe(minor)) == NULL)
return -ENODEV;
@@ -1388,8 +1391,6 @@ static int __init vpe_module_init(void)
/* dump_mtregs(); */
- INIT_LIST_HEAD(&vpecontrol.vpe_list);
- INIT_LIST_HEAD(&vpecontrol.tc_list);
val = read_c0_mvpconf0();
for (i = 0; i < ((val & MVPCONF0_PTC) + 1); i++) {
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 6dd7ae1b7c2..12878359f2c 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -40,12 +40,12 @@ static DEFINE_MUTEX(lasat_info_mutex);
/* Strategy function to write EEPROM after changing string entry */
int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
+ void *newval, size_t newlen)
{
int r;
mutex_lock(&lasat_info_mutex);
r = sysctl_string(table, name,
- nlen, oldval, oldlenp, newval, newlen, context);
+ nlen, oldval, oldlenp, newval, newlen);
if (r < 0) {
mutex_unlock(&lasat_info_mutex);
return r;
@@ -119,11 +119,11 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
/* Sysctl for setting the IP addresses */
int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
+ void *newval, size_t newlen)
{
int r;
mutex_lock(&lasat_info_mutex);
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+ r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
if (r < 0) {
mutex_unlock(&lasat_info_mutex);
return r;
@@ -139,14 +139,14 @@ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
/* Same for RTC */
int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
+ void *newval, size_t newlen)
{
int r;
mutex_lock(&lasat_info_mutex);
rtctmp = ds1603_read();
if (rtctmp < 0)
rtctmp = 0;
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+ r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
if (r < 0) {
mutex_unlock(&lasat_info_mutex);
return r;
@@ -251,13 +251,12 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
- void *newval, size_t newlen,
- void **context)
+ void *newval, size_t newlen)
{
int r;
mutex_lock(&lasat_info_mutex);
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+ r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
if (r < 0) {
mutex_unlock(&lasat_info_mutex);
return r;
@@ -286,11 +285,11 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
mutex_unlock(&lasat_info_mutex);
return r;
}
- if (filp && filp->f_dentry)
+ if (filp && filp->f_path.dentry)
{
- if (!strcmp(filp->f_dentry->d_name.name, "prid"))
+ if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
- if (!strcmp(filp->f_dentry->d_name.name, "debugaccess"))
+ if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
}
lasat_write_eeprom_info();
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 888b61ea12f..989c900b8b1 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,7 +2,7 @@
# Makefile for MIPS-specific library files..
#
-lib-y += csum_partial.o csum_partial_copy.o memcpy.o promlib.o \
+lib-y += csum_partial.o memcpy.o promlib.o \
strlen_user.o strncpy_user.o strnlen_user.o uncached.o
obj-y += iomap.o
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S
index 15611d9df7a..c0a77fe038b 100644
--- a/arch/mips/lib/csum_partial.S
+++ b/arch/mips/lib/csum_partial.S
@@ -8,47 +8,72 @@
* Copyright (C) 1998, 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
+#include <linux/errno.h>
#include <asm/asm.h>
+#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#ifdef CONFIG_64BIT
-#define T0 ta0
-#define T1 ta1
-#define T2 ta2
-#define T3 ta3
-#define T4 t0
-#define T7 t3
-#else
-#define T0 t0
-#define T1 t1
-#define T2 t2
-#define T3 t3
-#define T4 t4
-#define T7 t7
+/*
+ * As we are sharing code base with the mips32 tree (which use the o32 ABI
+ * register definitions). We need to redefine the register definitions from
+ * the n64 ABI register naming to the o32 ABI register naming.
+ */
+#undef t0
+#undef t1
+#undef t2
+#undef t3
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+
+#define USE_DOUBLE
#endif
+#ifdef USE_DOUBLE
+
+#define LOAD ld
+#define ADD daddu
+#define NBYTES 8
+
+#else
+
+#define LOAD lw
+#define ADD addu
+#define NBYTES 4
+
+#endif /* USE_DOUBLE */
+
+#define UNIT(unit) ((unit)*NBYTES)
+
#define ADDC(sum,reg) \
- addu sum, reg; \
+ ADD sum, reg; \
sltu v1, sum, reg; \
- addu sum, v1
+ ADD sum, v1
-#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
- lw _t0, (offset + 0x00)(src); \
- lw _t1, (offset + 0x04)(src); \
- lw _t2, (offset + 0x08)(src); \
- lw _t3, (offset + 0x0c)(src); \
+#define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \
+ LOAD _t0, (offset + UNIT(0))(src); \
+ LOAD _t1, (offset + UNIT(1))(src); \
+ LOAD _t2, (offset + UNIT(2))(src); \
+ LOAD _t3, (offset + UNIT(3))(src); \
ADDC(sum, _t0); \
ADDC(sum, _t1); \
ADDC(sum, _t2); \
- ADDC(sum, _t3); \
- lw _t0, (offset + 0x10)(src); \
- lw _t1, (offset + 0x14)(src); \
- lw _t2, (offset + 0x18)(src); \
- lw _t3, (offset + 0x1c)(src); \
- ADDC(sum, _t0); \
- ADDC(sum, _t1); \
- ADDC(sum, _t2); \
- ADDC(sum, _t3); \
+ ADDC(sum, _t3)
+
+#ifdef USE_DOUBLE
+#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
+ CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)
+#else
+#define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \
+ CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3); \
+ CSUM_BIGCHUNK1(src, offset + 0x10, sum, _t0, _t1, _t2, _t3)
+#endif
/*
* a0: source address
@@ -61,86 +86,27 @@
.text
.set noreorder
-
-/* unknown src alignment and < 8 bytes to go */
-small_csumcpy:
- move a1, T2
-
- andi T0, a1, 4
- beqz T0, 1f
- andi T0, a1, 2
-
- /* Still a full word to go */
- ulw T1, (src)
- PTR_ADDIU src, 4
- ADDC(sum, T1)
-
-1: move T1, zero
- beqz T0, 1f
- andi T0, a1, 1
-
- /* Still a halfword to go */
- ulhu T1, (src)
- PTR_ADDIU src, 2
-
-1: beqz T0, 1f
- sll T1, T1, 16
-
- lbu T2, (src)
- nop
-
-#ifdef __MIPSEB__
- sll T2, T2, 8
-#endif
- or T1, T2
-
-1: ADDC(sum, T1)
-
- /* fold checksum */
- sll v1, sum, 16
- addu sum, v1
- sltu v1, sum, v1
- srl sum, sum, 16
- addu sum, v1
-
- /* odd buffer alignment? */
- beqz T7, 1f
- nop
- sll v1, sum, 8
- srl sum, sum, 8
- or sum, v1
- andi sum, 0xffff
-1:
- .set reorder
- /* Add the passed partial csum. */
- ADDC(sum, a2)
- jr ra
- .set noreorder
-
-/* ------------------------------------------------------------------------- */
-
.align 5
LEAF(csum_partial)
move sum, zero
- move T7, zero
+ move t7, zero
sltiu t8, a1, 0x8
bnez t8, small_csumcpy /* < 8 bytes to copy */
- move T2, a1
+ move t2, a1
- beqz a1, out
- andi T7, src, 0x1 /* odd buffer? */
+ andi t7, src, 0x1 /* odd buffer? */
hword_align:
- beqz T7, word_align
+ beqz t7, word_align
andi t8, src, 0x2
- lbu T0, (src)
+ lbu t0, (src)
LONG_SUBU a1, a1, 0x1
#ifdef __MIPSEL__
- sll T0, T0, 8
+ sll t0, t0, 8
#endif
- ADDC(sum, T0)
+ ADDC(sum, t0)
PTR_ADDU src, src, 0x1
andi t8, src, 0x2
@@ -148,9 +114,9 @@ word_align:
beqz t8, dword_align
sltiu t8, a1, 56
- lhu T0, (src)
+ lhu t0, (src)
LONG_SUBU a1, a1, 0x2
- ADDC(sum, T0)
+ ADDC(sum, t0)
sltiu t8, a1, 56
PTR_ADDU src, src, 0x2
@@ -162,9 +128,9 @@ dword_align:
beqz t8, qword_align
andi t8, src, 0x8
- lw T0, 0x00(src)
+ lw t0, 0x00(src)
LONG_SUBU a1, a1, 0x4
- ADDC(sum, T0)
+ ADDC(sum, t0)
PTR_ADDU src, src, 0x4
andi t8, src, 0x8
@@ -172,11 +138,17 @@ qword_align:
beqz t8, oword_align
andi t8, src, 0x10
- lw T0, 0x00(src)
- lw T1, 0x04(src)
+#ifdef USE_DOUBLE
+ ld t0, 0x00(src)
LONG_SUBU a1, a1, 0x8
- ADDC(sum, T0)
- ADDC(sum, T1)
+ ADDC(sum, t0)
+#else
+ lw t0, 0x00(src)
+ lw t1, 0x04(src)
+ LONG_SUBU a1, a1, 0x8
+ ADDC(sum, t0)
+ ADDC(sum, t1)
+#endif
PTR_ADDU src, src, 0x8
andi t8, src, 0x10
@@ -184,75 +156,560 @@ oword_align:
beqz t8, begin_movement
LONG_SRL t8, a1, 0x7
- lw T3, 0x08(src)
- lw T4, 0x0c(src)
- lw T0, 0x00(src)
- lw T1, 0x04(src)
- ADDC(sum, T3)
- ADDC(sum, T4)
- ADDC(sum, T0)
- ADDC(sum, T1)
+#ifdef USE_DOUBLE
+ ld t0, 0x00(src)
+ ld t1, 0x08(src)
+ ADDC(sum, t0)
+ ADDC(sum, t1)
+#else
+ CSUM_BIGCHUNK1(src, 0x00, sum, t0, t1, t3, t4)
+#endif
LONG_SUBU a1, a1, 0x10
PTR_ADDU src, src, 0x10
LONG_SRL t8, a1, 0x7
begin_movement:
beqz t8, 1f
- andi T2, a1, 0x40
+ andi t2, a1, 0x40
move_128bytes:
- CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
- CSUM_BIGCHUNK(src, 0x20, sum, T0, T1, T3, T4)
- CSUM_BIGCHUNK(src, 0x40, sum, T0, T1, T3, T4)
- CSUM_BIGCHUNK(src, 0x60, sum, T0, T1, T3, T4)
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
LONG_SUBU t8, t8, 0x01
bnez t8, move_128bytes
PTR_ADDU src, src, 0x80
1:
- beqz T2, 1f
- andi T2, a1, 0x20
+ beqz t2, 1f
+ andi t2, a1, 0x20
move_64bytes:
- CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
- CSUM_BIGCHUNK(src, 0x20, sum, T0, T1, T3, T4)
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
PTR_ADDU src, src, 0x40
1:
- beqz T2, do_end_words
+ beqz t2, do_end_words
andi t8, a1, 0x1c
move_32bytes:
- CSUM_BIGCHUNK(src, 0x00, sum, T0, T1, T3, T4)
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
andi t8, a1, 0x1c
PTR_ADDU src, src, 0x20
do_end_words:
- beqz t8, maybe_end_cruft
- LONG_SRL t8, t8, 0x2
+ beqz t8, small_csumcpy
+ andi t2, a1, 0x3
+ LONG_SRL t8, t8, 0x2
end_words:
- lw T0, (src)
+ lw t0, (src)
LONG_SUBU t8, t8, 0x1
- ADDC(sum, T0)
+ ADDC(sum, t0)
bnez t8, end_words
PTR_ADDU src, src, 0x4
-maybe_end_cruft:
- andi T2, a1, 0x3
+/* unknown src alignment and < 8 bytes to go */
+small_csumcpy:
+ move a1, t2
-small_memcpy:
- j small_csumcpy; move a1, T2 /* XXX ??? */
- beqz t2, out
- move a1, T2
+ andi t0, a1, 4
+ beqz t0, 1f
+ andi t0, a1, 2
-end_bytes:
- lb T0, (src)
- LONG_SUBU a1, a1, 0x1
- bnez a2, end_bytes
- PTR_ADDU src, src, 0x1
+ /* Still a full word to go */
+ ulw t1, (src)
+ PTR_ADDIU src, 4
+ ADDC(sum, t1)
+
+1: move t1, zero
+ beqz t0, 1f
+ andi t0, a1, 1
+
+ /* Still a halfword to go */
+ ulhu t1, (src)
+ PTR_ADDIU src, 2
-out:
+1: beqz t0, 1f
+ sll t1, t1, 16
+
+ lbu t2, (src)
+ nop
+
+#ifdef __MIPSEB__
+ sll t2, t2, 8
+#endif
+ or t1, t2
+
+1: ADDC(sum, t1)
+
+ /* fold checksum */
+#ifdef USE_DOUBLE
+ dsll32 v1, sum, 0
+ daddu sum, v1
+ sltu v1, sum, v1
+ dsra32 sum, sum, 0
+ addu sum, v1
+#endif
+ sll v1, sum, 16
+ addu sum, v1
+ sltu v1, sum, v1
+ srl sum, sum, 16
+ addu sum, v1
+
+ /* odd buffer alignment? */
+ beqz t7, 1f
+ nop
+ sll v1, sum, 8
+ srl sum, sum, 8
+ or sum, v1
+ andi sum, 0xffff
+1:
+ .set reorder
+ /* Add the passed partial csum. */
+ ADDC(sum, a2)
jr ra
- move v0, sum
+ .set noreorder
END(csum_partial)
+
+
+/*
+ * checksum and copy routines based on memcpy.S
+ *
+ * csum_partial_copy_nocheck(src, dst, len, sum)
+ * __csum_partial_copy_user(src, dst, len, sum, errp)
+ *
+ * See "Spec" in memcpy.S for details. Unlike __copy_user, all
+ * function in this file use the standard calling convention.
+ */
+
+#define src a0
+#define dst a1
+#define len a2
+#define psum a3
+#define sum v0
+#define odd t8
+#define errptr t9
+
+/*
+ * The exception handler for loads requires that:
+ * 1- AT contain the address of the byte just past the end of the source
+ * of the copy,
+ * 2- src_entry <= src < AT, and
+ * 3- (dst - src) == (dst_entry - src_entry),
+ * The _entry suffix denotes values when __copy_user was called.
+ *
+ * (1) is set up up by __csum_partial_copy_from_user and maintained by
+ * not writing AT in __csum_partial_copy
+ * (2) is met by incrementing src by the number of bytes copied
+ * (3) is met by not doing loads between a pair of increments of dst and src
+ *
+ * The exception handlers for stores stores -EFAULT to errptr and return.
+ * These handlers do not need to overwrite any data.
+ */
+
+#define EXC(inst_reg,addr,handler) \
+9: inst_reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+#ifdef USE_DOUBLE
+
+#define LOAD ld
+#define LOADL ldl
+#define LOADR ldr
+#define STOREL sdl
+#define STORER sdr
+#define STORE sd
+#define ADD daddu
+#define SUB dsubu
+#define SRL dsrl
+#define SLL dsll
+#define SLLV dsllv
+#define SRLV dsrlv
+#define NBYTES 8
+#define LOG_NBYTES 3
+
+#else
+
+#define LOAD lw
+#define LOADL lwl
+#define LOADR lwr
+#define STOREL swl
+#define STORER swr
+#define STORE sw
+#define ADD addu
+#define SUB subu
+#define SRL srl
+#define SLL sll
+#define SLLV sllv
+#define SRLV srlv
+#define NBYTES 4
+#define LOG_NBYTES 2
+
+#endif /* USE_DOUBLE */
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LDFIRST LOADR
+#define LDREST LOADL
+#define STFIRST STORER
+#define STREST STOREL
+#define SHIFT_DISCARD SLLV
+#define SHIFT_DISCARD_REVERT SRLV
+#else
+#define LDFIRST LOADL
+#define LDREST LOADR
+#define STFIRST STOREL
+#define STREST STORER
+#define SHIFT_DISCARD SRLV
+#define SHIFT_DISCARD_REVERT SLLV
+#endif
+
+#define FIRST(unit) ((unit)*NBYTES)
+#define REST(unit) (FIRST(unit)+NBYTES-1)
+
+#define ADDRMASK (NBYTES-1)
+
+ .set noat
+
+LEAF(__csum_partial_copy_user)
+ PTR_ADDU AT, src, len /* See (1) above. */
+#ifdef CONFIG_64BIT
+ move errptr, a4
+#else
+ lw errptr, 16(sp)
+#endif
+FEXPORT(csum_partial_copy_nocheck)
+ move sum, zero
+ move odd, zero
+ /*
+ * Note: dst & src may be unaligned, len may be 0
+ * Temps
+ */
+ /*
+ * The "issue break"s below are very approximate.
+ * Issue delays for dcache fills will perturb the schedule, as will
+ * load queue full replay traps, etc.
+ *
+ * If len < NBYTES use byte operations.
+ */
+ sltu t2, len, NBYTES
+ and t1, dst, ADDRMASK
+ bnez t2, copy_bytes_checklen
+ and t0, src, ADDRMASK
+ andi odd, dst, 0x1 /* odd buffer? */
+ bnez t1, dst_unaligned
+ nop
+ bnez t0, src_unaligned_dst_aligned
+ /*
+ * use delay slot for fall-through
+ * src and dst are aligned; need to compute rem
+ */
+both_aligned:
+ SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
+ beqz t0, cleanup_both_aligned # len < 8*NBYTES
+ nop
+ SUB len, 8*NBYTES # subtract here for bgez loop
+ .align 4
+1:
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+EXC( LOAD t4, UNIT(4)(src), l_exc_copy)
+EXC( LOAD t5, UNIT(5)(src), l_exc_copy)
+EXC( LOAD t6, UNIT(6)(src), l_exc_copy)
+EXC( LOAD t7, UNIT(7)(src), l_exc_copy)
+ SUB len, len, 8*NBYTES
+ ADD src, src, 8*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc)
+ ADDC(sum, t0)
+EXC( STORE t1, UNIT(1)(dst), s_exc)
+ ADDC(sum, t1)
+EXC( STORE t2, UNIT(2)(dst), s_exc)
+ ADDC(sum, t2)
+EXC( STORE t3, UNIT(3)(dst), s_exc)
+ ADDC(sum, t3)
+EXC( STORE t4, UNIT(4)(dst), s_exc)
+ ADDC(sum, t4)
+EXC( STORE t5, UNIT(5)(dst), s_exc)
+ ADDC(sum, t5)
+EXC( STORE t6, UNIT(6)(dst), s_exc)
+ ADDC(sum, t6)
+EXC( STORE t7, UNIT(7)(dst), s_exc)
+ ADDC(sum, t7)
+ bgez len, 1b
+ ADD dst, dst, 8*NBYTES
+ ADD len, 8*NBYTES # revert len (see above)
+
+ /*
+ * len == the number of bytes left to copy < 8*NBYTES
+ */
+cleanup_both_aligned:
+#define rem t7
+ beqz len, done
+ sltu t0, len, 4*NBYTES
+ bnez t0, less_than_4units
+ and rem, len, (NBYTES-1) # rem = len % NBYTES
+ /*
+ * len >= 4*NBYTES
+ */
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+ ADD src, src, 4*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc)
+ ADDC(sum, t0)
+EXC( STORE t1, UNIT(1)(dst), s_exc)
+ ADDC(sum, t1)
+EXC( STORE t2, UNIT(2)(dst), s_exc)
+ ADDC(sum, t2)
+EXC( STORE t3, UNIT(3)(dst), s_exc)
+ ADDC(sum, t3)
+ beqz len, done
+ ADD dst, dst, 4*NBYTES
+less_than_4units:
+ /*
+ * rem = len % NBYTES
+ */
+ beq rem, len, copy_bytes
+ nop
+1:
+EXC( LOAD t0, 0(src), l_exc)
+ ADD src, src, NBYTES
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc)
+ ADDC(sum, t0)
+ bne rem, len, 1b
+ ADD dst, dst, NBYTES
+
+ /*
+ * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
+ * A loop would do only a byte at a time with possible branch
+ * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE
+ * because can't assume read-access to dst. Instead, use
+ * STREST dst, which doesn't require read access to dst.
+ *
+ * This code should perform better than a simple loop on modern,
+ * wide-issue mips processors because the code has fewer branches and
+ * more instruction-level parallelism.
+ */
+#define bits t2
+ beqz len, done
+ ADD t1, dst, len # t1 is just past last byte of dst
+ li bits, 8*NBYTES
+ SLL rem, len, 3 # rem = number of bits to keep
+EXC( LOAD t0, 0(src), l_exc)
+ SUB bits, bits, rem # bits = number of bits to discard
+ SHIFT_DISCARD t0, t0, bits
+EXC( STREST t0, -1(t1), s_exc)
+ SHIFT_DISCARD_REVERT t0, t0, bits
+ .set reorder
+ ADDC(sum, t0)
+ b done
+ .set noreorder
+dst_unaligned:
+ /*
+ * dst is unaligned
+ * t0 = src & ADDRMASK
+ * t1 = dst & ADDRMASK; T1 > 0
+ * len >= NBYTES
+ *
+ * Copy enough bytes to align dst
+ * Set match = (src and dst have same alignment)
+ */
+#define match rem
+EXC( LDFIRST t3, FIRST(0)(src), l_exc)
+ ADD t2, zero, NBYTES
+EXC( LDREST t3, REST(0)(src), l_exc_copy)
+ SUB t2, t2, t1 # t2 = number of bytes copied
+ xor match, t0, t1
+EXC( STFIRST t3, FIRST(0)(dst), s_exc)
+ SLL t4, t1, 3 # t4 = number of bits to discard
+ SHIFT_DISCARD t3, t3, t4
+ /* no SHIFT_DISCARD_REVERT to handle odd buffer properly */
+ ADDC(sum, t3)
+ beq len, t2, done
+ SUB len, len, t2
+ ADD dst, dst, t2
+ beqz match, both_aligned
+ ADD src, src, t2
+
+src_unaligned_dst_aligned:
+ SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
+ beqz t0, cleanup_src_unaligned
+ and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
+1:
+/*
+ * Avoid consecutive LD*'s to the same register since some mips
+ * implementations can't issue them in the same cycle.
+ * It's OK to load FIRST(N+1) before REST(N) because the two addresses
+ * are to the same unit (unless src is aligned, but it's not).
+ */
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+EXC( LDREST t1, REST(1)(src), l_exc_copy)
+EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy)
+EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy)
+EXC( LDREST t2, REST(2)(src), l_exc_copy)
+EXC( LDREST t3, REST(3)(src), l_exc_copy)
+ ADD src, src, 4*NBYTES
+#ifdef CONFIG_CPU_SB1
+ nop # improves slotting
+#endif
+EXC( STORE t0, UNIT(0)(dst), s_exc)
+ ADDC(sum, t0)
+EXC( STORE t1, UNIT(1)(dst), s_exc)
+ ADDC(sum, t1)
+EXC( STORE t2, UNIT(2)(dst), s_exc)
+ ADDC(sum, t2)
+EXC( STORE t3, UNIT(3)(dst), s_exc)
+ ADDC(sum, t3)
+ bne len, rem, 1b
+ ADD dst, dst, 4*NBYTES
+
+cleanup_src_unaligned:
+ beqz len, done
+ and rem, len, NBYTES-1 # rem = len % NBYTES
+ beq rem, len, copy_bytes
+ nop
+1:
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+ ADD src, src, NBYTES
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc)
+ ADDC(sum, t0)
+ bne len, rem, 1b
+ ADD dst, dst, NBYTES
+
+copy_bytes_checklen:
+ beqz len, done
+ nop
+copy_bytes:
+ /* 0 < len < NBYTES */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define SHIFT_START 0
+#define SHIFT_INC 8
+#else
+#define SHIFT_START 8*(NBYTES-1)
+#define SHIFT_INC -8
+#endif
+ move t2, zero # partial word
+ li t3, SHIFT_START # shift
+/* use l_exc_copy here to return correct sum on fault */
+#define COPY_BYTE(N) \
+EXC( lbu t0, N(src), l_exc_copy); \
+ SUB len, len, 1; \
+EXC( sb t0, N(dst), s_exc); \
+ SLLV t0, t0, t3; \
+ addu t3, SHIFT_INC; \
+ beqz len, copy_bytes_done; \
+ or t2, t0
+
+ COPY_BYTE(0)
+ COPY_BYTE(1)
+#ifdef USE_DOUBLE
+ COPY_BYTE(2)
+ COPY_BYTE(3)
+ COPY_BYTE(4)
+ COPY_BYTE(5)
+#endif
+EXC( lbu t0, NBYTES-2(src), l_exc_copy)
+ SUB len, len, 1
+EXC( sb t0, NBYTES-2(dst), s_exc)
+ SLLV t0, t0, t3
+ or t2, t0
+copy_bytes_done:
+ ADDC(sum, t2)
+done:
+ /* fold checksum */
+#ifdef USE_DOUBLE
+ dsll32 v1, sum, 0
+ daddu sum, v1
+ sltu v1, sum, v1
+ dsra32 sum, sum, 0
+ addu sum, v1
+#endif
+ sll v1, sum, 16
+ addu sum, v1
+ sltu v1, sum, v1
+ srl sum, sum, 16
+ addu sum, v1
+
+ /* odd buffer alignment? */
+ beqz odd, 1f
+ nop
+ sll v1, sum, 8
+ srl sum, sum, 8
+ or sum, v1
+ andi sum, 0xffff
+1:
+ .set reorder
+ ADDC(sum, psum)
+ jr ra
+ .set noreorder
+
+l_exc_copy:
+ /*
+ * Copy bytes from src until faulting load address (or until a
+ * lb faults)
+ *
+ * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
+ * may be more than a byte beyond the last address.
+ * Hence, the lb below may get an exception.
+ *
+ * Assumes src < THREAD_BUADDR($28)
+ */
+ LOAD t0, TI_TASK($28)
+ li t2, SHIFT_START
+ LOAD t0, THREAD_BUADDR(t0)
+1:
+EXC( lbu t1, 0(src), l_exc)
+ ADD src, src, 1
+ sb t1, 0(dst) # can't fault -- we're copy_from_user
+ SLLV t1, t1, t2
+ addu t2, SHIFT_INC
+ ADDC(sum, t1)
+ bne src, t0, 1b
+ ADD dst, dst, 1
+l_exc:
+ LOAD t0, TI_TASK($28)
+ nop
+ LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
+ nop
+ SUB len, AT, t0 # len number of uncopied bytes
+ /*
+ * Here's where we rely on src and dst being incremented in tandem,
+ * See (3) above.
+ * dst += (fault addr - src) to put dst at first byte to clear
+ */
+ ADD dst, t0 # compute start address in a1
+ SUB dst, src
+ /*
+ * Clear len bytes starting at dst. Can't call __bzero because it
+ * might modify len. An inefficient loop for these rare times...
+ */
+ beqz len, done
+ SUB src, len, 1
+1: sb zero, 0(dst)
+ ADD dst, dst, 1
+ bnez src, 1b
+ SUB src, src, 1
+ li v1, -EFAULT
+ b done
+ sw v1, (errptr)
+
+s_exc:
+ li v0, -1 /* invalid checksum */
+ li v1, -EFAULT
+ jr ra
+ sw v1, (errptr)
+ END(__csum_partial_copy_user)
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
deleted file mode 100644
index 1720f2ceeea..00000000000
--- a/arch/mips/lib/csum_partial_copy.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics GmbH
- * Copyright (C) 1998, 1999 Ralf Baechle
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-
-/*
- * copy while checksumming, otherwise like csum_partial
- */
-__wsum csum_partial_copy_nocheck(const void *src,
- void *dst, int len, __wsum sum)
-{
- /*
- * It's 2:30 am and I don't feel like doing it real ...
- * This is lots slower than the real thing (tm)
- */
- sum = csum_partial(src, len, sum);
- memcpy(dst, src, len);
-
- return sum;
-}
-
-/*
- * Copy from userspace and compute checksum. If we catch an exception
- * then zero the rest of the buffer.
- */
-__wsum csum_partial_copy_from_user (const void __user *src,
- void *dst, int len, __wsum sum, int *err_ptr)
-{
- int missing;
-
- might_sleep();
- missing = copy_from_user(dst, src, len);
- if (missing) {
- memset(dst + len - missing, 0, missing);
- *err_ptr = -EFAULT;
- }
-
- return csum_partial(dst, len, sum);
-}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index e4604c73f02..a3c3a1d462b 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -47,6 +47,9 @@
#ifdef CONFIG_MIPS_MALTA
#include <asm/mips-boards/maltaint.h>
#endif
+#ifdef CONFIG_MIPS_SEAD
+#include <asm/mips-boards/seadint.h>
+#endif
unsigned long cpu_khz;
@@ -263,11 +266,13 @@ void __init mips_time_init(void)
void __init plat_timer_setup(struct irqaction *irq)
{
+#ifdef MSC01E_INT_BASE
if (cpu_has_veic) {
set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
- }
- else {
+ } else
+#endif
+ {
if (cpu_has_vint)
set_vi_handler (MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 77ee5c6d33c..cb7f349b051 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -20,4 +20,5 @@
#
obj-y := malta_int.o malta_setup.o
+obj-$(CONFIG_MTD) += malta_mtd.o
obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_mtd.c b/arch/mips/mips-boards/malta/malta_mtd.c
new file mode 100644
index 00000000000..8ad9bdf25dc
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_mtd.c
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 MIPS Technologies, Inc.
+ * written by Ralf Baechle <ralf@linux-mips.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <mtd/mtd-abi.h>
+
+static struct mtd_partition malta_mtd_partitions[] = {
+ {
+ .name = "YAMON",
+ .offset = 0x0,
+ .size = 0x100000,
+ .mask_flags = MTD_WRITEABLE
+ }, {
+ .name = "User FS",
+ .offset = 0x100000,
+ .size = 0x2e0000
+ }, {
+ .name = "Board Config",
+ .offset = 0x3e0000,
+ .size = 0x020000,
+ .mask_flags = MTD_WRITEABLE
+ }
+};
+
+static struct physmap_flash_data malta_flash_data = {
+ .width = 4,
+ .nr_parts = ARRAY_SIZE(malta_mtd_partitions),
+ .parts = malta_mtd_partitions
+};
+
+static struct resource malta_flash_resource = {
+ .start = 0x1e000000,
+ .end = 0x1e3fffff,
+ .flags = IORESOURCE_MEM
+};
+
+static struct platform_device malta_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &malta_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &malta_flash_resource,
+};
+
+static int __init malta_mtd_init(void)
+{
+ platform_device_register(&malta_flash);
+
+ return 0;
+}
+
+module_init(malta_mtd_init)
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 282f3e52eea..56ea76679cd 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -21,13 +21,6 @@
#include <linux/pci.h>
#include <linux/screen_info.h>
-#ifdef CONFIG_MTD
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#endif
-
#include <asm/cpu.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
@@ -58,30 +51,6 @@ struct resource standard_io_resources[] = {
{ .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY },
};
-#ifdef CONFIG_MTD
-static struct mtd_partition malta_mtd_partitions[] = {
- {
- .name = "YAMON",
- .offset = 0x0,
- .size = 0x100000,
- .mask_flags = MTD_WRITEABLE
- },
- {
- .name = "User FS",
- .offset = 0x100000,
- .size = 0x2e0000
- },
- {
- .name = "Board Config",
- .offset = 0x3e0000,
- .size = 0x020000,
- .mask_flags = MTD_WRITEABLE
- }
-};
-
-#define number_partitions (sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition))
-#endif
-
const char *get_system_type(void)
{
return "MIPS Malta";
@@ -211,14 +180,6 @@ void __init plat_mem_setup(void)
#endif
#endif
-#ifdef CONFIG_MTD
- /*
- * Support for MTD on Malta. Use the generic physmap driver
- */
- physmap_configure(0x1e000000, 0x400000, 4, NULL);
- physmap_set_partitions(malta_mtd_partitions, number_partitions);
-#endif
-
mips_reboot_setup();
board_time_init = mips_time_init;
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index f445fcddfdf..874ccb0066b 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -21,7 +21,7 @@
* Sead board.
*/
#include <linux/init.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
@@ -108,7 +108,7 @@ asmlinkage void plat_irq_dispatch(void)
if (irq >= 0)
do_IRQ(MIPSCPU_INT_BASE + irq);
else
- spurious_interrupt(regs);
+ spurious_interrupt();
}
void __init arch_init_irq(void)
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
index 2659c1c3b78..ea2066c3a1f 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mips-boards/sim/sim_setup.c
@@ -57,7 +57,7 @@ void __init plat_mem_setup(void)
board_time_init = sim_time_init;
prom_printf("Linux started...\n");
-#ifdef CONFIG_MT_SMP
+#ifdef CONFIG_MIPS_MT_SMP
sanitize_tlb_entries();
#endif
}
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index caf807ded51..1f954a238a6 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -32,6 +32,7 @@ void (*local_flush_data_cache_page)(void * addr);
void (*flush_data_cache_page)(unsigned long addr);
void (*flush_icache_all)(void);
+EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
EXPORT_SYMBOL(flush_data_cache_page);
#ifdef CONFIG_DMA_NONCOHERENT
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 9e29ba9205f..49065c133eb 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -203,6 +203,31 @@ static inline void kunmap_coherent(struct page *page)
preempt_check_resched();
}
+void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma)
+{
+ void *vfrom, *vto;
+
+ vto = kmap_atomic(to, KM_USER1);
+ if (cpu_has_dc_aliases) {
+ vfrom = kmap_coherent(from, vaddr);
+ copy_page(vto, vfrom);
+ kunmap_coherent(from);
+ } else {
+ vfrom = kmap_atomic(from, KM_USER0);
+ copy_page(vto, vfrom);
+ kunmap_atomic(vfrom, KM_USER0);
+ }
+ if (((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) ||
+ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+ flush_data_cache_page((unsigned long)vto);
+ kunmap_atomic(vto, KM_USER1);
+ /* Make sure this page is cleared on other CPU's too before using it */
+ smp_wmb();
+}
+
+EXPORT_SYMBOL(copy_user_highpage);
+
void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
@@ -316,7 +341,7 @@ static int __init page_is_ram(unsigned long pagenr)
void __init paging_init(void)
{
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
- unsigned long max_dma, high, low;
+ unsigned long max_dma, low;
#ifndef CONFIG_FLATMEM
unsigned long zholes_size[MAX_NR_ZONES] = { 0, };
unsigned long i, j, pfn;
@@ -331,7 +356,6 @@ void __init paging_init(void)
max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
low = max_low_pfn;
- high = highend_pfn;
#ifdef CONFIG_ISA
if (low < max_dma)
@@ -344,13 +368,13 @@ void __init paging_init(void)
zones_size[ZONE_DMA] = low;
#endif
#ifdef CONFIG_HIGHMEM
- if (cpu_has_dc_aliases) {
- printk(KERN_WARNING "This processor doesn't support highmem.");
- if (high - low)
- printk(" %ldk highmem ignored", high - low);
- printk("\n");
- } else
- zones_size[ZONE_HIGHMEM] = high - low;
+ zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn;
+
+ if (cpu_has_dc_aliases && zones_size[ZONE_HIGHMEM]) {
+ printk(KERN_WARNING "This processor doesn't support highmem."
+ " %ldk highmem ignored\n", zones_size[ZONE_HIGHMEM]);
+ zones_size[ZONE_HIGHMEM] = 0;
+ }
#endif
#ifdef CONFIG_FLATMEM
@@ -477,7 +501,8 @@ void free_initmem(void)
freed = prom_free_prom_memory();
if (freed)
- printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
+ printk(KERN_INFO "Freeing firmware memory: %ldkb freed\n",
+ freed >> 10);
free_init_pages("unused kernel memory",
__pa_symbol(&__init_begin),
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index cea7d0ea36e..fc2c96f0a1f 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -6,98 +6,13 @@
* (C) Copyright 1995 1996 Linus Torvalds
* (C) Copyright 2001, 2002 Ralf Baechle
*/
+#include <linux/mm.h>
#include <linux/module.h>
#include <asm/addrspace.h>
#include <asm/byteorder.h>
#include <linux/vmalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/io.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
- phys_t size, phys_t phys_addr, unsigned long flags)
-{
- phys_t end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
- | __WRITEABLE | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
- phys_t size, phys_t phys_addr, unsigned long flags)
-{
- phys_t end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, phys_t phys_addr,
- phys_t size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- 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))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}
+#include <linux/io.h>
/*
* Generic mapping function (not visible outside):
@@ -121,6 +36,7 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
unsigned long offset;
phys_t last_addr;
void * addr;
+ pgprot_t pgprot;
phys_addr = fixup_bigphys_addr(phys_addr, size);
@@ -152,6 +68,9 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
return NULL;
}
+ pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+ | __WRITEABLE | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -166,7 +85,8 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
if (!area)
return NULL;
addr = 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, pgprot)) {
vunmap(addr);
return NULL;
}
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index d41fc5885e8..dc795be6280 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -243,11 +243,10 @@ static void __init __build_store_reg(int reg)
static inline void build_store_reg(int reg)
{
- if (cpu_has_prefetch)
- if (reg)
- build_dst_pref(pref_offset_copy);
- else
- build_dst_pref(pref_offset_clear);
+ int pref_off = cpu_has_prefetch ?
+ (reg ? pref_offset_copy : pref_offset_clear) : 0;
+ if (pref_off)
+ build_dst_pref(pref_off);
else if (cpu_has_cache_cdex_s)
build_cdex_s();
else if (cpu_has_cache_cdex_p)
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 2e0e21ef433..65160d4984d 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -106,7 +106,6 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
ENTER_CRITICAL(flags);
size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
size = (size + 1) >> 1;
- local_irq_save(flags);
if (size <= current_cpu_data.tlbsize/2) {
int oldpid = read_c0_entryhi();
int newpid = cpu_asid(cpu, mm);
diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c
index 6509a9c9863..2f75c6b91ec 100644
--- a/arch/mips/momentum/ocelot_g/prom.c
+++ b/arch/mips/momentum/ocelot_g/prom.c
@@ -28,7 +28,7 @@ struct callvectors* debug_vectors;
extern unsigned long marvell_base;
extern unsigned long bus_clock;
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
extern unsigned char prom_mac_addr_base[6];
#endif
@@ -61,7 +61,7 @@ void __init prom_init(void)
mips_machgroup = MACH_GROUP_MOMENCO;
mips_machtype = MACH_MOMENCO_OCELOT_G;
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
/* get the base MAC address for on-board ethernet ports */
memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
#endif
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
index d288f7b0184..9db638a7982 100644
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -64,7 +64,7 @@
#include "ocelot_pld.h"
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
extern unsigned char prom_mac_addr_base[6];
#endif
@@ -185,7 +185,7 @@ void __init plat_mem_setup(void)
/* do handoff reconfiguration */
PMON_v2_setup();
-#ifdef CONFIG_GALILLEO_GT64240_ETH
+#ifdef CONFIG_GALILEO_GT64240_ETH
/* get the mac addr */
memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
#endif
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 70cb55b89df..82b20c28bef 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -43,7 +43,7 @@ obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o
obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
-obj-$(CONFIG_SNI_RM200_PCI) += fixup-sni.o ops-sni.o
+obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
index 4256b3b30b7..50546dab668 100644
--- a/arch/mips/pci/fixup-pnx8550.c
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -33,7 +33,7 @@
#define DBG(x...)
#endif
-extern char irq_tab_jbs[][5];
+extern char pnx8550_irq_tab[][5];
void __init pcibios_fixup_resources(struct pci_dev *dev)
{
@@ -47,7 +47,7 @@ void __init pcibios_fixup(void)
int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
- return irq_tab_jbs[slot][pin];
+ return pnx8550_irq_tab[slot][pin];
}
/* Do platform specific device initialization at pci_enable_device() time */
diff --git a/arch/mips/pci/ops-pnx8550.c b/arch/mips/pci/ops-pnx8550.c
index 454b65cc335..f556b7a8dcc 100644
--- a/arch/mips/pci/ops-pnx8550.c
+++ b/arch/mips/pci/ops-pnx8550.c
@@ -202,7 +202,7 @@ write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
break;
}
- err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
+ err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(1 << (where & 3)), &data);
return err;
}
diff --git a/arch/mips/philips/pnx8550/common/prom.c b/arch/mips/philips/pnx8550/common/prom.c
index f8952c1359c..eb6ec11fef0 100644
--- a/arch/mips/philips/pnx8550/common/prom.c
+++ b/arch/mips/philips/pnx8550/common/prom.c
@@ -35,23 +35,15 @@ char * prom_getcmdline(void)
return &(arcs_cmdline[0]);
}
-void prom_init_cmdline(void)
+void __init prom_init_cmdline(void)
{
- char *cp;
- int actr;
-
- actr = 1; /* Always ignore argv[0] */
+ int i;
- cp = &(arcs_cmdline[0]);
- while(actr < prom_argc) {
- strcpy(cp, prom_argv[actr]);
- cp += strlen(prom_argv[actr]);
- *cp++ = ' ';
- actr++;
+ arcs_cmdline[0] = '\0';
+ for (i = 0; i < prom_argc; i++) {
+ strcat(arcs_cmdline, prom_argv[i]);
+ strcat(arcs_cmdline, " ");
}
- if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
- --cp;
- *cp = '\0';
}
char *prom_getenv(char *envname)
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
index 65c440e8480..68def3880a1 100644
--- a/arch/mips/philips/pnx8550/common/time.c
+++ b/arch/mips/philips/pnx8550/common/time.c
@@ -33,7 +33,17 @@
#include <int.h>
#include <cm.h>
-extern unsigned int mips_hpt_frequency;
+static unsigned long cpj;
+
+static cycle_t hpt_read(void)
+{
+ return read_c0_count2();
+}
+
+static void timer_ack(void)
+{
+ write_c0_compare(cpj);
+}
/*
* pnx8550_time_init() - it does the following things:
@@ -68,27 +78,48 @@ void pnx8550_time_init(void)
* HZ timer interrupts per second.
*/
mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
+ cpj = (mips_hpt_frequency + HZ / 2) / HZ;
+ write_c0_count(0);
+ timer_ack();
+
+ /* Setup Timer 2 */
+ write_c0_count2(0);
+ write_c0_compare2(0xffffffff);
+
+ clocksource_mips.read = hpt_read;
+ mips_timer_ack = timer_ack;
+}
+
+static irqreturn_t monotonic_interrupt(int irq, void *dev_id)
+{
+ /* Timer 2 clear interrupt */
+ write_c0_compare2(-1);
+ return IRQ_HANDLED;
}
+static struct irqaction monotonic_irqaction = {
+ .handler = monotonic_interrupt,
+ .flags = IRQF_DISABLED,
+ .name = "Monotonic timer",
+};
+
void __init plat_timer_setup(struct irqaction *irq)
{
int configPR;
setup_irq(PNX8550_INT_TIMER1, irq);
+ setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction);
- /* Start timer1 */
+ /* Timer 1 start */
configPR = read_c0_config7();
configPR &= ~0x00000008;
write_c0_config7(configPR);
- /* Timer 2 stop */
+ /* Timer 2 start */
configPR = read_c0_config7();
- configPR |= 0x00000010;
+ configPR &= ~0x00000010;
write_c0_config7(configPR);
- write_c0_count2(0);
- write_c0_compare2(0xffffffff);
-
/* Timer 3 stop */
configPR = read_c0_config7();
configPR |= 0x00000020;
diff --git a/arch/mips/philips/pnx8550/jbs/irqmap.c b/arch/mips/philips/pnx8550/jbs/irqmap.c
index f78e0423dc9..98c3429e6e5 100644
--- a/arch/mips/philips/pnx8550/jbs/irqmap.c
+++ b/arch/mips/philips/pnx8550/jbs/irqmap.c
@@ -28,9 +28,9 @@
#include <linux/init.h>
#include <int.h>
-char irq_tab_jbs[][5] __initdata = {
- [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
- [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
- [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+char pnx8550_irq_tab[][5] __initdata = {
+ [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+ [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+ [17] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
};
diff --git a/arch/mips/philips/pnx8550/stb810/Makefile b/arch/mips/philips/pnx8550/stb810/Makefile
new file mode 100644
index 00000000000..f14b592af39
--- /dev/null
+++ b/arch/mips/philips/pnx8550/stb810/Makefile
@@ -0,0 +1,4 @@
+
+# Makefile for the Philips STB810 Board.
+
+lib-y := prom_init.o board_setup.o irqmap.o
diff --git a/arch/mips/philips/pnx8550/stb810/board_setup.c b/arch/mips/philips/pnx8550/stb810/board_setup.c
new file mode 100644
index 00000000000..345d71e53cf
--- /dev/null
+++ b/arch/mips/philips/pnx8550/stb810/board_setup.c
@@ -0,0 +1,49 @@
+/*
+ * STB810 specific board startup routines.
+ *
+ * Based on the arch/mips/philips/pnx8550/jbs/board_setup.c
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2005 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+
+#include <glb.h>
+
+void __init board_setup(void)
+{
+ unsigned long config0, configpr;
+
+ config0 = read_c0_config();
+
+ /* clear all three cache coherency fields */
+ config0 &= ~(0x7 | (7<<25) | (7<<28));
+ config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
+ (CONF_CM_DEFAULT<<28));
+ write_c0_config(config0);
+
+ configpr = read_c0_config7();
+ configpr |= (1<<19); /* enable tlb */
+ write_c0_config7(configpr);
+}
diff --git a/arch/mips/philips/pnx8550/stb810/irqmap.c b/arch/mips/philips/pnx8550/stb810/irqmap.c
new file mode 100644
index 00000000000..5ee11e19975
--- /dev/null
+++ b/arch/mips/philips/pnx8550/stb810/irqmap.c
@@ -0,0 +1,23 @@
+/*
+ * Philips STB810 board irqmap.
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2005 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <int.h>
+
+char pnx8550_irq_tab[][5] __initdata = {
+ [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+ [9] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+ [10] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+};
+
diff --git a/arch/mips/philips/pnx8550/stb810/prom_init.c b/arch/mips/philips/pnx8550/stb810/prom_init.c
new file mode 100644
index 00000000000..ea5b4e0fb47
--- /dev/null
+++ b/arch/mips/philips/pnx8550/stb810/prom_init.c
@@ -0,0 +1,49 @@
+/*
+ * STB810 specific prom routines
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2005 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "Philips PNX8550/STB810";
+}
+
+void __init prom_init(void)
+{
+ unsigned long memsize;
+
+ prom_argc = (int) fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ prom_init_cmdline();
+
+ mips_machgroup = MACH_GROUP_PHILIPS;
+ mips_machtype = MACH_PHILIPS_STB810;
+
+ memsize = 0x08000000; /* Trimedia uses memory above */
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
index 5a5ea6c0b9f..b54b529a29f 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
@@ -158,7 +158,6 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB
#define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 )
#define TOSHIBA_RBTX4927_IRQ_ISA_DISABLE ( 1 << 24 )
#define TOSHIBA_RBTX4927_IRQ_ISA_MASK ( 1 << 25 )
-#define TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ ( 1 << 26 )
#define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff
#endif
@@ -175,7 +174,6 @@ static const u32 toshiba_rbtx4927_irq_debug_flag =
// | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE
// | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE
// | TOSHIBA_RBTX4927_IRQ_ISA_MASK
-// | TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ
);
#endif
@@ -226,7 +224,6 @@ static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq);
static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq);
-static void toshiba_rbtx4927_irq_isa_end(unsigned int irq);
#endif
#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
@@ -249,7 +246,6 @@ static struct irq_chip toshiba_rbtx4927_irq_isa_type = {
.mask = toshiba_rbtx4927_irq_isa_disable,
.mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
.unmask = toshiba_rbtx4927_irq_isa_enable,
- .end = toshiba_rbtx4927_irq_isa_end,
};
#endif
@@ -402,7 +398,8 @@ static void __init toshiba_rbtx4927_irq_isa_init(void)
for (i = TOSHIBA_RBTX4927_IRQ_ISA_BEG;
i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++)
- set_irq_chip(i, &toshiba_rbtx4927_irq_isa_type);
+ set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_isa_type,
+ handle_level_irq);
setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC,
&toshiba_rbtx4927_irq_isa_master);
@@ -470,26 +467,6 @@ static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq)
#endif
-#ifdef CONFIG_TOSHIBA_FPCIB0
-static void toshiba_rbtx4927_irq_isa_end(unsigned int irq)
-{
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ,
- "irq=%d\n", irq);
-
- if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
- || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
- TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
- "bad irq=%d\n", irq);
- panic("\n");
- }
-
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- toshiba_rbtx4927_irq_isa_enable(irq);
- }
-}
-#endif
-
-
void __init arch_init_irq(void)
{
extern void tx4927_irq_init(void);
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index c8dfd8092ca..92f41f6f934 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -6,7 +6,6 @@ config CASIO_E55
select ISA
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
config IBM_WORKPAD
bool "Support for IBM WorkPad z50"
@@ -16,7 +15,6 @@ config IBM_WORKPAD
select ISA
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
config NEC_CMBVR4133
bool "Support for NEC CMB-VR4133"
@@ -41,7 +39,6 @@ config TANBAC_TB022X
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
help
The TANBAC VR4131 multichip module(TB0225) and
the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms
@@ -74,7 +71,6 @@ config VICTOR_MPC30X
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
config ZAO_CAPCELLA
bool "Support for ZAO Networks Capcella"
@@ -84,7 +80,6 @@ config ZAO_CAPCELLA
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
config PCI_VR41XX
bool "Add PCI control unit support of NEC VR4100 series"
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 397ba94cd7e..16decf4ac2f 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -1,7 +1,7 @@
/*
* Interrupt handing routines for NEC VR4100 series.
*
- * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq)
if (cascade->get_irq != NULL) {
unsigned int source_irq = irq;
desc = irq_desc + source_irq;
- desc->chip->ack(source_irq);
+ if (desc->chip->mask_ack)
+ desc->chip->mask_ack(source_irq);
+ else {
+ desc->chip->mask(source_irq);
+ desc->chip->ack(source_irq);
+ }
irq = cascade->get_irq(irq);
if (irq < 0)
atomic_inc(&irq_err_count);
else
irq_dispatch(irq);
- desc->chip->end(source_irq);
+ if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+ desc->chip->unmask(source_irq);
} else
do_IRQ(irq);
}
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
index a039bb7251f..128ed8d6f11 100644
--- a/arch/mips/vr41xx/nec-cmbvr4133/irq.c
+++ b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
@@ -45,19 +45,12 @@ static void ack_i8259_irq(unsigned int irq)
mask_and_ack_8259A(irq - I8259_IRQ_BASE);
}
-static void end_i8259_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
static struct irq_chip i8259_irq_type = {
.typename = "XT-PIC",
.ack = ack_i8259_irq,
.mask = disable_i8259_irq,
.mask_ack = ack_i8259_irq,
.unmask = enable_i8259_irq,
- .end = end_i8259_irq,
};
static int i8259_get_irq_number(int irq)
@@ -92,7 +85,7 @@ void __init rockhopper_init_irq(void)
}
for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
- set_irq_chip(i, &i8259_irq_type);
+ set_irq_chip_and_handler(i, &i8259_irq_type, handle_level_irq);
setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index d2101237442..0f9ff618c6d 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -25,6 +25,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_FIND_NEXT_BIT
bool
default y
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 372edb0348d..c57fcb4b217 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs_hpux(file->f_dentry, &tmp);
+ error = vfs_statfs_hpux(file->f_path.dentry, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 5b6bc6e8a42..3b67d115fb0 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -611,7 +611,7 @@ void smp_cpus_done(unsigned int cpu_max)
}
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
if (cpu != 0 && cpu < parisc_max_cpus)
smp_boot_one_cpu(cpu);
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 920bdbf8404..c10ab47d81f 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -343,7 +343,7 @@ void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct
struct pt_regs *r = &t->thread.regs;
struct pt_regs *r2;
- r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
if (!r2)
return;
*r2 = *r;
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 6c6102307c0..92d496ad07c 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -9,110 +9,8 @@
#include <linux/vmalloc.h>
#include <linux/errno.h>
#include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm/cacheflush.h>
-
-static inline void
-remap_area_pte(pte_t *pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end, pfn;
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
- _PAGE_ACCESSED | flags);
-
- address &= ~PMD_MASK;
-
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
-
- BUG_ON(address >= end);
-
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- BUG_ON(!pte_none(*pte));
-
- set_pte(pte, pfn_pte(pfn, pgprot));
-
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int
-remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
-
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
-
- BUG_ON(address >= end);
-
- phys_addr -= address;
- do {
- pte_t *pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
-
- remap_area_pte(pte, address, end - address,
- address + phys_addr, flags);
-
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
-
- return 0;
-}
-
-static int
-remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- pgd_t *dir;
- int error = 0;
- unsigned long end = address + size;
-
- BUG_ON(address >= end);
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
-
- flush_cache_all();
-
- 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))
- break;
-
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
-
- flush_tlb_all();
-
- return error;
-}
/*
* Generic mapping function (not visible outside):
@@ -131,6 +29,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
void __iomem *addr;
struct vm_struct *area;
unsigned long offset, last_addr;
+ pgprot_t pgprot;
#ifdef CONFIG_EISA
unsigned long end = phys_addr + size - 1;
@@ -164,6 +63,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
}
}
+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
+ _PAGE_ACCESSED | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -179,7 +81,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
return NULL;
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, pgprot)) {
vfree(addr);
return NULL;
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 291c95ac4b3..d6abe495c6b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -41,6 +41,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default y
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default y if 64BIT
+
config GENERIC_HWEIGHT
bool
default y
@@ -99,6 +107,11 @@ config AUDIT_ARCH
bool
default y
+config GENERIC_BUG
+ bool
+ default y
+ depends on BUG
+
config DEFAULT_UIMAGE
bool
help
@@ -423,7 +436,7 @@ config PPC_EFIKA
select RTAS_PROC
select PPC_MPC52xx
select PPC_NATIVE
- default y
+ default n
config PPC_LITE5200
bool "Freescale Lite5200 Eval Board"
@@ -458,7 +471,7 @@ config PPC_PREP
select PPC_INDIRECT_PCI
select PPC_UDBG_16550
select PPC_NATIVE
- default y
+ default n
config PPC_MAPLE
depends on PPC_MULTIPLATFORM && PPC64
@@ -470,6 +483,8 @@ config PPC_MAPLE
select PPC_UDBG_16550
select PPC_970_NAP
select PPC_NATIVE
+ select PPC_RTAS
+ select ATA_NONSTANDARD if ATA
default n
help
This option enables support for the Maple 970FX Evaluation Board.
@@ -511,12 +526,15 @@ config PPC_IBM_CELL_BLADE
select UDBG_RTAS_CONSOLE
config PPC_PS3
- bool "Sony PS3"
+ bool "Sony PS3 (incomplete)"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL
help
This option enables support for the Sony PS3 game console
and other platforms using the PS3 hypervisor.
+ Support for this platform is not yet complete, so
+ enabling this will not result in a bootable kernel on a
+ PS3 system.
config PPC_NATIVE
bool
@@ -706,7 +724,7 @@ config FORCE_MAX_ZONEORDER
config MATH_EMULATION
bool "Math emulation"
- depends on 4xx || 8xx || E200 || E500
+ depends on 4xx || 8xx || E200 || PPC_83xx || E500
---help---
Some PowerPC chips designed for embedded applications do not have
a floating-point unit and therefore do not implement the
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 343dbcfdf08..98392fb5f58 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -152,6 +152,9 @@ $(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits)
$(obj)/zImage.ps3: vmlinux
$(STRIP) -s -R .comment $< -o $@
+$(obj)/zImage.initrd.ps3: vmlinux
+ @echo " WARNING zImage.initrd.ps3 not supported (yet)"
+
$(obj)/uImage: vmlinux $(wrapperbits)
$(call cmd,wrap,uboot)
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 8bc0d259796..186870704ad 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -10,6 +10,12 @@
* option) any later version.
*/
+/*
+ * WARNING: Do not depend on this tree layout remaining static just yet.
+ * The MPC5200 device tree conventions are still in flux
+ * Keep an eye on the linuxppc-dev mailing list for more details
+ */
+
/ {
model = "Lite5200";
compatible = "lite5200\0lite52xx\0mpc5200\0mpc52xx";
@@ -238,7 +244,7 @@
// PSC3 in CODEC mode example
i2s@2400 { // PSC3
- device_type = "i2s";
+ device_type = "sound";
compatible = "mpc5200-psc-i2s\0mpc52xx-psc-i2s";
reg = <2400 100>;
interrupts = <2 3 0>;
@@ -265,7 +271,7 @@
// PSC6 in AC97 mode example
ac97@2c00 { // PSC6
- device_type = "ac97";
+ device_type = "sound";
compatible = "mpc5200-psc-ac97\0mpc52xx-psc-ac97";
reg = <2c00 100>;
interrupts = <2 4 0>;
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 81cb76418a7..5bb2760d7c3 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -10,6 +10,12 @@
* option) any later version.
*/
+/*
+ * WARNING: Do not depend on this tree layout remaining static just yet.
+ * The MPC5200 device tree conventions are still in flux
+ * Keep an eye on the linuxppc-dev mailing list for more details
+ */
+
/ {
model = "Lite5200b";
compatible = "lite5200b\0lite52xx\0mpc5200b\0mpc52xx";
@@ -243,7 +249,7 @@
// PSC3 in CODEC mode example
i2s@2400 { // PSC3
- device_type = "i2s";
+ device_type = "sound";
compatible = "mpc5200b-psc-i2s\0mpc52xx-psc-i2s";
reg = <2400 100>;
interrupts = <2 3 0>;
@@ -270,7 +276,7 @@
// PSC6 in AC97 mode example
ac97@2c00 { // PSC6
- device_type = "ac97";
+ device_type = "sound";
compatible = "mpc5200b-psc-ac97\0mpc52xx-psc-ac97";
reg = <2c00 100>;
interrupts = <2 4 0>;
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index a98c982c73a..e956548da00 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Wed Nov 22 15:33:04 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:12:56 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@ CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -66,6 +69,7 @@ CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -128,14 +132,16 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
CONFIG_PPC_CELL=y
CONFIG_PPC_CELL_NATIVE=y
CONFIG_PPC_IBM_CELL_BLADE=y
-CONFIG_UDBG_RTAS_CONSOLE=y
CONFIG_PPC_PS3=y
+CONFIG_PPC_NATIVE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
# CONFIG_U3_DART is not set
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
@@ -177,12 +183,14 @@ CONFIG_CBE_CPUFREQ=m
CONFIG_PS3_HTAB_SIZE=20
# CONFIG_PS3_DYNAMIC_DMA is not set
CONFIG_PS3_USE_LPAR_ADDR=y
+CONFIG_PS3_VUART=y
#
# Kernel options
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -270,7 +278,10 @@ CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPIP=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
@@ -289,6 +300,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -317,31 +329,67 @@ CONFIG_NETFILTER=y
#
# Core Netfilter Configuration
#
-# CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
#
# 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_CONNTRACK_EVENTS is not set
-CONFIG_IP_NF_CT_PROTO_SCTP=y
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_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_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
#
# IPv6: Netfilter Configuration (EXPERIMENTAL)
#
# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -373,6 +421,7 @@ CONFIG_IP_NF_QUEUE=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -428,6 +477,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=131072
@@ -457,6 +507,7 @@ 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_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
#
@@ -468,7 +519,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
@@ -492,6 +542,7 @@ CONFIG_BLK_DEV_AEC62XX=y
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
# CONFIG_BLK_DEV_SVWKS is not set
CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -505,8 +556,74 @@ CONFIG_IDEDMA_AUTO=y
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
+CONFIG_SCSI=m
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_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_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -538,6 +655,9 @@ CONFIG_DM_MULTIPATH=m
# Fusion MPT device support
#
# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
@@ -552,6 +672,7 @@ CONFIG_DM_MULTIPATH=m
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -559,7 +680,7 @@ CONFIG_DM_MULTIPATH=m
#
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
-CONFIG_BONDING=y
+CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
CONFIG_TUN=y
@@ -604,11 +725,11 @@ CONFIG_E1000_NAPI=y
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
CONFIG_SKGE=m
-# CONFIG_SKY2 is not set
+CONFIG_SKY2=m
# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
+CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
-CONFIG_SPIDER_NET=m
+CONFIG_SPIDER_NET=y
# CONFIG_QLA3XXX is not set
#
@@ -618,6 +739,7 @@ CONFIG_SPIDER_NET=m
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -637,6 +759,7 @@ CONFIG_SPIDER_NET=m
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
@@ -703,6 +826,7 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_DIGIEPCA is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_MOXA_SMARTIO_NEW is not set
# CONFIG_ISI is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
@@ -756,16 +880,17 @@ CONFIG_WATCHDOG_RTAS=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
# CONFIG_HW_RANDOM 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
@@ -855,12 +980,14 @@ CONFIG_I2C_ALGOBIT=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Console display driver support
@@ -875,18 +1002,145 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=m
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
+CONFIG_USB=m
+# 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_MULTITHREAD_PROBE is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII 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_ADUTUX 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_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -912,7 +1166,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
# InfiniBand support
#
-CONFIG_INFINIBAND=y
+CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_USER_MAD=m
CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_ADDR_TRANS=y
@@ -922,6 +1176,8 @@ CONFIG_INFINIBAND_MTHCA_DEBUG=y
CONFIG_INFINIBAND_IPOIB=m
CONFIG_INFINIBAND_IPOIB_DEBUG=y
CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+# CONFIG_INFINIBAND_SRP is not set
+# CONFIG_INFINIBAND_ISER is not set
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -946,6 +1202,10 @@ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1028,23 +1288,18 @@ CONFIG_RAMFS=y
#
# Network File Systems
#
-CONFIG_NFS_FS=m
+CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
-CONFIG_LOCKD=m
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
-CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
+CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1120,8 +1375,14 @@ CONFIG_NLS_ISO8859_15=m
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1130,7 +1391,10 @@ CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1146,6 +1410,8 @@ CONFIG_OPROFILE=y
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=15
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1159,12 +1425,11 @@ CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -1191,6 +1456,7 @@ CONFIG_CRYPTO_BLKCIPHER=m
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
@@ -1199,8 +1465,10 @@ CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index fee72f8a2fb..029c9a0e730 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:22:54 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:12:58 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@ CONFIG_CLASSIC32=y
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
@@ -59,18 +63,22 @@ CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -79,12 +87,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -103,6 +111,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -124,13 +133,16 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
CONFIG_PPC_CHRP=y
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_EFIKA is not set
+# CONFIG_PPC_LITE5200 is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_NATIVE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
@@ -138,6 +150,8 @@ CONFIG_RTAS_PROC=y
# CONFIG_MMIO_NVRAM is not set
CONFIG_PPC_MPC106=y
# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
# CONFIG_WANT_EARLY_SERIAL is not set
@@ -149,6 +163,7 @@ CONFIG_MPIC=y
CONFIG_HIGHMEM=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -161,6 +176,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_KEXEC is not set
CONFIG_IRQ_ALL_CPUS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -243,10 +259,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -263,24 +282,29 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_IP_NF_QUEUE is not set
#
@@ -306,7 +330,6 @@ CONFIG_IP_NF_AMANDA=m
# 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
@@ -381,6 +404,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -407,7 +436,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
@@ -422,6 +450,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -430,6 +459,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# 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_SL82C105=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
CONFIG_BLK_DEV_VIA82CXXX=y
@@ -445,6 +475,8 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -464,14 +496,16 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -487,12 +521,13 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_ATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
@@ -506,17 +541,18 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX 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_MMIO=y
-# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC395x is not set
@@ -525,6 +561,12 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Old CD-ROM drivers (not SCSI, not IDE)
@@ -557,6 +599,7 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -607,6 +650,7 @@ CONFIG_DE4X5=y
# CONFIG_NET_ISA is not set
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_AC3200 is not set
@@ -655,6 +699,7 @@ CONFIG_MV643XX_ETH=y
# CONFIG_MV643XX_ETH_0 is not set
# CONFIG_MV643XX_ETH_1 is not set
# CONFIG_MV643XX_ETH_2 is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -663,6 +708,7 @@ CONFIG_MV643XX_ETH=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -690,6 +736,7 @@ CONFIG_PPP_BSDCOMP=m
CONFIG_PPP_MPPE=m
CONFIG_PPPOE=m
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -710,6 +757,7 @@ CONFIG_PPPOE=m
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -732,6 +780,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL is not set
@@ -778,12 +827,14 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_BRIQ_PANEL=m
# CONFIG_HVC_RTAS is not set
#
@@ -802,10 +853,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -814,7 +861,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -881,6 +927,7 @@ CONFIG_I2C_ALGOBIT=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -889,14 +936,9 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -909,6 +951,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
CONFIG_FB=y
+CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -949,6 +992,7 @@ CONFIG_FB_3DFX=y
# CONFIG_FB_3DFX_ACCEL is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -979,6 +1023,11 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -993,6 +1042,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1034,13 +1084,13 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
@@ -1070,6 +1120,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1087,6 +1138,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1094,12 +1146,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1157,6 +1210,10 @@ CONFIG_USB_MON=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1166,6 +1223,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1173,6 +1231,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1207,8 +1266,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1308,17 +1369,22 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1329,8 +1395,11 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=15
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1345,14 +1414,16 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1367,7 +1438,11 @@ CONFIG_XMON_DEFAULT=y
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_MANAGER=m
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
@@ -1376,6 +1451,10 @@ CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_DES is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 92d0a9dd0b8..7724847f702 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:22:55 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:15:04 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,6 +24,8 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -30,6 +34,9 @@ CONFIG_GENERIC_TBSYNC=y
CONFIG_POWER4_ONLY=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -51,18 +58,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -71,12 +82,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -95,6 +106,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
#
@@ -114,23 +126,28 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
# CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
CONFIG_PPC_PMAC=y
CONFIG_PPC_PMAC64=y
# CONFIG_PPC_MAPLE is not set
+# CONFIG_PPC_PASEMI is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
CONFIG_U3_DART=y
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_MPIC_BROKEN_U3=y
# CONFIG_PPC_MPC106 is not set
CONFIG_PPC_970_NAP=y
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
@@ -152,6 +169,7 @@ CONFIG_MPIC=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -171,6 +189,7 @@ CONFIG_IRQ_ALL_CPUS=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -225,6 +244,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_NET_KEY=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -243,10 +263,13 @@ CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -263,24 +286,29 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
#
@@ -307,7 +335,6 @@ CONFIG_LLC=y
# 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
@@ -382,6 +409,12 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -408,7 +441,6 @@ CONFIG_BLK_DEV_IDEPCI=y
# 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=y
@@ -423,6 +455,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -431,6 +464,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# 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_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -448,6 +482,8 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -467,14 +503,16 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -487,26 +525,12 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
-# CONFIG_SATA_AHCI is not set
-CONFIG_SATA_SVW=y
-# CONFIG_SCSI_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -515,14 +539,71 @@ CONFIG_SATA_SVW=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SVW=y
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
#
# Multi-device support (RAID and LVM)
@@ -537,6 +618,7 @@ CONFIG_MD_RAID10=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
@@ -591,11 +673,13 @@ CONFIG_IEEE1394_RAWIO=y
CONFIG_ADB_PMU=y
# CONFIG_ADB_PMU_LED is not set
CONFIG_PMAC_SMU=y
+CONFIG_MAC_EMUMOUSEBTN=y
CONFIG_THERM_PM72=y
CONFIG_WINDFARM=y
CONFIG_WINDFARM_PM81=y
CONFIG_WINDFARM_PM91=y
CONFIG_WINDFARM_PM112=y
+# CONFIG_PMAC_RACKMETER is not set
#
# Network device support
@@ -652,7 +736,7 @@ CONFIG_E1000=y
# CONFIG_SK98LIN is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -661,6 +745,7 @@ CONFIG_TIGON3=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -691,6 +776,7 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_PPP_MPPE is not set
CONFIG_PPPOE=m
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -711,6 +797,7 @@ CONFIG_PPPOE=m
# Input device support
#
CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
#
# Userland interfaces
@@ -733,6 +820,7 @@ CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
@@ -789,13 +877,7 @@ CONFIG_GEN_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
CONFIG_AGP=m
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_VIA is not set
CONFIG_AGP_UNINORTH=m
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
@@ -806,7 +888,6 @@ CONFIG_MAX_RAW_DEVS=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -871,6 +952,7 @@ CONFIG_I2C_POWERMAC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -879,14 +961,9 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -899,6 +976,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
CONFIG_FB=y
+CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -930,6 +1008,7 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -1080,6 +1159,11 @@ CONFIG_SND_USB_AUDIO=m
# CONFIG_SOUND_PRIME is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1094,6 +1178,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1135,18 +1220,19 @@ CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
CONFIG_HID_FF=y
CONFIG_HID_PID=y
CONFIG_LOGITECH_FF=y
CONFIG_THRUSTMASTER_FF=y
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_HIDDEV=y
# CONFIG_USB_AIPTEK is not set
# CONFIG_USB_WACOM is not set
@@ -1174,12 +1260,14 @@ CONFIG_USB_CATC=m
CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET_MII is not set
CONFIG_USB_USBNET=m
# CONFIG_USB_NET_AX8817X is not set
CONFIG_USB_NET_CDCETHER=m
# CONFIG_USB_NET_GL620A is not set
# CONFIG_USB_NET_NET1080 is not set
# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
# CONFIG_USB_NET_RNDIS_HOST is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
@@ -1194,6 +1282,7 @@ CONFIG_USB_MON=y
#
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
# CONFIG_USB_SERIAL_AIRPRIME is not set
# CONFIG_USB_SERIAL_ARK3116 is not set
CONFIG_USB_SERIAL_BELKIN=m
@@ -1228,6 +1317,8 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_HP4X is not set
@@ -1239,6 +1330,7 @@ CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
# CONFIG_USB_SERIAL_OPTION is not set
CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
CONFIG_USB_EZUSB=y
#
@@ -1246,6 +1338,7 @@ CONFIG_USB_EZUSB=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1253,12 +1346,13 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1316,6 +1410,10 @@ CONFIG_USB_APPLEDISPLAY=m
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1328,6 +1426,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1344,6 +1443,7 @@ CONFIG_XFS_FS=m
CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1380,8 +1480,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -1505,17 +1607,22 @@ CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_UTF8=y
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1528,8 +1635,11 @@ CONFIG_OPROFILE=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1543,9 +1653,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
@@ -1565,7 +1676,12 @@ CONFIG_BOOTX_TEXT=y
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1574,9 +1690,14 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index b5005506c2f..5fc87448704 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc1
-# Fri Oct 6 13:25:04 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:16:44 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@ CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -32,6 +35,9 @@ CONFIG_AUDIT_ARCH=y
CONFIG_POWER3=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -63,12 +69,13 @@ CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -125,18 +132,22 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_PSERIES is not set
CONFIG_PPC_ISERIES=y
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_PPC_PS3 is not set
# CONFIG_U3_DART is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_IBMVIO=y
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
+CONFIG_PPC_INDIRECT_IO=y
+CONFIG_GENERIC_IOMAP=y
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
# CONFIG_MPIC is not set
@@ -146,6 +157,7 @@ CONFIG_IBMVIO=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -178,6 +190,7 @@ CONFIG_RESOURCES_64BIT=y
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
@@ -192,7 +205,6 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -245,6 +257,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -261,21 +274,37 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
CONFIG_NETFILTER_XT_MATCH_DSCP=m
# CONFIG_NETFILTER_XT_MATCH_ESP is not set
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
@@ -286,27 +315,17 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -317,23 +336,25 @@ CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
CONFIG_IP_NF_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_NF_NAT=m
+CONFIG_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_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -440,6 +461,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -449,6 +476,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
@@ -469,6 +497,7 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -515,6 +544,7 @@ CONFIG_SCSI_IBMVSCSI=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -562,6 +592,7 @@ CONFIG_DM_ZERO=m
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -647,6 +678,7 @@ CONFIG_E1000=m
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -765,10 +797,6 @@ CONFIG_GEN_RTC=y
# 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=y
@@ -779,7 +807,6 @@ CONFIG_MAX_RAW_DEVS=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -795,6 +822,7 @@ CONFIG_MAX_RAW_DEVS=256
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -803,11 +831,6 @@ CONFIG_MAX_RAW_DEVS=256
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -822,6 +845,7 @@ CONFIG_MAX_RAW_DEVS=256
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -830,6 +854,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -892,6 +921,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -904,6 +937,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -937,6 +971,7 @@ CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
#
# CD-ROM/DVD Filesystems
@@ -1024,7 +1059,6 @@ CONFIG_CIFS_POSIX=y
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set
-CONFIG_GENERIC_ACL=y
#
# Partition Types
@@ -1080,6 +1114,8 @@ CONFIG_NLS_ISO8859_1=y
# Distributed Lock Manager
#
CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
# CONFIG_DLM_DEBUG is not set
#
@@ -1094,6 +1130,7 @@ CONFIG_VIOPATH=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1105,6 +1142,7 @@ CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1119,6 +1157,8 @@ CONFIG_PLIST=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1132,8 +1172,8 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set
@@ -1142,6 +1182,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_DEBUGGER is not set
CONFIG_IRQSTACKS=y
+# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1155,10 +1196,11 @@ CONFIG_IRQSTACKS=y
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1167,8 +1209,10 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index 23fd210eb56..405c1c90821 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Wed Nov 15 20:36:30 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:17:58 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@ CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -69,12 +70,13 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -130,6 +132,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_PPC_MULTIPLATFORM is not set
CONFIG_EMBEDDED6xx=y
# CONFIG_APUS is not set
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_RTAS is not set
@@ -166,7 +169,6 @@ CONFIG_LINKSTATION=y
# CONFIG_TQM8260 is not set
# CONFIG_ADS8272 is not set
# CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
# CONFIG_EV64360 is not set
CONFIG_PPC_GEN550=y
CONFIG_MPC10X_BRIDGE=y
@@ -181,6 +183,7 @@ CONFIG_MPIC=y
# CONFIG_HIGHMEM is not set
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_PREEMPT_NONE=y
@@ -217,7 +220,6 @@ CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -286,6 +288,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -302,18 +305,35 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_MARK=m
# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
CONFIG_NETFILTER_XT_MATCH_ESP=m
-# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
@@ -324,27 +344,17 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
# CONFIG_NETFILTER_XT_MATCH_REALM is not set
# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
# CONFIG_NETFILTER_XT_MATCH_STRING is not set
# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -355,22 +365,25 @@ CONFIG_IP_NF_MATCH_IPRANGE=m
# CONFIG_IP_NF_MATCH_TTL is not set
# CONFIG_IP_NF_MATCH_OWNER is not set
# CONFIG_IP_NF_MATCH_ADDRTYPE 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 is not set
# CONFIG_IP_NF_TARGET_ULOG is not set
# CONFIG_IP_NF_TARGET_TCPMSS is not set
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_NF_NAT=m
+CONFIG_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 is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
@@ -580,6 +593,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
@@ -599,6 +613,7 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -646,6 +661,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -683,6 +699,7 @@ CONFIG_ATA=y
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
@@ -726,6 +743,7 @@ CONFIG_PATA_SIL680=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -777,6 +795,7 @@ CONFIG_R8169=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -899,6 +918,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -921,10 +941,6 @@ CONFIG_HW_RANDOM=y
# 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
@@ -1032,6 +1048,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -1042,6 +1059,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -1063,6 +1081,7 @@ CONFIG_HWMON=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Console display driver support
@@ -1077,6 +1096,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1091,6 +1115,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1170,6 +1195,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1218,6 +1244,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
#
# USB Miscellaneous drivers
@@ -1324,6 +1351,10 @@ CONFIG_RTC_DRV_RS5C372=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1398,7 +1429,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
@@ -1488,8 +1518,14 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1497,6 +1533,7 @@ CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1511,6 +1548,8 @@ CONFIG_OPROFILE=m
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1524,12 +1563,11 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
@@ -1551,6 +1589,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1559,8 +1598,10 @@ CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig
index ee7655776d4..8cbd87ded6b 100644
--- a/arch/powerpc/configs/lite5200_defconfig
+++ b/arch/powerpc/configs/lite5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Mon Nov 27 11:08:20 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:18:18 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@ CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -68,6 +69,7 @@ CONFIG_SYSVIPC=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -151,6 +153,7 @@ CONFIG_PPC_LITE5200=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -259,6 +262,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -374,6 +378,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_SCSI_PROC_FS is not set
@@ -393,6 +398,7 @@ CONFIG_SCSI=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -440,6 +446,7 @@ CONFIG_SCSI=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -477,7 +484,7 @@ CONFIG_ATA=y
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
-CONFIG_PATA_MPC52xx=y
+# CONFIG_PATA_MARVELL is not set
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
@@ -494,6 +501,7 @@ CONFIG_PATA_MPC52xx=y
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
#
# Multi-device support (RAID and LVM)
@@ -521,6 +529,7 @@ CONFIG_PATA_MPC52xx=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -572,6 +581,7 @@ CONFIG_NETDEVICES=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -632,6 +642,7 @@ CONFIG_NETDEVICES=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_MPC52xx=y
@@ -657,10 +668,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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
@@ -707,6 +714,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -777,6 +785,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -873,6 +885,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
@@ -880,6 +897,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -893,6 +911,8 @@ CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -906,12 +926,11 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS 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_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index ae96a5b2f00..de97f2f0ae9 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Mon Oct 9 11:59:34 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:19:02 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@ CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
CONFIG_GENERIC_TBSYNC=y
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -31,6 +34,9 @@ CONFIG_AUDIT_ARCH=y
CONFIG_POWER4_ONLY=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -61,12 +67,13 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -123,18 +130,27 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
CONFIG_PPC_MAPLE=y
# CONFIG_PPC_PASEMI is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
CONFIG_U3_DART=y
-# CONFIG_PPC_RTAS is not set
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_RTAS_FLASH is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_MPIC_BROKEN_U3=y
# CONFIG_PPC_MPC106 is not set
CONFIG_PPC_970_NAP=y
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
CONFIG_MPIC=y
@@ -144,6 +160,7 @@ CONFIG_MPIC=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -190,7 +207,6 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -246,6 +262,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -346,6 +363,12 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -371,7 +394,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
@@ -395,6 +417,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# 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_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -439,6 +462,7 @@ CONFIG_IDEDMA_AUTO=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -523,6 +547,7 @@ CONFIG_TIGON3=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -618,6 +643,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
#
# IPMI
@@ -634,10 +661,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -647,7 +670,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -711,6 +733,7 @@ CONFIG_I2C_AMD8111=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -719,15 +742,9 @@ CONFIG_I2C_AMD8111=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-# CONFIG_TIFM_CORE is not set
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -740,6 +757,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Console display driver support
@@ -754,6 +772,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -768,6 +791,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -803,7 +827,6 @@ CONFIG_USB_UHCI_HCD=y
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
@@ -819,7 +842,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
#
# USB Imaging devices
@@ -833,6 +855,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_KAWETH is not set
CONFIG_USB_PEGASUS=y
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -881,6 +904,7 @@ 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_MOS7720 is not set
# CONFIG_USB_SERIAL_MOS7840 is not set
# CONFIG_USB_SERIAL_NAVMAN is not set
# CONFIG_USB_SERIAL_PL2303 is not set
@@ -892,6 +916,7 @@ CONFIG_USB_SERIAL_TI=m
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
CONFIG_USB_EZUSB=y
#
@@ -913,6 +938,7 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -970,6 +996,10 @@ CONFIG_USB_EZUSB=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -978,12 +1008,14 @@ CONFIG_EXT2_FS_XIP=y
CONFIG_FS_XIP=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1133,14 +1165,21 @@ CONFIG_NLS_DEFAULT="utf-8"
CONFIG_NLS_UTF8=y
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1155,6 +1194,8 @@ CONFIG_PLIST=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1169,8 +1210,8 @@ CONFIG_DEBUG_SLAB=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set
@@ -1180,6 +1221,7 @@ CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
# CONFIG_IRQSTACKS is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1195,9 +1237,10 @@ CONFIG_BOOTX_TEXT=y
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
@@ -1206,8 +1249,10 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index d1811e75451..fdf09eabe6e 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:26:55 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:20:53 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@ CONFIG_CLASSIC32=y
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
@@ -58,16 +62,20 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
@@ -75,12 +83,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -93,6 +101,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -114,19 +123,19 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_PPC_ISERIES is not set
CONFIG_EMBEDDED6xx=y
# CONFIG_APUS is not set
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_UDBG_RTAS_CONSOLE is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_PPC_TODC is not set
# CONFIG_KATANA is not set
# CONFIG_WILLOW is not set
# CONFIG_CPCI690 is not set
@@ -141,6 +150,7 @@ CONFIG_EMBEDDED6xx=y
# CONFIG_PRPMC750 is not set
# CONFIG_PRPMC800 is not set
# CONFIG_SANDPOINT is not set
+# CONFIG_LINKSTATION is not set
CONFIG_MPC7448HPC2=y
# CONFIG_RADSTONE_PPC7D is not set
# CONFIG_PAL4 is not set
@@ -152,7 +162,6 @@ CONFIG_MPC7448HPC2=y
# CONFIG_TQM8260 is not set
# CONFIG_ADS8272 is not set
# CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
# CONFIG_EV64360 is not set
CONFIG_TSI108_BRIDGE=y
# CONFIG_WANT_EARLY_SERIAL is not set
@@ -164,6 +173,7 @@ CONFIG_MPIC=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -173,6 +183,7 @@ CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -237,6 +248,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -258,10 +270,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -291,7 +306,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -362,6 +376,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -371,6 +391,8 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -389,14 +411,16 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -409,27 +433,13 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
-# CONFIG_SATA_AHCI is not set
-# CONFIG_SATA_SVW is not set
-# CONFIG_SCSI_ATA_PIIX is not set
-CONFIG_SATA_MV=y
-# CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -438,15 +448,73 @@ CONFIG_SATA_MV=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+CONFIG_SATA_MV=y
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
#
# Multi-device support (RAID and LVM)
@@ -474,6 +542,7 @@ CONFIG_SATA_MV=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -505,6 +574,7 @@ CONFIG_PHYLIB=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -563,6 +633,8 @@ CONFIG_8139TOO=y
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
+CONFIG_TSI108_ETH=y
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -571,6 +643,7 @@ CONFIG_8139TOO=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -610,6 +683,7 @@ CONFIG_8139TOO=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -654,6 +728,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -677,10 +752,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -689,7 +760,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -705,6 +775,7 @@ CONFIG_GEN_RTC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -713,17 +784,14 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -735,6 +803,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -743,6 +812,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -805,6 +879,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -814,6 +892,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -821,6 +900,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -850,8 +930,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -921,13 +1003,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -938,12 +1027,14 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -957,7 +1048,3 @@ CONFIG_LOG_BUF_SHIFT=14
# Cryptographic options
#
# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index 0561b73a918..45757b61370 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Mon Sep 25 19:41:14 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:23:43 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@ CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
CONFIG_PPC_83xx=y
# CONFIG_PPC_85xx is not set
@@ -40,6 +41,8 @@ CONFIG_PPC_83xx=y
CONFIG_6xx=y
CONFIG_83xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
@@ -59,16 +62,20 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -98,6 +105,7 @@ CONFIG_MODULE_UNLOAD=y
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -120,8 +128,10 @@ CONFIG_PPC_GEN550=y
#
# Platform support
#
+# CONFIG_MPC832x_MDS is not set
# CONFIG_MPC834x_SYS is not set
CONFIG_MPC834x_ITX=y
+# CONFIG_MPC8360E_PB is not set
CONFIG_MPC834x=y
# CONFIG_MPIC is not set
@@ -131,6 +141,7 @@ CONFIG_MPC834x=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -138,8 +149,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -206,6 +219,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -227,10 +241,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -411,9 +428,16 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
# CONFIG_BLK_DEV_IDE is not set
# CONFIG_BLK_DEV_HD_ONLY is not set
# CONFIG_BLK_DEV_HD is not set
@@ -423,6 +447,8 @@ CONFIG_IDE=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -441,14 +467,16 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -461,27 +489,13 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
-# CONFIG_SATA_AHCI is not set
-# CONFIG_SATA_SVW is not set
-# CONFIG_SCSI_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-CONFIG_SATA_SIL=y
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -490,15 +504,73 @@ CONFIG_SATA_SIL=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
#
# Multi-device support (RAID and LVM)
@@ -535,6 +607,7 @@ CONFIG_MD_RAID1=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -566,6 +639,7 @@ CONFIG_PHYLIB=y
CONFIG_CICADA_PHY=y
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -622,6 +696,7 @@ CONFIG_E100=y
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -630,6 +705,7 @@ CONFIG_GFAR_NAPI=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -669,6 +745,7 @@ CONFIG_GFAR_NAPI=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -713,6 +790,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -753,10 +831,6 @@ CONFIG_HW_RANDOM=y
# 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
@@ -765,7 +839,6 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -842,6 +915,7 @@ CONFIG_SPI_MPC83xx=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -876,29 +950,27 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -911,6 +983,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -919,6 +992,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -933,6 +1011,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -972,6 +1051,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -1010,6 +1090,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1027,6 +1108,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1034,12 +1116,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1067,6 +1150,7 @@ 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
+# CONFIG_USB_MIDI_GADGET is not set
#
# MMC/SD Card support
@@ -1102,6 +1186,7 @@ CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
#
# RTC interfaces
@@ -1145,6 +1230,10 @@ CONFIG_NET_DMA=y
CONFIG_INTEL_IOATDMA=y
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1154,6 +1243,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1161,6 +1251,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1190,8 +1281,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1206,7 +1299,6 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
@@ -1249,6 +1341,10 @@ CONFIG_PARTITION_ADVANCED=y
# 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
@@ -1262,13 +1358,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1279,8 +1382,11 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1294,9 +1400,10 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
@@ -1316,8 +1423,10 @@ CONFIG_FORCED_INLINING=y
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-# CONFIG_CRYPTO_MANAGER is not set
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
@@ -1326,8 +1435,10 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 9eefab96789..c24db58be45 100644
--- a/arch/powerpc/configs/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:28:54 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:24:10 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
CONFIG_PPC_83xx=y
# CONFIG_PPC_85xx is not set
@@ -39,6 +41,8 @@ CONFIG_PPC_83xx=y
CONFIG_6xx=y
CONFIG_83xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
@@ -58,28 +62,32 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -97,6 +105,7 @@ CONFIG_MODULE_UNLOAD=y
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -119,8 +128,10 @@ CONFIG_PPC_GEN550=y
#
# Platform support
#
+# CONFIG_MPC832x_MDS is not set
CONFIG_MPC834x_SYS=y
# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC8360E_PB is not set
CONFIG_MPC834x=y
# CONFIG_MPIC is not set
@@ -130,6 +141,7 @@ CONFIG_MPC834x=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -137,8 +149,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -204,6 +218,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -225,10 +240,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -258,7 +276,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -329,6 +346,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -338,6 +361,12 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -362,6 +391,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -393,6 +423,7 @@ CONFIG_MARVELL_PHY=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -449,6 +480,7 @@ CONFIG_E100=y
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
# CONFIG_GFAR_NAPI is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -457,6 +489,7 @@ CONFIG_GIANFAR=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -495,6 +528,7 @@ CONFIG_GIANFAR=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -539,6 +573,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -575,10 +610,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -587,7 +618,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -653,6 +683,7 @@ CONFIG_I2C_MPC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -686,29 +717,27 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -720,6 +749,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -728,6 +758,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -790,6 +825,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -799,6 +838,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -806,6 +846,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -835,8 +876,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -905,13 +948,20 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -922,11 +972,14 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -941,7 +994,11 @@ CONFIG_LOG_BUF_SHIFT=14
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
@@ -950,6 +1007,10 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc8360emds_defconfig b/arch/powerpc/configs/mpc8360emds_defconfig
index c0703415d60..58e6795dbfe 100644
--- a/arch/powerpc/configs/mpc8360emds_defconfig
+++ b/arch/powerpc/configs/mpc8360emds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Thu Sep 21 18:14:27 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:24:40 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,13 +23,13 @@ CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
CONFIG_PPC_83xx=y
# CONFIG_PPC_85xx is not set
@@ -40,6 +41,8 @@ CONFIG_PPC_83xx=y
CONFIG_6xx=y
CONFIG_83xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
@@ -59,16 +62,20 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -98,6 +105,7 @@ CONFIG_MODULE_UNLOAD=y
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -121,6 +129,7 @@ CONFIG_PPC_GEN550=y
#
# Platform support
#
+# CONFIG_MPC832x_MDS is not set
# CONFIG_MPC834x_SYS is not set
# CONFIG_MPC834x_ITX is not set
CONFIG_MPC8360E_PB=y
@@ -133,6 +142,7 @@ CONFIG_PPC_MPC836x=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -140,8 +150,10 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -207,6 +219,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -228,10 +241,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -331,6 +347,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -340,6 +362,8 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -358,14 +382,16 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -378,11 +404,12 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
@@ -392,15 +419,22 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -428,6 +462,7 @@ CONFIG_SCSI_PROC_FS=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -488,6 +523,7 @@ CONFIG_UCC_GETH=y
# CONFIG_UGETH_MAGIC_PACKET is not set
# CONFIG_UGETH_FILTERING is not set
# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -496,6 +532,7 @@ CONFIG_UCC_GETH=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -535,6 +572,7 @@ CONFIG_UCC_GETH=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -579,6 +617,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -615,10 +654,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -627,7 +662,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -693,6 +727,7 @@ CONFIG_I2C_MPC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -726,29 +761,27 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -760,6 +793,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -768,6 +802,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -830,6 +869,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -839,6 +882,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -846,6 +890,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -875,8 +920,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -945,20 +992,27 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# QE Options
#
-# CONFIG_UCC_SLOW is not set
+CONFIG_UCC_SLOW=y
CONFIG_UCC_FAST=y
CONFIG_UCC=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -969,11 +1023,14 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -988,7 +1045,11 @@ CONFIG_LOG_BUF_SHIFT=14
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
@@ -997,6 +1058,10 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 67e7d0b5793..17120c47230 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:29:23 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:25:24 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
@@ -38,6 +40,8 @@ CONFIG_PPC_85xx=y
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
@@ -58,16 +62,20 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,12 +84,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -94,6 +102,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -116,6 +125,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_MPC8540_ADS=y
+# CONFIG_MPC8560_ADS is not set
# CONFIG_MPC85xx_CDS is not set
CONFIG_MPC8540=y
CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -127,6 +137,7 @@ CONFIG_MPIC=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -137,6 +148,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -199,6 +211,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -220,10 +233,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -253,7 +269,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -320,6 +335,11 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -329,6 +349,12 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -351,6 +377,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -377,6 +404,7 @@ CONFIG_PHYLIB=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -429,6 +457,7 @@ CONFIG_GFAR_NAPI=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -472,6 +501,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
@@ -493,17 +523,12 @@ 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_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -519,6 +544,7 @@ CONFIG_GEN_RTC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -527,17 +553,14 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -549,6 +572,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -557,6 +581,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -617,6 +646,10 @@ CONFIG_FIRMWARE_EDID=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -626,6 +659,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -633,6 +667,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -662,8 +697,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -729,13 +766,20 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -746,8 +790,11 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -761,10 +808,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
@@ -782,7 +829,3 @@ CONFIG_FORCED_INLINING=y
# Cryptographic options
#
# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
index ddc2a7b07ba..ecaa267a853 100644
--- a/arch/powerpc/configs/mpc8560_ads_defconfig
+++ b/arch/powerpc/configs/mpc8560_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc4
-# Fri Aug 11 16:45:05 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:25:53 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
@@ -38,6 +40,8 @@ CONFIG_PPC_85xx=y
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
@@ -58,16 +62,20 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,12 +84,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -94,6 +102,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -110,7 +119,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_MPIC=y
CONFIG_CPM2=y
# CONFIG_WANT_EARLY_SERIAL is not set
@@ -122,6 +130,7 @@ CONFIG_MPC8560_ADS=y
# CONFIG_MPC85xx_CDS is not set
CONFIG_MPC8560=y
CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPIC=y
#
# Kernel options
@@ -129,6 +138,7 @@ CONFIG_PPC_INDIRECT_PCI_BE=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -140,6 +150,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_PC_KEYBOARD is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -152,13 +163,13 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
-# CONFIG_SOFTWARE_SUSPEND is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
CONFIG_FSL_SOC=y
@@ -205,6 +216,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -226,10 +238,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -259,7 +274,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -331,6 +345,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -340,6 +360,12 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -364,6 +390,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -395,6 +422,7 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -437,6 +465,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -445,6 +474,7 @@ CONFIG_GFAR_NAPI=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -483,6 +513,7 @@ CONFIG_GFAR_NAPI=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -522,6 +553,7 @@ CONFIG_INPUT=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
@@ -536,7 +568,6 @@ CONFIG_SERIAL_CPM_SCC2=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_BRIQ_PANEL is not set
#
# IPMI
@@ -554,10 +585,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -566,7 +593,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -582,6 +608,7 @@ CONFIG_GEN_RTC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -590,17 +617,14 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -612,6 +636,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -620,6 +645,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -682,6 +712,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -691,6 +725,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -698,6 +733,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -727,8 +763,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -794,13 +832,20 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -811,8 +856,11 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -826,10 +874,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
@@ -848,7 +896,3 @@ CONFIG_FORCED_INLINING=y
# Cryptographic options
#
# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
index 72edf9f6682..1f61bce33e3 100644
--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:29:49 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:26:46 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
@@ -38,6 +40,8 @@ CONFIG_PPC_85xx=y
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
@@ -58,16 +62,20 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,12 +84,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -94,6 +102,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -116,6 +125,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8560_ADS is not set
CONFIG_MPC85xx_CDS=y
CONFIG_MPC8540=y
CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -127,6 +137,7 @@ CONFIG_MPIC=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -137,6 +148,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -202,6 +214,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -223,10 +236,13 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -256,7 +272,6 @@ CONFIG_TCP_CONG_BIC=y
# 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
@@ -328,9 +343,16 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
CONFIG_BLK_DEV_IDE=y
#
@@ -353,7 +375,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
# CONFIG_IDEDMA_PCI_AUTO is not set
@@ -367,6 +388,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -375,6 +397,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
CONFIG_BLK_DEV_VIA82CXXX=y
@@ -389,6 +412,12 @@ CONFIG_BLK_DEV_IDEDMA=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -413,6 +442,7 @@ CONFIG_BLK_DEV_IDEDMA=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -444,6 +474,7 @@ CONFIG_PHYLIB=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -483,6 +514,7 @@ CONFIG_E1000_NAPI=y
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -491,6 +523,7 @@ CONFIG_GFAR_NAPI=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -529,6 +562,7 @@ CONFIG_GFAR_NAPI=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -573,6 +607,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -596,10 +631,6 @@ CONFIG_GEN_RTC=y
# 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
@@ -608,7 +639,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -624,6 +654,7 @@ CONFIG_GEN_RTC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -632,17 +663,14 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -654,6 +682,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -662,6 +691,11 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -724,6 +758,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -733,6 +771,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -740,6 +779,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -769,8 +809,10 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -836,13 +878,20 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -853,8 +902,11 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -868,10 +920,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
@@ -889,7 +941,3 @@ CONFIG_FORCED_INLINING=y
# Cryptographic options
#
# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index 92a527fccf8..53fcd6932f5 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:30:15 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:27:14 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@ CONFIG_PPC_86xx=y
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
@@ -62,15 +66,18 @@ CONFIG_LOCALVERSION=""
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -79,15 +86,15 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-# CONFIG_SLAB is not set
+CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-CONFIG_SLOB=y
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -97,6 +104,7 @@ CONFIG_SLOB=y
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -129,6 +137,7 @@ CONFIG_MPC8641=y
CONFIG_HIGHMEM=y
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_PREEMPT_NONE=y
@@ -140,6 +149,7 @@ CONFIG_BINFMT_ELF=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_IRQ_ALL_CPUS is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -206,6 +216,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -226,21 +237,29 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
CONFIG_INET6_XFRM_MODE_TRANSPORT=y
CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -267,7 +286,6 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
# 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
@@ -339,6 +357,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
@@ -348,6 +372,12 @@ CONFIG_BLK_DEV_INITRD=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -372,6 +402,7 @@ CONFIG_BLK_DEV_INITRD=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -403,6 +434,7 @@ CONFIG_PHYLIB=y
# CONFIG_CICADA_PHY is not set
CONFIG_VITESSE_PHY=y
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -440,6 +472,7 @@ CONFIG_MII=y
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
# CONFIG_GFAR_NAPI is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -448,6 +481,7 @@ CONFIG_GIANFAR=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -486,6 +520,7 @@ CONFIG_GIANFAR=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -542,6 +577,7 @@ CONFIG_SERIAL_8250_RSA=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
@@ -563,10 +599,6 @@ CONFIG_UNIX98_PTYS=y
# 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
@@ -575,7 +607,6 @@ CONFIG_UNIX98_PTYS=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -640,6 +671,7 @@ CONFIG_SENSORS_EEPROM=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -648,14 +680,9 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -667,6 +694,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Console display driver support
@@ -682,6 +710,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -744,6 +777,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -753,6 +790,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -760,6 +798,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -788,8 +827,10 @@ CONFIG_FS_MBCACHE=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -904,13 +945,20 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -921,12 +969,16 @@ CONFIG_PLIST=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -936,10 +988,10 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
@@ -957,7 +1009,3 @@ CONFIG_FORCED_INLINING=y
# Cryptographic options
#
# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index 765c8bb90dd..f611df480fd 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:30:23 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:28:56 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,13 +22,14 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
CONFIG_CLASSIC32=y
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -38,6 +40,8 @@ CONFIG_CLASSIC32=y
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
@@ -58,17 +62,21 @@ CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -77,12 +85,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -100,6 +108,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_LSF=y
@@ -121,18 +130,22 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_EFIKA is not set
+# CONFIG_PPC_LITE5200 is not set
CONFIG_PPC_PMAC=y
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_PPC_NATIVE=y
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_PPC_MPC106=y
# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
@@ -157,6 +170,7 @@ CONFIG_MPIC=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -167,6 +181,7 @@ CONFIG_BINFMT_MISC=m
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_KEXEC is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -181,6 +196,8 @@ CONFIG_PROC_DEVICETREE=y
CONFIG_PM=y
# CONFIG_PM_LEGACY is not set
CONFIG_PM_DEBUG=y
+# CONFIG_DISABLE_CONSOLE_SUSPEND is not set
+CONFIG_PM_SYSFS_DEPRECATED=y
CONFIG_SOFTWARE_SUSPEND=y
CONFIG_PM_STD_PARTITION=""
CONFIG_SECCOMP=y
@@ -254,6 +271,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -272,10 +290,13 @@ CONFIG_INET_ESP=y
# CONFIG_INET_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -292,14 +313,33 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
@@ -312,61 +352,49 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_NETBIOS_NS=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_PPTP=m
-CONFIG_IP_NF_H323=m
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=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=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
CONFIG_IP_NF_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_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_PPTP=m
-CONFIG_IP_NF_NAT_H323=m
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
@@ -384,8 +412,11 @@ CONFIG_IP_DCCP_ACKVEC=y
# DCCP CCIDs Configuration (EXPERIMENTAL)
#
CONFIG_IP_DCCP_CCID2=m
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
CONFIG_IP_DCCP_CCID3=m
CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
#
# DCCP Kernel Hacking
@@ -410,7 +441,6 @@ CONFIG_IP_DCCP_TFRC_LIB=m
# 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
@@ -567,6 +597,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -594,7 +630,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
@@ -609,6 +644,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -617,6 +653,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_PDC202XX_NEW=y
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIIMAGE is not set
+CONFIG_BLK_DEV_SL82C105=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -634,6 +671,8 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
#
@@ -653,14 +692,16 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -678,11 +719,12 @@ CONFIG_AIC7XXX_DEBUG_MASK=0
CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
CONFIG_SCSI_AIC7XXX_OLD=m
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_ATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
@@ -692,14 +734,15 @@ CONFIG_SCSI_AIC7XXX_OLD=m
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
CONFIG_SCSI_SYM53C8XX_MMIO=y
-# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
@@ -709,6 +752,7 @@ CONFIG_SCSI_MESH=y
CONFIG_SCSI_MESH_SYNC_RATE=5
CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
CONFIG_SCSI_MAC53C94=y
+# CONFIG_SCSI_SRP is not set
#
# PCMCIA SCSI adapter support
@@ -720,6 +764,11 @@ CONFIG_SCSI_MAC53C94=y
# CONFIG_PCMCIA_SYM53C500 is not set
#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
# Multi-device support (RAID and LVM)
#
CONFIG_MD=y
@@ -732,6 +781,7 @@ CONFIG_MD_RAID10=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
@@ -798,6 +848,7 @@ CONFIG_THERM_WINDTUNNEL=m
CONFIG_THERM_ADT746X=m
# CONFIG_WINDFARM is not set
# CONFIG_ANSLCD is not set
+CONFIG_PMAC_RACKMETER=m
#
# Network device support
@@ -838,6 +889,7 @@ CONFIG_SUNGEM=y
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
@@ -874,6 +926,7 @@ CONFIG_PCNET32=y
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -882,6 +935,7 @@ CONFIG_PCNET32=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -957,6 +1011,7 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_PPP_MPPE is not set
# CONFIG_PPPOE is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=y
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -977,6 +1032,7 @@ CONFIG_PPP_BSDCOMP=m
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -999,6 +1055,7 @@ CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
@@ -1039,6 +1096,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=m
CONFIG_SERIAL_PMACZILOG=m
# CONFIG_SERIAL_JSM is not set
@@ -1062,13 +1120,7 @@ CONFIG_GEN_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
CONFIG_AGP=m
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_VIA is not set
CONFIG_AGP_UNINORTH=m
CONFIG_DRM=m
# CONFIG_DRM_TDFX is not set
@@ -1091,7 +1143,6 @@ CONFIG_DRM_RADEON=m
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -1167,14 +1218,9 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -1187,6 +1233,7 @@ CONFIG_VIDEO_V4L2=y
#
# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB=y
+CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1235,6 +1282,7 @@ CONFIG_FB_3DFX=y
# CONFIG_FB_3DFX_ACCEL is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -1393,6 +1441,11 @@ CONFIG_SND_USB_AUDIO=m
# CONFIG_SOUND_PRIME is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1408,6 +1461,7 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
CONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1448,13 +1502,13 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
CONFIG_USB_HIDINPUT_POWERBOOK=y
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
@@ -1484,12 +1538,14 @@ CONFIG_USB_APPLETOUCH=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET_MII=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_CDCETHER=m
# CONFIG_USB_NET_GL620A is not set
CONFIG_USB_NET_NET1080=m
# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
# CONFIG_USB_NET_RNDIS_HOST is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
CONFIG_USB_NET_ZAURUS=m
@@ -1504,6 +1560,7 @@ CONFIG_USB_MON=y
#
CONFIG_USB_SERIAL=m
# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
# CONFIG_USB_SERIAL_AIRPRIME is not set
# CONFIG_USB_SERIAL_ARK3116 is not set
# CONFIG_USB_SERIAL_BELKIN is not set
@@ -1538,6 +1595,8 @@ 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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
# CONFIG_USB_SERIAL_NAVMAN is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_HP4X is not set
@@ -1548,6 +1607,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
CONFIG_USB_EZUSB=y
#
@@ -1555,6 +1615,7 @@ CONFIG_USB_EZUSB=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1562,12 +1623,13 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1630,6 +1692,10 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1639,6 +1705,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1646,6 +1713,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1682,8 +1750,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
@@ -1802,8 +1872,14 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
CONFIG_CRC32=y
@@ -1815,6 +1891,7 @@ CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1826,8 +1903,11 @@ CONFIG_OPROFILE=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1841,14 +1921,16 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
# CONFIG_BDI_SWITCH is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1863,7 +1945,12 @@ CONFIG_BOOTX_TEXT=y
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1872,9 +1959,14 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 1c009651f92..debac66e825 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:45:11 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:28:58 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,6 +24,8 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -31,6 +35,10 @@ CONFIG_GENERIC_TBSYNC=y
CONFIG_POWER3=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+CONFIG_PPC_DCR_MMIO=y
+CONFIG_PPC_DCR=y
+CONFIG_PPC_OF_PLATFORM_PCI=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -52,19 +60,24 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_TASK_XACCT is not set
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -73,12 +86,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -97,6 +110,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+CONFIG_BLOCK=y
CONFIG_BLK_DEV_IO_TRACE=y
#
@@ -116,16 +130,20 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
CONFIG_PPC_PSERIES=y
+CONFIG_PPC_ISERIES=y
+# CONFIG_PPC_MPC52xx is not set
CONFIG_PPC_PMAC=y
CONFIG_PPC_PMAC64=y
CONFIG_PPC_MAPLE=y
+# CONFIG_PPC_PASEMI is not set
CONFIG_PPC_CELL=y
CONFIG_PPC_CELL_NATIVE=y
CONFIG_PPC_IBM_CELL_BLADE=y
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
CONFIG_UDBG_RTAS_CONSOLE=y
CONFIG_XICS=y
CONFIG_U3_DART=y
@@ -139,6 +157,8 @@ CONFIG_IBMVIO=y
# CONFIG_IBMEBUS is not set
# CONFIG_PPC_MPC106 is not set
CONFIG_PPC_970_NAP=y
+CONFIG_PPC_INDIRECT_IO=y
+CONFIG_GENERIC_IOMAP=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
@@ -160,14 +180,16 @@ CONFIG_MPIC=y
#
CONFIG_SPU_FS=m
CONFIG_SPU_BASE=y
-CONFIG_SPUFS_MMAP=y
CONFIG_CBE_RAS=y
+CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
#
# Kernel options
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -192,6 +214,7 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -201,6 +224,7 @@ CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ARCH_MEMORY_PROBE=y
@@ -254,6 +278,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_NET_KEY=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -272,10 +297,13 @@ CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -294,25 +322,31 @@ CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-CONFIG_IP_NF_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
#
@@ -339,7 +373,6 @@ CONFIG_LLC=y
# 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
@@ -412,6 +445,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -438,7 +477,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
@@ -453,6 +491,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -461,6 +500,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# 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_SL82C105=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -478,6 +518,8 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
#
@@ -497,14 +539,16 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -517,26 +561,12 @@ CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
-# CONFIG_SATA_AHCI is not set
-CONFIG_SATA_SVW=y
-# CONFIG_SCSI_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_SCSI_PDC_ADMA is not set
# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -546,6 +576,7 @@ CONFIG_SATA_SVW=y
CONFIG_SCSI_IBMVSCSI=y
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
@@ -556,10 +587,66 @@ CONFIG_SCSI_IPR_TRACE=y
CONFIG_SCSI_IPR_DUMP=y
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SVW=y
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
#
# Multi-device support (RAID and LVM)
@@ -575,6 +662,7 @@ CONFIG_MD_RAID5_RESHAPE=y
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
@@ -630,11 +718,13 @@ CONFIG_IEEE1394_RAWIO=y
CONFIG_ADB_PMU=y
# CONFIG_ADB_PMU_LED is not set
CONFIG_PMAC_SMU=y
+# CONFIG_MAC_EMUMOUSEBTN is not set
CONFIG_THERM_PM72=y
CONFIG_WINDFARM=y
CONFIG_WINDFARM_PM81=y
CONFIG_WINDFARM_PM91=y
CONFIG_WINDFARM_PM112=y
+# CONFIG_PMAC_RACKMETER is not set
#
# Network device support
@@ -675,6 +765,7 @@ CONFIG_VORTEX=y
CONFIG_IBMVETH=m
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
@@ -713,7 +804,7 @@ CONFIG_E1000=y
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
CONFIG_SPIDER_NET=m
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
@@ -723,6 +814,7 @@ CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -741,6 +833,7 @@ CONFIG_IBMOL=y
# Wan interfaces
#
# CONFIG_WAN is not set
+CONFIG_ISERIES_VETH=m
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=m
@@ -753,6 +846,7 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_PPP_MPPE is not set
CONFIG_PPPOE=m
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
CONFIG_NETCONSOLE=y
@@ -775,6 +869,7 @@ CONFIG_NET_POLL_CONTROLLER=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -797,6 +892,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL is not set
@@ -850,6 +946,7 @@ CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_HVC_DRIVER=y
CONFIG_HVC_CONSOLE=y
+CONFIG_HVC_ISERIES=y
CONFIG_HVC_RTAS=y
CONFIG_HVCS=m
@@ -868,10 +965,6 @@ CONFIG_GEN_RTC=y
# 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=y
@@ -882,7 +975,6 @@ CONFIG_MAX_RAW_DEVS=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -947,6 +1039,7 @@ CONFIG_I2C_POWERMAC=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -955,14 +1048,9 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -975,6 +1063,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
CONFIG_FB=y
+CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1011,6 +1100,7 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+CONFIG_FB_IBM_GXT4500=y
# CONFIG_FB_VIRTUAL is not set
#
@@ -1159,6 +1249,11 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
# CONFIG_SOUND_PRIME is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1173,6 +1268,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1214,13 +1310,13 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
CONFIG_USB_HIDDEV=y
@@ -1250,6 +1346,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
# CONFIG_USB_MON is not set
@@ -1267,6 +1364,7 @@ CONFIG_USB_HIDDEV=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1274,12 +1372,13 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1318,6 +1417,7 @@ CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_AMSO1100 is not set
CONFIG_INFINIBAND_IPOIB=m
CONFIG_INFINIBAND_IPOIB_DEBUG=y
# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
@@ -1347,6 +1447,10 @@ CONFIG_INFINIBAND_ISER=m
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1359,6 +1463,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1379,6 +1484,7 @@ CONFIG_XFS_FS=m
CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1414,8 +1520,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -1540,8 +1648,23 @@ CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# iSeries device drivers
+#
+# CONFIG_VIOCONS is not set
+CONFIG_VIODASD=y
+CONFIG_VIOCD=m
+CONFIG_VIOTAPE=m
+CONFIG_VIOPATH=y
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1551,6 +1674,7 @@ CONFIG_ZLIB_DEFLATE=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1563,8 +1687,11 @@ CONFIG_OPROFILE=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1578,16 +1705,19 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_HCALL_STATS is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
# CONFIG_XMON_DEFAULT is not set
+CONFIG_XMON_DISASSEMBLY=y
CONFIG_IRQSTACKS=y
CONFIG_BOOTX_TEXT=y
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1602,7 +1732,12 @@ CONFIG_BOOTX_TEXT=y
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1611,9 +1746,14 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index f2d888e014a..32560876c3d 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Tue Nov 21 19:38:53 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:29:11 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -23,6 +25,7 @@ CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -64,6 +67,7 @@ CONFIG_SYSVIPC=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -126,6 +130,7 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
@@ -157,12 +162,14 @@ CONFIG_SPU_BASE=y
CONFIG_PS3_HTAB_SIZE=20
CONFIG_PS3_DYNAMIC_DMA=y
CONFIG_PS3_USE_LPAR_ADDR=y
+CONFIG_PS3_VUART=y
#
# Kernel options
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -260,6 +267,7 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -365,6 +373,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
@@ -384,6 +393,7 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -426,6 +436,7 @@ CONFIG_SCSI_PROC_FS=y
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -548,10 +559,6 @@ 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_RAW_DRIVER is not set
# CONFIG_HANGCHECK_TIMER is not set
@@ -597,6 +604,7 @@ CONFIG_GEN_RTC=y
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Console display driver support
@@ -611,6 +619,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -671,6 +684,10 @@ CONFIG_DUMMY_CONSOLE=y
#
#
+# Virtualization
+#
+
+#
# File systems
#
# CONFIG_EXT2_FS is not set
@@ -771,6 +788,11 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
@@ -778,6 +800,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -792,6 +815,8 @@ CONFIG_PLIST=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
@@ -805,12 +830,11 @@ CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS 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_DEBUG_VM is not set
CONFIG_DEBUG_LIST=y
CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index d2833c1a1f3..1c794fe718f 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc6
-# Sun Sep 10 10:45:12 2006
+# Linux kernel version: 2.6.20-rc5
+# Mon Jan 22 22:31:27 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -10,6 +10,8 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_ARCH_HAS_ILOG2_U64=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -22,6 +24,8 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -31,6 +35,9 @@ CONFIG_PPC_UDBG_16550=y
CONFIG_POWER3=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_OF_PLATFORM_PCI is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
@@ -52,19 +59,22 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
+# CONFIG_UTS_NS is not set
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CPUSETS=y
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -73,12 +83,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -97,6 +107,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
#
@@ -116,15 +127,19 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_ISERIES is not set
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
CONFIG_PPC_PSERIES=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_PPC_MPC52xx is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
+# CONFIG_PPC_PASEMI is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_NATIVE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
CONFIG_XICS=y
# CONFIG_U3_DART is not set
@@ -137,6 +152,8 @@ CONFIG_IBMVIO=y
CONFIG_IBMEBUS=y
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
CONFIG_MPIC=y
@@ -146,6 +163,7 @@ CONFIG_MPIC=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -170,6 +188,7 @@ CONFIG_NODES_SHIFT=4
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -183,7 +202,6 @@ CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
-CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
CONFIG_NODES_SPAN_OTHER_NODES=y
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
@@ -235,6 +253,7 @@ CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_NET_KEY=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -253,10 +272,13 @@ CONFIG_INET_XFRM_TUNNEL=m
CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -275,25 +297,30 @@ CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK_ENABLED=m
+CONFIG_NF_CONNTRACK_SUPPORT=y
+# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CONNTRACK_EVENTS=y
-CONFIG_IP_NF_CONNTRACK_NETLINK=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
#
@@ -320,7 +347,6 @@ CONFIG_LLC=y
# 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
@@ -402,6 +428,12 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -428,7 +460,6 @@ CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
@@ -443,6 +474,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -451,6 +483,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# 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_SL82C105=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -465,6 +498,8 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
#
@@ -484,14 +519,16 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=m
CONFIG_SCSI_SAS_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
@@ -504,10 +541,11 @@ CONFIG_SCSI_SAS_ATTRS=m
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-CONFIG_ATA=y
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
@@ -520,6 +558,7 @@ CONFIG_SCSI_IBMVSCSI=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_STEX is not set
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
@@ -530,10 +569,66 @@ CONFIG_SCSI_IPR_TRACE=y
CONFIG_SCSI_IPR_DUMP=y
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA_FC=m
+# CONFIG_SCSI_QLA_ISCSI is not set
CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
#
# Multi-device support (RAID and LVM)
@@ -548,6 +643,7 @@ CONFIG_MD_RAID10=m
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
@@ -576,6 +672,7 @@ CONFIG_DM_MULTIPATH_EMC=m
#
# Macintosh device drivers
#
+# CONFIG_MAC_EMUMOUSEBTN is not set
# CONFIG_WINDFARM is not set
#
@@ -617,6 +714,7 @@ CONFIG_VORTEX=y
CONFIG_IBMVETH=y
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
+# CONFIG_PCNET32_NAPI is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
@@ -655,17 +753,19 @@ CONFIG_E1000=y
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_CHELSIO_T1 is not set
+CONFIG_EHEA=m
CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -697,6 +797,7 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_PPP_MPPE is not set
CONFIG_PPPOE=m
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
CONFIG_NETCONSOLE=y
@@ -719,6 +820,7 @@ CONFIG_NET_POLL_CONTROLLER=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -741,6 +843,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL is not set
@@ -815,10 +918,6 @@ CONFIG_GEN_RTC=y
# 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=y
@@ -829,7 +928,6 @@ CONFIG_MAX_RAW_DEVS=1024
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -894,6 +992,7 @@ CONFIG_I2C_ALGOBIT=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -902,14 +1001,9 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_HWMON_VID is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
#
# Digital Video Broadcasting Devices
@@ -922,6 +1016,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_FIRMWARE_EDID=y
CONFIG_FB=y
+CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -957,6 +1052,7 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+CONFIG_FB_IBM_GXT4500=y
# CONFIG_FB_VIRTUAL is not set
#
@@ -989,6 +1085,11 @@ CONFIG_LCD_DEVICE=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1003,6 +1104,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1043,13 +1145,13 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
CONFIG_USB_HIDDEV=y
@@ -1079,6 +1181,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1097,6 +1200,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -1104,12 +1208,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1148,6 +1253,9 @@ CONFIG_INFINIBAND_USER_ACCESS=m
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_EHCA=m
+CONFIG_INFINIBAND_EHCA_SCALING=y
+# CONFIG_INFINIBAND_AMSO1100 is not set
CONFIG_INFINIBAND_IPOIB=m
CONFIG_INFINIBAND_IPOIB_DEBUG=y
# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
@@ -1177,6 +1285,10 @@ CONFIG_INFINIBAND_SRP=m
#
#
+# Virtualization
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1189,6 +1301,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1209,6 +1322,7 @@ CONFIG_XFS_FS=m
CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
CONFIG_OCFS2_FS=m
CONFIG_OCFS2_DEBUG_MASKLOG=y
# CONFIG_MINIX_FS is not set
@@ -1246,8 +1360,10 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -1357,17 +1473,22 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
#
# Instrumentation Support
@@ -1380,8 +1501,11 @@ CONFIG_KPROBES=y
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1395,16 +1519,20 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_LKDTM is not set
CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_HCALL_STATS=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
CONFIG_IRQSTACKS=y
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1419,7 +1547,12 @@ CONFIG_IRQSTACKS=y
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
@@ -1428,9 +1561,14 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 4fe53d08ab8..d2ded19e406 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -77,6 +77,7 @@ endif
ifeq ($(CONFIG_PPC_ISERIES),y)
extra-y += lparmap.s
+$(obj)/head_64.o: $(obj)/lparmap.s
AFLAGS_head_64.o += -I$(obj)
endif
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index e96521530d2..030d300cd71 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -303,5 +303,8 @@ int main(void)
DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
+#ifdef CONFIG_BUG
+ DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
+#endif
return 0;
}
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 9d1614c3ce6..b742013bb9d 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -833,7 +833,7 @@ static struct cpu_spec cpu_specs[] = {
.pvr_mask = 0x7fff0000,
.pvr_value = 0x00840000,
.cpu_name = "e300c2",
- .cpu_features = CPU_FTRS_E300,
+ .cpu_features = CPU_FTRS_E300C2,
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 32,
.dcache_bsize = 32,
@@ -1136,8 +1136,7 @@ static struct cpu_spec cpu_specs[] = {
.pvr_mask = 0xff000fff,
.pvr_value = 0x53000890,
.cpu_name = "440SPe Rev. A",
- .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB,
+ .cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 1a3d4de197d..2551c0884af 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -28,6 +28,7 @@
#include <asm/asm-offsets.h>
#include <asm/cputable.h>
#include <asm/firmware.h>
+#include <asm/bug.h>
/*
* System calls.
@@ -634,19 +635,15 @@ _GLOBAL(enter_rtas)
li r0,0
mtcr r0
+#ifdef CONFIG_BUG
/* There is no way it is acceptable to get here with interrupts enabled,
* check it with the asm equivalent of WARN_ON
*/
lbz r0,PACASOFTIRQEN(r13)
1: tdnei r0,0
-.section __bug_table,"a"
- .llong 1b,__LINE__ + 0x1000000, 1f, 2f
-.previous
-.section .rodata,"a"
-1: .asciz __FILE__
-2: .asciz "enter_rtas"
-.previous
-
+ EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING
+#endif
+
/* Hard-disable interrupts */
mfmsr r6
rldicl r7,r6,48,1
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index d88e182e40b..9417cf5b4b7 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -437,6 +437,13 @@ Alignment:
/* Floating-point unavailable */
. = 0x800
FPUnavailable:
+BEGIN_FTR_SECTION
+/*
+ * Certain Freescale cores don't have a FPU and treat fp instructions
+ * as a FP Unavailable exception. Redirect to illegal/emulation handling.
+ */
+ b ProgramCheck
+END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
EXCEPTION_PROLOG
bne load_up_fpu /* if from user, just load it up */
addi r3,r1,STACK_FRAME_OVERHEAD
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index e2c3c6a85f3..8339fd609de 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/cache.h>
+#include <linux/bug.h>
#include "setup.h"
@@ -290,23 +291,11 @@ int module_finalize(const Elf_Ehdr *hdr,
struct module *me)
{
const Elf_Shdr *sect;
+ int err;
- me->arch.bug_table = NULL;
- me->arch.num_bugs = 0;
-
- /* Find the __bug_table section, if present */
- sect = find_section(hdr, sechdrs, "__bug_table");
- if (sect != NULL) {
- me->arch.bug_table = (void *) sect->sh_addr;
- me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
- }
-
- /*
- * Strictly speaking this should have a spinlock to protect against
- * traversals, but since we only traverse on BUG()s, a spinlock
- * could potentially lead to deadlock and thus be counter-productive.
- */
- list_add(&me->arch.bug_list, &module_bug_list);
+ err = module_bug_finalize(hdr, sechdrs, me);
+ if (err) /* never true, currently */
+ return err;
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -320,7 +309,7 @@ int module_finalize(const Elf_Ehdr *hdr,
void module_arch_cleanup(struct module *mod)
{
- list_del(&mod->arch.bug_list);
+ module_bug_cleanup(mod);
}
struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 8dd1f0aae5d..75c7c4f1928 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -20,6 +20,7 @@
#include <linux/moduleloader.h>
#include <linux/err.h>
#include <linux/vmalloc.h>
+#include <linux/bug.h>
#include <asm/module.h>
#include <asm/uaccess.h>
#include <asm/firmware.h>
@@ -439,23 +440,11 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, struct module *me)
{
const Elf_Shdr *sect;
+ int err;
- me->arch.bug_table = NULL;
- me->arch.num_bugs = 0;
-
- /* Find the __bug_table section, if present */
- sect = find_section(hdr, sechdrs, "__bug_table");
- if (sect != NULL) {
- me->arch.bug_table = (void *) sect->sh_addr;
- me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
- }
-
- /*
- * Strictly speaking this should have a spinlock to protect against
- * traversals, but since we only traverse on BUG()s, a spinlock
- * could potentially lead to deadlock and thus be counter-productive.
- */
- list_add(&me->arch.bug_list, &module_bug_list);
+ err = module_bug_finalize(hdr, sechdrs, me);
+ if (err)
+ return err;
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -475,7 +464,7 @@ int module_finalize(const Elf_Ehdr *hdr,
void module_arch_cleanup(struct module *mod)
{
- list_del(&mod->arch.bug_list);
+ module_bug_cleanup(mod);
}
struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 6960f090991..869cebbba96 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -505,7 +505,7 @@ static int nvram_scan_partitions(void)
return -ENODEV;
total_size = ppc_md.nvram_size();
- header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
+ header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
if (!header) {
printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
return -ENOMEM;
@@ -574,7 +574,7 @@ static int __init nvram_init(void)
}
/* initialize our anchor for the nvram partition list */
- nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+ nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
if (!nvram_part) {
printk(KERN_ERR "nvram_init: Failed kmalloc\n");
return -ENOMEM;
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 8a06724e029..e921514e655 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -109,9 +109,7 @@ int of_device_register(struct of_device *ofdev)
if (rc)
return rc;
- device_create_file(&ofdev->dev, &dev_attr_devspec);
-
- return 0;
+ return device_create_file(&ofdev->dev, &dev_attr_devspec);
}
void of_device_unregister(struct of_device *ofdev)
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index b3189d0161b..b7345176b39 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -50,6 +50,7 @@ static struct of_device_id of_default_bus_ids[] = {
{ .type = "plb5", },
{ .type = "plb4", },
{ .type = "opb", },
+ { .type = "ebc", },
{},
};
@@ -169,7 +170,7 @@ static void of_platform_make_bus_id(struct of_device *dev)
char *name = dev->dev.bus_id;
const u32 *reg;
u64 addr;
- long magic;
+ int magic;
/*
* If it's a DCR based device, use 'd' for native DCRs
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 2f54cd81dea..c54f3639c5a 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -670,7 +670,7 @@ pcibios_make_OF_bus_map(void)
struct pci_controller* hose;
struct property *map_prop;
- pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+ pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
if (!pci_to_OF_bus_map) {
printk(KERN_ERR "Can't allocate OF bus map !\n");
return;
@@ -736,25 +736,46 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
return NULL;
}
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
+ unsigned int devfn)
{
- const unsigned int *reg;
- u8* fdata = (u8*)data;
-
- reg = get_property(node, "reg", NULL);
- if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
- && ((reg[0] >> 16) & 0xff) == fdata[0])
- return 1;
- return 0;
+ struct device_node *np = NULL;
+ const u32 *reg;
+ unsigned int psize;
+
+ while ((np = of_get_next_child(parent, np)) != NULL) {
+ reg = get_property(np, "reg", &psize);
+ if (reg == NULL || psize < 4)
+ continue;
+ if (((reg[0] >> 8) & 0xff) == devfn)
+ return np;
+ }
+ return NULL;
}
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+
+static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
{
- u8 filter_data[2] = {bus, dev_fn};
+ struct device_node *parent, *np;
+
+ /* Are we a root bus ? */
+ if (bus->self == NULL || bus->parent == NULL) {
+ struct pci_controller *hose = pci_bus_to_hose(bus->number);
+ if (hose == NULL)
+ return NULL;
+ return of_node_get(hose->arch_data);
+ }
- return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+ /* not a root bus, we need to get our parent */
+ parent = scan_OF_for_pci_bus(bus->parent);
+ if (parent == NULL)
+ return NULL;
+
+ /* now iterate for children for a match */
+ np = scan_OF_for_pci_dev(parent, bus->self->devfn);
+ of_node_put(parent);
+
+ return np;
}
/*
@@ -763,43 +784,25 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
struct device_node *
pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
{
- struct pci_controller *hose;
- struct device_node *node;
- int busnr;
+ struct device_node *parent, *np;
if (!have_of)
return NULL;
-
- /* Lookup the hose */
- busnr = bus->number;
- hose = pci_bus_to_hose(busnr);
- if (!hose)
- return NULL;
- /* Check it has an OF node associated */
- node = (struct device_node *) hose->arch_data;
- if (!node)
+ DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
+ parent = scan_OF_for_pci_bus(bus);
+ if (parent == NULL)
return NULL;
-
- /* Fixup bus number according to what OF think it is. */
-#ifdef CONFIG_PPC_PMAC
- /* The G5 need a special case here. Basically, we don't remap all
- * busses on it so we don't create the pci-OF-map. However, we do
- * remap the AGP bus and so have to deal with it. A future better
- * fix has to be done by making the remapping per-host and always
- * filling the pci_to_OF map. --BenH
+ DBG(" parent is %s\n", parent ? parent->full_name : "<NULL>");
+ np = scan_OF_for_pci_dev(parent, devfn);
+ of_node_put(parent);
+ DBG(" result is %s\n", np ? np->full_name : "<NULL>");
+
+ /* XXX most callers don't release the returned node
+ * mostly because ppc64 doesn't increase the refcount,
+ * we need to fix that.
*/
- if (machine_is(powermac) && busnr >= 0xf0)
- busnr -= 0xf0;
- else
-#endif
- if (pci_to_OF_bus_map)
- busnr = pci_to_OF_bus_map[busnr];
- if (busnr == 0xff)
- return NULL;
-
- /* Now, lookup childs of the hose */
- return scan_OF_childs_for_device(node->child, busnr, devfn);
+ return np;
}
EXPORT_SYMBOL(pci_busdev_to_OF_node);
@@ -1544,7 +1547,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- unsigned long *offset,
+ resource_size_t *offset,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
@@ -1556,7 +1559,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
*offset += hose->pci_mem_offset;
+#endif
res_bit = IORESOURCE_MEM;
} else {
io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
@@ -1624,9 +1629,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
else
prot |= _PAGE_GUARDED;
- printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev),
- (unsigned long long)rp->start, prot);
-
return __pgprot(prot);
}
@@ -1695,7 +1697,7 @@ 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;
+ resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
int ret;
@@ -1808,22 +1810,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- unsigned long offset = 0;
+ resource_size_t offset = 0;
if (hose == NULL)
return;
if (rsrc->flags & IORESOURCE_IO)
- offset = (void __iomem *)_IO_BASE - hose->io_base_virt
- + hose->io_base_phys;
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+ /* We pass a fully fixed up address to userland for MMIO instead of
+ * a BAR value because X is lame and expects to be able to use that
+ * to pass to /dev/mem !
+ *
+ * That means that we'll have potentially 64 bits values where some
+ * userland apps only expect 32 (like X itself since it thinks only
+ * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+ * 32 bits CHRPs :-(
+ *
+ * Hopefully, the sysfs insterface is immune to that gunk. Once X
+ * has been fixed (and the fix spread enough), we can re-enable the
+ * 2 lines below and pass down a BAR value to userland. In that case
+ * we'll also have to re-enable the matching code in
+ * __pci_mmap_make_offset().
+ *
+ * BenH.
+ */
+#if 0
+ else if (rsrc->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+#endif
- *start = rsrc->start + offset;
- *end = rsrc->end + offset;
+ *start = rsrc->start - offset;
+ *end = rsrc->end - offset;
}
-void __init
-pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
- int flags, char *name)
+void __init pci_init_resource(struct resource *res, resource_size_t start,
+ resource_size_t end, int flags, char *name)
{
res->start = start;
res->end = end;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 6fa9a0a5c8d..01f18c68340 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -360,6 +360,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
DBG(" class: 0x%x\n", dev->class);
dev->current_state = 4; /* unknown power state */
+ dev->error_state = pci_channel_io_normal;
if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
/* a PCI-PCI bridge */
@@ -682,7 +683,7 @@ int pci_proc_domain(struct pci_bus *bus)
* Returns negative error code on failure, zero on success.
*/
static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- unsigned long *offset,
+ resource_size_t *offset,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
@@ -694,7 +695,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
*offset += hose->pci_mem_offset;
+#endif
res_bit = IORESOURCE_MEM;
} else {
io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
@@ -762,9 +765,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
else
prot |= _PAGE_GUARDED;
- printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
- prot);
-
return __pgprot(prot);
}
@@ -832,7 +832,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
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;
+ resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
int ret;
@@ -1333,20 +1333,41 @@ EXPORT_SYMBOL(pci_read_irq_line);
void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
- u64 *start, u64 *end)
+ resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned long offset = 0;
+ resource_size_t offset = 0;
if (hose == NULL)
return;
if (rsrc->flags & IORESOURCE_IO)
- offset = pci_io_base - (unsigned long)hose->io_base_virt +
- hose->io_base_phys;
+ offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
+ /* We pass a fully fixed up address to userland for MMIO instead of
+ * a BAR value because X is lame and expects to be able to use that
+ * to pass to /dev/mem !
+ *
+ * That means that we'll have potentially 64 bits values where some
+ * userland apps only expect 32 (like X itself since it thinks only
+ * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+ * 32 bits CHRPs :-(
+ *
+ * Hopefully, the sysfs insterface is immune to that gunk. Once X
+ * has been fixed (and the fix spread enough), we can re-enable the
+ * 2 lines below and pass down a BAR value to userland. In that case
+ * we'll also have to re-enable the matching code in
+ * __pci_mmap_make_offset().
+ *
+ * BenH.
+ */
+#if 0
+ else if (rsrc->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+#endif
- *start = rsrc->start + offset;
- *end = rsrc->end + offset;
+ *start = rsrc->start - offset;
+ *end = rsrc->end - offset;
}
struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
@@ -1409,7 +1430,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
bus = pci_bus_b(ln);
- if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate))
+ if (in_bus >= bus->number && in_bus <= bus->subordinate)
break;
bus = NULL;
}
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 9179f0739ea..95776b6af4e 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -208,7 +208,7 @@ EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
extern long *intercept_table;
EXPORT_SYMBOL(intercept_table);
#endif /* CONFIG_PPC_STD_MMU_32 */
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_DCR_NATIVE
EXPORT_SYMBOL(__mtdcr);
EXPORT_SYMBOL(__mfdcr);
#endif
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index f598cb51953..dd7001cacf7 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -83,7 +83,7 @@ __initcall(proc_ppc64_init);
static loff_t page_map_seek( struct file *file, loff_t off, int whence)
{
loff_t new;
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
switch(whence) {
case 0:
@@ -106,13 +106,13 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
}
static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
if ((vma->vm_end - vma->vm_start) > dp->size)
return -EINVAL;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index c18dbe77fdc..1fc732a552d 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -804,6 +804,56 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
return of_read_ulong(p, s);
}
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Interpret the ibm,dynamic-memory property in the
+ * /ibm,dynamic-reconfiguration-memory node.
+ * This contains a list of memory blocks along with NUMA affinity
+ * information.
+ */
+static int __init early_init_dt_scan_drconf_memory(unsigned long node)
+{
+ cell_t *dm, *ls;
+ unsigned long l, n;
+ unsigned long base, size, lmb_size, flags;
+
+ ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
+ if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
+ return 0;
+ lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
+
+ dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
+ if (dm == NULL || l < sizeof(cell_t))
+ return 0;
+
+ n = *dm++; /* number of entries */
+ if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))
+ return 0;
+
+ for (; n != 0; --n) {
+ base = dt_mem_next_cell(dt_root_addr_cells, &dm);
+ flags = dm[3];
+ /* skip DRC index, pad, assoc. list index, flags */
+ dm += 4;
+ /* skip this block if the reserved bit is set in flags (0x80)
+ or if the block is not assigned to this partition (0x8) */
+ if ((flags & 0x80) || !(flags & 0x8))
+ continue;
+ size = lmb_size;
+ if (iommu_is_off) {
+ if (base >= 0x80000000ul)
+ continue;
+ if ((base + size) > 0x80000000ul)
+ size = 0x80000000ul - base;
+ }
+ lmb_add(base, size);
+ }
+ lmb_dump_all();
+ return 0;
+}
+#else
+#define early_init_dt_scan_drconf_memory(node) 0
+#endif /* CONFIG_PPC_PSERIES */
static int __init early_init_dt_scan_memory(unsigned long node,
const char *uname, int depth, void *data)
@@ -812,6 +862,11 @@ static int __init early_init_dt_scan_memory(unsigned long node,
cell_t *reg, *endp;
unsigned long l;
+ /* Look for the ibm,dynamic-reconfiguration-memory node */
+ if (depth == 1 &&
+ strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
+ return early_init_dt_scan_drconf_memory(node);
+
/* We are scanning "memory" nodes only */
if (type == NULL) {
/*
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 46cf32670dd..520ef42f642 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -679,7 +679,7 @@ static unsigned char ibm_architecture_vec[] = {
/* option vector 5: PAPR/OF options */
3 - 2, /* length */
0, /* don't ignore, don't halt */
- OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
+ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY,
};
/* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 0dfbe1cd28e..12c51e4ad2b 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -920,9 +920,20 @@ static int of_irq_map_oldworld(struct device_node *device, int index,
/*
* Old machines just have a list of interrupt numbers
- * and no interrupt-controller nodes.
+ * and no interrupt-controller nodes. We also have dodgy
+ * cases where the APPL,interrupts property is completely
+ * missing behind pci-pci bridges and we have to get it
+ * from the parent (the bridge itself, as apple just wired
+ * everything together on these)
*/
- ints = get_property(device, "AAPL,interrupts", &intlen);
+ while (device) {
+ ints = get_property(device, "AAPL,interrupts", &intlen);
+ if (ints != NULL)
+ break;
+ device = device->parent;
+ if (device && strcmp(device->type, "pci") != 0)
+ break;
+ }
if (ints == NULL)
return -EINVAL;
intlen /= sizeof(u32);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 387ed0d9ad6..76b5d7ebdcc 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -303,6 +303,12 @@ int rtas_token(const char *service)
}
EXPORT_SYMBOL(rtas_token);
+int rtas_service_present(const char *service)
+{
+ return rtas_token(service) != RTAS_UNKNOWN_SERVICE;
+}
+EXPORT_SYMBOL(rtas_service_present);
+
#ifdef CONFIG_RTAS_ERROR_LOGGING
/*
* Return the firmware-specified size of the error log buffer
@@ -810,32 +816,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
return 0;
}
-#ifdef CONFIG_HOTPLUG_CPU
-/* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
- /* The token is initialized for real in setup_system() */
- .token = RTAS_UNKNOWN_SERVICE,
- .nargs = 0,
- .nret = 1,
- .rets = &rtas_stop_self_args.args[0],
-};
-
-void rtas_stop_self(void)
-{
- struct rtas_args *rtas_args = &rtas_stop_self_args;
-
- local_irq_disable();
-
- BUG_ON(rtas_args->token == RTAS_UNKNOWN_SERVICE);
-
- printk("cpu %u (hwid %u) Ready to die...\n",
- smp_processor_id(), hard_smp_processor_id());
- enter_rtas(__pa(rtas_args));
-
- panic("Alas, I survived.\n");
-}
-#endif
-
/*
* Call early during boot, before mem init or bootmem, to retrieve the RTAS
* informations from the device-tree and allocate the RMO buffer for userland
@@ -880,9 +860,6 @@ void __init rtas_initialize(void)
#endif
rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
-#ifdef CONFIG_HOTPLUG_CPU
- rtas_stop_self_args.token = rtas_token("stop-self");
-#endif /* CONFIG_HOTPLUG_CPU */
#ifdef CONFIG_RTAS_ERROR_LOGGING
rtas_last_error_token = rtas_token("rtas-last-error");
#endif
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 7d0f13fecc0..0c4fcd34bfe 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -193,7 +193,7 @@ static void free_flash_list(struct flash_block_list *f)
static int rtas_flash_release(struct inode *inode, struct file *file)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_update_flash_t *uf;
uf = (struct rtas_update_flash_t *) dp->data;
@@ -255,7 +255,7 @@ static void get_flash_status_msg(int status, char *buf)
static ssize_t rtas_flash_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_update_flash_t *uf;
char msg[RTAS_MSG_MAXLEN];
int msglen;
@@ -299,7 +299,7 @@ void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags)
static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
size_t count, loff_t *off)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_update_flash_t *uf;
char *p;
int next_free;
@@ -391,7 +391,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf)
static ssize_t manage_flash_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_manage_flash_t *args_buf;
char msg[RTAS_MSG_MAXLEN];
int msglen;
@@ -421,7 +421,7 @@ static ssize_t manage_flash_read(struct file *file, char __user *buf,
static ssize_t manage_flash_write(struct file *file, const char __user *buf,
size_t count, loff_t *off)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_manage_flash_t *args_buf;
const char reject_str[] = "0";
const char commit_str[] = "1";
@@ -492,7 +492,7 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
static ssize_t validate_flash_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_validate_flash_t *args_buf;
char msg[RTAS_MSG_MAXLEN];
int msglen;
@@ -520,7 +520,7 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,
static ssize_t validate_flash_write(struct file *file, const char __user *buf,
size_t count, loff_t *off)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_validate_flash_t *args_buf;
int rc;
@@ -569,7 +569,7 @@ done:
static int validate_flash_release(struct inode *inode, struct file *file)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
struct rtas_validate_flash_t *args_buf;
args_buf = (struct rtas_validate_flash_t *) dp->data;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index e4ebe1a6228..6b405a3f43f 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -835,11 +835,21 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
return -EINVAL;
if (old_ctx != NULL) {
+ struct mcontext __user *mctx;
+
+ /*
+ * old_ctx might not be 16-byte aligned, in which
+ * case old_ctx->uc_mcontext won't be either.
+ * Because we have the old_ctx->uc_pad2 field
+ * before old_ctx->uc_mcontext, we need to round down
+ * from &old_ctx->uc_mcontext to a 16-byte boundary.
+ */
+ mctx = (struct mcontext __user *)
+ ((unsigned long) &old_ctx->uc_mcontext & ~0xfUL);
if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
- || save_user_regs(regs, &old_ctx->uc_mcontext, 0)
+ || save_user_regs(regs, mctx, 0)
|| put_sigset_t(&old_ctx->uc_sigmask, &current->blocked)
- || __put_user(to_user_ptr(&old_ctx->uc_mcontext),
- &old_ctx->uc_regs))
+ || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))
return -EFAULT;
}
if (new_ctx == NULL)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9b28c238b6c..0e8beca460a 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -468,7 +468,7 @@ static int __devinit cpu_enable(unsigned int cpu)
return -ENOSYS;
}
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
int c;
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 63ed265b7f0..400ab2b946e 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -181,6 +181,8 @@ SYSFS_PMCSETUP(pmc6, SPRN_PMC6);
SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
SYSFS_PMCSETUP(purr, SPRN_PURR);
+SYSFS_PMCSETUP(spurr, SPRN_SPURR);
+SYSFS_PMCSETUP(dscr, SPRN_DSCR);
static SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0);
static SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1);
@@ -194,6 +196,8 @@ static SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6);
static SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7);
static SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8);
static SYSDEV_ATTR(purr, 0600, show_purr, NULL);
+static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
+static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
static void register_cpu_online(unsigned int cpu)
{
@@ -231,6 +235,12 @@ static void register_cpu_online(unsigned int cpu)
if (cpu_has_feature(CPU_FTR_PURR))
sysdev_create_file(s, &attr_purr);
+
+ if (cpu_has_feature(CPU_FTR_SPURR))
+ sysdev_create_file(s, &attr_spurr);
+
+ if (cpu_has_feature(CPU_FTR_DSCR))
+ sysdev_create_file(s, &attr_dscr);
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -272,6 +282,12 @@ static void unregister_cpu_online(unsigned int cpu)
if (cpu_has_feature(CPU_FTR_PURR))
sysdev_remove_file(s, &attr_purr);
+
+ if (cpu_has_feature(CPU_FTR_SPURR))
+ sysdev_remove_file(s, &attr_spurr);
+
+ if (cpu_has_feature(CPU_FTR_DSCR))
+ sysdev_remove_file(s, &attr_dscr);
}
#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 0d4e203fa7a..535f5066564 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -32,6 +32,7 @@
#include <linux/kprobes.h>
#include <linux/kexec.h>
#include <linux/backlight.h>
+#include <linux/bug.h>
#include <asm/kdebug.h>
#include <asm/pgtable.h>
@@ -727,54 +728,9 @@ static int emulate_instruction(struct pt_regs *regs)
return -EINVAL;
}
-/*
- * Look through the list of trap instructions that are used for BUG(),
- * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
- * that the exception was caused by a trap instruction of some kind.
- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
- * otherwise.
- */
-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
-
-#ifndef CONFIG_MODULES
-#define module_find_bug(x) NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
+int is_valid_bugaddr(unsigned long addr)
{
- struct bug_entry *bug;
-
- for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
- if (bugaddr == bug->bug_addr)
- return bug;
- return module_find_bug(bugaddr);
-}
-
-static int check_bug_trap(struct pt_regs *regs)
-{
- struct bug_entry *bug;
- unsigned long addr;
-
- if (regs->msr & MSR_PR)
- return 0; /* not in kernel */
- addr = regs->nip; /* address of trap instruction */
- if (addr < PAGE_OFFSET)
- return 0;
- bug = find_bug(regs->nip);
- if (bug == NULL)
- return 0;
- if (bug->line & BUG_WARNING_TRAP) {
- /* this is a WARN_ON rather than BUG/BUG_ON */
- printk(KERN_ERR "Badness in %s at %s:%ld\n",
- bug->function, bug->file,
- bug->line & ~BUG_WARNING_TRAP);
- dump_stack();
- return 1;
- }
- printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
- bug->function, bug->file, bug->line);
-
- return 0;
+ return is_kernel_addr(addr);
}
void __kprobes program_check_exception(struct pt_regs *regs)
@@ -782,6 +738,8 @@ void __kprobes program_check_exception(struct pt_regs *regs)
unsigned int reason = get_reason(regs);
extern int do_mathemu(struct pt_regs *regs);
+ /* We can now get here via a FP Unavailable exception if the core
+ * has no FPU, in that case no reason flags will be set */
#ifdef CONFIG_MATH_EMULATION
/* (reason & REASON_ILLEGAL) would be the obvious thing here,
* but there seems to be a hardware bug on the 405GP (RevD)
@@ -808,7 +766,9 @@ void __kprobes program_check_exception(struct pt_regs *regs)
return;
if (debugger_bpt(regs))
return;
- if (check_bug_trap(regs)) {
+
+ if (!(regs->msr & MSR_PR) && /* not user-mode */
+ report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
regs->nip += 4;
return;
}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index a4b28c73bba..ae0ede19879 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -284,6 +284,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
* pages though
*/
vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+ * without matching up the same kernel and hardware config to see
+ * what PC values meant.
+ */
+ vma->vm_flags |= VM_ALWAYSDUMP;
vma->vm_flags |= mm->def_flags;
vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
vma->vm_ops = &vdso_vmops;
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 04b98671a06..04b8e71bf5b 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -62,11 +62,7 @@ SECTIONS
__stop___ex_table = .;
}
- __bug_table : {
- __start___bug_table = .;
- *(__bug_table)
- __stop___bug_table = .;
- }
+ BUG_TABLE
/*
* Init sections discarded at runtime
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 89c836d5480..1bb20d84108 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -744,7 +744,8 @@ static int htlb_check_hinted_area(unsigned long addr, unsigned long len)
struct vm_area_struct *vma;
vma = find_vma(current->mm, addr);
- if (!vma || ((addr + len) <= vma->vm_start))
+ if (TASK_SIZE - len >= addr &&
+ (!vma || ((addr + len) <= vma->vm_start)))
return 0;
return -ENOMEM;
@@ -815,6 +816,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return -EINVAL;
if (len & ~HPAGE_MASK)
return -EINVAL;
+ if (len > TASK_SIZE)
+ return -ENOMEM;
if (!cpu_has_feature(CPU_FTR_16M_PAGE))
return -EINVAL;
@@ -823,9 +826,6 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
BUG_ON((addr + len) < addr);
if (test_thread_flag(TIF_32BIT)) {
- /* Paranoia, caller should have dealt with this */
- BUG_ON((addr + len) > 0x100000000UL);
-
curareas = current->mm->context.low_htlb_areas;
/* First see if we can use the hint address */
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
index add8c1a9af6..c831815c31f 100644
--- a/arch/powerpc/mm/imalloc.c
+++ b/arch/powerpc/mm/imalloc.c
@@ -138,7 +138,7 @@ static struct vm_struct * split_im_region(unsigned long v_addr,
struct vm_struct *vm2 = NULL;
struct vm_struct *new_vm = NULL;
- vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL);
+ vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
if (vm1 == NULL) {
printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
return NULL;
@@ -172,7 +172,7 @@ static struct vm_struct * split_im_region(unsigned long v_addr,
* uppermost remainder, and use existing parent one for the
* lower remainder of parent range
*/
- vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL);
+ vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
if (vm2 == NULL) {
printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
kfree(vm1);
@@ -206,7 +206,7 @@ static struct vm_struct * __add_new_im_area(unsigned long req_addr,
break;
}
- area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
area->flags = 0;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 9da01dc8cfd..262790910ff 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -295,6 +295,63 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start,
return lmb_end_of_DRAM() - start;
}
+/*
+ * Extract NUMA information from the ibm,dynamic-reconfiguration-memory
+ * node. This assumes n_mem_{addr,size}_cells have been set.
+ */
+static void __init parse_drconf_memory(struct device_node *memory)
+{
+ const unsigned int *lm, *dm, *aa;
+ unsigned int ls, ld, la;
+ unsigned int n, aam, aalen;
+ unsigned long lmb_size, size;
+ int nid, default_nid = 0;
+ unsigned int start, ai, flags;
+
+ lm = get_property(memory, "ibm,lmb-size", &ls);
+ dm = get_property(memory, "ibm,dynamic-memory", &ld);
+ aa = get_property(memory, "ibm,associativity-lookup-arrays", &la);
+ if (!lm || !dm || !aa ||
+ ls < sizeof(unsigned int) || ld < sizeof(unsigned int) ||
+ la < 2 * sizeof(unsigned int))
+ return;
+
+ lmb_size = read_n_cells(n_mem_size_cells, &lm);
+ n = *dm++; /* number of LMBs */
+ aam = *aa++; /* number of associativity lists */
+ aalen = *aa++; /* length of each associativity list */
+ if (ld < (n * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int) ||
+ la < (aam * aalen + 2) * sizeof(unsigned int))
+ return;
+
+ for (; n != 0; --n) {
+ start = read_n_cells(n_mem_addr_cells, &dm);
+ ai = dm[2];
+ flags = dm[3];
+ dm += 4;
+ /* 0x80 == reserved, 0x8 = assigned to us */
+ if ((flags & 0x80) || !(flags & 0x8))
+ continue;
+ nid = default_nid;
+ /* flags & 0x40 means associativity index is invalid */
+ if (min_common_depth > 0 && min_common_depth <= aalen &&
+ (flags & 0x40) == 0 && ai < aam) {
+ /* this is like of_node_to_nid_single */
+ nid = aa[ai * aalen + min_common_depth - 1];
+ if (nid == 0xffff || nid >= MAX_NUMNODES)
+ nid = default_nid;
+ }
+ node_set_online(nid);
+
+ size = numa_enforce_memory_limit(start, lmb_size);
+ if (!size)
+ continue;
+
+ add_active_range(nid, start >> PAGE_SHIFT,
+ (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
+ }
+}
+
static int __init parse_numa_properties(void)
{
struct device_node *cpu = NULL;
@@ -385,6 +442,14 @@ new_range:
goto new_range;
}
+ /*
+ * Now do the same thing for each LMB listed in the ibm,dynamic-memory
+ * property in the ibm,dynamic-reconfiguration-memory node.
+ */
+ memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+ if (memory)
+ parse_drconf_memory(memory);
+
return 0;
}
diff --git a/arch/powerpc/platforms/4xx/Kconfig b/arch/powerpc/platforms/4xx/Kconfig
index ed39d6a3d22..2f2a13ed766 100644
--- a/arch/powerpc/platforms/4xx/Kconfig
+++ b/arch/powerpc/platforms/4xx/Kconfig
@@ -179,7 +179,7 @@ config BIOS_FIXUP
# OAK doesn't exist but wanted to keep this around for any future 403GCX boards
config 403GCX
bool
- depends OAK
+ depends on OAK
default y
config 405EP
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index a375c15b431..0f21bab33f6 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -40,8 +40,6 @@
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
@@ -155,6 +153,7 @@ define_machine(lite52xx) {
.name = "lite52xx",
.probe = lite52xx_probe,
.setup_arch = lite52xx_setup_arch,
+ .init = mpc52xx_declare_of_platform_devices,
.init_IRQ = mpc52xx_init_irq,
.get_irq = mpc52xx_get_irq,
.show_cpuinfo = lite52xx_show_cpuinfo,
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 8331ff45777..cc40889074b 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -116,11 +116,12 @@ unmap_regs:
if (xlb) iounmap(xlb);
}
-static int __init
+void __init
mpc52xx_declare_of_platform_devices(void)
{
/* Find every child of the SOC node and add it to of_platform */
- return of_platform_bus_probe(NULL, NULL, NULL);
+ if (of_platform_bus_probe(NULL, NULL, NULL))
+ printk(KERN_ERR __FILE__ ": "
+ "Error while probing of_platform bus\n");
}
-device_initcall(mpc52xx_declare_of_platform_devices);
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index f58c9780b66..4d471190be8 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -103,7 +103,7 @@ static void __init mpc832x_sys_setup_arch(void)
#ifdef CONFIG_QUICC_ENGINE
qe_reset();
- if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+ if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
par_io_init(np);
of_node_put(np);
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
index 7bfd47ad723..53b92a904e8 100644
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
@@ -108,7 +108,7 @@ static void __init mpc8360_sys_setup_arch(void)
#ifdef CONFIG_QUICC_ENGINE
qe_reset();
- if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+ if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
par_io_init(np);
of_node_put(np);
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 44d95eaf22e..507d1b98f27 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -5,9 +5,9 @@ ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_PPC_PMAC) += powermac/
endif
endif
+obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_CHRP) += chrp/
obj-$(CONFIG_4xx) += 4xx/
-obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_83xx) += 83xx/
obj-$(CONFIG_PPC_85xx) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index 616a0a3fd0e..70e0d968d30 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -115,6 +115,7 @@ static struct sysdev_attribute attr_spu_temperature = {
static struct attribute *spu_attributes[] = {
&attr_spu_temperature.attr,
+ NULL,
};
static struct attribute_group spu_attribute_group = {
@@ -135,6 +136,7 @@ static struct sysdev_attribute attr_ppe_temperature1 = {
static struct attribute *ppe_attributes[] = {
&attr_ppe_temperature0.attr,
&attr_ppe_temperature1.attr,
+ NULL,
};
static struct attribute_group ppe_attribute_group = {
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 580d4259591..7c73128305e 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -37,7 +37,7 @@
*/
#define SPIDER_DISABLE_PREFETCH
-#define MAX_SPIDERS 2
+#define MAX_SPIDERS 3
static struct spider_pci_bus {
void __iomem *regs;
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index 99c612025e8..d04ae1671e6 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -382,11 +382,14 @@ static irqreturn_t cbe_pm_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-int __init cbe_init_pm_irq(void)
+static int __init cbe_init_pm_irq(void)
{
unsigned int irq;
int rc, node;
+ if (!machine_is(cell))
+ return 0;
+
for_each_node(node) {
irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI |
(node << IIC_IRQ_NODE_SHIFT));
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
index a5de0430c56..910a926b61a 100644
--- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
@@ -37,8 +37,9 @@
#include "interrupt.h"
#include "spu_priv1_mmio.h"
+static DEFINE_MUTEX(add_spumem_mutex);
+
struct spu_pdata {
- int nid;
struct device_node *devnode;
struct spu_priv1 __iomem *priv1;
};
@@ -56,20 +57,9 @@ struct device_node *spu_devnode(struct spu *spu)
EXPORT_SYMBOL_GPL(spu_devnode);
-static int __init find_spu_node_id(struct device_node *spe)
-{
- const unsigned int *id;
- struct device_node *cpu;
- cpu = spe->parent->parent;
- id = get_property(cpu, "node-id", NULL);
- return id ? *id : 0;
-}
-
static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
const char *prop)
{
- static DEFINE_MUTEX(add_spumem_mutex);
-
const struct address_prop {
unsigned long address;
unsigned int len;
@@ -87,7 +77,7 @@ static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
start_pfn = p->address >> PAGE_SHIFT;
nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- pgdata = NODE_DATA(spu_get_pdata(spu)->nid);
+ pgdata = NODE_DATA(spu->node);
zone = pgdata->node_zones;
/* XXX rethink locking here */
@@ -140,6 +130,7 @@ static int __init spu_map_interrupts_old(struct spu *spu,
{
unsigned int isrc;
const u32 *tmp;
+ int nid;
/* Get the interrupt source unit from the device-tree */
tmp = get_property(np, "isrc", NULL);
@@ -147,8 +138,15 @@ static int __init spu_map_interrupts_old(struct spu *spu,
return -ENODEV;
isrc = tmp[0];
+ tmp = get_property(np->parent->parent, "node-id", NULL);
+ if (!tmp) {
+ printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__);
+ nid = spu->node;
+ } else
+ nid = tmp[0];
+
/* Add the node number */
- isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
+ isrc |= nid << IIC_IRQ_NODE_SHIFT;
/* Now map interrupts of all 3 classes */
spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
@@ -237,70 +235,88 @@ err:
return ret;
}
-static int spu_map_resource(struct device_node *node, int nr,
- void __iomem** virt, unsigned long *phys)
+static int spu_map_resource(struct spu *spu, int nr,
+ void __iomem** virt, unsigned long *phys)
{
+ struct device_node *np = spu_get_pdata(spu)->devnode;
+ unsigned long start_pfn, nr_pages;
+ struct pglist_data *pgdata;
+ struct zone *zone;
struct resource resource = { };
+ unsigned long len;
int ret;
- ret = of_address_to_resource(node, nr, &resource);
+ ret = of_address_to_resource(np, nr, &resource);
if (ret)
goto out;
if (phys)
*phys = resource.start;
- *virt = ioremap(resource.start, resource.end - resource.start);
+ len = resource.end - resource.start + 1;
+ *virt = ioremap(resource.start, len);
if (!*virt)
ret = -EINVAL;
+ start_pfn = resource.start >> PAGE_SHIFT;
+ nr_pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ pgdata = NODE_DATA(spu->node);
+ zone = pgdata->node_zones;
+
+ /* XXX rethink locking here */
+ mutex_lock(&add_spumem_mutex);
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ mutex_unlock(&add_spumem_mutex);
+
out:
return ret;
}
-static int __init spu_map_device(struct spu *spu, struct device_node *node)
+static int __init spu_map_device(struct spu *spu)
{
+ struct device_node *np = spu_get_pdata(spu)->devnode;
int ret = -ENODEV;
- spu->name = get_property(node, "name", NULL);
+
+ spu->name = get_property(np, "name", NULL);
if (!spu->name)
goto out;
- ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
- &spu->local_store_phys);
+ ret = spu_map_resource(spu, 0, (void __iomem**)&spu->local_store,
+ &spu->local_store_phys);
if (ret) {
pr_debug("spu_new: failed to map %s resource 0\n",
- node->full_name);
+ np->full_name);
goto out;
}
- ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
- &spu->problem_phys);
+ ret = spu_map_resource(spu, 1, (void __iomem**)&spu->problem,
+ &spu->problem_phys);
if (ret) {
pr_debug("spu_new: failed to map %s resource 1\n",
- node->full_name);
+ np->full_name);
goto out_unmap;
}
- ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
- NULL);
+ ret = spu_map_resource(spu, 2, (void __iomem**)&spu->priv2, NULL);
if (ret) {
pr_debug("spu_new: failed to map %s resource 2\n",
- node->full_name);
+ np->full_name);
goto out_unmap;
}
if (!firmware_has_feature(FW_FEATURE_LPAR))
- ret = spu_map_resource(node, 3,
- (void __iomem**)&spu_get_pdata(spu)->priv1, NULL);
+ ret = spu_map_resource(spu, 3,
+ (void __iomem**)&spu_get_pdata(spu)->priv1, NULL);
if (ret) {
pr_debug("spu_new: failed to map %s resource 3\n",
- node->full_name);
+ np->full_name);
goto out_unmap;
}
- pr_debug("spu_new: %s maps:\n", node->full_name);
+ pr_debug("spu_new: %s maps:\n", np->full_name);
pr_debug(" local store : 0x%016lx -> 0x%p\n",
spu->local_store_phys, spu->local_store);
pr_debug(" problem state : 0x%016lx -> 0x%p\n",
spu->problem_phys, spu->problem);
pr_debug(" priv2 : 0x%p\n", spu->priv2);
pr_debug(" priv1 : 0x%p\n",
- spu_get_pdata(spu)->priv1);
+ spu_get_pdata(spu)->priv1);
return 0;
@@ -340,8 +356,9 @@ static int __init of_create_spu(struct spu *spu, void *data)
ret = -ENOMEM;
goto out;
}
+ spu_get_pdata(spu)->devnode = of_node_get(spe);
- spu->node = find_spu_node_id(spe);
+ spu->node = of_node_to_nid(spe);
if (spu->node >= MAX_NUMNODES) {
printk(KERN_WARNING "SPE %s on node %d ignored,"
" node number too big\n", spe->full_name, spu->node);
@@ -350,11 +367,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
goto out_free;
}
- spu_get_pdata(spu)->nid = of_node_to_nid(spe);
- if (spu_get_pdata(spu)->nid == -1)
- spu_get_pdata(spu)->nid = 0;
-
- ret = spu_map_device(spu, spe);
+ ret = spu_map_device(spu);
/* try old method */
if (ret)
ret = spu_map_device_old(spu, spe);
@@ -367,8 +380,6 @@ static int __init of_create_spu(struct spu *spu, void *data)
if (ret)
goto out_unmap;
- spu_get_pdata(spu)->devnode = of_node_get(spe);
-
pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", spu->name,
spu->local_store, spu->problem, spu_get_pdata(spu)->priv1,
spu->priv2, spu->number);
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 26945c491f6..725e1956115 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -147,7 +147,7 @@ static int spufs_arch_notes_size(void)
struct fdtable *fdt = files_fdtable(current->files);
int size = 0, fd;
- for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) {
+ for (fd = 0; fd < fdt->max_fds; fd++) {
if (FD_ISSET(fd, fdt->open_fds)) {
struct file *file = fcheck(fd);
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index e3af9112c02..738b9244382 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -205,7 +205,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
struct dentry *dir;
int ret;
- dir = file->f_dentry;
+ dir = file->f_path.dentry;
parent = dir->d_parent->d_inode;
ctx = SPUFS_I(dir->d_inode)->i_ctx;
@@ -363,7 +363,7 @@ static int spufs_gang_close(struct inode *inode, struct file *file)
struct dentry *dir;
int ret;
- dir = file->f_dentry;
+ dir = file->f_path.dentry;
parent = dir->d_parent->d_inode;
ret = spufs_rmgang(parent, dir);
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index a6d1ae4dc2a..8e37bdf4dfd 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -46,7 +46,7 @@ static long do_spu_run(struct file *filp,
if (filp->f_op != &spufs_context_fops)
goto out;
- i = SPUFS_I(filp->f_dentry->d_inode);
+ i = SPUFS_I(filp->f_path.dentry->d_inode);
ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
if (put_user(npc, unpc))
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index ddbe398fbd4..b3c2ce4cb7a 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -35,7 +35,7 @@ config HDPU
Select HDPU if configuring a Sky Computers Compute Blade.
config HDPU_FEATURES
- depends HDPU
+ depends on HDPU
tristate "HDPU-Features"
help
Select to enable HDPU enhanced features.
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index 887b68804e6..54e6b3b6f26 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -31,5 +31,5 @@ endmenu
config VIOPATH
bool
- depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH
+ depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || ISERIES_VETH
default y
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index e3e929e1b46..c1f4502a3c6 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -17,6 +17,7 @@
#include <asm/system.h>
#include <asm/paca.h>
+#include <asm/firmware.h>
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_call_event.h>
@@ -318,6 +319,9 @@ static int __init proc_lpevents_init(void)
{
struct proc_dir_entry *e;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
if (e)
e->proc_fops = &proc_lpevents_operations;
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index b5737d68d6c..1ad0e4aaad1 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -38,6 +38,7 @@
#include <asm/uaccess.h>
#include <asm/paca.h>
#include <asm/abs_addr.h>
+#include <asm/firmware.h>
#include <asm/iseries/vio.h>
#include <asm/iseries/mf.h>
#include <asm/iseries/hv_lp_config.h>
@@ -1178,7 +1179,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
- struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
ssize_t rc;
dma_addr_t dma_addr;
char *page;
@@ -1235,6 +1236,9 @@ static int __init mf_proc_init(void)
char name[2];
int i;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
mf_proc_root = proc_mkdir("iSeries/mf", NULL);
if (!mf_proc_root)
return 1;
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
index c241413629a..b54e37101e6 100644
--- a/arch/powerpc/platforms/iseries/proc.c
+++ b/arch/powerpc/platforms/iseries/proc.c
@@ -24,6 +24,7 @@
#include <asm/processor.h>
#include <asm/time.h>
#include <asm/lppaca.h>
+#include <asm/firmware.h>
#include <asm/iseries/hv_call_xm.h>
#include "processor_vpd.h"
@@ -31,7 +32,12 @@
static int __init iseries_proc_create(void)
{
- struct proc_dir_entry *e = proc_mkdir("iSeries", 0);
+ struct proc_dir_entry *e;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
+ e = proc_mkdir("iSeries", 0);
if (!e)
return 1;
@@ -106,6 +112,9 @@ static int __init iseries_proc_init(void)
{
struct proc_dir_entry *e;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
if (e)
e->proc_fops = &proc_titantod_operations;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index bdf2afbb60c..cce7e309340 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -527,7 +527,8 @@ static void __init iSeries_fixup_klimit(void)
static int __init iSeries_src_init(void)
{
/* clear the progress line */
- ppc_md.progress(" ", 0xffff);
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ ppc_md.progress(" ", 0xffff);
return 0;
}
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 84e7ee2c086..a6799ed34a6 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -42,6 +42,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/prom.h>
+#include <asm/firmware.h>
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_lp_config.h>
@@ -183,6 +184,9 @@ static int __init vio_proc_init(void)
{
struct proc_dir_entry *e;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+
e = create_proc_entry("iSeries/config", 0, NULL);
if (e)
e->proc_fops = &proc_viopath_operations;
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 3a32deda765..3f6a69f6719 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -562,7 +562,7 @@ void __init maple_pci_init(void)
for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
if (np->name == NULL)
continue;
- if (strcmp(np->name, "pci") == 0) {
+ if (!strcmp(np->name, "pci") || !strcmp(np->name, "pcie")) {
if (add_bridge(np) == 0)
of_node_get(np);
}
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 094989d50ba..50855d4fd5a 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -60,6 +60,7 @@
#include <asm/of_device.h>
#include <asm/lmb.h>
#include <asm/mpic.h>
+#include <asm/rtas.h>
#include <asm/udbg.h>
#include "maple.h"
@@ -166,6 +167,16 @@ struct smp_ops_t maple_smp_ops = {
};
#endif /* CONFIG_SMP */
+static void __init maple_use_rtas_reboot_and_halt_if_present(void)
+{
+ if (rtas_service_present("system-reboot") &&
+ rtas_service_present("power-off")) {
+ ppc_md.restart = rtas_restart;
+ ppc_md.power_off = rtas_power_off;
+ ppc_md.halt = rtas_halt;
+ }
+}
+
void __init maple_setup_arch(void)
{
/* init to some ~sane value until calibrate_delay() runs */
@@ -181,6 +192,7 @@ void __init maple_setup_arch(void)
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
+ maple_use_rtas_reboot_and_halt_if_present();
printk(KERN_DEBUG "Using native/NAP idle loop\n");
}
@@ -242,7 +254,6 @@ static void __init maple_init_IRQ(void)
printk(KERN_DEBUG "OpenPIC addr: %lx, has ISUs: %d\n",
openpic_addr, has_isus);
}
- of_node_put(root);
BUG_ON(openpic_addr == 0);
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 89d6e295dbf..bea7d1bb1a3 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -129,7 +129,6 @@ static __init void pas_init_IRQ(void)
}
openpic_addr = of_read_number(opprop, naddr);
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
- of_node_put(root);
mpic = mpic_alloc(mpic_node, openpic_addr, MPIC_PRIMARY, 0, 0,
" PAS-OPIC ");
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 451bfcd5502..de52ec4e9e5 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -40,4 +40,15 @@ config PS3_USE_LPAR_ADDR
If you have any doubt, choose the default y.
+config PS3_VUART
+ depends on PPC_PS3
+ bool "PS3 Virtual UART support"
+ default y
+ help
+ Include support for the PS3 Virtual UART.
+
+ This support is required for several system services
+ including the System Manager and AV Settings. In
+ general, all users will say Y.
+
endmenu
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile
index 3757cfabc8c..1994904f580 100644
--- a/arch/powerpc/platforms/ps3/Makefile
+++ b/arch/powerpc/platforms/ps3/Makefile
@@ -1,4 +1,5 @@
-obj-y += setup.o mm.o smp.o time.o hvcall.o htab.o repository.o
+obj-y += setup.o mm.o time.o hvcall.o htab.o repository.o
obj-y += interrupt.o exports.o os-area.o
+obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SPU_BASE) += spu.o
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 056c1e4141b..6f5de438b98 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -71,7 +71,7 @@ int ps3_free_io_irq(unsigned int virq)
result = lv1_destruct_io_irq_outlet(virq_to_hw(virq));
- if (!result)
+ if (result)
pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
__func__, __LINE__, ps3_result(result));
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 997243a91be..69590fbf83d 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
+
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 3c2d63ebf78..da6e5362e7c 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -337,6 +337,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n",
pdn->eeh_check_count);
dump_stack();
+ msleep(5000);
/* re-read the slot reset state */
if (read_slot_reset_state(pdn, rets) != 0)
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index b6b462d3c60..f2bae04424f 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -153,7 +153,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
return piar;
}
}
- piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+ piar = kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
if (!piar)
return NULL;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index c2bc9904f1c..cbd6b0711ab 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -170,14 +170,19 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
static void eeh_report_resume(struct pci_dev *dev, void *userdata)
{
struct pci_driver *driver = dev->driver;
+ struct device_node *dn = pci_device_to_OF_node(dev);
dev->error_state = pci_channel_io_normal;
if (!driver)
return;
- if (!driver->err_handler)
- return;
- if (!driver->err_handler->resume)
+
+ if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+ PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+ enable_irq(dev->irq);
+ }
+ if (!driver->err_handler ||
+ !driver->err_handler->resume)
return;
driver->err_handler->resume(dev);
@@ -407,6 +412,8 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
if (rc)
result = PCI_ERS_RESULT_NEED_RESET;
+ else
+ result = PCI_ERS_RESULT_RECOVERED;
}
/* If any device has a hard failure, then shut off everything. */
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
new file mode 100644
index 00000000000..f460b9cbfd4
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -0,0 +1,275 @@
+/*
+ * pseries CPU Hotplug infrastructure.
+ *
+ * Split out from arch/powerpc/platforms/pseries/setup.c
+ * arch/powerpc/kernel/rtas.c, and arch/powerpc/platforms/pseries/smp.c
+ *
+ * Peter Bergner, IBM March 2001.
+ * Copyright (C) 2001 IBM.
+ * Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+ * Plus various changes from other IBM teams...
+ *
+ * Copyright (C) 2006 Michael Ellerman, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as 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/delay.h>
+#include <linux/cpu.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/firmware.h>
+#include <asm/machdep.h>
+#include <asm/vdso_datapage.h>
+#include <asm/pSeries_reconfig.h>
+#include "xics.h"
+
+/* This version can't take the spinlock, because it never returns */
+static struct rtas_args rtas_stop_self_args = {
+ .token = RTAS_UNKNOWN_SERVICE,
+ .nargs = 0,
+ .nret = 1,
+ .rets = &rtas_stop_self_args.args[0],
+};
+
+static void rtas_stop_self(void)
+{
+ struct rtas_args *args = &rtas_stop_self_args;
+
+ local_irq_disable();
+
+ BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+
+ printk("cpu %u (hwid %u) Ready to die...\n",
+ smp_processor_id(), hard_smp_processor_id());
+ enter_rtas(__pa(args));
+
+ panic("Alas, I survived.\n");
+}
+
+static void pseries_mach_cpu_die(void)
+{
+ local_irq_disable();
+ idle_task_exit();
+ xics_teardown_cpu(0);
+ rtas_stop_self();
+ /* Should never get here... */
+ BUG();
+ for(;;);
+}
+
+static int qcss_tok; /* query-cpu-stopped-state token */
+
+/* Get state of physical CPU.
+ * Return codes:
+ * 0 - The processor is in the RTAS stopped state
+ * 1 - stop-self is in progress
+ * 2 - The processor is not in the RTAS stopped state
+ * -1 - Hardware Error
+ * -2 - Hardware Busy, Try again later.
+ */
+static int query_cpu_stopped(unsigned int pcpu)
+{
+ int cpu_status, status;
+
+ status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+ if (status != 0) {
+ printk(KERN_ERR
+ "RTAS query-cpu-stopped-state failed: %i\n", status);
+ return status;
+ }
+
+ return cpu_status;
+}
+
+static int pseries_cpu_disable(void)
+{
+ int cpu = smp_processor_id();
+
+ cpu_clear(cpu, cpu_online_map);
+ vdso_data->processorCount--;
+
+ /*fix boot_cpuid here*/
+ if (cpu == boot_cpuid)
+ boot_cpuid = any_online_cpu(cpu_online_map);
+
+ /* FIXME: abstract this to not be platform specific later on */
+ xics_migrate_irqs_away();
+ return 0;
+}
+
+static void pseries_cpu_die(unsigned int cpu)
+{
+ int tries;
+ int cpu_status;
+ unsigned int pcpu = get_hard_smp_processor_id(cpu);
+
+ for (tries = 0; tries < 25; tries++) {
+ cpu_status = query_cpu_stopped(pcpu);
+ if (cpu_status == 0 || cpu_status == -1)
+ break;
+ msleep(200);
+ }
+ if (cpu_status != 0) {
+ printk("Querying DEAD? cpu %i (%i) shows %i\n",
+ cpu, pcpu, cpu_status);
+ }
+
+ /* Isolation and deallocation are definatly done by
+ * drslot_chrp_cpu. If they were not they would be
+ * done here. Change isolate state to Isolate and
+ * change allocation-state to Unusable.
+ */
+ paca[cpu].cpu_start = 0;
+}
+
+/*
+ * 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 int pseries_add_processor(struct device_node *np)
+{
+ unsigned int cpu;
+ cpumask_t candidate_map, tmp = CPU_MASK_NONE;
+ int err = -ENOSPC, len, nthreads, i;
+ const u32 *intserv;
+
+ intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ if (!intserv)
+ return 0;
+
+ nthreads = len / sizeof(u32);
+ for (i = 0; i < nthreads; i++)
+ cpu_set(i, tmp);
+
+ lock_cpu_hotplug();
+
+ BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
+
+ /* 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.
+ */
+ 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;
+ }
+
+ 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;
+ const u32 *intserv;
+
+ intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ if (!intserv)
+ return;
+
+ nthreads = len / sizeof(u32);
+
+ 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]);
+ }
+ 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,
+};
+
+static int __init pseries_cpu_hotplug_init(void)
+{
+ rtas_stop_self_args.token = rtas_token("stop-self");
+ qcss_tok = rtas_token("query-cpu-stopped-state");
+
+ if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+ qcss_tok == RTAS_UNKNOWN_SERVICE) {
+ printk(KERN_INFO "CPU Hotplug not supported by firmware "
+ "- disabling.\n");
+ return 0;
+ }
+
+ ppc_md.cpu_die = pseries_mach_cpu_die;
+ smp_ops->cpu_disable = pseries_cpu_disable;
+ smp_ops->cpu_die = pseries_cpu_die;
+
+ /* Processors can be added/removed only on LPAR */
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+ pSeries_reconfig_notifier_register(&pseries_smp_nb);
+
+ return 0;
+}
+arch_initcall(pseries_cpu_hotplug_init);
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index c00cfed7af2..5c7e3878989 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -26,7 +26,7 @@
BEGIN_FTR_SECTION; \
mfspr r0,SPRN_PURR; /* get PURR and */ \
std r0,STK_PARM(r6)(r1); /* save for later */ \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR);
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);
/*
* postcall is performed immediately before function return which
@@ -43,7 +43,7 @@ BEGIN_FTR_SECTION; \
mfspr r8,SPRN_PURR; /* PURR after */ \
ld r6,STK_PARM(r6)(r1); /* PURR before */ \
subf r6,r6,r8; /* delta */ \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
+END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
ld r5,STK_PARM(r5)(r1); /* timebase before */ \
subf r5,r5,r7; /* time delta */ \
\
@@ -66,7 +66,7 @@ BEGIN_FTR_SECTION; \
ld r7,HCALL_STAT_PURR(r4); /* PURR */ \
add r7,r7,r6; \
std r7,HCALL_STAT_PURR(r4); \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
+END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
1:
#else
#define HCALL_INST_PRECALL
@@ -145,6 +145,7 @@ _GLOBAL(plpar_hcall9)
HVSC /* invoke the hypervisor */
+ mr r0,r12
ld r12,STK_PARM(r4)(r1)
std r4, 0(r12)
std r5, 8(r12)
@@ -154,7 +155,7 @@ _GLOBAL(plpar_hcall9)
std r9, 40(r12)
std r10,48(r12)
std r11,56(r12)
- std r12,64(r12)
+ std r0, 64(r12)
HCALL_INST_POSTCALL
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index 446e17d162a..3ddc04925d5 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -34,7 +34,7 @@ DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats);
*/
static void *hc_start(struct seq_file *m, loff_t *pos)
{
- if ((int)*pos < HCALL_STAT_ARRAY_SIZE)
+ if ((int)*pos < (HCALL_STAT_ARRAY_SIZE-1))
return (void *)(unsigned long)(*pos + 1);
return NULL;
@@ -57,7 +57,7 @@ static int hc_show(struct seq_file *m, void *p)
struct hcall_stats *hs = (struct hcall_stats *)m->private;
if (hs[h_num].num_calls) {
- if (!cpu_has_feature(CPU_FTR_PURR))
+ if (cpu_has_feature(CPU_FTR_PURR))
seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2,
hs[h_num].num_calls,
hs[h_num].tb_total,
@@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file)
rc = seq_open(file, &hcall_inst_seq_ops);
seq = file->private_data;
- seq->private = file->f_dentry->d_inode->i_private;
+ seq->private = file->f_path.dentry->d_inode->i_private;
return rc;
}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 3c95392f4f4..e6653a868b9 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -459,7 +459,8 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
phb->node);
iommu_table_setparms(phb, dn, tbl);
- dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node);
+ PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);
+ dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;
return;
}
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 77a5bb1d9c3..45368a57d7d 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -47,7 +47,7 @@ static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */
static ssize_t scanlog_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
struct proc_dir_entry *dp;
unsigned int *data;
int status;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 0dc2548ca9b..042ecae107a 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -347,21 +347,6 @@ static int __init pSeries_init_panel(void)
}
arch_initcall(pSeries_init_panel);
-#ifdef CONFIG_HOTPLUG_CPU
-static void pSeries_mach_cpu_die(void)
-{
- local_irq_disable();
- idle_task_exit();
- xics_teardown_cpu(0);
- rtas_stop_self();
- /* Should never get here... */
- BUG();
- for(;;);
-}
-#else
-#define pSeries_mach_cpu_die NULL
-#endif
-
static int pseries_set_dabr(unsigned long dabr)
{
return plpar_hcall_norets(H_SET_DABR, dabr);
@@ -437,19 +422,14 @@ static int __init pSeries_probe_hypertas(unsigned long node,
if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
powerpc_firmware_features |= FW_FEATURE_LPAR;
- if (firmware_has_feature(FW_FEATURE_LPAR))
- hpte_init_lpar();
- else
- hpte_init_native();
-
return 1;
}
static int __init pSeries_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "device_type", NULL);
+ char *dtype = of_get_flat_dt_prop(root, "device_type", NULL);
+
if (dtype == NULL)
return 0;
if (strcmp(dtype, "chrp"))
@@ -467,6 +447,11 @@ static int __init pSeries_probe(void)
/* Now try to figure out if we are running on LPAR */
of_scan_flat_dt(pSeries_probe_hypertas, NULL);
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+ hpte_init_lpar();
+ else
+ hpte_init_native();
+
DBG("Machine is%s LPAR !\n",
(powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
@@ -561,7 +546,6 @@ define_machine(pseries) {
.power_off = rtas_power_off,
.halt = rtas_halt,
.panic = rtas_os_term,
- .cpu_die = pSeries_mach_cpu_die,
.get_boot_time = rtas_get_boot_time,
.get_rtc_time = rtas_get_rtc_time,
.set_rtc_time = rtas_set_rtc_time,
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index c6624b8a0e7..4408518eaeb 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -64,197 +64,6 @@ static cpumask_t of_spin_map;
extern void generic_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
- * 1 - stop-self is in progress
- * 2 - The processor is not in the RTAS stopped state
- * -1 - Hardware Error
- * -2 - Hardware Busy, Try again later.
- */
-static int query_cpu_stopped(unsigned int pcpu)
-{
- int cpu_status;
- int status, qcss_tok;
-
- qcss_tok = rtas_token("query-cpu-stopped-state");
- if (qcss_tok == RTAS_UNKNOWN_SERVICE)
- return -1;
- status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
- if (status != 0) {
- printk(KERN_ERR
- "RTAS query-cpu-stopped-state failed: %i\n", status);
- return status;
- }
-
- return cpu_status;
-}
-
-static int pSeries_cpu_disable(void)
-{
- int cpu = smp_processor_id();
-
- cpu_clear(cpu, cpu_online_map);
- vdso_data->processorCount--;
-
- /*fix boot_cpuid here*/
- if (cpu == boot_cpuid)
- boot_cpuid = any_online_cpu(cpu_online_map);
-
- /* FIXME: abstract this to not be platform specific later on */
- xics_migrate_irqs_away();
- return 0;
-}
-
-static void pSeries_cpu_die(unsigned int cpu)
-{
- int tries;
- int cpu_status;
- unsigned int pcpu = get_hard_smp_processor_id(cpu);
-
- for (tries = 0; tries < 25; tries++) {
- cpu_status = query_cpu_stopped(pcpu);
- if (cpu_status == 0 || cpu_status == -1)
- break;
- msleep(200);
- }
- if (cpu_status != 0) {
- printk("Querying DEAD? cpu %i (%i) shows %i\n",
- cpu, pcpu, cpu_status);
- }
-
- /* Isolation and deallocation are definatly done by
- * drslot_chrp_cpu. If they were not they would be
- * done here. Change isolate state to Isolate and
- * change allocation-state to Unusable.
- */
- paca[cpu].cpu_start = 0;
-}
-
-/*
- * 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 int pSeries_add_processor(struct device_node *np)
-{
- unsigned int cpu;
- cpumask_t candidate_map, tmp = CPU_MASK_NONE;
- int err = -ENOSPC, len, nthreads, i;
- const u32 *intserv;
-
- intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
- if (!intserv)
- return 0;
-
- nthreads = len / sizeof(u32);
- for (i = 0; i < nthreads; i++)
- cpu_set(i, tmp);
-
- lock_cpu_hotplug();
-
- BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
-
- /* 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.
- */
- 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;
- }
-
- 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;
- const u32 *intserv;
-
- intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len);
- if (!intserv)
- return;
-
- nthreads = len / sizeof(u32);
-
- 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]);
- }
- 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
*
@@ -422,15 +231,6 @@ static void __init smp_init_pseries(void)
DBG(" -> smp_init_pSeries()\n");
-#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 (firmware_has_feature(FW_FEATURE_LPAR))
- pSeries_reconfig_notifier_register(&pSeries_smp_nb);
-#endif
-
/* Mark threads which are still spinning in hold loops. */
if (cpu_has_feature(CPU_FTR_SMT)) {
for_each_present_cpu(i) {
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index b5b2b1103de..81d172d6503 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -224,7 +224,6 @@ static void xics_unmask_irq(unsigned int virq)
static void xics_mask_real_irq(unsigned int irq)
{
int call_status;
- unsigned int server;
if (irq == XICS_IPI)
return;
@@ -236,9 +235,9 @@ static void xics_mask_real_irq(unsigned int irq)
return;
}
- server = get_irq_server(irq);
/* Have to set XIVE to 0xff to be able to remove a slot */
- call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
+ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
+ default_server, 0xff);
if (call_status != 0) {
printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
" returned %d\n", irq, call_status);
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 6cc34597a62..2621a7e72d2 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,13 +5,13 @@ endif
obj-$(CONFIG_MPIC) += mpic.o
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
-obj-$(CONFIG_PPC_DCR) += dcr.o dcr-low.o
+obj-$(CONFIG_PPC_DCR) += dcr.o
+obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
-obj-$(CONFIG_MTD) += rom.o
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
@@ -20,5 +20,6 @@ endif
# Temporary hack until we have migrated to asm-powerpc
ifeq ($(ARCH),powerpc)
+obj-$(CONFIG_MTD) += rom.o
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
endif
diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S
deleted file mode 100644
index 2078f39e2f1..00000000000
--- a/arch/powerpc/sysdev/dcr.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * "Indirect" DCR access
- *
- * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <asm/ppc_asm.h>
-#include <asm/processor.h>
-
-#define DCR_ACCESS_PROLOG(table) \
- rlwinm r3,r3,4,18,27; \
- lis r5,table@h; \
- ori r5,r5,table@l; \
- add r3,r3,r5; \
- mtctr r3; \
- bctr
-
-_GLOBAL(__mfdcr)
- DCR_ACCESS_PROLOG(__mfdcr_table)
-
-_GLOBAL(__mtdcr)
- DCR_ACCESS_PROLOG(__mtdcr_table)
-
-__mfdcr_table:
- mfdcr r3,0; blr
-__mtdcr_table:
- mtdcr 0,r4; blr
-
-dcr = 1
- .rept 1023
- mfdcr r3,dcr; blr
- mtdcr dcr,r4; blr
- dcr = dcr + 1
- .endr
diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c
index ff23f5a4d4b..e073e246293 100644
--- a/arch/powerpc/sysdev/mmio_nvram.c
+++ b/arch/powerpc/sysdev/mmio_nvram.c
@@ -80,33 +80,39 @@ static ssize_t mmio_nvram_get_size(void)
int __init mmio_nvram_init(void)
{
struct device_node *nvram_node;
- const unsigned long *buffer;
- int proplen;
unsigned long nvram_addr;
+ struct resource r;
int ret;
- ret = -ENODEV;
nvram_node = of_find_node_by_type(NULL, "nvram");
- if (!nvram_node)
+ if (!nvram_node) {
+ printk(KERN_WARNING "nvram: no node found in device-tree\n");
+ return -ENODEV;
+ }
+
+ ret = of_address_to_resource(nvram_node, 0, &r);
+ if (ret) {
+ printk(KERN_WARNING "nvram: failed to get address (err %d)\n",
+ ret);
goto out;
-
- ret = -EIO;
- buffer = get_property(nvram_node, "reg", &proplen);
- if (proplen != 2*sizeof(unsigned long))
- goto out;
-
- ret = -ENODEV;
- nvram_addr = buffer[0];
- mmio_nvram_len = buffer[1];
- if ( (!mmio_nvram_len) || (!nvram_addr) )
+ }
+ nvram_addr = r.start;
+ mmio_nvram_len = r.end - r.start + 1;
+ if ( (!mmio_nvram_len) || (!nvram_addr) ) {
+ printk(KERN_WARNING "nvram: address or lenght is 0\n");
+ ret = -EIO;
goto out;
+ }
mmio_nvram_start = ioremap(nvram_addr, mmio_nvram_len);
- if (!mmio_nvram_start)
+ if (!mmio_nvram_start) {
+ printk(KERN_WARNING "nvram: failed to ioremap\n");
+ ret = -ENOMEM;
goto out;
+ }
- printk(KERN_INFO "mmio NVRAM, %luk mapped to %p\n",
- mmio_nvram_len >> 10, mmio_nvram_start);
+ printk(KERN_INFO "mmio NVRAM, %luk at 0x%lx mapped to %p\n",
+ mmio_nvram_len >> 10, nvram_addr, mmio_nvram_start);
ppc_md.nvram_read = mmio_nvram_read;
ppc_md.nvram_write = mmio_nvram_write;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 411480d5c62..d01ced11694 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -390,7 +390,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
if (id == PCI_CAP_ID_HT) {
id = readb(devbase + pos + 3);
- if (id == HT_CAPTYPE_IRQ)
+ if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_IRQ)
break;
}
}
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 6995f51b948..74e48d94f27 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -223,23 +223,15 @@ static void qe_ic_mask_irq(unsigned int virq)
qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
temp & ~qe_ic_info[src].mask);
- spin_unlock_irqrestore(&qe_ic_lock, flags);
-}
-
-static void qe_ic_mask_irq_and_ack(unsigned int virq)
-{
- struct qe_ic *qe_ic = qe_ic_from_irq(virq);
- unsigned int src = virq_to_hw(virq);
- unsigned long flags;
- u32 temp;
-
- spin_lock_irqsave(&qe_ic_lock, flags);
-
- temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
- qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
- temp & ~qe_ic_info[src].mask);
-
- /* There is nothing to do for ack here, ack is handled in ISR */
+ /* Flush the above write before enabling interrupts; otherwise,
+ * spurious interrupts will sometimes happen. To be 100% sure
+ * that the write has reached the device before interrupts are
+ * enabled, the mask register would have to be read back; however,
+ * this is not required for correctness, only to avoid wasting
+ * time on a large number of spurious interrupts. In testing,
+ * a sync reduced the observed spurious interrupts to zero.
+ */
+ mb();
spin_unlock_irqrestore(&qe_ic_lock, flags);
}
@@ -248,7 +240,7 @@ static struct irq_chip qe_ic_irq_chip = {
.typename = " QEIC ",
.unmask = qe_ic_unmask_irq,
.mask = qe_ic_mask_irq,
- .mask_ack = qe_ic_mask_irq_and_ack,
+ .mask_ack = qe_ic_mask_irq,
};
static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
@@ -331,34 +323,22 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
return irq_linear_revmap(qe_ic->irqhost, irq);
}
-/* FIXME: We mask all the QE Low interrupts while handling. We should
- * let other interrupt come in, but BAD interrupts are generated */
void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc)
{
struct qe_ic *qe_ic = desc->handler_data;
- struct irq_chip *chip = irq_desc[irq].chip;
-
unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
- chip->mask_ack(irq);
if (cascade_irq != NO_IRQ)
generic_handle_irq(cascade_irq);
- chip->unmask(irq);
}
-/* FIXME: We mask all the QE High interrupts while handling. We should
- * let other interrupt come in, but BAD interrupts are generated */
void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc)
{
struct qe_ic *qe_ic = desc->handler_data;
- struct irq_chip *chip = irq_desc[irq].chip;
-
unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
- chip->mask_ack(irq);
if (cascade_irq != NO_IRQ)
generic_handle_irq(cascade_irq);
- chip->unmask(irq);
}
void __init qe_ic_init(struct device_node *node, unsigned int flags)
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c
index bf5b3f10e6c..c855a3b298a 100644
--- a/arch/powerpc/sysdev/rom.c
+++ b/arch/powerpc/sysdev/rom.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <asm/of_device.h>
+#include <asm/of_platform.h>
static int __init powerpc_flash_init(void)
{
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index a34ed49e035..77540a2f770 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -22,6 +22,7 @@
#include <linux/sysrq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/bug.h>
#include <asm/ptrace.h>
#include <asm/string.h>
@@ -35,7 +36,6 @@
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/sstep.h>
-#include <asm/bug.h>
#include <asm/irq_regs.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
@@ -1346,7 +1346,7 @@ static void backtrace(struct pt_regs *excp)
static void print_bug_trap(struct pt_regs *regs)
{
- struct bug_entry *bug;
+ const struct bug_entry *bug;
unsigned long addr;
if (regs->msr & MSR_PR)
@@ -1357,11 +1357,11 @@ static void print_bug_trap(struct pt_regs *regs)
bug = find_bug(regs->nip);
if (bug == NULL)
return;
- if (bug->line & BUG_WARNING_TRAP)
+ if (is_warning_bug(bug))
return;
- printf("kernel BUG in %s at %s:%d!\n",
- bug->function, bug->file, (unsigned int)bug->line);
+ printf("kernel BUG at %s:%u!\n",
+ bug->file, bug->line);
}
void excprint(struct pt_regs *fp)
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index 709952c25f2..06b84c372e5 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -1892,10 +1892,10 @@ init_fcc_param(fcc_info_t *fip, struct net_device *dev,
/* Allocate space for the buffer descriptors from regular memory.
* Initialize base addresses for the buffer descriptors.
*/
- cep->rx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
+ cep->rx_bd_base = kmalloc(sizeof(cbd_t) * RX_RING_SIZE,
GFP_KERNEL | GFP_DMA);
ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
- cep->tx_bd_base = (cbd_t *)kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
+ cep->tx_bd_base = kmalloc(sizeof(cbd_t) * TX_RING_SIZE,
GFP_KERNEL | GFP_DMA);
ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 959d31c26cb..b7bb5f0b3c5 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -2165,7 +2165,7 @@ static int sq_release(struct inode *inode, struct file *file)
int rc = 0;
if (sq.busy)
- rc = sq_fsync(file, file->f_dentry);
+ rc = sq_fsync(file, file->f_path.dentry);
sound.soft = sound.dsp;
sound.hard = sound.dsp;
sound_silence();
@@ -2218,25 +2218,25 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
return 0;
case SNDCTL_DSP_POST:
case SNDCTL_DSP_SYNC:
- return sq_fsync(file, file->f_dentry);
+ return sq_fsync(file, file->f_path.dentry);
/* ++TeSche: before changing any of these it's
* probably wise to wait until sound playing has
* settled down. */
case SNDCTL_DSP_SPEED:
- sq_fsync(file, file->f_dentry);
+ sq_fsync(file, file->f_path.dentry);
IOCTL_IN(arg, data);
return IOCTL_OUT(arg, sound_set_speed(data));
case SNDCTL_DSP_STEREO:
- sq_fsync(file, file->f_dentry);
+ sq_fsync(file, file->f_path.dentry);
IOCTL_IN(arg, data);
return IOCTL_OUT(arg, sound_set_stereo(data));
case SOUND_PCM_WRITE_CHANNELS:
- sq_fsync(file, file->f_dentry);
+ sq_fsync(file, file->f_path.dentry);
IOCTL_IN(arg, data);
return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
case SNDCTL_DSP_SETFMT:
- sq_fsync(file, file->f_dentry);
+ sq_fsync(file, file->f_path.dentry);
IOCTL_IN(arg, data);
return IOCTL_OUT(arg, sound_set_format(data));
case SNDCTL_DSP_GETFMTS:
@@ -2601,7 +2601,7 @@ int __init tdm8xx_sound_init(void)
/* Initialize beep stuff */
orig_mksound = kd_mksound;
kd_mksound = cs_mksound;
- beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+ beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
if (beep_buf == NULL)
printk(KERN_WARNING "dmasound: no memory for "
"beep buffer\n");
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index edf71a4ecc9..8eb82efe05a 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -19,6 +19,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default y
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_HWEIGHT
bool
default y
@@ -52,6 +60,11 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config GENERIC_BUG
+ bool
+ default y
+ depends on BUG
+
source "init/Kconfig"
menu "Processor"
@@ -611,7 +624,7 @@ config HDPU
Select HDPU if configuring a Sky Computers Compute Blade.
config HDPU_FEATURES
- depends HDPU
+ depends on HDPU
tristate "HDPU-Features"
help
Select to enable HDPU enhanced features.
@@ -722,7 +735,7 @@ config LITE5200
config LITE5200B
bool "Freescale LITE5200B"
- depends LITE5200
+ depends on LITE5200
help
Support for the LITE5200B dev board for the MPC5200 from Freescale.
This is the new board with 2 PCI slots.
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 63808e01cb0..5e723c4c257 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -879,7 +879,7 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
- unsigned long *offset,
+ resource_size_t *offset,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
@@ -891,7 +891,9 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
+#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
*offset += hose->pci_mem_offset;
+#endif
res_bit = IORESOURCE_MEM;
} else {
io_offset = hose->io_base_virt - ___IO_BASE;
@@ -1030,7 +1032,7 @@ 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;
+ resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
int ret;
@@ -1132,21 +1134,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
- unsigned long offset = 0;
+ resource_size_t offset = 0;
if (hose == NULL)
return;
if (rsrc->flags & IORESOURCE_IO)
- offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+
+ /* We pass a fully fixed up address to userland for MMIO instead of
+ * a BAR value because X is lame and expects to be able to use that
+ * to pass to /dev/mem !
+ *
+ * That means that we'll have potentially 64 bits values where some
+ * userland apps only expect 32 (like X itself since it thinks only
+ * Sparc has 64 bits MMIO) but if we don't do that, we break it on
+ * 32 bits CHRPs :-(
+ *
+ * Hopefully, the sysfs insterface is immune to that gunk. Once X
+ * has been fixed (and the fix spread enough), we can re-enable the
+ * 2 lines below and pass down a BAR value to userland. In that case
+ * we'll also have to re-enable the matching code in
+ * __pci_mmap_make_offset().
+ *
+ * BenH.
+ */
+#if 0
+ else if (rsrc->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+#endif
- *start = rsrc->start + offset;
- *end = rsrc->end + offset;
+ *start = rsrc->start - offset;
+ *end = rsrc->end - offset;
}
-void __init
-pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
- int flags, char *name)
+void __init pci_init_resource(struct resource *res, resource_size_t start,
+ resource_size_t end, int flags, char *name)
{
res->start = start;
res->end = end;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 2f835b9e95e..810f7aa72e9 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/prctl.h>
+#include <linux/bug.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -559,64 +560,9 @@ static void emulate_single_step(struct pt_regs *regs)
}
}
-/*
- * Look through the list of trap instructions that are used for BUG(),
- * BUG_ON() and WARN_ON() and see if we hit one. At this point we know
- * that the exception was caused by a trap instruction of some kind.
- * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
- * otherwise.
- */
-extern struct bug_entry __start___bug_table[], __stop___bug_table[];
-
-#ifndef CONFIG_MODULES
-#define module_find_bug(x) NULL
-#endif
-
-struct bug_entry *find_bug(unsigned long bugaddr)
-{
- struct bug_entry *bug;
-
- for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
- if (bugaddr == bug->bug_addr)
- return bug;
- return module_find_bug(bugaddr);
-}
-
-int check_bug_trap(struct pt_regs *regs)
+int is_valid_bugaddr(unsigned long addr)
{
- struct bug_entry *bug;
- unsigned long addr;
-
- if (regs->msr & MSR_PR)
- return 0; /* not in kernel */
- addr = regs->nip; /* address of trap instruction */
- if (addr < PAGE_OFFSET)
- return 0;
- bug = find_bug(regs->nip);
- if (bug == NULL)
- return 0;
- if (bug->line & BUG_WARNING_TRAP) {
- /* this is a WARN_ON rather than BUG/BUG_ON */
-#ifdef CONFIG_XMON
- xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n",
- bug->function, bug->file,
- bug->line & ~BUG_WARNING_TRAP);
-#endif /* CONFIG_XMON */
- printk(KERN_ERR "Badness in %s at %s:%ld\n",
- bug->function, bug->file,
- bug->line & ~BUG_WARNING_TRAP);
- dump_stack();
- return 1;
- }
-#ifdef CONFIG_XMON
- xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
- bug->function, bug->file, bug->line);
- xmon(regs);
-#endif /* CONFIG_XMON */
- printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
- bug->function, bug->file, bug->line);
-
- return 0;
+ return addr >= PAGE_OFFSET;
}
void program_check_exception(struct pt_regs *regs)
@@ -671,7 +617,9 @@ void program_check_exception(struct pt_regs *regs)
/* trap exception */
if (debugger_bpt(regs))
return;
- if (check_bug_trap(regs)) {
+
+ if (!(regs->msr & MSR_PR) && /* not user-mode */
+ report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) {
regs->nip += 4;
return;
}
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 293bd489e7d..6980de420e9 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -189,7 +189,7 @@ config BIOS_FIXUP
# OAK doesn't exist but wanted to keep this around for any future 403GCX boards
config 403GCX
bool
- depends OAK
+ depends on OAK
default y
config 405EP
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
index 90ed375c9b9..f87e06f6bab 100644
--- a/arch/ppc/platforms/ev64360.c
+++ b/arch/ppc/platforms/ev64360.c
@@ -358,13 +358,12 @@ ev64360_setup_mtd(void)
ptbl_entries = 3;
- if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+ if ((ptbl = kzalloc(ptbl_entries * sizeof(struct mtd_partition),
GFP_KERNEL)) == NULL) {
printk(KERN_WARNING "Can't alloc MTD partition table\n");
return -ENOMEM;
}
- memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
ptbl[0].name = "reserved";
ptbl[0].offset = 0;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 583d9ff0a57..12272361c01 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -22,6 +22,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config GENERIC_HWEIGHT
bool
default y
@@ -233,8 +241,14 @@ config WARN_STACK_SIZE
This allows you to specify the maximum frame size a function may
have without the compiler complaining about it.
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
+
source "mm/Kconfig"
+config HOLES_IN_ZONE
+ def_bool y
+
comment "I/O subsystem configuration"
config MACHCHK_WARNING
@@ -258,14 +272,6 @@ config QDIO
If unsure, say Y.
-config QDIO_PERF_STATS
- bool "Performance statistics in /proc"
- depends on QDIO
- help
- Say Y here to get performance statistics in /proc/qdio_perf
-
- If unsure, say N.
-
config QDIO_DEBUG
bool "Extended debugging information"
depends on QDIO
@@ -401,7 +407,7 @@ config APPLDATA_BASE
config APPLDATA_MEM
tristate "Monitor memory management statistics"
- depends on APPLDATA_BASE
+ depends on APPLDATA_BASE && VM_EVENT_COUNTERS
help
This provides memory management related data to the Linux - VM Monitor
Stream, like paging/swapping rate, memory utilisation, etc.
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 7cd51e73e27..5368cf4a350 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,14 +1,15 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Wed Oct 18 17:11:10 2006
+# Linux kernel version: 2.6.20-rc1
+# Fri Dec 15 16:52:28 2006
#
CONFIG_MMU=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
CONFIG_S390=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -37,12 +38,13 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -119,6 +121,7 @@ CONFIG_PACK_STACK=y
CONFIG_CHECK_STACK=y
CONFIG_STACK_GUARD=256
# CONFIG_WARN_STACK is not set
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -128,13 +131,13 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
+CONFIG_HOLES_IN_ZONE=y
#
# I/O subsystem configuration
#
CONFIG_MACHCHK_WARNING=y
CONFIG_QDIO=y
-# CONFIG_QDIO_PERF_STATS is not set
# CONFIG_QDIO_DEBUG is not set
#
@@ -197,6 +200,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
@@ -212,7 +216,6 @@ CONFIG_INET6_XFRM_MODE_BEET=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -247,6 +250,7 @@ CONFIG_IPV6_SIT=y
# QoS and/or fair queueing
#
CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FIFO=y
CONFIG_NET_SCH_CLK_JIFFIES=y
# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
# CONFIG_NET_SCH_CLK_CPU is not set
@@ -278,6 +282,7 @@ CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
# CONFIG_CLS_U32_PERF is not set
+CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_EMATCH is not set
@@ -316,6 +321,7 @@ CONFIG_SYS_HYPERVISOR=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
@@ -336,6 +342,7 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
#
# SCSI Transports
@@ -547,6 +554,7 @@ CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
#
# CD-ROM/DVD Filesystems
@@ -572,7 +580,7 @@ CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
#
# Miscellaneous filesystems
@@ -617,7 +625,6 @@ CONFIG_SUNRPC=y
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set
-CONFIG_GENERIC_ACL=y
#
# Partition Types
@@ -647,6 +654,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+CONFIG_DLM=m
+CONFIG_DLM_TCP=y
+# CONFIG_DLM_SCTP is not set
+# CONFIG_DLM_DEBUG is not set
+
+#
# Instrumentation Support
#
@@ -664,6 +679,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_SCHEDSTATS is not set
@@ -680,13 +697,11 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
-CONFIG_HEADERS_CHECK=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
@@ -700,10 +715,11 @@ CONFIG_HEADERS_CHECK=y
# Cryptographic options
#
CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=m
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
@@ -714,8 +730,10 @@ CONFIG_CRYPTO_MANAGER=m
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_DES is not set
# CONFIG_CRYPTO_DES_S390 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
@@ -741,8 +759,10 @@ CONFIG_CRYPTO_CBC=m
#
# Library routines
#
+CONFIG_BITREVERSE=m
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 443fa377d9f..2782cf9da5b 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -379,7 +379,7 @@ static void *diag204_alloc_vbuf(int pages)
static void *diag204_alloc_rbuf(void)
{
diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
- if (diag204_buf)
+ if (!diag204_buf)
return ERR_PTR(-ENOMEM);
diag204_buf_pages = 1;
return diag204_buf;
@@ -521,7 +521,7 @@ __init int hypfs_diag_init(void)
}
rc = diag224_get_name_table();
if (rc) {
- diag224_delete_name_table();
+ diag204_free_buffer();
printk(KERN_ERR "hypfs: could not get name table.\n");
}
return rc;
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index cd702ae45d6..b6716c4b993 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -109,7 +109,7 @@ static void hypfs_drop_inode(struct inode *inode)
static int hypfs_open(struct inode *inode, struct file *filp)
{
- char *data = filp->f_dentry->d_inode->i_private;
+ char *data = filp->f_path.dentry->d_inode->i_private;
struct hypfs_sb_info *fs_info;
if (filp->f_mode & FMODE_WRITE) {
@@ -174,7 +174,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
struct hypfs_sb_info *fs_info;
size_t count = iov_length(iov, nr_segs);
- sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
+ sb = iocb->ki_filp->f_path.dentry->d_inode->i_sb;
fs_info = sb->s_fs_info;
/*
* Currently we only allow one update per second for two reasons:
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 43f3d0c7e13..bb57bc0e3fc 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -191,13 +191,13 @@ debug_areas_alloc(int pages_per_area, int nr_areas)
debug_entry_t*** areas;
int i,j;
- areas = (debug_entry_t ***) kmalloc(nr_areas *
+ areas = kmalloc(nr_areas *
sizeof(debug_entry_t**),
GFP_KERNEL);
if (!areas)
goto fail_malloc_areas;
for (i = 0; i < nr_areas; i++) {
- areas[i] = (debug_entry_t**) kmalloc(pages_per_area *
+ areas[i] = kmalloc(pages_per_area *
sizeof(debug_entry_t*),GFP_KERNEL);
if (!areas[i]) {
goto fail_malloc_areas2;
@@ -242,7 +242,7 @@ debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size,
/* alloc everything */
- rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL);
+ rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
if(!rc)
goto fail_malloc_rc;
rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
@@ -603,13 +603,13 @@ debug_open(struct inode *inode, struct file *file)
debug_info_t *debug_info, *debug_info_snapshot;
down(&debug_lock);
- debug_info = file->f_dentry->d_inode->i_private;
+ debug_info = file->f_path.dentry->d_inode->i_private;
/* find debug view */
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
if (!debug_info->views[i])
continue;
else if (debug_info->debugfs_entries[i] ==
- file->f_dentry) {
+ file->f_path.dentry) {
goto found; /* found view ! */
}
}
@@ -634,7 +634,7 @@ found:
rc = -ENOMEM;
goto out;
}
- p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t),
+ p_info = kmalloc(sizeof(file_private_info_t),
GFP_KERNEL);
if(!p_info){
if(debug_info_snapshot)
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 4388b3309e0..eca507050e4 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -164,11 +164,14 @@ startup_continue:
srl %r7,28
clr %r6,%r7 # compare cc with last access code
be .Lsame-.LPG1(%r13)
- b .Lchkmem-.LPG1(%r13)
+ lhi %r8,0 # no program checks
+ b .Lsavchk-.LPG1(%r13)
.Lsame:
ar %r5,%r1 # add 128KB to end of chunk
bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
.Lchkmem: # > 2GB or tprot got a program check
+ lhi %r8,1 # set program check flag
+.Lsavchk:
clr %r4,%r5 # chunk size > 0?
be .Lchkloop-.LPG1(%r13)
st %r4,0(%r3) # store start address of chunk
@@ -190,8 +193,15 @@ startup_continue:
je .Ldonemem # if not, leave
chi %r10,0 # do we have chunks left?
je .Ldonemem
+ chi %r8,1 # program check ?
+ je .Lpgmchk
+ lr %r4,%r5 # potential new chunk
+ alr %r5,%r1 # add 128KB to end of chunk
+ j .Llpcnt
+.Lpgmchk:
alr %r5,%r1 # add 128KB to end of chunk
lr %r4,%r5 # potential new chunk
+.Llpcnt:
clr %r5,%r9 # should we go on?
jl .Lloop
.Ldonemem:
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index c526279e112..6ba3f4512dd 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -172,12 +172,15 @@ startup_continue:
srl %r7,28
clr %r6,%r7 # compare cc with last access code
je .Lsame
- j .Lchkmem
+ lghi %r8,0 # no program checks
+ j .Lsavchk
.Lsame:
algr %r5,%r1 # add 128KB to end of chunk
# no need to check here,
brc 12,.Lloop # this is the same chunk
.Lchkmem: # > 16EB or tprot got a program check
+ lghi %r8,1 # set program check flag
+.Lsavchk:
clgr %r4,%r5 # chunk size > 0?
je .Lchkloop
stg %r4,0(%r3) # store start address of chunk
@@ -204,8 +207,15 @@ startup_continue:
chi %r10, 0 # do we have chunks left?
je .Ldonemem
.Lhsaskip:
+ chi %r8,1 # program check ?
+ je .Lpgmchk
+ lgr %r4,%r5 # potential new chunk
+ algr %r5,%r1 # add 128KB to end of chunk
+ j .Llpcnt
+.Lpgmchk:
algr %r5,%r1 # add 128KB to end of chunk
lgr %r4,%r5 # potential new chunk
+.Llpcnt:
clgr %r5,%r9 # should we go on?
jl .Lloop
.Ldonemem:
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index a36bea1188d..9e9972e8a52 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -609,42 +609,12 @@ static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
static struct subsys_attribute on_panic_attr =
__ATTR(on_panic, 0644, on_panic_show, on_panic_store);
-static void print_fcp_block(struct ipl_parameter_block *fcp_block)
-{
- printk(KERN_EMERG "wwpn: %016llx\n",
- (unsigned long long)fcp_block->ipl_info.fcp.wwpn);
- printk(KERN_EMERG "lun: %016llx\n",
- (unsigned long long)fcp_block->ipl_info.fcp.lun);
- printk(KERN_EMERG "bootprog: %lld\n",
- (unsigned long long)fcp_block->ipl_info.fcp.bootprog);
- printk(KERN_EMERG "br_lba: %lld\n",
- (unsigned long long)fcp_block->ipl_info.fcp.br_lba);
- printk(KERN_EMERG "device: %llx\n",
- (unsigned long long)fcp_block->ipl_info.fcp.devno);
- printk(KERN_EMERG "opt: %x\n", fcp_block->ipl_info.fcp.opt);
-}
-
void do_reipl(void)
{
struct ccw_dev_id devid;
static char buf[100];
char loadparm[LOADPARM_LEN + 1];
- switch (reipl_type) {
- case IPL_TYPE_CCW:
- reipl_get_ascii_loadparm(loadparm);
- printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n",
- reipl_block_ccw->ipl_info.ccw.devno);
- printk(KERN_EMERG "loadparm = '%s'\n", loadparm);
- break;
- case IPL_TYPE_FCP:
- printk(KERN_EMERG "reboot on fcp device:\n");
- print_fcp_block(reipl_block_fcp);
- break;
- default:
- break;
- }
-
switch (reipl_method) {
case IPL_METHOD_CCW_CIO:
devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
@@ -654,6 +624,7 @@ void do_reipl(void)
reipl_ccw_dev(&devid);
break;
case IPL_METHOD_CCW_VM:
+ reipl_get_ascii_loadparm(loadparm);
if (strlen(loadparm) == 0)
sprintf(buf, "IPL %X",
reipl_block_ccw->ipl_info.ccw.devno);
@@ -683,7 +654,6 @@ void do_reipl(void)
diag308(DIAG308_IPL, NULL);
break;
}
- printk(KERN_EMERG "reboot failed!\n");
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}
@@ -692,19 +662,6 @@ static void do_dump(void)
struct ccw_dev_id devid;
static char buf[100];
- switch (dump_type) {
- case IPL_TYPE_CCW:
- printk(KERN_EMERG "Automatic dump on ccw device: 0.0.%04x\n",
- dump_block_ccw->ipl_info.ccw.devno);
- break;
- case IPL_TYPE_FCP:
- printk(KERN_EMERG "Automatic dump on fcp device:\n");
- print_fcp_block(dump_block_fcp);
- break;
- default:
- return;
- }
-
switch (dump_method) {
case IPL_METHOD_CCW_CIO:
smp_send_stop();
@@ -1037,15 +994,21 @@ static void do_reset_calls(void)
}
extern void reset_mcck_handler(void);
+extern void reset_pgm_handler(void);
+extern __u32 dump_prefix_page;
void s390_reset_system(void)
{
struct _lowcore *lc;
- /* Stack for interrupt/machine check handler */
lc = (struct _lowcore *)(unsigned long) store_prefix();
+
+ /* Stack for interrupt/machine check handler */
lc->panic_stack = S390_lowcore.panic_stack;
+ /* Save prefix page address for dump case */
+ dump_prefix_page = (unsigned long) lc;
+
/* Disable prefixing */
set_prefix(0);
@@ -1056,5 +1019,11 @@ void s390_reset_system(void)
S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
S390_lowcore.mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
+
+ /* Set new program check handler */
+ S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
+ S390_lowcore.program_new_psw.addr =
+ PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler;
+
do_reset_calls();
}
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index f9434d42ce9..c3f4d9b9508 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -16,7 +16,7 @@ do_reipl_asm: basr %r13,0
stm %r0,%r15,__LC_GPREGS_SAVE_AREA
stctl %c0,%c15,__LC_CREGS_SAVE_AREA
stam %a0,%a15,__LC_AREGS_SAVE_AREA
- stpx __LC_PREFIX_SAVE_AREA
+ mvc __LC_PREFIX_SAVE_AREA(4),dump_prefix_page-.Lpg0(%r13)
stckc .Lclkcmp-.Lpg0(%r13)
mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13)
stpt __LC_CPU_TIMER_SAVE_AREA
@@ -79,3 +79,7 @@ do_reipl_asm: basr %r13,0
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
+ .globl dump_prefix_page
+dump_prefix_page:
+ .long 0x00000000
+
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index f18ef260ca2..dbb3eed3886 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -20,7 +20,7 @@ do_reipl_asm: basr %r13,0
stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1)
stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1)
stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1)
- stpx __LC_PREFIX_SAVE_AREA-0x1000(%r1)
+ mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),dump_prefix_page-.Lpg0(%r13)
stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
stckc .Lclkcmp-.Lpg0(%r13)
mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
@@ -103,3 +103,6 @@ do_reipl_asm: basr %r13,0
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
+ .globl dump_prefix_page
+dump_prefix_page:
+ .long 0x00000000
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
index be8688c0665..8a87355161f 100644
--- a/arch/s390/kernel/reset.S
+++ b/arch/s390/kernel/reset.S
@@ -3,6 +3,7 @@
*
* Copyright (C) IBM Corp. 2006
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ * Michael Holzheu <holzheu@de.ibm.com>
*/
#include <asm/ptrace.h>
@@ -27,6 +28,26 @@ reset_mcck_handler:
s390_reset_mcck_handler:
.quad 0
+ .globl reset_pgm_handler
+reset_pgm_handler:
+ stmg %r0,%r15,__LC_SAVE_AREA
+ basr %r13,0
+0: lg %r15,__LC_PANIC_STACK # load panic stack
+ aghi %r15,-STACK_FRAME_OVERHEAD
+ lg %r1,s390_reset_pgm_handler-0b(%r13)
+ ltgr %r1,%r1
+ jz 1f
+ basr %r14,%r1
+ lmg %r0,%r15,__LC_SAVE_AREA
+ lpswe __LC_PGM_OLD_PSW
+1: lpswe disabled_wait_psw-0b(%r13)
+ .globl s390_reset_pgm_handler
+s390_reset_pgm_handler:
+ .quad 0
+ .align 8
+disabled_wait_psw:
+ .quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler
+
#else /* CONFIG_64BIT */
.globl reset_mcck_handler
@@ -45,4 +66,25 @@ reset_mcck_handler:
s390_reset_mcck_handler:
.long 0
+ .globl reset_pgm_handler
+reset_pgm_handler:
+ stm %r0,%r15,__LC_SAVE_AREA
+ basr %r13,0
+0: l %r15,__LC_PANIC_STACK # load panic stack
+ ahi %r15,-STACK_FRAME_OVERHEAD
+ l %r1,s390_reset_pgm_handler-0b(%r13)
+ ltr %r1,%r1
+ jz 1f
+ basr %r14,%r1
+ lm %r0,%r15,__LC_SAVE_AREA
+ lpsw __LC_PGM_OLD_PSW
+
+1: lpsw disabled_wait_psw-0b(%r13)
+ .globl s390_reset_pgm_handler
+s390_reset_pgm_handler:
+ .long 0
+disabled_wait_psw:
+ .align 8
+ .long 0x000a0000,0x00000000 + reset_pgm_handler
+
#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index 4faf96f8a83..bc5beaa8f98 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -37,7 +37,7 @@ int register_external_interrupt(__u16 code, ext_int_handler_t handler)
ext_int_info_t *p;
int index;
- p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+ p = kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
if (p == NULL)
return -ENOMEM;
p->code = code;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b928fecdc74..5d8ee3baac1 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -64,9 +64,8 @@ unsigned int console_devno = -1;
unsigned int console_irq = -1;
unsigned long machine_flags = 0;
-struct mem_chunk memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
-unsigned long __initdata zholes_size[MAX_NR_ZONES];
static unsigned long __initdata memory_end;
/*
@@ -354,21 +353,6 @@ void machine_power_off(void)
*/
void (*pm_power_off)(void) = machine_power_off;
-static void __init
-add_memory_hole(unsigned long start, unsigned long end)
-{
- unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
-
- if (end <= dma_pfn)
- zholes_size[ZONE_DMA] += end - start + 1;
- else if (start > dma_pfn)
- zholes_size[ZONE_NORMAL] += end - start + 1;
- else {
- zholes_size[ZONE_DMA] += dma_pfn - start + 1;
- zholes_size[ZONE_NORMAL] += end - dma_pfn;
- }
-}
-
static int __init early_parse_mem(char *p)
{
memory_end = memparse(p, &p);
@@ -492,7 +476,7 @@ static void __init setup_memory_end(void)
int i;
memory_size = real_size = 0;
- max_phys = VMALLOC_END - VMALLOC_MIN_SIZE;
+ max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE;
memory_end &= PAGE_MASK;
max_mem = memory_end ? min(max_phys, memory_end) : max_phys;
@@ -521,7 +505,6 @@ setup_memory(void)
{
unsigned long bootmap_size;
unsigned long start_pfn, end_pfn, init_pfn;
- unsigned long last_rw_end;
int i;
/*
@@ -577,39 +560,27 @@ setup_memory(void)
/*
* Register RAM areas with the bootmem allocator.
*/
- last_rw_end = start_pfn;
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
- unsigned long start_chunk, end_chunk;
+ unsigned long start_chunk, end_chunk, pfn;
if (memory_chunk[i].type != CHUNK_READ_WRITE)
continue;
- start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
- start_chunk >>= PAGE_SHIFT;
- end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
- end_chunk >>= PAGE_SHIFT;
- if (start_chunk < start_pfn)
- start_chunk = start_pfn;
- if (end_chunk > end_pfn)
- end_chunk = end_pfn;
- if (start_chunk < end_chunk) {
- /* Initialize storage key for RAM pages */
- for (init_pfn = start_chunk ; init_pfn < end_chunk;
- init_pfn++)
- page_set_storage_key(init_pfn << PAGE_SHIFT,
- PAGE_DEFAULT_KEY);
- free_bootmem(start_chunk << PAGE_SHIFT,
- (end_chunk - start_chunk) << PAGE_SHIFT);
- if (last_rw_end < start_chunk)
- add_memory_hole(last_rw_end, start_chunk - 1);
- last_rw_end = end_chunk;
- }
+ start_chunk = PFN_DOWN(memory_chunk[i].addr);
+ end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1;
+ end_chunk = min(end_chunk, end_pfn);
+ if (start_chunk >= end_chunk)
+ continue;
+ add_active_range(0, start_chunk, end_chunk);
+ pfn = max(start_chunk, start_pfn);
+ for (; pfn <= end_chunk; pfn++)
+ page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
}
psw_set_key(PAGE_DEFAULT_KEY);
- if (last_rw_end < end_pfn - 1)
- add_memory_hole(last_rw_end, end_pfn - 1);
+ free_bootmem_with_active_regions(0, max_pfn);
+ reserve_bootmem(0, PFN_PHYS(start_pfn));
/*
* Reserve the bootmem bitmap itself as well. We do this in two
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 19090f7d4f5..c0cd255fddb 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -794,7 +794,10 @@ static int __init topology_init(void)
int ret;
for_each_possible_cpu(cpu) {
- ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu);
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ c->hotpluggable = 1;
+ ret = register_cpu(c, cpu);
if (ret)
printk(KERN_WARNING "topology_init: register_cpu %d "
"failed (%d)\n", cpu, ret);
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 8741bdc0929..49c3e46b406 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -8,8 +8,9 @@
*/
#include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/hardirq.h>
#include <linux/mm.h>
+#include <asm/uaccess.h>
#include <asm/futex.h>
static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
@@ -18,6 +19,8 @@ static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
struct vm_area_struct *vma;
int ret = -EFAULT;
+ if (in_atomic())
+ return ret;
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
if (unlikely(!vma))
@@ -60,8 +63,9 @@ out:
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
+ down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", current->comm);
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index bbaca66fa29..56a0214e992 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -258,8 +258,6 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
{
int oldval = 0, newval, ret;
- pagefault_disable();
-
switch (op) {
case FUTEX_OP_SET:
__futex_atomic_op("lr %2,%5\n",
@@ -284,7 +282,6 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
default:
ret = -ENOSYS;
}
- pagefault_enable();
*old = oldval;
return ret;
}
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index aa9a42b6e62..8e09db1edbb 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,6 +2,6 @@
# Makefile for the linux s390-specific parts of the memory manager.
#
-obj-y := init.o fault.o ioremap.o extmem.o mmap.o
+obj-y := init.o fault.o ioremap.o extmem.o mmap.o vmem.o
obj-$(CONFIG_CMM) += cmm.o
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 9e9bc48463a..775bf19e742 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -16,6 +16,7 @@
#include <linux/bootmem.h>
#include <linux/ctype.h>
#include <asm/page.h>
+#include <asm/pgtable.h>
#include <asm/ebcdic.h>
#include <asm/errno.h>
#include <asm/extmem.h>
@@ -238,65 +239,6 @@ query_segment_type (struct dcss_segment *seg)
}
/*
- * check if the given segment collides with guest storage.
- * returns 1 if this is the case, 0 if no collision was found
- */
-static int
-segment_overlaps_storage(struct dcss_segment *seg)
-{
- int i;
-
- for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
- if (memory_chunk[i].type != CHUNK_READ_WRITE)
- continue;
- if ((memory_chunk[i].addr >> 20) > (seg->end >> 20))
- continue;
- if (((memory_chunk[i].addr + memory_chunk[i].size - 1) >> 20)
- < (seg->start_addr >> 20))
- continue;
- return 1;
- }
- return 0;
-}
-
-/*
- * check if segment collides with other segments that are currently loaded
- * returns 1 if this is the case, 0 if no collision was found
- */
-static int
-segment_overlaps_others (struct dcss_segment *seg)
-{
- struct list_head *l;
- struct dcss_segment *tmp;
-
- BUG_ON(!mutex_is_locked(&dcss_lock));
- list_for_each(l, &dcss_list) {
- tmp = list_entry(l, struct dcss_segment, list);
- if ((tmp->start_addr >> 20) > (seg->end >> 20))
- continue;
- if ((tmp->end >> 20) < (seg->start_addr >> 20))
- continue;
- if (seg == tmp)
- continue;
- return 1;
- }
- return 0;
-}
-
-/*
- * check if segment exceeds the kernel mapping range (detected or set via mem=)
- * returns 1 if this is the case, 0 if segment fits into the range
- */
-static inline int
-segment_exceeds_range (struct dcss_segment *seg)
-{
- int seg_last_pfn = (seg->end) >> PAGE_SHIFT;
- if (seg_last_pfn > max_pfn)
- return 1;
- return 0;
-}
-
-/*
* get info about a segment
* possible return values:
* -ENOSYS : we are not running on VM
@@ -341,24 +283,26 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
rc = query_segment_type (seg);
if (rc < 0)
goto out_free;
- if (segment_exceeds_range(seg)) {
- PRINT_WARN ("segment_load: not loading segment %s - exceeds"
- " kernel mapping range\n",name);
- rc = -ERANGE;
+
+ rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+
+ switch (rc) {
+ case 0:
+ break;
+ case -ENOSPC:
+ PRINT_WARN("segment_load: not loading segment %s - overlaps "
+ "storage/segment\n", name);
goto out_free;
- }
- if (segment_overlaps_storage(seg)) {
- PRINT_WARN ("segment_load: not loading segment %s - overlaps"
- " storage\n",name);
- rc = -ENOSPC;
+ case -ERANGE:
+ PRINT_WARN("segment_load: not loading segment %s - exceeds "
+ "kernel mapping range\n", name);
goto out_free;
- }
- if (segment_overlaps_others(seg)) {
- PRINT_WARN ("segment_load: not loading segment %s - overlaps"
- " other segments\n",name);
- rc = -EBUSY;
+ default:
+ PRINT_WARN("segment_load: not loading segment %s (rc: %d)\n",
+ name, rc);
goto out_free;
}
+
if (do_nonshared)
dcss_command = DCSS_LOADNSR;
else
@@ -372,7 +316,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
rc = dcss_diag_translate_rc (seg->end);
dcss_diag(DCSS_PURGESEG, seg->dcss_name,
&seg->start_addr, &seg->end);
- goto out_free;
+ goto out_shared;
}
seg->do_nonshared = do_nonshared;
atomic_set(&seg->ref_count, 1);
@@ -391,6 +335,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
(void*)seg->start_addr, (void*)seg->end,
segtype_string[seg->vm_segtype]);
goto out;
+ out_shared:
+ remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
out_free:
kfree(seg);
out:
@@ -530,12 +476,12 @@ segment_unload(char *name)
"please report to linux390@de.ibm.com\n",name);
goto out_unlock;
}
- if (atomic_dec_return(&seg->ref_count) == 0) {
- list_del(&seg->list);
- dcss_diag(DCSS_PURGESEG, seg->dcss_name,
- &dummy, &dummy);
- kfree(seg);
- }
+ if (atomic_dec_return(&seg->ref_count) != 0)
+ goto out_unlock;
+ remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+ list_del(&seg->list);
+ dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
+ kfree(seg);
out_unlock:
mutex_unlock(&dcss_lock);
}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index e1881c31b1c..4bb21be3b00 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -24,6 +24,7 @@
#include <linux/pagemap.h>
#include <linux/bootmem.h>
#include <linux/pfn.h>
+#include <linux/poison.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -69,6 +70,8 @@ void show_mem(void)
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
i = max_mapnr;
while (i-- > 0) {
+ if (!pfn_valid(i))
+ continue;
page = pfn_to_page(i);
total++;
if (PageReserved(page))
@@ -84,150 +87,52 @@ void show_mem(void)
printk("%d pages swap cached\n",cached);
}
-extern unsigned long __initdata zholes_size[];
-/*
- * paging_init() sets up the page tables
- */
-
-#ifndef CONFIG_64BIT
-void __init paging_init(void)
+static void __init setup_ro_region(void)
{
- pgd_t * pg_dir;
- pte_t * pg_table;
- pte_t pte;
- int i;
- unsigned long tmp;
- unsigned long pfn = 0;
- unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
- static const int ssm_mask = 0x04000000L;
- unsigned long ro_start_pfn, ro_end_pfn;
- unsigned long zones_size[MAX_NR_ZONES];
-
- ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata);
- ro_end_pfn = PFN_UP((unsigned long)&__end_rodata);
-
- memset(zones_size, 0, sizeof(zones_size));
- zones_size[ZONE_DMA] = max_low_pfn;
- free_area_init_node(0, &contig_page_data, zones_size,
- __pa(PAGE_OFFSET) >> PAGE_SHIFT,
- zholes_size);
-
- /* unmap whole virtual address space */
-
- pg_dir = swapper_pg_dir;
-
- for (i = 0; i < PTRS_PER_PGD; i++)
- pmd_clear((pmd_t *) pg_dir++);
-
- /*
- * map whole physical memory to virtual memory (identity mapping)
- */
-
- pg_dir = swapper_pg_dir;
-
- while (pfn < max_low_pfn) {
- /*
- * pg_table is physical at this point
- */
- pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
-
- pmd_populate_kernel(&init_mm, (pmd_t *) pg_dir, pg_table);
- pg_dir++;
-
- for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
- if (pfn >= ro_start_pfn && pfn < ro_end_pfn)
- pte = pfn_pte(pfn, __pgprot(_PAGE_RO));
- else
- pte = pfn_pte(pfn, PAGE_KERNEL);
- if (pfn >= max_low_pfn)
- pte_val(pte) = _PAGE_TYPE_EMPTY;
- set_pte(pg_table, pte);
- pfn++;
- }
- }
-
- S390_lowcore.kernel_asce = pgdir_k;
-
- /* enable virtual mapping in kernel mode */
- __ctl_load(pgdir_k, 1, 1);
- __ctl_load(pgdir_k, 7, 7);
- __ctl_load(pgdir_k, 13, 13);
- __raw_local_irq_ssm(ssm_mask);
-
- local_flush_tlb();
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ pte_t new_pte;
+ unsigned long address, end;
+
+ address = ((unsigned long)&__start_rodata) & PAGE_MASK;
+ end = PFN_ALIGN((unsigned long)&__end_rodata);
+
+ for (; address < end; address += PAGE_SIZE) {
+ pgd = pgd_offset_k(address);
+ pmd = pmd_offset(pgd, address);
+ pte = pte_offset_kernel(pmd, address);
+ new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
+ set_pte(pte, new_pte);
+ }
}
-#else /* CONFIG_64BIT */
+extern void vmem_map_init(void);
+/*
+ * paging_init() sets up the page tables
+ */
void __init paging_init(void)
{
- pgd_t * pg_dir;
- pmd_t * pm_dir;
- pte_t * pt_dir;
- pte_t pte;
- int i,j,k;
- unsigned long pfn = 0;
- unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) |
- _KERN_REGION_TABLE;
+ pgd_t *pg_dir;
+ int i;
+ unsigned long pgdir_k;
static const int ssm_mask = 0x04000000L;
- unsigned long zones_size[MAX_NR_ZONES];
- unsigned long dma_pfn, high_pfn;
- unsigned long ro_start_pfn, ro_end_pfn;
-
- memset(zones_size, 0, sizeof(zones_size));
- dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
- high_pfn = max_low_pfn;
- ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata);
- ro_end_pfn = PFN_UP((unsigned long)&__end_rodata);
-
- if (dma_pfn > high_pfn)
- zones_size[ZONE_DMA] = high_pfn;
- else {
- zones_size[ZONE_DMA] = dma_pfn;
- zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
- }
-
- /* Initialize mem_map[]. */
- free_area_init_node(0, &contig_page_data, zones_size,
- __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
- /*
- * map whole physical memory to virtual memory (identity mapping)
- */
-
- pg_dir = swapper_pg_dir;
-
- for (i = 0 ; i < PTRS_PER_PGD ; i++,pg_dir++) {
+ pg_dir = swapper_pg_dir;
- if (pfn >= max_low_pfn) {
- pgd_clear(pg_dir);
- continue;
- }
-
- pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4);
- pgd_populate(&init_mm, pg_dir, pm_dir);
-
- for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
- if (pfn >= max_low_pfn) {
- pmd_clear(pm_dir);
- continue;
- }
-
- pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
- pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
-
- for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
- if (pfn >= ro_start_pfn && pfn < ro_end_pfn)
- pte = pfn_pte(pfn, __pgprot(_PAGE_RO));
- else
- pte = pfn_pte(pfn, PAGE_KERNEL);
- if (pfn >= max_low_pfn)
- pte_val(pte) = _PAGE_TYPE_EMPTY;
- set_pte(pt_dir, pte);
- pfn++;
- }
- }
- }
+#ifdef CONFIG_64BIT
+ pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE;
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ pgd_clear(pg_dir + i);
+#else
+ pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ pmd_clear((pmd_t *)(pg_dir + i));
+#endif
+ vmem_map_init();
+ setup_ro_region();
S390_lowcore.kernel_asce = pgdir_k;
@@ -237,9 +142,11 @@ void __init paging_init(void)
__ctl_load(pgdir_k, 13, 13);
__raw_local_irq_ssm(ssm_mask);
- local_flush_tlb();
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
+ max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+ free_area_init_nodes(max_zone_pfns);
}
-#endif /* CONFIG_64BIT */
void __init mem_init(void)
{
@@ -269,6 +176,8 @@ void __init mem_init(void)
printk("Write protected kernel read-only data: %#lx - %#lx\n",
(unsigned long)&__start_rodata,
PFN_ALIGN((unsigned long)&__end_rodata) - 1);
+ printk("Virtual memmap size: %ldk\n",
+ (max_pfn * sizeof(struct page)) >> 10);
}
void free_initmem(void)
@@ -279,6 +188,7 @@ void free_initmem(void)
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
+ memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
free_page(addr);
totalram_pages++;
}
diff --git a/arch/s390/mm/ioremap.c b/arch/s390/mm/ioremap.c
index 0f6e9ecbefe..3d2100a4e20 100644
--- a/arch/s390/mm/ioremap.c
+++ b/arch/s390/mm/ioremap.c
@@ -15,87 +15,8 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, __pgprot(flags)));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return 0;
-}
/*
* Generic mapping function (not visible outside):
@@ -122,7 +43,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
if (!area)
return NULL;
addr = 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, __pgprot(flags))) {
vfree(addr);
return NULL;
}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
new file mode 100644
index 00000000000..cd3d93e8c21
--- /dev/null
+++ b/arch/s390/mm/vmem.c
@@ -0,0 +1,382 @@
+/*
+ * arch/s390/mm/vmem.c
+ *
+ * Copyright IBM Corp. 2006
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/tlbflush.h>
+
+unsigned long vmalloc_end;
+EXPORT_SYMBOL(vmalloc_end);
+
+static struct page *vmem_map;
+static DEFINE_MUTEX(vmem_mutex);
+
+struct memory_segment {
+ struct list_head list;
+ unsigned long start;
+ unsigned long size;
+};
+
+static LIST_HEAD(mem_segs);
+
+void memmap_init(unsigned long size, int nid, unsigned long zone,
+ unsigned long start_pfn)
+{
+ struct page *start, *end;
+ struct page *map_start, *map_end;
+ int i;
+
+ start = pfn_to_page(start_pfn);
+ end = start + size;
+
+ for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+ unsigned long cstart, cend;
+
+ cstart = PFN_DOWN(memory_chunk[i].addr);
+ cend = cstart + PFN_DOWN(memory_chunk[i].size);
+
+ map_start = mem_map + cstart;
+ map_end = mem_map + cend;
+
+ if (map_start < start)
+ map_start = start;
+ if (map_end > end)
+ map_end = end;
+
+ map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1))
+ / sizeof(struct page);
+ map_end += ((PFN_ALIGN((unsigned long) map_end)
+ - (unsigned long) map_end)
+ / sizeof(struct page));
+
+ if (map_start < map_end)
+ memmap_init_zone((unsigned long)(map_end - map_start),
+ nid, zone, page_to_pfn(map_start),
+ MEMMAP_EARLY);
+ }
+}
+
+static inline void *vmem_alloc_pages(unsigned int order)
+{
+ if (slab_is_available())
+ return (void *)__get_free_pages(GFP_KERNEL, order);
+ return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
+}
+
+static inline pmd_t *vmem_pmd_alloc(void)
+{
+ pmd_t *pmd;
+ int i;
+
+ pmd = vmem_alloc_pages(PMD_ALLOC_ORDER);
+ if (!pmd)
+ return NULL;
+ for (i = 0; i < PTRS_PER_PMD; i++)
+ pmd_clear(pmd + i);
+ return pmd;
+}
+
+static inline pte_t *vmem_pte_alloc(void)
+{
+ pte_t *pte;
+ pte_t empty_pte;
+ int i;
+
+ pte = vmem_alloc_pages(PTE_ALLOC_ORDER);
+ if (!pte)
+ return NULL;
+ pte_val(empty_pte) = _PAGE_TYPE_EMPTY;
+ for (i = 0; i < PTRS_PER_PTE; i++)
+ set_pte(pte + i, empty_pte);
+ return pte;
+}
+
+/*
+ * Add a physical memory range to the 1:1 mapping.
+ */
+static int vmem_add_range(unsigned long start, unsigned long size)
+{
+ unsigned long address;
+ pgd_t *pg_dir;
+ pmd_t *pm_dir;
+ pte_t *pt_dir;
+ pte_t pte;
+ int ret = -ENOMEM;
+
+ for (address = start; address < start + size; address += PAGE_SIZE) {
+ pg_dir = pgd_offset_k(address);
+ if (pgd_none(*pg_dir)) {
+ pm_dir = vmem_pmd_alloc();
+ if (!pm_dir)
+ goto out;
+ pgd_populate(&init_mm, pg_dir, pm_dir);
+ }
+
+ pm_dir = pmd_offset(pg_dir, address);
+ if (pmd_none(*pm_dir)) {
+ pt_dir = vmem_pte_alloc();
+ if (!pt_dir)
+ goto out;
+ pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
+ }
+
+ pt_dir = pte_offset_kernel(pm_dir, address);
+ pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL);
+ set_pte(pt_dir, pte);
+ }
+ ret = 0;
+out:
+ flush_tlb_kernel_range(start, start + size);
+ return ret;
+}
+
+/*
+ * Remove a physical memory range from the 1:1 mapping.
+ * Currently only invalidates page table entries.
+ */
+static void vmem_remove_range(unsigned long start, unsigned long size)
+{
+ unsigned long address;
+ pgd_t *pg_dir;
+ pmd_t *pm_dir;
+ pte_t *pt_dir;
+ pte_t pte;
+
+ pte_val(pte) = _PAGE_TYPE_EMPTY;
+ for (address = start; address < start + size; address += PAGE_SIZE) {
+ pg_dir = pgd_offset_k(address);
+ if (pgd_none(*pg_dir))
+ continue;
+ pm_dir = pmd_offset(pg_dir, address);
+ if (pmd_none(*pm_dir))
+ continue;
+ pt_dir = pte_offset_kernel(pm_dir, address);
+ set_pte(pt_dir, pte);
+ }
+ flush_tlb_kernel_range(start, start + size);
+}
+
+/*
+ * Add a backed mem_map array to the virtual mem_map array.
+ */
+static int vmem_add_mem_map(unsigned long start, unsigned long size)
+{
+ unsigned long address, start_addr, end_addr;
+ struct page *map_start, *map_end;
+ pgd_t *pg_dir;
+ pmd_t *pm_dir;
+ pte_t *pt_dir;
+ pte_t pte;
+ int ret = -ENOMEM;
+
+ map_start = vmem_map + PFN_DOWN(start);
+ map_end = vmem_map + PFN_DOWN(start + size);
+
+ start_addr = (unsigned long) map_start & PAGE_MASK;
+ end_addr = PFN_ALIGN((unsigned long) map_end);
+
+ for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
+ pg_dir = pgd_offset_k(address);
+ if (pgd_none(*pg_dir)) {
+ pm_dir = vmem_pmd_alloc();
+ if (!pm_dir)
+ goto out;
+ pgd_populate(&init_mm, pg_dir, pm_dir);
+ }
+
+ pm_dir = pmd_offset(pg_dir, address);
+ if (pmd_none(*pm_dir)) {
+ pt_dir = vmem_pte_alloc();
+ if (!pt_dir)
+ goto out;
+ pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
+ }
+
+ pt_dir = pte_offset_kernel(pm_dir, address);
+ if (pte_none(*pt_dir)) {
+ unsigned long new_page;
+
+ new_page =__pa(vmem_alloc_pages(0));
+ if (!new_page)
+ goto out;
+ pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
+ set_pte(pt_dir, pte);
+ }
+ }
+ ret = 0;
+out:
+ flush_tlb_kernel_range(start_addr, end_addr);
+ return ret;
+}
+
+static int vmem_add_mem(unsigned long start, unsigned long size)
+{
+ int ret;
+
+ ret = vmem_add_range(start, size);
+ if (ret)
+ return ret;
+ return vmem_add_mem_map(start, size);
+}
+
+/*
+ * Add memory segment to the segment list if it doesn't overlap with
+ * an already present segment.
+ */
+static int insert_memory_segment(struct memory_segment *seg)
+{
+ struct memory_segment *tmp;
+
+ if (PFN_DOWN(seg->start + seg->size) > max_pfn ||
+ seg->start + seg->size < seg->start)
+ return -ERANGE;
+
+ list_for_each_entry(tmp, &mem_segs, list) {
+ if (seg->start >= tmp->start + tmp->size)
+ continue;
+ if (seg->start + seg->size <= tmp->start)
+ continue;
+ return -ENOSPC;
+ }
+ list_add(&seg->list, &mem_segs);
+ return 0;
+}
+
+/*
+ * Remove memory segment from the segment list.
+ */
+static void remove_memory_segment(struct memory_segment *seg)
+{
+ list_del(&seg->list);
+}
+
+static void __remove_shared_memory(struct memory_segment *seg)
+{
+ remove_memory_segment(seg);
+ vmem_remove_range(seg->start, seg->size);
+}
+
+int remove_shared_memory(unsigned long start, unsigned long size)
+{
+ struct memory_segment *seg;
+ int ret;
+
+ mutex_lock(&vmem_mutex);
+
+ ret = -ENOENT;
+ list_for_each_entry(seg, &mem_segs, list) {
+ if (seg->start == start && seg->size == size)
+ break;
+ }
+
+ if (seg->start != start || seg->size != size)
+ goto out;
+
+ ret = 0;
+ __remove_shared_memory(seg);
+ kfree(seg);
+out:
+ mutex_unlock(&vmem_mutex);
+ return ret;
+}
+
+int add_shared_memory(unsigned long start, unsigned long size)
+{
+ struct memory_segment *seg;
+ struct page *page;
+ unsigned long pfn, num_pfn, end_pfn;
+ int ret;
+
+ mutex_lock(&vmem_mutex);
+ ret = -ENOMEM;
+ seg = kzalloc(sizeof(*seg), GFP_KERNEL);
+ if (!seg)
+ goto out;
+ seg->start = start;
+ seg->size = size;
+
+ ret = insert_memory_segment(seg);
+ if (ret)
+ goto out_free;
+
+ ret = vmem_add_mem(start, size);
+ if (ret)
+ goto out_remove;
+
+ pfn = PFN_DOWN(start);
+ num_pfn = PFN_DOWN(size);
+ end_pfn = pfn + num_pfn;
+
+ page = pfn_to_page(pfn);
+ memset(page, 0, num_pfn * sizeof(struct page));
+
+ for (; pfn < end_pfn; pfn++) {
+ page = pfn_to_page(pfn);
+ init_page_count(page);
+ reset_page_mapcount(page);
+ SetPageReserved(page);
+ INIT_LIST_HEAD(&page->lru);
+ }
+ goto out;
+
+out_remove:
+ __remove_shared_memory(seg);
+out_free:
+ kfree(seg);
+out:
+ mutex_unlock(&vmem_mutex);
+ return ret;
+}
+
+/*
+ * map whole physical memory to virtual memory (identity mapping)
+ */
+void __init vmem_map_init(void)
+{
+ unsigned long map_size;
+ int i;
+
+ map_size = ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * sizeof(struct page);
+ vmalloc_end = PFN_ALIGN(VMALLOC_END_INIT) - PFN_ALIGN(map_size);
+ vmem_map = (struct page *) vmalloc_end;
+ NODE_DATA(0)->node_mem_map = vmem_map;
+
+ for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
+ vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
+}
+
+/*
+ * Convert memory chunk array to a memory segment list so there is a single
+ * list that contains both r/w memory and shared memory segments.
+ */
+static int __init vmem_convert_memory_chunk(void)
+{
+ struct memory_segment *seg;
+ int i;
+
+ mutex_lock(&vmem_mutex);
+ for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+ if (!memory_chunk[i].size)
+ continue;
+ seg = kzalloc(sizeof(*seg), GFP_KERNEL);
+ if (!seg)
+ panic("Out of memory...\n");
+ seg->start = memory_chunk[i].addr;
+ seg->size = memory_chunk[i].size;
+ insert_memory_segment(seg);
+ }
+ mutex_unlock(&vmem_mutex);
+ return 0;
+}
+
+core_initcall(vmem_convert_memory_chunk);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d83d64af31f..3aa3b885ab3 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -59,6 +59,14 @@ config LOCKDEP_SUPPORT
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
source "init/Kconfig"
menu "System type"
@@ -471,7 +479,7 @@ config SH_CLK_MD
int "CPU Mode Pin Setting"
depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206
help
- MD2 - MD0 Setting.
+ MD2 - MD0 pin setting.
menu "CPU Frequency scaling"
@@ -572,18 +580,6 @@ config NR_CPUS
source "kernel/Kconfig.preempt"
-config CPU_HAS_SR_RB
- bool "CPU has SR.RB"
- depends on CPU_SH3 || CPU_SH4
- default y
- help
- This will enable the use of SR.RB register bank usage. Processors
- that are lacking this bit must have another method in place for
- accomplishing what is taken care of by the banked registers.
-
- See <file:Documentation/sh/register-banks.txt> for further
- information on SR.RB and register banking in the kernel in general.
-
config NODES_SHIFT
int
default "1"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 66a25ef4ef1..87902e0298e 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -31,7 +31,8 @@ config EARLY_SCIF_CONSOLE_PORT
hex "SCIF port for early console"
depends on EARLY_SCIF_CONSOLE
default "0xffe00000" if CPU_SUBTYPE_SH7780
- default "0xfffe9800" if CPU_SUBTYPE_SH72060
+ default "0xfffe9800" if CPU_SUBTYPE_SH7206
+ default "0xf8420000" if CPU_SUBTYPE_SH7619
default "0xffe80000" if CPU_SH4
config EARLY_PRINTK
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index d10bba5e107..c1dbef21263 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -179,7 +179,7 @@ maketools: include/linux/version.h FORCE
all: zImage
-zImage: vmlinux
+zImage uImage uImage.srec vmlinux.srec: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
compressed: zImage
@@ -190,5 +190,8 @@ archclean:
CLEAN_FILES += include/asm-sh/machtypes.h
define archhelp
- @echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)'
+ @echo '* zImage - Compressed kernel image'
+ @echo ' vmlinux.srec - Create an ELF S-record'
+ @echo ' uImage - Create a bootable image for U-Boot'
+ @echo ' uImage.srec - Create an S-record for U-Boot'
endef
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
index 8f2e1c68b90..3eba6d086d7 100644
--- a/arch/sh/boards/landisk/irq.c
+++ b/arch/sh/boards/landisk/irq.c
@@ -16,8 +16,8 @@
*/
#include <linux/init.h>
#include <linux/irq.h>
-#include <asm/io.h>
-#include <asm/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
#include <asm/landisk/iodata_landisk.h>
static void enable_landisk_irq(unsigned int irq);
diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c
index 3fb0c5f5b23..27da88486f7 100644
--- a/arch/sh/boards/se/7206/irq.c
+++ b/arch/sh/boards/se/7206/irq.c
@@ -10,6 +10,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/se7206.h>
#define INTSTS0 0x31800000
@@ -18,6 +19,13 @@
#define INTMSK1 0x31800006
#define INTSEL 0x31800008
+#define IRQ0_IRQ 64
+#define IRQ1_IRQ 65
+#define IRQ3_IRQ 67
+
+#define INTC_IPR01 0xfffe0818
+#define INTC_ICR1 0xfffe0802
+
static void disable_se7206_irq(unsigned int irq)
{
unsigned short val;
@@ -39,7 +47,7 @@ static void disable_se7206_irq(unsigned int irq)
case IRQ1_IRQ:
msk0 |= 0x000f;
break;
- case IRQ2_IRQ:
+ case IRQ3_IRQ:
msk0 |= 0x0f00;
msk1 |= 0x00ff;
break;
@@ -70,7 +78,7 @@ static void enable_se7206_irq(unsigned int irq)
case IRQ1_IRQ:
msk0 &= ~0x000f;
break;
- case IRQ2_IRQ:
+ case IRQ3_IRQ:
msk0 &= ~0x0f00;
msk1 &= ~0x00ff;
break;
@@ -96,7 +104,7 @@ static void eoi_se7206_irq(unsigned int irq)
case IRQ1_IRQ:
sts0 &= ~0x000f;
break;
- case IRQ2_IRQ:
+ case IRQ3_IRQ:
sts0 &= ~0x0f00;
sts1 &= ~0x00ff;
break;
@@ -106,7 +114,7 @@ static void eoi_se7206_irq(unsigned int irq)
}
static struct irq_chip se7206_irq_chip __read_mostly = {
- .name = "SE7206-FPGA-IRQ",
+ .name = "SE7206-FPGA",
.mask = disable_se7206_irq,
.unmask = enable_se7206_irq,
.mask_ack = disable_se7206_irq,
diff --git a/arch/sh/boards/se/7619/Makefile b/arch/sh/boards/se/7619/Makefile
index 3666eca8a65..d21775c28cd 100644
--- a/arch/sh/boards/se/7619/Makefile
+++ b/arch/sh/boards/se/7619/Makefile
@@ -2,4 +2,4 @@
# Makefile for the 7619 SolutionEngine specific parts of the kernel
#
-obj-y := setup.o io.o
+obj-y := setup.o
diff --git a/arch/sh/boards/se/7619/io.c b/arch/sh/boards/se/7619/io.c
deleted file mode 100644
index 176f1f39cd9..00000000000
--- a/arch/sh/boards/se/7619/io.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * linux/arch/sh/boards/se/7619/io.c
- *
- * Copyright (C) 2006 Yoshinori Sato
- *
- * I/O routine for Hitachi 7619 SolutionEngine.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <asm/se7619.h>
-#include <asm/irq.h>
-
-/* FIXME: M3A-ZAB7 Compact Flash Slot support */
-
-static inline void delay(void)
-{
- ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */
-}
-
-#define badio(name,port) \
- printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \
- #name, (port), (__u32) __builtin_return_address(0))
-
-unsigned char se7619___inb(unsigned long port)
-{
- badio(inb, port);
- return 0;
-}
-
-unsigned char se7619___inb_p(unsigned long port)
-{
- badio(inb_p, port);
- delay();
- return 0;
-}
-
-unsigned short se7619___inw(unsigned long port)
-{
- badio(inw, port);
- return 0;
-}
-
-unsigned int se7619___inl(unsigned long port)
-{
- badio(inl, port);
- return 0;
-}
-
-void se7619___outb(unsigned char value, unsigned long port)
-{
- badio(outb, port);
-}
-
-void se7619___outb_p(unsigned char value, unsigned long port)
-{
- badio(outb_p, port);
- delay();
-}
-
-void se7619___outw(unsigned short value, unsigned long port)
-{
- badio(outw, port);
-}
-
-void se7619___outl(unsigned int value, unsigned long port)
-{
- badio(outl, port);
-}
-
-void se7619___insb(unsigned long port, void *addr, unsigned long count)
-{
- badio(inw, port);
-}
-
-void se7619___insw(unsigned long port, void *addr, unsigned long count)
-{
- badio(inw, port);
-}
-
-void se7619___insl(unsigned long port, void *addr, unsigned long count)
-{
- badio(insl, port);
-}
-
-void se7619___outsb(unsigned long port, const void *addr, unsigned long count)
-{
- badio(insl, port);
-}
-
-void se7619___outsw(unsigned long port, const void *addr, unsigned long count)
-{
- badio(insl, port);
-}
-
-void se7619___outsl(unsigned long port, const void *addr, unsigned long count)
-{
- badio(outsw, port);
-}
diff --git a/arch/sh/boards/se/7619/setup.c b/arch/sh/boards/se/7619/setup.c
index e627b26de0d..52d2c4d5d2f 100644
--- a/arch/sh/boards/se/7619/setup.c
+++ b/arch/sh/boards/se/7619/setup.c
@@ -9,7 +9,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/io.h>
-#include <asm/se7619.h>
#include <asm/machvec.h>
/*
@@ -19,25 +18,5 @@
struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 108,
- .mv_inb = se7619___inb,
- .mv_inw = se7619___inw,
- .mv_inl = se7619___inl,
- .mv_outb = se7619___outb,
- .mv_outw = se7619___outw,
- .mv_outl = se7619___outl,
-
- .mv_inb_p = se7619___inb_p,
- .mv_inw_p = se7619___inw,
- .mv_inl_p = se7619___inl,
- .mv_outb_p = se7619___outb_p,
- .mv_outw_p = se7619___outw,
- .mv_outl_p = se7619___outl,
-
- .mv_insb = se7619___insb,
- .mv_insw = se7619___insw,
- .mv_insl = se7619___insl,
- .mv_outsb = se7619___outsb,
- .mv_outsw = se7619___outsw,
- .mv_outsl = se7619___outsl,
};
ALIAS_MV(se)
diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile
index 60797b31089..11dc272c618 100644
--- a/arch/sh/boot/Makefile
+++ b/arch/sh/boot/Makefile
@@ -8,13 +8,49 @@
# Copyright (C) 1999 Stuart Menefy
#
-targets := zImage
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+#
+# Assign safe dummy values if these variables are not defined,
+# in order to suppress error message.
+#
+CONFIG_PAGE_OFFSET ?= 0x80000000
+CONFIG_MEMORY_START ?= 0x0c000000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
+CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000
+
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+ CONFIG_ZERO_PAGE_OFFSET
+
+targets := zImage vmlinux.srec uImage uImage.srec
subdir- := compressed
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
- @echo 'Kernel: $@ is ready'
+ @echo ' Kernel: $@ is ready'
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
+KERNEL_LOAD := $(shell printf "0x%8x" $$[$(CONFIG_PAGE_OFFSET) + \
+ $(CONFIG_MEMORY_START) + \
+ $(CONFIG_ZERO_PAGE_OFFSET)+0x1000])
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \
+ -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \
+ -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
+$(obj)/uImage: $(obj)/zImage FORCE
+ $(call if_changed,uimage)
+ @echo ' Image $@ is ready'
+
+OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec
+$(obj)/vmlinux.srec: $(obj)/compressed/vmlinux
+ $(call if_changed,objcopy)
+
+OBJCOPYFLAGS_uImage.srec := -I binary -O srec
+$(obj)/uImage.srec: $(obj)/uImage
+ $(call if_changed,objcopy)
+
+clean-files += uImage uImage.srec vmlinux.srec
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index e5f44379007..d9512416f88 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -15,13 +15,7 @@ endif
#
# IMAGE_OFFSET is the load offset of the compression loader
-# Assign dummy values if these 2 variables are not defined,
-# in order to suppress error message.
#
-CONFIG_PAGE_OFFSET ?= 0x80000000
-CONFIG_MEMORY_START ?= 0x0c000000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
-
IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_PAGE_OFFSET) + \
$(CONFIG_MEMORY_START) + \
$(CONFIG_BOOT_LINK_OFFSET)])
diff --git a/arch/sh/boot/compressed/head.S b/arch/sh/boot/compressed/head.S
index 4c26a192277..a8399b01372 100644
--- a/arch/sh/boot/compressed/head.S
+++ b/arch/sh/boot/compressed/head.S
@@ -8,6 +8,7 @@
.text
#include <linux/linkage.h>
+#include <asm/page.h>
.global startup
startup:
@@ -97,7 +98,7 @@ init_stack_addr:
decompress_kernel_addr:
.long decompress_kernel
kernel_start_addr:
- .long _text+0x1000
+ .long _text+PAGE_SIZE
.align 9
fake_headers_as_bzImage:
diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c
index 35452d85b7f..df65e305acf 100644
--- a/arch/sh/boot/compressed/misc.c
+++ b/arch/sh/boot/compressed/misc.c
@@ -13,6 +13,7 @@
#include <asm/uaccess.h>
#include <asm/addrspace.h>
+#include <asm/page.h>
#ifdef CONFIG_SH_STANDARD_BIOS
#include <asm/sh_bios.h>
#endif
@@ -229,7 +230,7 @@ long* stack_start = &user_stack[STACK_SIZE];
void decompress_kernel(void)
{
output_data = 0;
- output_ptr = P2SEGADDR((unsigned long)&_text+0x1000);
+ output_ptr = P2SEGADDR((unsigned long)&_text+PAGE_SIZE);
free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index 238c0f10990..e7f8ddb0ada 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18
-# Tue Oct 3 11:14:13 2006
+# Linux kernel version: 2.6.19
+# Thu Dec 7 17:13:04 2006
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -10,6 +10,9 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -33,6 +36,7 @@ CONFIG_SYSVIPC=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -114,6 +118,8 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_SH_LANDISK=y
# CONFIG_SH_TITAN is not set
# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+# CONFIG_SH_7619_SOLUTION_ENGINE is not set
# CONFIG_SH_UNKNOWN is not set
#
@@ -125,6 +131,12 @@ CONFIG_CPU_SH4=y
# SH-2 Processor Support
#
# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
#
# SH-3 Processor Support
@@ -160,6 +172,7 @@ CONFIG_CPU_SUBTYPE_SH7751R=y
#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
#
# SH4AL-DSP Processor Support
@@ -175,6 +188,9 @@ CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x04000000
CONFIG_VSYSCALL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -196,16 +212,21 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# Processor features
#
CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_SH_FPU=y
# CONFIG_SH_DSP is not set
# CONFIG_SH_STORE_QUEUES is not set
CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_IPR_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
#
# Timer support
#
CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+# CONFIG_NO_IDLE_HZ is not set
CONFIG_SH_PCLK_FREQ=33333333
#
@@ -216,9 +237,7 @@ CONFIG_SH_PCLK_FREQ=33333333
#
# DMA support
#
-CONFIG_SH_DMA=y
-CONFIG_NR_ONCHIP_DMA_CHANNELS=4
-# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+# CONFIG_SH_DMA is not set
#
# Companion Chips
@@ -227,6 +246,11 @@ CONFIG_NR_ONCHIP_DMA_CHANNELS=4
CONFIG_HEARTBEAT=y
#
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
# Kernel features
#
# CONFIG_HZ_100 is not set
@@ -340,11 +364,13 @@ CONFIG_IP_PNP=y
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
@@ -361,24 +387,12 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_NETBIOS_NS is not set
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_H323 is not set
-# CONFIG_IP_NF_SIP is not set
CONFIG_IP_NF_QUEUE=m
#
@@ -477,6 +491,12 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_ATA_OVER_ETH is not set
#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -519,6 +539,7 @@ CONFIG_BLK_DEV_AEC62XX=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_IT821X is not set
@@ -542,6 +563,7 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
@@ -561,6 +583,7 @@ CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -602,12 +625,12 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC395x is not set
@@ -615,6 +638,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# PCMCIA SCSI adapter support
@@ -757,6 +781,7 @@ CONFIG_8139CP=y
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -871,10 +896,6 @@ CONFIG_HW_RANDOM=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
#
@@ -889,7 +910,6 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -905,6 +925,7 @@ CONFIG_HW_RANDOM=y
#
# Dallas's 1-wire bus
#
+# CONFIG_W1 is not set
#
# Hardware Monitoring support
@@ -917,10 +938,6 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Misc devices
-#
-
-#
# Multimedia devices
#
CONFIG_VIDEO_DEV=m
@@ -1037,6 +1054,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1106,7 +1124,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
#
# USB Imaging devices
@@ -1121,6 +1138,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_KAWETH is not set
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1156,6 +1174,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m
# 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_MOS7720 is not set
# CONFIG_USB_SERIAL_MOS7840 is not set
# CONFIG_USB_SERIAL_NAVMAN is not set
CONFIG_USB_SERIAL_PL2303=m
@@ -1167,6 +1186,7 @@ CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
#
# USB Miscellaneous drivers
@@ -1188,6 +1208,7 @@ CONFIG_USB_EMI26=m
CONFIG_USB_SISUSBVGA=m
CONFIG_USB_SISUSBVGA_CON=y
# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1254,6 +1275,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -1264,6 +1286,7 @@ CONFIG_REISERFS_FS=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
@@ -1414,6 +1437,7 @@ CONFIG_NLS_CODEPAGE_932=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
@@ -1422,6 +1446,7 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
@@ -1445,6 +1470,4 @@ CONFIG_SH_STANDARD_BIOS=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
CONFIG_PLIST=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 36cec0b6e7c..87ab9080fd1 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Sun Nov 5 16:20:10 2006
+# Linux kernel version: 2.6.19
+# Wed Dec 6 14:40:15 2006
#
CONFIG_SUPERH=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
@@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -34,24 +36,23 @@ CONFIG_LOCALVERSION=""
# CONFIG_IKCONFIG is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
-CONFIG_UID16=y
+# CONFIG_UID16 is not set
# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_KALLSYMS is not set
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_TINY_SHMEM=y
-CONFIG_BASE_SMALL=0
+CONFIG_BASE_SMALL=1
# CONFIG_SLOB is not set
#
@@ -160,6 +161,7 @@ CONFIG_CPU_SUBTYPE_SH7206=y
#
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
#
# SH4AL-DSP Processor Support
@@ -172,7 +174,10 @@ CONFIG_CPU_SUBTYPE_SH7206=y
#
CONFIG_PAGE_OFFSET=0x00000000
CONFIG_MEMORY_START=0x0c000000
-CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -194,6 +199,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# Processor features
#
# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_SH_FPU is not set
# CONFIG_SH_FPU_EMU is not set
# CONFIG_SH_DSP is not set
@@ -203,6 +209,8 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
#
CONFIG_SH_CMT=y
# CONFIG_SH_MTU2 is not set
+CONFIG_SH_TIMER_IRQ=140
+# CONFIG_NO_IDLE_HZ is not set
CONFIG_SH_PCLK_FREQ=33333333
CONFIG_SH_CLK_MD=6
@@ -222,6 +230,11 @@ CONFIG_SH_CLK_MD=6
# CONFIG_HD6446X_SERIES is not set
#
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
# Kernel features
#
CONFIG_HZ_100=y
@@ -279,9 +292,6 @@ CONFIG_NET=y
# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -297,9 +307,9 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
@@ -371,7 +381,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
@@ -422,7 +432,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0x1000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# CONFIG_MTD_SOLUTIONENGINE is not set
# CONFIG_MTD_UCLINUX is not set
@@ -468,10 +478,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=4
# 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_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -519,7 +526,50 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Network device support
#
-# CONFIG_NETDEVICES 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
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+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
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -536,7 +586,26 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Input device support
#
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
@@ -564,8 +633,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_UNIX98_PTYS is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
#
# IPMI
@@ -576,7 +644,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -610,12 +678,8 @@ CONFIG_HW_RANDOM=y
#
# Hardware Monitoring support
#
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Multimedia devices
@@ -630,7 +694,7 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
#
@@ -701,8 +765,7 @@ CONFIG_FIRMWARE_EDID=y
#
# File systems
#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
@@ -755,7 +818,7 @@ CONFIG_RAMFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -793,8 +856,9 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_KERNEL is not set
@@ -819,7 +883,7 @@ CONFIG_LOG_BUF_SHIFT=14
#
# Library routines
#
-CONFIG_CRC_CCITT=y
+# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
new file mode 100644
index 00000000000..20ac7f4c53f
--- /dev/null
+++ b/arch/sh/configs/se7619_defconfig
@@ -0,0 +1,744 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19
+# Wed Dec 6 16:35:36 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SLAB=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_7343_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_7206_SOLUTION_ENGINE is not set
+CONFIG_SH_7619_SOLUTION_ENGINE=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH2=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+CONFIG_CPU_SUBTYPE_SH7619=y
+
+#
+# SH-2A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+
+#
+# SH4AL-DSP Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+
+#
+# Memory management options
+#
+CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_SH_WRITETHROUGH=y
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+
+#
+# Timer support
+#
+CONFIG_SH_CMT=y
+CONFIG_SH_TIMER_IRQ=86
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_SH_PCLK_FREQ=31250000
+CONFIG_SH_CLK_MD=5
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_KEXEC is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=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
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC 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_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=y
+CONFIG_MTD_PHYSMAP_START=0xa0000000
+CONFIG_MTD_PHYSMAP_LEN=0x01000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# 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
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index f2b9157c314..b3d20c0e021 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -14,7 +14,7 @@
#include <asm/push-switch.h>
#define DRV_NAME "push-switch"
-#define DRV_VERSION "0.1.0"
+#define DRV_VERSION "0.1.1"
static ssize_t switch_show(struct device *dev,
struct device_attribute *attr,
@@ -32,10 +32,10 @@ static void switch_timer(unsigned long data)
schedule_work(&psw->work);
}
-static void switch_work_handler(void *data)
+static void switch_work_handler(struct work_struct *work)
{
- struct platform_device *pdev = data;
- struct push_switch *psw = platform_get_drvdata(pdev);
+ struct push_switch *psw = container_of(work, struct push_switch, work);
+ struct platform_device *pdev = psw->pdev;
psw->state = 0;
@@ -76,12 +76,15 @@ static int switch_drv_probe(struct platform_device *pdev)
}
}
- INIT_WORK(&psw->work, switch_work_handler, pdev);
+ INIT_WORK(&psw->work, switch_work_handler);
init_timer(&psw->debounce);
psw->debounce.function = switch_timer;
psw->debounce.data = (unsigned long)psw;
+ /* Workqueue API brain-damage */
+ psw->pdev = pdev;
+
platform_set_drvdata(pdev, psw);
return 0;
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index 0582e6712b7..d055a3ea6b4 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_CPU_SH2) = sh2/
obj-$(CONFIG_CPU_SH2A) = sh2a/
obj-$(CONFIG_CPU_SH3) = sh3/
obj-$(CONFIG_CPU_SH4) = sh4/
+obj-$(CONFIG_CPU_SH4A) += sh4a/
obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index 34d51b3745e..d51fa5e9904 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -177,15 +177,21 @@ interrupt_entry:
7: .long do_IRQ
8: .long do_exception_error
-trap_entry:
- add #-0x10,r9
+trap_entry:
+ /* verbose BUG trapa entry check */
+ mov #0x3e,r8
+ cmp/ge r8,r9
+ bf/s 1f
+ add #-0x10,r9
+ add #0x10,r9
+1:
shll2 r9 ! TRA
mov #OFF_TRA,r8
add r15,r8
mov.l r9,@r8
mov r9,r8
#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 5f, r9
+ mov.l 2f, r9
jsr @r9
nop
#endif
@@ -194,12 +200,8 @@ trap_entry:
nop
.align 2
-1: .long syscall_exit
-2: .long break_point_trap_software
-3: .long NR_syscalls
-4: .long sys_call_table
#ifdef CONFIG_TRACE_IRQFLAGS
-5: .long trace_hardirqs_on
+2: .long trace_hardirqs_on
#endif
#if defined(CONFIG_SH_STANDARD_BIOS)
@@ -264,7 +266,7 @@ ENTRY(address_error_handler)
restore_all:
cli
#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 3f, r0
+ mov.l 1f, r0
jsr @r0
nop
#endif
@@ -309,20 +311,14 @@ restore_all:
mov.l @r15,r15
rte
nop
-2:
- mov.l 1f,r8
- mov.l 2f,r9
- jmp @r9
- lds r8,pr
- .align 2
+#ifdef CONFIG_TRACE_IRQFLAGS
+1: .long trace_hardirqs_off
+#endif
$current_thread_info:
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
-#ifdef CONFIG_TRACE_IRQFLAGS
-3: .long trace_hardirqs_off
-#endif
! common exception handler
#include "../../entry-common.S"
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 82c2d905152..79283e6c1d8 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -51,3 +51,44 @@ static int __init sh7619_devices_setup(void)
ARRAY_SIZE(sh7619_devices));
}
__initcall(sh7619_devices_setup);
+
+#define INTC_IPRC 0xf8080000UL
+#define INTC_IPRD 0xf8080002UL
+
+#define CMI0_IRQ 86
+
+#define SCIF0_ERI_IRQ 88
+#define SCIF0_RXI_IRQ 89
+#define SCIF0_BRI_IRQ 90
+#define SCIF0_TXI_IRQ 91
+
+#define SCIF1_ERI_IRQ 92
+#define SCIF1_RXI_IRQ 93
+#define SCIF1_BRI_IRQ 94
+#define SCIF1_TXI_IRQ 95
+
+#define SCIF2_BRI_IRQ 96
+#define SCIF2_ERI_IRQ 97
+#define SCIF2_RXI_IRQ 98
+#define SCIF2_TXI_IRQ 99
+
+static struct ipr_data sh7619_ipr_map[] = {
+ { CMI0_IRQ, INTC_IPRC, 1, 2 },
+ { SCIF0_ERI_IRQ, INTC_IPRD, 3, 3 },
+ { SCIF0_RXI_IRQ, INTC_IPRD, 3, 3 },
+ { SCIF0_BRI_IRQ, INTC_IPRD, 3, 3 },
+ { SCIF0_TXI_IRQ, INTC_IPRD, 3, 3 },
+ { SCIF1_ERI_IRQ, INTC_IPRD, 2, 3 },
+ { SCIF1_RXI_IRQ, INTC_IPRD, 2, 3 },
+ { SCIF1_BRI_IRQ, INTC_IPRD, 2, 3 },
+ { SCIF1_TXI_IRQ, INTC_IPRD, 2, 3 },
+ { SCIF2_ERI_IRQ, INTC_IPRD, 1, 3 },
+ { SCIF2_RXI_IRQ, INTC_IPRD, 1, 3 },
+ { SCIF2_BRI_IRQ, INTC_IPRD, 1, 3 },
+ { SCIF2_TXI_IRQ, INTC_IPRD, 1, 3 },
+};
+
+void __init init_IRQ_ipr(void)
+{
+ make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index cdfeef49e62..4b60fcc7d66 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -17,22 +17,22 @@ static struct plat_sci_port sci_platform_data[] = {
.mapbase = 0xfffe8000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
- .irqs = { 240, 241, 242, 243},
+ .irqs = { 241, 242, 243, 240},
}, {
.mapbase = 0xfffe8800,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
- .irqs = { 244, 245, 246, 247},
+ .irqs = { 247, 244, 245, 246},
}, {
.mapbase = 0xfffe9000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
- .irqs = { 248, 249, 250, 251},
+ .irqs = { 249, 250, 251, 248},
}, {
.mapbase = 0xfffe9800,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
- .irqs = { 252, 253, 254, 255},
+ .irqs = { 253, 254, 255, 252},
}, {
.flags = 0,
}
@@ -56,3 +56,57 @@ static int __init sh7206_devices_setup(void)
ARRAY_SIZE(sh7206_devices));
}
__initcall(sh7206_devices_setup);
+
+#define INTC_IPR08 0xfffe0c04UL
+#define INTC_IPR09 0xfffe0c06UL
+#define INTC_IPR14 0xfffe0c10UL
+
+#define CMI0_IRQ 140
+
+#define MTU1_TGI1A 164
+
+#define SCIF0_BRI_IRQ 240
+#define SCIF0_ERI_IRQ 241
+#define SCIF0_RXI_IRQ 242
+#define SCIF0_TXI_IRQ 243
+
+#define SCIF1_BRI_IRQ 244
+#define SCIF1_ERI_IRQ 245
+#define SCIF1_RXI_IRQ 246
+#define SCIF1_TXI_IRQ 247
+
+#define SCIF2_BRI_IRQ 248
+#define SCIF2_ERI_IRQ 249
+#define SCIF2_RXI_IRQ 250
+#define SCIF2_TXI_IRQ 251
+
+#define SCIF3_BRI_IRQ 252
+#define SCIF3_ERI_IRQ 253
+#define SCIF3_RXI_IRQ 254
+#define SCIF3_TXI_IRQ 255
+
+static struct ipr_data sh7206_ipr_map[] = {
+ { CMI0_IRQ, INTC_IPR08, 3, 2 },
+ { MTU2_TGI1A, INTC_IPR09, 1, 2 },
+ { SCIF0_ERI_IRQ, INTC_IPR14, 3, 3 },
+ { SCIF0_RXI_IRQ, INTC_IPR14, 3, 3 },
+ { SCIF0_BRI_IRQ, INTC_IPR14, 3, 3 },
+ { SCIF0_TXI_IRQ, INTC_IPR14, 3, 3 },
+ { SCIF1_ERI_IRQ, INTC_IPR14, 2, 3 },
+ { SCIF1_RXI_IRQ, INTC_IPR14, 2, 3 },
+ { SCIF1_BRI_IRQ, INTC_IPR14, 2, 3 },
+ { SCIF1_TXI_IRQ, INTC_IPR14, 2, 3 },
+ { SCIF2_ERI_IRQ, INTC_IPR14, 1, 3 },
+ { SCIF2_RXI_IRQ, INTC_IPR14, 1, 3 },
+ { SCIF2_BRI_IRQ, INTC_IPR14, 1, 3 },
+ { SCIF2_TXI_IRQ, INTC_IPR14, 1, 3 },
+ { SCIF3_ERI_IRQ, INTC_IPR14, 0, 3 },
+ { SCIF3_RXI_IRQ, INTC_IPR14, 0, 3 },
+ { SCIF3_BRI_IRQ, INTC_IPR14, 0, 3 },
+ { SCIF3_TXI_IRQ, INTC_IPR14, 0, 3 },
+};
+
+void __init init_IRQ_ipr(void)
+{
+ make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 6e415baf04b..19ca68c7188 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -12,17 +12,12 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
-obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o
# Primary on-chip clocks (common)
+ifndef CONFIG_CPU_SH4A
clock-$(CONFIG_CPU_SH4) := clock-sh4.o
-clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
+endif
# Additional clocks by subtype
clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index afe0f1b1c03..9031a22a2ce 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -119,11 +119,20 @@ int __init detect_cpu_and_cache_system(void)
break;
case 0x3000:
case 0x3003:
+ case 0x3009:
cpu_data->type = CPU_SH7343;
cpu_data->icache.ways = 4;
cpu_data->dcache.ways = 4;
cpu_data->flags |= CPU_HAS_LLSC;
break;
+ case 0x3008:
+ if (prr == 0xa0) {
+ cpu_data->type = CPU_SH7722;
+ cpu_data->icache.ways = 4;
+ cpu_data->dcache.ways = 4;
+ cpu_data->flags |= CPU_HAS_LLSC;
+ }
+ break;
case 0x8000:
cpu_data->type = CPU_ST40RA;
cpu_data->flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index bbcb06f18b0..cbac27634c0 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -14,6 +14,36 @@
#include <linux/io.h>
#include <asm/sci.h>
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xffc80000,
+ .end = 0xffc80000 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = 21,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = 22,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = 20,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffe00000,
@@ -39,6 +69,7 @@ static struct platform_device sci_device = {
};
static struct platform_device *sh7750_devices[] __initdata = {
+ &rtc_device,
&sci_device,
};
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 0c9ea38d2ca..d7fff752e56 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -111,8 +111,9 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
vma->phys_addr = map->addr;
- if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr,
- map->size, flags)) {
+ if (ioremap_page_range((unsigned long)vma->addr,
+ (unsigned long)vma->addr + map->size,
+ vma->phys_addr, __pgprot(flags))) {
vunmap(vma->addr);
return -EAGAIN;
}
@@ -176,7 +177,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
- ret = __sq_remap(map, flags);
+ ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
if (unlikely(ret != 0))
goto out;
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
new file mode 100644
index 00000000000..a8f493f2f21
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the Linux/SuperH SH-4 backends.
+#
+
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
+
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7343.o
+
+obj-y += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
index 2fa5cb2ae68..2fa5cb2ae68 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh73180.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
new file mode 100644
index 00000000000..1707a213f0c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7343.c
+ *
+ * SH7343/SH7722 support for the clock framework
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+/*
+ * SH7343/SH7722 uses a common set of multipliers and divisors, so this
+ * is quite simple..
+ */
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void master_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) & 0x000f);
+ clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_master_clk_ops = {
+ .init = master_clk_init,
+ .recalc = master_clk_recalc,
+};
+
+static void module_clk_init(struct clk *clk)
+{
+ clk->parent = NULL;
+ clk->rate = CONFIG_SH_PCLK_FREQ;
+}
+
+static struct clk_ops sh7343_module_clk_ops = {
+ .init = module_clk_init,
+};
+
+static void bus_clk_init(struct clk *clk)
+{
+ clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
+ clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_bus_clk_ops = {
+ .init = bus_clk_init,
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_init(struct clk *clk)
+{
+ clk->parent = clk_get(NULL, "module_clk");
+ clk->flags |= CLK_RATE_PROPAGATES;
+ clk_set_rate(clk, clk_get_rate(clk));
+}
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
+ clk->rate = clk->parent->rate * pll_calc() *
+ multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_cpu_clk_ops = {
+ .init = cpu_clk_init,
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7343_clk_ops[] = {
+ &sh7343_master_clk_ops,
+ &sh7343_module_clk_ops,
+ &sh7343_bus_clk_ops,
+ &sh7343_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7343_clk_ops))
+ *ops = sh7343_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
index c8694bac647..c8694bac647 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
index 9e6a216750c..9e6a216750c 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4a/setup-sh73180.c
index cc9ea1e2e5d..cc9ea1e2e5d 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh73180.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 91d61cf91ba..91d61cf91ba 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
new file mode 100644
index 00000000000..1143fbf65fa
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -0,0 +1,80 @@
+/*
+ * SH7722 Setup
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 80, 81, 83, 82 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7722_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7722_devices_setup(void)
+{
+ return platform_add_devices(sh7722_devices,
+ ARRAY_SIZE(sh7722_devices));
+}
+__initcall(sh7722_devices_setup);
+
+static struct ipr_data sh7722_ipr_map[] = {
+ /* IRQ, IPR-idx, shift, prio */
+ { 16, 0, 12, 2 }, /* TMU0 */
+ { 17, 0, 8, 2 }, /* TMU1 */
+ { 80, 6, 12, 3 }, /* SCIF ERI */
+ { 81, 6, 12, 3 }, /* SCIF RXI */
+ { 82, 6, 12, 3 }, /* SCIF BRI */
+ { 83, 6, 12, 3 }, /* SCIF TXI */
+};
+
+static unsigned long ipr_offsets[] = {
+ 0xa4080000, /* 0: IPRA */
+ 0xa4080004, /* 1: IPRB */
+ 0xa4080008, /* 2: IPRC */
+ 0xa408000c, /* 3: IPRD */
+ 0xa4080010, /* 4: IPRE */
+ 0xa4080014, /* 5: IPRF */
+ 0xa4080018, /* 6: IPRG */
+ 0xa408001c, /* 7: IPRH */
+ 0xa4080020, /* 8: IPRI */
+ 0xa4080024, /* 9: IPRJ */
+ 0xa4080028, /* 10: IPRK */
+ 0xa408002c, /* 11: IPRL */
+};
+
+unsigned int map_ipridx_to_addr(int idx)
+{
+ if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+ return 0;
+ return ipr_offsets[idx];
+}
+
+void __init init_IRQ_ipr(void)
+{
+ make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index 6a04cc5f5ac..6a04cc5f5ac 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 9aeaa2ddaa2..9aeaa2ddaa2 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 60340823798..560b91cdd15 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -144,16 +144,16 @@ static struct console *early_console =
;
static int __initdata keep_early;
+static int early_console_initialized;
-int __init setup_early_printk(char *opt)
+int __init setup_early_printk(char *buf)
{
- char *space;
- char buf[256];
+ if (!buf)
+ return 0;
- strlcpy(buf, opt, sizeof(buf));
- space = strchr(buf, ' ');
- if (space)
- *space = 0;
+ if (early_console_initialized)
+ return 0;
+ early_console_initialized = 1;
if (strstr(buf, "keep"))
keep_early = 1;
@@ -175,12 +175,14 @@ int __init setup_early_printk(char *opt)
if (likely(early_console))
register_console(early_console);
- return 1;
+ return 0;
}
-__setup("earlyprintk=", setup_early_printk);
+early_param("earlyprintk", setup_early_printk);
void __init disable_early_printk(void)
{
+ if (!early_console_initialized || !early_console)
+ return;
if (!keep_early) {
printk("disabling early console\n");
unregister_console(early_console);
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index 29136a35d7c..fc279aeb73a 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -79,18 +79,29 @@ debug_kernel_sw:
.align 2
3: .long kgdb_handle_exception
#endif /* CONFIG_SH_KGDB */
-
+#ifdef CONFIG_SH_STANDARD_BIOS
+ bra debug_kernel_fw
+ nop
+#endif
#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
-
.align 2
debug_trap:
#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+ mov r8, r0
+ shlr2 r0
+ cmp/eq #0x3f, r0 ! sh_bios() trap
+ bf 1f
+#ifdef CONFIG_SH_KGDB
+ cmp/eq #0xff, r0 ! XXX: KGDB trap, fix for SH-2.
+ bf 1f
+#endif
mov #OFF_SR, r0
mov.l @(r0,r15), r0 ! get status register
shll r0
shll r0 ! kernel space?
bt/s debug_kernel
+1:
#endif
mov.l @r15, r0 ! Restore R0 value
mov.l 1f, r8
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index 6aca4bc6ec5..71a3ad7d283 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -33,7 +33,8 @@ ENTRY(empty_zero_page)
.long 0x00360000 /* INITRD_START */
.long 0x000a0000 /* INITRD_SIZE */
.long 0
- .balign PAGE_SIZE,0,PAGE_SIZE
+1:
+ .skip PAGE_SIZE - empty_zero_page - 1b
.text
/*
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index f3e2631be14..486c06e1803 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -470,9 +470,10 @@ unsigned long get_wchan(struct task_struct *p)
*/
pc = thread_saved_pc(p);
if (in_sched_functions(pc)) {
- schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
- return (unsigned long)((unsigned long *)schedule_frame)[1];
+ schedule_frame = (unsigned long)p->thread.sp;
+ return ((unsigned long *)schedule_frame)[21];
}
+
return pc;
}
@@ -498,6 +499,16 @@ asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+ /* Rewind */
regs->pc -= 2;
+
+#ifdef CONFIG_BUG
+ if (__kernel_text_address(instruction_pointer(regs))) {
+ u16 insn = *(u16 *)instruction_pointer(regs);
+ if (insn == TRAPA_BUG_OPCODE)
+ handle_BUG(regs);
+ }
+#endif
+
force_sig(SIGTRAP, current);
}
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index f8dd6b7bfab..225f9ea5cdd 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -84,8 +84,7 @@ unsigned long memory_start, memory_end;
static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
struct sh_machine_vector** mvp,
- unsigned long *mv_io_base,
- int *mv_mmio_enable)
+ unsigned long *mv_io_base)
{
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
@@ -112,23 +111,6 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
}
}
-#ifdef CONFIG_EARLY_PRINTK
- if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
- char *ep_end;
-
- if (to != command_line)
- to--;
-
- from += 12;
- ep_end = strchr(from, ' ');
-
- setup_early_printk(from);
- printk("early console enabled\n");
-
- from = ep_end;
- }
-#endif
-
if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
char* mv_end;
char* mv_comma;
@@ -145,7 +127,6 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
int ints[3];
get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
*mv_io_base = ints[1];
- *mv_mmio_enable = ints[2];
mv_len = mv_comma - from;
} else {
mv_len = mv_end - from;
@@ -158,6 +139,7 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
*mvp = get_mv_byname(mv_name);
}
+
c = *(from++);
if (!c)
break;
@@ -177,9 +159,8 @@ static int __init sh_mv_setup(char **cmdline_p)
struct sh_machine_vector *mv = NULL;
char mv_name[MV_NAME_SIZE] = "";
unsigned long mv_io_base = 0;
- int mv_mmio_enable = 0;
- parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
+ parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
#ifdef CONFIG_SH_UNKNOWN
if (mv == NULL) {
@@ -258,6 +239,7 @@ void __init setup_arch(char **cmdline_p)
sh_mv_setup(cmdline_p);
+
/*
* Find the highest page frame number we have available
*/
@@ -305,6 +287,7 @@ void __init setup_arch(char **cmdline_p)
PFN_PHYS(pages));
}
+
/*
* Reserve the kernel text and
* Reserve the bootmem bitmap. We do this in two steps (first step
@@ -325,14 +308,18 @@ void __init setup_arch(char **cmdline_p)
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
if (&__rd_start != &__rd_end) {
LOADER_TYPE = 1;
- INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
- INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
+ INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
+ __MEMORY_START;
+ INITRD_SIZE = (unsigned long)&__rd_end -
+ (unsigned long)&__rd_start;
}
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
- reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
- initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START;
+ reserve_bootmem_node(NODE_DATA(0), INITRD_START +
+ __MEMORY_START, INITRD_SIZE);
+ initrd_start = INITRD_START + PAGE_OFFSET +
+ __MEMORY_START;
initrd_end = initrd_start + INITRD_SIZE;
} else {
printk("initrd extends beyond end of memory "
@@ -404,7 +391,7 @@ static const char *cpu_name[] = {
[CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
- [CPU_SH7785] = "SH7785",
+ [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722",
[CPU_SH_NONE] = "Unknown"
};
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index ceee7914340..e6106239a0f 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -70,13 +70,26 @@ DECLARE_EXPORT(__sdivsi3);
DECLARE_EXPORT(__ashrdi3);
DECLARE_EXPORT(__ashldi3);
DECLARE_EXPORT(__lshrdi3);
-DECLARE_EXPORT(__movstr);
DECLARE_EXPORT(__movstrSI16);
+#if __GNUC__ == 4
+DECLARE_EXPORT(__movmem);
+#else
+DECLARE_EXPORT(__movstr);
+#endif
#ifdef CONFIG_CPU_SH4
+#if __GNUC__ == 4
+DECLARE_EXPORT(__movmem_i4_even);
+DECLARE_EXPORT(__movmem_i4_odd);
+DECLARE_EXPORT(__movmemSI12_i4);
+DECLARE_EXPORT(__sdivsi3_i4i);
+DECLARE_EXPORT(__udiv_qrnnd_16);
+DECLARE_EXPORT(__udivsi3_i4i);
+#else /* GCC 3.x */
DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);
DECLARE_EXPORT(__movstrSI12_i4);
+#endif /* __GNUC__ == 4 */
#endif
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index bb1c480a59c..379c88bf5d9 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -101,7 +101,7 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
*/
#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
-#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
+#if defined(CONFIG_CPU_SH2)
#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */
#else
#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 5083b6ed4b3..e18f183e103 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -314,6 +314,12 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
#endif
}
+#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
+#define SYSCALL_ARG3 "trapa #0x23"
+#else
+#define SYSCALL_ARG3 "trapa #0x13"
+#endif
+
/*
* Do a system call from kernel instead of calling sys_execve so we
* end up with proper pt_regs.
@@ -324,7 +330,7 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
register long __sc4 __asm__ ("r4") = (long) filename;
register long __sc5 __asm__ ("r5") = (long) argv;
register long __sc6 __asm__ ("r6") = (long) envp;
- __asm__ __volatile__ ("trapa #0x13" : "=z" (__sc0)
+ __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)
: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
: "memory");
return __sc0;
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 3762d9dc204..ec110157992 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -19,6 +19,7 @@
#include <linux/kallsyms.h>
#include <linux/io.h>
#include <linux/debug_locks.h>
+#include <linux/limits.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -129,6 +130,40 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
return -EFAULT;
}
+#ifdef CONFIG_BUG
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+static inline void do_bug_verbose(struct pt_regs *regs)
+{
+ struct bug_frame f;
+ long len;
+
+ if (__copy_from_user(&f, (const void __user *)regs->pc,
+ sizeof(struct bug_frame)))
+ return;
+
+ len = __strnlen_user(f.file, PATH_MAX) - 1;
+ if (unlikely(len < 0 || len >= PATH_MAX))
+ f.file = "<bad filename>";
+ len = __strnlen_user(f.func, PATH_MAX) - 1;
+ if (unlikely(len < 0 || len >= PATH_MAX))
+ f.func = "<bad function>";
+
+ printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n",
+ f.func, f.file, f.line);
+}
+#else
+static inline void do_bug_verbose(struct pt_regs *regs)
+{
+}
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+#endif /* CONFIG_BUG */
+
+void handle_BUG(struct pt_regs *regs)
+{
+ do_bug_verbose(regs);
+ die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
+}
+
/*
* handle an instruction that does an unaligned memory access by emulating the
* desired behaviour
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 77b4026d568..f34bdcc33a7 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -51,7 +51,7 @@ SECTIONS
}
. = ALIGN(PAGE_SIZE);
- .data.page_aligned : { *(.data.idt) }
+ .data.page_aligned : { *(.data.page_aligned) }
. = ALIGN(32);
__per_cpu_start = .;
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 4e0362f5038..29f4ee35c6d 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -35,6 +35,9 @@ config CPU_SUBTYPE_ST40
select CPU_SH4
select CPU_HAS_INTC2_IRQ
+config CPU_SHX2
+ bool
+
#
# Processor subtypes
#
@@ -180,6 +183,7 @@ config CPU_SUBTYPE_SH7780
config CPU_SUBTYPE_SH7785
bool "Support SH7785 processor"
select CPU_SH4A
+ select CPU_SHX2
select CPU_HAS_INTC2_IRQ
comment "SH4AL-DSP Processor Support"
@@ -192,6 +196,12 @@ config CPU_SUBTYPE_SH7343
bool "Support SH7343 processor"
select CPU_SH4AL_DSP
+config CPU_SUBTYPE_SH7722
+ bool "Support SH7722 processor"
+ select CPU_SH4AL_DSP
+ select CPU_SHX2
+ select CPU_HAS_IPR_IRQ
+
endmenu
menu "Memory management options"
@@ -250,7 +260,7 @@ config 32BIT
config X2TLB
bool "Enable extended TLB mode"
- depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
+ depends on CPU_SHX2 && MMU && EXPERIMENTAL
help
Selecting this option will enable the extended mode of the SH-X2
TLB. For legacy SH-X behaviour and interoperability, say N. For
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index ae531affccb..c6955157c98 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -107,7 +107,7 @@ void __init p3_cache_init(void)
emit_cache_params();
- if (remap_area_pages(P3SEG, 0, PAGE_SIZE * 4, _PAGE_CACHABLE))
+ if (ioremap_page_range(P3SEG, P3SEG + (PAGE_SIZE * 4), 0, PAGE_KERNEL))
panic("%s failed.", __FUNCTION__);
for (i = 0; i < cpu_data->dcache.n_aliases; i++)
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 59f4cc18235..29bd37b1488 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -77,6 +77,7 @@ void show_mem(void)
printk("%d pages swap cached\n",cached);
}
+#ifdef CONFIG_MMU
static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
{
pgd_t *pgd;
@@ -139,6 +140,7 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
set_pte_phys(address, phys, prot);
}
+#endif /* CONFIG_MMU */
/* References to section boundaries */
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index 11d54c14982..90b494a0cf4 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -16,97 +16,13 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/pci.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/addrspace.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
- unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
- unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
- flush_cache_all();
- if (address >= end)
- BUG();
- 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))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}
-
/*
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
@@ -121,6 +37,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
{
struct vm_struct * area;
unsigned long offset, last_addr, addr, orig_addr;
+ pgprot_t pgprot;
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -190,8 +107,9 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
}
#endif
+ pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
if (likely(size))
- if (remap_area_pages(addr, phys_addr, size, flags)) {
+ if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
vunmap((void *)orig_addr);
return NULL;
}
diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
index c265185b22a..60402eec4b4 100644
--- a/arch/sh/oprofile/op_model_sh7750.c
+++ b/arch/sh/oprofile/op_model_sh7750.c
@@ -142,7 +142,7 @@ static u64 sh7750_read_counter(int counter)
*/
static inline int to_counter(struct file *file)
{
- const unsigned char *name = file->f_dentry->d_parent->d_name.name;
+ const unsigned char *name = file->f_path.dentry->d_parent->d_name.name;
return (int)simple_strtol(name, NULL, 10);
}
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 58c678e0666..7bc0744b7ab 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -39,6 +39,14 @@ config RWSEM_XCHGADD_ALGORITHM
config GENERIC_ISA_DMA
bool
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
source init/Kconfig
menu "System type"
diff --git a/arch/sh64/mm/ioremap.c b/arch/sh64/mm/ioremap.c
index 80c56754f51..ff26c02511a 100644
--- a/arch/sh64/mm/ioremap.c
+++ b/arch/sh64/mm/ioremap.c
@@ -18,7 +18,7 @@
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <linux/ioport.h>
@@ -28,96 +28,6 @@
static void shmedia_mapioaddr(unsigned long, unsigned long);
static unsigned long shmedia_ioremap(struct resource *, u32, int);
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ |
- _PAGE_WRITE | _PAGE_DIRTY |
- _PAGE_ACCESSED | _PAGE_SHARED | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
-
- pfn = phys_addr >> PAGE_SHIFT;
-
- pr_debug(" %s: pte %p address %lx size %lx phys_addr %lx\n",
- __FUNCTION__,pte,address,size,phys_addr);
-
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
-
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
-
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
-
- phys_addr -= address;
-
- if (address >= end)
- BUG();
-
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags)) {
- break;
- }
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return 0;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -136,12 +46,17 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot;
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
return NULL;
+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ |
+ _PAGE_WRITE | _PAGE_DIRTY |
+ _PAGE_ACCESSED | _PAGE_SHARED | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -158,7 +73,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
return NULL;
area->phys_addr = phys_addr;
addr = 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, pgprot)) {
vunmap(addr);
return NULL;
}
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 92a7c8a636d..d0dec1ea2ee 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -166,6 +166,14 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config SUN_PM
bool
default y
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index a6985626300..79e54894529 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -1,41 +1,59 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20-rc1
+# Sun Dec 17 14:20:47 2006
#
CONFIG_MMU=y
-CONFIG_UID16=y
CONFIG_HIGHMEM=y
CONFIG_GENERIC_ISA_DMA=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_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_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -43,17 +61,36 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
-# General setup
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# General machine setup
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
# CONFIG_SMP is not set
+CONFIG_SPARC=y
CONFIG_SPARC32=y
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
@@ -61,73 +98,170 @@ CONFIG_SERIAL_CONSOLE=y
CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_SUN_PM=y
# CONFIG_SUN4 is not set
CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
+# CONFIG_PCI_DEBUG is not set
CONFIG_SUN_OPENPROMFS=m
+# CONFIG_SPARC_LED is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_MISC=m
CONFIG_SUNOS_EMUL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
#
-# Parallel port support
+# Networking
#
-# CONFIG_PARPORT is not set
+CONFIG_NET=y
#
-# Generic Driver Options
+# Networking options
#
-# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
#
-# Graphics support
+# DCCP Configuration (EXPERIMENTAL)
#
-# CONFIG_FB is not set
+# CONFIG_IP_DCCP is not set
#
-# Console display driver support
+# SCTP Configuration (EXPERIMENTAL)
#
-# CONFIG_MDA_CONSOLE is not set
-# CONFIG_PROM_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+CONFIG_SCTP_DBG_OBJCNT=y
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
#
-# Memory Technology Devices (MTD)
+# TIPC Configuration (EXPERIMENTAL)
#
-# CONFIG_MTD is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
#
-# Serial drivers
+# QoS and/or fair queueing
#
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_NET_SCHED is not set
#
-# Non-8250 serial port support
+# Network testing
#
-CONFIG_SERIAL_SUNCORE=y
-CONFIG_SERIAL_SUNZILOG=y
-CONFIG_SERIAL_SUNZILOG_CONSOLE=y
-CONFIG_SERIAL_SUNSU=y
-CONFIG_SERIAL_SUNSU_CONSOLE=y
-# CONFIG_SERIAL_SUNSAB is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
#
-# Misc Linux/SPARC drivers
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
-CONFIG_SUN_OPENPROMIO=m
-CONFIG_SUN_MOSTEK_RTC=m
-# CONFIG_SUN_BPP is not set
-# CONFIG_SUN_VIDEOPIX is not set
-# CONFIG_SUN_AURORA is not set
-# CONFIG_TADPOLE_TS102_UCTRL is not set
-# CONFIG_SUN_JSFLASH is not set
-CONFIG_APM_RTC_IS_GMT=y
-CONFIG_RTC=m
#
# Block devices
@@ -137,28 +271,37 @@ CONFIG_RTC=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=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
# 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_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
-# ATA/ATAPI/MFM/RLL support
+# Misc devices
#
-# CONFIG_IDE is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
#
-# ISDN subsystem
+# ATA/ATAPI/MFM/RLL support
#
-# CONFIG_ISDN is not set
+# CONFIG_IDE is not set
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
@@ -170,6 +313,7 @@ CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -177,57 +321,58 @@ CONFIG_CHR_DEV_SG=m
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
-# SCSI Transport Attributes
+# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=m
# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
+# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_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_STEX 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_QLOGICPTI=m
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_SUNESP=y
+# CONFIG_SCSI_SRP is not set
#
-# Fibre Channel support
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
#
-# CONFIG_FC4 is not set
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
@@ -235,85 +380,31 @@ CONFIG_SCSI_SUNESP=y
# CONFIG_MD is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
+# Fusion MPT device support
#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-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=y
-CONFIG_INET_ESP=y
-CONFIG_INET_IPCOMP=y
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
#
-# SCTP Configuration (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
#
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-CONFIG_SCTP_DBG_OBJCNT=y
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-# 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
+# CONFIG_IEEE1394 is not set
#
-# QoS and/or fair queueing
+# I2O device support
#
-# CONFIG_NET_SCHED is not set
+# CONFIG_I2O is not set
#
-# Network testing
+# Network device support
#
-CONFIG_NET_PKTGEN=m
-# 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 is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
#
# ARCnet devices
@@ -321,6 +412,11 @@ CONFIG_TUN=m
# CONFIG_ARCNET is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -330,6 +426,7 @@ CONFIG_HAPPYMEAL=m
CONFIG_SUNBMAC=m
CONFIG_SUNQE=m
# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
#
@@ -350,14 +447,22 @@ CONFIG_SUNQE=m
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
#
+# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -380,17 +485,24 @@ CONFIG_SUNQE=m
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
-# Unix98 PTY support
+# ISDN subsystem
#
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
#
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
@@ -405,17 +517,6 @@ CONFIG_INPUT_EVDEV=m
CONFIG_INPUT_EVBUG=m
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=m
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=m
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -424,6 +525,7 @@ CONFIG_KEYBOARD_SUNKBD=m
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=m
CONFIG_MOUSE_SERIAL=m
@@ -433,29 +535,239 @@ CONFIG_MOUSE_SERIAL=m
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=m
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SUNCORE=y
+CONFIG_SERIAL_SUNZILOG=y
+CONFIG_SERIAL_SUNZILOG_CONSOLE=y
+CONFIG_SERIAL_SUNSU=y
+CONFIG_SERIAL_SUNSU_CONSOLE=y
+# CONFIG_SERIAL_SUNSAB is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+CONFIG_RTC=m
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_PROM_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Virtualization
+#
+
+#
+# Misc Linux/SPARC drivers
+#
+CONFIG_SUN_OPENPROMIO=m
+CONFIG_SUN_MOSTEK_RTC=m
+# CONFIG_SUN_BPP is not set
+# CONFIG_SUN_VIDEOPIX is not set
+# CONFIG_TADPOLE_TS102_UCTRL is not set
+# CONFIG_SUN_JSFLASH is not set
+
+#
+# Unix98 PTY support
+#
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
# File systems
#
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+# CONFIG_EXT4DEV_FS is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_XFS_FS=m
-CONFIG_XFS_RT=y
CONFIG_XFS_QUOTA=y
CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -468,7 +780,8 @@ CONFIG_ISO9660_FS=m
#
# 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
#
@@ -476,13 +789,12 @@ CONFIG_ISO9660_FS=m
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -512,17 +824,23 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=m
CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
CONFIG_AFS_FS=m
CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
#
# Partition Types
@@ -559,6 +877,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
@@ -575,70 +894,104 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
+# Distributed Lock Manager
#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_DLM is not set
#
-# Watchdog Cards
+# Instrumentation Support
#
-# CONFIG_WATCHDOG is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_TEST is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 54d51b40460..987ec6782f9 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -153,7 +153,7 @@ void __iomem *of_ioremap(struct resource *res, unsigned long offset,
}
EXPORT_SYMBOL(of_ioremap);
-void of_iounmap(void __iomem *base, unsigned long size)
+void of_iounmap(struct resource *res, void __iomem *base, unsigned long size)
{
iounmap(base);
}
@@ -317,9 +317,8 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0)
goto err_nopages;
- if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+ if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
goto err_nomem;
- memset((char*)res, 0, sizeof(struct resource));
if (allocate_resource(&_sparc_dvma, res, len_total,
_sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
@@ -589,12 +588,11 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
return NULL;
}
- if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+ if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
free_pages(va, order);
printk("pci_alloc_consistent: no core\n");
return NULL;
}
- memset((char*)res, 0, sizeof(struct resource));
if (allocate_resource(&_sparc_dvma, res, len_total,
_sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
@@ -728,7 +726,8 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
/* IIep is write-through, not flushing. */
for (n = 0; n < nents; n++) {
BUG_ON(page_address(sg->page) == NULL);
- sg->dvma_address = virt_to_phys(page_address(sg->page));
+ sg->dvma_address =
+ virt_to_phys(page_address(sg->page)) + sg->offset;
sg->dvma_length = sg->length;
sg++;
}
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index c8cb211b907..5b4841d067c 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -425,7 +425,7 @@ int request_fast_irq(unsigned int irq,
}
if (action == NULL)
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ action = kmalloc(sizeof(struct irqaction),
GFP_ATOMIC);
if (!action) {
@@ -528,7 +528,7 @@ int request_irq(unsigned int irq,
}
if (action == NULL)
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ action = kmalloc(sizeof(struct irqaction),
GFP_ATOMIC);
if (!action) {
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 46200c43ffb..dab6169e31c 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -793,10 +793,9 @@ struct of_device* of_platform_device_create(struct device_node *np,
{
struct of_device *dev;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
- memset(dev, 0, sizeof(*dev));
dev->dev.parent = parent;
dev->dev.bus = bus;
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 89a28cc018c..113bd48a89b 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -54,6 +54,7 @@ void (*pm_idle)(void);
* handler when auxio is not present-- unused for now...
*/
void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
/*
* sysctl - toggle power-off restriction for serial console
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 1baf13ed5c3..003f8eed32f 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -289,7 +289,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
if (request == PTRACE_TRACEME) {
ret = ptrace_traceme();
- pt_succ_return(regs, 0);
+ if (ret < 0)
+ pt_error_return(regs, -ret);
+ else
+ pt_succ_return(regs, 0);
goto out;
}
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 276f22881d0..6b5f26b0fb7 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -292,8 +292,8 @@ int setup_profiling_timer(unsigned int multiplier)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
- extern void smp4m_boot_cpus(void);
- extern void smp4d_boot_cpus(void);
+ extern void __init smp4m_boot_cpus(void);
+ extern void __init smp4d_boot_cpus(void);
int i, cpuid, extra;
printk("Entering SMP Mode...\n");
@@ -375,8 +375,8 @@ void __init smp_prepare_boot_cpu(void)
int __cpuinit __cpu_up(unsigned int cpu)
{
- extern int smp4m_boot_one_cpu(int);
- extern int smp4d_boot_one_cpu(int);
+ extern int __cpuinit smp4m_boot_one_cpu(int);
+ extern int __cpuinit smp4d_boot_one_cpu(int);
int ret=0;
switch(sparc_cpu_model) {
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 33dadd9f287..d8e008a04e2 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -83,9 +83,6 @@ extern int __divdi3(int, int);
/* Private functions with odd calling conventions. */
extern void ___atomic24_add(void);
extern void ___atomic24_sub(void);
-extern void ___set_bit(void);
-extern void ___clear_bit(void);
-extern void ___change_bit(void);
extern void ___rw_read_enter(void);
extern void ___rw_read_try(void);
extern void ___rw_read_exit(void);
@@ -125,11 +122,6 @@ EXPORT_SYMBOL(pfn_base);
EXPORT_SYMBOL(___atomic24_add);
EXPORT_SYMBOL(___atomic24_sub);
-/* Bit operations. */
-EXPORT_SYMBOL(___set_bit);
-EXPORT_SYMBOL(___clear_bit);
-EXPORT_SYMBOL(___change_bit);
-
/* Per-CPU information table */
EXPORT_PER_CPU_SYMBOL(__cpu_data);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index d4f9da8170c..0e27e226e0e 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -327,7 +327,7 @@ int sun4d_request_irq(unsigned int irq,
}
if (action == NULL)
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
+ action = kmalloc(sizeof(struct irqaction),
GFP_ATOMIC);
if (!action) {
@@ -545,8 +545,11 @@ void __init sun4d_init_sbi_irq(void)
nsbi = 0;
for_each_sbus(sbus)
nsbi++;
- sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
- memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
+ sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
+ if (!sbus_actions) {
+ prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n");
+ prom_halt();
+ }
for_each_sbus(sbus) {
#ifdef CONFIG_SMP
extern unsigned char boot_cpu_id;
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index c80ea61e8ba..c69de5d4863 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -164,7 +164,7 @@ void __init smp4d_boot_cpus(void)
local_flush_cache_all();
}
-int smp4d_boot_one_cpu(int i)
+int __cpuinit smp4d_boot_one_cpu(int i)
{
extern unsigned long sun4d_cpu_startup;
unsigned long *entry = &sun4d_cpu_startup;
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 6f3ac548ee6..0bf8c165fc9 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -94,8 +94,8 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
* SunOS is so stupid some times... hmph!
*/
if (file) {
- if (imajor(file->f_dentry->d_inode) == MEM_MAJOR &&
- iminor(file->f_dentry->d_inode) == 5) {
+ if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR &&
+ iminor(file->f_path.dentry->d_inode) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
file = NULL;
@@ -655,7 +655,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
if (!file)
goto out;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
socket = SOCKET_I(inode);
local.sin_family = AF_INET;
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 6c7aa51b590..2fcce000d87 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -78,7 +78,6 @@ unsigned long profile_pc(struct pt_regs *regs)
extern char __copy_user_begin[], __copy_user_end[];
extern char __atomic_begin[], __atomic_end[];
extern char __bzero_begin[], __bzero_end[];
- extern char __bitops_begin[], __bitops_end[];
unsigned long pc = regs->pc;
@@ -88,9 +87,7 @@ unsigned long profile_pc(struct pt_regs *regs)
(pc >= (unsigned long) __atomic_begin &&
pc < (unsigned long) __atomic_end) ||
(pc >= (unsigned long) __bzero_begin &&
- pc < (unsigned long) __bzero_end) ||
- (pc >= (unsigned long) __bitops_begin &&
- pc < (unsigned long) __bitops_end))
+ pc < (unsigned long) __bzero_end))
pc = regs->u_regs[UREG_RETPC];
return pc;
}
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 5db7e1d8538..9ddc5b9ce3b 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -7,7 +7,7 @@ EXTRA_AFLAGS := -ansi -DST_DIV0=0x02
lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
- copy_user.o locks.o atomic.o atomic32.o bitops.o \
+ copy_user.o locks.o atomic.o \
lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
-obj-y += iomap.o
+obj-y += iomap.o atomic32.o
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index de84f8534ba..53ddcd9d1e6 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -76,3 +76,42 @@ void atomic_set(atomic_t *v, int i)
spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
}
EXPORT_SYMBOL(atomic_set);
+
+unsigned long ___set_bit(unsigned long *addr, unsigned long mask)
+{
+ unsigned long old, flags;
+
+ spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ old = *addr;
+ *addr = old | mask;
+ spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+
+ return old & mask;
+}
+EXPORT_SYMBOL(___set_bit);
+
+unsigned long ___clear_bit(unsigned long *addr, unsigned long mask)
+{
+ unsigned long old, flags;
+
+ spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ old = *addr;
+ *addr = old & ~mask;
+ spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+
+ return old & mask;
+}
+EXPORT_SYMBOL(___clear_bit);
+
+unsigned long ___change_bit(unsigned long *addr, unsigned long mask)
+{
+ unsigned long old, flags;
+
+ spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ old = *addr;
+ *addr = old ^ mask;
+ spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+
+ return old & mask;
+}
+EXPORT_SYMBOL(___change_bit);
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S
deleted file mode 100644
index cb7fb66a40c..00000000000
--- a/arch/sparc/lib/bitops.S
+++ /dev/null
@@ -1,109 +0,0 @@
-/* bitops.S: Low level assembler bit operations.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/ptrace.h>
-#include <asm/psr.h>
-
- .text
- .align 4
-
- .globl __bitops_begin
-__bitops_begin:
-
- /* Take bits in %g2 and set them in word at %g1,
- * return whether bits were set in original value
- * in %g2. %g4 holds value to restore into %o7
- * in delay slot of jmpl return, %g3 + %g5 + %g7 can be
- * used as temporaries and thus is considered clobbered
- * by all callers.
- */
- .globl ___set_bit
-___set_bit:
- rd %psr, %g3
- nop; nop; nop;
- or %g3, PSR_PIL, %g5
- wr %g5, 0x0, %psr
- nop; nop; nop
-#ifdef CONFIG_SMP
- set bitops_spinlock, %g5
-2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
- orcc %g7, 0x0, %g0 ! Did we get it?
- bne 2b ! Nope...
-#endif
- ld [%g1], %g7
- or %g7, %g2, %g5
- and %g7, %g2, %g2
-#ifdef CONFIG_SMP
- st %g5, [%g1]
- set bitops_spinlock, %g5
- stb %g0, [%g5]
-#else
- st %g5, [%g1]
-#endif
- wr %g3, 0x0, %psr
- nop; nop; nop
- jmpl %o7, %g0
- mov %g4, %o7
-
- /* Same as above, but clears the bits from %g2 instead. */
- .globl ___clear_bit
-___clear_bit:
- rd %psr, %g3
- nop; nop; nop
- or %g3, PSR_PIL, %g5
- wr %g5, 0x0, %psr
- nop; nop; nop
-#ifdef CONFIG_SMP
- set bitops_spinlock, %g5
-2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
- orcc %g7, 0x0, %g0 ! Did we get it?
- bne 2b ! Nope...
-#endif
- ld [%g1], %g7
- andn %g7, %g2, %g5
- and %g7, %g2, %g2
-#ifdef CONFIG_SMP
- st %g5, [%g1]
- set bitops_spinlock, %g5
- stb %g0, [%g5]
-#else
- st %g5, [%g1]
-#endif
- wr %g3, 0x0, %psr
- nop; nop; nop
- jmpl %o7, %g0
- mov %g4, %o7
-
- /* Same thing again, but this time toggles the bits from %g2. */
- .globl ___change_bit
-___change_bit:
- rd %psr, %g3
- nop; nop; nop
- or %g3, PSR_PIL, %g5
- wr %g5, 0x0, %psr
- nop; nop; nop
-#ifdef CONFIG_SMP
- set bitops_spinlock, %g5
-2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
- orcc %g7, 0x0, %g0 ! Did we get it?
- bne 2b ! Nope...
-#endif
- ld [%g1], %g7
- xor %g7, %g2, %g5
- and %g7, %g2, %g2
-#ifdef CONFIG_SMP
- st %g5, [%g1]
- set bitops_spinlock, %g5
- stb %g0, [%g5]
-#else
- st %g5, [%g1]
-#endif
- wr %g3, 0x0, %psr
- nop; nop; nop
- jmpl %o7, %g0
- mov %g4, %o7
-
- .globl __bitops_end
-__bitops_end:
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index 2bb1309003d..4ccda77d08d 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -22,6 +22,7 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/dma.h>
+#include <asm/oplib.h>
/* #define IOUNIT_DEBUG */
#ifdef IOUNIT_DEBUG
@@ -41,9 +42,12 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
struct linux_prom_registers iommu_promregs[PROMREG_MAX];
struct resource r;
- iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
+ iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
+ if (!iounit) {
+ prom_printf("SUN4D: Cannot alloc iounit, halting.\n");
+ prom_halt();
+ }
- memset(iounit, 0, sizeof(*iounit));
iounit->limit[0] = IOUNIT_BMAP1_START;
iounit->limit[1] = IOUNIT_BMAP2_START;
iounit->limit[2] = IOUNIT_BMAPM_START;
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index b627f8dbcaa..d41f66ac7ff 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -26,6 +26,14 @@ config MMU
bool
default y
+config STACKTRACE_SUPPORT
+ bool
+ default y
+
+config LOCKDEP_SUPPORT
+ bool
+ default y
+
config TIME_INTERPOLATION
bool
default y
@@ -34,6 +42,14 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
config AUDIT_ARCH
bool
default y
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
index afe0a7720a2..1f130f3b6c2 100644
--- a/arch/sparc64/Kconfig.debug
+++ b/arch/sparc64/Kconfig.debug
@@ -1,5 +1,9 @@
menu "Kernel hacking"
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
source "lib/Kconfig.debug"
config DEBUG_STACK_USAGE
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 2f4612fa81f..5a9e68b13e6 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,24 +1,29 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Tue Oct 17 19:29:20 2006
+# Linux kernel version: 2.6.20-rc2
+# Thu Dec 28 15:09:49 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
CONFIG_64BIT=y
CONFIG_MMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
CONFIG_TIME_INTERPOLATION=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_AUDIT_ARCH=y
CONFIG_SPARC64_PAGE_SIZE_8KB=y
# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
# CONFIG_SPARC64_PAGE_SIZE_512KB is not set
# CONFIG_SPARC64_PAGE_SIZE_4MB is not set
CONFIG_SECCOMP=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -42,13 +47,14 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -203,6 +209,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -219,7 +226,6 @@ CONFIG_INET6_XFRM_MODE_BEET=m
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=m
CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -238,6 +244,8 @@ CONFIG_IP_DCCP_CCID2=m
# CONFIG_IP_DCCP_CCID2_DEBUG is not set
CONFIG_IP_DCCP_CCID3=m
CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
#
# DCCP Kernel Hacking
@@ -326,7 +334,7 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_UB=m
+# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
@@ -405,6 +413,7 @@ CONFIG_IDEDMA_AUTO=y
#
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y
@@ -425,6 +434,7 @@ CONFIG_CHR_DEV_SG=m
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -468,6 +478,7 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SUNESP is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -598,6 +609,7 @@ CONFIG_BNX2=m
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -724,10 +736,6 @@ 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
@@ -832,6 +840,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -842,6 +851,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -954,7 +964,6 @@ CONFIG_SND_VERBOSE_PROCFS=y
#
CONFIG_SND_MPU401_UART=m
CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_AC97_BUS=m
CONFIG_SND_DUMMY=m
CONFIG_SND_VIRMIDI=m
CONFIG_SND_MTPAV=m
@@ -1037,6 +1046,12 @@ CONFIG_SND_SUN_CS4231=m
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
#
# USB support
@@ -1053,6 +1068,7 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1082,14 +1098,25 @@ CONFIG_USB_UHCI_HCD=m
#
# may also be needed; see USB_STORAGE Help for more information
#
-# CONFIG_USB_STORAGE is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
CONFIG_USB_HIDDEV=y
@@ -1119,6 +1146,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
# CONFIG_USB_MON is not set
@@ -1208,6 +1236,10 @@ CONFIG_USB_HIDDEV=y
#
#
+# Virtualization
+#
+
+#
# Misc Linux/SPARC drivers
#
CONFIG_SUN_OPENPROMIO=m
@@ -1364,6 +1396,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Instrumentation Support
#
CONFIG_PROFILING=y
@@ -1373,10 +1410,13 @@ CONFIG_KPROBES=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1387,17 +1427,16 @@ CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
-# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -1420,8 +1459,9 @@ CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
@@ -1430,8 +1470,10 @@ CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
@@ -1456,6 +1498,7 @@ CONFIG_CRYPTO_TEST=m
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC32=y
@@ -1463,3 +1506,4 @@ CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index e1eabebaed3..eff0c01d357 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -14,6 +14,7 @@ obj-y := process.o setup.o cpu.o idprom.o \
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
visemul.o prom.o of_device.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
pci_psycho.o pci_sabre.o pci_schizo.o \
pci_sun4v.o pci_sun4v_asm.o
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index d7caa60a007..f205fc7cbcd 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -209,7 +209,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
- bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
return -ENOEXEC;
}
@@ -349,7 +349,7 @@ static int load_aout32_library(struct file *file)
int retval;
struct exec ex;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
retval = -ENOEXEC;
error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 259f37e516f..9699abeb990 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -341,7 +341,7 @@ static void fetch_decode_regs(struct mctrl_info *mp)
static int init_one_mctrl(struct device_node *dp)
{
- struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+ struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
int portid = of_getintprop_default(dp, "portid", -1);
struct linux_prom64_registers *regs;
void *pval;
@@ -349,7 +349,6 @@ static int init_one_mctrl(struct device_node *dp)
if (!mp)
return -1;
- memset(mp, 0, sizeof(*mp));
if (portid == -1)
goto fail;
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 6f28bec0a9b..c15a3edcb82 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -597,7 +597,12 @@ __spitfire_cee_trap_continue:
1: ba,pt %xcc, etrap_irq
rd %pc, %g7
-2: mov %l4, %o1
+2:
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
+ mov %l4, %o1
mov %l5, %o2
call spitfire_access_error
add %sp, PTREGS_OFF, %o0
@@ -824,6 +829,10 @@ do_cheetah_plus_data_parity:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
mov 0x0, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
@@ -855,6 +864,10 @@ do_cheetah_plus_insn_parity:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
mov 0x1, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
@@ -1183,6 +1196,10 @@ c_fast_ecc:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
mov %l4, %o1
mov %l5, %o2
call cheetah_fecc_handler
@@ -1211,6 +1228,10 @@ c_cee:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
mov %l4, %o1
mov %l5, %o2
call cheetah_cee_handler
@@ -1239,6 +1260,10 @@ c_deferred:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
mov %l4, %o1
mov %l5, %o2
call cheetah_deferred_handler
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index c8e9dc9d68a..baea10a9819 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -78,11 +78,7 @@ sparc_ramdisk_image64:
/* PROM cif handler code address is in %o4. */
sparc64_boot:
-1: rd %pc, %g7
- set 1b, %g1
- cmp %g1, %g7
- be,pn %xcc, sparc64_boot_after_remap
- mov %o4, %l7
+ mov %o4, %l7
/* We need to remap the kernel. Use position independant
* code to remap us to KERNBASE.
@@ -295,7 +291,6 @@ is_sun4v:
add %sp, (192 + 128), %sp
-sparc64_boot_after_remap:
sethi %hi(prom_root_compatible), %g1
or %g1, %lo(prom_root_compatible), %g1
sethi %hi(prom_sun4v_name), %g7
@@ -489,6 +484,14 @@ tlb_fixup_done:
call __bzero
sub %o1, %o0, %o1
+#ifdef CONFIG_LOCKDEP
+ /* We have this call this super early, as even prom_init can grab
+ * spinlocks and thus call into the lockdep code.
+ */
+ call lockdep_init
+ nop
+#endif
+
mov %l6, %o1 ! OpenPROM stack
call prom_init
mov %l7, %o0 ! OpenPROM cif handler
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index d64b1ea848d..c3d068c7a41 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -372,14 +372,14 @@ static void run_pre_handler(unsigned int virt_irq)
}
}
-static struct hw_interrupt_type sun4u_irq = {
+static struct irq_chip sun4u_irq = {
.typename = "sun4u",
.enable = sun4u_irq_enable,
.disable = sun4u_irq_disable,
.end = sun4u_irq_end,
};
-static struct hw_interrupt_type sun4u_irq_ack = {
+static struct irq_chip sun4u_irq_ack = {
.typename = "sun4u+ack",
.enable = sun4u_irq_enable,
.disable = sun4u_irq_disable,
@@ -387,14 +387,14 @@ static struct hw_interrupt_type sun4u_irq_ack = {
.end = sun4u_irq_end,
};
-static struct hw_interrupt_type sun4v_irq = {
+static struct irq_chip sun4v_irq = {
.typename = "sun4v",
.enable = sun4v_irq_enable,
.disable = sun4v_irq_disable,
.end = sun4v_irq_end,
};
-static struct hw_interrupt_type sun4v_irq_ack = {
+static struct irq_chip sun4v_irq_ack = {
.typename = "sun4v+ack",
.enable = sun4v_irq_enable,
.disable = sun4v_irq_disable,
@@ -493,22 +493,6 @@ out:
return bucket->virt_irq;
}
-void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq)
-{
- struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
- unsigned long pstate;
- unsigned int *ent;
-
- __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
- __asm__ __volatile__("wrpr %0, %1, %%pstate"
- : : "r" (pstate), "i" (PSTATE_IE));
- ent = irq_work(smp_processor_id());
- bucket->irq_chain = *ent;
- *ent = __irq(bucket);
- set_softint(1 << PIL_DEVICE_IRQ);
- __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
-}
-
void ack_bad_irq(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
index f028e68b23f..98721a8f861 100644
--- a/arch/sparc64/kernel/isa.c
+++ b/arch/sparc64/kernel/isa.c
@@ -22,14 +22,15 @@ static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
printk(" [%s", isa_dev->prom_node->name);
}
-static struct linux_prom_registers * __init
-isa_dev_get_resource(struct sparc_isa_device *isa_dev)
+static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev)
{
struct linux_prom_registers *pregs;
unsigned long base, len;
int prop_len;
pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
+ if (!pregs)
+ return;
/* Only the first one is interesting. */
len = pregs[0].reg_size;
@@ -44,12 +45,9 @@ isa_dev_get_resource(struct sparc_isa_device *isa_dev)
request_resource(&isa_dev->bus->parent->io_space,
&isa_dev->resource);
-
- return pregs;
}
-static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
- struct linux_prom_registers *pregs)
+static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev)
{
struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
@@ -69,17 +67,14 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
printk(" ->");
while (dp) {
- struct linux_prom_registers *regs;
struct sparc_isa_device *isa_dev;
- isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+ isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
if (!isa_dev) {
fatal_err("cannot allocate child isa_dev");
prom_halt();
}
- memset(isa_dev, 0, sizeof(*isa_dev));
-
/* Link it in to parent. */
isa_dev->next = parent_isa_dev->child;
parent_isa_dev->child = isa_dev;
@@ -87,8 +82,8 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
isa_dev->bus = parent_isa_dev->bus;
isa_dev->prom_node = dp;
- regs = isa_dev_get_resource(isa_dev);
- isa_dev_get_irq(isa_dev, regs);
+ isa_dev_get_resource(isa_dev);
+ isa_dev_get_irq(isa_dev);
report_dev(isa_dev, 1);
@@ -101,17 +96,14 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
struct device_node *dp = isa_br->prom_node->child;
while (dp) {
- struct linux_prom_registers *regs;
struct sparc_isa_device *isa_dev;
- isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+ isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
if (!isa_dev) {
printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
return;
}
- memset(isa_dev, 0, sizeof(*isa_dev));
-
isa_dev->ofdev.node = dp;
isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
isa_dev->ofdev.dev.bus = &isa_bus_type;
@@ -141,8 +133,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
isa_dev->bus = isa_br;
isa_dev->prom_node = dp;
- regs = isa_dev_get_resource(isa_dev);
- isa_dev_get_irq(isa_dev, regs);
+ isa_dev_get_resource(isa_dev);
+ isa_dev_get_irq(isa_dev);
report_dev(isa_dev, 0);
@@ -180,14 +172,12 @@ void __init isa_init(void)
pbm = pdev_cookie->pbm;
dp = pdev_cookie->prom_node;
- isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
+ isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL);
if (!isa_br) {
printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
return;
}
- memset(isa_br, 0, sizeof(*isa_br));
-
isa_br->ofdev.node = dp;
isa_br->ofdev.dev.parent = &pdev->dev;
isa_br->ofdev.dev.bus = &isa_bus_type;
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 8e75ed762fd..ae221f0d4a6 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -45,7 +45,11 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
p->ainsn.insn[0] = *p->addr;
+ flushi(&p->ainsn.insn[0]);
+
p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
+ flushi(&p->ainsn.insn[1]);
+
p->opcode = *p->addr;
return 0;
}
@@ -185,16 +189,19 @@ no_kprobe:
/* If INSN is a relative control transfer instruction,
* return the corrected branch destination value.
*
- * The original INSN location was REAL_PC, it actually
- * executed at PC and produced destination address NPC.
+ * regs->tpc and regs->tnpc still hold the values of the
+ * program counters at the time of trap due to the execution
+ * of the BREAKPOINT_INSTRUCTION_2 at p->ainsn.insn[1]
+ *
*/
-static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
- unsigned long pc,
- unsigned long npc)
+static unsigned long __kprobes relbranch_fixup(u32 insn, struct kprobe *p,
+ struct pt_regs *regs)
{
+ unsigned long real_pc = (unsigned long) p->addr;
+
/* Branch not taken, no mods necessary. */
- if (npc == pc + 0x4UL)
- return real_pc + 0x4UL;
+ if (regs->tnpc == regs->tpc + 0x4UL)
+ return real_pc + 0x8UL;
/* The three cases are call, branch w/prediction,
* and traditional branch.
@@ -202,14 +209,21 @@ static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
if ((insn & 0xc0000000) == 0x40000000 ||
(insn & 0xc1c00000) == 0x00400000 ||
(insn & 0xc1c00000) == 0x00800000) {
+ unsigned long ainsn_addr;
+
+ ainsn_addr = (unsigned long) &p->ainsn.insn[0];
+
/* The instruction did all the work for us
* already, just apply the offset to the correct
* instruction location.
*/
- return (real_pc + (npc - pc));
+ return (real_pc + (regs->tnpc - ainsn_addr));
}
- return real_pc + 0x4UL;
+ /* It is jmpl or some other absolute PC modification instruction,
+ * leave NPC as-is.
+ */
+ return regs->tnpc;
}
/* If INSN is an instruction which writes it's PC location
@@ -220,12 +234,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
{
unsigned long *slot = NULL;
- /* Simplest cast is call, which always uses %o7 */
+ /* Simplest case is 'call', which always uses %o7 */
if ((insn & 0xc0000000) == 0x40000000) {
slot = &regs->u_regs[UREG_I7];
}
- /* Jmpl encodes the register inside of the opcode */
+ /* 'jmpl' encodes the register inside of the opcode */
if ((insn & 0xc1f80000) == 0x81c00000) {
unsigned long rd = ((insn >> 25) & 0x1f);
@@ -247,11 +261,11 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
/*
* Called after single-stepping. p->addr is the address of the
- * instruction whose first byte has been replaced by the breakpoint
+ * instruction which has been replaced by the breakpoint
* instruction. To avoid the SMP problems that can occur when we
* temporarily put back the original opcode to single-step, we
* single-stepped a copy of the instruction. The address of this
- * copy is p->ainsn.insn.
+ * copy is &p->ainsn.insn[0].
*
* This function prepares to return from the post-single-step
* breakpoint trap.
@@ -261,11 +275,11 @@ static void __kprobes resume_execution(struct kprobe *p,
{
u32 insn = p->ainsn.insn[0];
+ regs->tnpc = relbranch_fixup(insn, p, regs);
+
+ /* This assignment must occur after relbranch_fixup() */
regs->tpc = kcb->kprobe_orig_tnpc;
- regs->tnpc = relbranch_fixup(insn,
- (unsigned long) p->addr,
- (unsigned long) &p->ainsn.insn[0],
- regs->tnpc);
+
retpc_fixup(regs, insn, (unsigned long) p->addr);
regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
@@ -430,17 +444,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
struct jprobe *jp = container_of(p, struct jprobe, kp);
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- kcb->jprobe_saved_regs_location = regs;
memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs));
- /* Save a whole stack frame, this gets arguments
- * pushed onto the stack after using up all the
- * arg registers.
- */
- memcpy(&(kcb->jprobe_saved_stack),
- (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
- sizeof(kcb->jprobe_saved_stack));
-
regs->tpc = (unsigned long) jp->entry;
regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
regs->tstate |= TSTATE_PIL;
@@ -450,10 +455,19 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
void __kprobes jprobe_return(void)
{
- __asm__ __volatile__(
- ".globl jprobe_return_trap_instruction\n"
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ register unsigned long orig_fp asm("g1");
+
+ orig_fp = kcb->jprobe_saved_regs.u_regs[UREG_FP];
+ __asm__ __volatile__("\n"
+"1: cmp %%sp, %0\n\t"
+ "blu,a,pt %%xcc, 1b\n\t"
+ " restore\n\t"
+ ".globl jprobe_return_trap_instruction\n"
"jprobe_return_trap_instruction:\n\t"
- "ta 0x70");
+ "ta 0x70"
+ : /* no outputs */
+ : "r" (orig_fp));
}
extern void jprobe_return_trap_instruction(void);
@@ -466,26 +480,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
if (addr == (u32 *) jprobe_return_trap_instruction) {
- if (kcb->jprobe_saved_regs_location != regs) {
- printk("JPROBE: Current regs (%p) does not match "
- "saved regs (%p).\n",
- regs, kcb->jprobe_saved_regs_location);
- printk("JPROBE: Saved registers\n");
- __show_regs(kcb->jprobe_saved_regs_location);
- printk("JPROBE: Current registers\n");
- __show_regs(regs);
- BUG();
- }
- /* Restore old register state. Do pt_regs
- * first so that UREG_FP is the original one for
- * the stack frame restore.
- */
memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs));
-
- memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
- &(kcb->jprobe_saved_stack),
- sizeof(kcb->jprobe_saved_stack));
-
preempt_enable_no_resched();
return 1;
}
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 8cc14fc6b6f..b0f3e0082a0 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -144,9 +144,12 @@ void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned lo
}
EXPORT_SYMBOL(of_ioremap);
-void of_iounmap(void __iomem *base, unsigned long size)
+void of_iounmap(struct resource *res, void __iomem *base, unsigned long size)
{
- release_region((unsigned long) base, size);
+ if (res->flags & IORESOURCE_MEM)
+ release_mem_region((unsigned long) base, size);
+ else
+ release_region((unsigned long) base, size);
}
EXPORT_SYMBOL(of_iounmap);
@@ -1007,10 +1010,9 @@ struct of_device* of_platform_device_create(struct device_node *np,
{
struct of_device *dev;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
- memset(dev, 0, sizeof(*dev));
dev->dev.parent = parent;
dev->dev.bus = bus;
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 03ad4c06758..6b04794b7a9 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -798,7 +798,7 @@ static struct pci_ops pci_sun4v_ops = {
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
- struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+ struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("%s: Critical allocation failure.\n", pbm->name);
@@ -806,7 +806,6 @@ static void pbm_scan_bus(struct pci_controller_info *p,
}
/* All we care about is the PBM. */
- memset(cookie, 0, sizeof(*cookie));
cookie->pbm = pbm;
pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm);
@@ -1048,12 +1047,11 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
/* Allocate and initialize the free area map. */
sz = num_tsb_entries / 8;
sz = (sz + 7UL) & ~7UL;
- iommu->arena.map = kmalloc(sz, GFP_KERNEL);
+ iommu->arena.map = kzalloc(sz, GFP_KERNEL);
if (!iommu->arena.map) {
prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
prom_halt();
}
- memset(iommu->arena.map, 0, sz);
iommu->arena.limit = num_tsb_entries;
sz = probe_existing_entries(pbm, iommu);
@@ -1164,24 +1162,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
per_cpu(pci_iommu_batch, i).pglist = (u64 *) page;
}
- p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+ p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p)
goto fatal_memory_error;
- memset(p, 0, sizeof(*p));
-
- iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+ iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu)
goto fatal_memory_error;
- memset(iommu, 0, sizeof(*iommu));
p->pbm_A.iommu = iommu;
- iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+ iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu)
goto fatal_memory_error;
- memset(iommu, 0, sizeof(*iommu));
p->pbm_B.iommu = iommu;
p->next = pci_controller_root;
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index d31975e6d6f..81111a12f0a 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -202,7 +202,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
#endif
if (request == PTRACE_TRACEME) {
ret = ptrace_traceme();
- pt_succ_return(regs, 0);
+ if (ret < 0)
+ pt_error_return(regs, -ret);
+ else
+ pt_succ_return(regs, 0);
goto out;
}
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 3522cd66f3b..079d18a11d2 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -165,14 +165,26 @@ rtrap:
__handle_softirq_continue:
rtrap_xcall:
sethi %hi(0xf << 20), %l4
- andcc %l1, TSTATE_PRIV, %l3
and %l1, %l4, %l4
+ andn %l1, %l4, %l1
+ srl %l4, 20, %l4
+#ifdef CONFIG_TRACE_IRQFLAGS
+ brnz,pn %l4, rtrap_no_irq_enable
+ nop
+ call trace_hardirqs_on
+ nop
+ wrpr %l4, %pil
+rtrap_no_irq_enable:
+#endif
+ andcc %l1, TSTATE_PRIV, %l3
bne,pn %icc, to_kernel
- andn %l1, %l4, %l1
+ nop
/* We must hold IRQs off and atomically test schedule+signal
* state, then hold them off all the way back to userspace.
- * If we are returning to kernel, none of this matters.
+ * If we are returning to kernel, none of this matters. Note
+ * that we are disabling interrupts via PSTATE_IE, not using
+ * %pil.
*
* If we do not do this, there is a window where we would do
* the tests, later the signal/resched event arrives but we do
@@ -256,7 +268,6 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
ld [%sp + PTREGS_OFF + PT_V9_Y], %o3
wr %o3, %g0, %y
- srl %l4, 20, %l4
wrpr %l4, 0x0, %pil
wrpr %g0, 0x1, %tl
wrpr %l1, %g0, %tstate
@@ -374,8 +385,8 @@ to_kernel:
ldx [%g6 + TI_FLAGS], %l5
andcc %l5, _TIF_NEED_RESCHED, %g0
be,pt %xcc, kern_fpucheck
- srl %l4, 20, %l5
- cmp %l5, 0
+ nop
+ cmp %l4, 0
bne,pn %xcc, kern_fpucheck
sethi %hi(PREEMPT_ACTIVE), %l6
stw %l6, [%g6 + TI_PRE_COUNT]
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index cc09d826641..fc99f7b8012 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1388,7 +1388,7 @@ void __devinit smp_prepare_boot_cpu(void)
{
}
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
{
int ret = smp_boot_one_cpu(cpu);
@@ -1447,11 +1447,8 @@ void __init setup_per_cpu_areas(void)
char *ptr;
/* Copy section for each CPU (we discard the original) */
- goal = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
-#ifdef CONFIG_MODULES
- if (goal < PERCPU_ENOUGH_ROOM)
- goal = PERCPU_ENOUGH_ROOM;
-#endif
+ goal = PERCPU_ENOUGH_ROOM;
+
__per_cpu_shift = 0;
for (size = 1UL; size < goal; size <<= 1UL)
__per_cpu_shift++;
diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
new file mode 100644
index 00000000000..c4d15f2762b
--- /dev/null
+++ b/arch/sparc64/kernel/stacktrace.c
@@ -0,0 +1,41 @@
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <asm/ptrace.h>
+
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+ unsigned long ksp, fp, thread_base;
+ struct thread_info *tp;
+
+ if (!task)
+ task = current;
+ tp = task_thread_info(task);
+ if (task == current) {
+ flushw_all();
+ __asm__ __volatile__(
+ "mov %%fp, %0"
+ : "=r" (ksp)
+ );
+ } else
+ ksp = tp->ksp;
+
+ fp = ksp + STACK_BIAS;
+ thread_base = (unsigned long) tp;
+ do {
+ struct reg_window *rw;
+
+ /* Bogus frame pointer? */
+ if (fp < (thread_base + sizeof(struct thread_info)) ||
+ fp >= (thread_base + THREAD_SIZE))
+ break;
+
+ rw = (struct reg_window *) fp;
+ if (trace->skip > 0)
+ trace->skip--;
+ else
+ trace->entries[trace->nr_entries++] = rw->ins[7];
+
+ fp = rw->ins[6] + STACK_BIAS;
+ } while (trace->nr_entries < trace->max_entries);
+}
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index 49703c3c576..405855dd886 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -190,7 +190,10 @@ sun4v_res_mondo:
mov %g1, %g4
ba,pt %xcc, etrap_irq
rd %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
/* Log the event. */
add %sp, PTREGS_OFF, %o0
call sun4v_resum_error
@@ -216,7 +219,10 @@ sun4v_res_mondo_queue_full:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
call sun4v_resum_overflow
add %sp, PTREGS_OFF, %o0
@@ -295,7 +301,10 @@ sun4v_nonres_mondo:
mov %g1, %g4
ba,pt %xcc, etrap_irq
rd %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
/* Log the event. */
add %sp, PTREGS_OFF, %o0
call sun4v_nonresum_error
@@ -321,7 +330,10 @@ sun4v_nonres_mondo_queue_full:
wrpr %g0, 15, %pil
ba,pt %xcc, etrap_irq
rd %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
call sun4v_nonresum_overflow
add %sp, PTREGS_OFF, %o0
diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S
index b731881224e..9871dbb1ab4 100644
--- a/arch/sparc64/kernel/sun4v_tlb_miss.S
+++ b/arch/sparc64/kernel/sun4v_tlb_miss.S
@@ -142,9 +142,9 @@ sun4v_dtlb_prot:
rdpr %tl, %g1
cmp %g1, 1
bgu,pn %xcc, winfix_trampoline
- nop
- ba,pt %xcc, sparc64_realfault_common
mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
+ ba,pt %xcc, sparc64_realfault_common
+ nop
/* Called from trap table:
* %g4: vaddr
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 7da72d3b322..2ebc2c05138 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -83,7 +83,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
file = fget(fd);
if (!file)
goto out;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
@@ -615,7 +615,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
if (!file)
return 0;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
socket = SOCKET_I(inode);
local.sin_family = AF_INET;
@@ -1055,7 +1055,7 @@ asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
break;
case 2:
rval = -EFAULT;
- kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+ kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
GFP_KERNEL);
if (!kmbuf)
break;
@@ -1078,7 +1078,7 @@ asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
break;
case 3:
rval = -EFAULT;
- kmbuf = (struct msgbuf *)kmalloc(sizeof(struct msgbuf) + arg3,
+ kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
GFP_KERNEL);
if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2,
kmbuf, arg3))
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index fe1796c939c..ad67784292d 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -10,7 +10,7 @@
*/
#include <linux/module.h>
-#include <linux/sched.h> /* for jiffies */
+#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/kallsyms.h>
#include <linux/signal.h>
@@ -1873,6 +1873,16 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
put_cpu();
+ if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) {
+ /* If err_type is 0x4, it's a powerdown request. Do
+ * not do the usual resumable error log because that
+ * makes it look like some abnormal error.
+ */
+ printk(KERN_INFO "Power down request...\n");
+ kill_cad_pid(SIGINT, 1);
+ return;
+ }
+
sun4v_log_error(regs, &local_copy, cpu,
KERN_ERR "RESUMABLE ERROR",
&sun4v_resum_oflow_cnt);
@@ -2261,8 +2271,12 @@ void die_if_kernel(char *str, struct pt_regs *regs)
do_exit(SIGSEGV);
}
+#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19))
+#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
+
extern int handle_popc(u32 insn, struct pt_regs *regs);
extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
+extern int vis_emul(struct pt_regs *, unsigned int);
void do_illegal_instruction(struct pt_regs *regs)
{
@@ -2287,10 +2301,18 @@ void do_illegal_instruction(struct pt_regs *regs)
if (handle_ldf_stq(insn, regs))
return;
} else if (tlb_type == hypervisor) {
- extern int vis_emul(struct pt_regs *, unsigned int);
+ if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) {
+ if (!vis_emul(regs, insn))
+ return;
+ } else {
+ struct fpustate *f = FPUSTATE;
- if (!vis_emul(regs, insn))
- return;
+ /* XXX maybe verify XFSR bits like
+ * XXX do_fpother() does?
+ */
+ if (do_mathemu(regs, f))
+ return;
+ }
}
}
info.si_signo = SIGILL;
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index a9b765271b8..bc18d480dd1 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -243,7 +243,7 @@ static inline int ok_for_kernel(unsigned int insn)
return !floating_point_load_or_store_p(insn);
}
-static void kernel_mna_trap_fault(void)
+static void kernel_mna_trap_fault(int fixup_tstate_asi)
{
struct pt_regs *regs = current_thread_info()->kern_una_regs;
unsigned int insn = current_thread_info()->kern_una_insn;
@@ -274,18 +274,15 @@ static void kernel_mna_trap_fault(void)
regs->tpc = entry->fixup;
regs->tnpc = regs->tpc + 4;
- regs->tstate &= ~TSTATE_ASI;
- regs->tstate |= (ASI_AIUS << 24UL);
+ if (fixup_tstate_asi) {
+ regs->tstate &= ~TSTATE_ASI;
+ regs->tstate |= (ASI_AIUS << 24UL);
+ }
}
-asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+static void log_unaligned(struct pt_regs *regs)
{
static unsigned long count, last_time;
- enum direction dir = decode_direction(insn);
- int size = decode_access_size(insn);
-
- current_thread_info()->kern_una_regs = regs;
- current_thread_info()->kern_una_insn = insn;
if (jiffies - last_time > 5 * HZ)
count = 0;
@@ -295,6 +292,28 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
printk("Kernel unaligned access at TPC[%lx] ", regs->tpc);
print_symbol("%s\n", regs->tpc);
}
+}
+
+asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+{
+ enum direction dir = decode_direction(insn);
+ int size = decode_access_size(insn);
+ int orig_asi, asi;
+
+ current_thread_info()->kern_una_regs = regs;
+ current_thread_info()->kern_una_insn = insn;
+
+ orig_asi = asi = decode_asi(insn, regs);
+
+ /* If this is a {get,put}_user() on an unaligned userspace pointer,
+ * just signal a fault and do not log the event.
+ */
+ if (asi == ASI_AIUS) {
+ kernel_mna_trap_fault(0);
+ return;
+ }
+
+ log_unaligned(regs);
if (!ok_for_kernel(insn) || dir == both) {
printk("Unsupported unaligned load/store trap for kernel "
@@ -302,10 +321,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
unaligned_panic("Kernel does fpu/atomic "
"unaligned load/store.", regs);
- kernel_mna_trap_fault();
+ kernel_mna_trap_fault(0);
} else {
unsigned long addr, *reg_addr;
- int orig_asi, asi, err;
+ int err;
addr = compute_effective_address(regs, insn,
((insn >> 25) & 0x1f));
@@ -315,7 +334,6 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
regs->tpc, dirstrings[dir], addr, size,
regs->u_regs[UREG_RETPC]);
#endif
- orig_asi = asi = decode_asi(insn, regs);
switch (asi) {
case ASI_NL:
case ASI_AIUPL:
@@ -365,7 +383,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
/* Not reached... */
}
if (unlikely(err))
- kernel_mna_trap_fault();
+ kernel_mna_trap_fault(1);
else
advance(regs);
}
diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c
index 84fedaa38aa..c3fd64706b5 100644
--- a/arch/sparc64/kernel/visemul.c
+++ b/arch/sparc64/kernel/visemul.c
@@ -128,9 +128,6 @@
/* 001001100 - Permute bytes as specified by GSR.MASK */
#define BSHUFFLE_OPF 0x04c
-#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19))
-#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
-
#define VIS_OPF_SHIFT 5
#define VIS_OPF_MASK (0x1ff << VIS_OPF_SHIFT)
@@ -810,9 +807,6 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
if (get_user(insn, (u32 __user *) pc))
return -EFAULT;
- if ((insn & VIS_OPCODE_MASK) != VIS_OPCODE_VAL)
- return -EINVAL;
-
opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT;
switch (opf) {
default:
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index a8e8802eed4..054822a3e05 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -872,6 +872,115 @@ static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn,
prom_halt();
}
+static void __init trim_pavail(unsigned long *cur_size_p,
+ unsigned long *end_of_phys_p)
+{
+ unsigned long to_trim = *cur_size_p - cmdline_memory_size;
+ unsigned long avoid_start, avoid_end;
+ int i;
+
+ to_trim = PAGE_ALIGN(to_trim);
+
+ avoid_start = avoid_end = 0;
+#ifdef CONFIG_BLK_DEV_INITRD
+ avoid_start = initrd_start;
+ avoid_end = PAGE_ALIGN(initrd_end);
+#endif
+
+ /* Trim some pavail[] entries in order to satisfy the
+ * requested "mem=xxx" kernel command line specification.
+ *
+ * We must not trim off the kernel image area nor the
+ * initial ramdisk range (if any). Also, we must not trim
+ * any pavail[] entry down to zero in order to preserve
+ * the invariant that all pavail[] entries have a non-zero
+ * size which is assumed by all of the code in here.
+ */
+ for (i = 0; i < pavail_ents; i++) {
+ unsigned long start, end, kern_end;
+ unsigned long trim_low, trim_high, n;
+
+ kern_end = PAGE_ALIGN(kern_base + kern_size);
+
+ trim_low = start = pavail[i].phys_addr;
+ trim_high = end = start + pavail[i].reg_size;
+
+ if (kern_base >= start &&
+ kern_base < end) {
+ trim_low = kern_base;
+ if (kern_end >= end)
+ continue;
+ }
+ if (kern_end >= start &&
+ kern_end < end) {
+ trim_high = kern_end;
+ }
+ if (avoid_start &&
+ avoid_start >= start &&
+ avoid_start < end) {
+ if (trim_low > avoid_start)
+ trim_low = avoid_start;
+ if (avoid_end >= end)
+ continue;
+ }
+ if (avoid_end &&
+ avoid_end >= start &&
+ avoid_end < end) {
+ if (trim_high < avoid_end)
+ trim_high = avoid_end;
+ }
+
+ if (trim_high <= trim_low)
+ continue;
+
+ if (trim_low == start && trim_high == end) {
+ /* Whole chunk is available for trimming.
+ * Trim all except one page, in order to keep
+ * entry non-empty.
+ */
+ n = (end - start) - PAGE_SIZE;
+ if (n > to_trim)
+ n = to_trim;
+
+ if (n) {
+ pavail[i].phys_addr += n;
+ pavail[i].reg_size -= n;
+ to_trim -= n;
+ }
+ } else {
+ n = (trim_low - start);
+ if (n > to_trim)
+ n = to_trim;
+
+ if (n) {
+ pavail[i].phys_addr += n;
+ pavail[i].reg_size -= n;
+ to_trim -= n;
+ }
+ if (to_trim) {
+ n = end - trim_high;
+ if (n > to_trim)
+ n = to_trim;
+ if (n) {
+ pavail[i].reg_size -= n;
+ to_trim -= n;
+ }
+ }
+ }
+
+ if (!to_trim)
+ break;
+ }
+
+ /* Recalculate. */
+ *cur_size_p = 0UL;
+ for (i = 0; i < pavail_ents; i++) {
+ *end_of_phys_p = pavail[i].phys_addr +
+ pavail[i].reg_size;
+ *cur_size_p += pavail[i].reg_size;
+ }
+}
+
static unsigned long __init bootmem_init(unsigned long *pages_avail,
unsigned long phys_base)
{
@@ -889,31 +998,13 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
end_of_phys_memory = pavail[i].phys_addr +
pavail[i].reg_size;
bytes_avail += pavail[i].reg_size;
- if (cmdline_memory_size) {
- if (bytes_avail > cmdline_memory_size) {
- unsigned long slack = bytes_avail - cmdline_memory_size;
-
- bytes_avail -= slack;
- end_of_phys_memory -= slack;
-
- pavail[i].reg_size -= slack;
- if ((long)pavail[i].reg_size <= 0L) {
- pavail[i].phys_addr = 0xdeadbeefUL;
- pavail[i].reg_size = 0UL;
- pavail_ents = i;
- } else {
- pavail[i+1].reg_size = 0Ul;
- pavail[i+1].phys_addr = 0xdeadbeefUL;
- pavail_ents = i + 1;
- }
- break;
- }
- }
}
- *pages_avail = bytes_avail >> PAGE_SHIFT;
-
- end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+ /* Determine the location of the initial ramdisk before trying
+ * to honor the "mem=xxx" command line argument. We must know
+ * where the kernel image and the ramdisk image are so that we
+ * do not trim those two areas from the physical memory map.
+ */
#ifdef CONFIG_BLK_DEV_INITRD
/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
@@ -932,6 +1023,16 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
}
}
#endif
+
+ if (cmdline_memory_size &&
+ bytes_avail > cmdline_memory_size)
+ trim_pavail(&bytes_avail,
+ &end_of_phys_memory);
+
+ *pages_avail = bytes_avail >> PAGE_SHIFT;
+
+ end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+
/* Initialize the boot-time allocator. */
max_pfn = max_low_pfn = end_pfn;
min_low_pfn = (phys_base >> PAGE_SHIFT);
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index d70b60a3bbc..737c26923c0 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -477,6 +477,10 @@ xcall_sync_tick:
sethi %hi(109f), %g7
b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
call smp_synchronize_tick_client
nop
clr %l6
@@ -508,6 +512,10 @@ xcall_report_regs:
sethi %hi(109f), %g7
b,pt %xcc, etrap_irq
109: or %g7, %lo(109b), %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+ call trace_hardirqs_off
+ nop
+#endif
call __show_regs
add %sp, PTREGS_OFF, %o0
clr %l6
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 12a940cc791..61be597bf43 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -449,7 +449,7 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
error = -EBADF;
file = fget(fd);
if (file) {
- error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf);
+ error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
fput(file);
}
@@ -481,7 +481,7 @@ asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
file = fget(fd);
if (file) {
lock_kernel();
- error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf);
+ error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
unlock_kernel();
fput(file);
}
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index be0a054e3ed..330743c5b3d 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -299,8 +299,8 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
rcu_read_lock();
fdt = files_fdtable(current->files);
if (! fdt->fd[fd] ||
- ! fdt->fd[fd]->f_dentry ||
- ! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
+ ! fdt->fd[fd]->f_path.dentry ||
+ ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) ||
! S_ISSOCK(ino->i_mode)) {
rcu_read_unlock();
return TBADF;
@@ -480,7 +480,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd
struct sol_socket_struct *sock;
struct module_info *mi;
- ino = filp->f_dentry->d_inode;
+ ino = filp->f_path.dentry->d_inode;
if (!S_ISSOCK(ino->i_mode))
return -EBADF;
sock = filp->private_data;
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 9ed997982f8..bca16e8c95c 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -77,7 +77,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
if (!file)
goto out;
else {
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
if(imajor(inode) == MEM_MAJOR &&
iminor(inode) == 5) {
flags |= MAP_ANONYMOUS;
@@ -423,9 +423,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
Solaris setpgrp and setsid? */
ret = sys_setpgid(0, 0);
if (ret) return ret;
- mutex_lock(&tty_mutex);
- current->signal->tty = NULL;
- mutex_unlock(&tty_mutex);
+ proc_clear_tty(current);
return process_group(current);
}
case 2: /* getsid */
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index 7c90e41fd3b..89a4757f192 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -96,13 +96,13 @@ static int socksys_open(struct inode * inode, struct file * filp)
* No shit. WTF is it supposed to do, anyway?
*
* Try instead:
- * d_delete(filp->f_dentry), then d_instantiate with sock inode
+ * d_delete(filp->f_path.dentry), then d_instantiate with sock inode
*/
- dentry = filp->f_dentry;
- filp->f_dentry = dget(fcheck(fd)->f_dentry);
- filp->f_dentry->d_inode->i_rdev = inode->i_rdev;
- filp->f_dentry->d_inode->i_flock = inode->i_flock;
- SOCKET_I(filp->f_dentry->d_inode)->file = filp;
+ dentry = filp->f_path.dentry;
+ filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry);
+ filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev;
+ filp->f_path.dentry->d_inode->i_flock = inode->i_flock;
+ SOCKET_I(filp->f_path.dentry->d_inode)->file = filp;
filp->f_op = &socksys_file_ops;
sock = (struct sol_socket_struct*)
mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
@@ -148,7 +148,7 @@ static unsigned int socksys_poll(struct file * filp, poll_table * wait)
struct inode *ino;
unsigned int mask = 0;
- ino=filp->f_dentry->d_inode;
+ ino=filp->f_path.dentry->d_inode;
if (ino && S_ISSOCK(ino->i_mode)) {
struct sol_socket_struct *sock;
sock = (struct sol_socket_struct*)filp->private_data;
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index b84e5456b02..a9d32ceabf2 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -147,7 +147,7 @@ static void timod_wake_socket(unsigned int fd)
SOLD("wakeing socket");
fdt = files_fdtable(current->files);
- sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode);
+ sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
wake_up_interruptible(&sock->wait);
read_lock(&sock->sk->sk_callback_lock);
if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -361,7 +361,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
fdt = files_fdtable(current->files);
filp = fdt->fd[fd];
- ino = filp->f_dentry->d_inode;
+ ino = filp->f_path.dentry->d_inode;
sock = (struct sol_socket_struct *)filp->private_data;
SOLD("entry");
if (get_user(ret, (int __user *)A(ctl_buf)))
@@ -644,7 +644,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
fdt = files_fdtable(current->files);
filp = fdt->fd[fd];
- ino = filp->f_dentry->d_inode;
+ ino = filp->f_path.dentry->d_inode;
sock = (struct sol_socket_struct *)filp->private_data;
SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
@@ -865,7 +865,7 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
filp = fdt->fd[fd];
if(!filp) goto out;
- ino = filp->f_dentry->d_inode;
+ ino = filp->f_path.dentry->d_inode;
if (!ino || !S_ISSOCK(ino->i_mode))
goto out;
@@ -933,7 +933,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
filp = fdt->fd[fd];
if(!filp) goto out;
- ino = filp->f_dentry->d_inode;
+ ino = filp->f_path.dentry->d_inode;
if (!ino) goto out;
if (!S_ISSOCK(ino->i_mode) &&
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 5ac1f2963ae..d32a80e6668 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -47,6 +47,11 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config GENERIC_BUG
+ bool
+ default y
+ depends on BUG
+
# Used in kernel/irq/manage.c and include/linux/irq.h
config IRQ_RELEASE_METHOD
bool
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index f191a550a07..d6cffb27fff 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -19,31 +19,31 @@ config SEMAPHORE_SLEEPERS
choice
prompt "Host memory split"
default HOST_VMSPLIT_3G
- ---help---
- This is needed when the host kernel on which you run has a non-default
- (like 2G/2G) memory split, instead of the customary 3G/1G. If you did
- not recompile your own kernel but use the default distro's one, you can
- safely accept the "Default split" option.
-
- It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via
- CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck
- patchset by Con Kolivas, or other ones) - option names match closely the
- host CONFIG_VM_SPLIT_* ones.
-
- A lower setting (where 1G/3G is lowest and 3G/1G is higher) will
- tolerate even more "normal" host kernels, but an higher setting will be
- stricter.
-
- So, if you do not know what to do here, say 'Default split'.
-
- config HOST_VMSPLIT_3G
- bool "Default split (3G/1G user/kernel host split)"
- config HOST_VMSPLIT_3G_OPT
- bool "3G/1G user/kernel host split (for full 1G low memory)"
- config HOST_VMSPLIT_2G
- bool "2G/2G user/kernel host split"
- config HOST_VMSPLIT_1G
- bool "1G/3G user/kernel host split"
+ help
+ This is needed when the host kernel on which you run has a non-default
+ (like 2G/2G) memory split, instead of the customary 3G/1G. If you did
+ not recompile your own kernel but use the default distro's one, you can
+ safely accept the "Default split" option.
+
+ It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via
+ CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck
+ patchset by Con Kolivas, or other ones) - option names match closely the
+ host CONFIG_VM_SPLIT_* ones.
+
+ A lower setting (where 1G/3G is lowest and 3G/1G is higher) will
+ tolerate even more "normal" host kernels, but an higher setting will be
+ stricter.
+
+ So, if you do not know what to do here, say 'Default split'.
+
+config HOST_VMSPLIT_3G
+ bool "Default split (3G/1G user/kernel host split)"
+config HOST_VMSPLIT_3G_OPT
+ bool "3G/1G user/kernel host split (for full 1G low memory)"
+config HOST_VMSPLIT_2G
+ bool "2G/2G user/kernel host split"
+config HOST_VMSPLIT_1G
+ bool "1G/3G user/kernel host split"
endchoice
config TOP_ADDR
@@ -67,13 +67,13 @@ config 3_LEVEL_PGTABLES
config STUB_CODE
hex
- default 0xbfffe000 if !HOST_2G_2G
- default 0x7fffe000 if HOST_2G_2G
+ default 0xbfffe000 if !HOST_VMSPLIT_2G
+ default 0x7fffe000 if HOST_VMSPLIT_2G
config STUB_DATA
hex
- default 0xbffff000 if !HOST_2G_2G
- default 0x7ffff000 if HOST_2G_2G
+ default 0xbffff000 if !HOST_VMSPLIT_2G
+ default 0x7ffff000 if HOST_VMSPLIT_2G
config STUB_START
hex
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index aa3090d05a8..83301e1ef67 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -246,7 +246,7 @@ out_up:
return ret;
}
-void line_set_termios(struct tty_struct *tty, struct termios * old)
+void line_set_termios(struct tty_struct *tty, struct ktermios * old)
{
/* nothing */
}
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 286bc0b3207..afe3d427ddf 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -72,9 +72,11 @@ static int uml_net_rx(struct net_device *dev)
return pkt_len;
}
-static void uml_dev_close(void* dev)
+static void uml_dev_close(struct work_struct *work)
{
- dev_close( (struct net_device *) dev);
+ struct uml_net_private *lp =
+ container_of(work, struct uml_net_private, work);
+ dev_close(lp->dev);
}
irqreturn_t uml_net_interrupt(int irq, void *dev_id)
@@ -89,7 +91,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
spin_lock(&lp->lock);
while((err = uml_net_rx(dev)) > 0) ;
if(err < 0) {
- DECLARE_WORK(close_work, uml_dev_close, dev);
printk(KERN_ERR
"Device '%s' read returned %d, shutting it down\n",
dev->name, err);
@@ -97,9 +98,10 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
* again lp->lock.
* And dev_close() can be safely called multiple times on the
* same device, since it tests for (dev->flags & IFF_UP). So
- * there's no harm in delaying the device shutdown. */
- schedule_work(&close_work);
-#error this is not permitted - close_work will go out of scope
+ * there's no harm in delaying the device shutdown.
+ * Furthermore, the workqueue will not re-enqueue an already
+ * enqueued work item. */
+ schedule_work(&lp->work);
goto out;
}
reactivate_fd(lp->fd, UM_ETH_IRQ);
@@ -334,13 +336,12 @@ static int eth_configure(int n, void *init, char *mac,
size = transport->private_size + sizeof(struct uml_net_private) +
sizeof(((struct uml_net_private *) 0)->user);
- device = kmalloc(sizeof(*device), GFP_KERNEL);
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
if (device == NULL) {
printk(KERN_ERR "eth_configure failed to allocate uml_net\n");
return(1);
}
- memset(device, 0, sizeof(*device));
INIT_LIST_HEAD(&device->list);
device->index = n;
@@ -366,6 +367,7 @@ static int eth_configure(int n, void *init, char *mac,
/* This points to the transport private data. It's still clear, but we
* must memset it to 0 *now*. Let's help the drivers. */
memset(lp, 0, size);
+ INIT_WORK(&lp->work, uml_dev_close);
/* sysfs register */
if (!driver_registered) {
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 214ee76c40d..5f232ae89fb 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -76,7 +76,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines,
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
int len);
extern void line_put_char(struct tty_struct *tty, unsigned char ch);
-extern void line_set_termios(struct tty_struct *tty, struct termios * old);
+extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
extern int line_chars_in_buffer(struct tty_struct *tty);
extern void line_flush_buffer(struct tty_struct *tty);
extern void line_flush_chars(struct tty_struct *tty);
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 280459fb0b2..218f8b47fdc 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -11,6 +11,7 @@
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/list.h>
+#include <linux/workqueue.h>
struct uml_net {
struct list_head list;
@@ -26,6 +27,7 @@ struct uml_net_private {
struct net_device *dev;
struct timer_list tl;
struct net_device_stats stats;
+ struct work_struct work;
int fd;
unsigned char mac[ETH_ALEN];
unsigned short (*protocol)(struct sk_buff *);
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 0561c43b468..8d56ec6cca7 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -39,12 +39,13 @@ static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
long error;
+ struct tty_struct *tty;
#ifdef CONFIG_TTY_LOG
mutex_lock(&tty_mutex);
- task_lock(current); /* FIXME: is this needed ? */
- log_exec(argv, current->signal->tty);
- task_unlock(current);
+ tty = get_current_tty();
+ if (tty)
+ log_exec(argv, tty);
mutex_unlock(&tty_mutex);
#endif
error = do_execve(file, argv, env, &current->thread.regs);
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 0e32adf03be..098720be019 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,4 +1,4 @@
-obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
+obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
sys_call_table.o tls.o
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
new file mode 100644
index 00000000000..200c8ba2879
--- /dev/null
+++ b/arch/um/sys-i386/bug.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevent in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+ unsigned short ud2;
+
+ if (probe_kernel_address((unsigned short __user *)eip, ud2))
+ return 0;
+
+ return ud2 == 0x0b0f;
+}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 49057d8bc66..5db7737df0f 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -166,7 +166,7 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
.func = 0,
.bytecount = bytecount,
- .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)};
+ .ptr = kmalloc(bytecount, GFP_KERNEL)};
u32 cpu;
if(ptrace_ldt.ptr == NULL)
@@ -426,7 +426,7 @@ void ldt_get_host_info(void)
host_ldt_entries = dummy_list;
else {
size = (size + 1) * sizeof(dummy_list[0]);
- host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
+ host_ldt_entries = kmalloc(size, GFP_KERNEL);
if(host_ldt_entries == NULL) {
printk("ldt_get_host_info: couldn't allocate host ldt list\n");
goto out_free;
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 0709fc6670c..3f6acd66771 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -219,7 +219,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
- stack_top &= -8UL;
+ /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
+ stack_top = ((stack_top + 4) & -16UL) - 4;
frame = (struct sigframe __user *) stack_top - 1;
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return 1;
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index f41768b8e25..4d9e5efa6fb 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,7 +4,7 @@
# Licensed under the GPL
#
-obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
+obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
ksyms.o tls.o
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
new file mode 100644
index 00000000000..200c8ba2879
--- /dev/null
+++ b/arch/um/sys-x86_64/bug.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevent in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+ unsigned short ud2;
+
+ if (probe_kernel_address((unsigned short __user *)eip, ud2))
+ return 0;
+
+ return ud2 == 0x0b0f;
+}
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 9edf114faf7..af2f017617b 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -191,8 +191,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
struct task_struct *me = current;
frame = (struct rt_sigframe __user *)
- round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
- frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128);
+ round_down(stack_top - sizeof(struct rt_sigframe), 16);
+ /* Subtract 128 for a red zone and 8 for proper alignment */
+ frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
goto out;
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 37ec644603a..f0d4d72e560 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -38,6 +38,14 @@ config TIME_LOW_RES
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
# Turn off some random 386 crap that can affect device config
config ISA
bool
@@ -97,17 +105,17 @@ menu "Processor type and features"
# currently support
config V850E_MA1
bool
- depends RTE_CB_MA1
+ depends on RTE_CB_MA1
default y
# Similarly for the RTE-V850E/NB85E-CB - V850E/TEG
config V850E_TEG
bool
- depends RTE_CB_NB85E
+ depends on RTE_CB_NB85E
default y
# ... and the RTE-V850E/ME2-CB - V850E/ME2
config V850E_ME2
bool
- depends RTE_CB_ME2
+ depends on RTE_CB_ME2
default y
@@ -115,7 +123,7 @@ menu "Processor type and features"
config V850E2_SIM85E2
bool
- depends V850E2_SIM85E2C || V850E2_SIM85E2S
+ depends on V850E2_SIM85E2C || V850E2_SIM85E2S
default y
@@ -124,7 +132,7 @@ menu "Processor type and features"
# V850E2 processors
config V850E2
bool
- depends V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA
+ depends on V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA
default y
@@ -133,7 +141,7 @@ menu "Processor type and features"
# Boards in the RTE-x-CB series
config RTE_CB
bool
- depends RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2
+ depends on RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2
default y
config RTE_CB_MULTI
@@ -141,28 +149,28 @@ menu "Processor type and features"
# RTE_CB_NB85E can either have multi ROM support or not, but
# other platforms (currently only RTE_CB_MA1) require it.
prompt "Multi monitor ROM support" if RTE_CB_NB85E
- depends RTE_CB_MA1 || RTE_CB_NB85E
+ depends on RTE_CB_MA1 || RTE_CB_NB85E
default y
config RTE_CB_MULTI_DBTRAP
bool "Pass illegal insn trap / dbtrap to kernel"
- depends RTE_CB_MULTI
+ depends on RTE_CB_MULTI
default n
config RTE_CB_MA1_KSRAM
bool "Kernel in SRAM (limits size of kernel)"
- depends RTE_CB_MA1 && RTE_CB_MULTI
+ depends on RTE_CB_MA1 && RTE_CB_MULTI
default n
config RTE_MB_A_PCI
bool "Mother-A PCI support"
- depends RTE_CB
+ depends on RTE_CB
default y
# The GBUS is used to talk to the RTE-MOTHER-A board
config RTE_GBUS_INT
bool
- depends RTE_MB_A_PCI
+ depends on RTE_MB_A_PCI
default y
# The only PCI bus we support is on the RTE-MOTHER-A board
@@ -201,7 +209,7 @@ menu "Processor type and features"
config ROM_KERNEL
bool "Kernel in ROM"
- depends V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2
+ depends on V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2
# Some platforms pre-zero memory, in which case the kernel doesn't need to
config ZERO_BSS
@@ -217,10 +225,10 @@ menu "Processor type and features"
config V850E_HIGHRES_TIMER
bool "High resolution timer support"
- depends V850E_TIMER_D
+ depends on V850E_TIMER_D
config TIME_BOOTUP
bool "Time bootup"
- depends V850E_HIGHRES_TIMER
+ depends on V850E_HIGHRES_TIMER
config RESET_GUARD
bool "Reset Guard"
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index bfbb9bcae12..d4275537b25 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -96,6 +96,19 @@ config AUDIT_ARCH
bool
default y
+config GENERIC_BUG
+ bool
+ default y
+ depends on BUG
+
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
source "init/Kconfig"
@@ -571,7 +584,7 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
config CC_STACKPROTECTOR
- bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)"
+ bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
This option turns on the -fstack-protector GCC feature. This
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index b471b8550d0..2941a915d4e 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -45,9 +45,7 @@ cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections
# actually it makes the kernel smaller too.
cflags-y += -fno-reorder-blocks
cflags-y += -Wno-sign-compare
-ifneq ($(CONFIG_UNWIND_INFO),y)
cflags-y += -fno-asynchronous-unwind-tables
-endif
ifneq ($(CONFIG_DEBUG_INFO),y)
# -fweb shrinks the kernel a bit, but the difference is very small
# it also messes up debugging, so don't use it for now.
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 96f226cfb33..69584c29530 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-git7
-# Wed Dec 6 23:50:47 2006
+# Linux kernel version: 2.6.20-rc3
+# Fri Jan 5 11:54:41 2007
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -22,6 +22,9 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_DMI=y
CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -170,6 +173,7 @@ CONFIG_SECCOMP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
# CONFIG_REORDER is not set
@@ -514,6 +518,7 @@ CONFIG_IDEDMA_AUTO=y
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
CONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_PROC_FS is not set
@@ -534,6 +539,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
@@ -587,6 +593,7 @@ CONFIG_MEGARAID_SAS=y
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -1049,6 +1056,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
@@ -1059,6 +1067,7 @@ CONFIG_SENSORS_SMSC47B397=m
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
@@ -1106,10 +1115,7 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-CONFIG_OSS_OBSOLETE_DRIVER=y
# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_ES1371 is not set
CONFIG_SOUND_ICH=y
# CONFIG_SOUND_TRIDENT is not set
@@ -1119,6 +1125,11 @@ CONFIG_SOUND_ICH=y
# CONFIG_SOUND_OSS is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1182,7 +1193,6 @@ CONFIG_USB_STORAGE=y
# USB Input Devices
#
CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
@@ -1303,6 +1313,11 @@ CONFIG_USB_MON=y
#
#
+# Virtualization
+#
+# CONFIG_KVM is not set
+
+#
# Firmware Drivers
#
# CONFIG_EDD is not set
@@ -1475,6 +1490,11 @@ CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_UTF8=y
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Instrumentation Support
#
CONFIG_PROFILING=y
@@ -1489,6 +1509,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1504,15 +1526,12 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
-CONFIG_UNWIND_INFO=y
-CONFIG_STACK_UNWIND=y
# CONFIG_FORCED_INLINING is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_DEBUG_RODATA is not set
@@ -1534,9 +1553,11 @@ CONFIG_DEBUG_STACKOVERFLOW=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 396d3c10001..fe83edb93c1 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -241,7 +241,7 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)
get_user(c,p++);
} while (c);
}
- put_user(NULL,argv);
+ put_user(0, argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
char c;
@@ -250,7 +250,7 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)
get_user(c,p++);
} while (c);
}
- put_user(NULL,envp);
+ put_user(0, envp);
current->mm->env_end = (unsigned long) p;
return sp;
}
@@ -272,7 +272,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
- i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
return -ENOEXEC;
}
@@ -357,7 +357,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
printk(KERN_WARNING
"fd_offset is not page aligned. Please convert program: %s\n",
- bprm->file->f_dentry->d_name.name);
+ bprm->file->f_path.dentry->d_name.name);
error_time = jiffies;
}
#endif
@@ -440,7 +440,7 @@ static int load_aout_library(struct file *file)
int retval;
struct exec ex;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
retval = -ENOEXEC;
error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
@@ -471,7 +471,7 @@ static int load_aout_library(struct file *file)
{
printk(KERN_WARNING
"N_TXTOFF is not page aligned. Please convert library: %s\n",
- file->f_dentry->d_name.name);
+ file->f_path.dentry->d_name.name);
error_time = jiffies;
}
#endif
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 543ef4f405e..5ce0bd486bb 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -64,55 +64,6 @@ typedef unsigned int elf_greg_t;
#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents. Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \
- (VSYSCALL32_EHDR->e_phnum) : 0)
-#define ELF_CORE_WRITE_EXTRA_PHDRS \
-do { \
- if (find_vma(current->mm, VSYSCALL32_BASE)) { \
- const struct elf32_phdr *const vsyscall_phdrs = \
- (const struct elf32_phdr *) (VSYSCALL32_BASE \
- + VSYSCALL32_EHDR->e_phoff);\
- int i; \
- Elf32_Off ofs = 0; \
- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
- struct elf32_phdr phdr = vsyscall_phdrs[i]; \
- if (phdr.p_type == PT_LOAD) { \
- BUG_ON(ofs != 0); \
- ofs = phdr.p_offset = offset; \
- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
- phdr.p_filesz = phdr.p_memsz; \
- offset += phdr.p_filesz; \
- } \
- else \
- phdr.p_offset += ofs; \
- phdr.p_paddr = 0; /* match other core phdrs */ \
- DUMP_WRITE(&phdr, sizeof(phdr)); \
- } \
- } \
-} while (0)
-#define ELF_CORE_WRITE_EXTRA_DATA \
-do { \
- if (find_vma(current->mm, VSYSCALL32_BASE)) { \
- const struct elf32_phdr *const vsyscall_phdrs = \
- (const struct elf32_phdr *) (VSYSCALL32_BASE \
- + VSYSCALL32_EHDR->e_phoff); \
- int i; \
- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
- if (vsyscall_phdrs[i].p_type == PT_LOAD) \
- DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
- PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
- } \
- } \
-} while (0)
-
struct elf_siginfo
{
int si_signo; /* signal number */
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index 3e5ed20cba4..59f1fa15591 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -59,6 +59,13 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack)
vma->vm_end = VSYSCALL32_END;
/* MAYWRITE to allow gdb to COW and set breakpoints */
vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+ * without matching up the same kernel and hardware config to see
+ * what PC values meant.
+ */
+ vma->vm_flags |= VM_ALWAYSDUMP;
vma->vm_flags |= mm->def_flags;
vma->vm_page_prot = protection_map[vma->vm_flags & 7];
vma->vm_ops = &syscall32_vm_ops;
@@ -75,6 +82,14 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack)
return 0;
}
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_start == VSYSCALL32_BASE &&
+ vma->vm_mm && vma->vm_mm->task_size == IA32_PAGE_OFFSET)
+ return "[vdso]";
+ return NULL;
+}
+
static int __init init_syscall32(void)
{
syscall32_page = (void *)get_zeroed_page(GFP_KERNEL);
diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
index 81f1562e539..45a6a1fd14a 100644
--- a/arch/x86_64/kernel/cpufreq/Kconfig
+++ b/arch/x86_64/kernel/cpufreq/Kconfig
@@ -27,10 +27,13 @@ config X86_POWERNOW_K8_ACPI
default y
config X86_SPEEDSTEP_CENTRINO
- tristate "Intel Enhanced SpeedStep"
+ tristate "Intel Enhanced SpeedStep (deprecated)"
select CPU_FREQ_TABLE
depends on ACPI_PROCESSOR
help
+ This is deprecated and this functionality is now merged into
+ acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
+ speedstep_centrino.
This adds the CPUFreq driver for Enhanced SpeedStep enabled
mobile CPUs. This means Intel Pentium M (Centrino) CPUs
or 64bit enabled Intel Xeons.
@@ -46,10 +49,12 @@ config X86_SPEEDSTEP_CENTRINO_ACPI
config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver"
+ select CPU_FREQ_TABLE
depends on ACPI_PROCESSOR
help
This driver adds a CPUFreq driver which utilizes the ACPI
Processor Performance States.
+ This driver also supports Intel Enhanced Speedstep.
For details, take a look at <file:Documentation/cpu-freq/>.
diff --git a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile
index d8b59387922..753ce1dd418 100644
--- a/arch/x86_64/kernel/cpufreq/Makefile
+++ b/arch/x86_64/kernel/cpufreq/Makefile
@@ -5,8 +5,8 @@
SRCDIR := ../../../i386/kernel/cpu/cpufreq
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
-obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
index 829698f6d04..49802f1bee9 100644
--- a/arch/x86_64/kernel/early-quirks.c
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -69,6 +69,11 @@ static void nvidia_bugs(void)
static void ati_bugs(void)
{
+ if (timer_over_8254 == 1) {
+ timer_over_8254 = 0;
+ printk(KERN_INFO
+ "ATI board detected. Disabling timer routing over 8254.\n");
+ }
}
static void intel_bugs(void)
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 601d332c4b7..9f5dac64aa8 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -1155,36 +1155,3 @@ ENTRY(call_softirq)
ret
CFI_ENDPROC
ENDPROC(call_softirq)
-
-#ifdef CONFIG_STACK_UNWIND
-ENTRY(arch_unwind_init_running)
- CFI_STARTPROC
- movq %r15, R15(%rdi)
- movq %r14, R14(%rdi)
- xchgq %rsi, %rdx
- movq %r13, R13(%rdi)
- movq %r12, R12(%rdi)
- xorl %eax, %eax
- movq %rbp, RBP(%rdi)
- movq %rbx, RBX(%rdi)
- movq (%rsp), %rcx
- movq %rax, R11(%rdi)
- movq %rax, R10(%rdi)
- movq %rax, R9(%rdi)
- movq %rax, R8(%rdi)
- movq %rax, RAX(%rdi)
- movq %rax, RCX(%rdi)
- movq %rax, RDX(%rdi)
- movq %rax, RSI(%rdi)
- movq %rax, RDI(%rdi)
- movq %rax, ORIG_RAX(%rdi)
- movq %rcx, RIP(%rdi)
- leaq 8(%rsp), %rcx
- movq $__KERNEL_CS, CS(%rdi)
- movq %rax, EFLAGS(%rdi)
- movq %rcx, RSP(%rdi)
- movq $__KERNEL_DS, SS(%rdi)
- jmpq *%rdx
- CFI_ENDPROC
-ENDPROC(arch_unwind_init_running)
-#endif
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 2a1dcd5f69c..d7bad90a5ad 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -55,6 +55,10 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
static int no_timer_check;
+static int disable_timer_pin_1 __initdata;
+
+int timer_over_8254 __initdata = 1;
+
/* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -350,6 +354,29 @@ static int __init disable_ioapic_setup(char *str)
}
early_param("noapic", disable_ioapic_setup);
+/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+static int __init disable_timer_pin_setup(char *arg)
+{
+ disable_timer_pin_1 = 1;
+ return 1;
+}
+__setup("disable_timer_pin_1", disable_timer_pin_setup);
+
+static int __init setup_disable_8254_timer(char *s)
+{
+ timer_over_8254 = -1;
+ return 1;
+}
+static int __init setup_enable_8254_timer(char *s)
+{
+ timer_over_8254 = 2;
+ return 1;
+}
+
+__setup("disable_8254_timer", setup_disable_8254_timer);
+__setup("enable_8254_timer", setup_enable_8254_timer);
+
+
/*
* Find the IRQ entry number of a certain pin.
*/
@@ -1568,33 +1595,10 @@ static inline void unlock_ExtINT_logic(void)
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
* is so screwy. Thanks to Brian Perkins for testing/hacking this beast
* fanatically on his truly buggy board.
+ *
+ * FIXME: really need to revamp this for modern platforms only.
*/
-
-static int try_apic_pin(int apic, int pin, char *msg)
-{
- apic_printk(APIC_VERBOSE, KERN_INFO
- "..TIMER: trying IO-APIC=%d PIN=%d %s",
- apic, pin, msg);
-
- /*
- * Ok, does IRQ0 through the IOAPIC work?
- */
- if (!no_timer_check && timer_irq_works()) {
- nmi_watchdog_default();
- if (nmi_watchdog == NMI_IO_APIC) {
- disable_8259A_irq(0);
- setup_nmi();
- enable_8259A_irq(0);
- }
- return 1;
- }
- clear_IO_APIC_pin(apic, pin);
- apic_printk(APIC_QUIET, KERN_ERR " .. failed\n");
- return 0;
-}
-
-/* The function from hell */
-static void check_timer(void)
+static inline void check_timer(void)
{
int apic1, pin1, apic2, pin2;
int vector;
@@ -1615,43 +1619,61 @@ static void check_timer(void)
*/
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1);
+ if (timer_over_8254 > 0)
+ enable_8259A_irq(0);
pin1 = find_isa_irq_pin(0, mp_INT);
apic1 = find_isa_irq_apic(0, mp_INT);
pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic;
- /* Do this first, otherwise we get double interrupts on ATI boards */
- if ((pin1 != -1) && try_apic_pin(apic1, pin1,"with 8259 IRQ0 disabled"))
- return;
+ apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+ vector, apic1, pin1, apic2, pin2);
- /* Now try again with IRQ0 8259A enabled.
- Assumes timer is on IO-APIC 0 ?!? */
- enable_8259A_irq(0);
- unmask_IO_APIC_irq(0);
- if (try_apic_pin(apic1, pin1, "with 8259 IRQ0 enabled"))
- return;
- disable_8259A_irq(0);
-
- /* Always try pin0 and pin2 on APIC 0 to handle buggy timer overrides
- on Nvidia boards */
- if (!(apic1 == 0 && pin1 == 0) &&
- try_apic_pin(0, 0, "fallback with 8259 IRQ0 disabled"))
- return;
- if (!(apic1 == 0 && pin1 == 2) &&
- try_apic_pin(0, 2, "fallback with 8259 IRQ0 disabled"))
- return;
+ if (pin1 != -1) {
+ /*
+ * Ok, does IRQ0 through the IOAPIC work?
+ */
+ unmask_IO_APIC_irq(0);
+ if (!no_timer_check && timer_irq_works()) {
+ nmi_watchdog_default();
+ if (nmi_watchdog == NMI_IO_APIC) {
+ disable_8259A_irq(0);
+ setup_nmi();
+ enable_8259A_irq(0);
+ }
+ if (disable_timer_pin_1 > 0)
+ clear_IO_APIC_pin(0, pin1);
+ return;
+ }
+ clear_IO_APIC_pin(apic1, pin1);
+ apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
+ "connected to IO-APIC\n");
+ }
- /* Then try pure 8259A routing on the 8259 as reported by BIOS*/
- enable_8259A_irq(0);
+ apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
+ "through the 8259A ... ");
if (pin2 != -1) {
+ apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
+ apic2, pin2);
+ /*
+ * legacy devices should be connected to IO APIC #0
+ */
setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
- if (try_apic_pin(apic2,pin2,"8259A broadcast ExtINT from BIOS"))
+ if (timer_irq_works()) {
+ apic_printk(APIC_VERBOSE," works.\n");
+ nmi_watchdog_default();
+ if (nmi_watchdog == NMI_IO_APIC) {
+ setup_nmi();
+ }
return;
+ }
+ /*
+ * Cleanup, just in case ...
+ */
+ clear_IO_APIC_pin(apic2, pin2);
}
-
- /* Tried all possibilities to go through the IO-APIC. Now come the
- really cheesy fallbacks. */
+ apic_printk(APIC_VERBOSE," failed.\n");
if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c
index 9d0958ff547..a888e67f587 100644
--- a/arch/x86_64/kernel/module.c
+++ b/arch/x86_64/kernel/module.c
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/bug.h>
#include <asm/system.h>
#include <asm/page.h>
@@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr,
lseg, lseg + locks->sh_size,
tseg, tseg + text->sh_size);
}
- return 0;
+
+ return module_bug_finalize(hdr, sechdrs, me);
}
void module_arch_cleanup(struct module *mod)
{
alternatives_smp_module_del(mod);
+ module_bug_cleanup(mod);
}
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 27e95e7922c..9cb42ecb7f8 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -193,6 +193,8 @@ void nmi_watchdog_default(void)
nmi_watchdog = NMI_IO_APIC;
}
+static int endflag __initdata = 0;
+
#ifdef CONFIG_SMP
/* The performance counters used by NMI_LOCAL_APIC don't trigger when
* the CPU is idle. To make sure the NMI watchdog really ticks on all
@@ -200,7 +202,6 @@ void nmi_watchdog_default(void)
*/
static __init void nmi_cpu_busy(void *data)
{
- volatile int *endflag = data;
local_irq_enable_in_hardirq();
/* Intentionally don't use cpu_relax here. This is
to make sure that the performance counter really ticks,
@@ -208,14 +209,13 @@ static __init void nmi_cpu_busy(void *data)
pause instruction. On a real HT machine this is fine because
all other CPUs are busy with "useless" delay loops and don't
care if they get somewhat less cycles. */
- while (*endflag == 0)
- barrier();
+ while (endflag == 0)
+ mb();
}
#endif
int __init check_nmi_watchdog (void)
{
- volatile int endflag = 0;
int *counts;
int cpu;
@@ -256,6 +256,7 @@ int __init check_nmi_watchdog (void)
if (!atomic_read(&nmi_active)) {
kfree(counts);
atomic_set(&nmi_active, -1);
+ endflag = 1;
return -1;
}
endflag = 1;
@@ -301,8 +302,6 @@ int __init setup_nmi_watchdog(char *str)
if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
return 0;
- if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
- return 0; /* no lapic support */
nmi_watchdog = nmi;
return 1;
}
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 3215675ab12..3d65b1d4c2b 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -1052,7 +1052,7 @@ void __init detect_calgary(void)
void *tbl;
int calgary_found = 0;
unsigned long ptr;
- int offset;
+ unsigned int offset, prev_offset;
int ret;
/*
@@ -1068,29 +1068,36 @@ void __init detect_calgary(void)
if (!early_pci_allowed())
return;
+ printk(KERN_DEBUG "Calgary: detecting Calgary via BIOS EBDA area\n");
+
ptr = (unsigned long)phys_to_virt(get_bios_ebda());
rio_table_hdr = NULL;
+ prev_offset = 0;
offset = 0x180;
- while (offset) {
+ /*
+ * The next offset is stored in the 1st word.
+ * Only parse up until the offset increases:
+ */
+ while (offset > prev_offset) {
/* The block id is stored in the 2nd word */
if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
/* set the pointer past the offset & block id */
rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
break;
}
- /* The next offset is stored in the 1st word. 0 means no more */
+ prev_offset = offset;
offset = *((unsigned short *)(ptr + offset));
}
if (!rio_table_hdr) {
- printk(KERN_ERR "Calgary: Unable to locate "
- "Rio Grande Table in EBDA - bailing!\n");
+ printk(KERN_DEBUG "Calgary: Unable to locate Rio Grande table "
+ "in EBDA - bailing!\n");
return;
}
ret = build_detail_arrays();
if (ret) {
- printk(KERN_ERR "Calgary: build_detail_arrays ret %d\n", ret);
+ printk(KERN_DEBUG "Calgary: build_detail_arrays ret %d\n", ret);
return;
}
@@ -1123,6 +1130,9 @@ void __init detect_calgary(void)
}
}
+ printk(KERN_DEBUG "Calgary: finished detection, Calgary %s\n",
+ calgary_found ? "found" : "not found");
+
if (calgary_found) {
iommu_detected = 1;
calgary_detected = 1;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index a418ee4c8c6..cbbc6adc1a9 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -109,7 +109,11 @@ void exit_idle(void)
static void default_idle(void)
{
current_thread_info()->status &= ~TS_POLLING;
- smp_mb__after_clear_bit();
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
local_irq_disable();
if (!need_resched()) {
/* Enables interrupts one instruction before HLT.
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 9f05bc9b2da..5cc76d0d331 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -656,6 +656,25 @@ core_initcall(cpufreq_tsc);
*/
#define TICK_COUNT 100000000
+#define TICK_MIN 5000
+
+/*
+ * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
+ * occurs between the reads of the hpet & TSC.
+ */
+static void __init read_hpet_tsc(int *hpet, int *tsc)
+{
+ int tsc1, tsc2, hpet1;
+
+ do {
+ tsc1 = get_cycles_sync();
+ hpet1 = hpet_readl(HPET_COUNTER);
+ tsc2 = get_cycles_sync();
+ } while (tsc2 - tsc1 > TICK_MIN);
+ *hpet = hpet1;
+ *tsc = tsc2;
+}
+
static unsigned int __init hpet_calibrate_tsc(void)
{
@@ -666,13 +685,11 @@ static unsigned int __init hpet_calibrate_tsc(void)
local_irq_save(flags);
local_irq_disable();
- hpet_start = hpet_readl(HPET_COUNTER);
- rdtscl(tsc_start);
+ read_hpet_tsc(&hpet_start, &tsc_start);
do {
local_irq_disable();
- hpet_now = hpet_readl(HPET_COUNTER);
- tsc_now = get_cycles_sync();
+ read_hpet_tsc(&hpet_now, &tsc_now);
local_irq_restore(flags);
} while ((tsc_now - tsc_start) < TICK_COUNT &&
(hpet_now - hpet_start) < TICK_COUNT);
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index a1641ffdffc..09d2e8a10a4 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -31,6 +31,7 @@
#include <linux/kexec.h>
#include <linux/unwind.h>
#include <linux/uaccess.h>
+#include <linux/bug.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -109,11 +110,6 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
}
int kstack_depth_to_print = 12;
-#ifdef CONFIG_STACK_UNWIND
-static int call_trace = 1;
-#else
-#define call_trace (-1)
-#endif
#ifdef CONFIG_KALLSYMS
void printk_address(unsigned long address)
@@ -216,32 +212,6 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
return NULL;
}
-struct ops_and_data {
- struct stacktrace_ops *ops;
- void *data;
-};
-
-static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
-{
- struct ops_and_data *oad = (struct ops_and_data *)context;
- int n = 0;
- unsigned long sp = UNW_SP(info);
-
- if (arch_unw_user_mode(info))
- return -1;
- while (unwind(info) == 0 && UNW_PC(info)) {
- n++;
- oad->ops->address(oad->data, UNW_PC(info));
- if (arch_unw_user_mode(info))
- break;
- if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
- && sp > UNW_SP(info))
- break;
- sp = UNW_SP(info);
- }
- return n;
-}
-
#define MSG(txt) ops->warning(data, txt)
/*
@@ -269,40 +239,6 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
if (!tsk)
tsk = current;
- if (call_trace >= 0) {
- int unw_ret = 0;
- struct unwind_frame_info info;
- struct ops_and_data oad = { .ops = ops, .data = data };
-
- if (regs) {
- if (unwind_init_frame_info(&info, tsk, regs) == 0)
- unw_ret = dump_trace_unwind(&info, &oad);
- } else if (tsk == current)
- unw_ret = unwind_init_running(&info, dump_trace_unwind,
- &oad);
- else {
- if (unwind_init_blocked(&info, tsk) == 0)
- unw_ret = dump_trace_unwind(&info, &oad);
- }
- if (unw_ret > 0) {
- if (call_trace == 1 && !arch_unw_user_mode(&info)) {
- ops->warning_symbol(data,
- "DWARF2 unwinder stuck at %s",
- UNW_PC(&info));
- if ((long)UNW_SP(&info) < 0) {
- MSG("Leftover inexact backtrace:");
- stack = (unsigned long *)UNW_SP(&info);
- if (!stack)
- goto out;
- } else
- MSG("Full inexact backtrace again:");
- } else if (call_trace >= 1)
- goto out;
- else
- MSG("Full inexact backtrace again:");
- } else
- MSG("Inexact backtrace:");
- }
if (!stack) {
unsigned long dummy;
stack = &dummy;
@@ -383,10 +319,9 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
/*
* This handles the process stack:
*/
- tinfo = current_thread_info();
+ tinfo = task_thread_info(tsk);
HANDLE_STACK (valid_stack_ptr(tinfo, stack));
#undef HANDLE_STACK
-out:
put_cpu();
}
EXPORT_SYMBOL(dump_trace);
@@ -524,30 +459,15 @@ bad:
printk("\n");
}
-void handle_BUG(struct pt_regs *regs)
-{
- struct bug_frame f;
- long len;
- const char *prefix = "";
+int is_valid_bugaddr(unsigned long rip)
+{
+ unsigned short ud2;
- if (user_mode(regs))
- return;
- if (__copy_from_user(&f, (const void __user *) regs->rip,
- sizeof(struct bug_frame)))
- return;
- if (f.filename >= 0 ||
- f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
- return;
- len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
- if (len < 0 || len >= PATH_MAX)
- f.filename = (int)(long)"unmapped filename";
- else if (len > 50) {
- f.filename += len - 50;
- prefix = "...";
- }
- printk("----------- [cut here ] --------- [please bite here ] ---------\n");
- printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
-}
+ if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2)))
+ return 0;
+
+ return ud2 == 0x0b0f;
+}
#ifdef CONFIG_BUG
void out_of_line_bug(void)
@@ -627,7 +547,9 @@ void die(const char * str, struct pt_regs * regs, long err)
{
unsigned long flags = oops_begin();
- handle_BUG(regs);
+ if (!user_mode(regs))
+ report_bug(regs->rip);
+
__die(str, regs, err);
oops_end(flags);
do_exit(SIGSEGV);
@@ -1200,21 +1122,3 @@ static int __init kstack_setup(char *s)
return 0;
}
early_param("kstack", kstack_setup);
-
-#ifdef CONFIG_STACK_UNWIND
-static int __init call_trace_setup(char *s)
-{
- if (!s)
- return -EINVAL;
- if (strcmp(s, "old") == 0)
- call_trace = -1;
- else if (strcmp(s, "both") == 0)
- call_trace = 0;
- else if (strcmp(s, "newfallback") == 0)
- call_trace = 1;
- else if (strcmp(s, "new") == 0)
- call_trace = 2;
- return 0;
-}
-early_param("call_trace", call_trace_setup);
-#endif
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 6a1f8f491e5..1e54ddf2338 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -13,6 +13,7 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(phys_startup_64)
jiffies_64 = jiffies;
+_proxy_pda = 0;
PHDRS {
text PT_LOAD FLAGS(5); /* R_E */
data PT_LOAD FLAGS(7); /* RWE */
@@ -51,6 +52,8 @@ SECTIONS
RODATA
+ BUG_TABLE
+
. = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */
/* Data */
.data : AT(ADDR(.data) - LOAD_OFFSET) {
@@ -218,9 +221,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
*(.exitcall.exit)
-#ifndef CONFIG_UNWIND_INFO
*(.eh_frame)
-#endif
}
STABS_DEBUG
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 4a673f5397a..2433d6fc68b 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -225,8 +225,7 @@ out:
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)
+ void __user *newval, size_t newlen)
{
return -ENOSYS;
}
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index c1e69a1f92a..2e74cb0b780 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -34,31 +34,24 @@ config GENERIC_HARDIRQS
bool
default y
+config ARCH_HAS_ILOG2_U32
+ bool
+ default n
+
+config ARCH_HAS_ILOG2_U64
+ bool
+ default n
+
source "init/Kconfig"
menu "Processor type and features"
choice
prompt "Xtensa Processor Configuration"
- default XTENSA_CPU_LINUX_BE
+ default XTENSA_VARIANT_FSF
-config XTENSA_CPU_LINUX_BE
- bool "linux_be"
- ---help---
- The linux_be processor configuration is the baseline Xtensa
- configurations included in this kernel and also used by
- binutils, gcc, and gdb. It contains no TIE, no coprocessors,
- and the following configuration options:
-
- Code Density Option 2 Misc Special Registers
- NSA/NSAU Instructions 128-bit Data Bus Width
- Processor ID 8K, 2-way I and D Caches
- Zero-Overhead Loops 2 Inst Address Break Registers
- Big Endian 2 Data Address Break Registers
- 64 General-Purpose Registers JTAG Interface and Trace Port
- 17 Interrupts MMU w/ TLBs and Autorefill
- 3 Interrupt Levels 8 Autorefill Ways (I/D TLBs)
- 3 Timers Unaligned Exceptions
+config XTENSA_VARIANT_FSF
+ bool "fsf"
endchoice
config MMU
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index 3a3a4c66ef8..95f836db38f 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -11,13 +11,13 @@
# this architecture
# Core configuration.
-# (Use CPU=<xtensa_config> to use another default compiler.)
+# (Use VAR=<xtensa_config> to use another default compiler.)
-cpu-$(CONFIG_XTENSA_CPU_LINUX_BE) := linux_be
-cpu-$(CONFIG_XTENSA_CPU_LINUX_CUSTOM) := linux_custom
+variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf
+variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom
-CPU = $(cpu-y)
-export CPU
+VARIANT = $(variant-y)
+export VARIANT
# Platform configuration
@@ -27,8 +27,6 @@ platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
PLATFORM = $(platform-y)
export PLATFORM
-CPPFLAGS += $(if $(KBUILD_SRC),-I$(srctree)/include/asm-xtensa/)
-CPPFLAGS += -Iinclude/asm
CFLAGS += -pipe -mlongcalls
KBUILD_DEFCONFIG := iss_defconfig
@@ -41,12 +39,12 @@ core-$(CONFIG_EMBEDDED_RAMDISK) += arch/xtensa/boot/ramdisk/
# Test for cross compiling
-ifneq ($(CPU),)
+ifneq ($(VARIANT),)
COMPILE_ARCH = $(shell uname -m)
ifneq ($(COMPILE_ARCH), xtensa)
ifndef CROSS_COMPILE
- CROSS_COMPILE = xtensa_$(CPU)-
+ CROSS_COMPILE = xtensa_$(VARIANT)-
endif
endif
endif
@@ -68,14 +66,13 @@ archinc := include/asm-xtensa
archprepare: $(archinc)/.platform
-# Update machine cpu and platform symlinks if something which affects
+# Update processor variant and platform symlinks if something which affects
# them changed.
$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf
- @echo ' SYMLINK $(archinc)/xtensa/config -> $(archinc)/xtensa/config-$(CPU)'
+ @echo ' SYMLINK $(archinc)/variant -> $(archinc)/variant-$(VARIANT)'
$(Q)mkdir -p $(archinc)
- $(Q)mkdir -p $(archinc)/xtensa
- $(Q)ln -fsn $(srctree)/$(archinc)/xtensa/config-$(CPU) $(archinc)/xtensa/config
+ $(Q)ln -fsn $(srctree)/$(archinc)/variant-$(VARIANT) $(archinc)/variant
@echo ' SYMLINK $(archinc)/platform -> $(archinc)/platform-$(PLATFORM)'
$(Q)ln -fsn $(srctree)/$(archinc)/platform-$(PLATFORM) $(archinc)/platform
@touch $@
@@ -89,7 +86,7 @@ zImage zImage.initrd: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
CLEAN_FILES += arch/xtensa/vmlinux.lds \
- $(archinc)/platform $(archinc)/xtensa/config \
+ $(archinc)/platform $(archinc)/variant \
$(archinc)/.platform
define archhelp
diff --git a/arch/xtensa/boot/boot-elf/bootstrap.S b/arch/xtensa/boot/boot-elf/bootstrap.S
index f857fc760aa..464298bc348 100644
--- a/arch/xtensa/boot/boot-elf/bootstrap.S
+++ b/arch/xtensa/boot/boot-elf/bootstrap.S
@@ -1,7 +1,4 @@
-#include <xtensa/config/specreg.h>
-#include <xtensa/config/core.h>
-
#include <asm/bootparam.h>
diff --git a/arch/xtensa/boot/boot-redboot/bootstrap.S b/arch/xtensa/boot/boot-redboot/bootstrap.S
index ee636b0da81..84848123e2a 100644
--- a/arch/xtensa/boot/boot-redboot/bootstrap.S
+++ b/arch/xtensa/boot/boot-redboot/bootstrap.S
@@ -1,9 +1,7 @@
-
-#define _ASMLANGUAGE
-#include <xtensa/config/specreg.h>
-#include <xtensa/config/core.h>
-#include <xtensa/cacheasm.h>
-
+#include <asm/variant/core.h>
+#include <asm/regs.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
/*
* RB-Data: RedBoot data/bss
* P: Boot-Parameters
@@ -77,8 +75,14 @@ _start:
/* Note: The assembler cannot relax "addi a0, a0, ..." to an
l32r, so we load to a4 first. */
- addi a4, a0, __start - __start_a0
- mov a0, a4
+ # addi a4, a0, __start - __start_a0
+ # mov a0, a4
+
+ movi a4, __start
+ movi a5, __start_a0
+ add a4, a0, a4
+ sub a0, a4, a5
+
movi a4, __start
movi a5, __reloc_end
@@ -106,9 +110,13 @@ _start:
/* We have to flush and invalidate the caches here before we jump. */
#if XCHAL_DCACHE_IS_WRITEBACK
- dcache_writeback_all a5, a6
+
+ ___flush_dcache_all a5 a6
+
#endif
- icache_invalidate_all a5, a6
+
+ ___invalidate_icache_all a5 a6
+ isync
movi a11, _reloc
jx a11
@@ -209,9 +217,14 @@ _reloc:
/* jump to the kernel */
2:
#if XCHAL_DCACHE_IS_WRITEBACK
- dcache_writeback_all a5, a6
+
+ ___flush_dcache_all a5 a6
+
#endif
- icache_invalidate_all a5, a6
+
+ ___invalidate_icache_all a5 a6
+
+ isync
movi a5, __start
movi a3, boot_initrd_start
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
index 802621dd486..f19854035e6 100644
--- a/arch/xtensa/configs/iss_defconfig
+++ b/arch/xtensa/configs/iss_defconfig
@@ -53,11 +53,7 @@ CONFIG_CC_ALIGN_JUMPS=0
#
# Processor type and features
#
-CONFIG_XTENSA_ARCH_LINUX_BE=y
-# CONFIG_XTENSA_ARCH_LINUX_LE is not set
-# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
-# CONFIG_XTENSA_ARCH_S5 is not set
-# CONFIG_XTENSA_CUSTOM is not set
+CONFIG_XTENSA_VARIANT_FSF=y
CONFIG_MMU=y
# CONFIG_XTENSA_UNALIGNED_USER is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index d573017a5dd..71f733c4f66 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds
obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
- setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o \
+ setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \
pci-dma.o
## windowspill.o
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
index a4956578a24..33d6e9d2e83 100644
--- a/arch/xtensa/kernel/align.S
+++ b/arch/xtensa/kernel/align.S
@@ -16,14 +16,9 @@
*/
#include <linux/linkage.h>
-#include <asm/ptrace.h>
-#include <asm/ptrace.h>
#include <asm/current.h>
#include <asm/asm-offsets.h>
-#include <asm/pgtable.h>
#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/thread_info.h>
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
@@ -216,7 +211,7 @@ ENTRY(fast_unaligned)
extui a5, a4, INSN_OP0, 4 # get insn.op0 nibble
-#if XCHAL_HAVE_NARROW
+#if XCHAL_HAVE_DENSITY
_beqi a5, OP0_L32I_N, .Lload # L32I.N, jump
addi a6, a5, -OP0_S32I_N
_beqz a6, .Lstore # S32I.N, do a store
@@ -251,7 +246,7 @@ ENTRY(fast_unaligned)
#endif
__src_b a3, a5, a6 # a3 has the data word
-#if XCHAL_HAVE_NARROW
+#if XCHAL_HAVE_DENSITY
addi a7, a7, 2 # increment PC (assume 16-bit insn)
extui a5, a4, INSN_OP0, 4
@@ -279,14 +274,14 @@ ENTRY(fast_unaligned)
1:
-#if XCHAL_HAVE_LOOP
- rsr a3, LEND # check if we reached LEND
- bne a7, a3, 1f
- rsr a3, LCOUNT # and LCOUNT != 0
- beqz a3, 1f
- addi a3, a3, -1 # decrement LCOUNT and set
+#if XCHAL_HAVE_LOOPS
+ rsr a5, LEND # check if we reached LEND
+ bne a7, a5, 1f
+ rsr a5, LCOUNT # and LCOUNT != 0
+ beqz a5, 1f
+ addi a5, a5, -1 # decrement LCOUNT and set
rsr a7, LBEG # set PC to LBEGIN
- wsr a3, LCOUNT
+ wsr a5, LCOUNT
#endif
1: wsr a7, EPC_1 # skip load instruction
@@ -336,7 +331,7 @@ ENTRY(fast_unaligned)
movi a6, 0 # mask: ffffffff:00000000
-#if XCHAL_HAVE_NARROW
+#if XCHAL_HAVE_DENSITY
addi a7, a7, 2 # incr. PC,assume 16-bit instruction
extui a5, a4, INSN_OP0, 4 # extract OP0
@@ -359,14 +354,14 @@ ENTRY(fast_unaligned)
/* Get memory address */
1:
-#if XCHAL_HAVE_LOOP
- rsr a3, LEND # check if we reached LEND
- bne a7, a3, 1f
- rsr a3, LCOUNT # and LCOUNT != 0
- beqz a3, 1f
- addi a3, a3, -1 # decrement LCOUNT and set
+#if XCHAL_HAVE_LOOPS
+ rsr a4, LEND # check if we reached LEND
+ bne a7, a4, 1f
+ rsr a4, LCOUNT # and LCOUNT != 0
+ beqz a4, 1f
+ addi a4, a4, -1 # decrement LCOUNT and set
rsr a7, LBEG # set PC to LBEGIN
- wsr a3, LCOUNT
+ wsr a4, LCOUNT
#endif
1: wsr a7, EPC_1 # skip store instruction
@@ -416,6 +411,7 @@ ENTRY(fast_unaligned)
/* Restore working register */
+ l32i a8, a2, PT_AREG8
l32i a7, a2, PT_AREG7
l32i a6, a2, PT_AREG6
l32i a5, a2, PT_AREG5
@@ -446,7 +442,7 @@ ENTRY(fast_unaligned)
mov a1, a2
rsr a0, PS
- bbsi.l a2, PS_UM_SHIFT, 1f # jump if user mode
+ bbsi.l a2, PS_UM_BIT, 1f # jump if user mode
movi a0, _kernel_exception
jx a0
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 7cd1d7f8f60..b256cfbef34 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -87,6 +87,11 @@ int main(void)
DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
BLANK();
DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
+
+ /* constants */
+ DEFINE(_CLONE_VM, CLONE_VM);
+ DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);
+
return 0;
}
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index cf5a93fb6a2..01bcb9fcfcb 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -90,7 +90,6 @@ ENTRY(enable_coprocessor)
rsync
retw
-#endif
ENTRY(save_coprocessor_extra)
entry sp, 16
@@ -197,4 +196,5 @@ _xtensa_reginfo_tables:
XCHAL_CP7_SA_CONTENTS_LIBDB
.word 0xFC000000 /* invalid register number,marks end of table*/
_xtensa_reginfo_table_end:
+#endif
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 89e409e9e0d..9e271ba009b 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -24,7 +24,7 @@
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/signal.h>
-#include <xtensa/coreasm.h>
+#include <asm/tlbflush.h>
/* Unimplemented features. */
@@ -364,7 +364,7 @@ common_exception:
movi a2, 1
extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0]
moveqz a3, a2, a0 # a3 = 1 iff interrupt exception
- movi a2, PS_WOE_MASK
+ movi a2, 1 << PS_WOE_BIT
or a3, a3, a2
rsr a0, EXCCAUSE
xsr a3, PS
@@ -399,7 +399,7 @@ common_exception_return:
/* Jump if we are returning from kernel exceptions. */
1: l32i a3, a1, PT_PS
- _bbsi.l a3, PS_UM_SHIFT, 2f
+ _bbsi.l a3, PS_UM_BIT, 2f
j kernel_exception_exit
/* Specific to a user exception exit:
@@ -422,7 +422,7 @@ common_exception_return:
* (Hint: There is only one user exception frame on stack)
*/
- movi a3, PS_WOE_MASK
+ movi a3, 1 << PS_WOE_BIT
_bbsi.l a4, TIF_NEED_RESCHED, 3f
_bbci.l a4, TIF_SIGPENDING, 4f
@@ -694,7 +694,7 @@ common_exception_exit:
ENTRY(debug_exception)
rsr a0, EPS + XCHAL_DEBUGLEVEL
- bbsi.l a0, PS_EXCM_SHIFT, 1f # exception mode
+ bbsi.l a0, PS_EXCM_BIT, 1f # exception mode
/* Set EPC_1 and EXCCAUSE */
@@ -707,7 +707,7 @@ ENTRY(debug_exception)
/* Restore PS to the value before the debug exc but with PS.EXCM set.*/
- movi a2, 1 << PS_EXCM_SHIFT
+ movi a2, 1 << PS_EXCM_BIT
or a2, a0, a2
movi a0, debug_exception # restore a3, debug jump vector
wsr a2, PS
@@ -715,7 +715,7 @@ ENTRY(debug_exception)
/* Switch to kernel/user stack, restore jump vector, and save a0 */
- bbsi.l a2, PS_UM_SHIFT, 2f # jump if user mode
+ bbsi.l a2, PS_UM_BIT, 2f # jump if user mode
addi a2, a1, -16-PT_SIZE # assume kernel stack
s32i a0, a2, PT_AREG0
@@ -778,7 +778,7 @@ ENTRY(unrecoverable_exception)
wsr a1, WINDOWBASE
rsync
- movi a1, PS_WOE_MASK | 1
+ movi a1, (1 << PS_WOE_BIT) | 1
wsr a1, PS
rsync
@@ -1004,13 +1004,10 @@ ENTRY(fast_syscall_kernel)
rsr a0, DEPC # get syscall-nr
_beqz a0, fast_syscall_spill_registers
-
- addi a0, a0, -__NR_sysxtensa
- _beqz a0, fast_syscall_sysxtensa
+ _beqi a0, __NR_xtensa, fast_syscall_xtensa
j kernel_exception
-
ENTRY(fast_syscall_user)
/* Skip syscall. */
@@ -1024,9 +1021,7 @@ ENTRY(fast_syscall_user)
rsr a0, DEPC # get syscall-nr
_beqz a0, fast_syscall_spill_registers
-
- addi a0, a0, -__NR_sysxtensa
- _beqz a0, fast_syscall_sysxtensa
+ _beqi a0, __NR_xtensa, fast_syscall_xtensa
j user_exception
@@ -1047,18 +1042,19 @@ ENTRY(fast_syscall_unrecoverable)
/*
* sysxtensa syscall handler
*
- * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused);
- * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused);
- * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
- * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
- * a2 a6 a3 a4 a5
+ * int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ * a2 a6 a3 a4 a5
*
* Entry condition:
*
- * a0: trashed, original value saved on stack (PT_AREG0)
+ * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0)
* a1: a1
- * a2: new stack pointer, original in DEPC
- * a3: dispatch table
+ * a2: new stack pointer, original in a0 and DEPC
+ * a3: dispatch table, original in excsave_1
+ * a4..a15: unchanged
* depc: a2, original value saved on stack (PT_DEPC)
* excsave_1: a3
*
@@ -1091,59 +1087,62 @@ ENTRY(fast_syscall_unrecoverable)
#define CATCH \
67:
-ENTRY(fast_syscall_sysxtensa)
-
- _beqz a6, 1f
- _blti a6, SYSXTENSA_COUNT, 2f
+ENTRY(fast_syscall_xtensa)
-1: j user_exception
-
-2: xsr a3, EXCSAVE_1 # restore a3, excsave1
- s32i a7, a2, PT_AREG7
+ xsr a3, EXCSAVE_1 # restore a3, excsave1
+ s32i a7, a2, PT_AREG7 # we need an additional register
movi a7, 4 # sizeof(unsigned int)
- access_ok a0, a3, a7, a2, .Leac
+ access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
- _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset
- _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
- _beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd
+ addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1
+ _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill
+ _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
- /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */
+ /* Fall through for ATOMIC_CMP_SWP. */
.Lswp: /* Atomic compare and swap */
-TRY l32i a7, a3, 0 # read old value
- bne a7, a4, 1f # same as old value? jump
- s32i a5, a3, 0 # different, modify value
- movi a7, 1 # and return 1
- j .Lret
-
-1: movi a7, 0 # same values: return 0
- j .Lret
-
-.Ladd: /* Atomic add */
-.Lexg: /* Atomic (exchange) add */
+TRY l32i a0, a3, 0 # read old value
+ bne a0, a4, 1f # same as old value? jump
+TRY s32i a5, a3, 0 # different, modify value
+ l32i a7, a2, PT_AREG7 # restore a7
+ l32i a0, a2, PT_AREG0 # restore a0
+ movi a2, 1 # and return 1
+ addi a6, a6, 1 # restore a6 (really necessary?)
+ rfe
-TRY l32i a7, a3, 0
- add a4, a4, a7
- s32i a4, a3, 0
- j .Lret
+1: l32i a7, a2, PT_AREG7 # restore a7
+ l32i a0, a2, PT_AREG0 # restore a0
+ movi a2, 0 # return 0 (note that we cannot set
+ addi a6, a6, 1 # restore a6 (really necessary?)
+ rfe
-.Lset: /* Atomic set */
+.Lnswp: /* Atomic set, add, and exg_add. */
-TRY l32i a7, a3, 0 # read old value as return value
- s32i a4, a3, 0 # write new value
+TRY l32i a7, a3, 0 # orig
+ add a0, a4, a7 # + arg
+ moveqz a0, a4, a6 # set
+TRY s32i a0, a3, 0 # write new value
-.Lret: mov a0, a2
+ mov a0, a2
mov a2, a7
- l32i a7, a0, PT_AREG7
- l32i a3, a0, PT_AREG3
- l32i a0, a0, PT_AREG0
+ l32i a7, a0, PT_AREG7 # restore a7
+ l32i a0, a0, PT_AREG0 # restore a0
+ addi a6, a6, 1 # restore a6 (really necessary?)
rfe
CATCH
-.Leac: movi a7, -EFAULT
- j .Lret
+.Leac: l32i a7, a2, PT_AREG7 # restore a7
+ l32i a0, a2, PT_AREG0 # restore a0
+ movi a2, -EFAULT
+ rfe
+
+.Lill: l32i a7, a2, PT_AREG0 # restore a7
+ l32i a0, a2, PT_AREG0 # restore a0
+ movi a2, -EINVAL
+ rfe
+
@@ -1491,7 +1490,7 @@ ENTRY(_spill_registers)
*/
rsr a0, PS
- _bbci.l a0, PS_UM_SHIFT, 1f
+ _bbci.l a0, PS_UM_BIT, 1f
/* User space: Setup a dummy frame and kill application.
* Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
@@ -1510,7 +1509,7 @@ ENTRY(_spill_registers)
l32i a1, a3, EXC_TABLE_KSTK
wsr a3, EXCSAVE_1
- movi a4, PS_WOE_MASK | 1
+ movi a4, (1 << PS_WOE_BIT) | 1
wsr a4, PS
rsync
@@ -1612,7 +1611,7 @@ ENTRY(fast_second_level_miss)
rsr a1, PTEVADDR
srli a1, a1, PAGE_SHIFT
slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK
- addi a1, a1, DTLB_WAY_PGTABLE # ... + way_number
+ addi a1, a1, DTLB_WAY_PGD # ... + way_number
wdtlb a0, a1
dsync
@@ -1654,7 +1653,7 @@ ENTRY(fast_second_level_miss)
mov a1, a2
rsr a2, PS
- bbsi.l a2, PS_UM_SHIFT, 1f
+ bbsi.l a2, PS_UM_BIT, 1f
j _kernel_exception
1: j _user_exception
@@ -1753,7 +1752,7 @@ ENTRY(fast_store_prohibited)
mov a1, a2
rsr a2, PS
- bbsi.l a2, PS_UM_SHIFT, 1f
+ bbsi.l a2, PS_UM_BIT, 1f
j _kernel_exception
1: j _user_exception
@@ -1907,6 +1906,103 @@ ENTRY(fast_coprocessor)
#endif /* XCHAL_EXTRA_SA_SIZE */
/*
+ * System Calls.
+ *
+ * void system_call (struct pt_regs* regs, int exccause)
+ * a2 a3
+ */
+
+ENTRY(system_call)
+ entry a1, 32
+
+ /* regs->syscall = regs->areg[2] */
+
+ l32i a3, a2, PT_AREG2
+ mov a6, a2
+ movi a4, do_syscall_trace_enter
+ s32i a3, a2, PT_SYSCALL
+ callx4 a4
+
+ /* syscall = sys_call_table[syscall_nr] */
+
+ movi a4, sys_call_table;
+ movi a5, __NR_syscall_count
+ movi a6, -ENOSYS
+ bgeu a3, a5, 1f
+
+ addx4 a4, a3, a4
+ l32i a4, a4, 0
+ movi a5, sys_ni_syscall;
+ beq a4, a5, 1f
+
+ /* Load args: arg0 - arg5 are passed via regs. */
+
+ l32i a6, a2, PT_AREG6
+ l32i a7, a2, PT_AREG3
+ l32i a8, a2, PT_AREG4
+ l32i a9, a2, PT_AREG5
+ l32i a10, a2, PT_AREG8
+ l32i a11, a2, PT_AREG9
+
+ /* Pass one additional argument to the syscall: pt_regs (on stack) */
+ s32i a2, a1, 0
+
+ callx4 a4
+
+1: /* regs->areg[2] = return_value */
+
+ s32i a6, a2, PT_AREG2
+ movi a4, do_syscall_trace_leave
+ mov a6, a2
+ callx4 a4
+ retw
+
+
+/*
+ * Create a kernel thread
+ *
+ * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+ * a2 a2 a3 a4
+ */
+
+ENTRY(kernel_thread)
+ entry a1, 16
+
+ mov a5, a2 # preserve fn over syscall
+ mov a7, a3 # preserve args over syscall
+
+ movi a3, _CLONE_VM | _CLONE_UNTRACED
+ movi a2, __NR_clone
+ or a6, a4, a3 # arg0: flags
+ mov a3, a1 # arg1: sp
+ syscall
+
+ beq a3, a1, 1f # branch if parent
+ mov a6, a7 # args
+ callx4 a5 # fn(args)
+
+ movi a2, __NR_exit
+ syscall # return value of fn(args) still in a6
+
+1: retw
+
+/*
+ * Do a system call from kernel instead of calling sys_execve, so we end up
+ * with proper pt_regs.
+ *
+ * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
+ * a2 a2 a3 a4
+ */
+
+ENTRY(kernel_execve)
+ entry a1, 16
+ mov a6, a2 # arg0 is in a6
+ movi a2, __NR_execve
+ syscall
+
+ retw
+
+/*
* Task switch.
*
* struct task* _switch_to (struct task* prev, struct task* next)
@@ -1924,7 +2020,7 @@ ENTRY(_switch_to)
/* Disable ints while we manipulate the stack pointer; spill regs. */
- movi a5, PS_EXCM_MASK | LOCKLEVEL
+ movi a5, (1 << PS_EXCM_BIT) | LOCKLEVEL
xsr a5, PS
rsr a3, EXCSAVE_1
rsync
@@ -1964,33 +2060,9 @@ ENTRY(ret_from_fork)
movi a4, schedule_tail
callx4 a4
- movi a4, do_syscall_trace
+ movi a4, do_syscall_trace_leave
+ mov a6, a1
callx4 a4
j common_exception_return
-
-
-/*
- * Table of syscalls
- */
-
-.data
-.align 4
-.global sys_call_table
-sys_call_table:
-
-#define SYSCALL(call, narg) .word call
-#include "syscalls.h"
-
-/*
- * Number of arguments of each syscall
- */
-
-.global sys_narg_table
-sys_narg_table:
-
-#undef SYSCALL
-#define SYSCALL(call, narg) .byte narg
-#include "syscalls.h"
-
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index c07cb252299..ea89910efa4 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -15,9 +15,9 @@
* Kevin Chea
*/
-#include <xtensa/cacheasm.h>
#include <asm/processor.h>
#include <asm/page.h>
+#include <asm/cacheasm.h>
/*
* This module contains the entry code for kernel images. It performs the
@@ -32,13 +32,6 @@
*
*/
- .macro iterate from, to , cmd
- .ifeq ((\to - \from) & ~0xfff)
- \cmd \from
- iterate "(\from+1)", \to, \cmd
- .endif
- .endm
-
/*
* _start
*
@@ -64,7 +57,7 @@ _startup:
/* Disable interrupts and exceptions. */
- movi a0, XCHAL_PS_EXCM_MASK
+ movi a0, LOCKLEVEL
wsr a0, PS
/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
@@ -91,11 +84,11 @@ _startup:
movi a1, 15
wsr a0, ICOUNTLEVEL
- .macro reset_dbreak num
- wsr a0, DBREAKC + \num
- .endm
-
- iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak
+ .set _index, 0
+ .rept XCHAL_NUM_DBREAK - 1
+ wsr a0, DBREAKC + _index
+ .set _index, _index + 1
+ .endr
#endif
/* Clear CCOUNT (not really necessary, but nice) */
@@ -110,10 +103,11 @@ _startup:
/* Disable all timers. */
- .macro reset_timer num
- wsr a0, CCOMPARE_0 + \num
- .endm
- iterate 0, XCHAL_NUM_TIMERS-1, reset_timer
+ .set _index, 0
+ .rept XCHAL_NUM_TIMERS - 1
+ wsr a0, CCOMPARE + _index
+ .set _index, _index + 1
+ .endr
/* Interrupt initialization. */
@@ -139,12 +133,21 @@ _startup:
rsync
/* Initialize the caches.
- * Does not include flushing writeback d-cache.
- * a6, a7 are just working registers (clobbered).
+ * a2, a3 are just working registers (clobbered).
*/
- icache_reset a2, a3
- dcache_reset a2, a3
+#if XCHAL_DCACHE_LINE_LOCKABLE
+ ___unlock_dcache_all a2 a3
+#endif
+
+#if XCHAL_ICACHE_LINE_LOCKABLE
+ ___unlock_icache_all a2 a3
+#endif
+
+ ___invalidate_dcache_all a2 a3
+ ___invalidate_icache_all a2 a3
+
+ isync
/* Unpack data sections
*
@@ -181,9 +184,9 @@ _startup:
movi a2, _bss_start # start of BSS
movi a3, _bss_end # end of BSS
-1: addi a2, a2, 4
+ __loopt a2, a3, a4, 2
s32i a0, a2, 0
- blt a2, a3, 1b
+ __endla a2, a4, 4
#if XCHAL_DCACHE_IS_WRITEBACK
@@ -191,7 +194,7 @@ _startup:
* instructions/data are available.
*/
- dcache_writeback_all a2, a3
+ ___flush_dcache_all a2 a3
#endif
/* Setup stack and enable window exceptions (keep irqs disabled) */
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index 1cf744ee095..c9ea73b7031 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -4,7 +4,7 @@
* Xtensa built-in interrupt controller and some generic functions copied
* from i386.
*
- * Copyright (C) 2002 - 2005 Tensilica, Inc.
+ * Copyright (C) 2002 - 2006 Tensilica, Inc.
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
*
*
@@ -22,11 +22,6 @@
#include <asm/uaccess.h>
#include <asm/platform.h>
-static void enable_xtensa_irq(unsigned int irq);
-static void disable_xtensa_irq(unsigned int irq);
-static void mask_and_ack_xtensa(unsigned int irq);
-static void end_xtensa_irq(unsigned int irq);
-
static unsigned int cached_irq_mask;
atomic_t irq_err_count;
@@ -46,8 +41,16 @@ void ack_bad_irq(unsigned int irq)
* handlers).
*/
-unsigned int do_IRQ(int irq, struct pt_regs *regs)
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
{
+ struct pt_regs *old_regs = set_irq_regs(regs);
+ struct irq_desc *desc = irq_desc + irq;
+
+ if (irq >= NR_IRQS) {
+ printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+ __FUNCTION__, irq);
+ }
+
irq_enter();
#ifdef CONFIG_DEBUG_STACKOVERFLOW
@@ -63,12 +66,10 @@ unsigned int do_IRQ(int irq, struct pt_regs *regs)
sp - sizeof(struct thread_info));
}
#endif
-
- __do_IRQ(irq, regs);
+ desc->handle_irq(irq, desc);
irq_exit();
-
- return 1;
+ set_irq_regs(old_regs);
}
/*
@@ -118,72 +119,68 @@ skip:
}
return 0;
}
-/* shutdown is same as "disable" */
-#define shutdown_xtensa_irq disable_xtensa_irq
-static unsigned int startup_xtensa_irq(unsigned int irq)
-{
- enable_xtensa_irq(irq);
- return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type xtensa_irq_type = {
- "Xtensa-IRQ",
- startup_xtensa_irq,
- shutdown_xtensa_irq,
- enable_xtensa_irq,
- disable_xtensa_irq,
- mask_and_ack_xtensa,
- end_xtensa_irq
-};
-
-static inline void mask_irq(unsigned int irq)
+static void xtensa_irq_mask(unsigned int irq)
{
cached_irq_mask &= ~(1 << irq);
set_sr (cached_irq_mask, INTENABLE);
}
-static inline void unmask_irq(unsigned int irq)
+static void xtensa_irq_unmask(unsigned int irq)
{
cached_irq_mask |= 1 << irq;
set_sr (cached_irq_mask, INTENABLE);
}
-static void disable_xtensa_irq(unsigned int irq)
+static void xtensa_irq_ack(unsigned int irq)
{
- unsigned long flags;
- local_save_flags(flags);
- mask_irq(irq);
- local_irq_restore(flags);
+ set_sr(1 << irq, INTCLEAR);
}
-static void enable_xtensa_irq(unsigned int irq)
+static int xtensa_irq_retrigger(unsigned int irq)
{
- unsigned long flags;
- local_save_flags(flags);
- unmask_irq(irq);
- local_irq_restore(flags);
-}
-
-static void mask_and_ack_xtensa(unsigned int irq)
-{
- disable_xtensa_irq(irq);
+ set_sr (1 << irq, INTSET);
+ return 1;
}
-static void end_xtensa_irq(unsigned int irq)
-{
- enable_xtensa_irq(irq);
-}
+static struct irq_chip xtensa_irq_chip = {
+ .name = "xtensa",
+ .mask = xtensa_irq_mask,
+ .unmask = xtensa_irq_unmask,
+ .ack = xtensa_irq_ack,
+ .retrigger = xtensa_irq_retrigger,
+};
void __init init_IRQ(void)
{
- int i;
+ int index;
- for (i=0; i < XTENSA_NR_IRQS; i++)
- irq_desc[i].chip = &xtensa_irq_type;
+ for (index = 0; index < XTENSA_NR_IRQS; index++) {
+ int mask = 1 << index;
- cached_irq_mask = 0;
+ if (mask & XCHAL_INTTYPE_MASK_SOFTWARE)
+ set_irq_chip_and_handler(index, &xtensa_irq_chip,
+ handle_simple_irq);
- platform_init_irq();
+ else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE)
+ set_irq_chip_and_handler(index, &xtensa_irq_chip,
+ handle_edge_irq);
+
+ else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL)
+ set_irq_chip_and_handler(index, &xtensa_irq_chip,
+ handle_level_irq);
+
+ else if (mask & XCHAL_INTTYPE_MASK_TIMER)
+ set_irq_chip_and_handler(index, &xtensa_irq_chip,
+ handle_edge_irq);
+
+ else /* XCHAL_INTTYPE_MASK_WRITE_ERROR */
+ /* XCHAL_INTTYPE_MASK_NMI */
+
+ set_irq_chip_and_handler(index, &xtensa_irq_chip,
+ handle_level_irq);
+ }
+
+ cached_irq_mask = 0;
}
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index 6648fa9d919..ca76f071666 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -1,5 +1,5 @@
/*
- * arch/xtensa/kernel/pci-dma.c
+ * arch/xtensa/pci-dma.c
*
* DMA coherent memory allocation.
*
@@ -29,28 +29,48 @@
*/
void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
{
- void *ret;
+ unsigned long ret;
+ unsigned long uncached = 0;
/* ignore region speicifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
- if (dev == NULL || (*dev->dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, get_order(size));
+ flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
- if (ret != NULL) {
- memset(ret, 0, size);
- *handle = virt_to_bus(ret);
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ flag |= GFP_DMA;
+ ret = (unsigned long)__get_free_pages(flag, get_order(size));
+
+ if (ret == 0)
+ return NULL;
+
+ /* We currently don't support coherent memory outside KSEG */
+
+ if (ret < XCHAL_KSEG_CACHED_VADDR
+ || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
+ BUG();
+
+
+ if (ret != 0) {
+ memset((void*) ret, 0, size);
+ uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;
+ *handle = virt_to_bus((void*)ret);
+ __flush_invalidate_dcache_range(ret, size);
}
- return (void*) BYPASS_ADDR((unsigned long)ret);
+
+ return (void*)uncached;
}
void dma_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
+ long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+
+ if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
+ BUG();
+
+ free_pages(addr, get_order(size));
}
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index a7c4178c2a8..795bd5ac6f4 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -1,4 +1,3 @@
-// TODO verify coprocessor handling
/*
* arch/xtensa/kernel/process.c
*
@@ -43,7 +42,7 @@
#include <asm/irq.h>
#include <asm/atomic.h>
#include <asm/asm-offsets.h>
-#include <asm/coprocessor.h>
+#include <asm/regs.h>
extern void ret_from_fork(void);
@@ -67,25 +66,6 @@ void (*pm_power_off)(void) = NULL;
EXPORT_SYMBOL(pm_power_off);
-#if XCHAL_CP_NUM > 0
-
-/*
- * Coprocessor ownership.
- */
-
-coprocessor_info_t coprocessor_info[] = {
- { 0, XTENSA_CPE_CP0_OFFSET },
- { 0, XTENSA_CPE_CP1_OFFSET },
- { 0, XTENSA_CPE_CP2_OFFSET },
- { 0, XTENSA_CPE_CP3_OFFSET },
- { 0, XTENSA_CPE_CP4_OFFSET },
- { 0, XTENSA_CPE_CP5_OFFSET },
- { 0, XTENSA_CPE_CP6_OFFSET },
- { 0, XTENSA_CPE_CP7_OFFSET },
-};
-
-#endif
-
/*
* Powermanagement idle function, if any is provided by the platform.
*/
@@ -110,12 +90,10 @@ void cpu_idle(void)
void exit_thread(void)
{
- release_coprocessors(current); /* Empty macro if no CPs are defined */
}
void flush_thread(void)
{
- release_coprocessors(current); /* Empty macro if no CPs are defined */
}
/*
@@ -183,36 +161,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
/*
- * Create a kernel thread
- */
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
- long retval;
- __asm__ __volatile__
- ("mov a5, %4\n\t" /* preserve fn in a5 */
- "mov a6, %3\n\t" /* preserve and setup arg in a6 */
- "movi a2, %1\n\t" /* load __NR_clone for syscall*/
- "mov a3, sp\n\t" /* sp check and sys_clone */
- "mov a4, %5\n\t" /* load flags for syscall */
- "syscall\n\t"
- "beq a3, sp, 1f\n\t" /* branch if parent */
- "callx4 a5\n\t" /* call fn */
- "movi a2, %2\n\t" /* load __NR_exit for syscall */
- "mov a3, a6\n\t" /* load fn return value */
- "syscall\n"
- "1:\n\t"
- "mov %0, a2\n\t" /* parent returns zero */
- :"=r" (retval)
- :"i" (__NR_clone), "i" (__NR_exit),
- "r" (arg), "r" (fn),
- "r" (flags | CLONE_VM)
- : "a2", "a3", "a4", "a5", "a6" );
- return retval;
-}
-
-
-/*
* These bracket the sleeping functions..
*/
@@ -275,7 +223,7 @@ void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
*/
elfregs->pc = regs->pc;
- elfregs->ps = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+ elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT));
elfregs->exccause = regs->exccause;
elfregs->excvaddr = regs->excvaddr;
elfregs->windowbase = regs->windowbase;
@@ -325,7 +273,7 @@ void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
*/
regs->pc = elfregs->pc;
- regs->ps = (elfregs->ps | XCHAL_PS_EXCM_MASK);
+ regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT));
regs->exccause = elfregs->exccause;
regs->excvaddr = elfregs->excvaddr;
regs->windowbase = elfregs->windowbase;
@@ -459,16 +407,7 @@ int do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
int
dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r)
{
-/* see asm/coprocessor.h for this magic number 16 */
-#if XTENSA_CP_EXTRA_SIZE > 16
- do_save_fpregs (r, regs, task);
-
- /* For now, bit 16 means some extra state may be present: */
-// FIXME!! need to track to return more accurate mask
- return 0x10000 | XCHAL_CP_MASK;
-#else
return 0; /* no coprocessors active on this processor */
-#endif
}
/*
@@ -483,3 +422,44 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
{
return dump_task_fpu(regs, current, r);
}
+
+asmlinkage
+long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
+ void __user *parent_tid, void *child_tls,
+ void __user *child_tid, long a5,
+ struct pt_regs *regs)
+{
+ if (!newsp)
+ newsp = regs->areg[1];
+ return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+}
+
+/*
+ * * xtensa_execve() executes a new program.
+ * */
+
+asmlinkage
+long xtensa_execve(char __user *name, char __user * __user *argv,
+ char __user * __user *envp,
+ long a3, long a4, long a5,
+ struct pt_regs *regs)
+{
+ long error;
+ char * filename;
+
+ filename = getname(name);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ // FIXME: release coprocessor??
+ error = do_execve(filename, argv, envp, regs);
+ if (error == 0) {
+ task_lock(current);
+ current->ptrace &= ~PT_DTRACE;
+ task_unlock(current);
+ }
+ putname(filename);
+out:
+ return error;
+}
+
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 9aea23cc0dc..8b6d3d0623b 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -96,7 +96,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Note: PS.EXCM is not set while user task is running;
* its being set in regs is for exception handling
* convenience. */
- tmp = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+ tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
break;
case REG_WB:
tmp = regs->windowbase;
@@ -332,12 +332,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
void do_syscall_trace(void)
{
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
-
- if (!(current->ptrace & PT_PTRACED))
- return;
-
/*
* The 0x80 provides a way for the tracing parent to distinguish
* between a syscall stop and SIGTRAP delivery
@@ -354,3 +348,23 @@ void do_syscall_trace(void)
current->exit_code = 0;
}
}
+
+void do_syscall_trace_enter(struct pt_regs *regs)
+{
+ if (test_thread_flag(TIF_SYSCALL_TRACE)
+ && (current->ptrace & PT_PTRACED))
+ do_syscall_trace();
+
+#if 0
+ if (unlikely(current->audit_context))
+ audit_syscall_entry(current, AUDIT_ARCH_XTENSA..);
+#endif
+}
+
+void do_syscall_trace_leave(struct pt_regs *regs)
+{
+ if ((test_thread_flag(TIF_SYSCALL_TRACE))
+ && (current->ptrace & PT_PTRACED))
+ do_syscall_trace();
+}
+
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index c99ab72b41b..b6374c09de2 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -42,8 +42,6 @@
#include <asm/page.h>
#include <asm/setup.h>
-#include <xtensa/config/system.h>
-
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
#endif
@@ -336,7 +334,7 @@ c_show(struct seq_file *f, void *slot)
/* high-level stuff */
seq_printf(f,"processor\t: 0\n"
"vendor_id\t: Tensilica\n"
- "model\t\t: Xtensa " XCHAL_HW_RELEASE_NAME "\n"
+ "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
"core ID\t\t: " XCHAL_CORE_ID "\n"
"build ID\t: 0x%x\n"
"byte order\t: %s\n"
@@ -420,25 +418,6 @@ c_show(struct seq_file *f, void *slot)
XCHAL_NUM_TIMERS,
XCHAL_DEBUGLEVEL);
- /* Coprocessors */
-#if XCHAL_HAVE_CP
- seq_printf(f, "coprocessors\t: %d\n", XCHAL_CP_NUM);
-#else
- seq_printf(f, "coprocessors\t: none\n");
-#endif
-
- /* {I,D}{RAM,ROM} and XLMI */
- seq_printf(f,"inst ROMs\t: %d\n"
- "inst RAMs\t: %d\n"
- "data ROMs\t: %d\n"
- "data RAMs\t: %d\n"
- "XLMI ports\t: %d\n",
- XCHAL_NUM_IROM,
- XCHAL_NUM_IRAM,
- XCHAL_NUM_DROM,
- XCHAL_NUM_DRAM,
- XCHAL_NUM_XLMI);
-
/* Cache */
seq_printf(f,"icache line size: %d\n"
"icache ways\t: %d\n"
@@ -466,24 +445,6 @@ c_show(struct seq_file *f, void *slot)
XCHAL_DCACHE_WAYS,
XCHAL_DCACHE_SIZE);
- /* MMU */
- seq_printf(f,"ASID bits\t: %d\n"
- "ASID invalid\t: %d\n"
- "ASID kernel\t: %d\n"
- "rings\t\t: %d\n"
- "itlb ways\t: %d\n"
- "itlb AR ways\t: %d\n"
- "dtlb ways\t: %d\n"
- "dtlb AR ways\t: %d\n",
- XCHAL_MMU_ASID_BITS,
- XCHAL_MMU_ASID_INVALID,
- XCHAL_MMU_ASID_KERNEL,
- XCHAL_MMU_RINGS,
- XCHAL_ITLB_WAYS,
- XCHAL_ITLB_ARF_WAYS,
- XCHAL_DTLB_WAYS,
- XCHAL_DTLB_ARF_WAYS);
-
return 0;
}
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index c494f0826fc..c6d9880a4cd 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -12,8 +12,8 @@
*
*/
-#include <xtensa/config/core.h>
-#include <xtensa/hal.h>
+#include <asm/variant/core.h>
+#include <asm/coprocessor.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -46,7 +46,7 @@ extern struct task_struct *coproc_owners[];
* Atomically swap in the new signal mask, and wait for a signal.
*/
-int sys_sigsuspend(struct pt_regs *regs)
+int xtensa_sigsuspend(struct pt_regs *regs)
{
old_sigset_t mask = (old_sigset_t) regs->areg[3];
sigset_t saveset;
@@ -68,7 +68,7 @@ int sys_sigsuspend(struct pt_regs *regs)
}
asmlinkage int
-sys_rt_sigsuspend(struct pt_regs *regs)
+xtensa_rt_sigsuspend(struct pt_regs *regs)
{
sigset_t *unewset = (sigset_t *) regs->areg[4];
size_t sigsetsize = (size_t) regs->areg[3];
@@ -96,7 +96,7 @@ sys_rt_sigsuspend(struct pt_regs *regs)
}
asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
+xtensa_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact)
{
struct k_sigaction new_ka, old_ka;
@@ -128,7 +128,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
}
asmlinkage int
-sys_sigaltstack(struct pt_regs *regs)
+xtensa_sigaltstack(struct pt_regs *regs)
{
const stack_t *uss = (stack_t *) regs->areg[4];
stack_t *uoss = (stack_t *) regs->areg[3];
@@ -216,8 +216,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
* handler, or the user mode value doesn't matter (e.g. PS.OWB).
*/
err |= __get_user(ps, &sc->sc_ps);
- regs->ps = (regs->ps & ~XCHAL_PS_CALLINC_MASK)
- | (ps & XCHAL_PS_CALLINC_MASK);
+ regs->ps = (regs->ps & ~PS_CALLINC_MASK)
+ | (ps & PS_CALLINC_MASK);
/* Additional corruption checks */
@@ -280,7 +280,7 @@ flush_my_cpstate(struct task_struct *tsk)
static int
save_cpextra (struct _cpstate *buf)
{
-#if (XCHAL_EXTRA_SA_SIZE == 0) && (XCHAL_CP_NUM == 0)
+#if XCHAL_CP_NUM == 0
return 0;
#else
@@ -350,7 +350,7 @@ setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
return err;
}
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
+asmlinkage int xtensa_sigreturn(struct pt_regs *regs)
{
struct sigframe *frame = (struct sigframe *)regs->areg[1];
sigset_t set;
@@ -382,7 +382,7 @@ badframe:
return 0;
}
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
{
struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
sigset_t set;
@@ -497,8 +497,10 @@ gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
/* Flush generated code out of the data cache */
- if (err == 0)
- __flush_invalidate_cache_range((unsigned long)codemem, 6UL);
+ if (err == 0) {
+ __invalidate_icache_range((unsigned long)codemem, 6UL);
+ __flush_invalidate_dcache_range((unsigned long)codemem, 6UL);
+ }
return err;
}
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
new file mode 100644
index 00000000000..fe3834bc1db
--- /dev/null
+++ b/arch/xtensa/kernel/syscall.c
@@ -0,0 +1,95 @@
+/*
+ * arch/xtensa/kernel/syscall.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ *
+ */
+#include <asm/uaccess.h>
+#include <asm/syscall.h>
+#include <asm/unistd.h>
+#include <linux/linkage.h>
+#include <linux/stringify.h>
+#include <linux/errno.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/mman.h>
+#include <linux/shm.h>
+
+typedef void (*syscall_t)(void);
+
+syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
+ [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
+
+#undef __SYSCALL
+#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
+#undef _XTENSA_UNISTD_H
+#undef __KERNEL_SYSCALLS__
+#include <asm/unistd.h>
+};
+
+/*
+ * xtensa_pipe() is the normal C calling standard for creating a pipe. It's not
+ * the way unix traditional does this, though.
+ */
+
+asmlinkage long xtensa_pipe(int __user *userfds)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(userfds, fd, 2 * sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+
+asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ int error = -EBADF;
+ struct file * file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(&current->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
+{
+ unsigned long ret;
+ long err;
+
+ err = do_shmat(shmid, shmaddr, shmflg, &ret);
+ if (err)
+ return err;
+ return (long)ret;
+}
+
diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c
deleted file mode 100644
index f49cb239e60..00000000000
--- a/arch/xtensa/kernel/syscalls.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * arch/xtensa/kernel/syscalls.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- * Copyright (C) 2000 Silicon Graphics, Inc.
- * Copyright (C) 1995 - 2000 by Ralf Baechle
- *
- * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
- * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
- * Chris Zankel <chris@zankel.net>
- * Kevin Chea
- *
- */
-
-#define DEBUG 0
-
-#include <linux/linkage.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/mman.h>
-#include <linux/sched.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/utsname.h>
-#include <linux/unistd.h>
-#include <linux/stringify.h>
-#include <linux/syscalls.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/errno.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
-#include <asm/mman.h>
-#include <asm/shmparam.h>
-#include <asm/page.h>
-
-extern void do_syscall_trace(void);
-typedef int (*syscall_t)(void *a0,...);
-extern syscall_t sys_call_table[];
-extern unsigned char sys_narg_table[];
-
-/*
- * sys_pipe() is the normal C calling standard for creating a pipe. It's not
- * the way unix traditional does this, though.
- */
-
-int sys_pipe(int __user *userfds)
-{
- int fd[2];
- int error;
-
- error = do_pipe(fd);
- if (!error) {
- if (copy_to_user(userfds, fd, 2 * sizeof(int)))
- error = -EFAULT;
- }
- return error;
-}
-
-/*
- * Common code for old and new mmaps.
- */
-long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
- unsigned long flags, unsigned long fd, unsigned long pgoff)
-{
- int error = -EBADF;
- struct file * file = NULL;
-
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (!(flags & MAP_ANONYMOUS)) {
- file = fget(fd);
- if (!file)
- goto out;
- }
-
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up_write(&current->mm->mmap_sem);
-
- if (file)
- fput(file);
-out:
- return error;
-}
-
-int sys_clone(struct pt_regs *regs)
-{
- unsigned long clone_flags;
- unsigned long newsp;
- int __user *parent_tidptr, *child_tidptr;
- clone_flags = regs->areg[4];
- newsp = regs->areg[3];
- parent_tidptr = (int __user *)regs->areg[5];
- child_tidptr = (int __user *)regs->areg[6];
- if (!newsp)
- newsp = regs->areg[1];
- return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-
-int sys_execve(struct pt_regs *regs)
-{
- int error;
- char * filename;
-
- filename = getname((char *) (long)regs->areg[5]);
- error = PTR_ERR(filename);
- if (IS_ERR(filename))
- goto out;
- error = do_execve(filename, (char **) (long)regs->areg[3],
- (char **) (long)regs->areg[4], regs);
- putname(filename);
-
-out:
- return error;
-}
-
-int sys_uname(struct old_utsname * name)
-{
- if (name && !copy_to_user(name, utsname(), sizeof (*name)))
- return 0;
- return -EFAULT;
-}
-
-/*
- * Build the string table for the builtin "poor man's strace".
- */
-
-#if DEBUG
-#define SYSCALL(fun, narg) #fun,
-static char *sfnames[] = {
-#include "syscalls.h"
-};
-#undef SYS
-#endif
-
-void system_call (struct pt_regs *regs)
-{
- syscall_t syscall;
- unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
- int nargs, res;
- unsigned int syscallnr;
- int ps;
-
-#if DEBUG
- int i;
- unsigned long parms[6];
- char *sysname;
-#endif
-
- regs->syscall = regs->areg[2];
-
- do_syscall_trace();
-
- /* Have to load after syscall_trace because strace
- * sometimes changes regs->syscall.
- */
- syscallnr = regs->syscall;
-
- parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
-
- /* Restore interrupt level to syscall invoker's.
- * If this were in assembly, we wouldn't disable
- * interrupts in the first place:
- */
- local_save_flags (ps);
- local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) |
- (regs->ps & XCHAL_PS_INTLEVEL_MASK) );
-
- if (syscallnr > __NR_Linux_syscalls) {
- regs->areg[2] = -ENOSYS;
- return;
- }
-
- syscall = sys_call_table[syscallnr];
- nargs = sys_narg_table[syscallnr];
-
- if (syscall == NULL) {
- regs->areg[2] = -ENOSYS;
- return;
- }
-
- /* There shouldn't be more than six arguments in the table! */
-
- if (nargs > 6)
- panic("Internal error - too many syscall arguments (%d)!\n",
- nargs);
-
- /* Linux takes system-call arguments in registers. The ABI
- * and Xtensa software conventions require the system-call
- * number in a2. If an argument exists in a2, we move it to
- * the next available register. Note that for improved
- * efficiency, we do NOT shift all parameters down one
- * register to maintain the original order.
- *
- * At best case (zero arguments), we just write the syscall
- * number to a2. At worst case (1 to 6 arguments), we move
- * the argument in a2 to the next available register, then
- * write the syscall number to a2.
- *
- * For clarity, the following truth table enumerates all
- * possibilities.
- *
- * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5
- * --------- -------------- ----------------------------------
- * 0 a2
- * 1 a2 a3
- * 2 a2 a4, a3
- * 3 a2 a5, a3, a4
- * 4 a2 a6, a3, a4, a5
- * 5 a2 a7, a3, a4, a5, a6
- * 6 a2 a8, a3, a4, a5, a6, a7
- */
- if (nargs) {
- parm0 = regs->areg[nargs+2];
- parm1 = regs->areg[3];
- parm2 = regs->areg[4];
- parm3 = regs->areg[5];
- parm4 = regs->areg[6];
- parm5 = regs->areg[7];
- } else /* nargs == 0 */
- parm0 = (unsigned long) regs;
-
-#if DEBUG
- parms[0] = parm0;
- parms[1] = parm1;
- parms[2] = parm2;
- parms[3] = parm3;
- parms[4] = parm4;
- parms[5] = parm5;
-
- sysname = sfnames[syscallnr];
- if (strncmp(sysname, "sys_", 4) == 0)
- sysname = sysname + 4;
-
- printk("\017SYSCALL:I:%x:%d:%s %s(", regs->pc, current->pid,
- current->comm, sysname);
- for (i = 0; i < nargs; i++)
- printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
- printk(")\n");
-#endif
-
- res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
-
-#if DEBUG
- printk("\017SYSCALL:O:%d:%s %s(",current->pid, current->comm, sysname);
- for (i = 0; i < nargs; i++)
- printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
- if (res < 4096)
- printk(") = %d\n", res);
- else
- printk(") = %#x\n", res);
-#endif /* DEBUG */
-
- regs->areg[2] = res;
- do_syscall_trace();
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-{
- long __res;
- asm volatile (
- " mov a5, %2 \n"
- " mov a4, %4 \n"
- " mov a3, %3 \n"
- " movi a2, %1 \n"
- " syscall \n"
- " mov %0, a2 \n"
- : "=a" (__res)
- : "i" (__NR_execve), "a" (filename), "a" (argv), "a" (envp)
- : "a2", "a3", "a4", "a5");
- return __res;
-}
diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h
deleted file mode 100644
index 216c10a3150..00000000000
--- a/arch/xtensa/kernel/syscalls.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * arch/xtensa/kernel/syscalls.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- *
- * Changes by Joe Taylor <joe@tensilica.com>
- */
-
-/*
- * This file is being included twice - once to build a list of all
- * syscalls and once to build a table of how many arguments each syscall
- * accepts. Syscalls that receive a pointer to the saved registers are
- * marked as having zero arguments.
- *
- * The binary compatibility calls are in a separate list.
- *
- * Entry '0' used to be system_call. It's removed to disable indirect
- * system calls for now so user tasks can't recurse. See mips'
- * sys_syscall for a comparable example.
- */
-
-SYSCALL(0, 0) /* 00 */
-SYSCALL(sys_exit, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_read, 3)
-SYSCALL(sys_write, 3)
-SYSCALL(sys_open, 3) /* 05 */
-SYSCALL(sys_close, 1)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_creat, 2)
-SYSCALL(sys_link, 2)
-SYSCALL(sys_unlink, 1) /* 10 */
-SYSCALL(sys_execve, 0)
-SYSCALL(sys_chdir, 1)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_mknod, 3)
-SYSCALL(sys_chmod, 2) /* 15 */
-SYSCALL(sys_lchown, 3)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_newstat, 2)
-SYSCALL(sys_lseek, 3)
-SYSCALL(sys_getpid, 0) /* 20 */
-SYSCALL(sys_mount, 5)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_setuid, 1)
-SYSCALL(sys_getuid, 0)
-SYSCALL(sys_ni_syscall, 1) /* 25 */
-SYSCALL(sys_ptrace, 4)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_newfstat, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_utime, 2) /* 30 */
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_access, 2)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_ni_syscall, 0) /* 35 */
-SYSCALL(sys_sync, 0)
-SYSCALL(sys_kill, 2)
-SYSCALL(sys_rename, 2)
-SYSCALL(sys_mkdir, 2)
-SYSCALL(sys_rmdir, 1) /* 40 */
-SYSCALL(sys_dup, 1)
-SYSCALL(sys_pipe, 1)
-SYSCALL(sys_times, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_brk, 1) /* 45 */
-SYSCALL(sys_setgid, 1)
-SYSCALL(sys_getgid, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_geteuid, 0)
-SYSCALL(sys_getegid, 0) /* 50 */
-SYSCALL(sys_acct, 1)
-SYSCALL(sys_umount, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ioctl, 3)
-SYSCALL(sys_fcntl, 3) /* 55 */
-SYSCALL(sys_ni_syscall, 2)
-SYSCALL(sys_setpgid, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_umask, 1) /* 60 */
-SYSCALL(sys_chroot, 1)
-SYSCALL(sys_ustat, 2)
-SYSCALL(sys_dup2, 2)
-SYSCALL(sys_getppid, 0)
-SYSCALL(sys_ni_syscall, 0) /* 65 */
-SYSCALL(sys_setsid, 0)
-SYSCALL(sys_sigaction, 3)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_setreuid, 2) /* 70 */
-SYSCALL(sys_setregid, 2)
-SYSCALL(sys_sigsuspend, 0)
-SYSCALL(sys_ni_syscall, 1)
-SYSCALL(sys_sethostname, 2)
-SYSCALL(sys_setrlimit, 2) /* 75 */
-SYSCALL(sys_getrlimit, 2)
-SYSCALL(sys_getrusage, 2)
-SYSCALL(sys_gettimeofday, 2)
-SYSCALL(sys_settimeofday, 2)
-SYSCALL(sys_getgroups, 2) /* 80 */
-SYSCALL(sys_setgroups, 2)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_symlink, 2)
-SYSCALL(sys_newlstat, 2)
-SYSCALL(sys_readlink, 3) /* 85 */
-SYSCALL(sys_uselib, 1)
-SYSCALL(sys_swapon, 2)
-SYSCALL(sys_reboot, 3)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 6) /* 90 */
-SYSCALL(sys_munmap, 2)
-SYSCALL(sys_truncate, 2)
-SYSCALL(sys_ftruncate, 2)
-SYSCALL(sys_fchmod, 2)
-SYSCALL(sys_fchown, 3) /* 95 */
-SYSCALL(sys_getpriority, 2)
-SYSCALL(sys_setpriority, 3)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_statfs, 2)
-SYSCALL(sys_fstatfs, 2) /* 100 */
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 2)
-SYSCALL(sys_syslog, 3)
-SYSCALL(sys_setitimer, 3)
-SYSCALL(sys_getitimer, 2) /* 105 */
-SYSCALL(sys_newstat, 2)
-SYSCALL(sys_newlstat, 2)
-SYSCALL(sys_newfstat, 2)
-SYSCALL(sys_uname, 1)
-SYSCALL(sys_ni_syscall, 0) /* 110 */
-SYSCALL(sys_vhangup, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_wait4, 4)
-SYSCALL(sys_swapoff, 1) /* 115 */
-SYSCALL(sys_sysinfo, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_fsync, 1)
-SYSCALL(sys_sigreturn, 0)
-SYSCALL(sys_clone, 0) /* 120 */
-SYSCALL(sys_setdomainname, 2)
-SYSCALL(sys_newuname, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_adjtimex, 1)
-SYSCALL(sys_mprotect, 3) /* 125 */
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 2)
-SYSCALL(sys_init_module, 2)
-SYSCALL(sys_delete_module, 1)
-SYSCALL(sys_ni_syscall, 1) /* 130 */
-SYSCALL(sys_quotactl, 0)
-SYSCALL(sys_getpgid, 1)
-SYSCALL(sys_fchdir, 1)
-SYSCALL(sys_bdflush, 2)
-SYSCALL(sys_sysfs, 3) /* 135 */
-SYSCALL(sys_personality, 1)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_setfsuid, 1)
-SYSCALL(sys_setfsgid, 1)
-SYSCALL(sys_llseek, 5) /* 140 */
-SYSCALL(sys_getdents, 3)
-SYSCALL(sys_select, 5)
-SYSCALL(sys_flock, 2)
-SYSCALL(sys_msync, 3)
-SYSCALL(sys_readv, 3) /* 145 */
-SYSCALL(sys_writev, 3)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_ni_syscall, 4) /* handled in fast syscall handler. */
-SYSCALL(sys_ni_syscall, 0) /* 150 */
-SYSCALL(sys_getsid, 1)
-SYSCALL(sys_fdatasync, 1)
-SYSCALL(sys_sysctl, 1)
-SYSCALL(sys_mlock, 2)
-SYSCALL(sys_munlock, 2) /* 155 */
-SYSCALL(sys_mlockall, 1)
-SYSCALL(sys_munlockall, 0)
-SYSCALL(sys_sched_setparam,2)
-SYSCALL(sys_sched_getparam,2)
-SYSCALL(sys_sched_setscheduler,3) /* 160 */
-SYSCALL(sys_sched_getscheduler,1)
-SYSCALL(sys_sched_yield,0)
-SYSCALL(sys_sched_get_priority_max,1)
-SYSCALL(sys_sched_get_priority_min,1)
-SYSCALL(sys_sched_rr_get_interval,2) /* 165 */
-SYSCALL(sys_nanosleep,2)
-SYSCALL(sys_mremap,4)
-SYSCALL(sys_accept, 3)
-SYSCALL(sys_bind, 3)
-SYSCALL(sys_connect, 3) /* 170 */
-SYSCALL(sys_getpeername, 3)
-SYSCALL(sys_getsockname, 3)
-SYSCALL(sys_getsockopt, 5)
-SYSCALL(sys_listen, 2)
-SYSCALL(sys_recv, 4) /* 175 */
-SYSCALL(sys_recvfrom, 6)
-SYSCALL(sys_recvmsg, 3)
-SYSCALL(sys_send, 4)
-SYSCALL(sys_sendmsg, 3)
-SYSCALL(sys_sendto, 6) /* 180 */
-SYSCALL(sys_setsockopt, 5)
-SYSCALL(sys_shutdown, 2)
-SYSCALL(sys_socket, 3)
-SYSCALL(sys_socketpair, 4)
-SYSCALL(sys_setresuid, 3) /* 185 */
-SYSCALL(sys_getresuid, 3)
-SYSCALL(sys_ni_syscall, 5)
-SYSCALL(sys_poll, 3)
-SYSCALL(sys_nfsservctl, 3)
-SYSCALL(sys_setresgid, 3) /* 190 */
-SYSCALL(sys_getresgid, 3)
-SYSCALL(sys_prctl, 5)
-SYSCALL(sys_rt_sigreturn, 0)
-SYSCALL(sys_rt_sigaction, 4)
-SYSCALL(sys_rt_sigprocmask, 4) /* 195 */
-SYSCALL(sys_rt_sigpending, 2)
-SYSCALL(sys_rt_sigtimedwait, 4)
-SYSCALL(sys_rt_sigqueueinfo, 3)
-SYSCALL(sys_rt_sigsuspend, 0)
-SYSCALL(sys_pread64, 5) /* 200 */
-SYSCALL(sys_pwrite64, 5)
-SYSCALL(sys_chown, 3)
-SYSCALL(sys_getcwd, 2)
-SYSCALL(sys_capget, 2)
-SYSCALL(sys_capset, 2) /* 205 */
-SYSCALL(sys_sigaltstack, 0)
-SYSCALL(sys_sendfile, 4)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_mmap, 6) /* 210 */
-SYSCALL(sys_truncate64, 2)
-SYSCALL(sys_ftruncate64, 2)
-SYSCALL(sys_stat64, 2)
-SYSCALL(sys_lstat64, 2)
-SYSCALL(sys_fstat64, 2) /* 215 */
-SYSCALL(sys_pivot_root, 2)
-SYSCALL(sys_mincore, 3)
-SYSCALL(sys_madvise, 3)
-SYSCALL(sys_getdents64, 3)
-SYSCALL(sys_ni_syscall, 0) /* 220 */
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 37347e36998..a350431363a 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -47,7 +47,7 @@ unsigned long long sched_clock(void)
return (unsigned long long)jiffies * (1000000000 / HZ);
}
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t timer_interrupt(int irq, void *dev_id);
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED,
@@ -150,7 +150,7 @@ EXPORT_SYMBOL(do_gettimeofday);
* The timer interrupt is called HZ times per second.
*/
-irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t timer_interrupt (int irq, void *dev_id)
{
unsigned long next;
@@ -160,9 +160,9 @@ irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
again:
while ((signed long)(get_ccount() - next) > 0) {
- profile_tick(CPU_PROFILING, regs);
+ profile_tick(CPU_PROFILING);
#ifndef CONFIG_SMP
- update_process_times(user_mode(regs));
+ update_process_times(user_mode(get_irq_regs()));
#endif
write_seqlock(&xtime_lock);
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index ce077d6bf3a..693ab268485 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -75,7 +75,7 @@ extern void system_call (struct pt_regs*);
#define USER 0x02
#define COPROCESSOR(x) \
-{ XCHAL_EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
+{ EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
typedef struct {
int cause;
@@ -85,38 +85,38 @@ typedef struct {
dispatch_init_table_t __init dispatch_init_table[] = {
-{ XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
-{ XCHAL_EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel },
-{ XCHAL_EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user },
-{ XCHAL_EXCCAUSE_SYSTEM_CALL, 0, system_call },
-/* XCHAL_EXCCAUSE_INSTRUCTION_FETCH unhandled */
-/* XCHAL_EXCCAUSE_LOAD_STORE_ERROR unhandled*/
-{ XCHAL_EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt },
-{ XCHAL_EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca },
-/* XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
-/* XCHAL_EXCCAUSE_PRIVILEGED unhandled */
+{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
+{ EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel },
+{ EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user },
+{ EXCCAUSE_SYSTEM_CALL, 0, system_call },
+/* EXCCAUSE_INSTRUCTION_FETCH unhandled */
+/* EXCCAUSE_LOAD_STORE_ERROR unhandled*/
+{ EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt },
+{ EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca },
+/* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
+/* EXCCAUSE_PRIVILEGED unhandled */
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
#ifdef CONFIG_UNALIGNED_USER
-{ XCHAL_EXCCAUSE_UNALIGNED, USER, fast_unaligned },
+{ EXCCAUSE_UNALIGNED, USER, fast_unaligned },
#else
-{ XCHAL_EXCCAUSE_UNALIGNED, 0, do_unaligned_user },
+{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user },
#endif
-{ XCHAL_EXCCAUSE_UNALIGNED, KRNL, fast_unaligned },
+{ EXCCAUSE_UNALIGNED, KRNL, fast_unaligned },
#endif
-{ XCHAL_EXCCAUSE_ITLB_MISS, 0, do_page_fault },
-{ XCHAL_EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss},
-{ XCHAL_EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit },
-{ XCHAL_EXCCAUSE_ITLB_PRIVILEGE, 0, do_page_fault },
-/* XCHAL_EXCCAUSE_SIZE_RESTRICTION unhandled */
-{ XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE, 0, do_page_fault },
-{ XCHAL_EXCCAUSE_DTLB_MISS, USER|KRNL, fast_second_level_miss},
-{ XCHAL_EXCCAUSE_DTLB_MISS, 0, do_page_fault },
-{ XCHAL_EXCCAUSE_DTLB_MULTIHIT, 0, do_multihit },
-{ XCHAL_EXCCAUSE_DTLB_PRIVILEGE, 0, do_page_fault },
-/* XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
-{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited },
-{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault },
-{ XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault },
+{ EXCCAUSE_ITLB_MISS, 0, do_page_fault },
+{ EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss},
+{ EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit },
+{ EXCCAUSE_ITLB_PRIVILEGE, 0, do_page_fault },
+/* EXCCAUSE_SIZE_RESTRICTION unhandled */
+{ EXCCAUSE_FETCH_CACHE_ATTRIBUTE, 0, do_page_fault },
+{ EXCCAUSE_DTLB_MISS, USER|KRNL, fast_second_level_miss},
+{ EXCCAUSE_DTLB_MISS, 0, do_page_fault },
+{ EXCCAUSE_DTLB_MULTIHIT, 0, do_multihit },
+{ EXCCAUSE_DTLB_PRIVILEGE, 0, do_page_fault },
+/* EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
+{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited },
+{ EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault },
+{ EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault },
/* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */
#if (XCHAL_CP_MASK & 1)
COPROCESSOR(0),
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 0e74397bfa2..eb2d7bb69ee 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -53,6 +53,8 @@
#include <asm/thread_info.h>
#include <asm/processor.h>
+#define WINDOW_VECTORS_SIZE 0x180
+
/*
* User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0)
@@ -210,7 +212,7 @@ ENTRY(_DoubleExceptionVector)
/* Check for kernel double exception (usually fatal). */
rsr a3, PS
- _bbci.l a3, PS_UM_SHIFT, .Lksp
+ _bbci.l a3, PS_UM_BIT, .Lksp
/* Check if we are currently handling a window exception. */
/* Note: We don't need to indicate that we enter a critical section. */
@@ -219,7 +221,7 @@ ENTRY(_DoubleExceptionVector)
movi a3, XCHAL_WINDOW_VECTORS_VADDR
_bltu a0, a3, .Lfixup
- addi a3, a3, XSHAL_WINDOW_VECTORS_SIZE
+ addi a3, a3, WINDOW_VECTORS_SIZE
_bgeu a0, a3, .Lfixup
/* Window overflow/underflow exception. Get stack pointer. */
@@ -245,7 +247,7 @@ ENTRY(_DoubleExceptionVector)
wsr a2, DEPC # save stack pointer temporarily
rsr a0, PS
- extui a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+ extui a0, a0, PS_OWB_SHIFT, 4
wsr a0, WINDOWBASE
rsync
@@ -312,8 +314,8 @@ ENTRY(_DoubleExceptionVector)
.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
rsr a3, EXCCAUSE
- beqi a3, XCHAL_EXCCAUSE_ITLB_MISS, 1f
- addi a3, a3, -XCHAL_EXCCAUSE_DTLB_MISS
+ beqi a3, EXCCAUSE_ITLB_MISS, 1f
+ addi a3, a3, -EXCCAUSE_DTLB_MISS
bnez a3, .Lunrecoverable
1: movi a3, fast_second_level_miss_double_kernel
jx a3
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index cfe75f52872..a36c104c3a5 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -16,19 +16,17 @@
#include <asm-generic/vmlinux.lds.h>
-#define _NOCLANGUAGE
-#include <xtensa/config/core.h>
-#include <xtensa/config/system.h>
+#include <asm/variant/core.h>
OUTPUT_ARCH(xtensa)
ENTRY(_start)
-#if XCHAL_MEMORY_ORDER == XTHAL_BIGENDIAN
+#ifdef __XTENSA_EB__
jiffies = jiffies_64 + 4;
#else
jiffies = jiffies_64;
#endif
-#define KERNELOFFSET 0x1000
+#define KERNELOFFSET 0xd0001000
/* Note: In the following macros, it would be nice to specify only the
vector name and section kind and construct "sym" and "section" using
@@ -75,7 +73,7 @@ jiffies = jiffies_64;
SECTIONS
{
- . = XCHAL_KSEG_CACHED_VADDR + KERNELOFFSET;
+ . = KERNELOFFSET;
/* .text section */
_text = .;
@@ -159,7 +157,7 @@ SECTIONS
/* Initialization code and data: */
- . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+ . = ALIGN(1 << 12);
__init_begin = .;
.init.text : {
_sinittext = .;
@@ -223,32 +221,32 @@ SECTIONS
.dummy)
SECTION_VECTOR (_DebugInterruptVector_literal,
.DebugInterruptVector.literal,
- XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) - 4,
+ XCHAL_DEBUG_VECTOR_VADDR - 4,
SIZEOF(.WindowVectors.text),
.WindowVectors.text)
SECTION_VECTOR (_DebugInterruptVector_text,
.DebugInterruptVector.text,
- XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL),
+ XCHAL_DEBUG_VECTOR_VADDR,
4,
.DebugInterruptVector.literal)
SECTION_VECTOR (_KernelExceptionVector_literal,
.KernelExceptionVector.literal,
- XCHAL_KERNELEXC_VECTOR_VADDR - 4,
+ XCHAL_KERNEL_VECTOR_VADDR - 4,
SIZEOF(.DebugInterruptVector.text),
.DebugInterruptVector.text)
SECTION_VECTOR (_KernelExceptionVector_text,
.KernelExceptionVector.text,
- XCHAL_KERNELEXC_VECTOR_VADDR,
+ XCHAL_KERNEL_VECTOR_VADDR,
4,
.KernelExceptionVector.literal)
SECTION_VECTOR (_UserExceptionVector_literal,
.UserExceptionVector.literal,
- XCHAL_USEREXC_VECTOR_VADDR - 4,
+ XCHAL_USER_VECTOR_VADDR - 4,
SIZEOF(.KernelExceptionVector.text),
.KernelExceptionVector.text)
SECTION_VECTOR (_UserExceptionVector_text,
.UserExceptionVector.text,
- XCHAL_USEREXC_VECTOR_VADDR,
+ XCHAL_USER_VECTOR_VADDR,
4,
.UserExceptionVector.literal)
SECTION_VECTOR (_DoubleExceptionVector_literal,
@@ -263,7 +261,7 @@ SECTIONS
.DoubleExceptionVector.literal)
. = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
- . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+ . = ALIGN(1 << 12);
__init_end = .;
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S
index e2d64dfd530..9d9cd990afa 100644
--- a/arch/xtensa/lib/checksum.S
+++ b/arch/xtensa/lib/checksum.S
@@ -16,8 +16,7 @@
#include <asm/errno.h>
#include <linux/linkage.h>
-#define _ASMLANGUAGE
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S
index e8f6d7eb722..ddda8f4bc86 100644
--- a/arch/xtensa/lib/memcopy.S
+++ b/arch/xtensa/lib/memcopy.S
@@ -9,7 +9,7 @@
* Copyright (C) 2002 - 2005 Tensilica Inc.
*/
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
.macro src_b r, w0, w1
#ifdef __XTENSA_EB__
diff --git a/arch/xtensa/lib/memset.S b/arch/xtensa/lib/memset.S
index 4de25134bc6..56a17495b2d 100644
--- a/arch/xtensa/lib/memset.S
+++ b/arch/xtensa/lib/memset.S
@@ -11,7 +11,7 @@
* Copyright (C) 2002 Tensilica Inc.
*/
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
/*
* void *memset(void *dst, int c, size_t length)
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
index 71d55df4389..a834057bda6 100644
--- a/arch/xtensa/lib/strncpy_user.S
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -11,7 +11,7 @@
* Copyright (C) 2002 Tensilica Inc.
*/
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
#include <linux/errno.h>
/* Load or store instructions that may cause exceptions use the EX macro. */
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
index cdff4d670f3..5e9c1e709b2 100644
--- a/arch/xtensa/lib/strnlen_user.S
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -11,7 +11,7 @@
* Copyright (C) 2002 Tensilica Inc.
*/
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
/* Load or store instructions that may cause exceptions use the EX macro. */
diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S
index 4641ef510f0..a8ab1d4fe0a 100644
--- a/arch/xtensa/lib/usercopy.S
+++ b/arch/xtensa/lib/usercopy.S
@@ -53,7 +53,7 @@
* a11/ original length
*/
-#include <xtensa/coreasm.h>
+#include <asm/variant/core.h>
#ifdef __XTENSA_EB__
#define ALIGN(R, W0, W1) src R, W0, W1
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index dd0dbec2e57..3dc6f2f07bb 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -21,7 +21,7 @@
#include <asm/system.h>
#include <asm/pgalloc.h>
-unsigned long asid_cache = ASID_FIRST_VERSION;
+unsigned long asid_cache = ASID_USER_FIRST;
void bad_page_fault(struct pt_regs*, unsigned long, int);
/*
@@ -58,10 +58,10 @@ void do_page_fault(struct pt_regs *regs)
return;
}
- is_write = (exccause == XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
- is_exec = (exccause == XCHAL_EXCCAUSE_ITLB_PRIVILEGE ||
- exccause == XCHAL_EXCCAUSE_ITLB_MISS ||
- exccause == XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
+ is_write = (exccause == EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
+ is_exec = (exccause == EXCCAUSE_ITLB_PRIVILEGE ||
+ exccause == EXCCAUSE_ITLB_MISS ||
+ exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
#if 0
printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index 660ef058c14..e1ec2d1e818 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -141,8 +141,8 @@ void __init bootmem_init(void)
if (min_low_pfn > max_pfn)
panic("No memory found!\n");
- max_low_pfn = max_pfn < MAX_LOW_MEMORY >> PAGE_SHIFT ?
- max_pfn : MAX_LOW_MEMORY >> PAGE_SHIFT;
+ max_low_pfn = max_pfn < MAX_MEM_PFN >> PAGE_SHIFT ?
+ max_pfn : MAX_MEM_PFN >> PAGE_SHIFT;
/* Find an area to use for the bootmem bitmap. */
@@ -215,7 +215,7 @@ void __init init_mmu (void)
/* Set rasid register to a known value. */
- set_rasid_register (ASID_ALL_RESERVED);
+ set_rasid_register (ASID_USER_FIRST);
/* Set PTEVADDR special register to the start of the page
* table, which is in kernel mappable space (ie. not
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S
index 327c0f17187..ae085332c60 100644
--- a/arch/xtensa/mm/misc.S
+++ b/arch/xtensa/mm/misc.S
@@ -19,9 +19,8 @@
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-
-#include <xtensa/cacheasm.h>
-#include <xtensa/cacheattrasm.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
/* clear_page (page) */
@@ -74,104 +73,66 @@ ENTRY(copy_page)
retw
-
/*
- * void __flush_invalidate_cache_all(void)
+ * void __invalidate_icache_page(ulong start)
*/
-ENTRY(__flush_invalidate_cache_all)
+ENTRY(__invalidate_icache_page)
entry sp, 16
- dcache_writeback_inv_all a2, a3
- icache_invalidate_all a2, a3
- retw
-/*
- * void __invalidate_icache_all(void)
- */
+ ___invalidate_icache_page a2 a3
+ isync
-ENTRY(__invalidate_icache_all)
- entry sp, 16
- icache_invalidate_all a2, a3
retw
/*
- * void __flush_invalidate_dcache_all(void)
+ * void __invalidate_dcache_page(ulong start)
*/
-ENTRY(__flush_invalidate_dcache_all)
+ENTRY(__invalidate_dcache_page)
entry sp, 16
- dcache_writeback_inv_all a2, a3
- retw
-
-/*
- * void __flush_invalidate_cache_range(ulong start, ulong size)
- */
+ ___invalidate_dcache_page a2 a3
+ dsync
-ENTRY(__flush_invalidate_cache_range)
- entry sp, 16
- mov a4, a2
- mov a5, a3
- dcache_writeback_inv_region a4, a5, a6
- icache_invalidate_region a2, a3, a4
retw
/*
- * void __invalidate_icache_page(ulong start)
+ * void __flush_invalidate_dcache_page(ulong start)
*/
-ENTRY(__invalidate_icache_page)
+ENTRY(__flush_invalidate_dcache_page)
entry sp, 16
- movi a3, PAGE_SIZE
- icache_invalidate_region a2, a3, a4
- retw
-/*
- * void __invalidate_dcache_page(ulong start)
- */
+ ___flush_invalidate_dcache_page a2 a3
-ENTRY(__invalidate_dcache_page)
- entry sp, 16
- movi a3, PAGE_SIZE
- dcache_invalidate_region a2, a3, a4
+ dsync
retw
/*
- * void __invalidate_icache_range(ulong start, ulong size)
+ * void __flush_dcache_page(ulong start)
*/
-ENTRY(__invalidate_icache_range)
+ENTRY(__flush_dcache_page)
entry sp, 16
- icache_invalidate_region a2, a3, a4
- retw
-/*
- * void __invalidate_dcache_range(ulong start, ulong size)
- */
+ ___flush_dcache_page a2 a3
-ENTRY(__invalidate_dcache_range)
- entry sp, 16
- dcache_invalidate_region a2, a3, a4
+ dsync
retw
-/*
- * void __flush_dcache_page(ulong start)
- */
-ENTRY(__flush_dcache_page)
- entry sp, 16
- movi a3, PAGE_SIZE
- dcache_writeback_region a2, a3, a4
- retw
/*
- * void __flush_invalidate_dcache_page(ulong start)
+ * void __invalidate_icache_range(ulong start, ulong size)
*/
-ENTRY(__flush_invalidate_dcache_page)
+ENTRY(__invalidate_icache_range)
entry sp, 16
- movi a3, PAGE_SIZE
- dcache_writeback_inv_region a2, a3, a4
+
+ ___invalidate_icache_range a2 a3 a4
+ isync
+
retw
/*
@@ -180,195 +141,69 @@ ENTRY(__flush_invalidate_dcache_page)
ENTRY(__flush_invalidate_dcache_range)
entry sp, 16
- dcache_writeback_inv_region a2, a3, a4
- retw
-/*
- * void __invalidate_dcache_all(void)
- */
+ ___flush_invalidate_dcache_range a2 a3 a4
+ dsync
-ENTRY(__invalidate_dcache_all)
- entry sp, 16
- dcache_invalidate_all a2, a3
retw
/*
- * void __flush_invalidate_dcache_page_phys(ulong start)
+ * void _flush_dcache_range(ulong start, ulong size)
*/
-ENTRY(__flush_invalidate_dcache_page_phys)
+ENTRY(__flush_dcache_range)
entry sp, 16
- movi a3, XCHAL_DCACHE_SIZE
- movi a4, PAGE_MASK | 1
- addi a2, a2, 1
-
-1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
-
- ldct a6, a3
+ ___flush_dcache_range a2 a3 a4
dsync
- and a6, a6, a4
- beq a6, a2, 2f
- bgeui a3, 2, 1b
- retw
-2: diwbi a3, 0
- bgeui a3, 2, 1b
retw
-ENTRY(check_dcache_low0)
- entry sp, 16
-
- movi a3, XCHAL_DCACHE_SIZE / 4
- movi a4, PAGE_MASK | 1
- addi a2, a2, 1
-
-1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
-
- ldct a6, a3
- dsync
- and a6, a6, a4
- beq a6, a2, 2f
- bgeui a3, 2, 1b
- retw
-
-2: j 2b
-
-ENTRY(check_dcache_high0)
- entry sp, 16
-
- movi a5, XCHAL_DCACHE_SIZE / 4
- movi a3, XCHAL_DCACHE_SIZE / 2
- movi a4, PAGE_MASK | 1
- addi a2, a2, 1
-
-1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
- addi a5, a5, -XCHAL_DCACHE_LINESIZE
-
- ldct a6, a3
- dsync
- and a6, a6, a4
- beq a6, a2, 2f
- bgeui a5, 2, 1b
- retw
-
-2: j 2b
+/*
+ * void _invalidate_dcache_range(ulong start, ulong size)
+ */
-ENTRY(check_dcache_low1)
+ENTRY(__invalidate_dcache_range)
entry sp, 16
- movi a5, XCHAL_DCACHE_SIZE / 4
- movi a3, XCHAL_DCACHE_SIZE * 3 / 4
- movi a4, PAGE_MASK | 1
- addi a2, a2, 1
+ ___invalidate_dcache_range a2 a3 a4
-1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
- addi a5, a5, -XCHAL_DCACHE_LINESIZE
- ldct a6, a3
- dsync
- and a6, a6, a4
- beq a6, a2, 2f
- bgeui a5, 2, 1b
retw
-2: j 2b
+/*
+ * void _invalidate_icache_all(void)
+ */
-ENTRY(check_dcache_high1)
+ENTRY(__invalidate_icache_all)
entry sp, 16
- movi a5, XCHAL_DCACHE_SIZE / 4
- movi a3, XCHAL_DCACHE_SIZE
- movi a4, PAGE_MASK | 1
- addi a2, a2, 1
-
-1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
- addi a5, a5, -XCHAL_DCACHE_LINESIZE
+ ___invalidate_icache_all a2 a3
+ isync
- ldct a6, a3
- dsync
- and a6, a6, a4
- beq a6, a2, 2f
- bgeui a5, 2, 1b
retw
-2: j 2b
-
-
/*
- * void __invalidate_icache_page_phys(ulong start)
+ * void _flush_invalidate_dcache_all(void)
*/
-ENTRY(__invalidate_icache_page_phys)
+ENTRY(__flush_invalidate_dcache_all)
entry sp, 16
- movi a3, XCHAL_ICACHE_SIZE
- movi a4, PAGE_MASK | 1
- addi a2, a2, 1
-
-1: addi a3, a3, -XCHAL_ICACHE_LINESIZE
-
- lict a6, a3
- isync
- and a6, a6, a4
- beq a6, a2, 2f
- bgeui a3, 2, 1b
- retw
+ ___flush_invalidate_dcache_all a2 a3
+ dsync
-2: iii a3, 0
- bgeui a3, 2, 1b
retw
+/*
+ * void _invalidate_dcache_all(void)
+ */
-#if 0
-
- movi a3, XCHAL_DCACHE_WAYS - 1
- movi a4, PAGE_SIZE
-
-1: mov a5, a2
- add a6, a2, a4
-
-2: diwbi a5, 0
- diwbi a5, XCHAL_DCACHE_LINESIZE
- diwbi a5, XCHAL_DCACHE_LINESIZE * 2
- diwbi a5, XCHAL_DCACHE_LINESIZE * 3
-
- addi a5, a5, XCHAL_DCACHE_LINESIZE * 4
- blt a5, a6, 2b
-
- addi a3, a3, -1
- addi a2, a2, XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS
- bgez a3, 1b
-
- retw
-
-ENTRY(__invalidate_icache_page_index)
+ENTRY(__invalidate_dcache_all)
entry sp, 16
- movi a3, XCHAL_ICACHE_WAYS - 1
- movi a4, PAGE_SIZE
-
-1: mov a5, a2
- add a6, a2, a4
-
-2: iii a5, 0
- iii a5, XCHAL_ICACHE_LINESIZE
- iii a5, XCHAL_ICACHE_LINESIZE * 2
- iii a5, XCHAL_ICACHE_LINESIZE * 3
-
- addi a5, a5, XCHAL_ICACHE_LINESIZE * 4
- blt a5, a6, 2b
-
- addi a3, a3, -1
- addi a2, a2, XCHAL_ICACHE_SIZE / XCHAL_ICACHE_WAYS
- bgez a3, 2b
+ ___invalidate_dcache_all a2 a3
+ dsync
retw
-#endif
-
-
-
-
-
-
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
index 0fefb866687..239461d8ea8 100644
--- a/arch/xtensa/mm/tlb.c
+++ b/arch/xtensa/mm/tlb.c
@@ -24,12 +24,12 @@
static inline void __flush_itlb_all (void)
{
- int way, index;
+ int w, i;
- for (way = 0; way < XCHAL_ITLB_ARF_WAYS; way++) {
- for (index = 0; index < ITLB_ENTRIES_PER_ARF_WAY; index++) {
- int entry = way + (index << PAGE_SHIFT);
- invalidate_itlb_entry_no_isync (entry);
+ for (w = 0; w < ITLB_ARF_WAYS; w++) {
+ for (i = 0; i < (1 << XCHAL_ITLB_ARF_ENTRIES_LOG2); i++) {
+ int e = w + (i << PAGE_SHIFT);
+ invalidate_itlb_entry_no_isync(e);
}
}
asm volatile ("isync\n");
@@ -37,12 +37,12 @@ static inline void __flush_itlb_all (void)
static inline void __flush_dtlb_all (void)
{
- int way, index;
+ int w, i;
- for (way = 0; way < XCHAL_DTLB_ARF_WAYS; way++) {
- for (index = 0; index < DTLB_ENTRIES_PER_ARF_WAY; index++) {
- int entry = way + (index << PAGE_SHIFT);
- invalidate_dtlb_entry_no_isync (entry);
+ for (w = 0; w < DTLB_ARF_WAYS; w++) {
+ for (i = 0; i < (1 << XCHAL_DTLB_ARF_ENTRIES_LOG2); i++) {
+ int e = w + (i << PAGE_SHIFT);
+ invalidate_dtlb_entry_no_isync(e);
}
}
asm volatile ("isync\n");
@@ -63,21 +63,25 @@ void flush_tlb_all (void)
void flush_tlb_mm(struct mm_struct *mm)
{
-#if 0
- printk("[tlbmm<%lx>]\n", (unsigned long)mm->context);
-#endif
-
if (mm == current->active_mm) {
int flags;
local_save_flags(flags);
- get_new_mmu_context(mm, asid_cache);
- set_rasid_register(ASID_INSERT(mm->context));
+ __get_new_mmu_context(mm);
+ __load_mmu_context(mm);
local_irq_restore(flags);
}
else
mm->context = 0;
}
+#define _ITLB_ENTRIES (ITLB_ARF_WAYS << XCHAL_ITLB_ARF_ENTRIES_LOG2)
+#define _DTLB_ENTRIES (DTLB_ARF_WAYS << XCHAL_DTLB_ARF_ENTRIES_LOG2)
+#if _ITLB_ENTRIES > _DTLB_ENTRIES
+# define _TLB_ENTRIES _ITLB_ENTRIES
+#else
+# define _TLB_ENTRIES _DTLB_ENTRIES
+#endif
+
void flush_tlb_range (struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
@@ -93,7 +97,7 @@ void flush_tlb_range (struct vm_area_struct *vma,
#endif
local_save_flags(flags);
- if (end-start + (PAGE_SIZE-1) <= SMALLEST_NTLB_ENTRIES << PAGE_SHIFT) {
+ if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) {
int oldpid = get_rasid_register();
set_rasid_register (ASID_INSERT(mm->context));
start &= PAGE_MASK;
@@ -111,9 +115,7 @@ void flush_tlb_range (struct vm_area_struct *vma,
set_rasid_register(oldpid);
} else {
- get_new_mmu_context(mm, asid_cache);
- if (mm == current->active_mm)
- set_rasid_register(ASID_INSERT(mm->context));
+ flush_tlb_mm(mm);
}
local_irq_restore(flags);
}
@@ -123,10 +125,6 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
struct mm_struct* mm = vma->vm_mm;
unsigned long flags;
int oldpid;
-#if 0
- printk("[tlbpage<%02lx,%08lx>]\n",
- (unsigned long)mm->context, page);
-#endif
if(mm->context == NO_CONTEXT)
return;
@@ -142,404 +140,5 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
set_rasid_register(oldpid);
local_irq_restore(flags);
-
-#if 0
- flush_tlb_all();
- return;
-#endif
-}
-
-
-#ifdef DEBUG_TLB
-
-#define USE_ITLB 0
-#define USE_DTLB 1
-
-struct way_config_t {
- int indicies;
- int indicies_log2;
- int pgsz_log2;
- int arf;
-};
-
-static struct way_config_t itlb[XCHAL_ITLB_WAYS] =
-{
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ARF)
- },
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ARF)
- },
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ARF)
- },
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ARF)
- },
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ARF)
- },
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ARF)
- },
- { XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES_LOG2),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, PAGESZ_LOG2_MIN),
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ARF)
- }
-};
-
-static struct way_config_t dtlb[XCHAL_DTLB_WAYS] =
-{
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ARF)
- },
- { XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES_LOG2),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, PAGESZ_LOG2_MIN),
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ARF)
- }
-};
-
-/* Total number of entries: */
-#define ITLB_TOTAL_ENTRIES \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES) + \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES) + \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES) + \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES) + \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES) + \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES) + \
- XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES)
-#define DTLB_TOTAL_ENTRIES \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES) + \
- XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES)
-
-
-typedef struct {
- unsigned va;
- unsigned pa;
- unsigned char asid;
- unsigned char ca;
- unsigned char way;
- unsigned char index;
- unsigned char pgsz_log2; /* 0 .. 32 */
- unsigned char type; /* 0=ITLB 1=DTLB */
-} tlb_dump_entry_t;
-
-/* Return -1 if a precedes b, +1 if a follows b, 0 if same: */
-int cmp_tlb_dump_info( tlb_dump_entry_t *a, tlb_dump_entry_t *b )
-{
- if (a->asid < b->asid) return -1;
- if (a->asid > b->asid) return 1;
- if (a->va < b->va) return -1;
- if (a->va > b->va) return 1;
- if (a->pa < b->pa) return -1;
- if (a->pa > b->pa) return 1;
- if (a->ca < b->ca) return -1;
- if (a->ca > b->ca) return 1;
- if (a->way < b->way) return -1;
- if (a->way > b->way) return 1;
- if (a->index < b->index) return -1;
- if (a->index > b->index) return 1;
- return 0;
-}
-
-void sort_tlb_dump_info( tlb_dump_entry_t *t, int n )
-{
- int i, j;
- /* Simple O(n*n) sort: */
- for (i = 0; i < n-1; i++)
- for (j = i+1; j < n; j++)
- if (cmp_tlb_dump_info(t+i, t+j) > 0) {
- tlb_dump_entry_t tmp = t[i];
- t[i] = t[j];
- t[j] = tmp;
- }
-}
-
-
-static tlb_dump_entry_t itlb_dump_info[ITLB_TOTAL_ENTRIES];
-static tlb_dump_entry_t dtlb_dump_info[DTLB_TOTAL_ENTRIES];
-
-
-static inline char *way_type (int type)
-{
- return type ? "autorefill" : "non-autorefill";
-}
-
-void print_entry (struct way_config_t *way_info,
- unsigned int way,
- unsigned int index,
- unsigned int virtual,
- unsigned int translation)
-{
- char valid_chr;
- unsigned int va, pa, asid, ca;
-
- va = virtual &
- ~((1 << (way_info->pgsz_log2 + way_info->indicies_log2)) - 1);
- asid = virtual & ((1 << XCHAL_MMU_ASID_BITS) - 1);
- pa = translation & ~((1 << way_info->pgsz_log2) - 1);
- ca = translation & ((1 << XCHAL_MMU_CA_BITS) - 1);
- valid_chr = asid ? 'V' : 'I';
-
- /* Compute and incorporate the effect of the index bits on the
- * va. It's more useful for kernel debugging, since we always
- * want to know the effective va anyway. */
-
- va += index << way_info->pgsz_log2;
-
- printk ("\t[%d,%d] (%c) vpn 0x%.8x ppn 0x%.8x asid 0x%.2x am 0x%x\n",
- way, index, valid_chr, va, pa, asid, ca);
-}
-
-void print_itlb_entry (struct way_config_t *way_info, int way, int index)
-{
- print_entry (way_info, way, index,
- read_itlb_virtual (way + (index << way_info->pgsz_log2)),
- read_itlb_translation (way + (index << way_info->pgsz_log2)));
-}
-
-void print_dtlb_entry (struct way_config_t *way_info, int way, int index)
-{
- print_entry (way_info, way, index,
- read_dtlb_virtual (way + (index << way_info->pgsz_log2)),
- read_dtlb_translation (way + (index << way_info->pgsz_log2)));
-}
-
-void dump_itlb (void)
-{
- int way, index;
-
- printk ("\nITLB: ways = %d\n", XCHAL_ITLB_WAYS);
-
- for (way = 0; way < XCHAL_ITLB_WAYS; way++) {
- printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
- way, itlb[way].indicies,
- itlb[way].pgsz_log2, way_type(itlb[way].arf));
- for (index = 0; index < itlb[way].indicies; index++) {
- print_itlb_entry(&itlb[way], way, index);
- }
- }
-}
-
-void dump_dtlb (void)
-{
- int way, index;
-
- printk ("\nDTLB: ways = %d\n", XCHAL_DTLB_WAYS);
-
- for (way = 0; way < XCHAL_DTLB_WAYS; way++) {
- printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
- way, dtlb[way].indicies,
- dtlb[way].pgsz_log2, way_type(dtlb[way].arf));
- for (index = 0; index < dtlb[way].indicies; index++) {
- print_dtlb_entry(&dtlb[way], way, index);
- }
- }
-}
-
-void dump_tlb (tlb_dump_entry_t *tinfo, struct way_config_t *config,
- int entries, int ways, int type, int show_invalid)
-{
- tlb_dump_entry_t *e = tinfo;
- int way, i;
-
- /* Gather all info: */
- for (way = 0; way < ways; way++) {
- struct way_config_t *cfg = config + way;
- for (i = 0; i < cfg->indicies; i++) {
- unsigned wayindex = way + (i << cfg->pgsz_log2);
- unsigned vv = (type ? read_dtlb_virtual (wayindex)
- : read_itlb_virtual (wayindex));
- unsigned pp = (type ? read_dtlb_translation (wayindex)
- : read_itlb_translation (wayindex));
-
- /* Compute and incorporate the effect of the index bits on the
- * va. It's more useful for kernel debugging, since we always
- * want to know the effective va anyway. */
-
- e->va = (vv & ~((1 << (cfg->pgsz_log2 + cfg->indicies_log2)) - 1));
- e->va += (i << cfg->pgsz_log2);
- e->pa = (pp & ~((1 << cfg->pgsz_log2) - 1));
- e->asid = (vv & ((1 << XCHAL_MMU_ASID_BITS) - 1));
- e->ca = (pp & ((1 << XCHAL_MMU_CA_BITS) - 1));
- e->way = way;
- e->index = i;
- e->pgsz_log2 = cfg->pgsz_log2;
- e->type = type;
- e++;
- }
- }
-#if 1
- /* Sort by ASID and VADDR: */
- sort_tlb_dump_info (tinfo, entries);
-#endif
-
- /* Display all sorted info: */
- printk ("\n%cTLB dump:\n", (type ? 'D' : 'I'));
- for (e = tinfo, i = 0; i < entries; i++, e++) {
-#if 0
- if (e->asid == 0 && !show_invalid)
- continue;
-#endif
- printk ("%c way=%d i=%d ASID=%02X V=%08X -> P=%08X CA=%X (%d %cB)\n",
- (e->type ? 'D' : 'I'), e->way, e->index,
- e->asid, e->va, e->pa, e->ca,
- (1 << (e->pgsz_log2 % 10)),
- " kMG"[e->pgsz_log2 / 10]
- );
- }
-}
-
-void dump_tlbs2 (int showinv)
-{
- dump_tlb (itlb_dump_info, itlb, ITLB_TOTAL_ENTRIES, XCHAL_ITLB_WAYS, 0, showinv);
- dump_tlb (dtlb_dump_info, dtlb, DTLB_TOTAL_ENTRIES, XCHAL_DTLB_WAYS, 1, showinv);
-}
-
-void dump_all_tlbs (void)
-{
- dump_tlbs2 (1);
-}
-
-void dump_valid_tlbs (void)
-{
- dump_tlbs2 (0);
}
-
-void dump_tlbs (void)
-{
- dump_itlb();
- dump_dtlb();
-}
-
-void dump_cache_tag(int dcache, int idx)
-{
- int w, i, s, e;
- unsigned long tag, index;
- unsigned long num_lines, num_ways, cache_size, line_size;
-
- num_ways = dcache ? XCHAL_DCACHE_WAYS : XCHAL_ICACHE_WAYS;
- cache_size = dcache ? XCHAL_DCACHE_SIZE : XCHAL_ICACHE_SIZE;
- line_size = dcache ? XCHAL_DCACHE_LINESIZE : XCHAL_ICACHE_LINESIZE;
-
- num_lines = cache_size / num_ways;
-
- s = 0; e = num_lines;
-
- if (idx >= 0)
- e = (s = idx * line_size) + 1;
-
- for (i = s; i < e; i+= line_size) {
- printk("\nline %#08x:", i);
- for (w = 0; w < num_ways; w++) {
- index = w * num_lines + i;
- if (dcache)
- __asm__ __volatile__("ldct %0, %1\n\t"
- : "=a"(tag) : "a"(index));
- else
- __asm__ __volatile__("lict %0, %1\n\t"
- : "=a"(tag) : "a"(index));
-
- printk(" %#010lx", tag);
- }
- }
- printk ("\n");
-}
-
-void dump_icache(int index)
-{
- unsigned long data, addr;
- int w, i;
-
- const unsigned long num_ways = XCHAL_ICACHE_WAYS;
- const unsigned long cache_size = XCHAL_ICACHE_SIZE;
- const unsigned long line_size = XCHAL_ICACHE_LINESIZE;
- const unsigned long num_lines = cache_size / num_ways / line_size;
-
- for (w = 0; w < num_ways; w++) {
- printk ("\nWay %d", w);
-
- for (i = 0; i < line_size; i+= 4) {
- addr = w * num_lines + index * line_size + i;
- __asm__ __volatile__("licw %0, %1\n\t"
- : "=a"(data) : "a"(addr));
- printk(" %#010lx", data);
- }
- }
- printk ("\n");
-}
-
-void dump_cache_tags(void)
-{
- printk("Instruction cache\n");
- dump_cache_tag(0, -1);
- printk("Data cache\n");
- dump_cache_tag(1, -1);
-}
-
-#endif
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c
index 5c947cae752..2f4f20ffe66 100644
--- a/arch/xtensa/platform-iss/console.c
+++ b/arch/xtensa/platform-iss/console.c
@@ -25,11 +25,15 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
-#include <xtensa/simcall.h>
+#include <asm/platform/simcall.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+
#define SERIAL_MAX_NUM_LINES 1
#define SERIAL_TIMER_VALUE (20 * HZ)
@@ -191,7 +195,7 @@ static int rs_read_proc(char *page, char **start, off_t off, int count,
}
-static const struct tty_operations serial_ops = {
+static struct tty_operations serial_ops = {
.open = rs_open,
.close = rs_close,
.write = rs_write,
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
index 15d64414bd6..8ebfc876122 100644
--- a/arch/xtensa/platform-iss/network.c
+++ b/arch/xtensa/platform-iss/network.c
@@ -34,7 +34,7 @@
#include <linux/timer.h>
#include <linux/platform_device.h>
-#include <xtensa/simcall.h>
+#include <asm/platform/simcall.h>
#define DRIVER_NAME "iss-netdev"
#define ETH_MAX_PACKET 1500
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 5934c4bfd52..ef126277b4b 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1462,20 +1462,7 @@ static struct elevator_type iosched_as = {
static int __init as_init(void)
{
- int ret;
-
- ret = elv_register(&iosched_as);
- if (!ret) {
- /*
- * don't allow AS to get unregistered, since we would have
- * to browse all tasks in the system and release their
- * as_io_context first
- */
- __module_get(THIS_MODULE);
- return 0;
- }
-
- return ret;
+ return elv_register(&iosched_as);
}
static void __exit as_exit(void)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 78c6b312bd3..07b70624377 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -219,9 +219,12 @@ static int cfq_queue_empty(request_queue_t *q)
return !cfqd->busy_queues;
}
-static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+static inline pid_t cfq_queue_pid(struct task_struct *task, int rw, int is_sync)
{
- if (rw == READ || rw == WRITE_SYNC)
+ /*
+ * Use the per-process queue, for read requests and syncronous writes
+ */
+ if (!(rw & REQ_RW) || is_sync)
return task->pid;
return CFQ_KEY_ASYNC;
@@ -473,7 +476,7 @@ static struct request *
cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
{
struct task_struct *tsk = current;
- pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
+ pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio), bio_sync(bio));
struct cfq_queue *cfqq;
cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
@@ -565,6 +568,33 @@ cfq_merged_requests(request_queue_t *q, struct request *rq,
cfq_remove_request(next);
}
+static int cfq_allow_merge(request_queue_t *q, struct request *rq,
+ struct bio *bio)
+{
+ struct cfq_data *cfqd = q->elevator->elevator_data;
+ const int rw = bio_data_dir(bio);
+ struct cfq_queue *cfqq;
+ pid_t key;
+
+ /*
+ * Disallow merge of a sync bio into an async request.
+ */
+ if ((bio_data_dir(bio) == READ || bio_sync(bio)) && !rq_is_sync(rq))
+ return 0;
+
+ /*
+ * Lookup the cfqq that this bio will be queued with. Allow
+ * merge only if rq is queued there.
+ */
+ key = cfq_queue_pid(current, rw, bio_sync(bio));
+ cfqq = cfq_find_cfq_hash(cfqd, key, current->ioprio);
+
+ if (cfqq == RQ_CFQQ(rq))
+ return 1;
+
+ return 0;
+}
+
static inline void
__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
@@ -1748,6 +1778,9 @@ static int cfq_may_queue(request_queue_t *q, int rw)
struct cfq_data *cfqd = q->elevator->elevator_data;
struct task_struct *tsk = current;
struct cfq_queue *cfqq;
+ unsigned int key;
+
+ key = cfq_queue_pid(tsk, rw, rw & REQ_RW_SYNC);
/*
* don't force setup of a queue from here, as a call to may_queue
@@ -1755,7 +1788,7 @@ static int cfq_may_queue(request_queue_t *q, int rw)
* so just lookup a possibly existing queue, or return 'may queue'
* if that fails
*/
- cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
+ cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
if (cfqq) {
cfq_init_prio_data(cfqq);
cfq_prio_boost(cfqq);
@@ -1798,10 +1831,10 @@ cfq_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask)
struct task_struct *tsk = current;
struct cfq_io_context *cic;
const int rw = rq_data_dir(rq);
- pid_t key = cfq_queue_pid(tsk, rw);
+ const int is_sync = rq_is_sync(rq);
+ pid_t key = cfq_queue_pid(tsk, rw, is_sync);
struct cfq_queue *cfqq;
unsigned long flags;
- int is_sync = key != CFQ_KEY_ASYNC;
might_sleep_if(gfp_mask & __GFP_WAIT);
@@ -2119,6 +2152,7 @@ static struct elevator_type iosched_cfq = {
.elevator_merge_fn = cfq_merge,
.elevator_merged_fn = cfq_merged_request,
.elevator_merge_req_fn = cfq_merged_requests,
+ .elevator_allow_merge_fn = cfq_allow_merge,
.elevator_dispatch_fn = cfq_dispatch_requests,
.elevator_add_req_fn = cfq_insert_request,
.elevator_activate_req_fn = cfq_activate_request,
diff --git a/block/elevator.c b/block/elevator.c
index c0063f345c5..f6dafa8c7c4 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -51,6 +51,21 @@ static const int elv_hash_shift = 6;
#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
/*
+ * Query io scheduler to see if the current process issuing bio may be
+ * merged with rq.
+ */
+static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
+{
+ request_queue_t *q = rq->q;
+ elevator_t *e = q->elevator;
+
+ if (e->ops->elevator_allow_merge_fn)
+ return e->ops->elevator_allow_merge_fn(q, rq, bio);
+
+ return 1;
+}
+
+/*
* can we safely merge with this request?
*/
inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
@@ -65,12 +80,15 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
return 0;
/*
- * same device and no special stuff set, merge is ok
+ * must be same device and not a special request
*/
- if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special)
- return 1;
+ if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
+ return 0;
- return 0;
+ if (!elv_iosched_allow_merge(rq, bio))
+ return 0;
+
+ return 1;
}
EXPORT_SYMBOL(elv_rq_merge_ok);
@@ -572,6 +590,12 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
*/
rq->cmd_flags |= REQ_SOFTBARRIER;
+ /*
+ * Most requeues happen because of a busy condition,
+ * don't force unplug of the queue for that case.
+ */
+ unplug_it = 0;
+
if (q->ordseq == 0) {
list_add(&rq->queuelist, &q->queue_head);
break;
@@ -586,11 +610,6 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
}
list_add_tail(&rq->queuelist, pos);
- /*
- * most requeues happen because of a busy condition, don't
- * force unplug of the queue for that case.
- */
- unplug_it = 0;
break;
default:
diff --git a/block/genhd.c b/block/genhd.c
index 653919d50cd..457fdac4c17 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -417,6 +417,34 @@ static struct disk_attribute disk_attr_stat = {
.show = disk_stats_read
};
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+
+static ssize_t disk_fail_store(struct gendisk * disk,
+ const char *buf, size_t count)
+{
+ int i;
+
+ if (count > 0 && sscanf(buf, "%d", &i) > 0) {
+ if (i == 0)
+ disk->flags &= ~GENHD_FL_FAIL;
+ else
+ disk->flags |= GENHD_FL_FAIL;
+ }
+
+ return count;
+}
+static ssize_t disk_fail_read(struct gendisk * disk, char *page)
+{
+ return sprintf(page, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
+}
+static struct disk_attribute disk_attr_fail = {
+ .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
+ .store = disk_fail_store,
+ .show = disk_fail_read
+};
+
+#endif
+
static struct attribute * default_attrs[] = {
&disk_attr_uevent.attr,
&disk_attr_dev.attr,
@@ -424,6 +452,9 @@ static struct attribute * default_attrs[] = {
&disk_attr_removable.attr,
&disk_attr_size.attr,
&disk_attr_stat.attr,
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+ &disk_attr_fail.attr,
+#endif
NULL,
};
diff --git a/block/ioctl.c b/block/ioctl.c
index 58aab630dfc..f6962b64660 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -72,7 +72,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
bdevp = bdget_disk(disk, part);
if (!bdevp)
return -ENOMEM;
- mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION);
+ mutex_lock(&bdevp->bd_mutex);
if (bdevp->bd_openers) {
mutex_unlock(&bdevp->bd_mutex);
bdput(bdevp);
@@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
fsync_bdev(bdevp);
invalidate_bdev(bdevp, 0);
- mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE);
+ mutex_lock(&bdev->bd_mutex);
delete_partition(disk, part);
mutex_unlock(&bdev->bd_mutex);
mutex_unlock(&bdevp->bd_mutex);
@@ -290,7 +290,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
ENOIOCTLCMD for unknown ioctls. */
long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
- struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
+ struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
int ret = -ENOIOCTLCMD;
if (disk->fops->compat_ioctl) {
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 31512cd9f3a..fb6789725e1 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -25,9 +25,11 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/writeback.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/interrupt.h>
#include <linux/cpu.h>
#include <linux/blktrace_api.h>
+#include <linux/fault-inject.h>
/*
* for max sense size
@@ -127,13 +129,6 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
}
EXPORT_SYMBOL(blk_get_backing_dev_info);
-void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data)
-{
- q->activity_fn = fn;
- q->activity_data = data;
-}
-EXPORT_SYMBOL(blk_queue_activity_fn);
-
/**
* blk_queue_prep_rq - set a prepare_request function for queue
* @q: queue
@@ -236,8 +231,6 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
* by default assume old behaviour and bounce for any highmem page
*/
blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
-
- blk_queue_activity_fn(q, NULL, NULL);
}
EXPORT_SYMBOL(blk_queue_make_request);
@@ -1412,8 +1405,7 @@ static inline int ll_new_hw_segment(request_queue_t *q,
return 1;
}
-static int ll_back_merge_fn(request_queue_t *q, struct request *req,
- struct bio *bio)
+int ll_back_merge_fn(request_queue_t *q, struct request *req, struct bio *bio)
{
unsigned short max_sectors;
int len;
@@ -1449,6 +1441,7 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
return ll_new_hw_segment(q, req, bio);
}
+EXPORT_SYMBOL(ll_back_merge_fn);
static int ll_front_merge_fn(request_queue_t *q, struct request *req,
struct bio *bio)
@@ -1919,9 +1912,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
}
q->request_fn = rfn;
- q->back_merge_fn = ll_back_merge_fn;
- q->front_merge_fn = ll_front_merge_fn;
- q->merge_requests_fn = ll_merge_requests_fn;
q->prep_rq_fn = NULL;
q->unplug_fn = generic_unplug_device;
q->queue_flags = (1 << QUEUE_FLAG_CLUSTER);
@@ -2065,15 +2055,16 @@ static void freed_request(request_queue_t *q, int rw, int priv)
* Returns NULL on failure, with queue_lock held.
* Returns !NULL on success, with queue_lock *not held*.
*/
-static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
- gfp_t gfp_mask)
+static struct request *get_request(request_queue_t *q, int rw_flags,
+ struct bio *bio, gfp_t gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
struct io_context *ioc = NULL;
+ const int rw = rw_flags & 0x01;
int may_queue, priv;
- may_queue = elv_may_queue(q, rw);
+ may_queue = elv_may_queue(q, rw_flags);
if (may_queue == ELV_MQUEUE_NO)
goto rq_starved;
@@ -2121,7 +2112,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
spin_unlock_irq(q->queue_lock);
- rq = blk_alloc_request(q, rw, priv, gfp_mask);
+ rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
if (unlikely(!rq)) {
/*
* Allocation failed presumably due to memory. Undo anything
@@ -2169,12 +2160,13 @@ out:
*
* Called with q->queue_lock held, and returns with it unlocked.
*/
-static struct request *get_request_wait(request_queue_t *q, int rw,
+static struct request *get_request_wait(request_queue_t *q, int rw_flags,
struct bio *bio)
{
+ const int rw = rw_flags & 0x01;
struct request *rq;
- rq = get_request(q, rw, bio, GFP_NOIO);
+ rq = get_request(q, rw_flags, bio, GFP_NOIO);
while (!rq) {
DEFINE_WAIT(wait);
struct request_list *rl = &q->rq;
@@ -2182,7 +2174,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
prepare_to_wait_exclusive(&rl->wait[rw], &wait,
TASK_UNINTERRUPTIBLE);
- rq = get_request(q, rw, bio, GFP_NOIO);
+ rq = get_request(q, rw_flags, bio, GFP_NOIO);
if (!rq) {
struct io_context *ioc;
@@ -2355,40 +2347,29 @@ static int __blk_rq_map_user(request_queue_t *q, struct request *rq,
else
bio = bio_copy_user(q, uaddr, len, reading);
- if (IS_ERR(bio)) {
+ if (IS_ERR(bio))
return PTR_ERR(bio);
- }
orig_bio = bio;
blk_queue_bounce(q, &bio);
+
/*
* We link the bounce buffer in and could have to traverse it
* later so we have to get a ref to prevent it from being freed
*/
bio_get(bio);
- /*
- * for most (all? don't know of any) queues we could
- * skip grabbing the queue lock here. only drivers with
- * funky private ->back_merge_fn() function could be
- * problematic.
- */
- spin_lock_irq(q->queue_lock);
if (!rq->bio)
blk_rq_bio_prep(q, rq, bio);
- else if (!q->back_merge_fn(q, rq, bio)) {
+ else if (!ll_back_merge_fn(q, rq, bio)) {
ret = -EINVAL;
- spin_unlock_irq(q->queue_lock);
goto unmap_bio;
} else {
rq->biotail->bi_next = bio;
rq->biotail = bio;
- rq->nr_sectors += bio_sectors(bio);
- rq->hard_nr_sectors = rq->nr_sectors;
rq->data_len += bio->bi_size;
}
- spin_unlock_irq(q->queue_lock);
return bio->bi_size;
@@ -2424,6 +2405,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
unsigned long len)
{
unsigned long bytes_read = 0;
+ struct bio *bio = NULL;
int ret;
if (len > (q->max_hw_sectors << 9))
@@ -2450,6 +2432,8 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
ret = __blk_rq_map_user(q, rq, ubuf, map_len);
if (ret < 0)
goto unmap_rq;
+ if (!bio)
+ bio = rq->bio;
bytes_read += ret;
ubuf += ret;
}
@@ -2457,7 +2441,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
rq->buffer = rq->data = NULL;
return 0;
unmap_rq:
- blk_rq_unmap_user(rq);
+ blk_rq_unmap_user(bio);
return ret;
}
@@ -2469,6 +2453,7 @@ EXPORT_SYMBOL(blk_rq_map_user);
* @rq: request to map data to
* @iov: pointer to the iovec
* @iov_count: number of elements in the iovec
+ * @len: I/O byte count
*
* Description:
* Data will be mapped directly for zero copy io, if possible. Otherwise
@@ -2514,27 +2499,33 @@ EXPORT_SYMBOL(blk_rq_map_user_iov);
/**
* blk_rq_unmap_user - unmap a request with user data
- * @rq: rq to be unmapped
+ * @bio: start of bio list
*
* Description:
- * Unmap a rq previously mapped by blk_rq_map_user().
- * rq->bio must be set to the original head of the request.
+ * Unmap a rq previously mapped by blk_rq_map_user(). The caller must
+ * supply the original rq->bio from the blk_rq_map_user() return, since
+ * the io completion may have changed rq->bio.
*/
-int blk_rq_unmap_user(struct request *rq)
+int blk_rq_unmap_user(struct bio *bio)
{
- struct bio *bio, *mapped_bio;
+ struct bio *mapped_bio;
+ int ret = 0, ret2;
- while ((bio = rq->bio)) {
- if (bio_flagged(bio, BIO_BOUNCED))
+ while (bio) {
+ mapped_bio = bio;
+ if (unlikely(bio_flagged(bio, BIO_BOUNCED)))
mapped_bio = bio->bi_private;
- else
- mapped_bio = bio;
- __blk_rq_unmap_user(mapped_bio);
- rq->bio = bio->bi_next;
- bio_put(bio);
+ ret2 = __blk_rq_unmap_user(mapped_bio);
+ if (ret2 && !ret)
+ ret = ret2;
+
+ mapped_bio = bio;
+ bio = bio->bi_next;
+ bio_put(mapped_bio);
}
- return 0;
+
+ return ret;
}
EXPORT_SYMBOL(blk_rq_unmap_user);
@@ -2694,9 +2685,6 @@ static inline void add_request(request_queue_t * q, struct request * req)
{
drive_stat_acct(req, req->nr_sectors, 1);
- if (q->activity_fn)
- q->activity_fn(q->activity_data, rq_data_dir(req));
-
/*
* elevator indicated where it wants this request to be
* inserted at elevator_merge time
@@ -2830,7 +2818,7 @@ static int attempt_merge(request_queue_t *q, struct request *req,
* will have updated segment counts, update sector
* counts here.
*/
- if (!q->merge_requests_fn(q, req, next))
+ if (!ll_merge_requests_fn(q, req, next))
return 0;
/*
@@ -2920,6 +2908,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
int el_ret, nr_sectors, barrier, err;
const unsigned short prio = bio_prio(bio);
const int sync = bio_sync(bio);
+ int rw_flags;
nr_sectors = bio_sectors(bio);
@@ -2946,7 +2935,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
case ELEVATOR_BACK_MERGE:
BUG_ON(!rq_mergeable(req));
- if (!q->back_merge_fn(q, req, bio))
+ if (!ll_back_merge_fn(q, req, bio))
break;
blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE);
@@ -2963,7 +2952,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
case ELEVATOR_FRONT_MERGE:
BUG_ON(!rq_mergeable(req));
- if (!q->front_merge_fn(q, req, bio))
+ if (!ll_front_merge_fn(q, req, bio))
break;
blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE);
@@ -2994,10 +2983,19 @@ static int __make_request(request_queue_t *q, struct bio *bio)
get_rq:
/*
+ * This sync check and mask will be re-done in init_request_from_bio(),
+ * but we need to set it earlier to expose the sync flag to the
+ * rq allocator and io schedulers.
+ */
+ rw_flags = bio_data_dir(bio);
+ if (sync)
+ rw_flags |= REQ_RW_SYNC;
+
+ /*
* Grab a free request. This is might sleep but can not fail.
* Returns with the queue unlocked.
*/
- req = get_request_wait(q, bio_data_dir(bio), bio);
+ req = get_request_wait(q, rw_flags, bio);
/*
* After dropping the lock and possibly sleeping here, our request
@@ -3056,6 +3054,42 @@ static void handle_bad_sector(struct bio *bio)
set_bit(BIO_EOF, &bio->bi_flags);
}
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+
+static DECLARE_FAULT_ATTR(fail_make_request);
+
+static int __init setup_fail_make_request(char *str)
+{
+ return setup_fault_attr(&fail_make_request, str);
+}
+__setup("fail_make_request=", setup_fail_make_request);
+
+static int should_fail_request(struct bio *bio)
+{
+ if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) ||
+ (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail))
+ return should_fail(&fail_make_request, bio->bi_size);
+
+ return 0;
+}
+
+static int __init fail_make_request_debugfs(void)
+{
+ return init_fault_attr_dentries(&fail_make_request,
+ "fail_make_request");
+}
+
+late_initcall(fail_make_request_debugfs);
+
+#else /* CONFIG_FAIL_MAKE_REQUEST */
+
+static inline int should_fail_request(struct bio *bio)
+{
+ return 0;
+}
+
+#endif /* CONFIG_FAIL_MAKE_REQUEST */
+
/**
* generic_make_request: hand a buffer to its device driver for I/O
* @bio: The bio describing the location in memory and on the device.
@@ -3141,6 +3175,9 @@ end_io:
if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
+ if (should_fail_request(bio))
+ goto end_io;
+
/*
* If this device has partitions, remap block n
* of partition p to block n+start(p) of the disk.
@@ -3195,10 +3232,12 @@ void submit_bio(int rw, struct bio *bio)
BIO_BUG_ON(!bio->bi_size);
BIO_BUG_ON(!bio->bi_io_vec);
bio->bi_rw |= rw;
- if (rw & WRITE)
+ if (rw & WRITE) {
count_vm_events(PGPGOUT, count);
- else
+ } else {
+ task_io_account_read(bio->bi_size);
count_vm_events(PGPGIN, count);
+ }
if (unlikely(block_dump)) {
char b[BDEVNAME_SIZE];
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index b3e210723a7..65c6a3cba6d 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -223,11 +223,12 @@ static int verify_command(struct file *file, unsigned char *cmd)
static int sg_io(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
{
- unsigned long start_time;
+ unsigned long start_time, timeout;
int writing = 0, ret = 0;
struct request *rq;
char sense[SCSI_SENSE_BUFFERSIZE];
unsigned char cmd[BLK_MAX_CDB];
+ struct bio *bio;
if (hdr->interface_id != 'S')
return -EINVAL;
@@ -270,14 +271,8 @@ static int sg_io(struct file *file, request_queue_t *q,
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- /*
- * bounce this after holding a reference to the original bio, it's
- * needed for proper unmapping
- */
- if (rq->bio)
- blk_queue_bounce(q, &rq->bio);
-
- rq->timeout = jiffies_to_msecs(hdr->timeout);
+ timeout = msecs_to_jiffies(hdr->timeout);
+ rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
if (!rq->timeout)
rq->timeout = q->sg_timeout;
if (!rq->timeout)
@@ -308,6 +303,7 @@ static int sg_io(struct file *file, request_queue_t *q,
if (ret)
goto out;
+ bio = rq->bio;
rq->retries = 0;
start_time = jiffies;
@@ -338,7 +334,7 @@ static int sg_io(struct file *file, request_queue_t *q,
hdr->sb_len_wr = len;
}
- if (blk_rq_unmap_user(rq))
+ if (blk_rq_unmap_user(bio))
ret = -EFAULT;
/* may not have succeeded, but output values written to control
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 034c939bf91..6e93004f218 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -17,7 +17,6 @@
#include <linux/crypto.h>
#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/io.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/seq_file.h>
diff --git a/crypto/sha512.c b/crypto/sha512.c
index 2dfe7f170b4..15eab9db9be 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -24,7 +24,7 @@
#define SHA384_DIGEST_SIZE 48
#define SHA512_DIGEST_SIZE 64
-#define SHA384_HMAC_BLOCK_SIZE 96
+#define SHA384_HMAC_BLOCK_SIZE 128
#define SHA512_HMAC_BLOCK_SIZE 128
struct sha512_ctx {
diff --git a/drivers/Kconfig b/drivers/Kconfig
index f3946341890..e7da9fa724e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -64,6 +64,8 @@ source "drivers/video/Kconfig"
source "sound/Kconfig"
+source "drivers/hid/Kconfig"
+
source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
@@ -78,4 +80,6 @@ source "drivers/rtc/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/kvm/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 67711770b1d..0dd96d1afd3 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_PCCARD) += pcmcia/
obj-$(CONFIG_DIO) += dio/
obj-$(CONFIG_SBUS) += sbus/
+obj-$(CONFIG_KVM) += kvm/
obj-$(CONFIG_ZORRO) += zorro/
obj-$(CONFIG_MAC) += macintosh/
obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
@@ -77,4 +78,5 @@ obj-$(CONFIG_CRYPTO) += crypto/
obj-$(CONFIG_SUPERH) += sh/
obj-$(CONFIG_GENERIC_TIME) += clocksource/
obj-$(CONFIG_DMA_ENGINE) += dma/
+obj-$(CONFIG_HID) += hid/
obj-$(CONFIG_PPC_PS3) += ps3/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 04854234120..674bf81c6e6 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1549,12 +1549,12 @@ int fd1772_init(void)
#ifdef TRACKBUFFER
BufferDrive = BufferSide = BufferTrack = -1;
/* Atari uses 512 - I want to eventually cope with 1K sectors */
- DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
+ DMABuffer = kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
TrackBuffer = DMABuffer + 512;
#else
/* Allocate memory for the DMAbuffer - on the Atari this takes it
out of some special memory... */
- DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
+ DMABuffer = kmalloc(2048); /* Copes with pretty large sectors */
#endif
err = -ENOMEM;
if (!DMAbuffer)
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index bdb9c8b78ed..9e584a7af43 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -360,7 +360,7 @@ static int __init i2c_ioc_init(void)
if (ret >= 0){
ret = misc_register(&rtc_dev);
if(ret < 0)
- i2c_bit_del_bus(&ioc_ops);
+ i2c_del_adapter(&ioc_ops);
}
return ret;
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0f9d4be7ed7..f4f000abc4e 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -11,7 +11,7 @@ config ACPI
bool "ACPI Support"
depends on IA64 || X86
depends on PCI
- select PM
+ depends on PM
default y
---help---
Advanced Configuration and Power Interface (ACPI) support for
@@ -97,6 +97,7 @@ config ACPI_BATTERY
config ACPI_BUTTON
tristate "Button"
+ depends on INPUT
default y
help
This driver handles events on the power, sleep and lid buttons.
@@ -172,6 +173,7 @@ config ACPI_NUMA
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
+ select BACKLIGHT_CLASS_DEVICE
---help---
This driver provides support for extra features of ACPI-compatible
ASUS laptops. As some of Medion laptops are made by ASUS, it may also
@@ -200,6 +202,7 @@ config ACPI_ASUS
config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras"
depends on X86
+ select BACKLIGHT_CLASS_DEVICE
---help---
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
@@ -225,6 +228,7 @@ config ACPI_IBM_DOCK
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
+ select BACKLIGHT_CLASS_DEVICE
---help---
This driver adds support for access to certain system settings
on "legacy free" Toshiba laptops. These laptops can be recognized by
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 11abc7bf777..6daeace796a 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -109,7 +109,7 @@ static struct proc_dir_entry *acpi_ac_dir;
static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_ac *ac = (struct acpi_ac *)seq->private;
+ struct acpi_ac *ac = seq->private;
if (!ac)
@@ -187,7 +187,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device)
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_ac *ac = (struct acpi_ac *)data;
+ struct acpi_ac *ac = data;
struct acpi_device *device = NULL;
@@ -221,10 +221,9 @@ static int acpi_ac_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL);
+ ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
if (!ac)
return -ENOMEM;
- memset(ac, 0, sizeof(struct acpi_ac));
ac->device = device;
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
@@ -269,7 +268,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- ac = (struct acpi_ac *)acpi_driver_data(device);
+ ac = acpi_driver_data(device);
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY, acpi_ac_notify);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 6bcd9e8e7bc..cd946ed192d 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -395,10 +395,9 @@ static int acpi_memory_device_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
+ mem_device = kzalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
if (!mem_device)
return -ENOMEM;
- memset(mem_device, 0, sizeof(struct acpi_memory_device));
INIT_LIST_HEAD(&mem_device->res_list);
mem_device->device = device;
@@ -429,7 +428,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- mem_device = (struct acpi_memory_device *)acpi_driver_data(device);
+ mem_device = acpi_driver_data(device);
kfree(mem_device);
return 0;
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index c7ac9297a20..396140bbbe5 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
+#include <linux/backlight.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#include <asm/uaccess.h>
@@ -402,6 +403,8 @@ static struct model_data model_conf[END_MODEL] = {
/* procdir we use */
static struct proc_dir_entry *asus_proc_dir;
+static struct backlight_device *asus_backlight_device;
+
/*
* This header is made available to allow proper configuration given model,
* revision number , ... this info cannot go in struct asus_hotk because it is
@@ -779,7 +782,7 @@ proc_write_lcd(struct file *file, const char __user * buffer,
return rv;
}
-static int read_brightness(void)
+static int read_brightness(struct backlight_device *bd)
{
int value;
@@ -801,9 +804,10 @@ static int read_brightness(void)
/*
* Change the brightness level
*/
-static void set_brightness(int value)
+static int set_brightness(int value)
{
acpi_status status = 0;
+ int ret = 0;
/* SPLV laptop */
if (hotk->methods->brightness_set) {
@@ -811,11 +815,12 @@ static void set_brightness(int value)
value, NULL))
printk(KERN_WARNING
"Asus ACPI: Error changing brightness\n");
- return;
+ ret = -EIO;
+ goto out;
}
/* No SPLV method if we are here, act as appropriate */
- value -= read_brightness();
+ value -= read_brightness(NULL);
while (value != 0) {
status = acpi_evaluate_object(NULL, (value > 0) ?
hotk->methods->brightness_up :
@@ -825,15 +830,22 @@ static void set_brightness(int value)
if (ACPI_FAILURE(status))
printk(KERN_WARNING
"Asus ACPI: Error changing brightness\n");
+ ret = -EIO;
}
- return;
+out:
+ return ret;
+}
+
+static int set_brightness_status(struct backlight_device *bd)
+{
+ return set_brightness(bd->props->brightness);
}
static int
proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
- return sprintf(page, "%d\n", read_brightness());
+ return sprintf(page, "%d\n", read_brightness(NULL));
}
static int
@@ -1134,7 +1146,7 @@ static int asus_hotk_get_info(void)
if (ACPI_FAILURE(status))
printk(KERN_WARNING " Couldn't get the DSDT table header\n");
else
- asus_info = (struct acpi_table_header *)dsdt.pointer;
+ asus_info = dsdt.pointer;
/* We have to write 0 on init this far for all ASUS models */
if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
@@ -1156,7 +1168,7 @@ static int asus_hotk_get_info(void)
* asus_model_match() and try something completely different.
*/
if (buffer.pointer) {
- model = (union acpi_object *)buffer.pointer;
+ model = buffer.pointer;
switch (model->type) {
case ACPI_TYPE_STRING:
string = model->string.pointer;
@@ -1252,11 +1264,9 @@ static int asus_hotk_add(struct acpi_device *device)
printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
ASUS_ACPI_VERSION);
- hotk =
- (struct asus_hotk *)kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+ hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
if (!hotk)
return -ENOMEM;
- memset(hotk, 0, sizeof(struct asus_hotk));
hotk->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
@@ -1333,6 +1343,26 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
return 0;
}
+static struct backlight_properties asus_backlight_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = read_brightness,
+ .update_status = set_brightness_status,
+ .max_brightness = 15,
+};
+
+static void __exit asus_acpi_exit(void)
+{
+ if (asus_backlight_device)
+ backlight_device_unregister(asus_backlight_device);
+
+ acpi_bus_unregister_driver(&asus_hotk_driver);
+ remove_proc_entry(PROC_ASUS, acpi_root_dir);
+
+ kfree(asus_info);
+
+ return;
+}
+
static int __init asus_acpi_init(void)
{
int result;
@@ -1370,17 +1400,15 @@ static int __init asus_acpi_init(void)
return result;
}
- return 0;
-}
-
-static void __exit asus_acpi_exit(void)
-{
- acpi_bus_unregister_driver(&asus_hotk_driver);
- remove_proc_entry(PROC_ASUS, acpi_root_dir);
-
- kfree(asus_info);
+ asus_backlight_device = backlight_device_register("asus",NULL,NULL,
+ &asus_backlight_data);
+ if (IS_ERR(asus_backlight_device)) {
+ printk(KERN_ERR "Could not register asus backlight device\n");
+ asus_backlight_device = NULL;
+ asus_acpi_exit();
+ }
- return;
+ return 0;
}
module_init(asus_acpi_init);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 026e40755cd..5f43e0d1489 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -149,7 +149,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
return -ENODEV;
}
- package = (union acpi_object *)buffer.pointer;
+ package = buffer.pointer;
/* Extract Package Data */
@@ -160,12 +160,11 @@ acpi_battery_get_info(struct acpi_battery *battery,
goto end;
}
- data.pointer = kmalloc(data.length, GFP_KERNEL);
+ data.pointer = kzalloc(data.length, GFP_KERNEL);
if (!data.pointer) {
result = -ENOMEM;
goto end;
}
- memset(data.pointer, 0, data.length);
status = acpi_extract_package(package, &format, &data);
if (ACPI_FAILURE(status)) {
@@ -179,7 +178,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
kfree(buffer.pointer);
if (!result)
- (*bif) = (struct acpi_battery_info *)data.pointer;
+ (*bif) = data.pointer;
return result;
}
@@ -209,7 +208,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
return -ENODEV;
}
- package = (union acpi_object *)buffer.pointer;
+ package = buffer.pointer;
/* Extract Package Data */
@@ -220,12 +219,11 @@ acpi_battery_get_status(struct acpi_battery *battery,
goto end;
}
- data.pointer = kmalloc(data.length, GFP_KERNEL);
+ data.pointer = kzalloc(data.length, GFP_KERNEL);
if (!data.pointer) {
result = -ENOMEM;
goto end;
}
- memset(data.pointer, 0, data.length);
status = acpi_extract_package(package, &format, &data);
if (ACPI_FAILURE(status)) {
@@ -239,7 +237,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
kfree(buffer.pointer);
if (!result)
- (*bst) = (struct acpi_battery_status *)data.pointer;
+ (*bst) = data.pointer;
return result;
}
@@ -334,7 +332,7 @@ static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
int result = 0;
- struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ struct acpi_battery *battery = seq->private;
struct acpi_battery_info *bif = NULL;
char *units = "?";
@@ -418,7 +416,7 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
static int acpi_battery_read_state(struct seq_file *seq, void *offset)
{
int result = 0;
- struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ struct acpi_battery *battery = seq->private;
struct acpi_battery_status *bst = NULL;
char *units = "?";
@@ -494,7 +492,7 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
{
- struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ struct acpi_battery *battery = seq->private;
char *units = "?";
@@ -531,8 +529,8 @@ acpi_battery_write_alarm(struct file *file,
{
int result = 0;
char alarm_string[12] = { '\0' };
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_battery *battery = (struct acpi_battery *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_battery *battery = m->private;
if (!battery || (count > sizeof(alarm_string) - 1))
@@ -658,7 +656,7 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_battery *battery = (struct acpi_battery *)data;
+ struct acpi_battery *battery = data;
struct acpi_device *device = NULL;
@@ -694,10 +692,9 @@ static int acpi_battery_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
+ battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
if (!battery)
return -ENOMEM;
- memset(battery, 0, sizeof(struct acpi_battery));
battery->device = device;
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
@@ -742,7 +739,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- battery = (struct acpi_battery *)acpi_driver_data(device);
+ battery = acpi_driver_data(device);
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 279c4bac92e..766332e4559 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -561,6 +561,9 @@ static int __init acpi_bus_init_irq(void)
case ACPI_IRQ_MODEL_IOSAPIC:
message = "IOSAPIC";
break;
+ case ACPI_IRQ_MODEL_PLATFORM:
+ message = "platform specific model";
+ break;
default:
printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
return -ENODEV;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 5ef885e82c7..ac860583c20 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -29,6 +29,7 @@
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/input.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -62,7 +63,7 @@
#define _COMPONENT ACPI_BUTTON_COMPONENT
ACPI_MODULE_NAME("acpi_button")
- MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
MODULE_LICENSE("GPL");
@@ -78,12 +79,14 @@ static struct acpi_driver acpi_button_driver = {
.ops = {
.add = acpi_button_add,
.remove = acpi_button_remove,
- },
+ },
};
struct acpi_button {
struct acpi_device *device; /* Fixed button kludge */
- u8 type;
+ unsigned int type;
+ struct input_dev *input;
+ char phys[32]; /* for input device */
unsigned long pushed;
};
@@ -109,8 +112,7 @@ static struct proc_dir_entry *acpi_button_dir;
static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = (struct acpi_button *)seq->private;
-
+ struct acpi_button *button = seq->private;
if (!button || !button->device)
return 0;
@@ -128,22 +130,17 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_button *button = (struct acpi_button *)seq->private;
+ struct acpi_button *button = seq->private;
acpi_status status;
unsigned long state;
-
if (!button || !button->device)
return 0;
status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state);
- if (ACPI_FAILURE(status)) {
- seq_printf(seq, "state: unsupported\n");
- } else {
- seq_printf(seq, "state: %s\n",
- (state ? "open" : "closed"));
- }
-
+ seq_printf(seq, "state: %s\n",
+ ACPI_FAILURE(status) ? "unsupported" :
+ (state ? "open" : "closed"));
return 0;
}
@@ -159,8 +156,7 @@ static struct proc_dir_entry *acpi_lid_dir;
static int acpi_button_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
- struct acpi_button *button = NULL;
-
+ struct acpi_button *button;
if (!device || !acpi_driver_data(device))
return -EINVAL;
@@ -228,10 +224,8 @@ static int acpi_button_add_fs(struct acpi_device *device)
static int acpi_button_remove_fs(struct acpi_device *device)
{
- struct acpi_button *button = NULL;
-
+ struct acpi_button *button = acpi_driver_data(device);
- button = acpi_driver_data(device);
if (acpi_device_dir(device)) {
if (button->type == ACPI_BUTTON_TYPE_LID)
remove_proc_entry(ACPI_BUTTON_FILE_STATE,
@@ -253,14 +247,34 @@ static int acpi_button_remove_fs(struct acpi_device *device)
static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_button *button = (struct acpi_button *)data;
-
+ struct acpi_button *button = data;
+ struct input_dev *input;
if (!button || !button->device)
return;
switch (event) {
case ACPI_BUTTON_NOTIFY_STATUS:
+ input = button->input;
+
+ if (button->type == ACPI_BUTTON_TYPE_LID) {
+ struct acpi_handle *handle = button->device->handle;
+ unsigned long state;
+
+ if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID",
+ NULL, &state)))
+ input_report_switch(input, SW_LID, !state);
+
+ } else {
+ int keycode = test_bit(KEY_SLEEP, input->keybit) ?
+ KEY_SLEEP : KEY_POWER;
+
+ input_report_key(input, keycode, 1);
+ input_sync(input);
+ input_report_key(input, keycode, 0);
+ }
+ input_sync(input);
+
acpi_bus_generate_event(button->device, event,
++button->pushed);
break;
@@ -275,8 +289,7 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
static acpi_status acpi_button_notify_fixed(void *data)
{
- struct acpi_button *button = (struct acpi_button *)data;
-
+ struct acpi_button *button = data;
if (!button)
return AE_BAD_PARAMETER;
@@ -286,24 +299,75 @@ static acpi_status acpi_button_notify_fixed(void *data)
return AE_OK;
}
-static int acpi_button_add(struct acpi_device *device)
+static int acpi_button_install_notify_handlers(struct acpi_button *button)
{
- int result = 0;
- acpi_status status = AE_OK;
- struct acpi_button *button = NULL;
+ acpi_status status;
+ switch (button->type) {
+ case ACPI_BUTTON_TYPE_POWERF:
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_notify_fixed,
+ button);
+ break;
+ case ACPI_BUTTON_TYPE_SLEEPF:
+ status =
+ acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_notify_fixed,
+ button);
+ break;
+ default:
+ status = acpi_install_notify_handler(button->device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_button_notify,
+ button);
+ break;
+ }
+
+ return ACPI_FAILURE(status) ? -ENODEV : 0;
+}
+
+static void acpi_button_remove_notify_handlers(struct acpi_button *button)
+{
+ switch (button->type) {
+ case ACPI_BUTTON_TYPE_POWERF:
+ acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+ acpi_button_notify_fixed);
+ break;
+ case ACPI_BUTTON_TYPE_SLEEPF:
+ acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_button_notify_fixed);
+ break;
+ default:
+ acpi_remove_notify_handler(button->device->handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_button_notify);
+ break;
+ }
+}
+
+static int acpi_button_add(struct acpi_device *device)
+{
+ int error;
+ struct acpi_button *button;
+ struct input_dev *input;
if (!device)
return -EINVAL;
- button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL);
+ button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
if (!button)
return -ENOMEM;
- memset(button, 0, sizeof(struct acpi_button));
button->device = device;
acpi_driver_data(device) = button;
+ button->input = input = input_allocate_device();
+ if (!input) {
+ error = -ENOMEM;
+ goto err_free_button;
+ }
+
/*
* Determine the button type (via hid), as fixed-feature buttons
* need to be handled a bit differently than generic-space.
@@ -338,39 +402,48 @@ static int acpi_button_add(struct acpi_device *device)
} else {
printk(KERN_ERR PREFIX "Unsupported hid [%s]\n",
acpi_device_hid(device));
- result = -ENODEV;
- goto end;
+ error = -ENODEV;
+ goto err_free_input;
}
- result = acpi_button_add_fs(device);
- if (result)
- goto end;
+ error = acpi_button_add_fs(device);
+ if (error)
+ goto err_free_input;
+
+ error = acpi_button_install_notify_handlers(button);
+ if (error)
+ goto err_remove_fs;
+
+ snprintf(button->phys, sizeof(button->phys),
+ "%s/button/input0", acpi_device_hid(device));
+
+ input->name = acpi_device_name(device);
+ input->phys = button->phys;
+ input->id.bustype = BUS_HOST;
+ input->id.product = button->type;
switch (button->type) {
+ case ACPI_BUTTON_TYPE_POWER:
case ACPI_BUTTON_TYPE_POWERF:
- status =
- acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
- acpi_button_notify_fixed,
- button);
+ input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_POWER, input->keybit);
break;
+
+ case ACPI_BUTTON_TYPE_SLEEP:
case ACPI_BUTTON_TYPE_SLEEPF:
- status =
- acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_button_notify_fixed,
- button);
+ input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_SLEEP, input->keybit);
break;
- default:
- status = acpi_install_notify_handler(device->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_button_notify,
- button);
+
+ case ACPI_BUTTON_TYPE_LID:
+ input->evbit[0] = BIT(EV_SW);
+ set_bit(SW_LID, input->swbit);
break;
}
- if (ACPI_FAILURE(status)) {
- result = -ENODEV;
- goto end;
- }
+ error = input_register_device(input);
+ if (error)
+ goto err_remove_handlers;
if (device->wakeup.flags.valid) {
/* Button's GPE is run-wake GPE */
@@ -385,47 +458,31 @@ static int acpi_button_add(struct acpi_device *device)
printk(KERN_INFO PREFIX "%s [%s]\n",
acpi_device_name(device), acpi_device_bid(device));
- end:
- if (result) {
- acpi_button_remove_fs(device);
- kfree(button);
- }
+ return 0;
- return result;
+ err_remove_handlers:
+ acpi_button_remove_notify_handlers(button);
+ err_remove_fs:
+ acpi_button_remove_fs(device);
+ err_free_input:
+ input_free_device(input);
+ err_free_button:
+ kfree(button);
+ return error;
}
static int acpi_button_remove(struct acpi_device *device, int type)
{
- acpi_status status = 0;
- struct acpi_button *button = NULL;
-
+ struct acpi_button *button;
if (!device || !acpi_driver_data(device))
return -EINVAL;
button = acpi_driver_data(device);
- /* Unregister for device notifications. */
- switch (button->type) {
- case ACPI_BUTTON_TYPE_POWERF:
- status =
- acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
- acpi_button_notify_fixed);
- break;
- case ACPI_BUTTON_TYPE_SLEEPF:
- status =
- acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_button_notify_fixed);
- break;
- default:
- status = acpi_remove_notify_handler(device->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_button_notify);
- break;
- }
-
+ acpi_button_remove_notify_handlers(button);
acpi_button_remove_fs(device);
-
+ input_unregister_device(button->input);
kfree(button);
return 0;
@@ -433,8 +490,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
static int __init acpi_button_init(void)
{
- int result = 0;
-
+ int result;
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
if (!acpi_button_dir)
@@ -451,7 +507,6 @@ static int __init acpi_button_init(void)
static void __exit acpi_button_exit(void)
{
-
acpi_bus_unregister_driver(&acpi_button_driver);
if (acpi_power_dir)
@@ -461,8 +516,6 @@ static void __exit acpi_button_exit(void)
if (acpi_lid_dir)
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
-
- return;
}
module_init(acpi_button_init);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 871aa520ece..0a1863ec91f 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -96,11 +96,10 @@ static int acpi_container_add(struct acpi_device *device)
return -EINVAL;
}
- container = kmalloc(sizeof(struct acpi_container), GFP_KERNEL);
+ container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
if (!container)
return -ENOMEM;
- memset(container, 0, sizeof(struct acpi_container));
container->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
@@ -117,7 +116,7 @@ static int acpi_container_remove(struct acpi_device *device, int type)
acpi_status status = AE_OK;
struct acpi_container *pc = NULL;
- pc = (struct acpi_container *)acpi_driver_data(device);
+ pc = acpi_driver_data(device);
kfree(pc);
return status;
}
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index bf5b79ed361..90990a4b652 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/notifier.h>
+#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -39,13 +40,15 @@ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
MODULE_LICENSE("GPL");
static struct atomic_notifier_head dock_notifier_list;
+static struct platform_device dock_device;
+static char dock_device_name[] = "dock";
struct dock_station {
acpi_handle handle;
unsigned long last_dock_time;
u32 flags;
spinlock_t dd_lock;
- spinlock_t hp_lock;
+ struct mutex hp_lock;
struct list_head dependent_devices;
struct list_head hotplug_devices;
};
@@ -115,9 +118,9 @@ static void
dock_add_hotplug_device(struct dock_station *ds,
struct dock_dependent_device *dd)
{
- spin_lock(&ds->hp_lock);
+ mutex_lock(&ds->hp_lock);
list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
- spin_unlock(&ds->hp_lock);
+ mutex_unlock(&ds->hp_lock);
}
/**
@@ -131,9 +134,9 @@ static void
dock_del_hotplug_device(struct dock_station *ds,
struct dock_dependent_device *dd)
{
- spin_lock(&ds->hp_lock);
+ mutex_lock(&ds->hp_lock);
list_del(&dd->hotplug_list);
- spin_unlock(&ds->hp_lock);
+ mutex_unlock(&ds->hp_lock);
}
/**
@@ -296,7 +299,7 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
{
struct dock_dependent_device *dd;
- spin_lock(&ds->hp_lock);
+ mutex_lock(&ds->hp_lock);
/*
* First call driver specific hotplug functions
@@ -318,15 +321,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
else
dock_create_acpi_device(dd->handle);
}
- spin_unlock(&ds->hp_lock);
+ mutex_unlock(&ds->hp_lock);
}
static void dock_event(struct dock_station *ds, u32 event, int num)
{
+ struct device *dev = &dock_device.dev;
/*
- * we don't do events until someone tells me that
- * they would like to have them.
+ * Indicate that the status of the dock station has
+ * changed.
*/
+ kobject_uevent(&dev->kobj, KOBJ_CHANGE);
}
/**
@@ -441,6 +446,9 @@ static int dock_in_progress(struct dock_station *ds)
*/
int register_dock_notifier(struct notifier_block *nb)
{
+ if (!dock_station)
+ return -ENODEV;
+
return atomic_notifier_chain_register(&dock_notifier_list, nb);
}
@@ -452,6 +460,9 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
*/
void unregister_dock_notifier(struct notifier_block *nb)
{
+ if (!dock_station)
+ return;
+
atomic_notifier_chain_unregister(&dock_notifier_list, nb);
}
@@ -512,6 +523,37 @@ void unregister_hotplug_dock_device(acpi_handle handle)
EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
/**
+ * handle_eject_request - handle an undock request checking for error conditions
+ *
+ * Check to make sure the dock device is still present, then undock and
+ * hotremove all the devices that may need removing.
+ */
+static int handle_eject_request(struct dock_station *ds, u32 event)
+{
+ if (!dock_present(ds))
+ return -ENODEV;
+
+ if (dock_in_progress(ds))
+ return -EBUSY;
+
+ /*
+ * here we need to generate the undock
+ * event prior to actually doing the undock
+ * so that the device struct still exists.
+ */
+ dock_event(ds, event, UNDOCK_EVENT);
+ hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
+ undock(ds);
+ eject_dock(ds);
+ if (dock_present(ds)) {
+ printk(KERN_ERR PREFIX "Unable to undock!\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/**
* dock_notify - act upon an acpi dock notification
* @handle: the dock station handle
* @event: the acpi event
@@ -519,13 +561,11 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
*
* If we are notified to dock, then check to see if the dock is
* present and then dock. Notify all drivers of the dock event,
- * and then hotplug and devices that may need hotplugging. For undock
- * check to make sure the dock device is still present, then undock
- * and hotremove all the devices that may need removing.
+ * and then hotplug and devices that may need hotplugging.
*/
static void dock_notify(acpi_handle handle, u32 event, void *data)
{
- struct dock_station *ds = (struct dock_station *)data;
+ struct dock_station *ds = data;
switch (event) {
case ACPI_NOTIFY_BUS_CHECK:
@@ -553,19 +593,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
* to the driver who wish to hotplug.
*/
case ACPI_NOTIFY_EJECT_REQUEST:
- if (!dock_in_progress(ds) && dock_present(ds)) {
- /*
- * here we need to generate the undock
- * event prior to actually doing the undock
- * so that the device struct still exists.
- */
- dock_event(ds, event, UNDOCK_EVENT);
- hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
- undock(ds);
- eject_dock(ds);
- if (dock_present(ds))
- printk(KERN_ERR PREFIX "Unable to undock!\n");
- }
+ handle_eject_request(ds, event);
break;
default:
printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
@@ -588,7 +616,7 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
acpi_handle tmp;
- struct dock_station *ds = (struct dock_station *)context;
+ struct dock_station *ds = context;
struct dock_dependent_device *dd;
status = acpi_bus_get_ejd(handle, &tmp);
@@ -604,6 +632,33 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
}
+/*
+ * show_docked - read method for "docked" file in sysfs
+ */
+static ssize_t show_docked(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
+
+}
+DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
+
+/*
+ * write_undock - write method for "undock" file in sysfs
+ */
+static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+
+ if (!count)
+ return -EINVAL;
+
+ ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
+ return ret ? ret: count;
+}
+DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
+
/**
* dock_add - add a new dock station
* @handle: the dock station handle
@@ -626,9 +681,33 @@ static int dock_add(acpi_handle handle)
INIT_LIST_HEAD(&dock_station->dependent_devices);
INIT_LIST_HEAD(&dock_station->hotplug_devices);
spin_lock_init(&dock_station->dd_lock);
- spin_lock_init(&dock_station->hp_lock);
+ mutex_init(&dock_station->hp_lock);
ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
+ /* initialize platform device stuff */
+ dock_device.name = dock_device_name;
+ ret = platform_device_register(&dock_device);
+ if (ret) {
+ printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);
+ kfree(dock_station);
+ return ret;
+ }
+ ret = device_create_file(&dock_device.dev, &dev_attr_docked);
+ if (ret) {
+ printk("Error %d adding sysfs file\n", ret);
+ platform_device_unregister(&dock_device);
+ kfree(dock_station);
+ return ret;
+ }
+ ret = device_create_file(&dock_device.dev, &dev_attr_undock);
+ if (ret) {
+ printk("Error %d adding sysfs file\n", ret);
+ device_remove_file(&dock_device.dev, &dev_attr_docked);
+ platform_device_unregister(&dock_device);
+ kfree(dock_station);
+ return ret;
+ }
+
/* Find dependent devices */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_dock_devices, dock_station,
@@ -638,7 +717,8 @@ static int dock_add(acpi_handle handle)
dd = alloc_dock_dependent_device(handle);
if (!dd) {
kfree(dock_station);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto dock_add_err_unregister;
}
add_dock_dependent_device(dock_station, dd);
@@ -658,8 +738,12 @@ static int dock_add(acpi_handle handle)
return 0;
dock_add_err:
- kfree(dock_station);
kfree(dd);
+dock_add_err_unregister:
+ device_remove_file(&dock_device.dev, &dev_attr_docked);
+ device_remove_file(&dock_device.dev, &dev_attr_undock);
+ platform_device_unregister(&dock_device);
+ kfree(dock_station);
return ret;
}
@@ -686,6 +770,11 @@ static int dock_remove(void)
if (ACPI_FAILURE(status))
printk(KERN_ERR "Error removing notify handler\n");
+ /* cleanup sysfs */
+ device_remove_file(&dock_device.dev, &dev_attr_docked);
+ device_remove_file(&dock_device.dev, &dev_attr_undock);
+ platform_device_unregister(&dock_device);
+
/* free dock station memory */
kfree(dock_station);
return 0;
@@ -703,7 +792,7 @@ static int dock_remove(void)
static acpi_status
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- int *count = (int *)context;
+ int *count = context;
acpi_status status = AE_OK;
if (is_dock(handle)) {
@@ -726,7 +815,7 @@ static int __init dock_init(void)
ACPI_UINT32_MAX, find_dock, &num, NULL);
if (!num)
- return -ENODEV;
+ printk(KERN_INFO "No dock devices found.\n");
return 0;
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e6d4b084dca..cbdf031f3c0 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -45,35 +45,34 @@ ACPI_MODULE_NAME("acpi_ec")
#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
-
+#undef PREFIX
+#define PREFIX "ACPI: EC: "
/* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
-
/* EC commands */
-#define ACPI_EC_COMMAND_READ 0x80
-#define ACPI_EC_COMMAND_WRITE 0x81
-#define ACPI_EC_BURST_ENABLE 0x82
-#define ACPI_EC_BURST_DISABLE 0x83
-#define ACPI_EC_COMMAND_QUERY 0x84
-
+enum ec_command {
+ ACPI_EC_COMMAND_READ = 0x80,
+ ACPI_EC_COMMAND_WRITE = 0x81,
+ ACPI_EC_BURST_ENABLE = 0x82,
+ ACPI_EC_BURST_DISABLE = 0x83,
+ ACPI_EC_COMMAND_QUERY = 0x84,
+};
/* EC events */
-enum {
+enum ec_event {
ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
- ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
+ ACPI_EC_EVENT_IBF_0, /* Input buffer empty */
};
-#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */
+#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
-#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
-#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
-enum {
- EC_INTR = 1, /* Output buffer full */
- EC_POLL, /* Input buffer empty */
-};
+static enum ec_mode {
+ EC_INTR = 1, /* Output buffer full */
+ EC_POLL, /* Input buffer empty */
+} acpi_ec_mode = EC_INTR;
static int acpi_ec_remove(struct acpi_device *device, int type);
static int acpi_ec_start(struct acpi_device *device);
@@ -93,22 +92,21 @@ static struct acpi_driver acpi_ec_driver = {
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
-struct acpi_ec {
+static struct acpi_ec {
acpi_handle handle;
unsigned long uid;
- unsigned long gpe_bit;
+ unsigned long gpe;
unsigned long command_addr;
unsigned long data_addr;
unsigned long global_lock;
- struct semaphore sem;
- unsigned int expect_event;
+ struct mutex lock;
+ atomic_t query_pending;
atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
wait_queue_head_t wait;
} *ec_ecdt;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
-static int acpi_ec_mode = EC_INTR;
/* --------------------------------------------------------------------------
Transaction Management
@@ -134,54 +132,41 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
-static int acpi_ec_check_status(u8 status, u8 event)
+static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
{
- switch (event) {
- case ACPI_EC_EVENT_OBF_1:
+ u8 status = acpi_ec_read_status(ec);
+
+ if (event == ACPI_EC_EVENT_OBF_1) {
if (status & ACPI_EC_FLAG_OBF)
return 1;
- break;
- case ACPI_EC_EVENT_IBF_0:
+ } else if (event == ACPI_EC_EVENT_IBF_0) {
if (!(status & ACPI_EC_FLAG_IBF))
return 1;
- break;
- default:
- break;
}
return 0;
}
-static int acpi_ec_wait(struct acpi_ec *ec, u8 event)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event)
{
- int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0;
- long time_left;
-
- ec->expect_event = event;
- if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
- ec->expect_event = 0;
- return 0;
- }
-
- do {
- if (acpi_ec_mode == EC_POLL) {
- udelay(ACPI_EC_UDELAY);
- } else {
- time_left = wait_event_timeout(ec->wait,
- !ec->expect_event,
- msecs_to_jiffies(ACPI_EC_DELAY));
- if (time_left > 0) {
- ec->expect_event = 0;
+ if (acpi_ec_mode == EC_POLL) {
+ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+ while (time_before(jiffies, delay)) {
+ if (acpi_ec_check_status(ec, event))
return 0;
- }
}
- if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
- ec->expect_event = 0;
+ } else {
+ if (wait_event_timeout(ec->wait,
+ acpi_ec_check_status(ec, event),
+ msecs_to_jiffies(ACPI_EC_DELAY)) ||
+ acpi_ec_check_status(ec, event)) {
return 0;
+ } else {
+ printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
+ " status = %d, expect_event = %d\n",
+ acpi_ec_read_status(ec), event);
}
- } while (--i > 0);
-
- ec->expect_event = 0;
+ }
return -ETIME;
}
@@ -196,7 +181,6 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
u8 tmp = 0;
u8 status = 0;
-
status = acpi_ec_read_status(ec);
if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
@@ -212,7 +196,7 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec)
atomic_set(&ec->leaving_burst, 0);
return 0;
- end:
+ end:
ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode"));
return -1;
}
@@ -221,58 +205,68 @@ int acpi_ec_leave_burst_mode(struct acpi_ec *ec)
{
u8 status = 0;
-
status = acpi_ec_read_status(ec);
- if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
+ if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) {
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
- if(status)
+ if (status)
goto end;
acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE);
acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
}
atomic_set(&ec->leaving_burst, 1);
return 0;
- end:
+ end:
ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"));
return -1;
}
-#endif /* ACPI_FUTURE_USAGE */
+#endif /* ACPI_FUTURE_USAGE */
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
- const u8 *wdata, unsigned wdata_len,
- u8 *rdata, unsigned rdata_len)
+ const u8 * wdata, unsigned wdata_len,
+ u8 * rdata, unsigned rdata_len)
{
- int result;
+ int result = 0;
acpi_ec_write_cmd(ec, command);
- for (; wdata_len > 0; wdata_len --) {
+ for (; wdata_len > 0; --wdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
- if (result)
- return result;
+ if (result) {
+ printk(KERN_ERR PREFIX
+ "write_cmd timeout, command = %d\n", command);
+ goto end;
+ }
acpi_ec_write_data(ec, *(wdata++));
}
- if (command == ACPI_EC_COMMAND_WRITE) {
+ if (!rdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
- if (result)
- return result;
+ if (result) {
+ printk(KERN_ERR PREFIX
+ "finish-write timeout, command = %d\n", command);
+ goto end;
+ }
+ } else if (command == ACPI_EC_COMMAND_QUERY) {
+ atomic_set(&ec->query_pending, 0);
}
- for (; rdata_len > 0; rdata_len --) {
+ for (; rdata_len > 0; --rdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
- if (result)
- return result;
+ if (result) {
+ printk(KERN_ERR PREFIX "read timeout, command = %d\n",
+ command);
+ goto end;
+ }
*(rdata++) = acpi_ec_read_data(ec);
}
-
- return 0;
+ end:
+ return result;
}
static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
- const u8 *wdata, unsigned wdata_len,
- u8 *rdata, unsigned rdata_len)
+ const u8 * wdata, unsigned wdata_len,
+ u8 * rdata, unsigned rdata_len)
{
int status;
u32 glk;
@@ -280,36 +274,40 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
return -EINVAL;
- if (rdata)
- memset(rdata, 0, rdata_len);
+ if (rdata)
+ memset(rdata, 0, rdata_len);
+ mutex_lock(&ec->lock);
if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
return -ENODEV;
}
- down(&ec->sem);
+
+ /* Make sure GPE is enabled before doing transaction */
+ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
if (status) {
- printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX
+ "input buffer is not empty, aborting transaction\n");
goto end;
}
- status = acpi_ec_transaction_unlocked(ec, command,
- wdata, wdata_len,
- rdata, rdata_len);
+ status = acpi_ec_transaction_unlocked(ec, command,
+ wdata, wdata_len,
+ rdata, rdata_len);
-end:
- up(&ec->sem);
+ end:
if (ec->global_lock)
acpi_release_global_lock(glk);
+ mutex_unlock(&ec->lock);
return status;
}
-static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
+static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
{
int result;
u8 d;
@@ -322,15 +320,15 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
{
- u8 wdata[2] = { address, data };
- return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
+ u8 wdata[2] = { address, data };
+ return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
wdata, 2, NULL, 0);
}
/*
* Externally callable EC access functions. For now, assume 1 EC only
*/
-int ec_read(u8 addr, u8 *val)
+int ec_read(u8 addr, u8 * val)
{
struct acpi_ec *ec;
int err;
@@ -369,9 +367,9 @@ int ec_write(u8 addr, u8 val)
EXPORT_SYMBOL(ec_write);
-extern int ec_transaction(u8 command,
- const u8 *wdata, unsigned wdata_len,
- u8 *rdata, unsigned rdata_len)
+int ec_transaction(u8 command,
+ const u8 * wdata, unsigned wdata_len,
+ u8 * rdata, unsigned rdata_len)
{
struct acpi_ec *ec;
@@ -386,65 +384,49 @@ extern int ec_transaction(u8 command,
EXPORT_SYMBOL(ec_transaction);
-static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
+static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
{
int result;
- u8 d;
+ u8 d;
- if (!ec || !data)
- return -EINVAL;
+ if (!ec || !data)
+ return -EINVAL;
- /*
- * Query the EC to find out which _Qxx method we need to evaluate.
- * Note that successful completion of the query causes the ACPI_EC_SCI
- * bit to be cleared (and thus clearing the interrupt source).
- */
+ /*
+ * Query the EC to find out which _Qxx method we need to evaluate.
+ * Note that successful completion of the query causes the ACPI_EC_SCI
+ * bit to be cleared (and thus clearing the interrupt source).
+ */
- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
- if (result)
- return result;
+ result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
+ if (result)
+ return result;
- if (!d)
- return -ENODATA;
+ if (!d)
+ return -ENODATA;
- *data = d;
- return 0;
+ *data = d;
+ return 0;
}
/* --------------------------------------------------------------------------
Event Management
-------------------------------------------------------------------------- */
-struct acpi_ec_query_data {
- acpi_handle handle;
- u8 data;
-};
-
static void acpi_ec_gpe_query(void *ec_cxt)
{
struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
u8 value = 0;
- static char object_name[8];
+ char object_name[8];
- if (!ec)
- goto end;
-
- value = acpi_ec_read_status(ec);
-
- if (!(value & ACPI_EC_FLAG_SCI))
- goto end;
-
- if (acpi_ec_query(ec, &value))
- goto end;
+ if (!ec || acpi_ec_query(ec, &value))
+ return;
snprintf(object_name, 8, "_Q%2.2X", value);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
-
- end:
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
}
static u32 acpi_ec_gpe_handler(void *data)
@@ -453,22 +435,18 @@ static u32 acpi_ec_gpe_handler(void *data)
u8 value;
struct acpi_ec *ec = (struct acpi_ec *)data;
- acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR);
- value = acpi_ec_read_status(ec);
-
if (acpi_ec_mode == EC_INTR) {
- if (acpi_ec_check_status(value, ec->expect_event)) {
- ec->expect_event = 0;
- wake_up(&ec->wait);
- }
+ wake_up(&ec->wait);
}
- if (value & ACPI_EC_FLAG_SCI) {
- status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
- return status == AE_OK ?
- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
+ value = acpi_ec_read_status(ec);
+ if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
+ atomic_set(&ec->query_pending, 1);
+ status =
+ acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query,
+ ec);
}
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
+
return status == AE_OK ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
@@ -504,7 +482,6 @@ acpi_ec_space_handler(u32 function,
acpi_integer f_v = 0;
int i = 0;
-
if ((address > 0xFF) || !value || !handler_context)
return AE_BAD_PARAMETER;
@@ -518,7 +495,7 @@ acpi_ec_space_handler(u32 function,
switch (function) {
case ACPI_READ:
temp = 0;
- result = acpi_ec_read(ec, (u8) address, (u8 *) &temp);
+ result = acpi_ec_read(ec, (u8) address, (u8 *) & temp);
break;
case ACPI_WRITE:
result = acpi_ec_write(ec, (u8) address, (u8) temp);
@@ -571,18 +548,15 @@ static int acpi_ec_read_info(struct seq_file *seq, void *offset)
{
struct acpi_ec *ec = (struct acpi_ec *)seq->private;
-
if (!ec)
goto end;
- seq_printf(seq, "gpe bit: 0x%02x\n",
- (u32) ec->gpe_bit);
+ seq_printf(seq, "gpe: 0x%02x\n", (u32) ec->gpe);
seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
- (u32) ec->command_addr,
- (u32) ec->data_addr);
+ (u32) ec->command_addr, (u32) ec->data_addr);
seq_printf(seq, "use global lock: %s\n",
ec->global_lock ? "yes" : "no");
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
end:
return 0;
@@ -605,7 +579,6 @@ static int acpi_ec_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
-
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_ec_dir);
@@ -648,18 +621,17 @@ static int acpi_ec_add(struct acpi_device *device)
acpi_status status = AE_OK;
struct acpi_ec *ec = NULL;
-
if (!device)
return -EINVAL;
- ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec)
return -ENOMEM;
- memset(ec, 0, sizeof(struct acpi_ec));
ec->handle = device->handle;
ec->uid = -1;
- init_MUTEX(&ec->sem);
+ mutex_init(&ec->lock);
+ atomic_set(&ec->query_pending, 0);
if (acpi_ec_mode == EC_INTR) {
atomic_set(&ec->leaving_burst, 1);
init_waitqueue_head(&ec->wait);
@@ -669,8 +641,7 @@ static int acpi_ec_add(struct acpi_device *device)
acpi_driver_data(device) = ec;
/* Use the global lock for all EC transactions? */
- acpi_evaluate_integer(ec->handle, "_GLK", NULL,
- &ec->global_lock);
+ acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
@@ -679,7 +650,7 @@ static int acpi_ec_add(struct acpi_device *device)
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler);
- acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+ acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
&acpi_ec_gpe_handler);
kfree(ec_ecdt);
@@ -687,11 +658,10 @@ static int acpi_ec_add(struct acpi_device *device)
/* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
- status =
- acpi_evaluate_integer(ec->handle, "_GPE", NULL,
- &ec->gpe_bit);
+ status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe);
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment"));
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Obtaining GPE bit assignment"));
result = -ENODEV;
goto end;
}
@@ -701,13 +671,13 @@ static int acpi_ec_add(struct acpi_device *device)
goto end;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
- acpi_device_name(device), acpi_device_bid(device),
- (u32) ec->gpe_bit));
+ acpi_device_name(device), acpi_device_bid(device),
+ (u32) ec->gpe));
if (!first_ec)
first_ec = device;
- end:
+ end:
if (result)
kfree(ec);
@@ -718,7 +688,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
{
struct acpi_ec *ec = NULL;
-
if (!device)
return -EINVAL;
@@ -761,7 +730,6 @@ static int acpi_ec_start(struct acpi_device *device)
acpi_status status = AE_OK;
struct acpi_ec *ec = NULL;
-
if (!device)
return -EINVAL;
@@ -782,27 +750,26 @@ static int acpi_ec_start(struct acpi_device *device)
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
- ec->gpe_bit, ec->command_addr, ec->data_addr));
+ ec->gpe, ec->command_addr, ec->data_addr));
/*
* Install GPE handler
*/
- status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
+ status = acpi_install_gpe_handler(NULL, ec->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) {
return -ENODEV;
}
- acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
+ acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
&acpi_ec_space_setup, ec);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec->gpe_bit,
- &acpi_ec_gpe_handler);
+ acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
return -ENODEV;
}
@@ -814,7 +781,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
acpi_status status = AE_OK;
struct acpi_ec *ec = NULL;
-
if (!device)
return -EINVAL;
@@ -826,9 +792,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
if (ACPI_FAILURE(status))
return -ENODEV;
- status =
- acpi_remove_gpe_handler(NULL, ec->gpe_bit,
- &acpi_ec_gpe_handler);
+ status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -841,7 +805,7 @@ acpi_fake_ecdt_callback(acpi_handle handle,
{
acpi_status status;
- init_MUTEX(&ec_ecdt->sem);
+ mutex_init(&ec_ecdt->lock);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
@@ -853,16 +817,15 @@ acpi_fake_ecdt_callback(acpi_handle handle,
ec_ecdt->uid = -1;
acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid);
- status =
- acpi_evaluate_integer(handle, "_GPE", NULL,
- &ec_ecdt->gpe_bit);
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe);
if (ACPI_FAILURE(status))
return status;
ec_ecdt->global_lock = TRUE;
ec_ecdt->handle = handle;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
- ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr));
+ ec_ecdt->gpe, ec_ecdt->command_addr,
+ ec_ecdt->data_addr));
return AE_CTRL_TERMINATE;
}
@@ -884,12 +847,11 @@ static int __init acpi_ec_fake_ecdt(void)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT"));
- ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec_ecdt) {
ret = -ENOMEM;
goto error;
}
- memset(ec_ecdt, 0, sizeof(struct acpi_ec));
status = acpi_get_devices(ACPI_EC_HID,
acpi_fake_ecdt_callback, NULL, NULL);
@@ -901,7 +863,7 @@ static int __init acpi_ec_fake_ecdt(void)
goto error;
}
return 0;
- error:
+ error:
return ret;
}
@@ -921,30 +883,28 @@ static int __init acpi_ec_get_real_ecdt(void)
/*
* Generate a temporary ec context to use until the namespace is scanned
*/
- ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ ec_ecdt = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec_ecdt)
return -ENOMEM;
- memset(ec_ecdt, 0, sizeof(struct acpi_ec));
- init_MUTEX(&ec_ecdt->sem);
+ mutex_init(&ec_ecdt->lock);
if (acpi_ec_mode == EC_INTR) {
init_waitqueue_head(&ec_ecdt->wait);
}
ec_ecdt->command_addr = ecdt_ptr->ec_control.address;
ec_ecdt->data_addr = ecdt_ptr->ec_data.address;
- ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
+ ec_ecdt->gpe = ecdt_ptr->gpe_bit;
/* use the GL just to be safe */
ec_ecdt->global_lock = TRUE;
ec_ecdt->uid = ecdt_ptr->uid;
- status =
- acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
+ status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
if (ACPI_FAILURE(status)) {
goto error;
}
return 0;
- error:
+ error:
ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT"));
kfree(ec_ecdt);
ec_ecdt = NULL;
@@ -970,14 +930,14 @@ int __init acpi_ec_ecdt_probe(void)
/*
* Install GPE handler
*/
- status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
+ status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe,
ACPI_GPE_EDGE_TRIGGERED,
&acpi_ec_gpe_handler, ec_ecdt);
if (ACPI_FAILURE(status)) {
goto error;
}
- acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
- acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
+ acpi_set_gpe_type(NULL, ec_ecdt->gpe, ACPI_GPE_TYPE_RUNTIME);
+ acpi_enable_gpe(NULL, ec_ecdt->gpe, ACPI_NOT_ISR);
status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC,
@@ -985,7 +945,7 @@ int __init acpi_ec_ecdt_probe(void)
&acpi_ec_space_setup,
ec_ecdt);
if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
+ acpi_remove_gpe_handler(NULL, ec_ecdt->gpe,
&acpi_ec_gpe_handler);
goto error;
}
@@ -1004,7 +964,6 @@ static int __init acpi_ec_init(void)
{
int result = 0;
-
if (acpi_disabled)
return 0;
@@ -1057,7 +1016,8 @@ static int __init acpi_ec_set_intr_mode(char *str)
acpi_ec_mode = EC_POLL;
}
acpi_ec_driver.ops.add = acpi_ec_add;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", intr ? "interrupt" : "polling"));
+ printk(KERN_NOTICE PREFIX "%s mode.\n",
+ intr ? "interrupt" : "polling");
return 1;
}
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index ee2a10bf907..bf63edc6608 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -331,7 +331,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
static u32 acpi_ev_global_lock_handler(void *context)
{
u8 acquired = FALSE;
- acpi_status status;
/*
* Attempt to get the lock
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 3a39c2e8e10..bf90f04f2c6 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -266,10 +266,10 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
walk_state->thread->thread_id)
&& (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) {
ACPI_ERROR((AE_INFO,
- "Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
- (u32) walk_state->thread->thread_id,
+ "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
+ (unsigned long)walk_state->thread->thread_id,
acpi_ut_get_node_name(obj_desc->mutex.node),
- (u32) obj_desc->mutex.owner_thread->thread_id));
+ (unsigned long)obj_desc->mutex.owner_thread->thread_id));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 045c89477e5..f305a826ca2 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -99,8 +99,8 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_fan *fan = (struct acpi_fan *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_fan *fan = m->private;
char state_string[12] = { '\0' };
@@ -186,10 +186,9 @@ static int acpi_fan_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL);
+ fan = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL);
if (!fan)
return -ENOMEM;
- memset(fan, 0, sizeof(struct acpi_fan));
fan->device = device;
strcpy(acpi_device_name(device), "Fan");
@@ -229,7 +228,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- fan = (struct acpi_fan *)acpi_driver_data(device);
+ fan = acpi_driver_data(device);
acpi_fan_remove_fs(device);
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index a2f46d587d5..8a0324b43e5 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -96,7 +96,7 @@ struct acpi_find_pci_root {
static acpi_status
do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
- unsigned long *busnr = (unsigned long *)data;
+ unsigned long *busnr = data;
struct acpi_resource_address64 address;
if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
@@ -189,8 +189,12 @@ find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv)
bus = tmp;
if (seg == find->seg && bus == find->bus)
+ {
find->handle = handle;
- status = AE_OK;
+ status = AE_CTRL_TERMINATE;
+ }
+ else
+ status = AE_OK;
exit:
kfree(buffer.pointer);
return status;
@@ -217,7 +221,7 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
acpi_status status;
struct acpi_device_info *info;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_find_child *find = (struct acpi_find_child *)context;
+ struct acpi_find_child *find = context;
status = acpi_get_object_info(handle, &buffer);
if (ACPI_SUCCESS(status)) {
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index 1ba2db67186..8edfb92f7ed 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -265,8 +265,7 @@ static char *format_result(union acpi_object *object)
static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_polling_hotkey *poll_hotkey =
- (struct acpi_polling_hotkey *)seq->private;
+ struct acpi_polling_hotkey *poll_hotkey = seq->private;
char *buf;
@@ -577,7 +576,7 @@ init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
if (ACPI_FAILURE(status))
goto do_fail_zero;
key->poll_hotkey.poll_result =
- (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+ kmalloc(sizeof(union acpi_object), GFP_KERNEL);
if (!key->poll_hotkey.poll_result)
goto do_fail_zero;
return AE_OK;
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
index 6342e612c20..8338be0990b 100644
--- a/drivers/acpi/i2c_ec.c
+++ b/drivers/acpi/i2c_ec.c
@@ -309,18 +309,16 @@ static int acpi_ec_hc_add(struct acpi_device *device)
return -EINVAL;
}
- ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
+ ec_hc = kzalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
if (!ec_hc) {
return -ENOMEM;
}
- memset(ec_hc, 0, sizeof(struct acpi_ec_hc));
- smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
+ smbus = kzalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
if (!smbus) {
kfree(ec_hc);
return -ENOMEM;
}
- memset(smbus, 0, sizeof(struct acpi_ec_smbus));
ec_hc->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
@@ -393,7 +391,7 @@ static void __exit acpi_ec_hc_exit(void)
struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
{
- return ((struct acpi_ec_hc *)acpi_driver_data(device->parent));
+ return acpi_driver_data(device->parent);
}
EXPORT_SYMBOL(acpi_get_ec_hc);
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 003a9876c96..c6144ca6663 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -3,6 +3,7 @@
*
*
* Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
+ * Copyright (C) 2006 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,10 +20,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define IBM_VERSION "0.12a"
+#define IBM_VERSION "0.13"
/*
* Changelog:
+ *
+ * 2006-11-22 0.13 new maintainer
+ * changelog now lives in git commit history, and will
+ * not be updated further in-file.
*
* 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels
* 2005-03-17 0.11 support for 600e, 770x
@@ -77,9 +82,16 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/string.h>
+
#include <linux/proc_fs.h>
+#include <linux/backlight.h>
#include <asm/uaccess.h>
+#include <linux/dmi.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+
#include <acpi/acpi_drivers.h>
#include <acpi/acnamesp.h>
@@ -88,7 +100,7 @@
#define IBM_FILE "ibm_acpi"
#define IBM_URL "http://ibm-acpi.sf.net/"
-MODULE_AUTHOR("Borislav Deianov");
+MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
MODULE_DESCRIPTION(IBM_DESC);
MODULE_VERSION(IBM_VERSION);
MODULE_LICENSE("GPL");
@@ -116,28 +128,6 @@ static acpi_handle root_handle = NULL;
static char *object##_path; \
static char *object##_paths[] = { paths }
-/*
- * The following models are supported to various degrees:
- *
- * 570, 600e, 600x, 770e, 770x
- * A20m, A21e, A21m, A21p, A22p, A30, A30p, A31, A31p
- * G40, G41
- * R30, R31, R32, R40, R40e, R50, R50e, R50p, R51
- * T20, T21, T22, T23, T30, T40, T40p, T41, T41p, T42, T42p, T43
- * X20, X21, X22, X23, X24, X30, X31, X40
- *
- * The following models have no supported features:
- *
- * 240, 240x, i1400
- *
- * Still missing DSDTs for the following models:
- *
- * A20p, A22e, A22m
- * R52
- * S31
- * T43p
- */
-
IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */
"\\_SB.PCI.ISA.EC", /* 570 */
"\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */
@@ -169,6 +159,7 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */
#endif
IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */
"\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
+ "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
"\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
); /* A21e, R30, R31 */
@@ -203,7 +194,7 @@ IBM_HANDLE(led, ec, "SLED", /* 570 */
IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */
IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */
-IBM_HANDLE(fans, ec, "FANS"); /* X31, X40 */
+IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */
IBM_HANDLE(gfan, ec, "GFAN", /* 570 */
"\\FSPD", /* 600e/x, 770e, 770x */
@@ -216,6 +207,152 @@ IBM_HANDLE(sfan, ec, "SFAN", /* 570 */
#define IBM_HKEY_HID "IBM0068"
#define IBM_PCI_HID "PNP0A03"
+enum thermal_access_mode {
+ IBMACPI_THERMAL_NONE = 0, /* No thermal support */
+ IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */
+ IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */
+ IBMACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */
+ IBMACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */
+};
+
+#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
+struct ibm_thermal_sensors_struct {
+ s32 temp[IBMACPI_MAX_THERMAL_SENSORS];
+};
+
+/*
+ * FAN ACCESS MODES
+ *
+ * IBMACPI_FAN_RD_ACPI_GFAN:
+ * ACPI GFAN method: returns fan level
+ *
+ * see IBMACPI_FAN_WR_ACPI_SFAN
+ * EC 0x2f not available if GFAN exists
+ *
+ * IBMACPI_FAN_WR_ACPI_SFAN:
+ * ACPI SFAN method: sets fan level, 0 (stop) to 7 (max)
+ *
+ * EC 0x2f might be available *for reading*, but never for writing.
+ *
+ * IBMACPI_FAN_WR_TPEC:
+ * ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported
+ * on almost all ThinkPads
+ *
+ * Fan speed changes of any sort (including those caused by the
+ * disengaged mode) are usually done slowly by the firmware as the
+ * maximum ammount of fan duty cycle change per second seems to be
+ * limited.
+ *
+ * Reading is not available if GFAN exists.
+ * Writing is not available if SFAN exists.
+ *
+ * Bits
+ * 7 automatic mode engaged;
+ * (default operation mode of the ThinkPad)
+ * fan level is ignored in this mode.
+ * 6 disengage mode (takes precedence over bit 7);
+ * not available on all thinkpads. May disable
+ * the tachometer, and speeds up fan to 100% duty-cycle,
+ * which speeds it up far above the standard RPM
+ * levels. It is not impossible that it could cause
+ * hardware damage.
+ * 5-3 unused in some models. Extra bits for fan level
+ * in others, but still useless as all values above
+ * 7 map to the same speed as level 7 in these models.
+ * 2-0 fan level (0..7 usually)
+ * 0x00 = stop
+ * 0x07 = max (set when temperatures critical)
+ * Some ThinkPads may have other levels, see
+ * IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41)
+ *
+ * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at
+ * boot. Apparently the EC does not intialize it, so unless ACPI DSDT
+ * does so, its initial value is meaningless (0x07).
+ *
+ * For firmware bugs, refer to:
+ * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
+ *
+ * ----
+ *
+ * ThinkPad EC register 0x84 (LSB), 0x85 (MSB):
+ * Main fan tachometer reading (in RPM)
+ *
+ * This register is present on all ThinkPads with a new-style EC, and
+ * it is known not to be present on the A21m/e, and T22, as there is
+ * something else in offset 0x84 according to the ACPI DSDT. Other
+ * ThinkPads from this same time period (and earlier) probably lack the
+ * tachometer as well.
+ *
+ * Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare
+ * was never fixed by IBM to report the EC firmware version string
+ * probably support the tachometer (like the early X models), so
+ * detecting it is quite hard. We need more data to know for sure.
+ *
+ * FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings
+ * might result.
+ *
+ * FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this
+ * register is not invalidated in ThinkPads that disable tachometer
+ * readings. Thus, the tachometer readings go stale.
+ *
+ * For firmware bugs, refer to:
+ * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
+ *
+ * IBMACPI_FAN_WR_ACPI_FANS:
+ * ThinkPad X31, X40, X41. Not available in the X60.
+ *
+ * FANS ACPI handle: takes three arguments: low speed, medium speed,
+ * high speed. ACPI DSDT seems to map these three speeds to levels
+ * as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH
+ * (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3")
+ *
+ * The speeds are stored on handles
+ * (FANA:FAN9), (FANC:FANB), (FANE:FAND).
+ *
+ * There are three default speed sets, acessible as handles:
+ * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
+ *
+ * ACPI DSDT switches which set is in use depending on various
+ * factors.
+ *
+ * IBMACPI_FAN_WR_TPEC is also available and should be used to
+ * command the fan. The X31/X40/X41 seems to have 8 fan levels,
+ * but the ACPI tables just mention level 7.
+ */
+
+enum fan_status_access_mode {
+ IBMACPI_FAN_NONE = 0, /* No fan status or control */
+ IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */
+ IBMACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */
+};
+
+enum fan_control_access_mode {
+ IBMACPI_FAN_WR_NONE = 0, /* No fan control */
+ IBMACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */
+ IBMACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */
+ IBMACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */
+};
+
+enum fan_control_commands {
+ IBMACPI_FAN_CMD_SPEED = 0x0001, /* speed command */
+ IBMACPI_FAN_CMD_LEVEL = 0x0002, /* level command */
+ IBMACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd,
+ * and also watchdog cmd */
+};
+
+enum { /* Fan control constants */
+ fan_status_offset = 0x2f, /* EC register 0x2f */
+ fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
+ * 0x84 must be read before 0x85 */
+
+ IBMACPI_FAN_EC_DISENGAGED = 0x40, /* EC mode: tachometer
+ * disengaged */
+ IBMACPI_FAN_EC_AUTO = 0x80, /* EC mode: auto fan
+ * control */
+};
+
+static char *ibm_thinkpad_ec_found = NULL;
+
struct ibm_struct {
char *name;
char param[32];
@@ -243,6 +380,8 @@ struct ibm_struct {
static struct proc_dir_entry *proc_dir = NULL;
+static struct backlight_device *ibm_backlight_device = NULL;
+
#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
#define strlencmp(a,b) (strncmp((a), (b), strlen(b)))
@@ -352,7 +491,7 @@ static char *next_cmd(char **cmds)
return start;
}
-static int driver_init(void)
+static int ibm_acpi_driver_init(void)
{
printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
printk(IBM_INFO "%s\n", IBM_URL);
@@ -581,8 +720,7 @@ static int wan_status(void)
{
int status;
- if (!wan_supported ||
- !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+ if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
status = 0;
return status;
@@ -630,12 +768,15 @@ static int wan_write(char *buf)
return 0;
}
-static int video_supported;
-static int video_orig_autosw;
+enum video_access_mode {
+ IBMACPI_VIDEO_NONE = 0,
+ IBMACPI_VIDEO_570, /* 570 */
+ IBMACPI_VIDEO_770, /* 600e/x, 770e, 770x */
+ IBMACPI_VIDEO_NEW, /* all others */
+};
-#define VIDEO_570 1
-#define VIDEO_770 2
-#define VIDEO_NEW 3
+static enum video_access_mode video_supported;
+static int video_orig_autosw;
static int video_init(void)
{
@@ -647,16 +788,16 @@ static int video_init(void)
if (!vid_handle)
/* video switching not supported on R30, R31 */
- video_supported = 0;
+ video_supported = IBMACPI_VIDEO_NONE;
else if (acpi_evalf(vid_handle, &video_orig_autosw, "SWIT", "qd"))
/* 570 */
- video_supported = VIDEO_570;
+ video_supported = IBMACPI_VIDEO_570;
else if (acpi_evalf(vid_handle, &video_orig_autosw, "^VADL", "qd"))
/* 600e/x, 770e, 770x */
- video_supported = VIDEO_770;
+ video_supported = IBMACPI_VIDEO_770;
else
/* all others */
- video_supported = VIDEO_NEW;
+ video_supported = IBMACPI_VIDEO_NEW;
return 0;
}
@@ -666,15 +807,15 @@ static int video_status(void)
int status = 0;
int i;
- if (video_supported == VIDEO_570) {
+ if (video_supported == IBMACPI_VIDEO_570) {
if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87))
status = i & 3;
- } else if (video_supported == VIDEO_770) {
+ } else if (video_supported == IBMACPI_VIDEO_770) {
if (acpi_evalf(NULL, &i, "\\VCDL", "d"))
status |= 0x01 * i;
if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
status |= 0x02 * i;
- } else if (video_supported == VIDEO_NEW) {
+ } else if (video_supported == IBMACPI_VIDEO_NEW) {
acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1);
if (acpi_evalf(NULL, &i, "\\VCDC", "d"))
status |= 0x02 * i;
@@ -693,9 +834,10 @@ static int video_autosw(void)
{
int autosw = 0;
- if (video_supported == VIDEO_570)
+ if (video_supported == IBMACPI_VIDEO_570)
acpi_evalf(vid_handle, &autosw, "SWIT", "d");
- else if (video_supported == VIDEO_770 || video_supported == VIDEO_NEW)
+ else if (video_supported == IBMACPI_VIDEO_770 ||
+ video_supported == IBMACPI_VIDEO_NEW)
acpi_evalf(vid_handle, &autosw, "^VDEE", "d");
return autosw & 1;
@@ -715,12 +857,12 @@ static int video_read(char *p)
len += sprintf(p + len, "status:\t\tsupported\n");
len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
- if (video_supported == VIDEO_NEW)
+ if (video_supported == IBMACPI_VIDEO_NEW)
len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
- if (video_supported == VIDEO_NEW)
+ if (video_supported == IBMACPI_VIDEO_NEW)
len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
@@ -735,7 +877,7 @@ static int video_switch(void)
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
return -EIO;
- ret = video_supported == VIDEO_570 ?
+ ret = video_supported == IBMACPI_VIDEO_570 ?
acpi_evalf(ec_handle, NULL, "_Q16", "v") :
acpi_evalf(vid_handle, NULL, "VSWT", "v");
acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw);
@@ -745,9 +887,9 @@ static int video_switch(void)
static int video_expand(void)
{
- if (video_supported == VIDEO_570)
+ if (video_supported == IBMACPI_VIDEO_570)
return acpi_evalf(ec_handle, NULL, "_Q17", "v");
- else if (video_supported == VIDEO_770)
+ else if (video_supported == IBMACPI_VIDEO_770)
return acpi_evalf(vid_handle, NULL, "VEXP", "v");
else
return acpi_evalf(NULL, NULL, "\\VEXP", "v");
@@ -757,10 +899,10 @@ static int video_switch2(int status)
{
int ret;
- if (video_supported == VIDEO_570) {
+ if (video_supported == IBMACPI_VIDEO_570) {
ret = acpi_evalf(NULL, NULL,
"\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
- } else if (video_supported == VIDEO_770) {
+ } else if (video_supported == IBMACPI_VIDEO_770) {
int autosw = video_autosw();
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
return -EIO;
@@ -796,10 +938,10 @@ static int video_write(char *buf)
enable |= 0x02;
} else if (strlencmp(cmd, "crt_disable") == 0) {
disable |= 0x02;
- } else if (video_supported == VIDEO_NEW &&
+ } else if (video_supported == IBMACPI_VIDEO_NEW &&
strlencmp(cmd, "dvi_enable") == 0) {
enable |= 0x08;
- } else if (video_supported == VIDEO_NEW &&
+ } else if (video_supported == IBMACPI_VIDEO_NEW &&
strlencmp(cmd, "dvi_disable") == 0) {
disable |= 0x08;
} else if (strlencmp(cmd, "auto_enable") == 0) {
@@ -907,6 +1049,7 @@ static int _sta(acpi_handle handle)
return status;
}
+
#ifdef CONFIG_ACPI_IBM_DOCK
#define dock_docked() (_sta(dock_handle) & 1)
@@ -1094,26 +1237,28 @@ static int cmos_write(char *buf)
return 0;
}
-static int led_supported;
-
-#define LED_570 1
-#define LED_OLD 2
-#define LED_NEW 3
+enum led_access_mode {
+ IBMACPI_LED_NONE = 0,
+ IBMACPI_LED_570, /* 570 */
+ IBMACPI_LED_OLD, /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
+ IBMACPI_LED_NEW, /* all others */
+};
+static enum led_access_mode led_supported;
static int led_init(void)
{
if (!led_handle)
/* led not supported on R30, R31 */
- led_supported = 0;
+ led_supported = IBMACPI_LED_NONE;
else if (strlencmp(led_path, "SLED") == 0)
/* 570 */
- led_supported = LED_570;
+ led_supported = IBMACPI_LED_570;
else if (strlencmp(led_path, "SYSL") == 0)
/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */
- led_supported = LED_OLD;
+ led_supported = IBMACPI_LED_OLD;
else
/* all others */
- led_supported = LED_NEW;
+ led_supported = IBMACPI_LED_NEW;
return 0;
}
@@ -1130,7 +1275,7 @@ static int led_read(char *p)
}
len += sprintf(p + len, "status:\t\tsupported\n");
- if (led_supported == LED_570) {
+ if (led_supported == IBMACPI_LED_570) {
/* 570 */
int i, status;
for (i = 0; i < 8; i++) {
@@ -1179,13 +1324,13 @@ static int led_write(char *buf)
} else
return -EINVAL;
- if (led_supported == LED_570) {
+ if (led_supported == IBMACPI_LED_570) {
/* 570 */
led = 1 << led;
if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
led, led_sled_arg1[ind]))
return -EIO;
- } else if (led_supported == LED_OLD) {
+ } else if (led_supported == IBMACPI_LED_OLD) {
/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
led = 1 << led;
ret = ec_write(EC_HLMS, led);
@@ -1272,50 +1417,142 @@ static int acpi_ec_write(int i, u8 v)
return 1;
}
-static int thermal_tmp_supported;
-static int thermal_updt_supported;
+static enum thermal_access_mode thermal_read_mode;
static int thermal_init(void)
{
- /* temperatures not supported on 570, G4x, R30, R31, R32 */
- thermal_tmp_supported = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+ u8 t, ta1, ta2;
+ int i;
+ int acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+
+ if (ibm_thinkpad_ec_found && experimental) {
+ /*
+ * Direct EC access mode: sensors at registers
+ * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for
+ * non-implemented, thermal sensors return 0x80 when
+ * not available
+ */
- /* 600e/x, 770e, 770x */
- thermal_updt_supported = acpi_evalf(ec_handle, NULL, "UPDT", "qv");
+ ta1 = ta2 = 0;
+ for (i = 0; i < 8; i++) {
+ if (likely(acpi_ec_read(0x78 + i, &t))) {
+ ta1 |= t;
+ } else {
+ ta1 = 0;
+ break;
+ }
+ if (likely(acpi_ec_read(0xC0 + i, &t))) {
+ ta2 |= t;
+ } else {
+ ta1 = 0;
+ break;
+ }
+ }
+ if (ta1 == 0) {
+ /* This is sheer paranoia, but we handle it anyway */
+ if (acpi_tmp7) {
+ printk(IBM_ERR
+ "ThinkPad ACPI EC access misbehaving, "
+ "falling back to ACPI TMPx access mode\n");
+ thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
+ } else {
+ printk(IBM_ERR
+ "ThinkPad ACPI EC access misbehaving, "
+ "disabling thermal sensors access\n");
+ thermal_read_mode = IBMACPI_THERMAL_NONE;
+ }
+ } else {
+ thermal_read_mode =
+ (ta2 != 0) ?
+ IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8;
+ }
+ } else if (acpi_tmp7) {
+ if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) {
+ /* 600e/x, 770e, 770x */
+ thermal_read_mode = IBMACPI_THERMAL_ACPI_UPDT;
+ } else {
+ /* Standard ACPI TMPx access, max 8 sensors */
+ thermal_read_mode = IBMACPI_THERMAL_ACPI_TMP07;
+ }
+ } else {
+ /* temperatures not supported on 570, G4x, R30, R31, R32 */
+ thermal_read_mode = IBMACPI_THERMAL_NONE;
+ }
return 0;
}
-static int thermal_read(char *p)
+static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
{
- int len = 0;
+ int i, t;
+ s8 tmp;
+ char tmpi[] = "TMPi";
- if (!thermal_tmp_supported)
- len += sprintf(p + len, "temperatures:\tnot supported\n");
- else {
- int i, t;
- char tmpi[] = "TMPi";
- s8 tmp[8];
+ if (!s)
+ return -EINVAL;
- if (thermal_updt_supported)
- if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+ switch (thermal_read_mode) {
+#if IBMACPI_MAX_THERMAL_SENSORS >= 16
+ case IBMACPI_THERMAL_TPEC_16:
+ for (i = 0; i < 8; i++) {
+ if (!acpi_ec_read(0xC0 + i, &tmp))
+ return -EIO;
+ s->temp[i + 8] = tmp * 1000;
+ }
+ /* fallthrough */
+#endif
+ case IBMACPI_THERMAL_TPEC_8:
+ for (i = 0; i < 8; i++) {
+ if (!acpi_ec_read(0x78 + i, &tmp))
return -EIO;
+ s->temp[i] = tmp * 1000;
+ }
+ return (thermal_read_mode == IBMACPI_THERMAL_TPEC_16) ? 16 : 8;
+ case IBMACPI_THERMAL_ACPI_UPDT:
+ if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
+ return -EIO;
for (i = 0; i < 8; i++) {
tmpi[3] = '0' + i;
if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
return -EIO;
- if (thermal_updt_supported)
- tmp[i] = (t - 2732 + 5) / 10;
- else
- tmp[i] = t;
+ s->temp[i] = (t - 2732) * 100;
}
+ return 8;
- len += sprintf(p + len,
- "temperatures:\t%d %d %d %d %d %d %d %d\n",
- tmp[0], tmp[1], tmp[2], tmp[3],
- tmp[4], tmp[5], tmp[6], tmp[7]);
+ case IBMACPI_THERMAL_ACPI_TMP07:
+ for (i = 0; i < 8; i++) {
+ tmpi[3] = '0' + i;
+ if (!acpi_evalf(ec_handle, &t, tmpi, "d"))
+ return -EIO;
+ s->temp[i] = t * 1000;
+ }
+ return 8;
+
+ case IBMACPI_THERMAL_NONE:
+ default:
+ return 0;
}
+}
+
+static int thermal_read(char *p)
+{
+ int len = 0;
+ int n, i;
+ struct ibm_thermal_sensors_struct t;
+
+ n = thermal_get_sensors(&t);
+ if (unlikely(n < 0))
+ return n;
+
+ len += sprintf(p + len, "temperatures:\t");
+
+ if (n > 0) {
+ for (i = 0; i < (n - 1); i++)
+ len += sprintf(p + len, "%d ", t.temp[i] / 1000);
+ len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
+ } else
+ len += sprintf(p + len, "not supported\n");
return len;
}
@@ -1381,12 +1618,23 @@ static int ecdump_write(char *buf)
static int brightness_offset = 0x31;
+static int brightness_get(struct backlight_device *bd)
+{
+ u8 level;
+ if (!acpi_ec_read(brightness_offset, &level))
+ return -EIO;
+
+ level &= 0x7;
+
+ return level;
+}
+
static int brightness_read(char *p)
{
int len = 0;
- u8 level;
+ int level;
- if (!acpi_ec_read(brightness_offset, &level)) {
+ if ((level = brightness_get(NULL)) < 0) {
len += sprintf(p + len, "level:\t\tunreadable\n");
} else {
len += sprintf(p + len, "level:\t\t%d\n", level & 0x7);
@@ -1401,16 +1649,34 @@ static int brightness_read(char *p)
#define BRIGHTNESS_UP 4
#define BRIGHTNESS_DOWN 5
-static int brightness_write(char *buf)
+static int brightness_set(int value)
{
int cmos_cmd, inc, i;
- u8 level;
+ int current_value = brightness_get(NULL);
+
+ value &= 7;
+
+ cmos_cmd = value > current_value ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
+ inc = value > current_value ? 1 : -1;
+ for (i = current_value; i != value; i += inc) {
+ if (!cmos_eval(cmos_cmd))
+ return -EIO;
+ if (!acpi_ec_write(brightness_offset, i + inc))
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int brightness_write(char *buf)
+{
+ int level;
int new_level;
char *cmd;
while ((cmd = next_cmd(&buf))) {
- if (!acpi_ec_read(brightness_offset, &level))
- return -EIO;
+ if ((level = brightness_get(NULL)) < 0)
+ return level;
level &= 7;
if (strlencmp(cmd, "up") == 0) {
@@ -1423,19 +1689,44 @@ static int brightness_write(char *buf)
} else
return -EINVAL;
- cmos_cmd = new_level > level ? BRIGHTNESS_UP : BRIGHTNESS_DOWN;
- inc = new_level > level ? 1 : -1;
- for (i = level; i != new_level; i += inc) {
- if (!cmos_eval(cmos_cmd))
- return -EIO;
- if (!acpi_ec_write(brightness_offset, i + inc))
- return -EIO;
- }
+ brightness_set(new_level);
+ }
+
+ return 0;
+}
+
+static int brightness_update_status(struct backlight_device *bd)
+{
+ return brightness_set(bd->props->brightness);
+}
+
+static struct backlight_properties ibm_backlight_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = brightness_get,
+ .update_status = brightness_update_status,
+ .max_brightness = 7,
+};
+
+static int brightness_init(void)
+{
+ ibm_backlight_device = backlight_device_register("ibm", NULL, NULL,
+ &ibm_backlight_data);
+ if (IS_ERR(ibm_backlight_device)) {
+ printk(IBM_ERR "Could not register backlight device\n");
+ return PTR_ERR(ibm_backlight_device);
}
return 0;
}
+static void brightness_exit(void)
+{
+ if (ibm_backlight_device) {
+ backlight_device_unregister(ibm_backlight_device);
+ ibm_backlight_device = NULL;
+ }
+}
+
static int volume_offset = 0x30;
static int volume_read(char *p)
@@ -1522,90 +1813,486 @@ static int volume_write(char *buf)
return 0;
}
-static int fan_status_offset = 0x2f;
-static int fan_rpm_offset = 0x84;
+static enum fan_status_access_mode fan_status_access_mode;
+static enum fan_control_access_mode fan_control_access_mode;
+static enum fan_control_commands fan_control_commands;
-static int fan_read(char *p)
+static int fan_control_status_known;
+static u8 fan_control_initial_status;
+
+static void fan_watchdog_fire(struct work_struct *ignored);
+static int fan_watchdog_maxinterval;
+static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire);
+
+static int fan_init(void)
{
- int len = 0;
- int s;
- u8 lo, hi, status;
+ fan_status_access_mode = IBMACPI_FAN_NONE;
+ fan_control_access_mode = IBMACPI_FAN_WR_NONE;
+ fan_control_commands = 0;
+ fan_control_status_known = 1;
+ fan_watchdog_maxinterval = 0;
if (gfan_handle) {
/* 570, 600e/x, 770e, 770x */
- if (!acpi_evalf(gfan_handle, &s, NULL, "d"))
- return -EIO;
+ fan_status_access_mode = IBMACPI_FAN_RD_ACPI_GFAN;
+ } else {
+ /* all other ThinkPads: note that even old-style
+ * ThinkPad ECs supports the fan control register */
+ if (likely(acpi_ec_read(fan_status_offset,
+ &fan_control_initial_status))) {
+ fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
+
+ /* In some ThinkPads, neither the EC nor the ACPI
+ * DSDT initialize the fan status, and it ends up
+ * being set to 0x07 when it *could* be either
+ * 0x07 or 0x80.
+ *
+ * Enable for TP-1Y (T43), TP-78 (R51e),
+ * TP-76 (R52), TP-70 (T43, R52), which are known
+ * to be buggy. */
+ if (fan_control_initial_status == 0x07 &&
+ ibm_thinkpad_ec_found &&
+ ((ibm_thinkpad_ec_found[0] == '1' &&
+ ibm_thinkpad_ec_found[1] == 'Y') ||
+ (ibm_thinkpad_ec_found[0] == '7' &&
+ (ibm_thinkpad_ec_found[1] == '6' ||
+ ibm_thinkpad_ec_found[1] == '8' ||
+ ibm_thinkpad_ec_found[1] == '0'))
+ )) {
+ printk(IBM_NOTICE
+ "fan_init: initial fan status is "
+ "unknown, assuming it is in auto "
+ "mode\n");
+ fan_control_status_known = 0;
+ }
+ } else {
+ printk(IBM_ERR
+ "ThinkPad ACPI EC access misbehaving, "
+ "fan status and control unavailable\n");
+ return 0;
+ }
+ }
- len += sprintf(p + len, "level:\t\t%d\n", s);
+ if (sfan_handle) {
+ /* 570, 770x-JL */
+ fan_control_access_mode = IBMACPI_FAN_WR_ACPI_SFAN;
+ fan_control_commands |=
+ IBMACPI_FAN_CMD_LEVEL | IBMACPI_FAN_CMD_ENABLE;
} else {
+ if (!gfan_handle) {
+ /* gfan without sfan means no fan control */
+ /* all other models implement TP EC 0x2f control */
+
+ if (fans_handle) {
+ /* X31, X40, X41 */
+ fan_control_access_mode =
+ IBMACPI_FAN_WR_ACPI_FANS;
+ fan_control_commands |=
+ IBMACPI_FAN_CMD_SPEED |
+ IBMACPI_FAN_CMD_LEVEL |
+ IBMACPI_FAN_CMD_ENABLE;
+ } else {
+ fan_control_access_mode = IBMACPI_FAN_WR_TPEC;
+ fan_control_commands |=
+ IBMACPI_FAN_CMD_LEVEL |
+ IBMACPI_FAN_CMD_ENABLE;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int fan_get_status(u8 *status)
+{
+ u8 s;
+
+ /* TODO:
+ * Add IBMACPI_FAN_RD_ACPI_FANS ? */
+
+ switch (fan_status_access_mode) {
+ case IBMACPI_FAN_RD_ACPI_GFAN:
+ /* 570, 600e/x, 770e, 770x */
+
+ if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
+ return -EIO;
+
+ if (likely(status))
+ *status = s & 0x07;
+
+ break;
+
+ case IBMACPI_FAN_RD_TPEC:
/* all except 570, 600e/x, 770e, 770x */
- if (!acpi_ec_read(fan_status_offset, &status))
- len += sprintf(p + len, "status:\t\tunreadable\n");
- else
- len += sprintf(p + len, "status:\t\t%s\n",
- enabled(status, 7));
+ if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
+ return -EIO;
- if (!acpi_ec_read(fan_rpm_offset, &lo) ||
- !acpi_ec_read(fan_rpm_offset + 1, &hi))
- len += sprintf(p + len, "speed:\t\tunreadable\n");
- else
- len += sprintf(p + len, "speed:\t\t%d\n",
- (hi << 8) + lo);
+ if (likely(status))
+ *status = s;
+
+ break;
+
+ default:
+ return -ENXIO;
}
- if (sfan_handle)
- /* 570, 770x-JL */
- len += sprintf(p + len, "commands:\tlevel <level>"
- " (<level> is 0-7)\n");
- if (!gfan_handle)
+ return 0;
+}
+
+static int fan_get_speed(unsigned int *speed)
+{
+ u8 hi, lo;
+
+ switch (fan_status_access_mode) {
+ case IBMACPI_FAN_RD_TPEC:
/* all except 570, 600e/x, 770e, 770x */
- len += sprintf(p + len, "commands:\tenable, disable\n");
- if (fans_handle)
- /* X31, X40 */
+ if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
+ !acpi_ec_read(fan_rpm_offset + 1, &hi)))
+ return -EIO;
+
+ if (likely(speed))
+ *speed = (hi << 8) | lo;
+
+ break;
+
+ default:
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void fan_exit(void)
+{
+ cancel_delayed_work(&fan_watchdog_task);
+ flush_scheduled_work();
+}
+
+static void fan_watchdog_reset(void)
+{
+ static int fan_watchdog_active = 0;
+
+ if (fan_watchdog_active)
+ cancel_delayed_work(&fan_watchdog_task);
+
+ if (fan_watchdog_maxinterval > 0) {
+ fan_watchdog_active = 1;
+ if (!schedule_delayed_work(&fan_watchdog_task,
+ msecs_to_jiffies(fan_watchdog_maxinterval
+ * 1000))) {
+ printk(IBM_ERR "failed to schedule the fan watchdog, "
+ "watchdog will not trigger\n");
+ }
+ } else
+ fan_watchdog_active = 0;
+}
+
+static int fan_read(char *p)
+{
+ int len = 0;
+ int rc;
+ u8 status;
+ unsigned int speed = 0;
+
+ switch (fan_status_access_mode) {
+ case IBMACPI_FAN_RD_ACPI_GFAN:
+ /* 570, 600e/x, 770e, 770x */
+ if ((rc = fan_get_status(&status)) < 0)
+ return rc;
+
+ len += sprintf(p + len, "status:\t\t%s\n"
+ "level:\t\t%d\n",
+ (status != 0) ? "enabled" : "disabled", status);
+ break;
+
+ case IBMACPI_FAN_RD_TPEC:
+ /* all except 570, 600e/x, 770e, 770x */
+ if ((rc = fan_get_status(&status)) < 0)
+ return rc;
+
+ if (unlikely(!fan_control_status_known)) {
+ if (status != fan_control_initial_status)
+ fan_control_status_known = 1;
+ else
+ /* Return most likely status. In fact, it
+ * might be the only possible status */
+ status = IBMACPI_FAN_EC_AUTO;
+ }
+
+ len += sprintf(p + len, "status:\t\t%s\n",
+ (status != 0) ? "enabled" : "disabled");
+
+ /* No ThinkPad boots on disengaged mode, we can safely
+ * assume the tachometer is online if fan control status
+ * was unknown */
+ if ((rc = fan_get_speed(&speed)) < 0)
+ return rc;
+
+ len += sprintf(p + len, "speed:\t\t%d\n", speed);
+
+ if (status & IBMACPI_FAN_EC_DISENGAGED)
+ /* Disengaged mode takes precedence */
+ len += sprintf(p + len, "level:\t\tdisengaged\n");
+ else if (status & IBMACPI_FAN_EC_AUTO)
+ len += sprintf(p + len, "level:\t\tauto\n");
+ else
+ len += sprintf(p + len, "level:\t\t%d\n", status);
+ break;
+
+ case IBMACPI_FAN_NONE:
+ default:
+ len += sprintf(p + len, "status:\t\tnot supported\n");
+ }
+
+ if (fan_control_commands & IBMACPI_FAN_CMD_LEVEL) {
+ len += sprintf(p + len, "commands:\tlevel <level>");
+
+ switch (fan_control_access_mode) {
+ case IBMACPI_FAN_WR_ACPI_SFAN:
+ len += sprintf(p + len, " (<level> is 0-7)\n");
+ break;
+
+ default:
+ len += sprintf(p + len, " (<level> is 0-7, "
+ "auto, disengaged)\n");
+ break;
+ }
+ }
+
+ if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE)
+ len += sprintf(p + len, "commands:\tenable, disable\n"
+ "commands:\twatchdog <timeout> (<timeout> is 0 (off), "
+ "1-120 (seconds))\n");
+
+ if (fan_control_commands & IBMACPI_FAN_CMD_SPEED)
len += sprintf(p + len, "commands:\tspeed <speed>"
" (<speed> is 0-65535)\n");
return len;
}
-static int fan_write(char *buf)
+static int fan_set_level(int level)
{
- char *cmd;
- int level, speed;
-
- while ((cmd = next_cmd(&buf))) {
- if (sfan_handle &&
- sscanf(cmd, "level %d", &level) == 1 &&
- level >= 0 && level <= 7) {
- /* 570, 770x-JL */
+ switch (fan_control_access_mode) {
+ case IBMACPI_FAN_WR_ACPI_SFAN:
+ if (level >= 0 && level <= 7) {
if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
return -EIO;
- } else if (!gfan_handle && strlencmp(cmd, "enable") == 0) {
- /* all except 570, 600e/x, 770e, 770x */
- if (!acpi_ec_write(fan_status_offset, 0x80))
- return -EIO;
- } else if (!gfan_handle && strlencmp(cmd, "disable") == 0) {
- /* all except 570, 600e/x, 770e, 770x */
- if (!acpi_ec_write(fan_status_offset, 0x00))
- return -EIO;
- } else if (fans_handle &&
- sscanf(cmd, "speed %d", &speed) == 1 &&
- speed >= 0 && speed <= 65535) {
- /* X31, X40 */
+ } else
+ return -EINVAL;
+ break;
+
+ case IBMACPI_FAN_WR_ACPI_FANS:
+ case IBMACPI_FAN_WR_TPEC:
+ if ((level != IBMACPI_FAN_EC_AUTO) &&
+ (level != IBMACPI_FAN_EC_DISENGAGED) &&
+ ((level < 0) || (level > 7)))
+ return -EINVAL;
+
+ if (!acpi_ec_write(fan_status_offset, level))
+ return -EIO;
+ else
+ fan_control_status_known = 1;
+ break;
+
+ default:
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int fan_set_enable(void)
+{
+ u8 s;
+ int rc;
+
+ switch (fan_control_access_mode) {
+ case IBMACPI_FAN_WR_ACPI_FANS:
+ case IBMACPI_FAN_WR_TPEC:
+ if ((rc = fan_get_status(&s)) < 0)
+ return rc;
+
+ /* Don't go out of emergency fan mode */
+ if (s != 7)
+ s = IBMACPI_FAN_EC_AUTO;
+
+ if (!acpi_ec_write(fan_status_offset, s))
+ return -EIO;
+ else
+ fan_control_status_known = 1;
+ break;
+
+ case IBMACPI_FAN_WR_ACPI_SFAN:
+ if ((rc = fan_get_status(&s)) < 0)
+ return rc;
+
+ s &= 0x07;
+
+ /* Set fan to at least level 4 */
+ if (s < 4)
+ s = 4;
+
+ if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s))
+ return -EIO;
+ break;
+
+ default:
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int fan_set_disable(void)
+{
+ switch (fan_control_access_mode) {
+ case IBMACPI_FAN_WR_ACPI_FANS:
+ case IBMACPI_FAN_WR_TPEC:
+ if (!acpi_ec_write(fan_status_offset, 0x00))
+ return -EIO;
+ else
+ fan_control_status_known = 1;
+ break;
+
+ case IBMACPI_FAN_WR_ACPI_SFAN:
+ if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00))
+ return -EIO;
+ break;
+
+ default:
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int fan_set_speed(int speed)
+{
+ switch (fan_control_access_mode) {
+ case IBMACPI_FAN_WR_ACPI_FANS:
+ if (speed >= 0 && speed <= 65535) {
if (!acpi_evalf(fans_handle, NULL, NULL, "vddd",
speed, speed, speed))
return -EIO;
} else
return -EINVAL;
- }
+ break;
+ default:
+ return -ENXIO;
+ }
return 0;
}
+static int fan_write_cmd_level(const char *cmd, int *rc)
+{
+ int level;
+
+ if (strlencmp(cmd, "level auto") == 0)
+ level = IBMACPI_FAN_EC_AUTO;
+ else if (strlencmp(cmd, "level disengaged") == 0)
+ level = IBMACPI_FAN_EC_DISENGAGED;
+ else if (sscanf(cmd, "level %d", &level) != 1)
+ return 0;
+
+ if ((*rc = fan_set_level(level)) == -ENXIO)
+ printk(IBM_ERR "level command accepted for unsupported "
+ "access mode %d", fan_control_access_mode);
+
+ return 1;
+}
+
+static int fan_write_cmd_enable(const char *cmd, int *rc)
+{
+ if (strlencmp(cmd, "enable") != 0)
+ return 0;
+
+ if ((*rc = fan_set_enable()) == -ENXIO)
+ printk(IBM_ERR "enable command accepted for unsupported "
+ "access mode %d", fan_control_access_mode);
+
+ return 1;
+}
+
+static int fan_write_cmd_disable(const char *cmd, int *rc)
+{
+ if (strlencmp(cmd, "disable") != 0)
+ return 0;
+
+ if ((*rc = fan_set_disable()) == -ENXIO)
+ printk(IBM_ERR "disable command accepted for unsupported "
+ "access mode %d", fan_control_access_mode);
+
+ return 1;
+}
+
+static int fan_write_cmd_speed(const char *cmd, int *rc)
+{
+ int speed;
+
+ /* TODO:
+ * Support speed <low> <medium> <high> ? */
+
+ if (sscanf(cmd, "speed %d", &speed) != 1)
+ return 0;
+
+ if ((*rc = fan_set_speed(speed)) == -ENXIO)
+ printk(IBM_ERR "speed command accepted for unsupported "
+ "access mode %d", fan_control_access_mode);
+
+ return 1;
+}
+
+static int fan_write_cmd_watchdog(const char *cmd, int *rc)
+{
+ int interval;
+
+ if (sscanf(cmd, "watchdog %d", &interval) != 1)
+ return 0;
+
+ if (interval < 0 || interval > 120)
+ *rc = -EINVAL;
+ else
+ fan_watchdog_maxinterval = interval;
+
+ return 1;
+}
+
+static int fan_write(char *buf)
+{
+ char *cmd;
+ int rc = 0;
+
+ while (!rc && (cmd = next_cmd(&buf))) {
+ if (!((fan_control_commands & IBMACPI_FAN_CMD_LEVEL) &&
+ fan_write_cmd_level(cmd, &rc)) &&
+ !((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
+ (fan_write_cmd_enable(cmd, &rc) ||
+ fan_write_cmd_disable(cmd, &rc) ||
+ fan_write_cmd_watchdog(cmd, &rc))) &&
+ !((fan_control_commands & IBMACPI_FAN_CMD_SPEED) &&
+ fan_write_cmd_speed(cmd, &rc))
+ )
+ rc = -EINVAL;
+ else if (!rc)
+ fan_watchdog_reset();
+ }
+
+ return rc;
+}
+
+static void fan_watchdog_fire(struct work_struct *ignored)
+{
+ printk(IBM_NOTICE "fan watchdog: enabling fan\n");
+ if (fan_set_enable()) {
+ printk(IBM_ERR "fan watchdog: error while enabling fan\n");
+ /* reschedule for later */
+ fan_watchdog_reset();
+ }
+}
+
static struct ibm_struct ibms[] = {
{
.name = "driver",
- .init = driver_init,
+ .init = ibm_acpi_driver_init,
.read = driver_read,
},
{
@@ -1702,6 +2389,8 @@ static struct ibm_struct ibms[] = {
.name = "brightness",
.read = brightness_read,
.write = brightness_write,
+ .init = brightness_init,
+ .exit = brightness_exit,
},
{
.name = "volume",
@@ -1712,6 +2401,8 @@ static struct ibm_struct ibms[] = {
.name = "fan",
.read = fan_read,
.write = fan_write,
+ .init = fan_init,
+ .exit = fan_exit,
.experimental = 1,
},
};
@@ -1719,7 +2410,7 @@ static struct ibm_struct ibms[] = {
static int dispatch_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
- struct ibm_struct *ibm = (struct ibm_struct *)data;
+ struct ibm_struct *ibm = data;
int len;
if (!ibm || !ibm->read)
@@ -1744,7 +2435,7 @@ static int dispatch_read(char *page, char **start, off_t off, int count,
static int dispatch_write(struct file *file, const char __user * userbuf,
unsigned long count, void *data)
{
- struct ibm_struct *ibm = (struct ibm_struct *)data;
+ struct ibm_struct *ibm = data;
char *kernbuf;
int ret;
@@ -1773,7 +2464,7 @@ static int dispatch_write(struct file *file, const char __user * userbuf,
static void dispatch_notify(acpi_handle handle, u32 event, void *data)
{
- struct ibm_struct *ibm = (struct ibm_struct *)data;
+ struct ibm_struct *ibm = data;
if (!ibm || !ibm->notify)
return;
@@ -1805,7 +2496,7 @@ static int __init setup_notify(struct ibm_struct *ibm)
ibm->name, status);
return -ENODEV;
}
-
+ ibm->notify_installed = 1;
return 0;
}
@@ -1818,14 +2509,13 @@ static int __init register_driver(struct ibm_struct *ibm)
{
int ret;
- ibm->driver = kmalloc(sizeof(struct acpi_driver), GFP_KERNEL);
+ ibm->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL);
if (!ibm->driver) {
printk(IBM_ERR "kmalloc(ibm->driver) failed\n");
return -1;
}
- memset(ibm->driver, 0, sizeof(struct acpi_driver));
- sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name);
+ sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name);
ibm->driver->ids = ibm->hid;
ibm->driver->ops.add = &ibm_device_add;
@@ -1882,7 +2572,6 @@ static int __init ibm_init(struct ibm_struct *ibm)
ret = setup_notify(ibm);
if (ret < 0)
return ret;
- ibm->notify_installed = 1;
}
return 0;
@@ -1971,6 +2660,33 @@ static void acpi_ibm_exit(void)
ibm_exit(&ibms[i]);
remove_proc_entry(IBM_DIR, acpi_root_dir);
+
+ if (ibm_thinkpad_ec_found)
+ kfree(ibm_thinkpad_ec_found);
+}
+
+static char* __init check_dmi_for_ec(void)
+{
+ struct dmi_device *dev = NULL;
+ char ec_fw_string[18];
+
+ /*
+ * ThinkPad T23 or newer, A31 or newer, R50e or newer,
+ * X32 or newer, all Z series; Some models must have an
+ * up-to-date BIOS or they will not be detected.
+ *
+ * See http://thinkwiki.org/wiki/List_of_DMI_IDs
+ */
+ while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
+ if (sscanf(dev->name,
+ "IBM ThinkPad Embedded Controller -[%17c",
+ ec_fw_string) == 1) {
+ ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
+ ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
+ return kstrdup(ec_fw_string, GFP_KERNEL);
+ }
+ }
+ return NULL;
}
static int __init acpi_ibm_init(void)
@@ -1992,6 +2708,12 @@ static int __init acpi_ibm_init(void)
return -ENODEV;
}
+ /* Models with newer firmware report the EC in DMI */
+ ibm_thinkpad_ec_found = check_dmi_for_ec();
+ if (ibm_thinkpad_ec_found)
+ printk(IBM_INFO "ThinkPad EC firmware %s\n",
+ ibm_thinkpad_ec_found);
+
/* these handles are not required */
IBM_HANDLE_INIT(vid);
IBM_HANDLE_INIT(vid2);
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index a163e1d3708..a18b1c22312 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -50,6 +50,50 @@ ACPI_MODULE_NAME("nsxfobj")
/*******************************************************************************
*
+ * FUNCTION: acpi_get_id
+ *
+ * PARAMETERS: Handle - Handle of object whose id is desired
+ * ret_id - Where the id will be placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This routine returns the owner id associated with a handle
+ *
+ ******************************************************************************/
+acpi_status acpi_get_id(acpi_handle handle, acpi_owner_id * ret_id)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+
+ /* Parameter Validation */
+
+ if (!ret_id) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Convert and validate the handle */
+
+ node = acpi_ns_map_handle_to_node(handle);
+ if (!node) {
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return (AE_BAD_PARAMETER);
+ }
+
+ *ret_id = node->owner_id;
+
+ status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_id)
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_get_type
*
* PARAMETERS: Handle - Handle of object whose type is desired
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index e5e448edca4..bd96a704592 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -248,7 +248,7 @@ int acpi_get_pxm(acpi_handle h)
handle = phandle;
status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
if (ACPI_SUCCESS(status))
- return (int)pxm;
+ return pxm;
status = acpi_get_parent(handle, &phandle);
} while (ACPI_SUCCESS(status));
return -1;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 02b30ae6a68..57ae1e5cde0 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -568,6 +568,7 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
static void acpi_os_execute_deferred(struct work_struct *work)
{
struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
+
if (!dpc) {
printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
return;
@@ -1031,7 +1032,7 @@ acpi_status
acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
{
*cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
- if (cache == NULL)
+ if (*cache == NULL)
return AE_ERROR;
else
return AE_OK;
@@ -1051,7 +1052,7 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
{
- (void)kmem_cache_shrink(cache);
+ kmem_cache_shrink(cache);
return (AE_OK);
}
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 1e2ae6e7a7e..55f57a61c55 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -122,19 +122,17 @@ int acpi_pci_bind(struct acpi_device *device)
if (!device || !device->parent)
return -EINVAL;
- pathname = kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
if (!pathname)
return -ENOMEM;
- memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
- data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
if (!data) {
kfree(pathname);
return -ENOMEM;
}
- memset(data, 0, sizeof(struct acpi_pci_data));
acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
@@ -281,10 +279,9 @@ int acpi_pci_unbind(struct acpi_device *device)
if (!device || !device->parent)
return -EINVAL;
- pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
if (!pathname)
return -ENOMEM;
- memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
@@ -331,11 +328,9 @@ acpi_pci_bind_root(struct acpi_device *device,
char *pathname = NULL;
struct acpi_buffer buffer = { 0, NULL };
-
- pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
if (!pathname)
return -ENOMEM;
- memset(pathname, 0, ACPI_PATHNAME_MAX);
buffer.length = ACPI_PATHNAME_MAX;
buffer.pointer = pathname;
@@ -345,12 +340,11 @@ acpi_pci_bind_root(struct acpi_device *device,
return -EINVAL;
}
- data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
if (!data) {
kfree(pathname);
return -ENOMEM;
}
- memset(data, 0, sizeof(struct acpi_pci_data));
data->id = *id;
data->bus = bus;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index feda0341f5a..fe7d007833a 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -89,10 +89,9 @@ acpi_pci_irq_add_entry(acpi_handle handle,
if (!prt)
return -EINVAL;
- entry = kmalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
+ entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
- memset(entry, 0, sizeof(struct acpi_prt_entry));
entry->id.segment = segment;
entry->id.bus = bus;
@@ -161,10 +160,9 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
static int first_time = 1;
- pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
+ pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
if (!pathname)
return -ENOMEM;
- memset(pathname, 0, ACPI_PATHNAME_MAX);
if (first_time) {
acpi_prt.count = 0;
@@ -198,11 +196,10 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
return -ENODEV;
}
- prt = kmalloc(buffer.length, GFP_KERNEL);
+ prt = kzalloc(buffer.length, GFP_KERNEL);
if (!prt) {
return -ENOMEM;
}
- memset(prt, 0, buffer.length);
buffer.pointer = prt;
status = acpi_get_irq_routing_table(handle, &buffer);
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index d53bd9878ca..481e633bbf4 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -103,7 +103,7 @@ DEFINE_MUTEX(acpi_link_lock);
static acpi_status
acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
{
- struct acpi_pci_link *link = (struct acpi_pci_link *)context;
+ struct acpi_pci_link *link = context;
u32 i = 0;
@@ -307,11 +307,10 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
if (!link || !irq)
return -EINVAL;
- resource = kmalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
+ resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
if (!resource)
return -ENOMEM;
- memset(resource, 0, sizeof(*resource) + 1);
buffer.length = sizeof(*resource) + 1;
buffer.pointer = resource;
@@ -613,7 +612,7 @@ acpi_pci_link_allocate_irq(acpi_handle handle,
return -1;
}
- link = (struct acpi_pci_link *)acpi_driver_data(device);
+ link = acpi_driver_data(device);
if (!link) {
printk(KERN_ERR PREFIX "Invalid link context\n");
return -1;
@@ -668,7 +667,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
return -1;
}
- link = (struct acpi_pci_link *)acpi_driver_data(device);
+ link = acpi_driver_data(device);
if (!link) {
printk(KERN_ERR PREFIX "Invalid link context\n");
return -1;
@@ -718,10 +717,9 @@ static int acpi_pci_link_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
+ link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
if (!link)
return -ENOMEM;
- memset(link, 0, sizeof(struct acpi_pci_link));
link->device = device;
strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
@@ -808,7 +806,7 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- link = (struct acpi_pci_link *)acpi_driver_data(device);
+ link = acpi_driver_data(device);
mutex_lock(&acpi_link_lock);
list_del(&link->node);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 0984a1ee24e..a860efa2c56 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -98,11 +98,12 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
struct acpi_pci_driver **pptr = &sub_driver;
while (*pptr) {
- if (*pptr != driver)
- continue;
- *pptr = (*pptr)->next;
- break;
+ if (*pptr == driver)
+ break;
+ pptr = &(*pptr)->next;
}
+ BUG_ON(!*pptr);
+ *pptr = (*pptr)->next;
if (!driver->remove)
return;
@@ -119,7 +120,7 @@ EXPORT_SYMBOL(acpi_pci_unregister_driver);
static acpi_status
get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
- int *busnr = (int *)data;
+ int *busnr = data;
struct acpi_resource_address64 address;
if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
@@ -164,10 +165,9 @@ static int acpi_pci_root_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
+ root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
return -ENOMEM;
- memset(root, 0, sizeof(struct acpi_pci_root));
INIT_LIST_HEAD(&root->node);
root->device = device;
@@ -331,7 +331,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- root = (struct acpi_pci_root *)acpi_driver_data(device);
+ root = acpi_driver_data(device);
kfree(root);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index fe67a8af520..0ba7dfbbb2e 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -108,7 +108,7 @@ acpi_power_get_context(acpi_handle handle,
return result;
}
- *resource = (struct acpi_power_resource *)acpi_driver_data(device);
+ *resource = acpi_driver_data(device);
if (!resource)
return -ENODEV;
@@ -442,7 +442,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
struct acpi_power_resource *resource = NULL;
- resource = (struct acpi_power_resource *)seq->private;
+ resource = seq->private;
if (!resource)
goto end;
@@ -532,10 +532,9 @@ static int acpi_power_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- resource = kmalloc(sizeof(struct acpi_power_resource), GFP_KERNEL);
+ resource = kzalloc(sizeof(struct acpi_power_resource), GFP_KERNEL);
if (!resource)
return -ENOMEM;
- memset(resource, 0, sizeof(struct acpi_power_resource));
resource->device = device;
strcpy(resource->name, device->pnp.bus_id);
@@ -590,7 +589,7 @@ static int acpi_power_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- resource = (struct acpi_power_resource *)acpi_driver_data(device);
+ resource = acpi_driver_data(device);
acpi_power_remove_fs(device);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 1908e0d2022..5f9496d59ed 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -277,7 +277,7 @@ static struct proc_dir_entry *acpi_processor_dir = NULL;
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = seq->private;
if (!pr)
@@ -476,9 +476,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr)
if (cpu_index == -1) {
if (ACPI_FAILURE
(acpi_processor_hotadd_init(pr->handle, &pr->id))) {
- printk(KERN_ERR PREFIX
- "Getting cpuindex for acpiid 0x%x\n",
- pr->acpi_id);
return -ENODEV;
}
}
@@ -542,12 +539,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
* Don't trust it blindly
*/
if (processor_device_array[pr->id] != NULL &&
- processor_device_array[pr->id] != (void *)device) {
+ processor_device_array[pr->id] != device) {
printk(KERN_WARNING "BIOS reported wrong ACPI id"
"for the processor\n");
return -ENODEV;
}
- processor_device_array[pr->id] = (void *)device;
+ processor_device_array[pr->id] = device;
processors[pr->id] = pr;
@@ -578,7 +575,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_processor *pr = (struct acpi_processor *)data;
+ struct acpi_processor *pr = data;
struct acpi_device *device = NULL;
@@ -615,10 +612,9 @@ static int acpi_processor_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- pr = kmalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
if (!pr)
return -ENOMEM;
- memset(pr, 0, sizeof(struct acpi_processor));
pr->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
@@ -637,7 +633,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- pr = (struct acpi_processor *)acpi_driver_data(device);
+ pr = acpi_driver_data(device);
if (pr->id >= NR_CPUS) {
kfree(pr);
@@ -901,13 +897,13 @@ static int __init acpi_processor_init(void)
acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
if (!acpi_processor_dir)
- return 0;
+ return -ENOMEM;
acpi_processor_dir->owner = THIS_MODULE;
result = acpi_bus_register_driver(&acpi_processor_driver);
if (result < 0) {
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
- return 0;
+ return result;
}
acpi_processor_install_hotplug_notify();
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 65b3f056ad8..3f30af21574 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -211,7 +211,11 @@ acpi_processor_power_activate(struct acpi_processor *pr,
static void acpi_safe_halt(void)
{
current_thread_info()->status &= ~TS_POLLING;
- smp_mb__after_clear_bit();
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
if (!need_resched())
safe_halt();
current_thread_info()->status |= TS_POLLING;
@@ -345,7 +349,11 @@ static void acpi_processor_idle(void)
*/
if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
current_thread_info()->status &= ~TS_POLLING;
- smp_mb__after_clear_bit();
+ /*
+ * TS_POLLING-cleared state must be visible before we
+ * test NEED_RESCHED:
+ */
+ smp_mb();
if (need_resched()) {
current_thread_info()->status |= TS_POLLING;
local_irq_enable();
@@ -673,7 +681,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
return -ENODEV;
}
- cst = (union acpi_object *)buffer.pointer;
+ cst = buffer.pointer;
/* There must be at least 2 elements */
if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
@@ -702,14 +710,14 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
memset(&cx, 0, sizeof(cx));
- element = (union acpi_object *)&(cst->package.elements[i]);
+ element = &(cst->package.elements[i]);
if (element->type != ACPI_TYPE_PACKAGE)
continue;
if (element->package.count != 4)
continue;
- obj = (union acpi_object *)&(element->package.elements[0]);
+ obj = &(element->package.elements[0]);
if (obj->type != ACPI_TYPE_BUFFER)
continue;
@@ -721,7 +729,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
continue;
/* There should be an easy way to extract an integer... */
- obj = (union acpi_object *)&(element->package.elements[1]);
+ obj = &(element->package.elements[1]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
@@ -754,13 +762,13 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
}
}
- obj = (union acpi_object *)&(element->package.elements[2]);
+ obj = &(element->package.elements[2]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
cx.latency = obj->integer.value;
- obj = (union acpi_object *)&(element->package.elements[3]);
+ obj = &(element->package.elements[3]);
if (obj->type != ACPI_TYPE_INTEGER)
continue;
@@ -1029,7 +1037,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = seq->private;
unsigned int i;
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 6fd174a3714..cbb6f0814ce 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -236,7 +236,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
return -ENODEV;
}
- pss = (union acpi_object *)buffer.pointer;
+ pss = buffer.pointer;
if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
printk(KERN_ERR PREFIX "Invalid _PSS data\n");
result = -EFAULT;
@@ -322,10 +322,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
if (result)
return result;
- result = acpi_processor_get_platform_limit(pr);
- if (result)
- return result;
-
return 0;
}
@@ -410,7 +406,7 @@ static struct file_operations acpi_processor_perf_fops = {
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = seq->private;
int i;
@@ -451,8 +447,8 @@ acpi_processor_write_performance(struct file *file,
size_t count, loff_t * data)
{
int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_processor *pr = m->private;
struct acpi_processor_performance *perf;
char state_string[12] = { '\0' };
unsigned int new_state = 0;
@@ -551,7 +547,7 @@ static int acpi_processor_get_psd(struct acpi_processor *pr)
return -ENODEV;
}
- psd = (union acpi_object *) buffer.pointer;
+ psd = buffer.pointer;
if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
result = -EFAULT;
@@ -736,10 +732,6 @@ int acpi_processor_preregister_performance(
}
err_ret:
- if (retval) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n"));
- }
-
for_each_possible_cpu(i) {
pr = processors[i];
if (!pr || !pr->performance)
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index ef5e0f6efdb..40fecd67ad8 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -208,7 +208,7 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
if (result)
return result;
- pr = (struct acpi_processor *)acpi_driver_data(device);
+ pr = acpi_driver_data(device);
if (!pr)
return -ENODEV;
@@ -348,8 +348,8 @@ static ssize_t acpi_processor_write_limit(struct file * file,
size_t count, loff_t * data)
{
int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_processor *pr = m->private;
char limit_string[25] = { '\0' };
int px = 0;
int tx = 0;
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index d044ec519db..0ec7dcde006 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -259,7 +259,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
static int acpi_processor_throttling_seq_show(struct seq_file *seq,
void *offset)
{
- struct acpi_processor *pr = (struct acpi_processor *)seq->private;
+ struct acpi_processor *pr = seq->private;
int i = 0;
int result = 0;
@@ -307,8 +307,8 @@ static ssize_t acpi_processor_write_throttling(struct file * file,
size_t count, loff_t * data)
{
int result = 0;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_processor *pr = (struct acpi_processor *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_processor *pr = m->private;
char state_string[12] = { '\0' };
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 8908a975e57..f58fc7447ab 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -923,7 +923,7 @@ static struct proc_dir_entry *acpi_battery_dir = NULL;
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
- struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ struct acpi_battery *battery = seq->private;
int cscale;
int result = 0;
@@ -1076,7 +1076,7 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
{
- struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ struct acpi_battery *battery = seq->private;
int result = 0;
int cscale;
@@ -1125,8 +1125,8 @@ static ssize_t
acpi_battery_write_alarm(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
- struct seq_file *seq = (struct seq_file *)file->private_data;
- struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+ struct seq_file *seq = file->private_data;
+ struct acpi_battery *battery = seq->private;
char alarm_string[12] = { '\0' };
int result, old_alarm, new_alarm;
@@ -1160,14 +1160,14 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_battery_set_alarm() failed\n"));
- (void)acpi_battery_set_alarm(battery, old_alarm);
+ acpi_battery_set_alarm(battery, old_alarm);
goto end;
}
result = acpi_battery_get_alarm(battery);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_battery_get_alarm() failed\n"));
- (void)acpi_battery_set_alarm(battery, old_alarm);
+ acpi_battery_set_alarm(battery, old_alarm);
goto end;
}
@@ -1217,7 +1217,7 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
static int acpi_ac_read_state(struct seq_file *seq, void *offset)
{
- struct acpi_sbs *sbs = (struct acpi_sbs *)seq->private;
+ struct acpi_sbs *sbs = seq->private;
int result;
if (sbs->zombie) {
@@ -1302,7 +1302,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
battery->init_state = 1;
}
- (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+ sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
result = acpi_sbs_generic_add_fs(&battery->battery_entry,
acpi_battery_dir,
@@ -1485,7 +1485,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
}
if (old_battery_present != new_battery_present) {
- (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+ sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
result = acpi_sbs_generate_event(sbs->device,
ACPI_SBS_BATTERY_NOTIFY_STATUS,
new_battery_present,
@@ -1498,7 +1498,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
}
}
if (old_remaining_capacity != battery->state.remaining_capacity) {
- (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+ sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
result = acpi_sbs_generate_event(sbs->device,
ACPI_SBS_BATTERY_NOTIFY_STATUS,
new_battery_present,
@@ -1576,12 +1576,11 @@ static int acpi_sbs_add(struct acpi_device *device)
int id, cnt;
acpi_status status = AE_OK;
- sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
+ sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
if (!sbs) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n"));
return -ENOMEM;
}
- memset(sbs, 0, sizeof(struct acpi_sbs));
cnt = 0;
while (cnt < 10) {
@@ -1659,7 +1658,7 @@ static int acpi_sbs_add(struct acpi_device *device)
init_timer(&sbs->update_timer);
if (update_mode == QUEUE_UPDATE_MODE) {
status = acpi_os_execute(OSL_GPE_HANDLER,
- acpi_sbs_update_queue, (void *)sbs);
+ acpi_sbs_update_queue, sbs);
if (status != AE_OK) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_os_execute() failed\n"));
@@ -1685,7 +1684,7 @@ static int acpi_sbs_add(struct acpi_device *device)
int acpi_sbs_remove(struct acpi_device *device, int type)
{
- struct acpi_sbs *sbs = NULL;
+ struct acpi_sbs *sbs;
int id;
if (!device) {
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 698a1540e30..283d87522c5 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -984,12 +984,11 @@ acpi_add_single_object(struct acpi_device **child,
if (!child)
return -EINVAL;
- device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL);
+ device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
if (!device) {
printk(KERN_ERR PREFIX "Memory allocation error\n");
return -ENOMEM;
}
- memset(device, 0, sizeof(struct acpi_device));
device->handle = handle;
device->parent = parent;
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index af1dbabaf0b..fab8f2694f0 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -183,11 +183,11 @@ late_initcall(acpi_wakeup_device_init);
#endif
/*
- * Disable all wakeup GPEs before power off.
- *
+ * Disable all wakeup GPEs before entering requested sleep state.
+ * @sleep_state: ACPI state
* Since acpi_enter_sleep_state() will disable all
* RUNTIME GPEs, we simply mark all GPES that
- * are not enabled for wakeup from S5 as RUNTIME.
+ * are not enabled for wakeup from requested state as RUNTIME.
*/
void acpi_gpe_sleep_prepare(u32 sleep_state)
{
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index bfb3bfcf9e9..ffa30c9fccb 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -228,7 +228,7 @@ void acpi_table_print_madt_entry(acpi_table_entry_header * header)
static int
acpi_table_compute_checksum(void *table_pointer, unsigned long length)
{
- u8 *p = (u8 *) table_pointer;
+ u8 *p = table_pointer;
unsigned long remains = length;
unsigned long sum = 0;
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 7767987be15..5ba9303293a 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -123,7 +123,6 @@ acpi_status acpi_load_tables(void)
ACPI_EXPORT_SYMBOL(acpi_load_tables)
-#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
*
* FUNCTION: acpi_load_table
@@ -221,6 +220,59 @@ ACPI_EXPORT_SYMBOL(acpi_load_table)
/*******************************************************************************
*
+ * FUNCTION: acpi_unload_table_id
+ *
+ * PARAMETERS: table_type - Type of table to be unloaded
+ * id - Owner ID of the table to be removed.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This routine is used to force the unload of a table (by id)
+ *
+ ******************************************************************************/
+acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id)
+{
+ struct acpi_table_desc *table_desc;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_unload_table);
+
+ /* Parameter validation */
+ if (table_type > ACPI_TABLE_ID_MAX)
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+
+ /* Find table from the requested type list */
+ table_desc = acpi_gbl_table_lists[table_type].next;
+ while (table_desc && table_desc->owner_id != id)
+ table_desc = table_desc->next;
+
+ if (!table_desc)
+ return_ACPI_STATUS(AE_NOT_EXIST);
+
+ /*
+ * Delete all namespace objects owned by this table. Note that these
+ * objects can appear anywhere in the namespace by virtue of the AML
+ * "Scope" operator. Thus, we need to track ownership by an ID, not
+ * simply a position within the hierarchy
+ */
+ acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(status);
+
+ (void)acpi_tb_uninstall_table(table_desc);
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+
+ return_ACPI_STATUS(AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
+
+#ifdef ACPI_FUTURE_USAGE
+/*******************************************************************************
+ *
* FUNCTION: acpi_unload_table
*
* PARAMETERS: table_type - Type of table to be unloaded
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 5753d06b786..40ddb4dd963 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -663,7 +663,7 @@ static void acpi_thermal_run(unsigned long data)
static void acpi_thermal_check(void *data)
{
int result = 0;
- struct acpi_thermal *tz = (struct acpi_thermal *)data;
+ struct acpi_thermal *tz = data;
unsigned long sleep_time = 0;
int i = 0;
struct acpi_thermal_state state;
@@ -778,7 +778,7 @@ static struct proc_dir_entry *acpi_thermal_dir;
static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = seq->private;
if (!tz)
@@ -813,7 +813,7 @@ static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
{
int result = 0;
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = seq->private;
if (!tz)
@@ -837,7 +837,7 @@ static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = seq->private;
int i = 0;
int j = 0;
@@ -893,8 +893,8 @@ acpi_thermal_write_trip_points(struct file *file,
const char __user * buffer,
size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_thermal *tz = m->private;
char *limit_string;
int num, critical, hot, passive;
@@ -902,12 +902,10 @@ acpi_thermal_write_trip_points(struct file *file,
int i = 0;
- limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
+ limit_string = kzalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
if (!limit_string)
return -ENOMEM;
- memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
-
active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL);
if (!active) {
kfree(limit_string);
@@ -953,7 +951,7 @@ acpi_thermal_write_trip_points(struct file *file,
static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = seq->private;
if (!tz)
@@ -984,8 +982,8 @@ acpi_thermal_write_cooling_mode(struct file *file,
const char __user * buffer,
size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_thermal *tz = m->private;
int result = 0;
char mode_string[12] = { '\0' };
@@ -1014,7 +1012,7 @@ acpi_thermal_write_cooling_mode(struct file *file,
static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+ struct acpi_thermal *tz = seq->private;
if (!tz)
@@ -1043,8 +1041,8 @@ acpi_thermal_write_polling(struct file *file,
const char __user * buffer,
size_t count, loff_t * ppos)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_thermal *tz = m->private;
int result = 0;
char polling_string[12] = { '\0' };
int seconds = 0;
@@ -1170,7 +1168,7 @@ static int acpi_thermal_remove_fs(struct acpi_device *device)
static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_thermal *tz = (struct acpi_thermal *)data;
+ struct acpi_thermal *tz = data;
struct acpi_device *device = NULL;
@@ -1271,10 +1269,9 @@ static int acpi_thermal_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
+ tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
if (!tz)
return -ENOMEM;
- memset(tz, 0, sizeof(struct acpi_thermal));
tz->device = device;
strcpy(tz->name, device->pnp.bus_id);
@@ -1324,7 +1321,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- tz = (struct acpi_thermal *)acpi_driver_data(device);
+ tz = acpi_driver_data(device);
/* avoid timer adding new defer task */
tz->zombie = 1;
@@ -1364,7 +1361,7 @@ static int acpi_thermal_resume(struct acpi_device *device, int state)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- tz = (struct acpi_thermal *)acpi_driver_data(device);
+ tz = acpi_driver_data(device);
acpi_thermal_get_temperature(tz);
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 7fe0b7ae973..d9b651ffcdc 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -41,6 +41,8 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
+#include <linux/backlight.h>
+
#include <asm/uaccess.h>
#include <acpi/acpi_drivers.h>
@@ -210,6 +212,7 @@ static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
}
static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
+static struct backlight_device *toshiba_backlight_device;
static int force_fan;
static int last_key_event;
static int key_event_valid;
@@ -271,14 +274,23 @@ dispatch_write(struct file *file, const char __user * buffer,
return result;
}
-static char *read_lcd(char *p)
+static int get_lcd(struct backlight_device *bd)
{
u32 hci_result;
u32 value;
hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
if (hci_result == HCI_SUCCESS) {
- value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
+ return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
+ } else
+ return -EFAULT;
+}
+
+static char *read_lcd(char *p)
+{
+ int value = get_lcd(NULL);
+
+ if (value >= 0) {
p += sprintf(p, "brightness: %d\n", value);
p += sprintf(p, "brightness_levels: %d\n",
HCI_LCD_BRIGHTNESS_LEVELS);
@@ -289,22 +301,37 @@ static char *read_lcd(char *p)
return p;
}
+static int set_lcd(int value)
+{
+ u32 hci_result;
+
+ value = value << HCI_LCD_BRIGHTNESS_SHIFT;
+ hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
+ if (hci_result != HCI_SUCCESS)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int set_lcd_status(struct backlight_device *bd)
+{
+ return set_lcd(bd->props->brightness);
+}
+
static unsigned long write_lcd(const char *buffer, unsigned long count)
{
int value;
- u32 hci_result;
+ int ret;
if (sscanf(buffer, " brightness : %i", &value) == 1 &&
value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
- value = value << HCI_LCD_BRIGHTNESS_SHIFT;
- hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
- if (hci_result != HCI_SUCCESS)
- return -EFAULT;
+ ret = set_lcd(value);
+ if (ret == 0)
+ ret = count;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return count;
+ return ret;
}
static char *read_video(char *p)
@@ -506,6 +533,26 @@ static acpi_status __exit remove_device(void)
return AE_OK;
}
+static struct backlight_properties toshiba_backlight_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = get_lcd,
+ .update_status = set_lcd_status,
+ .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
+};
+
+static void __exit toshiba_acpi_exit(void)
+{
+ if (toshiba_backlight_device)
+ backlight_device_unregister(toshiba_backlight_device);
+
+ remove_device();
+
+ if (toshiba_proc_dir)
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+
+ return;
+}
+
static int __init toshiba_acpi_init(void)
{
acpi_status status = AE_OK;
@@ -546,17 +593,16 @@ static int __init toshiba_acpi_init(void)
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
}
- return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
-}
-
-static void __exit toshiba_acpi_exit(void)
-{
- remove_device();
-
- if (toshiba_proc_dir)
- remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ toshiba_backlight_device = backlight_device_register("toshiba",NULL,
+ NULL,
+ &toshiba_backlight_data);
+ if (IS_ERR(toshiba_backlight_device)) {
+ printk(KERN_ERR "Could not register toshiba backlight device\n");
+ toshiba_backlight_device = NULL;
+ toshiba_acpi_exit();
+ }
- return;
+ return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
}
module_init(toshiba_acpi_init);
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index bb1eaf9aa65..9e9054e155c 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -180,8 +180,9 @@ acpi_ut_debug_print(u32 requested_debug_level,
if (thread_id != acpi_gbl_prev_thread_id) {
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf
- ("\n**** Context Switch from TID %X to TID %X ****\n\n",
- (u32) acpi_gbl_prev_thread_id, (u32) thread_id);
+ ("\n**** Context Switch from TID %lX to TID %lX ****\n\n",
+ (unsigned long) acpi_gbl_prev_thread_id,
+ (unsigned long) thread_id);
}
acpi_gbl_prev_thread_id = thread_id;
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index c39062a047c..180e73ceb6e 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -243,23 +243,24 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
#endif
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %X attempting to acquire Mutex [%s]\n",
- (u32) this_thread_id, acpi_ut_get_mutex_name(mutex_id)));
+ "Thread %lX attempting to acquire Mutex [%s]\n",
+ (unsigned long) this_thread_id,
+ acpi_ut_get_mutex_name(mutex_id)));
status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
ACPI_WAIT_FOREVER);
if (ACPI_SUCCESS(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %X acquired Mutex [%s]\n",
- (u32) this_thread_id,
+ "Thread %lX acquired Mutex [%s]\n",
+ (unsigned long) this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
acpi_gbl_mutex_info[mutex_id].use_count++;
acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
} else {
ACPI_EXCEPTION((AE_INFO, status,
- "Thread %X could not acquire Mutex [%X]",
- (u32) this_thread_id, mutex_id));
+ "Thread %lX could not acquire Mutex [%X]",
+ (unsigned long) this_thread_id, mutex_id));
}
return (status);
@@ -285,7 +286,8 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
this_thread_id = acpi_os_get_thread_id();
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
- "Thread %X releasing Mutex [%s]\n", (u32) this_thread_id,
+ "Thread %lX releasing Mutex [%s]\n",
+ (unsigned long) this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
if (mutex_id > ACPI_MAX_MUTEX) {
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index d0d84c43a9d..68a809fa7b1 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -83,7 +83,7 @@ acpi_extract_package(union acpi_object *package,
return AE_BAD_DATA;
}
- format_string = (char *)format->pointer;
+ format_string = format->pointer;
/*
* Calculate size_required.
@@ -262,11 +262,10 @@ acpi_evaluate_integer(acpi_handle handle,
if (!data)
return AE_BAD_PARAMETER;
- element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
+ element = kzalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
if (!element)
return AE_NO_MEMORY;
- memset(element, 0, sizeof(union acpi_object));
buffer.length = sizeof(union acpi_object);
buffer.pointer = element;
status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
@@ -321,12 +320,11 @@ acpi_evaluate_string(acpi_handle handle,
return AE_BAD_DATA;
}
- *data = kmalloc(element->string.length + 1, GFP_KERNEL);
+ *data = kzalloc(element->string.length + 1, GFP_KERNEL);
if (!data) {
printk(KERN_ERR PREFIX "Memory allocation\n");
return -ENOMEM;
}
- memset(*data, 0, element->string.length + 1);
memcpy(*data, element->string.pointer, element->string.length);
@@ -361,7 +359,7 @@ acpi_evaluate_reference(acpi_handle handle,
if (ACPI_FAILURE(status))
goto end;
- package = (union acpi_object *)buffer.pointer;
+ package = buffer.pointer;
if ((buffer.length == 0) || !package) {
printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n",
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 56666a98247..3d54680d033 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
* Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
+ * Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -47,11 +48,11 @@
#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
-#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82
-#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83
-#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84
-#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
-#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
+#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85
+#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86
+#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
+#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
+#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
#define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
#define ACPI_VIDEO_HEAD_END (~0u)
@@ -386,7 +387,7 @@ acpi_video_device_EDID(struct acpi_video_device *device,
if (ACPI_FAILURE(status))
return -ENODEV;
- obj = (union acpi_object *)buffer.pointer;
+ obj = buffer.pointer;
if (obj && obj->type == ACPI_TYPE_BUFFER)
*edid = obj;
@@ -532,11 +533,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
int count = 0;
union acpi_object *o;
- br = kmalloc(sizeof(*br), GFP_KERNEL);
+ br = kzalloc(sizeof(*br), GFP_KERNEL);
if (!br) {
printk(KERN_ERR "can't allocate memory\n");
} else {
- memset(br, 0, sizeof(*br));
br->levels = kmalloc(obj->package.count *
sizeof *(br->levels), GFP_KERNEL);
if (!br->levels)
@@ -654,8 +654,7 @@ static struct proc_dir_entry *acpi_video_dir;
static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev =
- (struct acpi_video_device *)seq->private;
+ struct acpi_video_device *dev = seq->private;
if (!dev)
@@ -688,8 +687,7 @@ acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
{
int status;
- struct acpi_video_device *dev =
- (struct acpi_video_device *)seq->private;
+ struct acpi_video_device *dev = seq->private;
unsigned long state;
@@ -727,8 +725,8 @@ acpi_video_device_write_state(struct file *file,
size_t count, loff_t * data)
{
int status;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_video_device *dev = m->private;
char str[12] = { 0 };
u32 state = 0;
@@ -754,8 +752,7 @@ acpi_video_device_write_state(struct file *file,
static int
acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev =
- (struct acpi_video_device *)seq->private;
+ struct acpi_video_device *dev = seq->private;
int i;
@@ -784,8 +781,8 @@ acpi_video_device_write_brightness(struct file *file,
const char __user * buffer,
size_t count, loff_t * data)
{
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_video_device *dev = m->private;
char str[4] = { 0 };
unsigned int level = 0;
int i;
@@ -817,8 +814,7 @@ acpi_video_device_write_brightness(struct file *file,
static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_device *dev =
- (struct acpi_video_device *)seq->private;
+ struct acpi_video_device *dev = seq->private;
int status;
int i;
union acpi_object *edid = NULL;
@@ -866,7 +862,7 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
if (!device)
return -ENODEV;
- vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
+ vid_dev = acpi_driver_data(device);
if (!vid_dev)
return -ENODEV;
@@ -931,7 +927,7 @@ static int acpi_video_device_remove_fs(struct acpi_device *device)
{
struct acpi_video_device *vid_dev;
- vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
+ vid_dev = acpi_driver_data(device);
if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
return -ENODEV;
@@ -950,7 +946,7 @@ static int acpi_video_device_remove_fs(struct acpi_device *device)
/* video bus */
static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ struct acpi_video_bus *video = seq->private;
if (!video)
@@ -975,7 +971,7 @@ static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ struct acpi_video_bus *video = seq->private;
if (!video)
@@ -995,7 +991,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ struct acpi_video_bus *video = seq->private;
unsigned long options;
int status;
@@ -1033,7 +1029,7 @@ acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ struct acpi_video_bus *video = seq->private;
int status;
unsigned long id;
@@ -1054,7 +1050,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
+ struct acpi_video_bus *video = seq->private;
seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
@@ -1079,8 +1075,8 @@ acpi_video_bus_write_POST(struct file *file,
size_t count, loff_t * data)
{
int status;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_video_bus *video = m->private;
char str[12] = { 0 };
unsigned long opt, options;
@@ -1119,8 +1115,8 @@ acpi_video_bus_write_DOS(struct file *file,
size_t count, loff_t * data)
{
int status;
- struct seq_file *m = (struct seq_file *)file->private_data;
- struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
+ struct seq_file *m = file->private_data;
+ struct acpi_video_bus *video = m->private;
char str[12] = { 0 };
unsigned long opt;
@@ -1150,7 +1146,7 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
struct acpi_video_bus *video;
- video = (struct acpi_video_bus *)acpi_driver_data(device);
+ video = acpi_driver_data(device);
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
@@ -1226,7 +1222,7 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
struct acpi_video_bus *video;
- video = (struct acpi_video_bus *)acpi_driver_data(device);
+ video = acpi_driver_data(device);
if (acpi_device_dir(device)) {
remove_proc_entry("info", acpi_device_dir(device));
@@ -1263,12 +1259,10 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
if (ACPI_SUCCESS(status)) {
- data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
+ data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
if (!data)
return -ENOMEM;
- memset(data, 0, sizeof(struct acpi_video_device));
-
strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
acpi_driver_data(device) = data;
@@ -1403,7 +1397,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
return status;
}
- dod = (union acpi_object *)buffer.pointer;
+ dod = buffer.pointer;
if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data"));
status = -EFAULT;
@@ -1426,7 +1420,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
count = 0;
for (i = 0; i < dod->package.count; i++) {
- obj = (union acpi_object *)&dod->package.elements[i];
+ obj = &dod->package.elements[i];
if (obj->type != ACPI_TYPE_INTEGER) {
printk(KERN_ERR PREFIX "Invalid _DOD data\n");
@@ -1509,8 +1503,34 @@ static int
acpi_video_get_next_level(struct acpi_video_device *device,
u32 level_current, u32 event)
{
- /*Fix me */
- return level_current;
+ int min, max, min_above, max_below, i, l;
+ max = max_below = 0;
+ min = min_above = 255;
+ for (i = 0; i < device->brightness->count; i++) {
+ l = device->brightness->levels[i];
+ if (l < min)
+ min = l;
+ if (l > max)
+ max = l;
+ if (l < min_above && l > level_current)
+ min_above = l;
+ if (l > max_below && l < level_current)
+ max_below = l;
+ }
+
+ switch (event) {
+ case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:
+ return (level_current < max) ? min_above : min;
+ case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:
+ return (level_current < max) ? min_above : max;
+ case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:
+ return (level_current > min) ? max_below : min;
+ case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:
+ case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:
+ return 0;
+ default:
+ return level_current;
+ }
}
static void
@@ -1612,7 +1632,7 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_video_bus *video = (struct acpi_video_bus *)data;
+ struct acpi_video_bus *video = data;
struct acpi_device *device = NULL;
printk("video bus notify\n");
@@ -1654,12 +1674,9 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_video_device *video_device =
- (struct acpi_video_device *)data;
+ struct acpi_video_device *video_device = data;
struct acpi_device *device = NULL;
-
- printk("video device notify\n");
if (!video_device)
return;
@@ -1696,10 +1713,9 @@ static int acpi_video_bus_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- video = kmalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
+ video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
if (!video)
return -ENOMEM;
- memset(video, 0, sizeof(struct acpi_video_bus));
video->device = device;
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
@@ -1757,7 +1773,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
- video = (struct acpi_video_bus *)acpi_driver_data(device);
+ video = acpi_driver_data(device);
acpi_video_bus_stop_devices(video);
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 984ab284382..1c94b43d2c9 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -19,6 +19,10 @@ config ATA
if ATA
+config ATA_NONSTANDARD
+ bool
+ default n
+
config SATA_AHCI
tristate "AHCI SATA support"
depends on PCI
@@ -40,9 +44,9 @@ config ATA_PIIX
tristate "Intel PIIX/ICH SATA support"
depends on PCI
help
- This option enables support for ICH5/6/7/8 Serial ATA.
- If PATA support was enabled previously, this enables
- support for select Intel PIIX/ICH PATA host controllers.
+ This option enables support for ICH5/6/7/8 Serial ATA
+ and support for PATA on the Intel PIIX3/PIIX4/ICH series
+ PATA host controllers.
If unsure, say N.
@@ -381,7 +385,7 @@ config PATA_OPTI
If unsure, say N.
config PATA_OPTIDMA
- tristate "OPTI FireStar PATA support (Veyr Experimental)"
+ tristate "OPTI FireStar PATA support (Very Experimental)"
depends on PCI && EXPERIMENTAL
help
This option enables DMA/PIO support for the later OPTi
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index f36da488a2c..48616c6fee9 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -75,6 +75,7 @@ enum {
AHCI_CMD_CLR_BUSY = (1 << 10),
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
+ RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
board_ahci = 0,
@@ -202,6 +203,10 @@ struct ahci_port_priv {
dma_addr_t cmd_tbl_dma;
void *rx_fis;
dma_addr_t rx_fis_dma;
+ /* for NCQ spurious interrupt analysis */
+ int ncq_saw_spurious_sdb_cnt;
+ unsigned int ncq_saw_d2h:1;
+ unsigned int ncq_saw_dmas:1;
};
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
@@ -361,7 +366,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
- { PCI_VDEVICE(AL, 0x5288), board_ahci }, /* ULi M5288 */
+ { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
@@ -402,6 +407,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */
{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */
{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */
+ { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci }, /* MCP65 */
+ { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci }, /* MCP65 */
+ { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci }, /* MCP65 */
+ { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci }, /* MCP65 */
+ { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */
+ { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */
+ { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */
+ { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */
@@ -578,35 +591,18 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
{
u32 cmd, scontrol;
- cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
-
- if (cap & HOST_CAP_SSC) {
- /* enable transitions to slumber mode */
- scontrol = readl(port_mmio + PORT_SCR_CTL);
- if ((scontrol & 0x0f00) > 0x100) {
- scontrol &= ~0xf00;
- writel(scontrol, port_mmio + PORT_SCR_CTL);
- }
-
- /* put device into slumber mode */
- writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
-
- /* wait for the transition to complete */
- ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
- PORT_CMD_ICC_SLUMBER, 1, 50);
- }
+ if (!(cap & HOST_CAP_SSS))
+ return;
- /* put device into listen mode */
- if (cap & HOST_CAP_SSS) {
- /* first set PxSCTL.DET to 0 */
- scontrol = readl(port_mmio + PORT_SCR_CTL);
- scontrol &= ~0xf;
- writel(scontrol, port_mmio + PORT_SCR_CTL);
+ /* put device into listen mode, first set PxSCTL.DET to 0 */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ scontrol &= ~0xf;
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
- /* then set PxCMD.SUD to 0 */
- cmd &= ~PORT_CMD_SPIN_UP;
- writel(cmd, port_mmio + PORT_CMD);
- }
+ /* then set PxCMD.SUD to 0 */
+ cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
+ cmd &= ~PORT_CMD_SPIN_UP;
+ writel(cmd, port_mmio + PORT_CMD);
}
static void ahci_init_port(void __iomem *port_mmio, u32 cap,
@@ -645,8 +641,6 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
u32 cap_save, impl_save, tmp;
cap_save = readl(mmio + HOST_CAP);
- cap_save &= ( (1<<28) | (1<<17) );
- cap_save |= (1 << 27);
impl_save = readl(mmio + HOST_PORTS_IMPL);
/* global controller reset */
@@ -909,7 +903,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf);
- tf.command = 0xff;
+ tf.command = 0x80;
ata_tf_to_fis(&tf, d2h_fis, 0);
rc = sata_std_hardreset(ap, class);
@@ -1120,8 +1114,9 @@ static void ahci_host_intr(struct ata_port *ap)
void __iomem *mmio = ap->host->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
struct ata_eh_info *ehi = &ap->eh_info;
+ struct ahci_port_priv *pp = ap->private_data;
u32 status, qc_active;
- int rc;
+ int rc, known_irq = 0;
status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT);
@@ -1148,17 +1143,53 @@ static void ahci_host_intr(struct ata_port *ap)
/* hmmm... a spurious interupt */
- /* some devices send D2H reg with I bit set during NCQ command phase */
- if (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS))
+ /* if !NCQ, ignore. No modern ATA device has broken HSM
+ * implementation for non-NCQ commands.
+ */
+ if (!ap->sactive)
return;
- /* ignore interim PIO setup fis interrupts */
- if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS))
- return;
+ if (status & PORT_IRQ_D2H_REG_FIS) {
+ if (!pp->ncq_saw_d2h)
+ ata_port_printk(ap, KERN_INFO,
+ "D2H reg with I during NCQ, "
+ "this message won't be printed again\n");
+ pp->ncq_saw_d2h = 1;
+ known_irq = 1;
+ }
+
+ if (status & PORT_IRQ_DMAS_FIS) {
+ if (!pp->ncq_saw_dmas)
+ ata_port_printk(ap, KERN_INFO,
+ "DMAS FIS during NCQ, "
+ "this message won't be printed again\n");
+ pp->ncq_saw_dmas = 1;
+ known_irq = 1;
+ }
+
+ if (status & PORT_IRQ_SDB_FIS &&
+ pp->ncq_saw_spurious_sdb_cnt < 10) {
+ /* SDB FIS containing spurious completions might be
+ * dangerous, we need to know more about them. Print
+ * more of it.
+ */
+ const u32 *f = pp->rx_fis + RX_FIS_SDB;
+
+ ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ "
+ "issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n",
+ readl(port_mmio + PORT_CMD_ISSUE),
+ readl(port_mmio + PORT_SCR_ACT),
+ le32_to_cpu(f[0]), le32_to_cpu(f[1]),
+ pp->ncq_saw_spurious_sdb_cnt < 10 ?
+ "" : ", shutting up");
+
+ pp->ncq_saw_spurious_sdb_cnt++;
+ known_irq = 1;
+ }
- if (ata_ratelimit())
+ if (!known_irq)
ata_port_printk(ap, KERN_INFO, "spurious interrupt "
- "(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
+ "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n",
status, ap->active_tag, ap->sactive);
}
@@ -1251,7 +1282,7 @@ static void ahci_thaw(struct ata_port *ap)
/* clear IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
writel(tmp, port_mmio + PORT_IRQ_STAT);
- writel(1 << ap->id, mmio + HOST_IRQ_STAT);
+ writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
/* turn IRQ back on */
writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 908751d27e7..24af56081b5 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -64,6 +64,7 @@ static void generic_error_handler(struct ata_port *ap)
/**
* generic_set_mode - mode setting
* @ap: interface to set up
+ * @unused: returned device on error
*
* Use a non standard set_mode function. We don't want to be tuned.
* The BIOS configured everything. Our job is not to fiddle. We
@@ -71,7 +72,7 @@ static void generic_error_handler(struct ata_port *ap)
* and respect them.
*/
-static void generic_set_mode(struct ata_port *ap)
+static int generic_set_mode(struct ata_port *ap, struct ata_device **unused)
{
int dma_enabled = 0;
int i;
@@ -82,7 +83,7 @@ static void generic_set_mode(struct ata_port *ap)
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
- if (ata_dev_enabled(dev)) {
+ if (ata_dev_ready(dev)) {
/* We don't really care */
dev->pio_mode = XFER_PIO_0;
dev->dma_mode = XFER_MW_DMA_0;
@@ -99,6 +100,7 @@ static void generic_set_mode(struct ata_port *ap)
}
}
}
+ return 0;
}
static struct scsi_host_template generic_sht = {
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index c7de0bb1591..47701b286f8 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -226,14 +226,26 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
/* 2801GBM/GHM (ICH7M, identical to ICH6M) */
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
- /* Enterprise Southbridge 2 (where's the datasheet?) */
+ /* Enterprise Southbridge 2 (631xESB/632xESB) */
{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
- /* SATA Controller 1 IDE (ICH8, no datasheet yet) */
+ /* SATA Controller 1 IDE (ICH8) */
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
- /* SATA Controller 2 IDE (ICH8, ditto) */
+ /* SATA Controller 2 IDE (ICH8) */
{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
- /* Mobile SATA Controller IDE (ICH8M, ditto) */
+ /* Mobile SATA Controller IDE (ICH8M) */
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller IDE (ICH9) */
+ { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller IDE (ICH9) */
+ { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller IDE (ICH9) */
+ { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller IDE (ICH9M) */
+ { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller IDE (ICH9M) */
+ { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ /* SATA Controller IDE (ICH9M) */
+ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
{ } /* terminate list */
};
@@ -330,7 +342,7 @@ static const struct ata_port_operations ich_pata_ops = {
.port_start = ata_port_start,
.port_stop = ata_port_stop,
- .host_stop = ata_host_stop,
+ .host_stop = piix_host_stop,
};
static const struct ata_port_operations piix_sata_ops = {
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 011c0a8a2dc..667acd28336 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1037,7 +1037,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
* the PIO timing number for the maximum. Turn it into
* a mask.
*/
- u8 mode = id[ATA_ID_OLD_PIO_MODES] & 0xFF;
+ u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
if (mode < 5) /* Valid PIO range */
pio_mask = (2 << mode) - 1;
else
@@ -1250,6 +1250,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
ata_sg_init(qc, sg, n_elem);
qc->nsect = buflen / ATA_SECT_SIZE;
+ qc->nbytes = buflen;
}
qc->private_data = &wait;
@@ -1332,7 +1333,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
}
/**
- * ata_exec_internal_sg - execute libata internal command
+ * ata_exec_internal - execute libata internal command
* @dev: Device to which the command is sent
* @tf: Taskfile registers for the command and the result
* @cdb: CDB for packet command
@@ -1353,11 +1354,17 @@ unsigned ata_exec_internal(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, void *buf, unsigned int buflen)
{
- struct scatterlist sg;
+ struct scatterlist *psg = NULL, sg;
+ unsigned int n_elem = 0;
- sg_init_one(&sg, buf, buflen);
+ if (dma_dir != DMA_NONE) {
+ WARN_ON(!buf);
+ sg_init_one(&sg, buf, buflen);
+ psg = &sg;
+ n_elem++;
+ }
- return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1);
+ return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, n_elem);
}
/**
@@ -2425,18 +2432,8 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
int i, rc = 0, used_dma = 0, found = 0;
/* has private set_mode? */
- if (ap->ops->set_mode) {
- /* FIXME: make ->set_mode handle no device case and
- * return error code and failing device on failure.
- */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- if (ata_dev_ready(&ap->device[i])) {
- ap->ops->set_mode(ap);
- break;
- }
- }
- return 0;
- }
+ if (ap->ops->set_mode)
+ return ap->ops->set_mode(ap, r_failed_dev);
/* step 1: calculate xfer_mask */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 08ad44b3e48..748435807d6 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1796,7 +1796,7 @@ static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
*r_failed_dev = dev;
DPRINTK("EXIT\n");
- return 0;
+ return rc;
}
/**
@@ -1979,6 +1979,10 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+ /* collect port action mask recorded in dev actions */
+ ehc->i.action |= ehc->i.dev_action[i] & ~ATA_EH_PERDEV_MASK;
+ ehc->i.dev_action[i] &= ATA_EH_PERDEV_MASK;
+
/* process hotplug request */
if (dev->flags & ATA_DFLAG_DETACH)
ata_eh_detach_dev(dev);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 664e1377b54..73902d33576 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -51,7 +51,7 @@
#define SECTOR_SIZE 512
-typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
+typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
@@ -273,8 +273,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
{
int rc = 0;
u8 scsi_cmd[MAX_COMMAND_SIZE];
- u8 args[7];
- struct scsi_sense_hdr sshdr;
+ u8 args[7], *sensebuf = NULL;
+ int cmd_result;
if (arg == NULL)
return -EINVAL;
@@ -282,10 +282,14 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
if (copy_from_user(args, arg, sizeof(args)))
return -EFAULT;
+ sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+ if (!sensebuf)
+ return -ENOMEM;
+
memset(scsi_cmd, 0, sizeof(scsi_cmd));
scsi_cmd[0] = ATA_16;
scsi_cmd[1] = (3 << 1); /* Non-data */
- /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+ scsi_cmd[2] = 0x20; /* cc but no off.line or data xfer */
scsi_cmd[4] = args[1];
scsi_cmd[6] = args[2];
scsi_cmd[8] = args[3];
@@ -295,11 +299,46 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
/* Good values for timeout and retries? Values below
from scsi_ioctl_send_command() for default case... */
- if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
- (10*HZ), 5))
+ cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0,
+ sensebuf, (10*HZ), 5, 0);
+
+ if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
+ u8 *desc = sensebuf + 8;
+ cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
+
+ /* If we set cc then ATA pass-through will cause a
+ * check condition even if no error. Filter that. */
+ if (cmd_result & SAM_STAT_CHECK_CONDITION) {
+ struct scsi_sense_hdr sshdr;
+ scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
+ &sshdr);
+ if (sshdr.sense_key==0 &&
+ sshdr.asc==0 && sshdr.ascq==0)
+ cmd_result &= ~SAM_STAT_CHECK_CONDITION;
+ }
+
+ /* Send userspace ATA registers */
+ if (sensebuf[0] == 0x72 && /* format is "descriptor" */
+ desc[0] == 0x09) {/* code is "ATA Descriptor" */
+ args[0] = desc[13]; /* status */
+ args[1] = desc[3]; /* error */
+ args[2] = desc[5]; /* sector count (0:7) */
+ args[3] = desc[7]; /* lbal */
+ args[4] = desc[9]; /* lbam */
+ args[5] = desc[11]; /* lbah */
+ args[6] = desc[12]; /* select */
+ if (copy_to_user(arg, args, sizeof(args)))
+ rc = -EFAULT;
+ }
+ }
+
+ if (cmd_result) {
rc = -EIO;
+ goto error;
+ }
- /* Need code to retrieve data from check condition? */
+ error:
+ kfree(sensebuf);
return rc;
}
@@ -372,7 +411,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
if (cmd->use_sg) {
qc->__sg = (struct scatterlist *) cmd->request_buffer;
qc->n_elem = cmd->use_sg;
- } else {
+ } else if (cmd->request_bufflen) {
qc->__sg = &qc->sgent;
qc->n_elem = 1;
}
@@ -935,7 +974,6 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
/**
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
* @qc: Storage for translated ATA taskfile
- * @scsicmd: SCSI command to translate
*
* Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY
* (to start). Perhaps these commands should be preceded by
@@ -948,22 +986,25 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
* RETURNS:
* Zero on success, non-zero on error.
*/
-
-static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
- const u8 *scsicmd)
+static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
{
+ struct scsi_cmnd *scmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->tf;
+ const u8 *cdb = scmd->cmnd;
+
+ if (scmd->cmd_len < 5)
+ goto invalid_fld;
tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
tf->protocol = ATA_PROT_NODATA;
- if (scsicmd[1] & 0x1) {
+ if (cdb[1] & 0x1) {
; /* ignore IMMED bit, violates sat-r05 */
}
- if (scsicmd[4] & 0x2)
+ if (cdb[4] & 0x2)
goto invalid_fld; /* LOEJ bit set not supported */
- if (((scsicmd[4] >> 4) & 0xf) != 0)
+ if (((cdb[4] >> 4) & 0xf) != 0)
goto invalid_fld; /* power conditions not supported */
- if (scsicmd[4] & 0x1) {
+ if (cdb[4] & 0x1) {
tf->nsect = 1; /* 1 sector, lba=0 */
if (qc->dev->flags & ATA_DFLAG_LBA) {
@@ -981,11 +1022,10 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
}
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
- } else {
- tf->nsect = 0; /* time period value (0 implies now) */
- tf->command = ATA_CMD_STANDBY;
- /* Consider: ATA STANDBY IMMEDIATE command */
- }
+ } else
+ /* Issue ATA STANDBY IMMEDIATE command */
+ tf->command = ATA_CMD_STANDBYNOW1;
+
/*
* Standby and Idle condition timers could be implemented but that
* would require libata to implement the Power condition mode page
@@ -996,7 +1036,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
return 0;
invalid_fld:
- ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
/* "Invalid field in cbd" */
return 1;
}
@@ -1005,7 +1045,6 @@ invalid_fld:
/**
* ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
* @qc: Storage for translated ATA taskfile
- * @scsicmd: SCSI command to translate (ignored)
*
* Sets up an ATA taskfile to issue FLUSH CACHE or
* FLUSH CACHE EXT.
@@ -1016,8 +1055,7 @@ invalid_fld:
* RETURNS:
* Zero on success, non-zero on error.
*/
-
-static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc)
{
struct ata_taskfile *tf = &qc->tf;
@@ -1034,7 +1072,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs
/**
* scsi_6_lba_len - Get LBA and transfer length
- * @scsicmd: SCSI command to translate
+ * @cdb: SCSI command to translate
*
* Calculate LBA and transfer length for 6-byte commands.
*
@@ -1042,18 +1080,17 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scs
* @plba: the LBA
* @plen: the transfer length
*/
-
-static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+static void scsi_6_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
{
u64 lba = 0;
u32 len = 0;
VPRINTK("six-byte command\n");
- lba |= ((u64)scsicmd[2]) << 8;
- lba |= ((u64)scsicmd[3]);
+ lba |= ((u64)cdb[2]) << 8;
+ lba |= ((u64)cdb[3]);
- len |= ((u32)scsicmd[4]);
+ len |= ((u32)cdb[4]);
*plba = lba;
*plen = len;
@@ -1061,7 +1098,7 @@ static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
/**
* scsi_10_lba_len - Get LBA and transfer length
- * @scsicmd: SCSI command to translate
+ * @cdb: SCSI command to translate
*
* Calculate LBA and transfer length for 10-byte commands.
*
@@ -1069,21 +1106,20 @@ static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
* @plba: the LBA
* @plen: the transfer length
*/
-
-static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+static void scsi_10_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
{
u64 lba = 0;
u32 len = 0;
VPRINTK("ten-byte command\n");
- lba |= ((u64)scsicmd[2]) << 24;
- lba |= ((u64)scsicmd[3]) << 16;
- lba |= ((u64)scsicmd[4]) << 8;
- lba |= ((u64)scsicmd[5]);
+ lba |= ((u64)cdb[2]) << 24;
+ lba |= ((u64)cdb[3]) << 16;
+ lba |= ((u64)cdb[4]) << 8;
+ lba |= ((u64)cdb[5]);
- len |= ((u32)scsicmd[7]) << 8;
- len |= ((u32)scsicmd[8]);
+ len |= ((u32)cdb[7]) << 8;
+ len |= ((u32)cdb[8]);
*plba = lba;
*plen = len;
@@ -1091,7 +1127,7 @@ static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
/**
* scsi_16_lba_len - Get LBA and transfer length
- * @scsicmd: SCSI command to translate
+ * @cdb: SCSI command to translate
*
* Calculate LBA and transfer length for 16-byte commands.
*
@@ -1099,27 +1135,26 @@ static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
* @plba: the LBA
* @plen: the transfer length
*/
-
-static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+static void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
{
u64 lba = 0;
u32 len = 0;
VPRINTK("sixteen-byte command\n");
- lba |= ((u64)scsicmd[2]) << 56;
- lba |= ((u64)scsicmd[3]) << 48;
- lba |= ((u64)scsicmd[4]) << 40;
- lba |= ((u64)scsicmd[5]) << 32;
- lba |= ((u64)scsicmd[6]) << 24;
- lba |= ((u64)scsicmd[7]) << 16;
- lba |= ((u64)scsicmd[8]) << 8;
- lba |= ((u64)scsicmd[9]);
+ lba |= ((u64)cdb[2]) << 56;
+ lba |= ((u64)cdb[3]) << 48;
+ lba |= ((u64)cdb[4]) << 40;
+ lba |= ((u64)cdb[5]) << 32;
+ lba |= ((u64)cdb[6]) << 24;
+ lba |= ((u64)cdb[7]) << 16;
+ lba |= ((u64)cdb[8]) << 8;
+ lba |= ((u64)cdb[9]);
- len |= ((u32)scsicmd[10]) << 24;
- len |= ((u32)scsicmd[11]) << 16;
- len |= ((u32)scsicmd[12]) << 8;
- len |= ((u32)scsicmd[13]);
+ len |= ((u32)cdb[10]) << 24;
+ len |= ((u32)cdb[11]) << 16;
+ len |= ((u32)cdb[12]) << 8;
+ len |= ((u32)cdb[13]);
*plba = lba;
*plen = len;
@@ -1128,7 +1163,6 @@ static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
/**
* ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
* @qc: Storage for translated ATA taskfile
- * @scsicmd: SCSI command to translate
*
* Converts SCSI VERIFY command to an ATA READ VERIFY command.
*
@@ -1138,23 +1172,28 @@ static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
* RETURNS:
* Zero on success, non-zero on error.
*/
-
-static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc)
{
+ struct scsi_cmnd *scmd = qc->scsicmd;
struct ata_taskfile *tf = &qc->tf;
struct ata_device *dev = qc->dev;
u64 dev_sectors = qc->dev->n_sectors;
+ const u8 *cdb = scmd->cmnd;
u64 block;
u32 n_block;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->protocol = ATA_PROT_NODATA;
- if (scsicmd[0] == VERIFY)
- scsi_10_lba_len(scsicmd, &block, &n_block);
- else if (scsicmd[0] == VERIFY_16)
- scsi_16_lba_len(scsicmd, &block, &n_block);
- else
+ if (cdb[0] == VERIFY) {
+ if (scmd->cmd_len < 10)
+ goto invalid_fld;
+ scsi_10_lba_len(cdb, &block, &n_block);
+ } else if (cdb[0] == VERIFY_16) {
+ if (scmd->cmd_len < 16)
+ goto invalid_fld;
+ scsi_16_lba_len(cdb, &block, &n_block);
+ } else
goto invalid_fld;
if (!n_block)
@@ -1229,24 +1268,23 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
return 0;
invalid_fld:
- ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
/* "Invalid field in cbd" */
return 1;
out_of_range:
- ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+ ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0);
/* "Logical Block Address out of range" */
return 1;
nothing_to_do:
- qc->scsicmd->result = SAM_STAT_GOOD;
+ scmd->result = SAM_STAT_GOOD;
return 1;
}
/**
* ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
* @qc: Storage for translated ATA taskfile
- * @scsicmd: SCSI command to translate
*
* Converts any of six SCSI read/write commands into the
* ATA counterpart, including starting sector (LBA),
@@ -1262,29 +1300,33 @@ nothing_to_do:
* RETURNS:
* Zero on success, non-zero on error.
*/
-
-static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ const u8 *cdb = scmd->cmnd;
unsigned int tf_flags = 0;
u64 block;
u32 n_block;
int rc;
- if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
- scsicmd[0] == WRITE_16)
+ if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16)
tf_flags |= ATA_TFLAG_WRITE;
/* Calculate the SCSI LBA, transfer length and FUA. */
- switch (scsicmd[0]) {
+ switch (cdb[0]) {
case READ_10:
case WRITE_10:
- scsi_10_lba_len(scsicmd, &block, &n_block);
- if (unlikely(scsicmd[1] & (1 << 3)))
+ if (unlikely(scmd->cmd_len < 10))
+ goto invalid_fld;
+ scsi_10_lba_len(cdb, &block, &n_block);
+ if (unlikely(cdb[1] & (1 << 3)))
tf_flags |= ATA_TFLAG_FUA;
break;
case READ_6:
case WRITE_6:
- scsi_6_lba_len(scsicmd, &block, &n_block);
+ if (unlikely(scmd->cmd_len < 6))
+ goto invalid_fld;
+ scsi_6_lba_len(cdb, &block, &n_block);
/* for 6-byte r/w commands, transfer length 0
* means 256 blocks of data, not 0 block.
@@ -1294,8 +1336,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
break;
case READ_16:
case WRITE_16:
- scsi_16_lba_len(scsicmd, &block, &n_block);
- if (unlikely(scsicmd[1] & (1 << 3)))
+ if (unlikely(scmd->cmd_len < 16))
+ goto invalid_fld;
+ scsi_16_lba_len(cdb, &block, &n_block);
+ if (unlikely(cdb[1] & (1 << 3)))
tf_flags |= ATA_TFLAG_FUA;
break;
default:
@@ -1326,17 +1370,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
goto out_of_range;
/* treat all other errors as -EINVAL, fall through */
invalid_fld:
- ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+ ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
/* "Invalid field in cbd" */
return 1;
out_of_range:
- ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+ ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0);
/* "Logical Block Address out of range" */
return 1;
nothing_to_do:
- qc->scsicmd->result = SAM_STAT_GOOD;
+ scmd->result = SAM_STAT_GOOD;
return 1;
}
@@ -1456,7 +1500,6 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
ata_xlat_func_t xlat_func)
{
struct ata_queued_cmd *qc;
- u8 *scsicmd = cmd->cmnd;
int is_io = xlat_func == ata_scsi_rw_xlat;
VPRINTK("ENTER\n");
@@ -1488,7 +1531,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
qc->complete_fn = ata_scsi_qc_complete;
- if (xlat_func(qc, scsicmd))
+ if (xlat_func(qc))
goto early_finish;
/* select device, send command to hardware */
@@ -1539,7 +1582,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
struct scatterlist *sg;
sg = (struct scatterlist *) cmd->request_buffer;
- buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
buflen = sg->length;
} else {
buf = cmd->request_buffer;
@@ -1567,7 +1610,7 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
struct scatterlist *sg;
sg = (struct scatterlist *) cmd->request_buffer;
- kunmap_atomic(buf - sg->offset, KM_USER0);
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
}
}
@@ -2344,7 +2387,6 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
/**
* atapi_xlat - Initialize PACKET taskfile
* @qc: command structure to be initialized
- * @scsicmd: SCSI CDB associated with this PACKET command
*
* LOCKING:
* spin_lock_irqsave(host lock)
@@ -2352,25 +2394,25 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
* RETURNS:
* Zero on success, non-zero on failure.
*/
-
-static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
{
- struct scsi_cmnd *cmd = qc->scsicmd;
+ struct scsi_cmnd *scmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
int using_pio = (dev->flags & ATA_DFLAG_PIO);
- int nodata = (cmd->sc_data_direction == DMA_NONE);
+ int nodata = (scmd->sc_data_direction == DMA_NONE);
if (!using_pio)
/* Check whether ATAPI DMA is safe */
if (ata_check_atapi_dma(qc))
using_pio = 1;
- memcpy(&qc->cdb, scsicmd, dev->cdb_len);
+ memset(qc->cdb, 0, dev->cdb_len);
+ memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
qc->complete_fn = atapi_qc_complete;
qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+ if (scmd->sc_data_direction == DMA_TO_DEVICE) {
qc->tf.flags |= ATA_TFLAG_WRITE;
DPRINTK("direction: write\n");
}
@@ -2392,12 +2434,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
qc->tf.protocol = ATA_PROT_ATAPI_DMA;
qc->tf.feature |= ATAPI_PKT_DMA;
- if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE))
+ if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
/* some SATA bridges need us to indicate data xfer direction */
qc->tf.feature |= ATAPI_DMADIR;
}
- qc->nbytes = cmd->request_bufflen;
+ qc->nbytes = scmd->request_bufflen;
return 0;
}
@@ -2517,28 +2559,27 @@ ata_scsi_map_proto(u8 byte1)
/**
* ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
* @qc: command structure to be initialized
- * @scsicmd: SCSI command to convert
*
* Handles either 12 or 16-byte versions of the CDB.
*
* RETURNS:
* Zero on success, non-zero on failure.
*/
-static unsigned int
-ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
+static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
{
struct ata_taskfile *tf = &(qc->tf);
- struct scsi_cmnd *cmd = qc->scsicmd;
+ struct scsi_cmnd *scmd = qc->scsicmd;
struct ata_device *dev = qc->dev;
+ const u8 *cdb = scmd->cmnd;
- if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
+ if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
goto invalid_fld;
/* We may not issue DMA commands if no DMA mode is set */
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld;
- if (scsicmd[1] & 0xe0)
+ if (cdb[1] & 0xe0)
/* PIO multi not supported yet */
goto invalid_fld;
@@ -2546,18 +2587,18 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
* 12 and 16 byte CDBs use different offsets to
* provide the various register values.
*/
- if (scsicmd[0] == ATA_16) {
+ if (cdb[0] == ATA_16) {
/*
* 16-byte CDB - may contain extended commands.
*
* If that is the case, copy the upper byte register values.
*/
- if (scsicmd[1] & 0x01) {
- tf->hob_feature = scsicmd[3];
- tf->hob_nsect = scsicmd[5];
- tf->hob_lbal = scsicmd[7];
- tf->hob_lbam = scsicmd[9];
- tf->hob_lbah = scsicmd[11];
+ if (cdb[1] & 0x01) {
+ tf->hob_feature = cdb[3];
+ tf->hob_nsect = cdb[5];
+ tf->hob_lbal = cdb[7];
+ tf->hob_lbam = cdb[9];
+ tf->hob_lbah = cdb[11];
tf->flags |= ATA_TFLAG_LBA48;
} else
tf->flags &= ~ATA_TFLAG_LBA48;
@@ -2565,26 +2606,26 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
/*
* Always copy low byte, device and command registers.
*/
- tf->feature = scsicmd[4];
- tf->nsect = scsicmd[6];
- tf->lbal = scsicmd[8];
- tf->lbam = scsicmd[10];
- tf->lbah = scsicmd[12];
- tf->device = scsicmd[13];
- tf->command = scsicmd[14];
+ tf->feature = cdb[4];
+ tf->nsect = cdb[6];
+ tf->lbal = cdb[8];
+ tf->lbam = cdb[10];
+ tf->lbah = cdb[12];
+ tf->device = cdb[13];
+ tf->command = cdb[14];
} else {
/*
* 12-byte CDB - incapable of extended commands.
*/
tf->flags &= ~ATA_TFLAG_LBA48;
- tf->feature = scsicmd[3];
- tf->nsect = scsicmd[4];
- tf->lbal = scsicmd[5];
- tf->lbam = scsicmd[6];
- tf->lbah = scsicmd[7];
- tf->device = scsicmd[8];
- tf->command = scsicmd[9];
+ tf->feature = cdb[3];
+ tf->nsect = cdb[4];
+ tf->lbal = cdb[5];
+ tf->lbam = cdb[6];
+ tf->lbah = cdb[7];
+ tf->device = cdb[8];
+ tf->command = cdb[9];
}
/*
* If slave is possible, enforce correct master/slave bit
@@ -2611,7 +2652,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
*/
tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE);
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ if (scmd->sc_data_direction == DMA_TO_DEVICE)
tf->flags |= ATA_TFLAG_WRITE;
/*
@@ -2620,7 +2661,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
* TODO: find out if we need to do more here to
* cover scatter/gather case.
*/
- qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE;
+ qc->nsect = scmd->request_bufflen / ATA_SECT_SIZE;
/* request result TF */
qc->flags |= ATA_QCFLAG_RESULT_TF;
@@ -2628,7 +2669,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
return 0;
invalid_fld:
- ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x00);
+ ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00);
/* "Invalid field in cdb" */
return 1;
}
@@ -2701,22 +2742,29 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
#endif
}
-static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
+static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
void (*done)(struct scsi_cmnd *),
struct ata_device *dev)
{
int rc = 0;
+ if (unlikely(!scmd->cmd_len)) {
+ ata_dev_printk(dev, KERN_WARNING, "WARNING: zero len CDB\n");
+ scmd->result = DID_ERROR << 16;
+ done(scmd);
+ return 0;
+ }
+
if (dev->class == ATA_DEV_ATA) {
ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
- cmd->cmnd[0]);
+ scmd->cmnd[0]);
if (xlat_func)
- rc = ata_scsi_translate(dev, cmd, done, xlat_func);
+ rc = ata_scsi_translate(dev, scmd, done, xlat_func);
else
- ata_scsi_simulate(dev, cmd, done);
+ ata_scsi_simulate(dev, scmd, done);
} else
- rc = ata_scsi_translate(dev, cmd, done, atapi_xlat);
+ rc = ata_scsi_translate(dev, scmd, done, atapi_xlat);
return rc;
}
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 10ee22ae5c1..12c88c58803 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -827,7 +827,8 @@ void ata_bmdma_error_handler(struct ata_port *ap)
*/
void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
{
- ata_bmdma_stop(qc);
+ if (qc->ap->ioaddr.bmdma_addr)
+ ata_bmdma_stop(qc);
}
#ifdef CONFIG_PCI
@@ -870,7 +871,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
bmdma = pci_resource_start(pdev, 4);
if (bmdma) {
- if (inb(bmdma + 2) & 0x80)
+ if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+ (inb(bmdma + 2) & 0x80))
probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
probe_ent->port[p].bmdma_addr = bmdma;
}
@@ -886,7 +888,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
bmdma = pci_resource_start(pdev, 4);
if (bmdma) {
bmdma += 8;
- if(inb(bmdma + 2) & 0x80)
+ if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+ (inb(bmdma + 2) & 0x80))
probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
probe_ent->port[p].bmdma_addr = bmdma;
}
@@ -914,13 +917,14 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
probe_ent->irq_flags = IRQF_SHARED;
if (port_mask & ATA_PORT_PRIMARY) {
- probe_ent->irq = ATA_PRIMARY_IRQ;
+ probe_ent->irq = ATA_PRIMARY_IRQ(pdev);
probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
if (bmdma) {
probe_ent->port[0].bmdma_addr = bmdma;
- if (inb(bmdma + 2) & 0x80)
+ if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+ (inb(bmdma + 2) & 0x80))
probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
}
ata_std_ports(&probe_ent->port[0]);
@@ -929,15 +933,16 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
if (port_mask & ATA_PORT_SECONDARY) {
if (probe_ent->irq)
- probe_ent->irq2 = ATA_SECONDARY_IRQ;
+ probe_ent->irq2 = ATA_SECONDARY_IRQ(pdev);
else
- probe_ent->irq = ATA_SECONDARY_IRQ;
+ probe_ent->irq = ATA_SECONDARY_IRQ(pdev);
probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
if (bmdma) {
probe_ent->port[1].bmdma_addr = bmdma + 8;
- if (inb(bmdma + 10) & 0x80)
+ if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) &&
+ (inb(bmdma + 10) & 0x80))
probe_ent->_host_flags |= ATA_HOST_SIMPLEX;
}
ata_std_ports(&probe_ent->port[1]);
@@ -1027,13 +1032,15 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
#endif
}
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- disable_dev_on_err = 0;
- goto err_out;
- }
-
- if (legacy_mode) {
+ if (!legacy_mode) {
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc) {
+ disable_dev_on_err = 0;
+ goto err_out;
+ }
+ } else {
+ /* Deal with combined mode hack. This side of the logic all
+ goes away once the combined mode hack is killed in 2.6.21 */
if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
struct resource *conflict, res;
res.start = ATA_PRIMARY_CMD;
@@ -1071,6 +1078,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
}
} else
legacy_mode |= ATA_PORT_SECONDARY;
+
+ if (legacy_mode & ATA_PORT_PRIMARY)
+ pci_request_region(pdev, 1, DRV_NAME);
+ if (legacy_mode & ATA_PORT_SECONDARY)
+ pci_request_region(pdev, 3, DRV_NAME);
+ /* If there is a DMA resource, allocate it */
+ pci_request_region(pdev, 4, DRV_NAME);
}
/* we have legacy mode, but all ports are unavailable */
@@ -1114,11 +1128,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
err_out_ent:
kfree(probe_ent);
err_out_regions:
- if (legacy_mode & ATA_PORT_PRIMARY)
- release_region(ATA_PRIMARY_CMD, 8);
- if (legacy_mode & ATA_PORT_SECONDARY)
- release_region(ATA_SECONDARY_CMD, 8);
- pci_release_regions(pdev);
+ /* All this conditional stuff is needed for the combined mode hack
+ until 2.6.21 when it can go */
+ if (legacy_mode) {
+ pci_release_region(pdev, 4);
+ if (legacy_mode & ATA_PORT_PRIMARY) {
+ release_region(ATA_PRIMARY_CMD, 8);
+ pci_release_region(pdev, 1);
+ }
+ if (legacy_mode & ATA_PORT_SECONDARY) {
+ release_region(ATA_SECONDARY_CMD, 8);
+ pci_release_region(pdev, 3);
+ }
+ } else
+ pci_release_regions(pdev);
err_out:
if (disable_dev_on_err)
pci_disable_device(pdev);
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 6f6672c5513..504e1dbfffd 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -36,15 +36,22 @@ enum {
static int atiixp_pre_reset(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- static struct pci_bits atiixp_enable_bits[] = {
+ static const struct pci_bits atiixp_enable_bits[] = {
{ 0x48, 1, 0x01, 0x00 },
{ 0x48, 1, 0x08, 0x00 }
};
+ u8 udma;
if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
return -ENOENT;
- ap->cbl = ATA_CBL_PATA80;
+ /* Hack from drivers/ide/pci. Really we want to know how to do the
+ raw detection not play follow the bios mode guess */
+ pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma);
+ if ((udma & 0x07) >= 0x04 || (udma & 0x70) >= 0x40)
+ ap->cbl = ATA_CBL_PATA80;
+ else
+ ap->cbl = ATA_CBL_PATA40;
return ata_std_prereset(ap);
}
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 15841a56369..449162cbf93 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -197,7 +197,7 @@ static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev)
static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
static const u8 udma_data[] = {
- 0x31, 0x21, 0x11, 0x25, 0x15, 0x05
+ 0x30, 0x20, 0x10, 0x20, 0x10, 0x00
};
static const u8 mwdma_data[] = {
0x30, 0x20, 0x10
@@ -213,12 +213,21 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
pci_read_config_byte(pdev, pciD, &regD);
pci_read_config_byte(pdev, pciU, &regU);
- regD &= ~(0x20 << shift);
- regU &= ~(0x35 << shift);
+ /* DMA bits off */
+ regD &= ~(0x20 << adev->devno);
+ /* DMA control bits */
+ regU &= ~(0x30 << shift);
+ /* DMA timing bits */
+ regU &= ~(0x05 << adev->devno);
- if (adev->dma_mode >= XFER_UDMA_0)
+ if (adev->dma_mode >= XFER_UDMA_0) {
+ /* Merge thge timing value */
regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
- else
+ /* Merge the control bits */
+ regU |= 1 << adev->devno; /* UDMA on */
+ if (adev->dma_mode > 2) /* 15nS timing */
+ regU |= 4 << adev->devno;
+ } else
regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift;
regD |= 0x20 << adev->devno;
@@ -239,8 +248,8 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u8 dma_intr;
- int dma_reg = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
- int dma_mask = ap->port_no ? ARTTIM2 : CFR;
+ int dma_mask = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+ int dma_reg = ap->port_no ? ARTTIM2 : CFR;
ata_bmdma_stop(qc);
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 1c628014dae..b1ca207e354 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -372,7 +372,8 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int cs5530_reinit_one(struct pci_dev *pdev)
{
/* If we fail on resume we are doomed */
- BUG_ON(cs5530_init_chip());
+ if (cs5530_init_chip())
+ BUG();
return ata_pci_device_resume(pdev);
}
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 47082df7199..dfb306057cf 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -25,7 +25,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
-#define DRV_VERSION "0.5.1"
+#define DRV_VERSION "0.5.2"
struct hpt_clock {
u8 xfer_speed;
@@ -416,7 +416,7 @@ static const char *bad_ata100_5[] = {
static unsigned long hpt370_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask)
{
- if (adev->class != ATA_DEV_ATA) {
+ if (adev->class == ATA_DEV_ATA) {
if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33))
mask &= ~ATA_MASK_UDMA;
if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
@@ -749,7 +749,7 @@ static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- int mscreg = 0x50 + 2 * ap->port_no;
+ int mscreg = 0x50 + 4 * ap->port_no;
u8 bwsr_stat, msc_stat;
pci_read_config_byte(pdev, 0x6A, &bwsr_stat);
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index f6817b4093a..886fab9aa62 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -25,7 +25,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x2n"
-#define DRV_VERSION "0.3"
+#define DRV_VERSION "0.3.2"
enum {
HPT_PCI_FAST = (1 << 31),
@@ -297,11 +297,11 @@ static int hpt3x2n_pair_idle(struct ata_port *ap)
return 0;
}
-static int hpt3x2n_use_dpll(struct ata_port *ap, int reading)
+static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
{
long flags = (long)ap->host->private_data;
/* See if we should use the DPLL */
- if (reading == 0)
+ if (writing)
return USE_DPLL; /* Needed for write */
if (flags & PCI66)
return USE_DPLL; /* Needed at 66Mhz */
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 0b56ff3d1cf..e8afd486434 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -476,6 +476,7 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
/**
* it821x_smart_set_mode - mode setting
* @ap: interface to set up
+ * @unused: device that failed (error only)
*
* Use a non standard set_mode function. We don't want to be tuned.
* The BIOS configured everything. Our job is not to fiddle. We
@@ -483,7 +484,7 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
* and respect them.
*/
-static void it821x_smart_set_mode(struct ata_port *ap)
+static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused)
{
int dma_enabled = 0;
int i;
@@ -512,6 +513,7 @@ static void it821x_smart_set_mode(struct ata_port *ap)
}
}
}
+ return 0;
}
/**
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index cb8924109f5..23b8aab3ebd 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -23,9 +23,9 @@
#include <scsi/scsi_host.h>
#define DRV_NAME "pata_ixp4xx_cf"
-#define DRV_VERSION "0.1.1"
+#define DRV_VERSION "0.1.1ac1"
-static void ixp4xx_set_mode(struct ata_port *ap)
+static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device *adev)
{
int i;
@@ -38,6 +38,7 @@ static void ixp4xx_set_mode(struct ata_port *ap)
dev->flags |= ATA_DFLAG_PIO;
}
}
+ return 0;
}
static void ixp4xx_phy_reset(struct ata_port *ap)
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 2d661cb4df3..d50264af284 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -204,20 +204,12 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
u32 reg;
- if (id->driver_data != 368) {
- /* Put the controller into AHCI mode in case the AHCI driver
- has not yet been loaded. This can be done with either
- function present */
+ /* PATA controller is fn 1, AHCI is fn 0 */
+ if (id->driver_data != 368 && PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
- /* FIXME: We may want a way to override this in future */
- pci_write_config_byte(pdev, 0x41, 0xa1);
-
- /* PATA controller is fn 1, AHCI is fn 0 */
- if (PCI_FUNC(pdev->devfn) != 1)
- return -ENODEV;
- }
- if ( id->driver_data == 365 || id->driver_data == 366) {
- /* The 365/66 have two PATA channels, redirect the second */
+ /* The 365/66 have two PATA channels, redirect the second */
+ if (id->driver_data == 365 || id->driver_data == 366) {
pci_read_config_dword(pdev, 0x80, &reg);
reg |= (1 << 24); /* IDE1 to PATA IDE secondary */
pci_write_config_dword(pdev, 0x80, reg);
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index c7d1738e4e6..581cb33c6f4 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -96,6 +96,7 @@ static int pio_mask = 0x1F; /* PIO range for autospeed devices */
/**
* legacy_set_mode - mode setting
* @ap: IDE interface
+ * @unused: Device that failed when error is returned
*
* Use a non standard set_mode function. We don't want to be tuned.
*
@@ -105,7 +106,7 @@ static int pio_mask = 0x1F; /* PIO range for autospeed devices */
* expand on this as per hdparm in the base kernel.
*/
-static void legacy_set_mode(struct ata_port *ap)
+static int legacy_set_mode(struct ata_port *ap, struct ata_device **unused)
{
int i;
@@ -118,6 +119,7 @@ static void legacy_set_mode(struct ata_port *ap)
dev->flags |= ATA_DFLAG_PIO;
}
}
+ return 0;
}
static struct scsi_host_template legacy_sht = {
@@ -698,8 +700,10 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
goto fail_io;
pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
- if (pdev == NULL)
+ if (IS_ERR(pdev)) {
+ ret = PTR_ERR(pdev);
goto fail_dev;
+ }
if (ht6560a & mask) {
ops = &ht6560a_port_ops;
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 443b1d85c6c..40ae11cbfda 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -30,7 +30,7 @@ static int pio_mask = 1;
* Provide our own set_mode() as we don't want to change anything that has
* already been configured..
*/
-static void pata_platform_set_mode(struct ata_port *ap)
+static int pata_platform_set_mode(struct ata_port *ap, struct ata_device **unused)
{
int i;
@@ -44,6 +44,7 @@ static void pata_platform_set_mode(struct ata_port *ap)
dev->flags |= ATA_DFLAG_PIO;
}
}
+ return 0;
}
static void pata_platform_host_stop(struct ata_host *host)
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 36f621abc39..afc0d990e7d 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -247,8 +247,8 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
*/
pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0);
- if (pdev == NULL)
- return -ENOMEM;
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
memset(&ae, 0, sizeof(struct ata_probe_ent));
INIT_LIST_HEAD(&ae.node);
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index 3677c642c9f..cec0729225e 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -52,19 +52,20 @@ static void rz1000_error_handler(struct ata_port *ap)
/**
* rz1000_set_mode - mode setting function
* @ap: ATA interface
+ * @unused: returned device on set_mode failure
*
* Use a non standard set_mode function. We don't want to be tuned. We
* would prefer to be BIOS generic but for the fact our hardware is
* whacked out.
*/
-static void rz1000_set_mode(struct ata_port *ap)
+static int rz1000_set_mode(struct ata_port *ap, struct ata_device **unused)
{
int i;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
- if (ata_dev_enabled(dev)) {
+ if (ata_dev_ready(dev)) {
/* We don't really care */
dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0;
@@ -72,6 +73,7 @@ static void rz1000_set_mode(struct ata_port *ap)
dev->flags |= ATA_DFLAG_PIO;
}
}
+ return 0;
}
@@ -105,8 +107,6 @@ static struct ata_port_operations rz1000_port_ops = {
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
- .error_handler = rz1000_error_handler,
-
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 32cf0bfa892..e8dfd8fc3ff 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -135,7 +135,7 @@ static void sil680_error_handler(struct ata_port *ap)
static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 };
- static u16 speed_t[5] = { 0x328A, 0x1281, 0x1281, 0x10C3, 0x10C1 };
+ static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 };
unsigned long tfaddr = sil680_selreg(ap, 0x02);
unsigned long addr = sil680_seldev(ap, adev, 0x04);
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index cc09d47fb92..f0b6c3b7142 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -23,6 +23,7 @@
* VIA VT8233c - UDMA100
* VIA VT8235 - UDMA133
* VIA VT8237 - UDMA133
+ * VIA VT8237S - UDMA133
* VIA VT8251 - UDMA133
*
* Most registers remain compatible across chips. Others start reserved
@@ -61,7 +62,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_via"
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
/*
* The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
@@ -95,6 +96,7 @@ static const struct via_isa_bridge {
u8 rev_max;
u16 flags;
} via_isa_bridges[] = {
+ { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
@@ -161,10 +163,15 @@ static int via_pre_reset(struct ata_port *ap)
return -ENOENT;
}
- if ((config->flags & VIA_UDMA) >= VIA_UDMA_66)
+ if ((config->flags & VIA_UDMA) >= VIA_UDMA_100)
ap->cbl = via_cable_detect(ap);
- else
+ /* The UDMA66 series has no cable detect so do drive side detect */
+ else if ((config->flags & VIA_UDMA) < VIA_UDMA_66)
ap->cbl = ATA_CBL_PATA40;
+ else
+ ap->cbl = ATA_CBL_PATA_UNK;
+
+
return ata_std_prereset(ap);
}
@@ -390,7 +397,7 @@ static void via_config_fifo(struct pci_dev *pdev, unsigned int flags)
enable &= 3;
if (flags & VIA_SET_FIFO) {
- u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
+ static const u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
u8 fifo;
pci_read_config_byte(pdev, 0x43, &fifo);
diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
index 3ea345cde52..5d1f518e1cc 100644
--- a/drivers/ata/pata_winbond.c
+++ b/drivers/ata/pata_winbond.c
@@ -206,8 +206,8 @@ static __init int winbond_init_one(unsigned long port)
*/
pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0);
- if (pdev == NULL)
- return -ENOMEM;
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
memset(&ae, 0, sizeof(struct ata_probe_ent));
INIT_LIST_HEAD(&ae.node);
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 9021e34d209..90786d7a20b 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -551,7 +551,7 @@ static int adma_port_start(struct ata_port *ap)
return rc;
adma_enter_reg_mode(ap);
rc = -ENOMEM;
- pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
if (!pp)
goto err_out;
pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
@@ -672,7 +672,7 @@ static int adma_ata_init_one(struct pci_dev *pdev,
if (rc)
goto err_out_iounmap;
- probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+ probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
goto err_out_iounmap;
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 1b8e0eb9e03..aae0b5201c1 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -523,8 +523,7 @@ static const struct ata_port_info mv_port_info[] = {
},
{ /* chip_7042 */
.sht = &mv_sht,
- .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
- MV_FLAG_DUAL_HC),
+ .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv_iie_ops,
@@ -545,6 +544,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
+ { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
+
{ } /* terminate list */
};
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 0d316eb3c21..f7a963eb1f0 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -270,14 +270,6 @@ static const struct pci_device_id nv_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
- { PCI_VDEVICE(NVIDIA, 0x045c), GENERIC }, /* MCP65 */
- { PCI_VDEVICE(NVIDIA, 0x045d), GENERIC }, /* MCP65 */
- { PCI_VDEVICE(NVIDIA, 0x045e), GENERIC }, /* MCP65 */
- { PCI_VDEVICE(NVIDIA, 0x045f), GENERIC }, /* MCP65 */
- { PCI_VDEVICE(NVIDIA, 0x0550), GENERIC }, /* MCP67 */
- { PCI_VDEVICE(NVIDIA, 0x0551), GENERIC }, /* MCP67 */
- { PCI_VDEVICE(NVIDIA, 0x0552), GENERIC }, /* MCP67 */
- { PCI_VDEVICE(NVIDIA, 0x0553), GENERIC }, /* MCP67 */
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
@@ -708,7 +700,6 @@ static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
{
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
- int handled;
/* freeze if hotplugged */
if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
@@ -727,13 +718,7 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
}
/* handle interrupt */
- handled = ata_host_intr(ap, qc);
- if (unlikely(!handled)) {
- /* spurious, clear it */
- ata_check_status(ap);
- }
-
- return 1;
+ return ata_host_intr(ap, qc);
}
static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
@@ -760,6 +745,11 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
u8 irq_stat = readb(host->mmio_base + NV_INT_STATUS_CK804)
>> (NV_INT_PORT_SHIFT * i);
+ if(ata_tag_valid(ap->active_tag))
+ /** NV_INT_DEV indication seems unreliable at times
+ at least in ADMA mode. Force it on always when a
+ command is active, to prevent losing interrupts. */
+ irq_stat |= NV_INT_DEV;
handled += nv_host_intr(ap, irq_stat);
continue;
}
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index db32d15b7fa..46d8a94669b 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -56,6 +56,8 @@
#define DRV_VERSION "2.0"
enum {
+ K2_FLAG_NO_ATAPI_DMA = (1 << 29),
+
/* Taskfile registers offsets */
K2_SATA_TF_CMD_OFFSET = 0x00,
K2_SATA_TF_DATA_OFFSET = 0x00,
@@ -83,11 +85,33 @@ enum {
/* Port stride */
K2_SATA_PORT_OFFSET = 0x100,
+
+ board_svw4 = 0,
+ board_svw8 = 1,
+};
+
+static const struct k2_board_info {
+ unsigned int n_ports;
+ unsigned long port_flags;
+} k2_board_info[] = {
+ /* board_svw4 */
+ { 4, K2_FLAG_NO_ATAPI_DMA },
+
+ /* board_svw8 */
+ { 8, K2_FLAG_NO_ATAPI_DMA },
};
static u8 k2_stat_check_status(struct ata_port *ap);
+static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA)
+ return -1; /* ATAPI DMA not supported */
+
+ return 0;
+}
+
static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
@@ -111,26 +135,31 @@ static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
- writeb(tf->ctl, ioaddr->ctl_addr);
+ writeb(tf->ctl, (void __iomem *) ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
- writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
- writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
- writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
- writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
- writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
+ writew(tf->feature | (((u16)tf->hob_feature) << 8),
+ (void __iomem *) ioaddr->feature_addr);
+ writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
+ (void __iomem *) ioaddr->nsect_addr);
+ writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
+ (void __iomem *) ioaddr->lbal_addr);
+ writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
+ (void __iomem *) ioaddr->lbam_addr);
+ writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
+ (void __iomem *) ioaddr->lbah_addr);
} else if (is_addr) {
- writew(tf->feature, ioaddr->feature_addr);
- writew(tf->nsect, ioaddr->nsect_addr);
- writew(tf->lbal, ioaddr->lbal_addr);
- writew(tf->lbam, ioaddr->lbam_addr);
- writew(tf->lbah, ioaddr->lbah_addr);
+ writew(tf->feature, (void __iomem *) ioaddr->feature_addr);
+ writew(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+ writew(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+ writew(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+ writew(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
}
if (tf->flags & ATA_TFLAG_DEVICE)
- writeb(tf->device, ioaddr->device_addr);
+ writeb(tf->device, (void __iomem *) ioaddr->device_addr);
ata_wait_idle(ap);
}
@@ -142,12 +171,12 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
u16 nsect, lbal, lbam, lbah, feature;
tf->command = k2_stat_check_status(ap);
- tf->device = readw(ioaddr->device_addr);
- feature = readw(ioaddr->error_addr);
- nsect = readw(ioaddr->nsect_addr);
- lbal = readw(ioaddr->lbal_addr);
- lbam = readw(ioaddr->lbam_addr);
- lbah = readw(ioaddr->lbah_addr);
+ tf->device = readw((void __iomem *)ioaddr->device_addr);
+ feature = readw((void __iomem *)ioaddr->error_addr);
+ nsect = readw((void __iomem *)ioaddr->nsect_addr);
+ lbal = readw((void __iomem *)ioaddr->lbal_addr);
+ lbam = readw((void __iomem *)ioaddr->lbam_addr);
+ lbah = readw((void __iomem *)ioaddr->lbah_addr);
tf->feature = feature;
tf->nsect = nsect;
@@ -313,6 +342,7 @@ static const struct ata_port_operations k2_sata_ops = {
.check_status = k2_stat_check_status,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
+ .check_atapi_dma = k2_sata_check_atapi_dma,
.bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio,
.bmdma_stop = ata_bmdma_stop,
@@ -359,6 +389,8 @@ 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 __iomem *mmio_base;
+ const struct k2_board_info *board_info =
+ &k2_board_info[ent->driver_data];
int pci_dev_busy = 0;
int rc;
int i;
@@ -424,7 +456,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->sht = &k2_sata_sht;
probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_MMIO;
+ ATA_FLAG_MMIO | board_info->port_flags;
probe_ent->port_ops = &k2_sata_ops;
probe_ent->n_ports = 4;
probe_ent->irq = pdev->irq;
@@ -441,7 +473,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* different controllers have different number of ports - currently 4 or 8 */
/* All ports are on the same function. Multi-function device is no
* longer available. This should not be seen in any system. */
- for (i = 0; i < ent->driver_data; i++)
+ for (i = 0; i < board_info->n_ports; i++)
k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
pci_set_master(pdev);
@@ -469,11 +501,11 @@ err_out:
* controller
* */
static const struct pci_device_id k2_sata_pci_tbl[] = {
- { PCI_VDEVICE(SERVERWORKS, 0x0240), 4 },
- { PCI_VDEVICE(SERVERWORKS, 0x0241), 4 },
- { PCI_VDEVICE(SERVERWORKS, 0x0242), 8 },
- { PCI_VDEVICE(SERVERWORKS, 0x024a), 4 },
- { PCI_VDEVICE(SERVERWORKS, 0x024b), 4 },
+ { PCI_VDEVICE(SERVERWORKS, 0x0240), board_svw4 },
+ { PCI_VDEVICE(SERVERWORKS, 0x0241), board_svw4 },
+ { PCI_VDEVICE(SERVERWORKS, 0x0242), board_svw8 },
+ { PCI_VDEVICE(SERVERWORKS, 0x024a), board_svw4 },
+ { PCI_VDEVICE(SERVERWORKS, 0x024b), board_svw4 },
{ }
};
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 5c603ca3a50..a43aec62d50 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -128,7 +128,8 @@ static const struct ata_port_operations uli_ops = {
static struct ata_port_info uli_port_info = {
.sht = &uli_sht,
- .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_IGN_SIMPLEX,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &uli_ops,
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1c7f19aecc2..d3d5c0d5703 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -74,9 +74,11 @@ enum {
static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
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 void svia_noop_freeze(struct ata_port *ap);
static void vt6420_error_handler(struct ata_port *ap);
static const struct pci_device_id svia_pci_tbl[] = {
+ { PCI_VDEVICE(VIA, 0x5337), vt6420 },
{ PCI_VDEVICE(VIA, 0x0591), vt6420 },
{ PCI_VDEVICE(VIA, 0x3149), vt6420 },
{ PCI_VDEVICE(VIA, 0x3249), vt6421 },
@@ -127,7 +129,7 @@ static const struct ata_port_operations vt6420_sata_ops = {
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_pio_data_xfer,
- .freeze = ata_bmdma_freeze,
+ .freeze = svia_noop_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = vt6420_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
@@ -203,6 +205,15 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
}
+static void svia_noop_freeze(struct ata_port *ap)
+{
+ /* Some VIA controllers choke if ATA_NIEN is manipulated in
+ * certain way. Leave it alone and just clear pending IRQ.
+ */
+ ata_chk_status(ap);
+ ata_bmdma_irq_clear(ap);
+}
+
/**
* vt6420_prereset - prereset for vt6420
* @ap: target ATA port
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index e654b990b90..0fa1b89f76d 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -149,21 +149,26 @@ static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
- writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
- writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
- writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
- writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
- writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
+ writew(tf->feature | (((u16)tf->hob_feature) << 8),
+ (void __iomem *) ioaddr->feature_addr);
+ writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
+ (void __iomem *) ioaddr->nsect_addr);
+ writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
+ (void __iomem *) ioaddr->lbal_addr);
+ writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
+ (void __iomem *) ioaddr->lbam_addr);
+ writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
+ (void __iomem *) ioaddr->lbah_addr);
} else if (is_addr) {
- writew(tf->feature, ioaddr->feature_addr);
- writew(tf->nsect, ioaddr->nsect_addr);
- writew(tf->lbal, ioaddr->lbal_addr);
- writew(tf->lbam, ioaddr->lbam_addr);
- writew(tf->lbah, ioaddr->lbah_addr);
+ writew(tf->feature, (void __iomem *) ioaddr->feature_addr);
+ writew(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+ writew(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+ writew(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+ writew(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
}
if (tf->flags & ATA_TFLAG_DEVICE)
- writeb(tf->device, ioaddr->device_addr);
+ writeb(tf->device, (void __iomem *) ioaddr->device_addr);
ata_wait_idle(ap);
}
@@ -175,12 +180,12 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
u16 nsect, lbal, lbam, lbah, feature;
tf->command = ata_check_status(ap);
- tf->device = readw(ioaddr->device_addr);
- feature = readw(ioaddr->error_addr);
- nsect = readw(ioaddr->nsect_addr);
- lbal = readw(ioaddr->lbal_addr);
- lbam = readw(ioaddr->lbam_addr);
- lbah = readw(ioaddr->lbah_addr);
+ tf->device = readw((void __iomem *) ioaddr->device_addr);
+ feature = readw((void __iomem *) ioaddr->error_addr);
+ nsect = readw((void __iomem *) ioaddr->nsect_addr);
+ lbal = readw((void __iomem *) ioaddr->lbal_addr);
+ lbam = readw((void __iomem *) ioaddr->lbam_addr);
+ lbah = readw((void __iomem *) ioaddr->lbah_addr);
tf->feature = feature;
tf->nsect = nsect;
@@ -327,8 +332,8 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned lon
port->ctl_addr = base + VSC_SATA_TF_CTL_OFFSET;
port->bmdma_addr = base + VSC_SATA_DMA_CMD_OFFSET;
port->scr_addr = base + VSC_SATA_SCR_STATUS_OFFSET;
- writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
- writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
+ writel(0, (void __iomem *) base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
+ writel(0, (void __iomem *) base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
}
diff --git a/drivers/atm/.gitignore b/drivers/atm/.gitignore
index a165b716771..fc0ae5eb05d 100644
--- a/drivers/atm/.gitignore
+++ b/drivers/atm/.gitignore
@@ -2,4 +2,4 @@
fore200e_mkfirm
fore200e_pca_fw.c
pca200e.bin
-
+pca200e_ecd.bin2
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index cfa5af883e1..33687454eb3 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -167,10 +167,6 @@ config ATM_ZATM_DEBUG
Note that extended debugging may create certain race conditions
itself. Enable this ONLY if you suspect problems with the driver.
-# bool 'Rolfs TI TNETA1570' CONFIG_ATM_TNETA1570 y
-# if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then
-# bool ' Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
-# fi
config ATM_NICSTAR
tristate "IDT 77201 (NICStAR) (ForeRunnerLE)"
depends on PCI && ATM && !64BIT
@@ -242,6 +238,7 @@ config ATM_IDT77252_USE_SUNI
config ATM_AMBASSADOR
tristate "Madge Ambassador (Collage PCI 155 Server)"
depends on PCI && ATM
+ select BITREVERSE
help
This is a driver for ATMizer based ATM card produced by Madge
Networks Ltd. Say Y (or M to compile as a module named ambassador)
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index afa7d750a59..3c372e08f77 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/poison.h>
+#include <linux/bitrev.h>
#include <asm/atomic.h>
#include <asm/io.h>
@@ -2068,18 +2069,6 @@ static void __devinit amb_ucode_version (amb_dev * dev) {
PRINTK (KERN_INFO, "microcode version is %u.%u", major, minor);
}
-// swap bits within byte to get Ethernet ordering
-static u8 bit_swap (u8 byte)
-{
- const u8 swap[] = {
- 0x0, 0x8, 0x4, 0xc,
- 0x2, 0xa, 0x6, 0xe,
- 0x1, 0x9, 0x5, 0xd,
- 0x3, 0xb, 0x7, 0xf
- };
- return ((swap[byte & 0xf]<<4) | swap[byte>>4]);
-}
-
// get end station address
static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
u32 lower4;
@@ -2101,9 +2090,9 @@ static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
PRINTDB (DBG_INIT, "ESI:");
for (i = 0; i < ESI_LEN; ++i) {
if (i < 4)
- esi[i] = bit_swap (lower4>>(8*i));
+ esi[i] = bitrev8(lower4>>(8*i));
else
- esi[i] = bit_swap (upper2>>(8*(i-4)));
+ esi[i] = bitrev8(upper2>>(8*(i-4)));
PRINTDM (DBG_INIT, " %02x", esi[i]);
}
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index bc1b13c8f5d..5aab7bd473a 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1832,7 +1832,7 @@ static int __devinit eni_start(struct atm_dev *dev)
/* initialize memory management */
buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
- eni_dev->free_list = (struct eni_free *) kmalloc(
+ eni_dev->free_list = kmalloc(
sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
if (!eni_dev->free_list) {
printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
@@ -2232,7 +2232,7 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
goto out0;
}
- eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
+ eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
if (!eni_dev) goto out0;
if (!cpu_zeroes) {
cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 3a7b21ff30a..4aeb3d062ff 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -172,25 +172,6 @@ fore200e_irq_itoa(int irq)
}
-static void*
-fore200e_kmalloc(int size, gfp_t flags)
-{
- void *chunk = kzalloc(size, flags);
-
- if (!chunk)
- printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);
-
- return chunk;
-}
-
-
-static void
-fore200e_kfree(void* chunk)
-{
- kfree(chunk);
-}
-
-
/* allocate and align a chunk of memory intended to hold the data behing exchanged
between the driver and the adapter (using streaming DVMA) */
@@ -206,7 +187,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i
chunk->align_size = size;
chunk->direction = direction;
- chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);
+ chunk->alloc_addr = kzalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);
if (chunk->alloc_addr == NULL)
return -ENOMEM;
@@ -228,7 +209,7 @@ fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
{
fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction);
- fore200e_kfree(chunk->alloc_addr);
+ kfree(chunk->alloc_addr);
}
@@ -882,7 +863,7 @@ fore200e_sba_detect(const struct fore200e_bus* bus, int index)
return NULL;
}
- fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
+ fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
if (fore200e == NULL)
return NULL;
@@ -1505,7 +1486,7 @@ fore200e_open(struct atm_vcc *vcc)
spin_unlock_irqrestore(&fore200e->q_lock, flags);
- fore200e_vcc = fore200e_kmalloc(sizeof(struct fore200e_vcc), GFP_ATOMIC);
+ fore200e_vcc = kzalloc(sizeof(struct fore200e_vcc), GFP_ATOMIC);
if (fore200e_vcc == NULL) {
vc_map->vcc = NULL;
return -ENOMEM;
@@ -1526,7 +1507,7 @@ fore200e_open(struct atm_vcc *vcc)
if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {
up(&fore200e->rate_sf);
- fore200e_kfree(fore200e_vcc);
+ kfree(fore200e_vcc);
vc_map->vcc = NULL;
return -EAGAIN;
}
@@ -1554,7 +1535,7 @@ fore200e_open(struct atm_vcc *vcc)
fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
- fore200e_kfree(fore200e_vcc);
+ kfree(fore200e_vcc);
return -EINVAL;
}
@@ -1630,7 +1611,7 @@ fore200e_close(struct atm_vcc* vcc)
clear_bit(ATM_VF_PARTIAL,&vcc->flags);
ASSERT(fore200e_vcc);
- fore200e_kfree(fore200e_vcc);
+ kfree(fore200e_vcc);
}
@@ -1831,7 +1812,7 @@ fore200e_getstats(struct fore200e* fore200e)
u32 stats_dma_addr;
if (fore200e->stats == NULL) {
- fore200e->stats = fore200e_kmalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA);
+ fore200e->stats = kzalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA);
if (fore200e->stats == NULL)
return -ENOMEM;
}
@@ -2002,17 +1983,6 @@ fore200e_setloop(struct fore200e* fore200e, int loop_mode)
}
-static inline unsigned int
-fore200e_swap(unsigned int in)
-{
-#if defined(__LITTLE_ENDIAN)
- return swab32(in);
-#else
- return in;
-#endif
-}
-
-
static int
fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats __user *arg)
{
@@ -2021,19 +1991,19 @@ fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats __user *arg)
if (fore200e_getstats(fore200e) < 0)
return -EIO;
- tmp.section_bip = fore200e_swap(fore200e->stats->oc3.section_bip8_errors);
- tmp.line_bip = fore200e_swap(fore200e->stats->oc3.line_bip24_errors);
- tmp.path_bip = fore200e_swap(fore200e->stats->oc3.path_bip8_errors);
- tmp.line_febe = fore200e_swap(fore200e->stats->oc3.line_febe_errors);
- tmp.path_febe = fore200e_swap(fore200e->stats->oc3.path_febe_errors);
- tmp.corr_hcs = fore200e_swap(fore200e->stats->oc3.corr_hcs_errors);
- tmp.uncorr_hcs = fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors);
- tmp.tx_cells = fore200e_swap(fore200e->stats->aal0.cells_transmitted) +
- fore200e_swap(fore200e->stats->aal34.cells_transmitted) +
- fore200e_swap(fore200e->stats->aal5.cells_transmitted);
- tmp.rx_cells = fore200e_swap(fore200e->stats->aal0.cells_received) +
- fore200e_swap(fore200e->stats->aal34.cells_received) +
- fore200e_swap(fore200e->stats->aal5.cells_received);
+ tmp.section_bip = cpu_to_be32(fore200e->stats->oc3.section_bip8_errors);
+ tmp.line_bip = cpu_to_be32(fore200e->stats->oc3.line_bip24_errors);
+ tmp.path_bip = cpu_to_be32(fore200e->stats->oc3.path_bip8_errors);
+ tmp.line_febe = cpu_to_be32(fore200e->stats->oc3.line_febe_errors);
+ tmp.path_febe = cpu_to_be32(fore200e->stats->oc3.path_febe_errors);
+ tmp.corr_hcs = cpu_to_be32(fore200e->stats->oc3.corr_hcs_errors);
+ tmp.uncorr_hcs = cpu_to_be32(fore200e->stats->oc3.ucorr_hcs_errors);
+ tmp.tx_cells = cpu_to_be32(fore200e->stats->aal0.cells_transmitted) +
+ cpu_to_be32(fore200e->stats->aal34.cells_transmitted) +
+ cpu_to_be32(fore200e->stats->aal5.cells_transmitted);
+ tmp.rx_cells = cpu_to_be32(fore200e->stats->aal0.cells_received) +
+ cpu_to_be32(fore200e->stats->aal34.cells_received) +
+ cpu_to_be32(fore200e->stats->aal5.cells_received);
if (arg)
return copy_to_user(arg, &tmp, sizeof(struct sonet_stats)) ? -EFAULT : 0;
@@ -2146,7 +2116,7 @@ fore200e_irq_request(struct fore200e* fore200e)
static int __devinit
fore200e_get_esi(struct fore200e* fore200e)
{
- struct prom_data* prom = fore200e_kmalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
+ struct prom_data* prom = kzalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
int ok, i;
if (!prom)
@@ -2154,7 +2124,7 @@ fore200e_get_esi(struct fore200e* fore200e)
ok = fore200e->bus->prom_read(fore200e, prom);
if (ok < 0) {
- fore200e_kfree(prom);
+ kfree(prom);
return -EBUSY;
}
@@ -2169,7 +2139,7 @@ fore200e_get_esi(struct fore200e* fore200e)
fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ];
}
- fore200e_kfree(prom);
+ kfree(prom);
return 0;
}
@@ -2194,7 +2164,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
DPRINTK(2, "rx buffers %d / %d are being allocated\n", scheme, magn);
/* allocate the array of receive buffers */
- buffer = bsq->buffer = fore200e_kmalloc(nbr * sizeof(struct buffer), GFP_KERNEL);
+ buffer = bsq->buffer = kzalloc(nbr * sizeof(struct buffer), GFP_KERNEL);
if (buffer == NULL)
return -ENOMEM;
@@ -2217,7 +2187,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
while (i > 0)
fore200e_chunk_free(fore200e, &buffer[ --i ].data);
- fore200e_kfree(buffer);
+ kfree(buffer);
return -ENOMEM;
}
@@ -2736,7 +2706,7 @@ fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent
goto out;
}
- fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
+ fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
if (fore200e == NULL) {
err = -ENOMEM;
goto out_disable;
@@ -2999,8 +2969,8 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" 4b5b:\n"
" crc_header_errors:\t\t%10u\n"
" framing_errors:\t\t%10u\n",
- fore200e_swap(fore200e->stats->phy.crc_header_errors),
- fore200e_swap(fore200e->stats->phy.framing_errors));
+ cpu_to_be32(fore200e->stats->phy.crc_header_errors),
+ cpu_to_be32(fore200e->stats->phy.framing_errors));
if (!left--)
return sprintf(page, "\n"
@@ -3012,13 +2982,13 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" path_febe_errors:\t\t%10u\n"
" corr_hcs_errors:\t\t%10u\n"
" ucorr_hcs_errors:\t\t%10u\n",
- fore200e_swap(fore200e->stats->oc3.section_bip8_errors),
- fore200e_swap(fore200e->stats->oc3.path_bip8_errors),
- fore200e_swap(fore200e->stats->oc3.line_bip24_errors),
- fore200e_swap(fore200e->stats->oc3.line_febe_errors),
- fore200e_swap(fore200e->stats->oc3.path_febe_errors),
- fore200e_swap(fore200e->stats->oc3.corr_hcs_errors),
- fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors));
+ cpu_to_be32(fore200e->stats->oc3.section_bip8_errors),
+ cpu_to_be32(fore200e->stats->oc3.path_bip8_errors),
+ cpu_to_be32(fore200e->stats->oc3.line_bip24_errors),
+ cpu_to_be32(fore200e->stats->oc3.line_febe_errors),
+ cpu_to_be32(fore200e->stats->oc3.path_febe_errors),
+ cpu_to_be32(fore200e->stats->oc3.corr_hcs_errors),
+ cpu_to_be32(fore200e->stats->oc3.ucorr_hcs_errors));
if (!left--)
return sprintf(page,"\n"
@@ -3029,12 +2999,12 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" vpi no conn:\t\t%10u\n"
" vci out of range:\t\t%10u\n"
" vci no conn:\t\t%10u\n",
- fore200e_swap(fore200e->stats->atm.cells_transmitted),
- fore200e_swap(fore200e->stats->atm.cells_received),
- fore200e_swap(fore200e->stats->atm.vpi_bad_range),
- fore200e_swap(fore200e->stats->atm.vpi_no_conn),
- fore200e_swap(fore200e->stats->atm.vci_bad_range),
- fore200e_swap(fore200e->stats->atm.vci_no_conn));
+ cpu_to_be32(fore200e->stats->atm.cells_transmitted),
+ cpu_to_be32(fore200e->stats->atm.cells_received),
+ cpu_to_be32(fore200e->stats->atm.vpi_bad_range),
+ cpu_to_be32(fore200e->stats->atm.vpi_no_conn),
+ cpu_to_be32(fore200e->stats->atm.vci_bad_range),
+ cpu_to_be32(fore200e->stats->atm.vci_no_conn));
if (!left--)
return sprintf(page,"\n"
@@ -3042,9 +3012,9 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" TX:\t\t\t%10u\n"
" RX:\t\t\t%10u\n"
" dropped:\t\t\t%10u\n",
- fore200e_swap(fore200e->stats->aal0.cells_transmitted),
- fore200e_swap(fore200e->stats->aal0.cells_received),
- fore200e_swap(fore200e->stats->aal0.cells_dropped));
+ cpu_to_be32(fore200e->stats->aal0.cells_transmitted),
+ cpu_to_be32(fore200e->stats->aal0.cells_received),
+ cpu_to_be32(fore200e->stats->aal0.cells_dropped));
if (!left--)
return sprintf(page,"\n"
@@ -3060,15 +3030,15 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" RX:\t\t\t%10u\n"
" dropped:\t\t\t%10u\n"
" protocol errors:\t\t%10u\n",
- fore200e_swap(fore200e->stats->aal34.cells_transmitted),
- fore200e_swap(fore200e->stats->aal34.cells_received),
- fore200e_swap(fore200e->stats->aal34.cells_dropped),
- fore200e_swap(fore200e->stats->aal34.cells_crc_errors),
- fore200e_swap(fore200e->stats->aal34.cells_protocol_errors),
- fore200e_swap(fore200e->stats->aal34.cspdus_transmitted),
- fore200e_swap(fore200e->stats->aal34.cspdus_received),
- fore200e_swap(fore200e->stats->aal34.cspdus_dropped),
- fore200e_swap(fore200e->stats->aal34.cspdus_protocol_errors));
+ cpu_to_be32(fore200e->stats->aal34.cells_transmitted),
+ cpu_to_be32(fore200e->stats->aal34.cells_received),
+ cpu_to_be32(fore200e->stats->aal34.cells_dropped),
+ cpu_to_be32(fore200e->stats->aal34.cells_crc_errors),
+ cpu_to_be32(fore200e->stats->aal34.cells_protocol_errors),
+ cpu_to_be32(fore200e->stats->aal34.cspdus_transmitted),
+ cpu_to_be32(fore200e->stats->aal34.cspdus_received),
+ cpu_to_be32(fore200e->stats->aal34.cspdus_dropped),
+ cpu_to_be32(fore200e->stats->aal34.cspdus_protocol_errors));
if (!left--)
return sprintf(page,"\n"
@@ -3084,15 +3054,15 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" dropped:\t\t\t%10u\n"
" CRC errors:\t\t%10u\n"
" protocol errors:\t\t%10u\n",
- fore200e_swap(fore200e->stats->aal5.cells_transmitted),
- fore200e_swap(fore200e->stats->aal5.cells_received),
- fore200e_swap(fore200e->stats->aal5.cells_dropped),
- fore200e_swap(fore200e->stats->aal5.congestion_experienced),
- fore200e_swap(fore200e->stats->aal5.cspdus_transmitted),
- fore200e_swap(fore200e->stats->aal5.cspdus_received),
- fore200e_swap(fore200e->stats->aal5.cspdus_dropped),
- fore200e_swap(fore200e->stats->aal5.cspdus_crc_errors),
- fore200e_swap(fore200e->stats->aal5.cspdus_protocol_errors));
+ cpu_to_be32(fore200e->stats->aal5.cells_transmitted),
+ cpu_to_be32(fore200e->stats->aal5.cells_received),
+ cpu_to_be32(fore200e->stats->aal5.cells_dropped),
+ cpu_to_be32(fore200e->stats->aal5.congestion_experienced),
+ cpu_to_be32(fore200e->stats->aal5.cspdus_transmitted),
+ cpu_to_be32(fore200e->stats->aal5.cspdus_received),
+ cpu_to_be32(fore200e->stats->aal5.cspdus_dropped),
+ cpu_to_be32(fore200e->stats->aal5.cspdus_crc_errors),
+ cpu_to_be32(fore200e->stats->aal5.cspdus_protocol_errors));
if (!left--)
return sprintf(page,"\n"
@@ -3103,11 +3073,11 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
" large b2:\t\t\t%10u\n"
" RX PDUs:\t\t\t%10u\n"
" TX PDUs:\t\t\t%10lu\n",
- fore200e_swap(fore200e->stats->aux.small_b1_failed),
- fore200e_swap(fore200e->stats->aux.large_b1_failed),
- fore200e_swap(fore200e->stats->aux.small_b2_failed),
- fore200e_swap(fore200e->stats->aux.large_b2_failed),
- fore200e_swap(fore200e->stats->aux.rpd_alloc_failed),
+ cpu_to_be32(fore200e->stats->aux.small_b1_failed),
+ cpu_to_be32(fore200e->stats->aux.large_b1_failed),
+ cpu_to_be32(fore200e->stats->aux.small_b2_failed),
+ cpu_to_be32(fore200e->stats->aux.large_b2_failed),
+ cpu_to_be32(fore200e->stats->aux.rpd_alloc_failed),
fore200e->tx_sat);
if (!left--)
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 7d9b4e52f0b..db33f6f4dd2 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -2351,7 +2351,7 @@ he_open(struct atm_vcc *vcc)
cid = he_mkcid(he_dev, vpi, vci);
- he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
+ he_vcc = kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
if (he_vcc == NULL) {
hprintk("unable to allocate he_vcc during open\n");
return -ENOMEM;
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 4dc10105d61..f96446c358b 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1845,7 +1845,7 @@ static u16 __devinit read_bia (const hrz_dev * dev, u16 addr)
/********** initialise a card **********/
-static int __init hrz_init (hrz_dev * dev) {
+static int __devinit hrz_init (hrz_dev * dev) {
int onefivefive;
u16 chan;
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 267825501df..09f477d4237 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -2602,7 +2602,7 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
struct atm_dev *atmdev;
int result;
- lanai = (struct lanai_dev *) kmalloc(sizeof(*lanai), GFP_KERNEL);
+ lanai = kmalloc(sizeof(*lanai), GFP_KERNEL);
if (lanai == NULL) {
printk(KERN_ERR DEV_LABEL
": couldn't allocate dev_data structure!\n");
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index bd090459480..aab9b3733d5 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -997,7 +997,7 @@ static scq_info *get_scq(int size, u32 scd)
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
return NULL;
- scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
+ scq = kmalloc(sizeof(scq_info), GFP_KERNEL);
if (scq == NULL)
return NULL;
scq->org = kmalloc(2 * size, GFP_KERNEL);
@@ -1006,7 +1006,7 @@ static scq_info *get_scq(int size, u32 scd)
kfree(scq);
return NULL;
}
- scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
+ scq->skb = kmalloc(sizeof(struct sk_buff *) *
(size / NS_SCQE_SIZE), GFP_KERNEL);
if (scq->skb == NULL)
{
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 7df0f373188..756d4f760da 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -996,7 +996,7 @@ static int start_tx(struct atm_dev *dev)
DPRINTK("start_tx\n");
zatm_dev = ZATM_DEV(dev);
- zatm_dev->tx_map = (struct atm_vcc **) kmalloc(sizeof(struct atm_vcc *)*
+ zatm_dev->tx_map = kmalloc(sizeof(struct atm_vcc *)*
zatm_dev->chans,GFP_KERNEL);
if (!zatm_dev->tx_map) return -ENOMEM;
zatm_dev->tx_bw = ATM_OC3_PCR;
@@ -1591,7 +1591,7 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev,
struct zatm_dev *zatm_dev;
int ret = -ENOMEM;
- zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
+ zatm_dev = kmalloc(sizeof(*zatm_dev), GFP_KERNEL);
if (!zatm_dev) {
printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL);
goto out;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index f098881f45b..8bf2ca2e56b 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -163,6 +163,8 @@ int class_register(struct class * cls)
void class_unregister(struct class * cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
+ if (cls->virtual_dir)
+ kobject_unregister(cls->virtual_dir);
remove_class_attrs(cls);
subsystem_unregister(&cls->subsys);
}
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index dbe0735f8c9..f95d5027727 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -173,7 +173,7 @@ pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags)
mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
mapsize *= sizeof (long);
- page = (struct dma_page *) kmalloc (mapsize + sizeof *page, mem_flags);
+ page = kmalloc(mapsize + sizeof *page, mem_flags);
if (!page)
return NULL;
page->vaddr = dma_alloc_coherent (pool->dev,
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4bad2870c48..64558f45e6b 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -127,6 +127,7 @@ static ssize_t firmware_loading_show(struct device *dev,
/**
* firmware_loading_store - set value in the 'loading' control file
* @dev: device pointer
+ * @attr: device attribute pointer
* @buf: buffer to scan for loading control value
* @count: number of bytes in @buf
*
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index d1df4a08792..f9c903ba9fc 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources);
* pointer. The memory associated with the platform data will be freed
* when the platform device is released.
*/
-int platform_device_add_data(struct platform_device *pdev, void *data, size_t size)
+int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)
{
void *d;
@@ -473,7 +473,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
*/
-int platform_driver_probe(struct platform_driver *drv,
+int __init_or_module platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
{
int retval, code;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 85072446d77..58c1debf86f 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -28,13 +28,6 @@ config ATARI_FLOPPY
tristate "Atari floppy support"
depends on ATARI
-config BLK_DEV_SWIM_IOP
- bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
- depends on MAC && EXPERIMENTAL && BROKEN
- help
- Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
- floppy controller on the Macintosh IIfx and Quadra 900/950.
-
config MAC_FLOPPY
tristate "Support for PowerMac floppy"
depends on PPC_PMAC && !PPC_PMAC64
@@ -431,14 +424,18 @@ config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media"
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
- compliant ATAPI or SCSI drive, which is just about any newer CD
- writer.
+ If you have a CDROM/DVD drive that supports packet writing, say
+ Y to include support. It should work with any MMC/Mt Fuji
+ compliant ATAPI or SCSI drive, which is just about any newer
+ DVD/CD writer.
- Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible.
+ Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs
+ is possible.
DVD-RW disks must be in restricted overwrite mode.
+ See the file <file:Documentation/cdrom/packet-writing.txt>
+ for further information on the use of this driver.
+
To compile this driver as a module, choose M here: the
module will be called pktcdvd.
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 410f259a803..dd88e33c1eb 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
-obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o
obj-$(CONFIG_ATARI_ACSI) += acsi.o
obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 8e41c87b026..e04be94d195 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -363,7 +363,7 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count,
loff_t *ppos )
{
- struct inode *node = file->f_dentry->d_inode;
+ struct inode *node = file->f_path.dentry->d_inode;
unsigned long page;
int length;
int end;
@@ -618,7 +618,7 @@ static ssize_t slm_write( struct file *file, const char *buf, size_t count,
loff_t *ppos )
{
- struct inode *node = file->f_dentry->d_inode;
+ struct inode *node = file->f_path.dentry->d_inode;
int device = iminor(node);
int n, filled, w, h;
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 97f7f535f41..bb022ed4a86 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -30,8 +30,6 @@ new_skb(ulong len)
skb->nh.raw = skb->mac.raw = skb->data;
skb->protocol = __constant_htons(ETH_P_AOE);
skb->priority = 0;
- skb_put(skb, len);
- memset(skb->head, 0, len);
skb->next = skb->prev = NULL;
/* tell the network layer not to perform IP checksums
@@ -122,8 +120,8 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
skb = f->skb;
h = (struct aoe_hdr *) skb->mac.raw;
ah = (struct aoe_atahdr *) (h+1);
- skb->len = sizeof *h + sizeof *ah;
- memset(h, 0, ETH_ZLEN);
+ skb_put(skb, sizeof *h + sizeof *ah);
+ memset(h, 0, skb->len);
f->tag = aoehdr_atainit(d, h);
f->waited = 0;
f->buf = buf;
@@ -149,7 +147,6 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
skb->len += bcnt;
skb->data_len = bcnt;
} else {
- skb->len = ETH_ZLEN;
writebit = 0;
}
@@ -206,6 +203,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
printk(KERN_INFO "aoe: skb alloc failure\n");
continue;
}
+ skb_put(skb, sizeof *h + sizeof *ch);
skb->dev = ifp;
if (sl_tail == NULL)
sl_tail = skb;
@@ -243,6 +241,7 @@ freeframe(struct aoedev *d)
continue;
if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) {
skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
+ skb_trim(f->skb, 0);
return f;
}
n++;
@@ -698,8 +697,8 @@ aoecmd_ata_id(struct aoedev *d)
skb = f->skb;
h = (struct aoe_hdr *) skb->mac.raw;
ah = (struct aoe_atahdr *) (h+1);
- skb->len = ETH_ZLEN;
- memset(h, 0, ETH_ZLEN);
+ skb_put(skb, sizeof *h + sizeof *ah);
+ memset(h, 0, skb->len);
f->tag = aoehdr_atainit(d, h);
f->waited = 0;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 892e092afe9..05dfe357527 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -225,6 +225,8 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
#include "cciss_scsi.c" /* For SCSI tape support */
+#define RAID_UNKNOWN 6
+
#ifdef CONFIG_PROC_FS
/*
@@ -232,7 +234,6 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
*/
#define ENG_GIG 1000000000
#define ENG_GIG_FACTOR (ENG_GIG/512)
-#define RAID_UNKNOWN 6
static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
"UNKNOWN"
};
@@ -535,7 +536,7 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
{
int ret;
lock_kernel();
- ret = cciss_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+ ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
unlock_kernel();
return ret;
}
@@ -1039,7 +1040,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
status = -ENOMEM;
goto cleanup1;
}
- buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int),
+ buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
GFP_KERNEL);
if (!buff_size) {
status = -ENOMEM;
@@ -1907,6 +1908,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
"does not support reading geometry\n");
drv->heads = 255;
drv->sectors = 32; // Sectors per track
+ drv->raid_level = RAID_UNKNOWN;
} else {
drv->heads = inq_buff->data_byte[6];
drv->sectors = inq_buff->data_byte[7];
@@ -2491,7 +2493,7 @@ static void do_cciss_request(request_queue_t *q)
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction =
- (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
+ (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] =
(rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
@@ -2837,7 +2839,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
if (err) {
printk(KERN_ERR "cciss: Cannot obtain PCI resources, "
"aborting\n");
- goto err_out_disable_pdev;
+ return err;
}
subsystem_vendor_id = pdev->subsystem_vendor;
@@ -2865,7 +2867,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
#ifdef CCISS_DEBUG
printk("address 0 = %x\n", c->paddr);
#endif /* CCISS_DEBUG */
- c->vaddr = remap_pci_mem(c->paddr, 200);
+ c->vaddr = remap_pci_mem(c->paddr, 0x250);
/* Wait for the board to become ready. (PCI hotplug needs this.)
* We poll for up to 120 secs, once per 100ms. */
@@ -3004,11 +3006,12 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
}
return 0;
- err_out_free_res:
+err_out_free_res:
+ /*
+ * Deliberately omit pci_disable_device(): it does something nasty to
+ * Smart Array controllers that pci_enable_device does not undo
+ */
pci_release_regions(pdev);
-
- err_out_disable_pdev:
- pci_disable_device(pdev);
return err;
}
@@ -3382,8 +3385,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
if (drv->queue)
blk_cleanup_queue(drv->queue);
}
+ /*
+ * Deliberately omit pci_disable_device(): it does something nasty to
+ * Smart Array controllers that pci_enable_device does not undo
+ */
pci_release_regions(pdev);
- pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_hba(i);
return -1;
@@ -3452,8 +3458,11 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
#ifdef CONFIG_CISS_SCSI_TAPE
kfree(hba[i]->scsi_rejects.complete);
#endif
+ /*
+ * Deliberately omit pci_disable_device(): it does something nasty to
+ * Smart Array controllers that pci_enable_device does not undo
+ */
pci_release_regions(pdev);
- pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_hba(i);
}
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index d5f519ebbc0..b94cd1c3213 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1625,7 +1625,7 @@ static void start_fwbk(int ctlr)
" processing\n");
/* Command does not return anything, but idasend command needs a
buffer */
- id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+ id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf==NULL)
{
printk(KERN_WARNING "cpqarray: Out of memory. "
@@ -1660,14 +1660,14 @@ static void getgeometry(int ctlr)
info_p->log_drv_map = 0;
- id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
+ id_ldrive = kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
if(id_ldrive == NULL)
{
printk( KERN_ERR "cpqarray: out of memory.\n");
return;
}
- id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+ id_ctlr_buf = kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
if(id_ctlr_buf == NULL)
{
kfree(id_ldrive);
@@ -1675,7 +1675,7 @@ static void getgeometry(int ctlr)
return;
}
- id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
+ id_lstatus_buf = kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
if(id_lstatus_buf == NULL)
{
kfree(id_ctlr_buf);
@@ -1684,7 +1684,7 @@ static void getgeometry(int ctlr)
return;
}
- sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
+ sense_config_buf = kmalloc(sizeof(config_t), GFP_KERNEL);
if(sense_config_buf == NULL)
{
kfree(id_lstatus_buf);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index beab6d2643c..6b5b6420740 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1000,7 +1000,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
if (lo->lo_state != Lo_bound)
return -ENXIO;
- error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
+ error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
if (error)
return error;
memset(info, 0, sizeof(*info));
@@ -1287,7 +1287,7 @@ loop_get_status_compat(struct loop_device *lo,
static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
int err;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7bf2cfbd628..090796bef78 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -537,7 +537,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
error = -EINVAL;
file = fget(arg);
if (file) {
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (S_ISSOCK(inode->i_mode)) {
lo->file = file;
lo->sock = SOCKET_I(inode);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index e45eaa26411..62462190e07 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2000 Jens Axboe <axboe@suse.de>
* Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com>
+ * Copyright (C) 2006 Thomas Maier <balagi@justmail.de>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
@@ -59,6 +60,8 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
@@ -83,9 +86,424 @@
static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
static struct proc_dir_entry *pkt_proc;
static int pktdev_major;
+static int write_congestion_on = PKT_WRITE_CONGESTION_ON;
+static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
static mempool_t *psd_pool;
+static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */
+static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */
+
+/* forward declaration */
+static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
+static int pkt_remove_dev(dev_t pkt_dev);
+static int pkt_seq_show(struct seq_file *m, void *p);
+
+
+
+/*
+ * create and register a pktcdvd kernel object.
+ */
+static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
+ const char* name,
+ struct kobject* parent,
+ struct kobj_type* ktype)
+{
+ struct pktcdvd_kobj *p;
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return NULL;
+ kobject_set_name(&p->kobj, "%s", name);
+ p->kobj.parent = parent;
+ p->kobj.ktype = ktype;
+ p->pd = pd;
+ if (kobject_register(&p->kobj) != 0)
+ return NULL;
+ return p;
+}
+/*
+ * remove a pktcdvd kernel object.
+ */
+static void pkt_kobj_remove(struct pktcdvd_kobj *p)
+{
+ if (p)
+ kobject_unregister(&p->kobj);
+}
+/*
+ * default release function for pktcdvd kernel objects.
+ */
+static void pkt_kobj_release(struct kobject *kobj)
+{
+ kfree(to_pktcdvdkobj(kobj));
+}
+
+
+/**********************************************************
+ *
+ * sysfs interface for pktcdvd
+ * by (C) 2006 Thomas Maier <balagi@justmail.de>
+ *
+ **********************************************************/
+
+#define DEF_ATTR(_obj,_name,_mode) \
+ static struct attribute _obj = { \
+ .name = _name, .owner = THIS_MODULE, .mode = _mode }
+
+/**********************************************************
+ /sys/class/pktcdvd/pktcdvd[0-7]/
+ stat/reset
+ stat/packets_started
+ stat/packets_finished
+ stat/kb_written
+ stat/kb_read
+ stat/kb_read_gather
+ write_queue/size
+ write_queue/congestion_off
+ write_queue/congestion_on
+ **********************************************************/
+
+DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200);
+DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444);
+DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444);
+DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444);
+DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444);
+DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444);
+
+static struct attribute *kobj_pkt_attrs_stat[] = {
+ &kobj_pkt_attr_st1,
+ &kobj_pkt_attr_st2,
+ &kobj_pkt_attr_st3,
+ &kobj_pkt_attr_st4,
+ &kobj_pkt_attr_st5,
+ &kobj_pkt_attr_st6,
+ NULL
+};
+
+DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444);
+DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644);
+DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on", 0644);
+
+static struct attribute *kobj_pkt_attrs_wqueue[] = {
+ &kobj_pkt_attr_wq1,
+ &kobj_pkt_attr_wq2,
+ &kobj_pkt_attr_wq3,
+ NULL
+};
+
+/* declares a char buffer[64] _dbuf, copies data from
+ * _b with length _l into it and ensures that _dbuf ends
+ * with a \0 character.
+ */
+#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \
+ char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \
+ if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \
+ memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0
+
+static ssize_t kobj_pkt_show(struct kobject *kobj,
+ struct attribute *attr, char *data)
+{
+ struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
+ int n = 0;
+ int v;
+ if (strcmp(attr->name, "packets_started") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.pkt_started);
+
+ } else if (strcmp(attr->name, "packets_finished") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.pkt_ended);
+
+ } else if (strcmp(attr->name, "kb_written") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1);
+
+ } else if (strcmp(attr->name, "kb_read") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1);
+
+ } else if (strcmp(attr->name, "kb_read_gather") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1);
+
+ } else if (strcmp(attr->name, "size") == 0) {
+ spin_lock(&pd->lock);
+ v = pd->bio_queue_size;
+ spin_unlock(&pd->lock);
+ n = sprintf(data, "%d\n", v);
+
+ } else if (strcmp(attr->name, "congestion_off") == 0) {
+ spin_lock(&pd->lock);
+ v = pd->write_congestion_off;
+ spin_unlock(&pd->lock);
+ n = sprintf(data, "%d\n", v);
+
+ } else if (strcmp(attr->name, "congestion_on") == 0) {
+ spin_lock(&pd->lock);
+ v = pd->write_congestion_on;
+ spin_unlock(&pd->lock);
+ n = sprintf(data, "%d\n", v);
+ }
+ return n;
+}
+
+static void init_write_congestion_marks(int* lo, int* hi)
+{
+ if (*hi > 0) {
+ *hi = max(*hi, 500);
+ *hi = min(*hi, 1000000);
+ if (*lo <= 0)
+ *lo = *hi - 100;
+ else {
+ *lo = min(*lo, *hi - 100);
+ *lo = max(*lo, 100);
+ }
+ } else {
+ *hi = -1;
+ *lo = -1;
+ }
+}
+
+static ssize_t kobj_pkt_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *data, size_t len)
+{
+ struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
+ int val;
+ DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */
+
+ if (strcmp(attr->name, "reset") == 0 && dlen > 0) {
+ pd->stats.pkt_started = 0;
+ pd->stats.pkt_ended = 0;
+ pd->stats.secs_w = 0;
+ pd->stats.secs_rg = 0;
+ pd->stats.secs_r = 0;
+
+ } else if (strcmp(attr->name, "congestion_off") == 0
+ && sscanf(dbuf, "%d", &val) == 1) {
+ spin_lock(&pd->lock);
+ pd->write_congestion_off = val;
+ init_write_congestion_marks(&pd->write_congestion_off,
+ &pd->write_congestion_on);
+ spin_unlock(&pd->lock);
+
+ } else if (strcmp(attr->name, "congestion_on") == 0
+ && sscanf(dbuf, "%d", &val) == 1) {
+ spin_lock(&pd->lock);
+ pd->write_congestion_on = val;
+ init_write_congestion_marks(&pd->write_congestion_off,
+ &pd->write_congestion_on);
+ spin_unlock(&pd->lock);
+ }
+ return len;
+}
+
+static struct sysfs_ops kobj_pkt_ops = {
+ .show = kobj_pkt_show,
+ .store = kobj_pkt_store
+};
+static struct kobj_type kobj_pkt_type_stat = {
+ .release = pkt_kobj_release,
+ .sysfs_ops = &kobj_pkt_ops,
+ .default_attrs = kobj_pkt_attrs_stat
+};
+static struct kobj_type kobj_pkt_type_wqueue = {
+ .release = pkt_kobj_release,
+ .sysfs_ops = &kobj_pkt_ops,
+ .default_attrs = kobj_pkt_attrs_wqueue
+};
+
+static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
+{
+ if (class_pktcdvd) {
+ pd->clsdev = class_device_create(class_pktcdvd,
+ NULL, pd->pkt_dev,
+ NULL, "%s", pd->name);
+ if (IS_ERR(pd->clsdev))
+ pd->clsdev = NULL;
+ }
+ if (pd->clsdev) {
+ pd->kobj_stat = pkt_kobj_create(pd, "stat",
+ &pd->clsdev->kobj,
+ &kobj_pkt_type_stat);
+ pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue",
+ &pd->clsdev->kobj,
+ &kobj_pkt_type_wqueue);
+ }
+}
+
+static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
+{
+ pkt_kobj_remove(pd->kobj_stat);
+ pkt_kobj_remove(pd->kobj_wqueue);
+ if (class_pktcdvd)
+ class_device_destroy(class_pktcdvd, pd->pkt_dev);
+}
+
+
+/********************************************************************
+ /sys/class/pktcdvd/
+ add map block device
+ remove unmap packet dev
+ device_map show mappings
+ *******************************************************************/
+
+static void class_pktcdvd_release(struct class *cls)
+{
+ kfree(cls);
+}
+static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
+{
+ int n = 0;
+ int idx;
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+ for (idx = 0; idx < MAX_WRITERS; idx++) {
+ struct pktcdvd_device *pd = pkt_devs[idx];
+ if (!pd)
+ continue;
+ n += sprintf(data+n, "%s %u:%u %u:%u\n",
+ pd->name,
+ MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
+ MAJOR(pd->bdev->bd_dev),
+ MINOR(pd->bdev->bd_dev));
+ }
+ mutex_unlock(&ctl_mutex);
+ return n;
+}
+
+static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
+ size_t count)
+{
+ unsigned int major, minor;
+ DECLARE_BUF_AS_STRING(dbuf, buf, count);
+ if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+ pkt_setup_dev(MKDEV(major, minor), NULL);
+ return count;
+ }
+ return -EINVAL;
+}
+
+static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
+ size_t count)
+{
+ unsigned int major, minor;
+ DECLARE_BUF_AS_STRING(dbuf, buf, count);
+ if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+ pkt_remove_dev(MKDEV(major, minor));
+ return count;
+ }
+ return -EINVAL;
+}
+
+static struct class_attribute class_pktcdvd_attrs[] = {
+ __ATTR(add, 0200, NULL, class_pktcdvd_store_add),
+ __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove),
+ __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL),
+ __ATTR_NULL
+};
+
+
+static int pkt_sysfs_init(void)
+{
+ int ret = 0;
+
+ /*
+ * create control files in sysfs
+ * /sys/class/pktcdvd/...
+ */
+ class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL);
+ if (!class_pktcdvd)
+ return -ENOMEM;
+ class_pktcdvd->name = DRIVER_NAME;
+ class_pktcdvd->owner = THIS_MODULE;
+ class_pktcdvd->class_release = class_pktcdvd_release;
+ class_pktcdvd->class_attrs = class_pktcdvd_attrs;
+ ret = class_register(class_pktcdvd);
+ if (ret) {
+ kfree(class_pktcdvd);
+ class_pktcdvd = NULL;
+ printk(DRIVER_NAME": failed to create class pktcdvd\n");
+ return ret;
+ }
+ return 0;
+}
+
+static void pkt_sysfs_cleanup(void)
+{
+ if (class_pktcdvd)
+ class_destroy(class_pktcdvd);
+ class_pktcdvd = NULL;
+}
+
+/********************************************************************
+ entries in debugfs
+
+ /debugfs/pktcdvd[0-7]/
+ info
+
+ *******************************************************************/
+
+static int pkt_debugfs_seq_show(struct seq_file *m, void *p)
+{
+ return pkt_seq_show(m, p);
+}
+
+static int pkt_debugfs_fops_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pkt_debugfs_seq_show, inode->i_private);
+}
+
+static struct file_operations debug_fops = {
+ .open = pkt_debugfs_fops_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static void pkt_debugfs_dev_new(struct pktcdvd_device *pd)
+{
+ if (!pkt_debugfs_root)
+ return;
+ pd->dfs_f_info = NULL;
+ pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root);
+ if (IS_ERR(pd->dfs_d_root)) {
+ pd->dfs_d_root = NULL;
+ return;
+ }
+ pd->dfs_f_info = debugfs_create_file("info", S_IRUGO,
+ pd->dfs_d_root, pd, &debug_fops);
+ if (IS_ERR(pd->dfs_f_info)) {
+ pd->dfs_f_info = NULL;
+ return;
+ }
+}
+
+static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd)
+{
+ if (!pkt_debugfs_root)
+ return;
+ if (pd->dfs_f_info)
+ debugfs_remove(pd->dfs_f_info);
+ pd->dfs_f_info = NULL;
+ if (pd->dfs_d_root)
+ debugfs_remove(pd->dfs_d_root);
+ pd->dfs_d_root = NULL;
+}
+
+static void pkt_debugfs_init(void)
+{
+ pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL);
+ if (IS_ERR(pkt_debugfs_root)) {
+ pkt_debugfs_root = NULL;
+ return;
+ }
+}
+
+static void pkt_debugfs_cleanup(void)
+{
+ if (!pkt_debugfs_root)
+ return;
+ debugfs_remove(pkt_debugfs_root);
+ pkt_debugfs_root = NULL;
+}
+
+/* ----------------------------------------------------------*/
+
static void pkt_bio_finished(struct pktcdvd_device *pd)
{
@@ -347,47 +765,34 @@ static inline struct bio *pkt_get_list_first(struct bio **list_head, struct bio
*/
static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc)
{
- char sense[SCSI_SENSE_BUFFERSIZE];
- request_queue_t *q;
+ request_queue_t *q = bdev_get_queue(pd->bdev);
struct request *rq;
- DECLARE_COMPLETION_ONSTACK(wait);
- int err = 0;
+ int ret = 0;
- q = bdev_get_queue(pd->bdev);
+ rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ?
+ WRITE : READ, __GFP_WAIT);
+
+ if (cgc->buflen) {
+ if (blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen, __GFP_WAIT))
+ goto out;
+ }
+
+ rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+ memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
+ if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
+ memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
- rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ? WRITE : READ,
- __GFP_WAIT);
- rq->errors = 0;
- rq->rq_disk = pd->bdev->bd_disk;
- rq->bio = NULL;
- rq->buffer = NULL;
rq->timeout = 60*HZ;
- rq->data = cgc->buffer;
- rq->data_len = cgc->buflen;
- rq->sense = sense;
- memset(sense, 0, sizeof(sense));
- rq->sense_len = 0;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->cmd_flags |= REQ_HARDBARRIER;
if (cgc->quiet)
rq->cmd_flags |= REQ_QUIET;
- memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
- if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
- memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
- rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
-
- rq->ref_count++;
- rq->end_io_data = &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);
-
- if (rq->errors)
- err = -EIO;
+ blk_execute_rq(rq->q, pd->bdev->bd_disk, rq, 0);
+ ret = rq->errors;
+out:
blk_put_request(rq);
- return err;
+ return ret;
}
/*
@@ -893,6 +1298,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
sector_t zone = 0; /* Suppress gcc warning */
struct pkt_rb_node *node, *first_node;
struct rb_node *n;
+ int wakeup;
VPRINTK("handle_queue\n");
@@ -965,7 +1371,13 @@ try_next_bio:
pkt->write_size += bio->bi_size / CD_FRAMESIZE;
spin_unlock(&pkt->lock);
}
+ /* check write congestion marks, and if bio_queue_size is
+ below, wake up any waiters */
+ wakeup = (pd->write_congestion_on > 0
+ && pd->bio_queue_size <= pd->write_congestion_off);
spin_unlock(&pd->lock);
+ if (wakeup)
+ blk_clear_queue_congested(pd->disk->queue, WRITE);
pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -2178,6 +2590,23 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
}
spin_unlock(&pd->cdrw.active_list_lock);
+ /*
+ * Test if there is enough room left in the bio work queue
+ * (queue size >= congestion on mark).
+ * If not, wait till the work queue size is below the congestion off mark.
+ */
+ spin_lock(&pd->lock);
+ if (pd->write_congestion_on > 0
+ && pd->bio_queue_size >= pd->write_congestion_on) {
+ blk_set_queue_congested(q, WRITE);
+ do {
+ spin_unlock(&pd->lock);
+ congestion_wait(WRITE, HZ);
+ spin_lock(&pd->lock);
+ } while(pd->bio_queue_size > pd->write_congestion_off);
+ }
+ spin_unlock(&pd->lock);
+
/*
* No matching packet found. Store the bio in the work queue.
*/
@@ -2297,6 +2726,9 @@ static int pkt_seq_show(struct seq_file *m, void *p)
seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
states[0], states[1], states[2], states[3], states[4], states[5]);
+ seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n",
+ pd->write_congestion_off,
+ pd->write_congestion_on);
return 0;
}
@@ -2436,36 +2868,33 @@ static struct block_device_operations pktcdvd_ops = {
/*
* Set up mapping from pktcdvd device to CD-ROM device.
*/
-static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
+static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
{
int idx;
int ret = -ENOMEM;
struct pktcdvd_device *pd;
struct gendisk *disk;
- dev_t dev = new_decode_dev(ctrl_cmd->dev);
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
for (idx = 0; idx < MAX_WRITERS; idx++)
if (!pkt_devs[idx])
break;
if (idx == MAX_WRITERS) {
printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS);
- return -EBUSY;
+ ret = -EBUSY;
+ goto out_mutex;
}
pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
if (!pd)
- return ret;
+ goto out_mutex;
pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE,
sizeof(struct pkt_rb_node));
if (!pd->rb_pool)
goto out_mem;
- disk = alloc_disk(1);
- if (!disk)
- goto out_mem;
- pd->disk = disk;
-
INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
spin_lock_init(&pd->cdrw.active_list_lock);
@@ -2476,11 +2905,18 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
init_waitqueue_head(&pd->wqueue);
pd->bio_queue = RB_ROOT;
+ pd->write_congestion_on = write_congestion_on;
+ pd->write_congestion_off = write_congestion_off;
+
+ disk = alloc_disk(1);
+ if (!disk)
+ goto out_mem;
+ pd->disk = disk;
disk->major = pktdev_major;
disk->first_minor = idx;
disk->fops = &pktcdvd_ops;
disk->flags = GENHD_FL_REMOVABLE;
- sprintf(disk->disk_name, DRIVER_NAME"%d", idx);
+ strcpy(disk->disk_name, pd->name);
disk->private_data = pd;
disk->queue = blk_alloc_queue(GFP_KERNEL);
if (!disk->queue)
@@ -2492,8 +2928,15 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
goto out_new_dev;
add_disk(disk);
+
+ pkt_sysfs_dev_new(pd);
+ pkt_debugfs_dev_new(pd);
+
pkt_devs[idx] = pd;
- ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
+ if (pkt_dev)
+ *pkt_dev = pd->pkt_dev;
+
+ mutex_unlock(&ctl_mutex);
return 0;
out_new_dev:
@@ -2504,17 +2947,22 @@ out_mem:
if (pd->rb_pool)
mempool_destroy(pd->rb_pool);
kfree(pd);
+out_mutex:
+ mutex_unlock(&ctl_mutex);
+ printk(DRIVER_NAME": setup of pktcdvd device failed\n");
return ret;
}
/*
* Tear down mapping from pktcdvd device to CD-ROM device.
*/
-static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
+static int pkt_remove_dev(dev_t pkt_dev)
{
struct pktcdvd_device *pd;
int idx;
- dev_t pkt_dev = new_decode_dev(ctrl_cmd->pkt_dev);
+ int ret = 0;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
for (idx = 0; idx < MAX_WRITERS; idx++) {
pd = pkt_devs[idx];
@@ -2523,15 +2971,22 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
}
if (idx == MAX_WRITERS) {
DPRINTK(DRIVER_NAME": dev not setup\n");
- return -ENXIO;
+ ret = -ENXIO;
+ goto out;
}
- if (pd->refcnt > 0)
- return -EBUSY;
-
+ if (pd->refcnt > 0) {
+ ret = -EBUSY;
+ goto out;
+ }
if (!IS_ERR(pd->cdrw.thread))
kthread_stop(pd->cdrw.thread);
+ pkt_devs[idx] = NULL;
+
+ pkt_debugfs_dev_remove(pd);
+ pkt_sysfs_dev_remove(pd);
+
blkdev_put(pd->bdev);
remove_proc_entry(pd->name, pkt_proc);
@@ -2541,18 +2996,24 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
blk_cleanup_queue(pd->disk->queue);
put_disk(pd->disk);
- pkt_devs[idx] = NULL;
mempool_destroy(pd->rb_pool);
kfree(pd);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
- return 0;
+
+out:
+ mutex_unlock(&ctl_mutex);
+ return ret;
}
static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
{
- struct pktcdvd_device *pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
+ struct pktcdvd_device *pd;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
if (pd) {
ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev);
ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
@@ -2561,6 +3022,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
ctrl_cmd->pkt_dev = 0;
}
ctrl_cmd->num_devices = MAX_WRITERS;
+
+ mutex_unlock(&ctl_mutex);
}
static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2568,6 +3031,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
void __user *argp = (void __user *)arg;
struct pkt_ctrl_command ctrl_cmd;
int ret = 0;
+ dev_t pkt_dev = 0;
if (cmd != PACKET_CTRL_CMD)
return -ENOTTY;
@@ -2579,21 +3043,16 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
case PKT_CTRL_CMD_SETUP:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
- ret = pkt_setup_dev(&ctrl_cmd);
- mutex_unlock(&ctl_mutex);
+ ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev);
+ ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev);
break;
case PKT_CTRL_CMD_TEARDOWN:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
- ret = pkt_remove_dev(&ctrl_cmd);
- mutex_unlock(&ctl_mutex);
+ ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev));
break;
case PKT_CTRL_CMD_STATUS:
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
pkt_get_status(&ctrl_cmd);
- mutex_unlock(&ctl_mutex);
break;
default:
return -ENOTTY;
@@ -2620,6 +3079,8 @@ static int __init pkt_init(void)
{
int ret;
+ mutex_init(&ctl_mutex);
+
psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE,
sizeof(struct packet_stacked_data));
if (!psd_pool)
@@ -2633,18 +3094,25 @@ static int __init pkt_init(void)
if (!pktdev_major)
pktdev_major = ret;
+ ret = pkt_sysfs_init();
+ if (ret)
+ goto out;
+
+ pkt_debugfs_init();
+
ret = misc_register(&pkt_misc);
if (ret) {
printk(DRIVER_NAME": Unable to register misc device\n");
- goto out;
+ goto out_misc;
}
- mutex_init(&ctl_mutex);
-
pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver);
return 0;
+out_misc:
+ pkt_debugfs_cleanup();
+ pkt_sysfs_cleanup();
out:
unregister_blkdev(pktdev_major, DRIVER_NAME);
out2:
@@ -2656,6 +3124,10 @@ static void __exit pkt_exit(void)
{
remove_proc_entry(DRIVER_NAME, proc_root_driver);
misc_deregister(&pkt_misc);
+
+ pkt_debugfs_cleanup();
+ pkt_sysfs_cleanup();
+
unregister_blkdev(pktdev_major, DRIVER_NAME);
mempool_destroy(psd_pool);
}
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
deleted file mode 100644
index ed7b06cf3e6..00000000000
--- a/drivers/block/swim_iop.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Driver for the SWIM (Super Woz Integrated Machine) IOP
- * floppy controller on the Macintosh IIfx and Quadra 900/950
- *
- * Written by Joshua M. Thompson (funaho@jurai.org)
- * based on the SWIM3 driver (c) 1996 by Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * 1999-06-12 (jmt) - Initial implementation.
- */
-
-/*
- * -------------------
- * Theory of Operation
- * -------------------
- *
- * Since the SWIM IOP is message-driven we implement a simple request queue
- * system. One outstanding request may be queued at any given time (this is
- * an IOP limitation); only when that request has completed can a new request
- * be sent.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/fd.h>
-#include <linux/ioctl.h>
-#include <linux/blkdev.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mac_iop.h>
-#include <asm/swim_iop.h>
-
-#define DRIVER_VERSION "Version 0.1 (1999-06-12)"
-
-#define MAX_FLOPPIES 4
-
-enum swim_state {
- idle,
- available,
- revalidating,
- transferring,
- ejecting
-};
-
-struct floppy_state {
- enum swim_state state;
- int drive_num; /* device number */
- int secpercyl; /* disk geometry information */
- int secpertrack;
- int total_secs;
- int write_prot; /* 1 if write-protected, 0 if not, -1 dunno */
- int ref_count;
- struct timer_list timeout;
- int ejected;
- struct wait_queue *wait;
- int wanted;
- int timeout_pending;
-};
-
-struct swim_iop_req {
- int sent;
- int complete;
- __u8 command[32];
- struct floppy_state *fs;
- void (*done)(struct swim_iop_req *);
-};
-
-static struct swim_iop_req *current_req;
-static int floppy_count;
-
-static struct floppy_state floppy_states[MAX_FLOPPIES];
-static DEFINE_SPINLOCK(swim_iop_lock);
-
-#define CURRENT elv_next_request(swim_queue)
-
-static char *drive_names[7] = {
- "not installed", /* DRV_NONE */
- "unknown (1)", /* DRV_UNKNOWN */
- "a 400K drive", /* DRV_400K */
- "an 800K drive" /* DRV_800K */
- "unknown (4)", /* ???? */
- "an FDHD", /* DRV_FDHD */
- "unknown (6)", /* ???? */
- "an Apple HD20" /* DRV_HD20 */
-};
-
-int swimiop_init(void);
-static void swimiop_init_request(struct swim_iop_req *);
-static int swimiop_send_request(struct swim_iop_req *);
-static void swimiop_receive(struct iop_msg *);
-static void swimiop_status_update(int, struct swim_drvstatus *);
-static int swimiop_eject(struct floppy_state *fs);
-
-static int floppy_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long param);
-static int floppy_open(struct inode *inode, struct file *filp);
-static int floppy_release(struct inode *inode, struct file *filp);
-static int floppy_check_change(struct gendisk *disk);
-static int floppy_revalidate(struct gendisk *disk);
-static int grab_drive(struct floppy_state *fs, enum swim_state state,
- int interruptible);
-static void release_drive(struct floppy_state *fs);
-static void set_timeout(struct floppy_state *fs, int nticks,
- void (*proc)(unsigned long));
-static void fd_request_timeout(unsigned long);
-static void do_fd_request(request_queue_t * q);
-static void start_request(struct floppy_state *fs);
-
-static struct block_device_operations floppy_fops = {
- .open = floppy_open,
- .release = floppy_release,
- .ioctl = floppy_ioctl,
- .media_changed = floppy_check_change,
- .revalidate_disk= floppy_revalidate,
-};
-
-static struct request_queue *swim_queue;
-/*
- * SWIM IOP initialization
- */
-
-int swimiop_init(void)
-{
- volatile struct swim_iop_req req;
- struct swimcmd_status *cmd = (struct swimcmd_status *) &req.command[0];
- struct swim_drvstatus *ds = &cmd->status;
- struct floppy_state *fs;
- int i;
-
- current_req = NULL;
- floppy_count = 0;
-
- if (!iop_ism_present)
- return -ENODEV;
-
- if (register_blkdev(FLOPPY_MAJOR, "fd"))
- return -EBUSY;
-
- swim_queue = blk_init_queue(do_fd_request, &swim_iop_lock);
- if (!swim_queue) {
- unregister_blkdev(FLOPPY_MAJOR, "fd");
- return -ENOMEM;
- }
-
- printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
- DRIVER_VERSION);
-
- if (iop_listen(SWIM_IOP, SWIM_CHAN, swimiop_receive, "SWIM") != 0) {
- printk(KERN_ERR "SWIM-IOP: IOP channel already in use; can't initialize.\n");
- unregister_blkdev(FLOPPY_MAJOR, "fd");
- blk_cleanup_queue(swim_queue);
- return -EBUSY;
- }
-
- printk(KERN_ERR "SWIM_IOP: probing for installed drives.\n");
-
- for (i = 0 ; i < MAX_FLOPPIES ; i++) {
- memset(&floppy_states[i], 0, sizeof(struct floppy_state));
- fs = &floppy_states[floppy_count];
-
- swimiop_init_request(&req);
- cmd->code = CMD_STATUS;
- cmd->drive_num = i + 1;
- if (swimiop_send_request(&req) != 0) continue;
- while (!req.complete);
- if (cmd->error != 0) {
- printk(KERN_ERR "SWIM-IOP: probe on drive %d returned error %d\n", i, (uint) cmd->error);
- continue;
- }
- if (ds->installed != 0x01) continue;
- printk("SWIM-IOP: drive %d is %s (%s, %s, %s, %s)\n", i,
- drive_names[ds->info.type],
- ds->info.external? "ext" : "int",
- ds->info.scsi? "scsi" : "floppy",
- ds->info.fixed? "fixed" : "removable",
- ds->info.secondary? "secondary" : "primary");
- swimiop_status_update(floppy_count, ds);
- fs->state = idle;
-
- init_timer(&fs->timeout);
- floppy_count++;
- }
- printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
-
- for (i = 0; i < floppy_count; i++) {
- struct gendisk *disk = alloc_disk(1);
- if (!disk)
- continue;
- disk->major = FLOPPY_MAJOR;
- disk->first_minor = i;
- disk->fops = &floppy_fops;
- sprintf(disk->disk_name, "fd%d", i);
- disk->private_data = &floppy_states[i];
- disk->queue = swim_queue;
- set_capacity(disk, 2880 * 2);
- add_disk(disk);
- }
-
- return 0;
-}
-
-static void swimiop_init_request(struct swim_iop_req *req)
-{
- req->sent = 0;
- req->complete = 0;
- req->done = NULL;
-}
-
-static int swimiop_send_request(struct swim_iop_req *req)
-{
- unsigned long flags;
- int err;
-
- /* It's doubtful an interrupt routine would try to send */
- /* a SWIM request, but I'd rather play it safe here. */
-
- local_irq_save(flags);
-
- if (current_req != NULL) {
- local_irq_restore(flags);
- return -ENOMEM;
- }
-
- current_req = req;
-
- /* Interrupts should be back on for iop_send_message() */
-
- local_irq_restore(flags);
-
- err = iop_send_message(SWIM_IOP, SWIM_CHAN, (void *) req,
- sizeof(req->command), (__u8 *) &req->command[0],
- swimiop_receive);
-
- /* No race condition here; we own current_req at this point */
-
- if (err) {
- current_req = NULL;
- } else {
- req->sent = 1;
- }
- return err;
-}
-
-/*
- * Receive a SWIM message from the IOP.
- *
- * This will be called in two cases:
- *
- * 1. A message has been successfully sent to the IOP.
- * 2. An unsolicited message was received from the IOP.
- */
-
-void swimiop_receive(struct iop_msg *msg)
-{
- struct swim_iop_req *req;
- struct swimmsg_status *sm;
- struct swim_drvstatus *ds;
-
- req = current_req;
-
- switch(msg->status) {
- case IOP_MSGSTATUS_COMPLETE:
- memcpy(&req->command[0], &msg->reply[0], sizeof(req->command));
- req->complete = 1;
- if (req->done) (*req->done)(req);
- current_req = NULL;
- break;
- case IOP_MSGSTATUS_UNSOL:
- sm = (struct swimmsg_status *) &msg->message[0];
- ds = &sm->status;
- swimiop_status_update(sm->drive_num, ds);
- iop_complete_message(msg);
- break;
- }
-}
-
-static void swimiop_status_update(int drive_num, struct swim_drvstatus *ds)
-{
- struct floppy_state *fs = &floppy_states[drive_num];
-
- fs->write_prot = (ds->write_prot == 0x80);
- if ((ds->disk_in_drive != 0x01) && (ds->disk_in_drive != 0x02)) {
- fs->ejected = 1;
- } else {
- fs->ejected = 0;
- }
- switch(ds->info.type) {
- case DRV_400K:
- fs->secpercyl = 10;
- fs->secpertrack = 10;
- fs->total_secs = 800;
- break;
- case DRV_800K:
- fs->secpercyl = 20;
- fs->secpertrack = 10;
- fs->total_secs = 1600;
- break;
- case DRV_FDHD:
- fs->secpercyl = 36;
- fs->secpertrack = 18;
- fs->total_secs = 2880;
- break;
- default:
- fs->secpercyl = 0;
- fs->secpertrack = 0;
- fs->total_secs = 0;
- break;
- }
-}
-
-static int swimiop_eject(struct floppy_state *fs)
-{
- int err, n;
- struct swim_iop_req req;
- struct swimcmd_eject *cmd = (struct swimcmd_eject *) &req.command[0];
-
- err = grab_drive(fs, ejecting, 1);
- if (err) return err;
-
- swimiop_init_request(&req);
- cmd->code = CMD_EJECT;
- cmd->drive_num = fs->drive_num;
- err = swimiop_send_request(&req);
- if (err) {
- release_drive(fs);
- return err;
- }
- for (n = 2*HZ; n > 0; --n) {
- if (req.complete) break;
- if (signal_pending(current)) {
- err = -EINTR;
- break;
- }
- schedule_timeout_interruptible(1);
- }
- release_drive(fs);
- return cmd->error;
-}
-
-static struct floppy_struct floppy_type =
- { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
-
-static int floppy_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long param)
-{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
- int err;
-
- if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- switch (cmd) {
- case FDEJECT:
- if (fs->ref_count != 1)
- return -EBUSY;
- err = swimiop_eject(fs);
- return err;
- case FDGETPRM:
- if (copy_to_user((void *) param, (void *) &floppy_type,
- sizeof(struct floppy_struct)))
- return -EFAULT;
- return 0;
- }
- return -ENOTTY;
-}
-
-static int floppy_open(struct inode *inode, struct file *filp)
-{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
-
- if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
- return -EBUSY;
-
- if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) {
- check_disk_change(inode->i_bdev);
- if (fs->ejected)
- return -ENXIO;
- }
-
- if ((filp->f_mode & 2) && fs->write_prot)
- return -EROFS;
-
- if (filp->f_flags & O_EXCL)
- fs->ref_count = -1;
- else
- ++fs->ref_count;
-
- return 0;
-}
-
-static int floppy_release(struct inode *inode, struct file *filp)
-{
- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
- if (fs->ref_count > 0)
- fs->ref_count--;
- return 0;
-}
-
-static int floppy_check_change(struct gendisk *disk)
-{
- struct floppy_state *fs = disk->private_data;
- return fs->ejected;
-}
-
-static int floppy_revalidate(struct gendisk *disk)
-{
- struct floppy_state *fs = disk->private_data;
- grab_drive(fs, revalidating, 0);
- /* yadda, yadda */
- release_drive(fs);
- return 0;
-}
-
-static void floppy_off(unsigned int nr)
-{
-}
-
-static int grab_drive(struct floppy_state *fs, enum swim_state state,
- int interruptible)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- if (fs->state != idle) {
- ++fs->wanted;
- while (fs->state != available) {
- if (interruptible && signal_pending(current)) {
- --fs->wanted;
- local_irq_restore(flags);
- return -EINTR;
- }
- interruptible_sleep_on(&fs->wait);
- }
- --fs->wanted;
- }
- fs->state = state;
- local_irq_restore(flags);
- return 0;
-}
-
-static void release_drive(struct floppy_state *fs)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- fs->state = idle;
- start_request(fs);
- local_irq_restore(flags);
-}
-
-static void set_timeout(struct floppy_state *fs, int nticks,
- void (*proc)(unsigned long))
-{
- unsigned long flags;
-
- local_irq_save(flags);
- if (fs->timeout_pending)
- del_timer(&fs->timeout);
- init_timer(&fs->timeout);
- fs->timeout.expires = jiffies + nticks;
- fs->timeout.function = proc;
- fs->timeout.data = (unsigned long) fs;
- add_timer(&fs->timeout);
- fs->timeout_pending = 1;
- local_irq_restore(flags);
-}
-
-static void do_fd_request(request_queue_t * q)
-{
- int i;
-
- for (i = 0 ; i < floppy_count ; i++) {
- start_request(&floppy_states[i]);
- }
-}
-
-static void fd_request_complete(struct swim_iop_req *req)
-{
- struct floppy_state *fs = req->fs;
- struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req->command[0];
-
- del_timer(&fs->timeout);
- fs->timeout_pending = 0;
- fs->state = idle;
- if (cmd->error) {
- printk(KERN_ERR "SWIM-IOP: error %d on read/write request.\n", cmd->error);
- end_request(CURRENT, 0);
- } else {
- CURRENT->sector += cmd->num_blocks;
- CURRENT->current_nr_sectors -= cmd->num_blocks;
- if (CURRENT->current_nr_sectors <= 0) {
- end_request(CURRENT, 1);
- return;
- }
- }
- start_request(fs);
-}
-
-static void fd_request_timeout(unsigned long data)
-{
- struct floppy_state *fs = (struct floppy_state *) data;
-
- fs->timeout_pending = 0;
- end_request(CURRENT, 0);
- fs->state = idle;
-}
-
-static void start_request(struct floppy_state *fs)
-{
- volatile struct swim_iop_req req;
- struct swimcmd_rw *cmd = (struct swimcmd_rw *) &req.command[0];
-
- if (fs->state == idle && fs->wanted) {
- fs->state = available;
- wake_up(&fs->wait);
- return;
- }
- while (CURRENT && fs->state == idle) {
- if (CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic("floppy: block not locked");
-#if 0
- printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
- CURRENT->rq_disk->disk_name, CURRENT->cmd,
- CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
- printk(" errors=%d current_nr_sectors=%ld\n",
- CURRENT->errors, CURRENT->current_nr_sectors);
-#endif
-
- if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
- end_request(CURRENT, 0);
- continue;
- }
- if (CURRENT->current_nr_sectors == 0) {
- end_request(CURRENT, 1);
- continue;
- }
- if (fs->ejected) {
- end_request(CURRENT, 0);
- continue;
- }
-
- swimiop_init_request(&req);
- req.fs = fs;
- req.done = fd_request_complete;
-
- if (CURRENT->cmd == WRITE) {
- if (fs->write_prot) {
- end_request(CURRENT, 0);
- continue;
- }
- cmd->code = CMD_WRITE;
- } else {
- cmd->code = CMD_READ;
-
- }
- cmd->drive_num = fs->drive_num;
- cmd->buffer = CURRENT->buffer;
- cmd->first_block = CURRENT->sector;
- cmd->num_blocks = CURRENT->current_nr_sectors;
-
- if (swimiop_send_request(&req)) {
- end_request(CURRENT, 0);
- continue;
- }
-
- set_timeout(fs, HZ*CURRENT->current_nr_sectors,
- fd_request_timeout);
-
- fs->state = transferring;
- }
-}
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index e19ba4ebcd4..68592c33601 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -49,6 +49,7 @@
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_lp_config.h>
#include <asm/iseries/vio.h>
+#include <asm/firmware.h>
MODULE_DESCRIPTION("iSeries Virtual DASD");
MODULE_AUTHOR("Dave Boutcher");
@@ -769,6 +770,11 @@ static int __init viodasd_init(void)
{
int rc;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
+ rc = -ENODEV;
+ goto early_fail;
+ }
+
/* Try to open to our host lp */
if (viopath_hostLp == HvLpIndexInvalid)
vio_set_hostlp();
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index fdea58ae16b..6bdf593081d 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -117,15 +117,23 @@ static struct usb_device_id blacklist_ids[] = {
/* IBM/Lenovo ThinkPad with Broadcom chip */
{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_WRONG_SCO_MTU },
/* ANYCOM Bluetooth USB-200 and USB-250 */
{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
+ /* HP laptop with Broadcom chip */
+ { USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_WRONG_SCO_MTU },
+
+ /* Dell laptop with Broadcom chip */
+ { USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_WRONG_SCO_MTU },
+
/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
/* Kensington Bluetooth USB adapter */
{ USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
+ { USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_WRONG_SCO_MTU },
/* ISSC Bluetooth Adapter v3.1 */
{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 2df5cf4ec74..3105dddf59f 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -337,6 +337,12 @@ static const char *mrw_address_space[] = { "DMA", "GAA" };
/* used in the audio ioctls */
#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
+/*
+ * Another popular OS uses 7 seconds as the hard timeout for default
+ * commands, so it is a good choice for us as well.
+ */
+#define CDROM_DEF_TIMEOUT (7 * HZ)
+
/* Not-exported routines. */
static int open_for_data(struct cdrom_device_info * cdi);
static int check_for_audio_disc(struct cdrom_device_info * cdi,
@@ -1528,7 +1534,7 @@ void init_cdrom_command(struct packet_command *cgc, void *buf, int len,
cgc->buffer = (char *) buf;
cgc->buflen = len;
cgc->data_direction = type;
- cgc->timeout = 5*HZ;
+ cgc->timeout = CDROM_DEF_TIMEOUT;
}
/* DVD handling */
@@ -1810,7 +1816,7 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
size = sizeof(s->disckey.value) + 4;
- if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+ if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
@@ -1861,7 +1867,7 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
size = sizeof(s->manufact.value) + 4;
- if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+ if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
@@ -2139,8 +2145,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
cdi->last_sense = s->sense_key;
}
- rq->bio = bio;
- if (blk_rq_unmap_user(rq))
+ if (blk_rq_unmap_user(bio))
ret = -EFAULT;
if (ret)
@@ -2849,7 +2854,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
/* FIXME: we need upper bound checking, too!! */
if (lba < 0)
return -EINVAL;
- cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
+ cgc.buffer = kmalloc(blocksize, GFP_KERNEL);
if (cgc.buffer == NULL)
return -ENOMEM;
memset(&sense, 0, sizeof(sense));
@@ -3031,7 +3036,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
int size = sizeof(dvd_struct);
if (!CDROM_CAN(CDC_DVD))
return -ENOSYS;
- if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL)
+ if ((s = kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n");
if (copy_from_user(s, (dvd_struct __user *)arg, size)) {
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index e6d8e9edede..b6c61bbb20e 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -1420,7 +1420,7 @@ int __init cm206_init(void)
return -EIO;
}
printk(" adapter at 0x%x", cm206_base);
- cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
+ cd = kmalloc(size, GFP_KERNEL);
if (!cd)
goto out_base;
/* Now we have found the adaptor card, try to reset it. As we have
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 54ca931e19e..93fbf84dcc4 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -47,6 +47,7 @@
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/vio.h>
+#include <asm/firmware.h>
#define VIOCD_DEVICE "iseries/vcd"
@@ -748,6 +749,9 @@ static int __init viocd_init(void)
struct proc_dir_entry *e;
int ret = 0;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
if (viopath_hostLp == HvLpIndexInvalid) {
vio_set_hostlp();
/* If we don't have a host, bail out */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 24f922f1278..9e43e39dc35 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -97,7 +97,7 @@ config SERIAL_NONSTANDARD
config COMPUTONE
tristate "Computone IntelliPort Plus serial support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
---help---
This driver supports the entire family of Intelliport II/Plus
controllers with the exception of the MicroChannel controllers and
@@ -201,9 +201,24 @@ config MOXA_SMARTIO
The module will be called mxser. If you want to do that, say M
here.
+config MOXA_SMARTIO_NEW
+ tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)"
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
+ help
+ Say Y here if you have a Moxa SmartIO multiport serial card and/or
+ want to help develop a new version of this driver.
+
+ This is upgraded (1.9.1) driver from original Moxa drivers with
+ changes finally resulting in PCI probing.
+
+ Use at your own risk.
+
+ This driver can also be built as a module. The module will be called
+ mxser_new. If you want to do that, say M here.
+
config ISI
tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && PCI
select FW_LOADER
help
This is a driver for the Multi-Tech cards which provide several
@@ -297,7 +312,7 @@ config SPECIALIX_RTSCTS
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/sx.txt> for details.
@@ -852,7 +867,7 @@ config SONYPI
config TANBAC_TB0219
tristate "TANBAC TB0219 base board support"
- depends TANBAC_TB022X
+ depends on TANBAC_TB022X
select GPIO_VR41XX
source "drivers/char/agp/Kconfig"
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index b1fcdab9094..fc110637ced 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o
obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
+obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o
obj-$(CONFIG_COMPUTONE) += ip2/
obj-$(CONFIG_RISCOM8) += riscom8.o
obj-$(CONFIG_ISI) += isicom.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index c603bf29158..a9f9c48c242 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -86,7 +86,7 @@ config AGP_NVIDIA
config AGP_SIS
tristate "SiS chipset support"
- depends on AGP
+ depends on AGP && X86
help
This option gives you AGP support for the GLX component of
X on Silicon Integrated Systems [SiS] chipsets.
@@ -103,7 +103,7 @@ config AGP_SWORKS
config AGP_VIA
tristate "VIA chipset support"
- depends on AGP
+ depends on AGP && X86
help
This option gives you AGP support for the GLX component of
X on VIA MVP3/Apollo Pro chipsets.
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 8b3317fd46c..1d59e2a5b9a 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -225,6 +225,10 @@ struct agp_bridge_data {
#define I810_GMS_DISABLE 0x00000000
#define I810_PGETBL_CTL 0x2020
#define I810_PGETBL_ENABLED 0x00000001
+#define I965_PGETBL_SIZE_MASK 0x0000000e
+#define I965_PGETBL_SIZE_512KB (0 << 1)
+#define I965_PGETBL_SIZE_256KB (1 << 1)
+#define I965_PGETBL_SIZE_128KB (2 << 1)
#define I810_DRAM_CTL 0x3000
#define I810_DRAM_ROW_0 0x00000001
#define I810_DRAM_ROW_0_SDRAM 0x00000001
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 51d0d562d01..c85c8cadb6d 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -101,6 +101,11 @@ static int amd_create_gatt_pages(int nr_tables)
for (i = 0; i < nr_tables; i++) {
entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL);
if (entry == NULL) {
+ while (i > 0) {
+ kfree(tables[i-1]);
+ i--;
+ }
+ kfree(tables);
retval = -ENOMEM;
break;
}
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 2f2c4efff8a..93d2209fee4 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -650,6 +650,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
+ /* VIA K8M890 / K8N890 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_VT3336,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
/* VIA K8T890 */
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index f244c668273..9987dc2e0c3 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -41,18 +41,18 @@ static struct gatt_mask ati_generic_masks[] =
};
-typedef struct _ati_page_map {
+struct ati_page_map {
unsigned long *real;
unsigned long __iomem *remapped;
-} ati_page_map;
+};
static struct _ati_generic_private {
volatile u8 __iomem *registers;
- ati_page_map **gatt_pages;
+ struct ati_page_map **gatt_pages;
int num_tables;
} ati_generic_private;
-static int ati_create_page_map(ati_page_map *page_map)
+static int ati_create_page_map(struct ati_page_map *page_map)
{
int i, err = 0;
@@ -82,7 +82,7 @@ static int ati_create_page_map(ati_page_map *page_map)
}
-static void ati_free_page_map(ati_page_map *page_map)
+static void ati_free_page_map(struct ati_page_map *page_map)
{
unmap_page_from_agp(virt_to_page(page_map->real));
iounmap(page_map->remapped);
@@ -94,8 +94,8 @@ static void ati_free_page_map(ati_page_map *page_map)
static void ati_free_gatt_pages(void)
{
int i;
- ati_page_map **tables;
- ati_page_map *entry;
+ struct ati_page_map **tables;
+ struct ati_page_map *entry;
tables = ati_generic_private.gatt_pages;
for (i = 0; i < ati_generic_private.num_tables; i++) {
@@ -112,30 +112,30 @@ static void ati_free_gatt_pages(void)
static int ati_create_gatt_pages(int nr_tables)
{
- ati_page_map **tables;
- ati_page_map *entry;
+ struct ati_page_map **tables;
+ struct ati_page_map *entry;
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL);
+ tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
for (i = 0; i < nr_tables; i++) {
- entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL);
+ entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
if (entry == NULL) {
- while (i>0) {
- kfree (tables[i-1]);
+ while (i > 0) {
+ kfree(tables[i-1]);
i--;
}
- kfree (tables);
- tables = NULL;
+ kfree(tables);
retval = -ENOMEM;
break;
}
tables[i] = entry;
retval = ati_create_page_map(entry);
- if (retval != 0) break;
+ if (retval != 0)
+ break;
}
ati_generic_private.num_tables = nr_tables;
ati_generic_private.gatt_pages = tables;
@@ -340,7 +340,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
static int ati_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
- ati_page_map page_dir;
+ struct ati_page_map page_dir;
unsigned long addr;
int retval;
u32 temp;
@@ -400,7 +400,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
static int ati_free_gatt_table(struct agp_bridge_data *bridge)
{
- ati_page_map page_dir;
+ struct ati_page_map page_dir;
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 5ff457b41ef..3491d6f84bc 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -419,6 +419,31 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
*requested_mode &= ~AGP2_RESERVED_MASK;
}
+ /*
+ * Some dumb bridges are programmed to disobey the AGP2 spec.
+ * This is likely a BIOS misprogramming rather than poweron default, or
+ * it would be a lot more common.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=8816
+ * AGPv2 spec 6.1.9 states:
+ * The RATE field indicates the data transfer rates supported by this
+ * device. A.G.P. devices must report all that apply.
+ * Fix them up as best we can.
+ */
+ switch (*bridge_agpstat & 7) {
+ case 4:
+ *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X);
+ printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate"
+ "Fixing up support for x2 & x1\n");
+ break;
+ case 2:
+ *bridge_agpstat |= AGPSTAT2_1X;
+ printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate"
+ "Fixing up support for x1\n");
+ break;
+ default:
+ break;
+ }
+
/* Check the speed bits make sense. Only one should be set. */
tmp = *requested_mode & 7;
switch (tmp) {
@@ -940,6 +965,9 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
if (!bridge)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
temp = bridge->current_size;
switch (bridge->driver->size_type) {
@@ -991,8 +1019,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
- readl(bridge->gatt_table+j); /* PCI Posting. */
}
+ readl(bridge->gatt_table+j-1); /* PCI Posting. */
bridge->driver->tlb_flush(mem);
return 0;
@@ -1009,6 +1037,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
if (!bridge)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
if (type != 0 || mem->type != 0) {
/* The generic routines know nothing of memory types */
return -EINVAL;
@@ -1017,10 +1048,9 @@ 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(bridge->scratch_page, bridge->gatt_table+i);
- readl(bridge->gatt_table+i); /* PCI Posting. */
}
+ readl(bridge->gatt_table+i-1); /* PCI Posting. */
- global_cache_flush();
bridge->driver->tlb_flush(mem);
return 0;
}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 555b3a8ab49..a3011de51f7 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -207,6 +207,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
int i, j, num_entries;
void *temp;
+ if (mem->page_count == 0)
+ return 0;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -221,12 +224,16 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
if (type != 0 || mem->type != 0) {
if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
/* special insert */
- global_cache_flush();
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
+
for (i = pg_start; i < (pg_start + mem->page_count); i++) {
writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
- global_cache_flush();
+ readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
+
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -236,14 +243,17 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
}
insert:
- global_cache_flush();
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
+
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
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();
+ readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -254,12 +264,14 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
{
int i;
+ if (mem->page_count == 0)
+ return 0;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
+ readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -370,6 +382,11 @@ static struct _intel_i830_private {
struct pci_dev *i830_dev; /* device one */
volatile u8 __iomem *registers;
volatile u32 __iomem *gtt; /* I915G */
+ /* gtt_entries is the number of gtt entries that are already mapped
+ * to stolen memory. Stolen memory is larger than the memory mapped
+ * through gtt_entries, as it includes some reserved space for the BIOS
+ * popup and for the GTT.
+ */
int gtt_entries;
} intel_i830_private;
@@ -380,14 +397,41 @@ static void intel_i830_init_gtt_entries(void)
u8 rdct;
int local = 0;
static const int ddt[4] = { 0, 16, 32, 64 };
- int size;
+ int size; /* reserved space (in kb) at the top of stolen memory */
pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
- /* We obtain the size of the GTT, which is also stored (for some
- * reason) at the top of stolen memory. Then we add 4KB to that
- * for the video BIOS popup, which is also stored in there. */
- size = agp_bridge->driver->fetch_size() + 4;
+ if (IS_I965) {
+ u32 pgetbl_ctl;
+
+ pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL,
+ &pgetbl_ctl);
+ /* The 965 has a field telling us the size of the GTT,
+ * which may be larger than what is necessary to map the
+ * aperture.
+ */
+ switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+ case I965_PGETBL_SIZE_128KB:
+ size = 128;
+ break;
+ case I965_PGETBL_SIZE_256KB:
+ size = 256;
+ break;
+ case I965_PGETBL_SIZE_512KB:
+ size = 512;
+ break;
+ default:
+ printk(KERN_INFO PFX "Unknown page table size, "
+ "assuming 512KB\n");
+ size = 512;
+ }
+ size += 4; /* add in BIOS popup space */
+ } else {
+ /* On previous hardware, the GTT size was just what was
+ * required to map the aperture.
+ */
+ size = agp_bridge->driver->fetch_size() + 4;
+ }
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -576,6 +620,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
int i,j,num_entries;
void *temp;
+ if (mem->page_count == 0)
+ return 0;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -598,16 +645,18 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
return -EINVAL;
- global_cache_flush(); /* FIXME: Necessary ?*/
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
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. */
}
+ readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -617,7 +666,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
{
int i;
- global_cache_flush();
+ if (mem->page_count == 0)
+ return 0;
if (pg_start < intel_i830_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
@@ -626,10 +676,9 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
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. */
}
+ readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -686,6 +735,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
int i,j,num_entries;
void *temp;
+ if (mem->page_count == 0)
+ return 0;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
@@ -708,15 +760,17 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
return -EINVAL;
- global_cache_flush();
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
for (i = 0, j = pg_start; i < mem->page_count; i++, 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. */
}
+ readl(intel_i830_private.gtt+j-1);
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -726,7 +780,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
{
int i;
- global_cache_flush();
+ if (mem->page_count == 0)
+ return 0;
if (pg_start < intel_i830_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
@@ -735,30 +790,34 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
- readl(intel_i830_private.gtt+i);
}
+ readl(intel_i830_private.gtt+i-1);
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
-static int intel_i915_fetch_size(void)
+/* Return the aperture size by just checking the resource length. The effect
+ * described in the spec of the MSAC registers is just changing of the
+ * resource size.
+ */
+static int intel_i9xx_fetch_size(void)
{
- struct aper_size_info_fixed *values;
- u32 temp, offset;
+ int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
+ int aper_size; /* size in megabytes */
+ int i;
-#define I915_256MB_ADDRESS_MASK (1<<27)
+ aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
+ for (i = 0; i < num_sizes; i++) {
+ if (aper_size == intel_i830_sizes[i].size) {
+ agp_bridge->current_size = intel_i830_sizes + i;
+ agp_bridge->previous_size = agp_bridge->current_size;
+ return aper_size;
+ }
+ }
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
- if (temp & I915_256MB_ADDRESS_MASK)
- offset = 0; /* 128MB aperture */
- else
- offset = 2; /* 256MB aperture */
- agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
- return values[offset].size;
+ return 0;
}
/* The intel i915 automatically initializes the agp aperture during POST.
@@ -821,40 +880,9 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
return addr | bridge->driver->masks[type].mask;
}
-static int intel_i965_fetch_size(void)
-{
- struct aper_size_info_fixed *values;
- u32 offset = 0;
- u8 temp;
-
-#define I965_512MB_ADDRESS_MASK (3<<1)
-
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
- temp &= I965_512MB_ADDRESS_MASK;
- switch (temp) {
- case 0x00:
- offset = 0; /* 128MB */
- break;
- case 0x06:
- offset = 3; /* 512MB */
- break;
- default:
- case 0x02:
- offset = 2; /* 256MB */
- break;
- }
-
- agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
-
- /* The i965 GTT is always sized as if it had a 512kB aperture size */
- return 512;
-}
-
/* The intel i965 automatically initializes the agp aperture during POST.
-+ * Use the memory already set aside for in the GTT.
-+ */
+ * Use the memory already set aside for in the GTT.
+ */
static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
{
int page_order;
@@ -1574,7 +1602,7 @@ static struct agp_bridge_driver intel_915_driver = {
.num_aperture_sizes = 4,
.needs_scratch_page = TRUE,
.configure = intel_i915_configure,
- .fetch_size = intel_i915_fetch_size,
+ .fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.tlb_flush = intel_i810_tlbflush,
.mask_memory = intel_i810_mask_memory,
@@ -1598,7 +1626,7 @@ static struct agp_bridge_driver intel_i965_driver = {
.num_aperture_sizes = 4,
.needs_scratch_page = TRUE,
.configure = intel_i915_configure,
- .fetch_size = intel_i965_fetch_size,
+ .fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.tlb_flush = intel_i810_tlbflush,
.mask_memory = intel_i965_mask_memory,
@@ -1927,6 +1955,15 @@ static int agp_intel_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
+ /* We should restore our graphics device's config space,
+ * as host bridge (00:00) resumes before graphics device (02:00),
+ * then our access to its pci space can work right.
+ */
+ if (intel_i810_private.i810_dev)
+ pci_restore_state(intel_i810_private.i810_dev);
+ if (intel_i830_private.i830_dev)
+ pci_restore_state(intel_i830_private.i830_dev);
+
if (bridge->driver == &intel_generic_driver)
intel_configure();
else if (bridge->driver == &intel_850_driver)
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index d73be4c2db8..902648db7ef 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -281,10 +281,11 @@ static int __devinit agp_sgi_init(void)
else
return 0;
- sgi_tioca_agp_bridges =
- (struct agp_bridge_data **)kmalloc(tioca_gart_found *
- sizeof(struct agp_bridge_data *),
- GFP_KERNEL);
+ sgi_tioca_agp_bridges = kmalloc(tioca_gart_found *
+ sizeof(struct agp_bridge_data *),
+ GFP_KERNEL);
+ if (!sgi_tioca_agp_bridges)
+ return -ENOMEM;
j = 0;
list_for_each_entry(info, &tioca_list, ca_list) {
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index c149ac9ce9a..2ded7a280d7 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -380,9 +380,23 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
/* P4M800CE */
{
.device_id = PCI_DEVICE_ID_VIA_P4M800CE,
- .chipset_name = "P4M800CE",
+ .chipset_name = "VT3314",
+ },
+ /* CX700 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_CX700,
+ .chipset_name = "CX700",
+ },
+ /* VT3336 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_VT3336,
+ .chipset_name = "VT3336",
+ },
+ /* P4M890 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_P4M890,
+ .chipset_name = "P4M890",
},
-
{ }, /* dummy final entry, always present */
};
@@ -524,6 +538,9 @@ static const struct pci_device_id agp_via_pci_table[] = {
ID(PCI_DEVICE_ID_VIA_83_87XX_1),
ID(PCI_DEVICE_ID_VIA_3296_0),
ID(PCI_DEVICE_ID_VIA_P4M800CE),
+ ID(PCI_DEVICE_ID_VIA_CX700),
+ ID(PCI_DEVICE_ID_VIA_VT3336),
+ ID(PCI_DEVICE_ID_VIA_P4M890),
{ }
};
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 66086fa2d59..feb4ac802a0 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -104,7 +104,7 @@ static struct async_struct *IRQ_ports;
static unsigned char current_ctl_bits;
-static void change_speed(struct async_struct *info, struct termios *old);
+static void change_speed(struct async_struct *info, struct ktermios *old);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -694,7 +694,7 @@ static void shutdown(struct async_struct * info)
* the specified baud rate for a serial port.
*/
static void change_speed(struct async_struct *info,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int quot = 0, baud_base, baud;
unsigned cflag, cval = 0;
@@ -1365,7 +1365,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
return 0;
}
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 04a12027a74..b99b7561260 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -443,7 +443,7 @@ int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
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);
+ q = kmalloc(sizeof(*p), GFP_KERNEL);
if (!q) {
if (p) p->refcount++;
return -ENOMEM;
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 8ce3f34cfc2..c02d9e99e05 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -82,7 +82,7 @@ static inline u32 cs5535_lowhigh_base(int reg)
static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
- u32 m = iminor(file->f_dentry->d_inode);
+ u32 m = iminor(file->f_path.dentry->d_inode);
int i, j;
u32 base = gpio_base + cs5535_lowhigh_base(m);
u32 m0, m1;
@@ -117,7 +117,7 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
- u32 m = iminor(file->f_dentry->d_inode);
+ u32 m = iminor(file->f_path.dentry->d_inode);
u32 base = gpio_base + cs5535_lowhigh_base(m);
int rd_bit = 1 << (m & 0x0f);
int i;
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index acb2de5e3a9..3ffa0807754 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1,8 +1,6 @@
#undef BLOCKMOVE
#define Z_WAKE
#undef Z_EXT_CHARS_IN_BUFFER
-static char rcsid[] =
-"$Revision: 2.3.2.20 $$Date: 2004/02/25 18:14:16 $";
/*
* linux/drivers/char/cyclades.c
@@ -593,18 +591,20 @@ static char rcsid[] =
*
*/
+#define CY_VERSION "2.4"
+
/* If you need to install more boards than NR_CARDS, change the constant
in the definition below. No other change is necessary to support up to
eight boards. Beyond that you'll have to extend cy_isa_addresses. */
-#define NR_CARDS 4
+#define NR_CARDS 4
/*
If the total number of ports is larger than NR_PORTS, change this
constant in the definition below. No other change is necessary to
support more boards/ports. */
-#define NR_PORTS 256
+#define NR_PORTS 256
#define ZE_V1_NPORTS 64
#define ZO_V1 0
@@ -625,9 +625,9 @@ static char rcsid[] =
#undef CY_PCI_DEBUG
#if 0
-#define PAUSE __asm__("nop");
+#define PAUSE __asm__("nop")
#else
-#define PAUSE ;
+#define PAUSE do {} while (0)
#endif
/*
@@ -663,7 +663,7 @@ static char rcsid[] =
do { \
spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \
} while (0)
-
+
#define CY_UNLOCK(info,flags) \
do { \
spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \
@@ -676,14 +676,14 @@ static char rcsid[] =
#include <linux/stat.h>
#include <linux/proc_fs.h>
-static void cy_throttle (struct tty_struct *tty);
-static void cy_send_xchar (struct tty_struct *tty, char ch);
+static void cy_throttle(struct tty_struct *tty);
+static void cy_send_xchar(struct tty_struct *tty, char ch);
#define IS_CYC_Z(card) ((card).num_chips == -1)
#define Z_FPGA_CHECK(card) \
- ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
- ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
+ ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
+ ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
#define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \
((card).ctl_addr))->mail_box_0)) || \
@@ -698,8 +698,6 @@ static void cy_send_xchar (struct tty_struct *tty, char ch);
#define STD_COM_FLAGS (0)
-#define JIFFIES_DIFF(n, j) ((j) - (n))
-
static struct tty_driver *cy_serial_driver;
#ifdef CONFIG_ISA
@@ -713,27 +711,28 @@ static struct tty_driver *cy_serial_driver;
*/
static unsigned int cy_isa_addresses[] = {
- 0xD0000,
- 0xD2000,
- 0xD4000,
- 0xD6000,
- 0xD8000,
- 0xDA000,
- 0xDC000,
- 0xDE000,
- 0,0,0,0,0,0,0,0
+ 0xD0000,
+ 0xD2000,
+ 0xD4000,
+ 0xD6000,
+ 0xD8000,
+ 0xDA000,
+ 0xDC000,
+ 0xDE000,
+ 0, 0, 0, 0, 0, 0, 0, 0
};
+
#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
#ifdef MODULE
static long maddr[NR_CARDS] = { 0, };
-static int irq[NR_CARDS] = { 0, };
+static int irq[NR_CARDS] = { 0, };
module_param_array(maddr, long, NULL, 0);
module_param_array(irq, int, NULL, 0);
#endif
-#endif /* CONFIG_ISA */
+#endif /* CONFIG_ISA */
/* This is the per-card data structure containing address, irq, number of
channels, etc. This driver supports a maximum of NR_CARDS cards.
@@ -745,7 +744,7 @@ static struct cyclades_card cy_card[NR_CARDS];
*/
static struct cyclades_port cy_port[NR_PORTS];
-static int cy_next_channel; /* next minor available */
+static int cy_next_channel; /* next minor available */
/*
* This is used to look up the divisor speeds and the timeouts
@@ -757,36 +756,42 @@ static int cy_next_channel; /* next minor available */
* 20
*/
static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
- 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000,
- 230400, 0};
-
-static char baud_co_25[] = { /* 25 MHz clock option table */
- /* value => 00 01 02 03 04 */
- /* divide by 8 32 128 512 2048 */
- 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
- 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-static char baud_bpr_25[] = { /* 25 MHz baud rate period table */
- 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
- 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15};
-
-static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */
- /* value => 00 01 02 03 04 */
- /* divide by 8 32 128 512 2048 */
- 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
- 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00};
-
-static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */
- 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
- 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
- 0x21};
-
-static char baud_cor3[] = { /* receive threshold */
- 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
- 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
- 0x07};
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+ 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
+ 230400, 0
+};
+
+static char baud_co_25[] = { /* 25 MHz clock option table */
+ /* value => 00 01 02 03 04 */
+ /* divide by 8 32 128 512 2048 */
+ 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static char baud_bpr_25[] = { /* 25 MHz baud rate period table */
+ 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
+ 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
+};
+
+static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */
+ /* value => 00 01 02 03 04 */
+ /* divide by 8 32 128 512 2048 */
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
+ 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+};
+
+static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */
+ 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
+ 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
+ 0x21
+};
+
+static char baud_cor3[] = { /* receive threshold */
+ 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
+ 0x07
+};
/*
* The Cyclades driver implements HW flow control as any serial driver.
@@ -799,42 +804,42 @@ static char baud_cor3[] = { /* receive threshold */
* cables.
*/
-static char rflow_thr[] = { /* rflow threshold */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
- 0x0a};
+static char rflow_thr[] = { /* rflow threshold */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a
+};
/* The Cyclom-Ye has placed the sequential chips in non-sequential
* address order. This look-up table overcomes that problem.
*/
-static int cy_chip_offset [] =
- { 0x0000,
- 0x0400,
- 0x0800,
- 0x0C00,
- 0x0200,
- 0x0600,
- 0x0A00,
- 0x0E00
- };
+static int cy_chip_offset[] = { 0x0000,
+ 0x0400,
+ 0x0800,
+ 0x0C00,
+ 0x0200,
+ 0x0600,
+ 0x0A00,
+ 0x0E00
+};
/* PCI related definitions */
-static unsigned short cy_pci_nboard;
-static unsigned short cy_isa_nboard;
-static unsigned short cy_nboard;
+static unsigned short cy_pci_nboard;
+static unsigned short cy_isa_nboard;
+static unsigned short cy_nboard;
#ifdef CONFIG_PCI
-static unsigned short cy_pci_dev_id[] = {
- PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */
- PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */
- PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */
- PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */
- PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */
- PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */
- PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */
- PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */
- 0 /* end of table */
- };
+static unsigned short cy_pci_dev_id[] = {
+ PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */
+ 0 /* end of table */
+};
#endif
static void cy_start(struct tty_struct *);
@@ -842,9 +847,9 @@ static void set_line_char(struct cyclades_port *);
static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong);
#ifdef CONFIG_ISA
static unsigned detect_isa_irq(void __iomem *);
-#endif /* CONFIG_ISA */
+#endif /* CONFIG_ISA */
-static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
+static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *);
#ifndef CONFIG_CYZ_INTR
static void cyz_poll(unsigned long);
@@ -855,41 +860,36 @@ static long cyz_polling_cycle = CZ_DEF_POLL;
static int cyz_timeron = 0;
static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
-#else /* CONFIG_CYZ_INTR */
+#else /* CONFIG_CYZ_INTR */
static void cyz_rx_restart(unsigned long);
static struct timer_list cyz_rx_full_timer[NR_PORTS];
-#endif /* CONFIG_CYZ_INTR */
+#endif /* CONFIG_CYZ_INTR */
-static inline int
-serial_paranoia_check(struct cyclades_port *info,
- char *name, const char *routine)
+static inline int serial_paranoia_check(struct cyclades_port *info,
+ char *name, const char *routine)
{
#ifdef SERIAL_PARANOIA_CHECK
- static const char *badmagic =
- "cyc Warning: bad magic number for serial struct (%s) in %s\n";
- static const char *badinfo =
- "cyc Warning: null cyclades_port for (%s) in %s\n";
- static const char *badrange =
- "cyc Warning: cyclades_port out of range for (%s) in %s\n";
-
- if (!info) {
- printk(badinfo, name, routine);
- return 1;
- }
-
- if( (long)info < (long)(&cy_port[0])
- || (long)(&cy_port[NR_PORTS]) < (long)info ){
- printk(badrange, name, routine);
- return 1;
- }
-
- if (info->magic != CYCLADES_MAGIC) {
- printk(badmagic, name, routine);
- return 1;
- }
+ if (!info) {
+ printk("cyc Warning: null cyclades_port for (%s) in %s\n",
+ name, routine);
+ return 1;
+ }
+
+ if ((long)info < (long)(&cy_port[0]) ||
+ (long)(&cy_port[NR_PORTS]) < (long)info) {
+ printk("cyc Warning: cyclades_port out of range for (%s) in "
+ "%s\n", name, routine);
+ return 1;
+ }
+
+ if (info->magic != CYCLADES_MAGIC) {
+ printk("cyc Warning: bad magic number for serial struct (%s) "
+ "in %s\n", name, routine);
+ return 1;
+ }
#endif
- return 0;
-} /* serial_paranoia_check */
+ return 0;
+} /* serial_paranoia_check */
/*
* This routine is used by the interrupt handler to schedule
@@ -897,13 +897,11 @@ serial_paranoia_check(struct cyclades_port *info,
* (also known as the "bottom half"). This can be called any
* number of times for any channel without harm.
*/
-static inline void
-cy_sched_event(struct cyclades_port *info, int event)
+static inline void cy_sched_event(struct cyclades_port *info, int event)
{
- info->event |= 1 << event; /* remember what kind of event and who */
- schedule_work(&info->tqueue);
-} /* cy_sched_event */
-
+ info->event |= 1 << event; /* remember what kind of event and who */
+ schedule_work(&info->tqueue);
+} /* cy_sched_event */
/*
* This routine is used to handle the "bottom half" processing for the
@@ -930,41 +928,36 @@ do_softint(struct work_struct *work)
{
struct cyclades_port *info =
container_of(work, struct cyclades_port, tqueue);
- struct tty_struct *tty;
-
- tty = info->tty;
- if (!tty)
- return;
-
- if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
- tty_hangup(info->tty);
- wake_up_interruptible(&info->open_wait);
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- }
- if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
- wake_up_interruptible(&info->open_wait);
- }
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
+ tty_hangup(info->tty);
+ wake_up_interruptible(&info->open_wait);
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ }
+ if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event))
+ wake_up_interruptible(&info->open_wait);
#ifdef CONFIG_CYZ_INTR
- if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
- if (cyz_rx_full_timer[info->line].function == NULL) {
- cyz_rx_full_timer[info->line].expires = jiffies + 1;
- cyz_rx_full_timer[info->line].function = cyz_rx_restart;
- cyz_rx_full_timer[info->line].data = (unsigned long)info;
- add_timer(&cyz_rx_full_timer[info->line]);
+ if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
+ if (cyz_rx_full_timer[info->line].function == NULL) {
+ cyz_rx_full_timer[info->line].expires = jiffies + 1;
+ cyz_rx_full_timer[info->line].function = cyz_rx_restart;
+ cyz_rx_full_timer[info->line].data =
+ (unsigned long)info;
+ add_timer(&cyz_rx_full_timer[info->line]);
+ }
}
- }
#endif
- if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) {
- wake_up_interruptible(&info->delta_msr_wait);
- }
- if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
- tty_wakeup(tty);
- wake_up_interruptible(&tty->write_wait);
- }
+ if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event))
+ wake_up_interruptible(&info->delta_msr_wait);
+ tty_wakeup(tty);
#ifdef Z_WAKE
- if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) {
- wake_up_interruptible(&info->shutdown_wait);
- }
+ if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event))
+ wake_up_interruptible(&info->shutdown_wait);
#endif
} /* do_softint */
@@ -979,341 +972,339 @@ do_softint(struct work_struct *work)
This function is only called from inside spinlock-protected code.
*/
-static int
-cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
+static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
{
- volatile int i;
+ volatile int i;
- /* Check to see that the previous command has completed */
- for(i = 0 ; i < 100 ; i++){
- if (cy_readb(base_addr+(CyCCR<<index)) == 0){
- break;
+ /* Check to see that the previous command has completed */
+ for (i = 0; i < 100; i++) {
+ if (cy_readb(base_addr + (CyCCR << index)) == 0) {
+ break;
+ }
+ udelay(10L);
}
- udelay(10L);
- }
- /* if the CCR never cleared, the previous command
- didn't finish within the "reasonable time" */
- if (i == 100) return (-1);
+ /* if the CCR never cleared, the previous command
+ didn't finish within the "reasonable time" */
+ if (i == 100)
+ return -1;
- /* Issue the new command */
- cy_writeb(base_addr+(CyCCR<<index), cmd);
+ /* Issue the new command */
+ cy_writeb(base_addr + (CyCCR << index), cmd);
- return(0);
-} /* cyy_issue_cmd */
+ return 0;
+} /* cyy_issue_cmd */
#ifdef CONFIG_ISA
/* ISA interrupt detection code */
-static unsigned
-detect_isa_irq(void __iomem *address)
+static unsigned detect_isa_irq(void __iomem * address)
{
- int irq;
- unsigned long irqs, flags;
- int save_xir, save_car;
- int index = 0; /* IRQ probing is only for ISA */
-
- /* forget possible initially masked and pending IRQ */
- irq = probe_irq_off(probe_irq_on());
-
- /* Clear interrupts on the board first */
- cy_writeb(address + (Cy_ClrIntr<<index), 0);
- /* Cy_ClrIntr is 0x1800 */
-
- irqs = probe_irq_on();
- /* Wait ... */
- udelay(5000L);
-
- /* Enable the Tx interrupts on the CD1400 */
- local_irq_save(flags);
- cy_writeb(address + (CyCAR<<index), 0);
- cyy_issue_cmd(address, CyCHAN_CTL|CyENB_XMTR, index);
-
- cy_writeb(address + (CyCAR<<index), 0);
- cy_writeb(address + (CySRER<<index),
- cy_readb(address + (CySRER<<index)) | CyTxRdy);
- local_irq_restore(flags);
-
- /* Wait ... */
- udelay(5000L);
-
- /* Check which interrupt is in use */
- irq = probe_irq_off(irqs);
-
- /* Clean up */
- save_xir = (u_char) cy_readb(address + (CyTIR<<index));
- save_car = cy_readb(address + (CyCAR<<index));
- cy_writeb(address + (CyCAR<<index), (save_xir & 0x3));
- cy_writeb(address + (CySRER<<index),
- cy_readb(address + (CySRER<<index)) & ~CyTxRdy);
- cy_writeb(address + (CyTIR<<index), (save_xir & 0x3f));
- cy_writeb(address + (CyCAR<<index), (save_car));
- cy_writeb(address + (Cy_ClrIntr<<index), 0);
- /* Cy_ClrIntr is 0x1800 */
-
- return (irq > 0)? irq : 0;
+ int irq;
+ unsigned long irqs, flags;
+ int save_xir, save_car;
+ int index = 0; /* IRQ probing is only for ISA */
+
+ /* forget possible initially masked and pending IRQ */
+ irq = probe_irq_off(probe_irq_on());
+
+ /* Clear interrupts on the board first */
+ cy_writeb(address + (Cy_ClrIntr << index), 0);
+ /* Cy_ClrIntr is 0x1800 */
+
+ irqs = probe_irq_on();
+ /* Wait ... */
+ udelay(5000L);
+
+ /* Enable the Tx interrupts on the CD1400 */
+ local_irq_save(flags);
+ cy_writeb(address + (CyCAR << index), 0);
+ cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
+
+ cy_writeb(address + (CyCAR << index), 0);
+ cy_writeb(address + (CySRER << index),
+ cy_readb(address + (CySRER << index)) | CyTxRdy);
+ local_irq_restore(flags);
+
+ /* Wait ... */
+ udelay(5000L);
+
+ /* Check which interrupt is in use */
+ irq = probe_irq_off(irqs);
+
+ /* Clean up */
+ save_xir = (u_char) cy_readb(address + (CyTIR << index));
+ save_car = cy_readb(address + (CyCAR << index));
+ cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
+ cy_writeb(address + (CySRER << index),
+ cy_readb(address + (CySRER << index)) & ~CyTxRdy);
+ cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
+ cy_writeb(address + (CyCAR << index), (save_car));
+ cy_writeb(address + (Cy_ClrIntr << index), 0);
+ /* Cy_ClrIntr is 0x1800 */
+
+ return (irq > 0) ? irq : 0;
}
-#endif /* CONFIG_ISA */
+#endif /* CONFIG_ISA */
-/* The real interrupt service routine is called
- whenever the card wants its hand held--chars
- received, out buffer empty, modem change, etc.
- */
-static irqreturn_t
-cyy_interrupt(int irq, void *dev_id)
+static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
+ void __iomem * base_addr, int status, int index)
{
- struct tty_struct *tty;
- int status;
- struct cyclades_card *cinfo;
- struct cyclades_port *info;
- void __iomem *base_addr, *card_base_addr;
- int chip;
- int save_xir, channel, save_car;
- char data;
- volatile int char_count;
- int outch;
- int i,j,index;
- int too_many;
- int had_work;
- int mdm_change;
- int mdm_status;
- int len;
- if((cinfo = (struct cyclades_card *)dev_id) == 0){
-#ifdef CY_DEBUG_INTERRUPTS
- printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
-#endif
- return IRQ_NONE; /* spurious interrupt */
- }
-
- card_base_addr = cinfo->base_addr;
- index = cinfo->bus_index;
-
-
- /* This loop checks all chips in the card. Make a note whenever
- _any_ chip had some work to do, as this is considered an
- indication that there will be more to do. Only when no chip
- has any work does this outermost loop exit.
- */
- do{
- had_work = 0;
- for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
- base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
- too_many = 0;
- while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) {
- had_work++;
- /* The purpose of the following test is to ensure that
- no chip can monopolize the driver. This forces the
- chips to be checked in a round-robin fashion (after
- draining each of a bunch (1000) of characters).
- */
- if(1000<too_many++){
- break;
- }
- if (status & CySRReceive) { /* reception interrupt */
+ struct cyclades_port *info;
+ struct tty_struct *tty;
+ volatile int char_count;
+ int i, j, len, mdm_change, mdm_status, outch;
+ int save_xir, channel, save_car;
+ char data;
+
+ if (status & CySRReceive) { /* reception interrupt */
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
+ printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
#endif
- /* determine the channel & change to that context */
- spin_lock(&cinfo->card_lock);
- save_xir = (u_char) cy_readb(base_addr+(CyRIR<<index));
- channel = (u_short ) (save_xir & CyIRChannel);
- i = channel + chip * 4 + cinfo->first_line;
- info = &cy_port[i];
- info->last_active = jiffies;
- save_car = cy_readb(base_addr+(CyCAR<<index));
- cy_writeb(base_addr+(CyCAR<<index), save_xir);
-
- /* if there is nowhere to put the data, discard it */
- if(info->tty == 0){
- j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask);
- if ( j == CyIVRRxEx ) { /* exception */
- data = cy_readb(base_addr+(CyRDSR<<index));
- } else { /* normal character reception */
- char_count = cy_readb(base_addr+(CyRDCR<<index));
- while(char_count--){
- data = cy_readb(base_addr+(CyRDSR<<index));
- }
- }
- }else{ /* there is an open port for this data */
- tty = info->tty;
- j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask);
- if ( j == CyIVRRxEx ) { /* exception */
- data = cy_readb(base_addr+(CyRDSR<<index));
-
- /* For statistics only */
- if (data & CyBREAK)
- info->icount.brk++;
- else if(data & CyFRAME)
- info->icount.frame++;
- else if(data & CyPARITY)
- info->icount.parity++;
- else if(data & CyOVERRUN)
- info->icount.overrun++;
-
- if(data & info->ignore_status_mask){
- info->icount.rx++;
- continue;
- }
- if (tty_buffer_request_room(tty, 1)) {
- if (data & info->read_status_mask){
- if(data & CyBREAK){
- tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_BREAK);
- info->icount.rx++;
- if (info->flags & ASYNC_SAK){
- do_SAK(tty);
- }
- }else if(data & CyFRAME){
- tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
- info->icount.rx++;
- info->idle_stats.frame_errs++;
- }else if(data & CyPARITY){
- /* Pieces of seven... */
- tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_PARITY);
- info->icount.rx++;
- info->idle_stats.parity_errs++;
- }else if(data & CyOVERRUN){
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ /* determine the channel & change to that context */
+ spin_lock(&cinfo->card_lock);
+ save_xir = (u_char) cy_readb(base_addr + (CyRIR << index));
+ channel = (u_short) (save_xir & CyIRChannel);
+ i = channel + chip * 4 + cinfo->first_line;
+ info = &cy_port[i];
+ info->last_active = jiffies;
+ save_car = cy_readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+ /* if there is nowhere to put the data, discard it */
+ if (info->tty == 0) {
+ j = (cy_readb(base_addr + (CyRIVR << index)) &
+ CyIVRMask);
+ if (j == CyIVRRxEx) { /* exception */
+ data = cy_readb(base_addr + (CyRDSR << index));
+ } else { /* normal character reception */
+ char_count = cy_readb(base_addr +
+ (CyRDCR << index));
+ while (char_count--) {
+ data = cy_readb(base_addr +
+ (CyRDSR << index));
+ }
+ }
+ } else { /* there is an open port for this data */
+ tty = info->tty;
+ j = (cy_readb(base_addr + (CyRIVR << index)) &
+ CyIVRMask);
+ if (j == CyIVRRxEx) { /* exception */
+ data = cy_readb(base_addr + (CyRDSR << index));
+
+ /* For statistics only */
+ if (data & CyBREAK)
+ info->icount.brk++;
+ else if (data & CyFRAME)
+ info->icount.frame++;
+ else if (data & CyPARITY)
+ info->icount.parity++;
+ else if (data & CyOVERRUN)
+ info->icount.overrun++;
+
+ if (data & info->ignore_status_mask) {
info->icount.rx++;
- /* If the flip buffer itself is
- overflowing, we still lose
- the next incoming character.
- */
- tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
- info->icount.rx++;
+ return;
+ }
+ if (tty_buffer_request_room(tty, 1)) {
+ if (data & info->read_status_mask) {
+ if (data & CyBREAK) {
+ tty_insert_flip_char(
+ tty,
+ cy_readb(
+ base_addr +
+ (CyRDSR <<
+ index)),
+ TTY_BREAK);
+ info->icount.rx++;
+ if (info->flags &
+ ASYNC_SAK) {
+ do_SAK(tty);
+ }
+ } else if (data & CyFRAME) {
+ tty_insert_flip_char(
+ tty,
+ cy_readb(
+ base_addr +
+ (CyRDSR <<
+ index)),
+ TTY_FRAME);
+ info->icount.rx++;
+ info->idle_stats.
+ frame_errs++;
+ } else if (data & CyPARITY) {
+ /* Pieces of seven... */
+ tty_insert_flip_char(
+ tty,
+ cy_readb(
+ base_addr +
+ (CyRDSR <<
+ index)),
+ TTY_PARITY);
+ info->icount.rx++;
+ info->idle_stats.
+ parity_errs++;
+ } else if (data & CyOVERRUN) {
+ tty_insert_flip_char(
+ tty, 0,
+ TTY_OVERRUN);
+ info->icount.rx++;
+ /* If the flip buffer itself is
+ overflowing, we still lose
+ the next incoming character.
+ */
+ tty_insert_flip_char(
+ tty,
+ cy_readb(
+ base_addr +
+ (CyRDSR <<
+ index)),
+ TTY_FRAME);
+ info->icount.rx++;
+ info->idle_stats.
+ overruns++;
+ /* These two conditions may imply */
+ /* a normal read should be done. */
+ /* }else if(data & CyTIMEOUT){ */
+ /* }else if(data & CySPECHAR){ */
+ } else {
+ tty_insert_flip_char(
+ tty, 0,
+ TTY_NORMAL);
+ info->icount.rx++;
+ }
+ } else {
+ tty_insert_flip_char(tty, 0,
+ TTY_NORMAL);
+ info->icount.rx++;
+ }
+ } else {
+ /* there was a software buffer
+ overrun and nothing could be
+ done about it!!! */
+ info->icount.buf_overrun++;
info->idle_stats.overruns++;
- /* These two conditions may imply */
- /* a normal read should be done. */
- /* }else if(data & CyTIMEOUT){ */
- /* }else if(data & CySPECHAR){ */
- }else {
- tty_insert_flip_char(tty, 0, TTY_NORMAL);
- info->icount.rx++;
- }
- }else{
- tty_insert_flip_char(tty, 0, TTY_NORMAL);
- info->icount.rx++;
- }
- }else{
- /* there was a software buffer
- overrun and nothing could be
- done about it!!! */
- info->icount.buf_overrun++;
- info->idle_stats.overruns++;
- }
- } else { /* normal character reception */
- /* load # chars available from the chip */
- char_count = cy_readb(base_addr+(CyRDCR<<index));
+ }
+ } else { /* normal character reception */
+ /* load # chars available from the chip */
+ char_count = cy_readb(base_addr +
+ (CyRDCR << index));
#ifdef CY_ENABLE_MONITORING
- ++info->mon.int_count;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
+ ++info->mon.int_count;
+ info->mon.char_count += char_count;
+ if (char_count > info->mon.char_max)
+ info->mon.char_max = char_count;
+ info->mon.char_last = char_count;
#endif
- len = tty_buffer_request_room(tty, char_count);
- while(len--){
- data = cy_readb(base_addr+(CyRDSR<<index));
- tty_insert_flip_char(tty, data, TTY_NORMAL);
- info->idle_stats.recv_bytes++;
- info->icount.rx++;
+ len = tty_buffer_request_room(tty, char_count);
+ while (len--) {
+ data = cy_readb(base_addr +
+ (CyRDSR << index));
+ tty_insert_flip_char(tty, data,
+ TTY_NORMAL);
+ info->idle_stats.recv_bytes++;
+ info->icount.rx++;
#ifdef CY_16Y_HACK
- udelay(10L);
+ udelay(10L);
#endif
- }
- info->idle_stats.recv_idle = jiffies;
- }
+ }
+ info->idle_stats.recv_idle = jiffies;
+ }
tty_schedule_flip(tty);
- }
- /* end of service */
- cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
- cy_writeb(base_addr+(CyCAR<<index), (save_car));
- spin_unlock(&cinfo->card_lock);
- }
-
-
- if (status & CySRTransmit) { /* transmission interrupt */
- /* Since we only get here when the transmit buffer
- is empty, we know we can always stuff a dozen
- characters. */
+ }
+ /* end of service */
+ cy_writeb(base_addr + (CyRIR << index), (save_xir & 0x3f));
+ cy_writeb(base_addr + (CyCAR << index), (save_car));
+ spin_unlock(&cinfo->card_lock);
+ }
+
+ if (status & CySRTransmit) { /* transmission interrupt */
+ /* Since we only get here when the transmit buffer
+ is empty, we know we can always stuff a dozen
+ characters. */
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
+ printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
#endif
- /* determine the channel & change to that context */
- spin_lock(&cinfo->card_lock);
- save_xir = (u_char) cy_readb(base_addr+(CyTIR<<index));
- channel = (u_short ) (save_xir & CyIRChannel);
- i = channel + chip * 4 + cinfo->first_line;
- save_car = cy_readb(base_addr+(CyCAR<<index));
- cy_writeb(base_addr+(CyCAR<<index), save_xir);
-
- /* validate the port# (as configured and open) */
- if( (i < 0) || (NR_PORTS <= i) ){
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
- goto txend;
- }
- info = &cy_port[i];
- info->last_active = jiffies;
- if(info->tty == 0){
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
- goto txdone;
- }
-
- /* load the on-chip space for outbound data */
- char_count = info->xmit_fifo_size;
-
- if(info->x_char) { /* send special char */
- outch = info->x_char;
- cy_writeb(base_addr+(CyTDR<<index), outch);
- char_count--;
+ /* determine the channel & change to that context */
+ spin_lock(&cinfo->card_lock);
+ save_xir = (u_char) cy_readb(base_addr + (CyTIR << index));
+ channel = (u_short) (save_xir & CyIRChannel);
+ i = channel + chip * 4 + cinfo->first_line;
+ save_car = cy_readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+ /* validate the port# (as configured and open) */
+ if ((i < 0) || (NR_PORTS <= i)) {
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) &
+ ~CyTxRdy);
+ goto txend;
+ }
+ info = &cy_port[i];
+ info->last_active = jiffies;
+ if (info->tty == 0) {
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) &
+ ~CyTxRdy);
+ goto txdone;
+ }
+
+ /* load the on-chip space for outbound data */
+ char_count = info->xmit_fifo_size;
+
+ if (info->x_char) { /* send special char */
+ outch = info->x_char;
+ cy_writeb(base_addr + (CyTDR << index), outch);
+ char_count--;
info->icount.tx++;
- info->x_char = 0;
- }
+ info->x_char = 0;
+ }
- if (info->breakon || info->breakoff) {
+ if (info->breakon || info->breakoff) {
if (info->breakon) {
- cy_writeb(base_addr + (CyTDR<<index), 0);
- cy_writeb(base_addr + (CyTDR<<index), 0x81);
- info->breakon = 0;
- char_count -= 2;
+ cy_writeb(base_addr + (CyTDR << index), 0);
+ cy_writeb(base_addr + (CyTDR << index), 0x81);
+ info->breakon = 0;
+ char_count -= 2;
}
if (info->breakoff) {
- cy_writeb(base_addr + (CyTDR<<index), 0);
- cy_writeb(base_addr + (CyTDR<<index), 0x83);
- info->breakoff = 0;
- char_count -= 2;
+ cy_writeb(base_addr + (CyTDR << index), 0);
+ cy_writeb(base_addr + (CyTDR << index), 0x83);
+ info->breakoff = 0;
+ char_count -= 2;
}
- }
-
- while (char_count-- > 0){
- if (!info->xmit_cnt){
- if (cy_readb(base_addr+(CySRER<<index))&CyTxMpty) {
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) &
- ~CyTxMpty);
- } else {
- cy_writeb(base_addr+(CySRER<<index),
- ((cy_readb(base_addr+(CySRER<<index))
- & ~CyTxRdy)
- | CyTxMpty));
- }
- goto txdone;
+ }
+
+ while (char_count-- > 0) {
+ if (!info->xmit_cnt) {
+ if (cy_readb(base_addr + (CySRER << index)) &
+ CyTxMpty) {
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr +
+ (CySRER << index)) &
+ ~CyTxMpty);
+ } else {
+ cy_writeb(base_addr + (CySRER << index),
+ (cy_readb(base_addr +
+ (CySRER << index)) &
+ ~CyTxRdy) | CyTxMpty);
+ }
+ goto txdone;
}
- if (info->xmit_buf == 0){
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) &
+ if (info->xmit_buf == 0) {
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index))&
~CyTxRdy);
- goto txdone;
+ goto txdone;
}
- if (info->tty->stopped || info->tty->hw_stopped){
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) &
+ if (info->tty->stopped || info->tty->hw_stopped) {
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index))&
~CyTxRdy);
- goto txdone;
+ goto txdone;
}
- /* Because the Embedded Transmit Commands have
- been enabled, we must check to see if the
+ /* Because the Embedded Transmit Commands have
+ been enabled, we must check to see if the
escape character, NULL, is being sent. If it
is, we must ensure that there is room for it
to be doubled in the output stream. Therefore
@@ -1322,125 +1313,182 @@ cyy_interrupt(int irq, void *dev_id)
after the check for a NULL output character.
This is necessary because there may not be
room for the two chars needed to send a NULL.)
- */
- outch = info->xmit_buf[info->xmit_tail];
- if( outch ){
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1)
- & (SERIAL_XMIT_SIZE - 1);
- cy_writeb(base_addr+(CyTDR<<index), outch);
- info->icount.tx++;
- }else{
- if(char_count > 1){
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1)
- & (SERIAL_XMIT_SIZE - 1);
- cy_writeb(base_addr+(CyTDR<<index),
- outch);
- cy_writeb(base_addr+(CyTDR<<index), 0);
+ */
+ outch = info->xmit_buf[info->xmit_tail];
+ if (outch) {
+ info->xmit_cnt--;
+ info->xmit_tail = (info->xmit_tail + 1) &
+ (SERIAL_XMIT_SIZE - 1);
+ cy_writeb(base_addr + (CyTDR << index), outch);
info->icount.tx++;
- char_count--;
- }else{
- }
- }
- }
-
- txdone:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
- }
- txend:
- /* end of service */
- cy_writeb(base_addr+(CyTIR<<index),
- (save_xir & 0x3f));
- cy_writeb(base_addr+(CyCAR<<index), (save_car));
- spin_unlock(&cinfo->card_lock);
- }
-
- if (status & CySRModem) { /* modem interrupt */
-
- /* determine the channel & change to that context */
- spin_lock(&cinfo->card_lock);
- save_xir = (u_char) cy_readb(base_addr+(CyMIR<<index));
- channel = (u_short ) (save_xir & CyIRChannel);
- info = &cy_port[channel + chip * 4
- + cinfo->first_line];
- info->last_active = jiffies;
- save_car = cy_readb(base_addr+(CyCAR<<index));
- cy_writeb(base_addr+(CyCAR<<index), save_xir);
-
- mdm_change = cy_readb(base_addr+(CyMISR<<index));
- mdm_status = cy_readb(base_addr+(CyMSVR1<<index));
-
- if(info->tty == 0){/* no place for data, ignore it*/
- ;
- }else{
+ } else {
+ if (char_count > 1) {
+ info->xmit_cnt--;
+ info->xmit_tail = (info->xmit_tail + 1)&
+ (SERIAL_XMIT_SIZE - 1);
+ cy_writeb(base_addr + (CyTDR << index),
+ outch);
+ cy_writeb(base_addr + (CyTDR << index),
+ 0);
+ info->icount.tx++;
+ char_count--;
+ } else {
+ }
+ }
+ }
+
+txdone:
+ if (info->xmit_cnt < WAKEUP_CHARS) {
+ cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+ }
+txend:
+ /* end of service */
+ cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f));
+ cy_writeb(base_addr + (CyCAR << index), (save_car));
+ spin_unlock(&cinfo->card_lock);
+ }
+
+ if (status & CySRModem) { /* modem interrupt */
+
+ /* determine the channel & change to that context */
+ spin_lock(&cinfo->card_lock);
+ save_xir = (u_char) cy_readb(base_addr + (CyMIR << index));
+ channel = (u_short) (save_xir & CyIRChannel);
+ info = &cy_port[channel + chip * 4 + cinfo->first_line];
+ info->last_active = jiffies;
+ save_car = cy_readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+ mdm_change = cy_readb(base_addr + (CyMISR << index));
+ mdm_status = cy_readb(base_addr + (CyMSVR1 << index));
+
+ if (info->tty == 0) { /* no place for data, ignore it */
+ ;
+ } else {
if (mdm_change & CyANY_DELTA) {
- /* For statistics only */
- if (mdm_change & CyDCD) info->icount.dcd++;
- if (mdm_change & CyCTS) info->icount.cts++;
- if (mdm_change & CyDSR) info->icount.dsr++;
- if (mdm_change & CyRI) info->icount.rng++;
+ /* For statistics only */
+ if (mdm_change & CyDCD)
+ info->icount.dcd++;
+ if (mdm_change & CyCTS)
+ info->icount.cts++;
+ if (mdm_change & CyDSR)
+ info->icount.dsr++;
+ if (mdm_change & CyRI)
+ info->icount.rng++;
+
+ cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+ }
+
+ if ((mdm_change & CyDCD) &&
+ (info->flags & ASYNC_CHECK_CD)) {
+ if (mdm_status & CyDCD) {
+ cy_sched_event(info,
+ Cy_EVENT_OPEN_WAKEUP);
+ } else {
+ cy_sched_event(info, Cy_EVENT_HANGUP);
+ }
+ }
+ if ((mdm_change & CyCTS) &&
+ (info->flags & ASYNC_CTS_FLOW)) {
+ if (info->tty->hw_stopped) {
+ if (mdm_status & CyCTS) {
+ /* cy_start isn't used
+ because... !!! */
+ info->tty->hw_stopped = 0;
+ cy_writeb(base_addr +
+ (CySRER << index),
+ cy_readb(base_addr +
+ (CySRER <<
+ index))|
+ CyTxRdy);
+ cy_sched_event(info,
+ Cy_EVENT_WRITE_WAKEUP);
+ }
+ } else {
+ if (!(mdm_status & CyCTS)) {
+ /* cy_stop isn't used
+ because ... !!! */
+ info->tty->hw_stopped = 1;
+ cy_writeb(base_addr +
+ (CySRER << index),
+ cy_readb(base_addr +
+ (CySRER <<
+ index)) &
+ ~CyTxRdy);
+ }
+ }
+ }
+ if (mdm_change & CyDSR) {
+ }
+ if (mdm_change & CyRI) {
+ }
+ }
+ /* end of service */
+ cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f));
+ cy_writeb(base_addr + (CyCAR << index), save_car);
+ spin_unlock(&cinfo->card_lock);
+ }
+}
+
+/* The real interrupt service routine is called
+ whenever the card wants its hand held--chars
+ received, out buffer empty, modem change, etc.
+ */
+static irqreturn_t cyy_interrupt(int irq, void *dev_id)
+{
+ int status;
+ struct cyclades_card *cinfo;
+ void __iomem *base_addr, *card_base_addr;
+ int chip;
+ int index;
+ int too_many;
+ int had_work;
+
+ if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
+#ifdef CY_DEBUG_INTERRUPTS
+ printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
+#endif
+ return IRQ_NONE; /* spurious interrupt */
+ }
+
+ card_base_addr = cinfo->base_addr;
+ index = cinfo->bus_index;
- cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+ /* This loop checks all chips in the card. Make a note whenever
+ _any_ chip had some work to do, as this is considered an
+ indication that there will be more to do. Only when no chip
+ has any work does this outermost loop exit.
+ */
+ do {
+ had_work = 0;
+ for (chip = 0; chip < cinfo->num_chips; chip++) {
+ base_addr = cinfo->base_addr +
+ (cy_chip_offset[chip] << index);
+ too_many = 0;
+ while ((status = cy_readb(base_addr +
+ (CySVRR << index))) != 0x00) {
+ had_work++;
+ /* The purpose of the following test is to ensure that
+ no chip can monopolize the driver. This forces the
+ chips to be checked in a round-robin fashion (after
+ draining each of a bunch (1000) of characters).
+ */
+ if (1000 < too_many++) {
+ break;
+ }
+ cyy_intr_chip(cinfo, chip, base_addr, status,
+ index);
}
+ }
+ } while (had_work);
- if((mdm_change & CyDCD)
- && (info->flags & ASYNC_CHECK_CD)){
- if(mdm_status & CyDCD){
- cy_sched_event(info,
- Cy_EVENT_OPEN_WAKEUP);
- }else{
- cy_sched_event(info,
- Cy_EVENT_HANGUP);
- }
- }
- if((mdm_change & CyCTS)
- && (info->flags & ASYNC_CTS_FLOW)){
- if(info->tty->hw_stopped){
- if(mdm_status & CyCTS){
- /* cy_start isn't used
- because... !!! */
- info->tty->hw_stopped = 0;
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) |
- CyTxRdy);
- cy_sched_event(info,
- Cy_EVENT_WRITE_WAKEUP);
- }
- }else{
- if(!(mdm_status & CyCTS)){
- /* cy_stop isn't used
- because ... !!! */
- info->tty->hw_stopped = 1;
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) &
- ~CyTxRdy);
- }
- }
- }
- if(mdm_change & CyDSR){
- }
- if(mdm_change & CyRI){
- }
- }
- /* end of service */
- cy_writeb(base_addr+(CyMIR<<index),
- (save_xir & 0x3f));
- cy_writeb(base_addr+(CyCAR<<index), save_car);
- spin_unlock(&cinfo->card_lock);
- }
- } /* end while status != 0 */
- } /* end loop for chips... */
- } while(had_work);
-
- /* clear interrupts */
- spin_lock(&cinfo->card_lock);
- cy_writeb(card_base_addr + (Cy_ClrIntr<<index), 0);
- /* Cy_ClrIntr is 0x1800 */
- spin_unlock(&cinfo->card_lock);
- return IRQ_HANDLED;
-} /* cyy_interrupt */
+ /* clear interrupts */
+ spin_lock(&cinfo->card_lock);
+ cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
+ /* Cy_ClrIntr is 0x1800 */
+ spin_unlock(&cinfo->card_lock);
+ return IRQ_HANDLED;
+} /* cyy_interrupt */
/***********************************************************/
/********* End of block of Cyclom-Y specific code **********/
@@ -1448,643 +1496,655 @@ cyy_interrupt(int irq, void *dev_id)
/***********************************************************/
static int
-cyz_fetch_msg( struct cyclades_card *cinfo,
- uclong *channel, ucchar *cmd, uclong *param)
+cyz_fetch_msg(struct cyclades_card *cinfo,
+ uclong * channel, ucchar * cmd, uclong * param)
{
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- unsigned long loc_doorbell;
-
- firm_id = cinfo->base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo)){
- return (-1);
- }
- zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
-
- loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
- (cinfo->ctl_addr))->loc_doorbell);
- if (loc_doorbell){
- *cmd = (char)(0xff & loc_doorbell);
- *channel = cy_readl(&board_ctrl->fwcmd_channel);
- *param = (uclong)cy_readl(&board_ctrl->fwcmd_param);
- cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell,
- 0xffffffff);
- return 1;
- }
- return 0;
-} /* cyz_fetch_msg */
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ unsigned long loc_doorbell;
+
+ firm_id = cinfo->base_addr + ID_ADDRESS;
+ if (!ISZLOADED(*cinfo)) {
+ return -1;
+ }
+ zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+ 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+
+ loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
+ (cinfo->ctl_addr))->loc_doorbell);
+ if (loc_doorbell) {
+ *cmd = (char)(0xff & loc_doorbell);
+ *channel = cy_readl(&board_ctrl->fwcmd_channel);
+ *param = (uclong) cy_readl(&board_ctrl->fwcmd_param);
+ cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
+ loc_doorbell, 0xffffffff);
+ return 1;
+ }
+ return 0;
+} /* cyz_fetch_msg */
static int
-cyz_issue_cmd( struct cyclades_card *cinfo,
- uclong channel, ucchar cmd, uclong param)
+cyz_issue_cmd(struct cyclades_card *cinfo,
+ uclong channel, ucchar cmd, uclong param)
{
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- unsigned long __iomem *pci_doorbell;
- int index;
-
- firm_id = cinfo->base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo)){
- return (-1);
- }
- zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
-
- index = 0;
- pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell;
- while( (cy_readl(pci_doorbell) & 0xff) != 0){
- if (index++ == 1000){
- return((int)(cy_readl(pci_doorbell) & 0xff));
- }
- udelay(50L);
- }
- cy_writel(&board_ctrl->hcmd_channel, channel);
- cy_writel(&board_ctrl->hcmd_param , param);
- cy_writel(pci_doorbell, (long)cmd);
-
- return(0);
-} /* cyz_issue_cmd */
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ unsigned long __iomem *pci_doorbell;
+ int index;
+
+ firm_id = cinfo->base_addr + ID_ADDRESS;
+ if (!ISZLOADED(*cinfo)) {
+ return -1;
+ }
+ zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+ 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+
+ index = 0;
+ pci_doorbell =
+ &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
+ while ((cy_readl(pci_doorbell) & 0xff) != 0) {
+ if (index++ == 1000) {
+ return (int)(cy_readl(pci_doorbell) & 0xff);
+ }
+ udelay(50L);
+ }
+ cy_writel(&board_ctrl->hcmd_channel, channel);
+ cy_writel(&board_ctrl->hcmd_param, param);
+ cy_writel(pci_doorbell, (long)cmd);
+
+ return 0;
+} /* cyz_issue_cmd */
static void
cyz_handle_rx(struct cyclades_port *info,
- volatile struct CH_CTRL __iomem *ch_ctrl,
- volatile struct BUF_CTRL __iomem *buf_ctrl)
+ volatile struct CH_CTRL __iomem * ch_ctrl,
+ volatile struct BUF_CTRL __iomem * buf_ctrl)
{
- struct cyclades_card *cinfo = &cy_card[info->card];
- struct tty_struct *tty = info->tty;
- volatile int char_count;
- int len;
+ struct cyclades_card *cinfo = &cy_card[info->card];
+ struct tty_struct *tty = info->tty;
+ volatile int char_count;
+ int len;
#ifdef BLOCKMOVE
- int small_count;
+ int small_count;
#else
- char data;
+ char data;
#endif
- volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
+ volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
- rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
- rx_put = cy_readl(&buf_ctrl->rx_put);
- rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
- rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
+ rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
+ rx_put = cy_readl(&buf_ctrl->rx_put);
+ rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+ rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
+ if (rx_put >= rx_get)
+ char_count = rx_put - rx_get;
+ else
+ char_count = rx_put - rx_get + rx_bufsize;
- if ( char_count ) {
- info->last_active = jiffies;
- info->jiffies[1] = jiffies;
+ if (char_count) {
+ info->last_active = jiffies;
+ info->jiffies[1] = jiffies;
#ifdef CY_ENABLE_MONITORING
- info->mon.int_count++;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
+ info->mon.int_count++;
+ info->mon.char_count += char_count;
+ if (char_count > info->mon.char_max)
+ info->mon.char_max = char_count;
+ info->mon.char_last = char_count;
#endif
- if(tty == 0){
- /* flush received characters */
- new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1);
- info->rflush_count++;
- }else{
+ if (tty == 0) {
+ /* flush received characters */
+ new_rx_get = (new_rx_get + char_count) &
+ (rx_bufsize - 1);
+ info->rflush_count++;
+ } else {
#ifdef BLOCKMOVE
- /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
- for performance, but because of buffer boundaries, there
- may be several steps to the operation */
- while(0 < (small_count =
- min_t(unsigned int, (rx_bufsize - new_rx_get),
- min_t(unsigned int, (TTY_FLIPBUF_SIZE - tty->flip.count), char_count))
- )) {
- memcpy_fromio(tty->flip.char_buf_ptr,
- (char *)(cinfo->base_addr
- + rx_bufaddr + new_rx_get),
- small_count);
-
- tty->flip.char_buf_ptr += small_count;
- memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count);
- tty->flip.flag_buf_ptr += small_count;
- new_rx_get = (new_rx_get + small_count) & (rx_bufsize - 1);
- char_count -= small_count;
- info->icount.rx += small_count;
- info->idle_stats.recv_bytes += small_count;
- tty->flip.count += small_count;
- }
+ /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+ for performance, but because of buffer boundaries, there
+ may be several steps to the operation */
+ while (0 < (small_count = min_t(unsigned int,
+ rx_bufsize - new_rx_get,
+ min_t(unsigned int, TTY_FLIPBUF_SIZE -
+ tty->flip.count, char_count)))){
+ memcpy_fromio(tty->flip.char_buf_ptr,
+ (char *)(cinfo->base_addr + rx_bufaddr +
+ new_rx_get),
+ small_count);
+
+ tty->flip.char_buf_ptr += small_count;
+ memset(tty->flip.flag_buf_ptr, TTY_NORMAL,
+ small_count);
+ tty->flip.flag_buf_ptr += small_count;
+ new_rx_get = (new_rx_get + small_count) &
+ (rx_bufsize - 1);
+ char_count -= small_count;
+ info->icount.rx += small_count;
+ info->idle_stats.recv_bytes += small_count;
+ tty->flip.count += small_count;
+ }
#else
- len = tty_buffer_request_room(tty, char_count);
- while(len--){
- data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
- new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
- tty_insert_flip_char(tty, data, TTY_NORMAL);
- info->idle_stats.recv_bytes++;
- info->icount.rx++;
- }
+ len = tty_buffer_request_room(tty, char_count);
+ while (len--) {
+ data = cy_readb(cinfo->base_addr + rx_bufaddr +
+ new_rx_get);
+ new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1);
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
+ info->idle_stats.recv_bytes++;
+ info->icount.rx++;
+ }
#endif
#ifdef CONFIG_CYZ_INTR
- /* Recalculate the number of chars in the RX buffer and issue
- a cmd in case it's higher than the RX high water mark */
- rx_put = cy_readl(&buf_ctrl->rx_put);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
- if(char_count >= cy_readl(&buf_ctrl->rx_threshold)) {
- cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
- }
+ /* Recalculate the number of chars in the RX buffer and issue
+ a cmd in case it's higher than the RX high water mark */
+ rx_put = cy_readl(&buf_ctrl->rx_put);
+ if (rx_put >= rx_get)
+ char_count = rx_put - rx_get;
+ else
+ char_count = rx_put - rx_get + rx_bufsize;
+ if (char_count >= (int)cy_readl(&buf_ctrl->
+ rx_threshold)) {
+ cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
+ }
#endif
- info->idle_stats.recv_idle = jiffies;
- tty_schedule_flip(tty);
+ info->idle_stats.recv_idle = jiffies;
+ tty_schedule_flip(tty);
+ }
+ /* Update rx_get */
+ cy_writel(&buf_ctrl->rx_get, new_rx_get);
}
- /* Update rx_get */
- cy_writel(&buf_ctrl->rx_get, new_rx_get);
- }
}
static void
cyz_handle_tx(struct cyclades_port *info,
- volatile struct CH_CTRL __iomem *ch_ctrl,
- volatile struct BUF_CTRL __iomem *buf_ctrl)
+ volatile struct CH_CTRL __iomem * ch_ctrl,
+ volatile struct BUF_CTRL __iomem * buf_ctrl)
{
- struct cyclades_card *cinfo = &cy_card[info->card];
- struct tty_struct *tty = info->tty;
- char data;
- volatile int char_count;
+ struct cyclades_card *cinfo = &cy_card[info->card];
+ struct tty_struct *tty = info->tty;
+ char data;
+ volatile int char_count;
#ifdef BLOCKMOVE
- int small_count;
+ int small_count;
#endif
- volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
+ volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
- if (info->xmit_cnt <= 0) /* Nothing to transmit */
- return;
+ if (info->xmit_cnt <= 0) /* Nothing to transmit */
+ return;
- tx_get = cy_readl(&buf_ctrl->tx_get);
- tx_put = cy_readl(&buf_ctrl->tx_put);
- tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
- tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
- if (tx_put >= tx_get)
- char_count = tx_get - tx_put - 1 + tx_bufsize;
- else
- char_count = tx_get - tx_put - 1;
+ tx_get = cy_readl(&buf_ctrl->tx_get);
+ tx_put = cy_readl(&buf_ctrl->tx_put);
+ tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+ tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
+ if (tx_put >= tx_get)
+ char_count = tx_get - tx_put - 1 + tx_bufsize;
+ else
+ char_count = tx_get - tx_put - 1;
- if ( char_count ) {
+ if (char_count) {
- if( tty == 0 ){
- goto ztxdone;
- }
+ if (tty == 0) {
+ goto ztxdone;
+ }
- if(info->x_char) { /* send special char */
- data = info->x_char;
+ if (info->x_char) { /* send special char */
+ data = info->x_char;
- cy_writeb((cinfo->base_addr + tx_bufaddr + tx_put), data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- info->x_char = 0;
- char_count--;
- info->icount.tx++;
- info->last_active = jiffies;
- info->jiffies[2] = jiffies;
- }
+ cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+ tx_put = (tx_put + 1) & (tx_bufsize - 1);
+ info->x_char = 0;
+ char_count--;
+ info->icount.tx++;
+ info->last_active = jiffies;
+ info->jiffies[2] = jiffies;
+ }
#ifdef BLOCKMOVE
- while(0 < (small_count =
- min_t(unsigned int, (tx_bufsize - tx_put),
- min_t(unsigned int, (SERIAL_XMIT_SIZE - info->xmit_tail),
- min_t(unsigned int, info->xmit_cnt, char_count))))) {
-
- memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put),
- &info->xmit_buf[info->xmit_tail],
- small_count);
-
- tx_put = (tx_put + small_count) & (tx_bufsize - 1);
- char_count -= small_count;
- info->icount.tx += small_count;
- info->xmit_cnt -= small_count;
- info->xmit_tail =
- (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
- info->last_active = jiffies;
- info->jiffies[2] = jiffies;
- }
+ while (0 < (small_count = min_t(unsigned int,
+ tx_bufsize - tx_put, min_t(unsigned int,
+ (SERIAL_XMIT_SIZE - info->xmit_tail),
+ min_t(unsigned int, info->xmit_cnt,
+ char_count))))) {
+
+ memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
+ tx_put),
+ &info->xmit_buf[info->xmit_tail],
+ small_count);
+
+ tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+ char_count -= small_count;
+ info->icount.tx += small_count;
+ info->xmit_cnt -= small_count;
+ info->xmit_tail = (info->xmit_tail + small_count) &
+ (SERIAL_XMIT_SIZE - 1);
+ info->last_active = jiffies;
+ info->jiffies[2] = jiffies;
+ }
#else
- while (info->xmit_cnt && char_count){
- data = info->xmit_buf[info->xmit_tail];
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
-
- cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- char_count--;
- info->icount.tx++;
- info->last_active = jiffies;
- info->jiffies[2] = jiffies;
- }
+ while (info->xmit_cnt && char_count) {
+ data = info->xmit_buf[info->xmit_tail];
+ info->xmit_cnt--;
+ info->xmit_tail = (info->xmit_tail + 1) &
+ (SERIAL_XMIT_SIZE - 1);
+
+ cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+ tx_put = (tx_put + 1) & (tx_bufsize - 1);
+ char_count--;
+ info->icount.tx++;
+ info->last_active = jiffies;
+ info->jiffies[2] = jiffies;
+ }
#endif
- ztxdone:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+ztxdone:
+ if (info->xmit_cnt < WAKEUP_CHARS) {
+ cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+ }
+ /* Update tx_put */
+ cy_writel(&buf_ctrl->tx_put, tx_put);
}
- /* Update tx_put */
- cy_writel(&buf_ctrl->tx_put, tx_put);
- }
}
-static void
-cyz_handle_cmd(struct cyclades_card *cinfo)
+static void cyz_handle_cmd(struct cyclades_card *cinfo)
{
- struct tty_struct *tty;
- struct cyclades_port *info;
- static volatile struct FIRM_ID __iomem *firm_id;
- static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
- static volatile struct BOARD_CTRL __iomem *board_ctrl;
- static volatile struct CH_CTRL __iomem *ch_ctrl;
- static volatile struct BUF_CTRL __iomem *buf_ctrl;
- uclong channel;
- ucchar cmd;
- uclong param;
- uclong hw_ver, fw_ver;
- int special_count;
- int delta_count;
-
- firm_id = cinfo->base_addr + ID_ADDRESS;
- zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- fw_ver = cy_readl(&board_ctrl->fw_version);
- hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0);
-
-
- while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
- special_count = 0;
- delta_count = 0;
- info = &cy_port[channel + cinfo->first_line];
- if((tty = info->tty) == 0) {
- continue;
- }
- ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
- buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
- switch(cmd) {
- case C_CM_PR_ERROR:
- tty_insert_flip_char(tty, 0, TTY_PARITY);
- info->icount.rx++;
- special_count++;
- break;
- case C_CM_FR_ERROR:
- tty_insert_flip_char(tty, 0, TTY_FRAME);
- info->icount.rx++;
- special_count++;
- break;
- case C_CM_RXBRK:
- tty_insert_flip_char(tty, 0, TTY_BREAK);
- info->icount.rx++;
- special_count++;
- break;
- case C_CM_MDCD:
- info->icount.dcd++;
- delta_count++;
- if (info->flags & ASYNC_CHECK_CD){
- if ((fw_ver > 241 ?
- ((u_long)param) :
- cy_readl(&ch_ctrl->rs_status)) & C_RS_DCD) {
- cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
- }else{
- cy_sched_event(info, Cy_EVENT_HANGUP);
- }
+ struct tty_struct *tty;
+ struct cyclades_port *info;
+ static volatile struct FIRM_ID __iomem *firm_id;
+ static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
+ static volatile struct BOARD_CTRL __iomem *board_ctrl;
+ static volatile struct CH_CTRL __iomem *ch_ctrl;
+ static volatile struct BUF_CTRL __iomem *buf_ctrl;
+ uclong channel;
+ ucchar cmd;
+ uclong param;
+ uclong hw_ver, fw_ver;
+ int special_count;
+ int delta_count;
+
+ firm_id = cinfo->base_addr + ID_ADDRESS;
+ zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+ 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ fw_ver = cy_readl(&board_ctrl->fw_version);
+ hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
+ mail_box_0);
+
+ while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
+ special_count = 0;
+ delta_count = 0;
+ info = &cy_port[channel + cinfo->first_line];
+ if ((tty = info->tty) == 0) {
+ continue;
}
- break;
- case C_CM_MCTS:
- info->icount.cts++;
- delta_count++;
- break;
- case C_CM_MRI:
- info->icount.rng++;
- delta_count++;
- break;
- case C_CM_MDSR:
- info->icount.dsr++;
- delta_count++;
- break;
+ ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+ buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
+
+ switch (cmd) {
+ case C_CM_PR_ERROR:
+ tty_insert_flip_char(tty, 0, TTY_PARITY);
+ info->icount.rx++;
+ special_count++;
+ break;
+ case C_CM_FR_ERROR:
+ tty_insert_flip_char(tty, 0, TTY_FRAME);
+ info->icount.rx++;
+ special_count++;
+ break;
+ case C_CM_RXBRK:
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
+ info->icount.rx++;
+ special_count++;
+ break;
+ case C_CM_MDCD:
+ info->icount.dcd++;
+ delta_count++;
+ if (info->flags & ASYNC_CHECK_CD) {
+ if ((fw_ver > 241 ? ((u_long) param) :
+ cy_readl(&ch_ctrl->rs_status)) &
+ C_RS_DCD) {
+ cy_sched_event(info,
+ Cy_EVENT_OPEN_WAKEUP);
+ } else {
+ cy_sched_event(info, Cy_EVENT_HANGUP);
+ }
+ }
+ break;
+ case C_CM_MCTS:
+ info->icount.cts++;
+ delta_count++;
+ break;
+ case C_CM_MRI:
+ info->icount.rng++;
+ delta_count++;
+ break;
+ case C_CM_MDSR:
+ info->icount.dsr++;
+ delta_count++;
+ break;
#ifdef Z_WAKE
- case C_CM_IOCTLW:
- cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
- break;
+ case C_CM_IOCTLW:
+ cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
+ break;
#endif
#ifdef CONFIG_CYZ_INTR
- case C_CM_RXHIWM:
- case C_CM_RXNNDT:
- case C_CM_INTBACK2:
- /* Reception Interrupt */
+ case C_CM_RXHIWM:
+ case C_CM_RXNNDT:
+ case C_CM_INTBACK2:
+ /* Reception Interrupt */
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r",
- info->card, channel);
+ printk("cyz_interrupt: rcvd intr, card %d, "
+ "port %ld\n\r", info->card, channel);
#endif
- cyz_handle_rx(info, ch_ctrl, buf_ctrl);
- break;
- case C_CM_TXBEMPTY:
- case C_CM_TXLOWWM:
- case C_CM_INTBACK:
- /* Transmission Interrupt */
+ cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+ break;
+ case C_CM_TXBEMPTY:
+ case C_CM_TXLOWWM:
+ case C_CM_INTBACK:
+ /* Transmission Interrupt */
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r",
- info->card, channel);
+ printk("cyz_interrupt: xmit intr, card %d, "
+ "port %ld\n\r", info->card, channel);
#endif
- cyz_handle_tx(info, ch_ctrl, buf_ctrl);
- break;
-#endif /* CONFIG_CYZ_INTR */
- case C_CM_FATAL:
- /* should do something with this !!! */
- break;
- default:
- break;
+ cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+ break;
+#endif /* CONFIG_CYZ_INTR */
+ case C_CM_FATAL:
+ /* should do something with this !!! */
+ break;
+ default:
+ break;
+ }
+ if (delta_count)
+ cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+ if (special_count)
+ tty_schedule_flip(tty);
}
- if(delta_count)
- cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
- if(special_count)
- tty_schedule_flip(tty);
- }
}
#ifdef CONFIG_CYZ_INTR
-static irqreturn_t
-cyz_interrupt(int irq, void *dev_id)
+static irqreturn_t cyz_interrupt(int irq, void *dev_id)
{
- struct cyclades_card *cinfo;
+ struct cyclades_card *cinfo;
- if((cinfo = (struct cyclades_card *)dev_id) == 0){
+ if ((cinfo = (struct cyclades_card *)dev_id) == 0) {
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
+ printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
#endif
- return IRQ_NONE; /* spurious interrupt */
- }
+ return IRQ_NONE; /* spurious interrupt */
+ }
- if (!ISZLOADED(*cinfo)) {
+ if (!ISZLOADED(*cinfo)) {
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq);
+ printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq);
#endif
- return IRQ_NONE;
- }
+ return IRQ_NONE;
+ }
- /* Handle the interrupts */
- cyz_handle_cmd(cinfo);
+ /* Handle the interrupts */
+ cyz_handle_cmd(cinfo);
- return IRQ_HANDLED;
-} /* cyz_interrupt */
+ return IRQ_HANDLED;
+} /* cyz_interrupt */
-static void
-cyz_rx_restart(unsigned long arg)
+static void cyz_rx_restart(unsigned long arg)
{
- struct cyclades_port *info = (struct cyclades_port *)arg;
- int retval;
- int card = info->card;
- uclong channel = (info->line) - (cy_card[card].first_line);
- unsigned long flags;
-
- CY_LOCK(info, flags);
- retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
- if (retval != 0){
- printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n",
- info->line, retval);
- }
- cyz_rx_full_timer[info->line].function = NULL;
- CY_UNLOCK(info, flags);
+ struct cyclades_port *info = (struct cyclades_port *)arg;
+ int retval;
+ int card = info->card;
+ uclong channel = (info->line) - (cy_card[card].first_line);
+ unsigned long flags;
+
+ CY_LOCK(info, flags);
+ retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
+ if (retval != 0) {
+ printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
+ cyz_rx_full_timer[info->line].function = NULL;
+ CY_UNLOCK(info, flags);
}
-#else /* CONFIG_CYZ_INTR */
+#else /* CONFIG_CYZ_INTR */
-static void
-cyz_poll(unsigned long arg)
+static void cyz_poll(unsigned long arg)
{
- struct cyclades_card *cinfo;
- struct cyclades_port *info;
- struct tty_struct *tty;
- static volatile struct FIRM_ID *firm_id;
- static volatile struct ZFW_CTRL *zfw_ctrl;
- static volatile struct BOARD_CTRL *board_ctrl;
- static volatile struct CH_CTRL *ch_ctrl;
- static volatile struct BUF_CTRL *buf_ctrl;
- int card, port;
-
- cyz_timerlist.expires = jiffies + (HZ);
- for (card = 0 ; card < NR_CARDS ; card++){
- cinfo = &cy_card[card];
-
- if (!IS_CYC_Z(*cinfo)) continue;
- if (!ISZLOADED(*cinfo)) continue;
+ struct cyclades_card *cinfo;
+ struct cyclades_port *info;
+ struct tty_struct *tty;
+ static volatile struct FIRM_ID *firm_id;
+ static volatile struct ZFW_CTRL *zfw_ctrl;
+ static volatile struct BOARD_CTRL *board_ctrl;
+ static volatile struct CH_CTRL *ch_ctrl;
+ static volatile struct BUF_CTRL *buf_ctrl;
+ int card, port;
- firm_id = cinfo->base_addr + ID_ADDRESS;
- zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &(zfw_ctrl->board_ctrl);
+ cyz_timerlist.expires = jiffies + (HZ);
+ for (card = 0; card < NR_CARDS; card++) {
+ cinfo = &cy_card[card];
+
+ if (!IS_CYC_Z(*cinfo))
+ continue;
+ if (!ISZLOADED(*cinfo))
+ continue;
+
+ firm_id = cinfo->base_addr + ID_ADDRESS;
+ zfw_ctrl = cinfo->base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &(zfw_ctrl->board_ctrl);
/* Skip first polling cycle to avoid racing conditions with the FW */
- if (!cinfo->intr_enabled) {
- cinfo->nports = (int) cy_readl(&board_ctrl->n_channel);
- cinfo->intr_enabled = 1;
- continue;
- }
+ if (!cinfo->intr_enabled) {
+ cinfo->nports = (int)cy_readl(&board_ctrl->n_channel);
+ cinfo->intr_enabled = 1;
+ continue;
+ }
- cyz_handle_cmd(cinfo);
+ cyz_handle_cmd(cinfo);
- for (port = 0 ; port < cinfo->nports ; port++) {
- info = &cy_port[ port + cinfo->first_line ];
- tty = info->tty;
- ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
- buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
+ for (port = 0; port < cinfo->nports; port++) {
+ info = &cy_port[port + cinfo->first_line];
+ tty = info->tty;
+ ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
+ buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
- if (!info->throttle)
- cyz_handle_rx(info, ch_ctrl, buf_ctrl);
- cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+ if (!info->throttle)
+ cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+ cyz_handle_tx(info, ch_ctrl, buf_ctrl);
+ }
+ /* poll every 'cyz_polling_cycle' period */
+ cyz_timerlist.expires = jiffies + cyz_polling_cycle;
}
- /* poll every 'cyz_polling_cycle' period */
- cyz_timerlist.expires = jiffies + cyz_polling_cycle;
- }
- add_timer(&cyz_timerlist);
+ add_timer(&cyz_timerlist);
+} /* cyz_poll */
- return;
-} /* cyz_poll */
-
-#endif /* CONFIG_CYZ_INTR */
+#endif /* CONFIG_CYZ_INTR */
/********** End of block of Cyclades-Z specific code *********/
/***********************************************************/
-
/* This is called whenever a port becomes active;
interrupts are enabled and DTR & RTS are turned on.
*/
-static int
-startup(struct cyclades_port * info)
+static int startup(struct cyclades_port *info)
{
- unsigned long flags;
- int retval = 0;
- void __iomem *base_addr;
- int card,chip,channel,index;
- unsigned long page;
+ unsigned long flags;
+ int retval = 0;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
+ unsigned long page;
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
- CY_LOCK(info, flags);
+ CY_LOCK(info, flags);
- if (info->flags & ASYNC_INITIALIZED){
- free_page(page);
- goto errout;
- }
+ if (info->flags & ASYNC_INITIALIZED) {
+ free_page(page);
+ goto errout;
+ }
- if (!info->type){
- if (info->tty){
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- free_page(page);
- goto errout;
- }
+ if (!info->type) {
+ if (info->tty) {
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ free_page(page);
+ goto errout;
+ }
- if (info->xmit_buf)
- free_page(page);
- else
- info->xmit_buf = (unsigned char *) page;
+ if (info->xmit_buf)
+ free_page(page);
+ else
+ info->xmit_buf = (unsigned char *)page;
- CY_UNLOCK(info, flags);
+ CY_UNLOCK(info, flags);
- set_line_char(info);
+ set_line_char(info);
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = cy_card[card].base_addr +
+ (cy_chip_offset[chip] << index);
#ifdef CY_DEBUG_OPEN
- printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n",
- card, chip, channel, (long)base_addr);/**/
+ printk("cyc startup card %d, chip %d, channel %d, "
+ "base_addr %lx\n",
+ card, chip, channel, (long)base_addr);
+ /**/
#endif
+ CY_LOCK(info, flags);
- CY_LOCK(info, flags);
-
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
- cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
- ? info->default_timeout : 0x02)); /* 10ms rx timeout */
+ cy_writeb(base_addr + (CyRTPR << index),
+ (info->default_timeout ? info->default_timeout : 0x02));
+ /* 10ms rx timeout */
- cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
+ cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
+ index);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
- cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+ cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
+ cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
#ifdef CY_DEBUG_DTR
- printk("cyc:startup raising DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc:startup raising DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr + (CyMSVR1 << index)),
+ cy_readb(base_addr + (CyMSVR2 << index)));
#endif
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) | CyRxData);
- info->flags |= ASYNC_INITIALIZED;
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) | CyRxData);
+ info->flags |= ASYNC_INITIALIZED;
- if (info->tty){
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- info->breakon = info->breakoff = 0;
- memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
- info->idle_stats.in_use =
- info->idle_stats.recv_idle =
- info->idle_stats.xmit_idle = jiffies;
+ if (info->tty) {
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ info->breakon = info->breakoff = 0;
+ memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+ info->idle_stats.in_use =
+ info->idle_stats.recv_idle =
+ info->idle_stats.xmit_idle = jiffies;
- CY_UNLOCK(info, flags);
+ CY_UNLOCK(info, flags);
- } else {
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
- int retval;
+ } else {
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+ int retval;
- base_addr = cy_card[card].base_addr;
+ base_addr = cy_card[card].base_addr;
- firm_id = base_addr + ID_ADDRESS;
- if (!ISZLOADED(cy_card[card])){
- return -ENODEV;
- }
+ firm_id = base_addr + ID_ADDRESS;
+ if (!ISZLOADED(cy_card[card])) {
+ return -ENODEV;
+ }
- zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- ch_ctrl = zfw_ctrl->ch_ctrl;
+ zfw_ctrl = cy_card[card].base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = zfw_ctrl->ch_ctrl;
#ifdef CY_DEBUG_OPEN
- printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
- card, channel, (long)base_addr);/**/
+ printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
+ card, channel, (long)base_addr);
+ /**/
#endif
+ CY_LOCK(info, flags);
- CY_LOCK(info, flags);
-
- cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
+ cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
#ifdef Z_WAKE
#ifdef CONFIG_CYZ_INTR
- cy_writel(&ch_ctrl[channel].intr_enable,
- C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
- C_IN_IOCTLW|
- C_IN_MDCD);
+ cy_writel(&ch_ctrl[channel].intr_enable,
+ C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
+ C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
#else
- cy_writel(&ch_ctrl[channel].intr_enable,
- C_IN_IOCTLW|
- C_IN_MDCD);
-#endif /* CONFIG_CYZ_INTR */
+ cy_writel(&ch_ctrl[channel].intr_enable,
+ C_IN_IOCTLW | C_IN_MDCD);
+#endif /* CONFIG_CYZ_INTR */
#else
#ifdef CONFIG_CYZ_INTR
- cy_writel(&ch_ctrl[channel].intr_enable,
- C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
- C_IN_MDCD);
+ cy_writel(&ch_ctrl[channel].intr_enable,
+ C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
+ C_IN_RXNNDT | C_IN_MDCD);
#else
- cy_writel(&ch_ctrl[channel].intr_enable,
- C_IN_MDCD);
-#endif /* CONFIG_CYZ_INTR */
-#endif /* Z_WAKE */
-
- retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
- if (retval != 0){
- printk("cyc:startup(1) retval on ttyC%d was %x\n",
- info->line, retval);
- }
+ cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD);
+#endif /* CONFIG_CYZ_INTR */
+#endif /* Z_WAKE */
+
+ retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
+ if (retval != 0) {
+ printk("cyc:startup(1) retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
- /* Flush RX buffers before raising DTR and RTS */
- retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, 0L);
- if (retval != 0){
- printk("cyc:startup(2) retval on ttyC%d was %x\n",
- info->line, retval);
- }
+ /* Flush RX buffers before raising DTR and RTS */
+ retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX,
+ 0L);
+ if (retval != 0) {
+ printk("cyc:startup(2) retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
- /* set timeout !!! */
- /* set RTS and DTR !!! */
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR) ;
- retval = cyz_issue_cmd(&cy_card[info->card],
- channel, C_CM_IOCTLM, 0L);
- if (retval != 0){
- printk("cyc:startup(3) retval on ttyC%d was %x\n",
- info->line, retval);
- }
+ /* set timeout !!! */
+ /* set RTS and DTR !!! */
+ cy_writel(&ch_ctrl[channel].rs_control,
+ cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
+ C_RS_DTR);
+ retval = cyz_issue_cmd(&cy_card[info->card], channel,
+ C_CM_IOCTLM, 0L);
+ if (retval != 0) {
+ printk("cyc:startup(3) retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:startup raising Z DTR\n");
+ printk("cyc:startup raising Z DTR\n");
#endif
- /* enable send, recv, modem !!! */
+ /* enable send, recv, modem !!! */
- info->flags |= ASYNC_INITIALIZED;
- if (info->tty){
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- info->breakon = info->breakoff = 0;
- memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
- info->idle_stats.in_use =
- info->idle_stats.recv_idle =
- info->idle_stats.xmit_idle = jiffies;
+ info->flags |= ASYNC_INITIALIZED;
+ if (info->tty) {
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ info->breakon = info->breakoff = 0;
+ memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+ info->idle_stats.in_use =
+ info->idle_stats.recv_idle =
+ info->idle_stats.xmit_idle = jiffies;
- CY_UNLOCK(info, flags);
- }
+ CY_UNLOCK(info, flags);
+ }
#ifdef CY_DEBUG_OPEN
printk(" cyc startup done\n");
@@ -2094,165 +2154,165 @@ startup(struct cyclades_port * info)
errout:
CY_UNLOCK(info, flags);
return retval;
-} /* startup */
-
+} /* startup */
-static void
-start_xmit( struct cyclades_port *info )
+static void start_xmit(struct cyclades_port *info)
{
- unsigned long flags;
- void __iomem *base_addr;
- int card,chip,channel,index;
-
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ unsigned long flags;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), channel);
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
- CY_UNLOCK(info, flags);
- } else {
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = cy_card[card].base_addr +
+ (cy_chip_offset[chip] << index);
+
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index), channel);
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) | CyTxRdy);
+ CY_UNLOCK(info, flags);
+ } else {
#ifdef CONFIG_CYZ_INTR
- int retval;
+ int retval;
- CY_LOCK(info, flags);
- retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L);
- if (retval != 0){
- printk("cyc:start_xmit retval on ttyC%d was %x\n",
- info->line, retval);
- }
- CY_UNLOCK(info, flags);
-#else /* CONFIG_CYZ_INTR */
- /* Don't have to do anything at this time */
-#endif /* CONFIG_CYZ_INTR */
- }
-} /* start_xmit */
+ CY_LOCK(info, flags);
+ retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK,
+ 0L);
+ if (retval != 0) {
+ printk("cyc:start_xmit retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
+ CY_UNLOCK(info, flags);
+#else /* CONFIG_CYZ_INTR */
+ /* Don't have to do anything at this time */
+#endif /* CONFIG_CYZ_INTR */
+ }
+} /* start_xmit */
/*
* This routine shuts down a serial port; interrupts are disabled,
* and DTR is dropped if the hangup on close termio flag is on.
*/
-static void
-shutdown(struct cyclades_port * info)
+static void shutdown(struct cyclades_port *info)
{
- unsigned long flags;
- void __iomem *base_addr;
- int card,chip,channel,index;
-
- if (!(info->flags & ASYNC_INITIALIZED)){
- return;
- }
-
- card = info->card;
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ unsigned long flags;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
+
+ if (!(info->flags & ASYNC_INITIALIZED)) {
+ return;
+ }
+
+ card = info->card;
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = cy_card[card].base_addr +
+ (cy_chip_offset[chip] << index);
#ifdef CY_DEBUG_OPEN
- printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n",
- card, chip, channel, (long)base_addr);
+ printk("cyc shutdown Y card %d, chip %d, channel %d, "
+ "base_addr %lx\n",
+ card, chip, channel, (long)base_addr);
#endif
- CY_LOCK(info, flags);
+ CY_LOCK(info, flags);
- /* Clear delta_msr_wait queue to avoid mem leaks. */
- wake_up_interruptible(&info->delta_msr_wait);
-
- if (info->xmit_buf){
- unsigned char * temp;
- temp = info->xmit_buf;
- info->xmit_buf = NULL;
- free_page((unsigned long) temp);
- }
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
- cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
- cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
+ /* Clear delta_msr_wait queue to avoid mem leaks. */
+ wake_up_interruptible(&info->delta_msr_wait);
+
+ if (info->xmit_buf) {
+ unsigned char *temp;
+ temp = info->xmit_buf;
+ info->xmit_buf = NULL;
+ free_page((unsigned long)temp);
+ }
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+ cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
+ cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
#ifdef CY_DEBUG_DTR
- printk("cyc shutdown dropping DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc shutdown dropping DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr + (CyMSVR1 << index)),
+ cy_readb(base_addr + (CyMSVR2 << index)));
#endif
- }
- cyy_issue_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR,index);
- /* it may be appropriate to clear _XMIT at
- some later date (after testing)!!! */
-
- if (info->tty){
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- info->flags &= ~ASYNC_INITIALIZED;
- CY_UNLOCK(info, flags);
- } else {
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
- int retval;
-
- base_addr = cy_card[card].base_addr;
+ }
+ cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
+ /* it may be appropriate to clear _XMIT at
+ some later date (after testing)!!! */
+
+ if (info->tty) {
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ info->flags &= ~ASYNC_INITIALIZED;
+ CY_UNLOCK(info, flags);
+ } else {
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+ int retval;
+
+ base_addr = cy_card[card].base_addr;
#ifdef CY_DEBUG_OPEN
- printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
- card, channel, (long)base_addr);
+ printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
+ card, channel, (long)base_addr);
#endif
- firm_id = base_addr + ID_ADDRESS;
- if (!ISZLOADED(cy_card[card])) {
- return;
- }
+ firm_id = base_addr + ID_ADDRESS;
+ if (!ISZLOADED(cy_card[card])) {
+ return;
+ }
- zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- ch_ctrl = zfw_ctrl->ch_ctrl;
+ zfw_ctrl = cy_card[card].base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = zfw_ctrl->ch_ctrl;
- CY_LOCK(info, flags);
+ CY_LOCK(info, flags);
- if (info->xmit_buf){
- unsigned char * temp;
- temp = info->xmit_buf;
- info->xmit_buf = NULL;
- free_page((unsigned long) temp);
- }
-
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
- cy_writel(&ch_ctrl[channel].rs_control,
- (uclong)(cy_readl(&ch_ctrl[channel].rs_control) &
- ~(C_RS_RTS | C_RS_DTR)));
- retval = cyz_issue_cmd(&cy_card[info->card],
- channel, C_CM_IOCTLM, 0L);
- if (retval != 0){
- printk("cyc:shutdown retval on ttyC%d was %x\n",
- info->line, retval);
+ if (info->xmit_buf) {
+ unsigned char *temp;
+ temp = info->xmit_buf;
+ info->xmit_buf = NULL;
+ free_page((unsigned long)temp);
}
+
+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+ cy_writel(&ch_ctrl[channel].rs_control,
+ (uclong)(cy_readl(&ch_ctrl[channel].rs_control)&
+ ~(C_RS_RTS | C_RS_DTR)));
+ retval = cyz_issue_cmd(&cy_card[info->card], channel,
+ C_CM_IOCTLM, 0L);
+ if (retval != 0) {
+ printk("cyc:shutdown retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:shutdown dropping Z DTR\n");
+ printk("cyc:shutdown dropping Z DTR\n");
#endif
- }
-
- if (info->tty){
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- info->flags &= ~ASYNC_INITIALIZED;
+ }
- CY_UNLOCK(info, flags);
- }
+ if (info->tty) {
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ info->flags &= ~ASYNC_INITIALIZED;
+
+ CY_UNLOCK(info, flags);
+ }
#ifdef CY_DEBUG_OPEN
- printk(" cyc shutdown done\n");
+ printk(" cyc shutdown done\n");
#endif
- return;
-} /* shutdown */
-
+} /* shutdown */
/*
* ------------------------------------------------------------
@@ -2261,527 +2321,546 @@ shutdown(struct cyclades_port * info)
*/
static int
-block_til_ready(struct tty_struct *tty, struct file * filp,
- struct cyclades_port *info)
+block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct cyclades_port *info)
{
- DECLARE_WAITQUEUE(wait, current);
- struct cyclades_card *cinfo;
- unsigned long flags;
- int chip, channel,index;
- int retval;
- void __iomem *base_addr;
-
- cinfo = &cy_card[info->card];
- channel = info->line - cinfo->first_line;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
+ DECLARE_WAITQUEUE(wait, current);
+ struct cyclades_card *cinfo;
+ unsigned long flags;
+ int chip, channel, index;
+ int retval;
+ void __iomem *base_addr;
+
+ cinfo = &cy_card[info->card];
+ channel = info->line - cinfo->first_line;
+
+ /*
+ * If the device is in the middle of being closed, then block
+ * until it's done, and then try again.
+ */
+ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING) {
+ interruptible_sleep_on(&info->close_wait);
+ }
+ return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
+ }
+
+ /*
+ * If non-blocking mode is set, then make the check up front
+ * and then exit.
+ */
+ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
}
- return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- }
-
- /*
- * If non-blocking mode is set, then make the check up front
- * and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * cy_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * cy_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
#ifdef CY_DEBUG_OPEN
- printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
- info->line, info->count);/**/
+ printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
+ info->line, info->count);
+ /**/
#endif
- CY_LOCK(info, flags);
- if (!tty_hung_up_p(filp))
- info->count--;
- CY_UNLOCK(info, flags);
+ CY_LOCK(info, flags);
+ if (!tty_hung_up_p(filp))
+ info->count--;
+ CY_UNLOCK(info, flags);
#ifdef CY_DEBUG_COUNT
- printk("cyc block_til_ready: (%d): decrementing count to %d\n",
- current->pid, info->count);
+ printk("cyc block_til_ready: (%d): decrementing count to %d\n",
+ current->pid, info->count);
#endif
- info->blocked_open++;
-
- if (!IS_CYC_Z(*cinfo)) {
- chip = channel>>2;
- channel &= 0x03;
- index = cinfo->bus_index;
- base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
-
- while (1) {
- CY_LOCK(info, flags);
- if ((tty->termios->c_cflag & CBAUD)){
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
- cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
+ info->blocked_open++;
+
+ if (!IS_CYC_Z(*cinfo)) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cinfo->bus_index;
+ base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
+
+ while (1) {
+ CY_LOCK(info, flags);
+ if ((tty->termios->c_cflag & CBAUD)) {
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ CyRTS);
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ CyDTR);
#ifdef CY_DEBUG_DTR
- printk("cyc:block_til_ready raising DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc:block_til_ready raising DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr +
+ (CyMSVR1 << index)),
+ cy_readb(base_addr +
+ (CyMSVR2 << index)));
#endif
- }
- CY_UNLOCK(info, flags);
+ }
+ CY_UNLOCK(info, flags);
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp)
- || !(info->flags & ASYNC_INITIALIZED) ){
- retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- break;
- }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ASYNC_INITIALIZED)) {
+ retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+ break;
+ }
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (!(info->flags & ASYNC_CLOSING)
- && (C_CLOCAL(tty)
- || (cy_readb(base_addr+(CyMSVR1<<index)) & CyDCD))) {
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
+ (cy_readb(base_addr +
+ (CyMSVR1 << index)) & CyDCD))) {
+ CY_UNLOCK(info, flags);
+ break;
+ }
CY_UNLOCK(info, flags);
- break;
- }
- CY_UNLOCK(info, flags);
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
#ifdef CY_DEBUG_OPEN
- printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
- info->line, info->count);/**/
+ printk("cyc block_til_ready blocking: ttyC%d, "
+ "count = %d\n",
+ info->line, info->count);
+ /**/
#endif
- schedule();
- }
- } else {
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
- int retval;
-
- base_addr = cinfo->base_addr;
- firm_id = base_addr + ID_ADDRESS;
- if (!ISZLOADED(*cinfo)){
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- return -EINVAL;
- }
-
- zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- ch_ctrl = zfw_ctrl->ch_ctrl;
-
- while (1) {
- if ((tty->termios->c_cflag & CBAUD)){
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) |
- (C_RS_RTS | C_RS_DTR));
- retval = cyz_issue_cmd(&cy_card[info->card],
- channel, C_CM_IOCTLM, 0L);
- if (retval != 0){
- printk("cyc:block_til_ready retval on ttyC%d was %x\n",
- info->line, retval);
+ schedule();
+ }
+ } else {
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+ int retval;
+
+ base_addr = cinfo->base_addr;
+ firm_id = base_addr + ID_ADDRESS;
+ if (!ISZLOADED(*cinfo)) {
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ return -EINVAL;
}
+
+ zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) &
+ 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = zfw_ctrl->ch_ctrl;
+
+ while (1) {
+ if ((tty->termios->c_cflag & CBAUD)) {
+ cy_writel(&ch_ctrl[channel].rs_control,
+ cy_readl(&ch_ctrl[channel].
+ rs_control) | (C_RS_RTS |
+ C_RS_DTR));
+ retval = cyz_issue_cmd(&cy_card[info->card],
+ channel, C_CM_IOCTLM, 0L);
+ if (retval != 0) {
+ printk("cyc:block_til_ready retval on "
+ "ttyC%d was %x\n",
+ info->line, retval);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:block_til_ready raising Z DTR\n");
+ printk("cyc:block_til_ready raising Z DTR\n");
#endif
- }
+ }
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp)
- || !(info->flags & ASYNC_INITIALIZED) ){
- retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- break;
- }
- if (!(info->flags & ASYNC_CLOSING)
- && (C_CLOCAL(tty)
- || (cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD))) {
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ASYNC_INITIALIZED)) {
+ retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+ break;
+ }
+ if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
+ (cy_readl(&ch_ctrl[channel].rs_status) &
+ C_RS_DCD))) {
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
#ifdef CY_DEBUG_OPEN
- printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
- info->line, info->count);/**/
+ printk("cyc block_til_ready blocking: ttyC%d, "
+ "count = %d\n",
+ info->line, info->count);
+ /**/
#endif
- schedule();
+ schedule();
+ }
}
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp)){
- info->count++;
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ if (!tty_hung_up_p(filp)) {
+ info->count++;
#ifdef CY_DEBUG_COUNT
- printk("cyc:block_til_ready (%d): incrementing count to %d\n",
- current->pid, info->count);
+ printk("cyc:block_til_ready (%d): incrementing count to %d\n",
+ current->pid, info->count);
#endif
- }
- info->blocked_open--;
+ }
+ info->blocked_open--;
#ifdef CY_DEBUG_OPEN
- printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
- info->line, info->count);/**/
+ printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
+ info->line, info->count);
+ /**/
#endif
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-} /* block_til_ready */
-
+ if (retval)
+ return retval;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+} /* block_til_ready */
/*
* This routine is called whenever a serial port is opened. It
* performs the serial-specific initialization for the tty structure.
*/
-static int
-cy_open(struct tty_struct *tty, struct file * filp)
+static int cy_open(struct tty_struct *tty, struct file *filp)
{
- struct cyclades_port *info;
- int retval, line;
-
- line = tty->index;
- if ((line < 0) || (NR_PORTS <= line)){
- return -ENODEV;
- }
- info = &cy_port[line];
- if (info->line < 0){
- return -ENODEV;
- }
-
- /* If the card's firmware hasn't been loaded,
- treat it as absent from the system. This
- will make the user pay attention.
- */
- if (IS_CYC_Z(cy_card[info->card])) {
- struct cyclades_card *cinfo = &cy_card[info->card];
- struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
-
- if (!ISZLOADED(*cinfo)) {
- if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *)
- (cinfo->ctl_addr))->mail_box_0)) &&
- Z_FPGA_CHECK (*cinfo)) &&
- (ZFIRM_HLT == cy_readl (&firm_id->signature)))
- {
- printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n");
- } else {
- printk("cyc:Cyclades-Z firmware not yet loaded\n");
- }
- return -ENODEV;
- }
-#ifdef CONFIG_CYZ_INTR
- else {
- /* In case this Z board is operating in interrupt mode, its
- interrupts should be enabled as soon as the first open happens
- to one of its ports. */
- if (!cinfo->intr_enabled) {
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
-
- zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff);
+ struct cyclades_port *info;
+ int retval, line;
- board_ctrl = &zfw_ctrl->board_ctrl;
+ line = tty->index;
+ if ((line < 0) || (NR_PORTS <= line)) {
+ return -ENODEV;
+ }
+ info = &cy_port[line];
+ if (info->line < 0) {
+ return -ENODEV;
+ }
- /* Enable interrupts on the PLX chip */
- cy_writew(cinfo->ctl_addr+0x68,
- cy_readw(cinfo->ctl_addr+0x68)|0x0900);
- /* Enable interrupts on the FW */
- retval = cyz_issue_cmd(cinfo,
- 0, C_CM_IRQ_ENBL, 0L);
- if (retval != 0){
- printk("cyc:IRQ enable retval was %x\n", retval);
+ /* If the card's firmware hasn't been loaded,
+ treat it as absent from the system. This
+ will make the user pay attention.
+ */
+ if (IS_CYC_Z(cy_card[info->card])) {
+ struct cyclades_card *cinfo = &cy_card[info->card];
+ struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
+
+ if (!ISZLOADED(*cinfo)) {
+ if (((ZE_V1 == cy_readl(
+ &((struct RUNTIME_9060 __iomem *)
+ (cinfo->ctl_addr))->mail_box_0)) &&
+ Z_FPGA_CHECK(*cinfo)) &&
+ (ZFIRM_HLT == cy_readl(
+ &firm_id->signature))) {
+ printk("cyc:Cyclades-Z Error: you need an "
+ "external power supply for this number "
+ "of ports.\n\rFirmware halted.\r\n");
+ } else {
+ printk("cyc:Cyclades-Z firmware not yet "
+ "loaded\n");
+ }
+ return -ENODEV;
}
- cinfo->nports = (int) cy_readl (&board_ctrl->n_channel);
- cinfo->intr_enabled = 1;
- }
+#ifdef CONFIG_CYZ_INTR
+ else {
+ /* In case this Z board is operating in interrupt mode, its
+ interrupts should be enabled as soon as the first open
+ happens to one of its ports. */
+ if (!cinfo->intr_enabled) {
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+
+ zfw_ctrl = cinfo->base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) &
+ 0xfffff);
+
+ board_ctrl = &zfw_ctrl->board_ctrl;
+
+ /* Enable interrupts on the PLX chip */
+ cy_writew(cinfo->ctl_addr + 0x68,
+ cy_readw(cinfo->ctl_addr +
+ 0x68) | 0x0900);
+ /* Enable interrupts on the FW */
+ retval = cyz_issue_cmd(cinfo, 0,
+ C_CM_IRQ_ENBL, 0L);
+ if (retval != 0) {
+ printk("cyc:IRQ enable retval was %x\n",
+ retval);
+ }
+ cinfo->nports =
+ (int)cy_readl(&board_ctrl->n_channel);
+ cinfo->intr_enabled = 1;
+ }
+ }
+#endif /* CONFIG_CYZ_INTR */
+ /* Make sure this Z port really exists in hardware */
+ if (info->line > (cinfo->first_line + cinfo->nports - 1))
+ return -ENODEV;
}
-#endif /* CONFIG_CYZ_INTR */
- /* Make sure this Z port really exists in hardware */
- if (info->line > (cinfo->first_line + cinfo->nports - 1))
- return -ENODEV;
- }
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_open ttyC%d\n", info->line); /* */
+ printk("cyc:cy_open ttyC%d\n", info->line); /* */
#endif
- tty->driver_data = info;
- info->tty = tty;
- if (serial_paranoia_check(info, tty->name, "cy_open")){
- return -ENODEV;
- }
+ tty->driver_data = info;
+ info->tty = tty;
+ if (serial_paranoia_check(info, tty->name, "cy_open")) {
+ return -ENODEV;
+ }
#ifdef CY_DEBUG_OPEN
- printk("cyc:cy_open ttyC%d, count = %d\n",
- info->line, info->count);/**/
+ printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count);
+ /**/
#endif
- info->count++;
+ info->count++;
#ifdef CY_DEBUG_COUNT
- printk("cyc:cy_open (%d): incrementing count to %d\n",
- current->pid, info->count);
+ printk("cyc:cy_open (%d): incrementing count to %d\n",
+ current->pid, info->count);
#endif
- /*
- * If the port is the middle of closing, bail out now
- */
- if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
- return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- }
-
- /*
- * Start up serial port
- */
- retval = startup(info);
- if (retval){
- return retval;
- }
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
-#ifdef CY_DEBUG_OPEN
- printk("cyc:cy_open returning after block_til_ready with %d\n",
- retval);
-#endif
- return retval;
- }
+ /*
+ * If the port is the middle of closing, bail out now
+ */
+ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
+ }
- info->throttle = 0;
+ /*
+ * Start up serial port
+ */
+ retval = startup(info);
+ if (retval) {
+ return retval;
+ }
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
#ifdef CY_DEBUG_OPEN
- printk(" cyc:cy_open done\n");/**/
+ printk("cyc:cy_open returning after block_til_ready with %d\n",
+ retval);
#endif
+ return retval;
+ }
- return 0;
-} /* cy_open */
+ info->throttle = 0;
+#ifdef CY_DEBUG_OPEN
+ printk(" cyc:cy_open done\n");
+ /**/
+#endif
+ return 0;
+} /* cy_open */
/*
* cy_wait_until_sent() --- wait until the transmitter is empty
*/
-static void
-cy_wait_until_sent(struct tty_struct *tty, int timeout)
+static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
- void __iomem *base_addr;
- int card,chip,channel,index;
- unsigned long orig_jiffies;
- int char_time;
-
- if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
- return;
-
- if (info->xmit_fifo_size == 0)
- return; /* Just in case.... */
-
-
- orig_jiffies = jiffies;
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
- char_time = char_time / 5;
- if (char_time <= 0)
- char_time = 1;
- if (timeout < 0)
- timeout = 0;
- if (timeout)
- char_time = min(char_time, timeout);
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than info->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*info->timeout.
- */
- if (!timeout || timeout > 2*info->timeout)
- timeout = 2*info->timeout;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
+ unsigned long orig_jiffies;
+ int char_time;
+
+ if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
+ return;
+
+ if (info->xmit_fifo_size == 0)
+ return; /* Just in case.... */
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
+ char_time = char_time / 5;
+ if (char_time <= 0)
+ char_time = 1;
+ if (timeout < 0)
+ timeout = 0;
+ if (timeout)
+ char_time = min(char_time, timeout);
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than info->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*info->timeout.
+ */
+ if (!timeout || timeout > 2 * info->timeout)
+ timeout = 2 * info->timeout;
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
- printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
- printk("jiff=%lu...", jiffies);
+ printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
+ printk("jiff=%lu...", jiffies);
#endif
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
- while (cy_readb(base_addr+(CySRER<<index)) & CyTxRdy) {
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+ while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) {
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
- printk("Not clean (jiff=%lu)...", jiffies);
+ printk("Not clean (jiff=%lu)...", jiffies);
#endif
- if (msleep_interruptible(jiffies_to_msecs(char_time)))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
+ if (msleep_interruptible(jiffies_to_msecs(char_time)))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies +
+ timeout))
+ break;
+ }
+ } else {
+ /* Nothing to do! */
}
- } else {
- // Nothing to do!
- }
- /* Run one more char cycle */
- msleep_interruptible(jiffies_to_msecs(char_time * 5));
+ /* Run one more char cycle */
+ msleep_interruptible(jiffies_to_msecs(char_time * 5));
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
- printk("Clean (jiff=%lu)...done\n", jiffies);
+ printk("Clean (jiff=%lu)...done\n", jiffies);
#endif
}
/*
* This routine is called when a particular tty device is closed.
*/
-static void
-cy_close(struct tty_struct *tty, struct file *filp)
+static void cy_close(struct tty_struct *tty, struct file *filp)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- unsigned long flags;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_close ttyC%d\n", info->line);
+ printk("cyc:cy_close ttyC%d\n", info->line);
#endif
- if (!info || serial_paranoia_check(info, tty->name, "cy_close")){
- return;
- }
+ if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
+ return;
+ }
- CY_LOCK(info, flags);
- /* If the TTY is being hung up, nothing to do */
- if (tty_hung_up_p(filp)) {
- CY_UNLOCK(info, flags);
- return;
- }
-
+ CY_LOCK(info, flags);
+ /* If the TTY is being hung up, nothing to do */
+ if (tty_hung_up_p(filp)) {
+ CY_UNLOCK(info, flags);
+ return;
+ }
#ifdef CY_DEBUG_OPEN
- printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
+ printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
#endif
- 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("cyc:cy_close: bad serial port count; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
- }
+ 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("cyc:cy_close: bad serial port count; tty->count is 1, "
+ "info->count is %d\n", info->count);
+ info->count = 1;
+ }
#ifdef CY_DEBUG_COUNT
- printk("cyc:cy_close at (%d): decrementing count to %d\n",
- current->pid, info->count - 1);
+ printk("cyc:cy_close at (%d): decrementing count to %d\n",
+ current->pid, info->count - 1);
#endif
- if (--info->count < 0) {
+ if (--info->count < 0) {
#ifdef CY_DEBUG_COUNT
- printk("cyc:cyc_close setting count to 0\n");
+ printk("cyc:cyc_close setting count to 0\n");
#endif
- info->count = 0;
- }
- if (info->count) {
- CY_UNLOCK(info, flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
-
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- CY_UNLOCK(info, flags);
- if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
- tty_wait_until_sent(tty, info->closing_wait);
- }
- CY_LOCK(info, flags);
-
- if (!IS_CYC_Z(cy_card[info->card])) {
- int channel = info->line - cy_card[info->card].first_line;
- int index = cy_card[info->card].bus_index;
- void __iomem *base_addr = cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] << index);
- /* Stop accepting input */
- channel &= 0x03;
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
- if (info->flags & ASYNC_INITIALIZED) {
- /* Waiting for on-board buffers to be empty before closing
- the port */
- CY_UNLOCK(info, flags);
- cy_wait_until_sent(tty, info->timeout);
- CY_LOCK(info, flags);
+ info->count = 0;
}
- } else {
-#ifdef Z_WAKE
- /* Waiting for on-board buffers to be empty before closing the port */
- void __iomem *base_addr = cy_card[info->card].base_addr;
- struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
- struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
- int channel = info->line - cy_card[info->card].first_line;
- int retval;
+ if (info->count) {
+ CY_UNLOCK(info, flags);
+ return;
+ }
+ info->flags |= ASYNC_CLOSING;
- if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
- retval = cyz_issue_cmd(&cy_card[info->card], channel,
- C_CM_IOCTLW, 0L);
- if (retval != 0){
- printk("cyc:cy_close retval on ttyC%d was %x\n",
- info->line, retval);
- }
- CY_UNLOCK(info, flags);
- interruptible_sleep_on(&info->shutdown_wait);
- CY_LOCK(info, flags);
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ CY_UNLOCK(info, flags);
+ if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
+ tty_wait_until_sent(tty, info->closing_wait);
}
+ CY_LOCK(info, flags);
+
+ if (!IS_CYC_Z(cy_card[info->card])) {
+ int channel = info->line - cy_card[info->card].first_line;
+ int index = cy_card[info->card].bus_index;
+ void __iomem *base_addr = cy_card[info->card].base_addr +
+ (cy_chip_offset[channel >> 2] << index);
+ /* Stop accepting input */
+ channel &= 0x03;
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) & ~CyRxData);
+ if (info->flags & ASYNC_INITIALIZED) {
+ /* Waiting for on-board buffers to be empty before closing
+ the port */
+ CY_UNLOCK(info, flags);
+ cy_wait_until_sent(tty, info->timeout);
+ CY_LOCK(info, flags);
+ }
+ } else {
+#ifdef Z_WAKE
+ /* Waiting for on-board buffers to be empty before closing the port */
+ void __iomem *base_addr = cy_card[info->card].base_addr;
+ struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
+ struct ZFW_CTRL __iomem *zfw_ctrl =
+ base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
+ int channel = info->line - cy_card[info->card].first_line;
+ int retval;
+
+ if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
+ retval = cyz_issue_cmd(&cy_card[info->card], channel,
+ C_CM_IOCTLW, 0L);
+ if (retval != 0) {
+ printk("cyc:cy_close retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
+ CY_UNLOCK(info, flags);
+ interruptible_sleep_on(&info->shutdown_wait);
+ CY_LOCK(info, flags);
+ }
#endif
- }
-
- CY_UNLOCK(info, flags);
- shutdown(info);
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
- tty_ldisc_flush(tty);
- CY_LOCK(info, flags);
-
- tty->closing = 0;
- info->event = 0;
- info->tty = NULL;
- if (info->blocked_open) {
+ }
+
CY_UNLOCK(info, flags);
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
+ shutdown(info);
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ tty_ldisc_flush(tty);
CY_LOCK(info, flags);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
+
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = NULL;
+ if (info->blocked_open) {
+ CY_UNLOCK(info, flags);
+ if (info->close_delay) {
+ msleep_interruptible(jiffies_to_msecs
+ (info->close_delay));
+ }
+ wake_up_interruptible(&info->open_wait);
+ CY_LOCK(info, flags);
+ }
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+ wake_up_interruptible(&info->close_wait);
#ifdef CY_DEBUG_OTHER
- printk(" cyc:cy_close done\n");
+ printk(" cyc:cy_close done\n");
#endif
- CY_UNLOCK(info, flags);
- return;
-} /* cy_close */
-
+ CY_UNLOCK(info, flags);
+} /* cy_close */
/* This routine gets called when tty_write has put something into
* the write_queue. The characters may come from user space or
@@ -2796,50 +2875,49 @@ cy_close(struct tty_struct *tty, struct file *filp)
* If the port is already active, there is no need to kick it.
*
*/
-static int
-cy_write(struct tty_struct * tty, const unsigned char *buf, int count)
+static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- unsigned long flags;
- int c, ret = 0;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
+ int c, ret = 0;
#ifdef CY_DEBUG_IO
- printk("cyc:cy_write ttyC%d\n", info->line); /* */
+ printk("cyc:cy_write ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_write")){
- return 0;
- }
-
- if (!info->xmit_buf)
- return 0;
+ if (serial_paranoia_check(info, tty->name, "cy_write")) {
+ return 0;
+ }
- CY_LOCK(info, flags);
- while (1) {
- c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
- (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
-
- if (c <= 0)
- break;
-
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt += c;
- buf += c;
- count -= c;
- ret += c;
- }
- CY_UNLOCK(info, flags);
-
- info->idle_stats.xmit_bytes += ret;
- info->idle_stats.xmit_idle = jiffies;
-
- if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
- start_xmit(info);
- }
- return ret;
-} /* cy_write */
+ if (!info->xmit_buf)
+ return 0;
+ CY_LOCK(info, flags);
+ while (1) {
+ c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
+ (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
+
+ if (c <= 0)
+ break;
+
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = (info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE - 1);
+ info->xmit_cnt += c;
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ CY_UNLOCK(info, flags);
+
+ info->idle_stats.xmit_bytes += ret;
+ info->idle_stats.xmit_idle = jiffies;
+
+ if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+ start_xmit(info);
+ }
+ return ret;
+} /* cy_write */
/*
* This routine is called by the kernel to write a single
@@ -2848,60 +2926,56 @@ cy_write(struct tty_struct * tty, const unsigned char *buf, int count)
* done stuffing characters into the driver. If there is no room
* in the queue, the character is ignored.
*/
-static void
-cy_put_char(struct tty_struct *tty, unsigned char ch)
+static void cy_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- unsigned long flags;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
#ifdef CY_DEBUG_IO
- printk("cyc:cy_put_char ttyC%d\n", info->line);
+ printk("cyc:cy_put_char ttyC%d\n", info->line);
#endif
- if (serial_paranoia_check(info, tty->name, "cy_put_char"))
- return;
+ if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+ return;
- if (!info->xmit_buf)
- return;
+ if (!info->xmit_buf)
+ return;
- CY_LOCK(info, flags);
- if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
- CY_UNLOCK(info, flags);
- return;
- }
+ CY_LOCK(info, flags);
+ if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
+ CY_UNLOCK(info, flags);
+ return;
+ }
- info->xmit_buf[info->xmit_head++] = ch;
- info->xmit_head &= SERIAL_XMIT_SIZE - 1;
- info->xmit_cnt++;
+ info->xmit_buf[info->xmit_head++] = ch;
+ info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+ info->xmit_cnt++;
info->idle_stats.xmit_bytes++;
info->idle_stats.xmit_idle = jiffies;
- CY_UNLOCK(info, flags);
-} /* cy_put_char */
-
+ CY_UNLOCK(info, flags);
+} /* cy_put_char */
/*
* This routine is called by the kernel after it has written a
* series of characters to the tty device using put_char().
*/
-static void
-cy_flush_chars(struct tty_struct *tty)
+static void cy_flush_chars(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+
#ifdef CY_DEBUG_IO
- printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */
+ printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
- return;
-
- if (info->xmit_cnt <= 0 || tty->stopped
- || tty->hw_stopped || !info->xmit_buf)
- return;
+ if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
+ return;
- start_xmit(info);
-} /* cy_flush_chars */
+ if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+ !info->xmit_buf)
+ return;
+ start_xmit(info);
+} /* cy_flush_chars */
/*
* This routine returns the numbers of characters the tty driver
@@ -2909,75 +2983,70 @@ cy_flush_chars(struct tty_struct *tty)
* to change as output buffers get emptied, or if the output flow
* control is activated.
*/
-static int
-cy_write_room(struct tty_struct *tty)
+static int cy_write_room(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- int ret;
-
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ int ret;
+
#ifdef CY_DEBUG_IO
- printk("cyc:cy_write_room ttyC%d\n", info->line); /* */
+ printk("cyc:cy_write_room ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_write_room"))
- return 0;
- ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
- if (ret < 0)
- ret = 0;
- return ret;
-} /* cy_write_room */
-
+ if (serial_paranoia_check(info, tty->name, "cy_write_room"))
+ return 0;
+ ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+ if (ret < 0)
+ ret = 0;
+ return ret;
+} /* cy_write_room */
-static int
-cy_chars_in_buffer(struct tty_struct *tty)
+static int cy_chars_in_buffer(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- int card, channel;
-
- if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
- return 0;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ int card, channel;
+
+ if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
+ return 0;
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
#ifdef Z_EXT_CHARS_IN_BUFFER
- if (!IS_CYC_Z(cy_card[card])) {
-#endif /* Z_EXT_CHARS_IN_BUFFER */
+ if (!IS_CYC_Z(cy_card[card])) {
+#endif /* Z_EXT_CHARS_IN_BUFFER */
#ifdef CY_DEBUG_IO
- printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
- info->line, info->xmit_cnt); /* */
+ printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */
#endif
- return info->xmit_cnt;
+ return info->xmit_cnt;
#ifdef Z_EXT_CHARS_IN_BUFFER
- } else {
- static volatile struct FIRM_ID *firm_id;
- static volatile struct ZFW_CTRL *zfw_ctrl;
- static volatile struct CH_CTRL *ch_ctrl;
- static volatile struct BUF_CTRL *buf_ctrl;
- int char_count;
- volatile uclong tx_put, tx_get, tx_bufsize;
-
- firm_id = cy_card[card].base_addr + ID_ADDRESS;
- zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
- buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
- tx_get = cy_readl(&buf_ctrl->tx_get);
- tx_put = cy_readl(&buf_ctrl->tx_put);
- tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
- if (tx_put >= tx_get)
- char_count = tx_put - tx_get;
- else
- char_count = tx_put - tx_get + tx_bufsize;
+ } else {
+ static volatile struct FIRM_ID *firm_id;
+ static volatile struct ZFW_CTRL *zfw_ctrl;
+ static volatile struct CH_CTRL *ch_ctrl;
+ static volatile struct BUF_CTRL *buf_ctrl;
+ int char_count;
+ volatile uclong tx_put, tx_get, tx_bufsize;
+
+ firm_id = cy_card[card].base_addr + ID_ADDRESS;
+ zfw_ctrl = cy_card[card].base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+ buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
+
+ tx_get = cy_readl(&buf_ctrl->tx_get);
+ tx_put = cy_readl(&buf_ctrl->tx_put);
+ tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+ if (tx_put >= tx_get)
+ char_count = tx_put - tx_get;
+ else
+ char_count = tx_put - tx_get + tx_bufsize;
#ifdef CY_DEBUG_IO
- printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
- info->line, info->xmit_cnt + char_count); /* */
+ printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count); /* */
#endif
- return (info->xmit_cnt + char_count);
- }
-#endif /* Z_EXT_CHARS_IN_BUFFER */
-} /* cy_chars_in_buffer */
-
+ return info->xmit_cnt + char_count;
+ }
+#endif /* Z_EXT_CHARS_IN_BUFFER */
+} /* cy_chars_in_buffer */
/*
* ------------------------------------------------------------
@@ -2985,178 +3054,179 @@ cy_chars_in_buffer(struct tty_struct *tty)
* ------------------------------------------------------------
*/
-static void
-cyy_baud_calc(struct cyclades_port *info, uclong baud)
+static void cyy_baud_calc(struct cyclades_port *info, uclong baud)
{
- int co, co_val, bpr;
- uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000);
-
- if (baud == 0) {
- info->tbpr = info->tco = info->rbpr = info->rco = 0;
- return;
- }
-
- /* determine which prescaler to use */
- for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
- if (cy_clock / co_val / baud > 63)
- break;
- }
-
- bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
- if (bpr > 255)
- bpr = 255;
-
- info->tbpr = info->rbpr = bpr;
- info->tco = info->rco = co;
+ int co, co_val, bpr;
+ uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
+ 25000000);
+
+ if (baud == 0) {
+ info->tbpr = info->tco = info->rbpr = info->rco = 0;
+ return;
+ }
+
+ /* determine which prescaler to use */
+ for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
+ if (cy_clock / co_val / baud > 63)
+ break;
+ }
+
+ bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
+ if (bpr > 255)
+ bpr = 255;
+
+ info->tbpr = info->rbpr = bpr;
+ info->tco = info->rco = co;
}
/*
* This routine finds or computes the various line characteristics.
* It used to be called config_setup
*/
-static void
-set_line_char(struct cyclades_port * info)
+static void set_line_char(struct cyclades_port *info)
{
- unsigned long flags;
- void __iomem *base_addr;
- int card,chip,channel,index;
- unsigned cflag, iflag;
- unsigned short chip_number;
- int baud, baud_rate = 0;
- int i;
-
-
- if (!info->tty || !info->tty->termios){
- return;
- }
- if (info->line == -1){
- return;
- }
- cflag = info->tty->termios->c_cflag;
- iflag = info->tty->termios->c_iflag;
-
- /*
- * Set up the tty->alt_speed kludge
- */
- if (info->tty) {
- 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;
- }
-
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
- chip_number = channel / 4;
-
- if (!IS_CYC_Z(cy_card[card])) {
-
- index = cy_card[card].bus_index;
-
- /* baud rate */
- baud = tty_get_baud_rate(info->tty);
- if ((baud == 38400) &&
- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
- if (info->custom_divisor)
- baud_rate = info->baud / info->custom_divisor;
- else
- baud_rate = info->baud;
- } else if (baud > CD1400_MAX_SPEED) {
- baud = CD1400_MAX_SPEED;
+ unsigned long flags;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
+ unsigned cflag, iflag;
+ unsigned short chip_number;
+ int baud, baud_rate = 0;
+ int i;
+
+ if (!info->tty || !info->tty->termios) {
+ return;
}
- /* find the baud index */
- for (i = 0; i < 20; i++) {
- if (baud == baud_table[i]) {
- break;
- }
+ if (info->line == -1) {
+ return;
}
- if (i == 20) {
- i = 19; /* CD1400_MAX_SPEED */
- }
+ cflag = info->tty->termios->c_cflag;
+ iflag = info->tty->termios->c_iflag;
- if ((baud == 38400) &&
- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
- cyy_baud_calc(info, baud_rate);
- } else {
- if(info->chip_rev >= CD1400_REV_J) {
- /* It is a CD1400 rev. J or later */
- info->tbpr = baud_bpr_60[i]; /* Tx BPR */
- info->tco = baud_co_60[i]; /* Tx CO */
- info->rbpr = baud_bpr_60[i]; /* Rx BPR */
- info->rco = baud_co_60[i]; /* Rx CO */
- } else {
- info->tbpr = baud_bpr_25[i]; /* Tx BPR */
- info->tco = baud_co_25[i]; /* Tx CO */
- info->rbpr = baud_bpr_25[i]; /* Rx BPR */
- info->rco = baud_co_25[i]; /* Rx CO */
- }
- }
- if (baud_table[i] == 134) {
- /* get it right for 134.5 baud */
- info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
- } else if ((baud == 38400) &&
- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
- info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2;
- } else if (baud_table[i]) {
- info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
- /* this needs to be propagated into the card info */
- } else {
- info->timeout = 0;
- }
- /* By tradition (is it a standard?) a baud rate of zero
- implies the line should be/has been closed. A bit
- later in this routine such a test is performed. */
-
- /* byte size and parity */
- info->cor5 = 0;
- info->cor4 = 0;
- info->cor3 = (info->default_threshold
- ? info->default_threshold
- : baud_cor3[i]); /* receive threshold */
- info->cor2 = CyETC;
- switch(cflag & CSIZE){
- case CS5:
- info->cor1 = Cy_5_BITS;
- break;
- case CS6:
- info->cor1 = Cy_6_BITS;
- break;
- case CS7:
- info->cor1 = Cy_7_BITS;
- break;
- case CS8:
- info->cor1 = Cy_8_BITS;
- break;
- }
- if(cflag & CSTOPB){
- info->cor1 |= Cy_2_STOP;
- }
- if (cflag & PARENB){
- if (cflag & PARODD){
- info->cor1 |= CyPARITY_O;
- }else{
- info->cor1 |= CyPARITY_E;
- }
- }else{
- info->cor1 |= CyPARITY_NONE;
- }
-
- /* CTS flow control flag */
- if (cflag & CRTSCTS){
- info->flags |= ASYNC_CTS_FLOW;
- info->cor2 |= CyCtsAE;
- }else{
- info->flags &= ~ASYNC_CTS_FLOW;
- info->cor2 &= ~CyCtsAE;
+ /*
+ * Set up the tty->alt_speed kludge
+ */
+ if (info->tty) {
+ 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;
}
- if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
- else
- info->flags |= ASYNC_CHECK_CD;
+
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ chip_number = channel / 4;
+
+ if (!IS_CYC_Z(cy_card[card])) {
+
+ index = cy_card[card].bus_index;
+
+ /* baud rate */
+ baud = tty_get_baud_rate(info->tty);
+ if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+ ASYNC_SPD_CUST) {
+ if (info->custom_divisor)
+ baud_rate = info->baud / info->custom_divisor;
+ else
+ baud_rate = info->baud;
+ } else if (baud > CD1400_MAX_SPEED) {
+ baud = CD1400_MAX_SPEED;
+ }
+ /* find the baud index */
+ for (i = 0; i < 20; i++) {
+ if (baud == baud_table[i]) {
+ break;
+ }
+ }
+ if (i == 20) {
+ i = 19; /* CD1400_MAX_SPEED */
+ }
+
+ if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+ ASYNC_SPD_CUST) {
+ cyy_baud_calc(info, baud_rate);
+ } else {
+ if (info->chip_rev >= CD1400_REV_J) {
+ /* It is a CD1400 rev. J or later */
+ info->tbpr = baud_bpr_60[i]; /* Tx BPR */
+ info->tco = baud_co_60[i]; /* Tx CO */
+ info->rbpr = baud_bpr_60[i]; /* Rx BPR */
+ info->rco = baud_co_60[i]; /* Rx CO */
+ } else {
+ info->tbpr = baud_bpr_25[i]; /* Tx BPR */
+ info->tco = baud_co_25[i]; /* Tx CO */
+ info->rbpr = baud_bpr_25[i]; /* Rx BPR */
+ info->rco = baud_co_25[i]; /* Rx CO */
+ }
+ }
+ if (baud_table[i] == 134) {
+ /* get it right for 134.5 baud */
+ info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
+ 2;
+ } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+ ASYNC_SPD_CUST) {
+ info->timeout = (info->xmit_fifo_size * HZ * 15 /
+ baud_rate) + 2;
+ } else if (baud_table[i]) {
+ info->timeout = (info->xmit_fifo_size * HZ * 15 /
+ baud_table[i]) + 2;
+ /* this needs to be propagated into the card info */
+ } else {
+ info->timeout = 0;
+ }
+ /* By tradition (is it a standard?) a baud rate of zero
+ implies the line should be/has been closed. A bit
+ later in this routine such a test is performed. */
+
+ /* byte size and parity */
+ info->cor5 = 0;
+ info->cor4 = 0;
+ /* receive threshold */
+ info->cor3 = (info->default_threshold ?
+ info->default_threshold : baud_cor3[i]);
+ info->cor2 = CyETC;
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->cor1 = Cy_5_BITS;
+ break;
+ case CS6:
+ info->cor1 = Cy_6_BITS;
+ break;
+ case CS7:
+ info->cor1 = Cy_7_BITS;
+ break;
+ case CS8:
+ info->cor1 = Cy_8_BITS;
+ break;
+ }
+ if (cflag & CSTOPB) {
+ info->cor1 |= Cy_2_STOP;
+ }
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ info->cor1 |= CyPARITY_O;
+ } else {
+ info->cor1 |= CyPARITY_E;
+ }
+ } else {
+ info->cor1 |= CyPARITY_NONE;
+ }
+
+ /* CTS flow control flag */
+ if (cflag & CRTSCTS) {
+ info->flags |= ASYNC_CTS_FLOW;
+ info->cor2 |= CyCtsAE;
+ } else {
+ info->flags &= ~ASYNC_CTS_FLOW;
+ info->cor2 &= ~CyCtsAE;
+ }
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+ else
+ info->flags |= ASYNC_CHECK_CD;
/***********************************************
The hardware option, CyRtsAO, presents RTS when
@@ -3168,300 +3238,319 @@ set_line_char(struct cyclades_port * info)
cable. Contact Marcio Saito for details.
***********************************************/
- chip = channel>>2;
- channel &= 0x03;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ chip = channel >> 2;
+ channel &= 0x03;
+ base_addr = cy_card[card].base_addr +
+ (cy_chip_offset[chip] << index);
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
-
- /* tx and rx baud rate */
-
- cy_writeb(base_addr+(CyTCOR<<index), info->tco);
- cy_writeb(base_addr+(CyTBPR<<index), info->tbpr);
- cy_writeb(base_addr+(CyRCOR<<index), info->rco);
- cy_writeb(base_addr+(CyRBPR<<index), info->rbpr);
-
- /* set line characteristics according configuration */
-
- cy_writeb(base_addr+(CySCHR1<<index),
- START_CHAR(info->tty));
- cy_writeb(base_addr+(CySCHR2<<index),
- STOP_CHAR(info->tty));
- cy_writeb(base_addr+(CyCOR1<<index), info->cor1);
- cy_writeb(base_addr+(CyCOR2<<index), info->cor2);
- cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
- cy_writeb(base_addr+(CyCOR4<<index), info->cor4);
- cy_writeb(base_addr+(CyCOR5<<index), info->cor5);
-
- cyy_issue_cmd(base_addr,
- CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index);
-
- cy_writeb(base_addr+(CyCAR<<index),
- (u_char)channel); /* !!! Is this needed? */
- cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
- ? info->default_timeout
- : 0x02)); /* 10ms rx timeout */
-
- if (C_CLOCAL(info->tty)) {
- /* without modem intr */
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) | CyMdmCh);
- /* act on 1->0 modem transitions */
- if ((cflag & CRTSCTS) && info->rflow) {
- cy_writeb(base_addr+(CyMCOR1<<index),
- (CyCTS|rflow_thr[i]));
- } else {
- cy_writeb(base_addr+(CyMCOR1<<index), CyCTS);
- }
- /* act on 0->1 modem transitions */
- cy_writeb(base_addr+(CyMCOR2<<index), CyCTS);
- } else {
- /* without modem intr */
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) | CyMdmCh);
- /* act on 1->0 modem transitions */
- if ((cflag & CRTSCTS) && info->rflow) {
- cy_writeb(base_addr+(CyMCOR1<<index),
- (CyDSR|CyCTS|CyRI|CyDCD|rflow_thr[i]));
- } else {
- cy_writeb(base_addr+(CyMCOR1<<index),
- CyDSR|CyCTS|CyRI|CyDCD);
- }
- /* act on 0->1 modem transitions */
- cy_writeb(base_addr+(CyMCOR2<<index),
- CyDSR|CyCTS|CyRI|CyDCD);
- }
-
- if(i == 0){ /* baud rate is zero, turn off line */
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+
+ /* tx and rx baud rate */
+
+ cy_writeb(base_addr + (CyTCOR << index), info->tco);
+ cy_writeb(base_addr + (CyTBPR << index), info->tbpr);
+ cy_writeb(base_addr + (CyRCOR << index), info->rco);
+ cy_writeb(base_addr + (CyRBPR << index), info->rbpr);
+
+ /* set line characteristics according configuration */
+
+ cy_writeb(base_addr + (CySCHR1 << index),
+ START_CHAR(info->tty));
+ cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->tty));
+ cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
+ cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
+ cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
+ cy_writeb(base_addr + (CyCOR4 << index), info->cor4);
+ cy_writeb(base_addr + (CyCOR5 << index), info->cor5);
+
+ cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
+ CyCOR3ch, index);
+
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel); /* !!! Is this needed? */
+ cy_writeb(base_addr + (CyRTPR << index),
+ (info->default_timeout ? info->default_timeout : 0x02));
+ /* 10ms rx timeout */
+
+ if (C_CLOCAL(info->tty)) {
+ /* without modem intr */
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr +
+ (CySRER << index)) | CyMdmCh);
+ /* act on 1->0 modem transitions */
+ if ((cflag & CRTSCTS) && info->rflow) {
+ cy_writeb(base_addr + (CyMCOR1 << index),
+ (CyCTS | rflow_thr[i]));
+ } else {
+ cy_writeb(base_addr + (CyMCOR1 << index),
+ CyCTS);
+ }
+ /* act on 0->1 modem transitions */
+ cy_writeb(base_addr + (CyMCOR2 << index), CyCTS);
} else {
- cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
+ /* without modem intr */
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr +
+ (CySRER << index)) | CyMdmCh);
+ /* act on 1->0 modem transitions */
+ if ((cflag & CRTSCTS) && info->rflow) {
+ cy_writeb(base_addr + (CyMCOR1 << index),
+ (CyDSR | CyCTS | CyRI | CyDCD |
+ rflow_thr[i]));
+ } else {
+ cy_writeb(base_addr + (CyMCOR1 << index),
+ CyDSR | CyCTS | CyRI | CyDCD);
+ }
+ /* act on 0->1 modem transitions */
+ cy_writeb(base_addr + (CyMCOR2 << index),
+ CyDSR | CyCTS | CyRI | CyDCD);
}
+
+ if (i == 0) { /* baud rate is zero, turn off line */
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ ~CyRTS);
+ } else {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ ~CyDTR);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:set_line_char dropping DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc:set_line_char dropping DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr + (CyMSVR1 << index)),
+ cy_readb(base_addr + (CyMSVR2 << index)));
#endif
- }else{
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
- } else {
- cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
- }
+ } else {
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ CyRTS);
+ } else {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ CyDTR);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:set_line_char raising DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc:set_line_char raising DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr + (CyMSVR1 << index)),
+ cy_readb(base_addr + (CyMSVR2 << index)));
#endif
- }
-
- if (info->tty){
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- }
- CY_UNLOCK(info, flags);
+ }
- } else {
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
- struct BUF_CTRL __iomem *buf_ctrl;
- uclong sw_flow;
- int retval;
-
- firm_id = cy_card[card].base_addr + ID_ADDRESS;
- if (!ISZLOADED(cy_card[card])) {
- return;
- }
+ if (info->tty) {
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ CY_UNLOCK(info, flags);
- zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
- buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
-
- /* baud rate */
- baud = tty_get_baud_rate(info->tty);
- if ((baud == 38400) &&
- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
- if (info->custom_divisor)
- baud_rate = info->baud / info->custom_divisor;
- else
- baud_rate = info->baud;
- } else if (baud > CYZ_MAX_SPEED) {
- baud = CYZ_MAX_SPEED;
- }
- cy_writel(&ch_ctrl->comm_baud , baud);
-
- if (baud == 134) {
- /* get it right for 134.5 baud */
- info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
- } else if ((baud == 38400) &&
- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) {
- info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2;
- } else if (baud) {
- info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2;
- /* this needs to be propagated into the card info */
} else {
- info->timeout = 0;
- }
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+ struct BUF_CTRL __iomem *buf_ctrl;
+ uclong sw_flow;
+ int retval;
+
+ firm_id = cy_card[card].base_addr + ID_ADDRESS;
+ if (!ISZLOADED(cy_card[card])) {
+ return;
+ }
- /* byte size and parity */
- switch(cflag & CSIZE){
- case CS5: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS5); break;
- case CS6: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS6); break;
- case CS7: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS7); break;
- case CS8: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS8); break;
- }
- if(cflag & CSTOPB){
- cy_writel(&ch_ctrl->comm_data_l,
- cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
- }else{
- cy_writel(&ch_ctrl->comm_data_l,
- cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
- }
- if (cflag & PARENB){
- if (cflag & PARODD){
- cy_writel(&ch_ctrl->comm_parity , C_PR_ODD);
- }else{
- cy_writel(&ch_ctrl->comm_parity , C_PR_EVEN);
- }
- }else{
- cy_writel(&ch_ctrl->comm_parity , C_PR_NONE);
- }
+ zfw_ctrl = cy_card[card].base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+ buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
+
+ /* baud rate */
+ baud = tty_get_baud_rate(info->tty);
+ if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+ ASYNC_SPD_CUST) {
+ if (info->custom_divisor)
+ baud_rate = info->baud / info->custom_divisor;
+ else
+ baud_rate = info->baud;
+ } else if (baud > CYZ_MAX_SPEED) {
+ baud = CYZ_MAX_SPEED;
+ }
+ cy_writel(&ch_ctrl->comm_baud, baud);
+
+ if (baud == 134) {
+ /* get it right for 134.5 baud */
+ info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
+ 2;
+ } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
+ ASYNC_SPD_CUST) {
+ info->timeout = (info->xmit_fifo_size * HZ * 15 /
+ baud_rate) + 2;
+ } else if (baud) {
+ info->timeout = (info->xmit_fifo_size * HZ * 15 /
+ baud) + 2;
+ /* this needs to be propagated into the card info */
+ } else {
+ info->timeout = 0;
+ }
- /* CTS flow control flag */
- if (cflag & CRTSCTS){
- cy_writel(&ch_ctrl->hw_flow,
- cy_readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
- }else{
- cy_writel(&ch_ctrl->hw_flow,
- cy_readl(&ch_ctrl->hw_flow) & ~(C_RS_CTS | C_RS_RTS));
- }
- /* As the HW flow control is done in firmware, the driver doesn't
- need to care about it */
- info->flags &= ~ASYNC_CTS_FLOW;
-
- /* XON/XOFF/XANY flow control flags */
- sw_flow = 0;
- if (iflag & IXON){
- sw_flow |= C_FL_OXX;
- if (iflag & IXANY)
- sw_flow |= C_FL_OIXANY;
- }
- cy_writel(&ch_ctrl->sw_flow, sw_flow);
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5:
+ cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
+ break;
+ case CS6:
+ cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
+ break;
+ case CS7:
+ cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
+ break;
+ case CS8:
+ cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
+ break;
+ }
+ if (cflag & CSTOPB) {
+ cy_writel(&ch_ctrl->comm_data_l,
+ cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
+ } else {
+ cy_writel(&ch_ctrl->comm_data_l,
+ cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
+ }
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
+ } else {
+ cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
+ }
+ } else {
+ cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
+ }
- retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
- if (retval != 0){
- printk("cyc:set_line_char retval on ttyC%d was %x\n",
- info->line, retval);
- }
+ /* CTS flow control flag */
+ if (cflag & CRTSCTS) {
+ cy_writel(&ch_ctrl->hw_flow,
+ cy_readl(&ch_ctrl->
+ hw_flow) | C_RS_CTS | C_RS_RTS);
+ } else {
+ cy_writel(&ch_ctrl->hw_flow,
+ cy_readl(&ch_ctrl->
+ hw_flow) & ~(C_RS_CTS | C_RS_RTS));
+ }
+ /* As the HW flow control is done in firmware, the driver
+ doesn't need to care about it */
+ info->flags &= ~ASYNC_CTS_FLOW;
+
+ /* XON/XOFF/XANY flow control flags */
+ sw_flow = 0;
+ if (iflag & IXON) {
+ sw_flow |= C_FL_OXX;
+ if (iflag & IXANY)
+ sw_flow |= C_FL_OIXANY;
+ }
+ cy_writel(&ch_ctrl->sw_flow, sw_flow);
- /* CD sensitivity */
- if (cflag & CLOCAL){
- info->flags &= ~ASYNC_CHECK_CD;
- }else{
- info->flags |= ASYNC_CHECK_CD;
- }
+ retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
+ if (retval != 0) {
+ printk("cyc:set_line_char retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
+
+ /* CD sensitivity */
+ if (cflag & CLOCAL) {
+ info->flags &= ~ASYNC_CHECK_CD;
+ } else {
+ info->flags |= ASYNC_CHECK_CD;
+ }
- if(baud == 0){ /* baud rate is zero, turn off line */
- cy_writel(&ch_ctrl->rs_control,
- cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
+ if (baud == 0) { /* baud rate is zero, turn off line */
+ cy_writel(&ch_ctrl->rs_control,
+ cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
#ifdef CY_DEBUG_DTR
- printk("cyc:set_line_char dropping Z DTR\n");
+ printk("cyc:set_line_char dropping Z DTR\n");
#endif
- }else{
- cy_writel(&ch_ctrl->rs_control,
- cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
+ } else {
+ cy_writel(&ch_ctrl->rs_control,
+ cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
#ifdef CY_DEBUG_DTR
- printk("cyc:set_line_char raising Z DTR\n");
+ printk("cyc:set_line_char raising Z DTR\n");
#endif
- }
+ }
- retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L);
- if (retval != 0){
- printk("cyc:set_line_char(2) retval on ttyC%d was %x\n",
- info->line, retval);
- }
+ retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L);
+ if (retval != 0) {
+ printk("cyc:set_line_char(2) retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
- if (info->tty){
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (info->tty) {
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
}
- }
-} /* set_line_char */
-
+} /* set_line_char */
static int
-get_serial_info(struct cyclades_port * info,
- struct serial_struct __user * retinfo)
+get_serial_info(struct cyclades_port *info,
+ struct serial_struct __user * retinfo)
{
- struct serial_struct tmp;
- struct cyclades_card *cinfo = &cy_card[info->card];
-
- if (!retinfo)
- return -EFAULT;
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = info->type;
- tmp.line = info->line;
- tmp.port = info->card * 0x100 + info->line - cinfo->first_line;
- tmp.irq = cinfo->irq;
- tmp.flags = info->flags;
- tmp.close_delay = info->close_delay;
- tmp.baud_base = info->baud;
- tmp.custom_divisor = info->custom_divisor;
- tmp.hub6 = 0; /*!!!*/
- return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0;
-} /* get_serial_info */
+ struct serial_struct tmp;
+ struct cyclades_card *cinfo = &cy_card[info->card];
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = info->type;
+ tmp.line = info->line;
+ tmp.port = info->card * 0x100 + info->line - cinfo->first_line;
+ tmp.irq = cinfo->irq;
+ tmp.flags = info->flags;
+ tmp.close_delay = info->close_delay;
+ tmp.baud_base = info->baud;
+ tmp.custom_divisor = info->custom_divisor;
+ tmp.hub6 = 0; /*!!! */
+ return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+} /* get_serial_info */
static int
-set_serial_info(struct cyclades_port * info,
- struct serial_struct __user * new_info)
+set_serial_info(struct cyclades_port *info,
+ struct serial_struct __user * new_info)
{
- struct serial_struct new_serial;
- struct cyclades_port old_info;
-
- if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
- return -EFAULT;
- old_info = *info;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((new_serial.close_delay != info->close_delay) ||
- (new_serial.baud_base != info->baud) ||
- ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
- (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
- return -EPERM;
- info->flags = ((info->flags & ~ASYNC_USR_MASK) |
- (new_serial.flags & ASYNC_USR_MASK));
- info->baud = new_serial.baud_base;
- info->custom_divisor = new_serial.custom_divisor;
- goto check_and_exit;
- }
-
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
-
- info->baud = new_serial.baud_base;
- info->custom_divisor = new_serial.custom_divisor;
- info->flags = ((info->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
- info->close_delay = new_serial.close_delay * HZ/100;
- info->closing_wait = new_serial.closing_wait * HZ/100;
+ struct serial_struct new_serial;
+ struct cyclades_port old_info;
+
+ if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+ return -EFAULT;
+ old_info = *info;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (new_serial.close_delay != info->close_delay ||
+ new_serial.baud_base != info->baud ||
+ (new_serial.flags & ASYNC_FLAGS &
+ ~ASYNC_USR_MASK) !=
+ (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
+ return -EPERM;
+ info->flags = (info->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK);
+ info->baud = new_serial.baud_base;
+ info->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+
+ info->baud = new_serial.baud_base;
+ info->custom_divisor = new_serial.custom_divisor;
+ info->flags = (info->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS);
+ info->close_delay = new_serial.close_delay * HZ / 100;
+ info->closing_wait = new_serial.closing_wait * HZ / 100;
check_and_exit:
- if (info->flags & ASYNC_INITIALIZED){
- set_line_char(info);
- return 0;
- }else{
- return startup(info);
- }
-} /* set_serial_info */
+ if (info->flags & ASYNC_INITIALIZED) {
+ set_line_char(info);
+ return 0;
+ } else {
+ return startup(info);
+ }
+} /* set_serial_info */
/*
* get_lsr_info - get line status register info
@@ -3473,441 +3562,452 @@ check_and_exit:
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
+static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value)
{
- int card, chip, channel, index;
- unsigned char status;
- unsigned int result;
- unsigned long flags;
- void __iomem *base_addr;
-
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ int card, chip, channel, index;
+ unsigned char status;
+ unsigned int result;
+ unsigned long flags;
+ void __iomem *base_addr;
- CY_LOCK(info, flags);
- status = cy_readb(base_addr+(CySRER<<index)) & (CyTxRdy|CyTxMpty);
- CY_UNLOCK(info, flags);
- result = (status ? 0 : TIOCSER_TEMT);
- } else {
- /* Not supported yet */
- return -EINVAL;
- }
- return put_user(result, (unsigned long __user *) value);
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+ CY_LOCK(info, flags);
+ status = cy_readb(base_addr + (CySRER << index)) &
+ (CyTxRdy | CyTxMpty);
+ CY_UNLOCK(info, flags);
+ result = (status ? 0 : TIOCSER_TEMT);
+ } else {
+ /* Not supported yet */
+ return -EINVAL;
+ }
+ return put_user(result, (unsigned long __user *)value);
}
-static int
-cy_tiocmget(struct tty_struct *tty, struct file *file)
+static int cy_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
- int card,chip,channel,index;
- void __iomem *base_addr;
- unsigned long flags;
- unsigned char status;
- unsigned long lstatus;
- unsigned int result;
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
-
- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
- return -ENODEV;
-
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ int card, chip, channel, index;
+ void __iomem *base_addr;
+ unsigned long flags;
+ unsigned char status;
+ unsigned long lstatus;
+ unsigned int result;
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- status = cy_readb(base_addr+(CyMSVR1<<index));
- status |= cy_readb(base_addr+(CyMSVR2<<index));
- CY_UNLOCK(info, flags);
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
- if (info->rtsdtr_inv) {
- result = ((status & CyRTS) ? TIOCM_DTR : 0)
- | ((status & CyDTR) ? TIOCM_RTS : 0);
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+ status = cy_readb(base_addr + (CyMSVR1 << index));
+ status |= cy_readb(base_addr + (CyMSVR2 << index));
+ CY_UNLOCK(info, flags);
+
+ if (info->rtsdtr_inv) {
+ result = ((status & CyRTS) ? TIOCM_DTR : 0) |
+ ((status & CyDTR) ? TIOCM_RTS : 0);
+ } else {
+ result = ((status & CyRTS) ? TIOCM_RTS : 0) |
+ ((status & CyDTR) ? TIOCM_DTR : 0);
+ }
+ result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
+ ((status & CyRI) ? TIOCM_RNG : 0) |
+ ((status & CyDSR) ? TIOCM_DSR : 0) |
+ ((status & CyCTS) ? TIOCM_CTS : 0);
} else {
- result = ((status & CyRTS) ? TIOCM_RTS : 0)
- | ((status & CyDTR) ? TIOCM_DTR : 0);
- }
- result |= ((status & CyDCD) ? TIOCM_CAR : 0)
- | ((status & CyRI) ? TIOCM_RNG : 0)
- | ((status & CyDSR) ? TIOCM_DSR : 0)
- | ((status & CyCTS) ? TIOCM_CTS : 0);
- } else {
- base_addr = cy_card[card].base_addr;
-
- if (cy_card[card].num_chips != -1){
- return -EINVAL;
- }
+ base_addr = cy_card[card].base_addr;
- firm_id = cy_card[card].base_addr + ID_ADDRESS;
- if (ISZLOADED(cy_card[card])) {
- zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- ch_ctrl = zfw_ctrl->ch_ctrl;
- lstatus = cy_readl(&ch_ctrl[channel].rs_status);
- result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0)
- | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0)
- | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0)
- | ((lstatus & C_RS_RI) ? TIOCM_RNG : 0)
- | ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0)
- | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
- }else{
- result = 0;
- return -ENODEV;
- }
+ if (cy_card[card].num_chips != -1) {
+ return -EINVAL;
+ }
- }
- return result;
-} /* cy_tiomget */
+ firm_id = cy_card[card].base_addr + ID_ADDRESS;
+ if (ISZLOADED(cy_card[card])) {
+ zfw_ctrl = cy_card[card].base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = zfw_ctrl->ch_ctrl;
+ lstatus = cy_readl(&ch_ctrl[channel].rs_status);
+ result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
+ ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
+ ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
+ ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
+ ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
+ ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
+ } else {
+ result = 0;
+ return -ENODEV;
+ }
+ }
+ return result;
+} /* cy_tiomget */
static int
cy_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
- int card,chip,channel,index;
- void __iomem *base_addr;
- unsigned long flags;
- struct FIRM_ID __iomem *firm_id;
- struct ZFW_CTRL __iomem *zfw_ctrl;
- struct BOARD_CTRL __iomem *board_ctrl;
- struct CH_CTRL __iomem *ch_ctrl;
- int retval;
-
- if (serial_paranoia_check(info, tty->name, __FUNCTION__))
- return -ENODEV;
-
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
- if (set & TIOCM_RTS){
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
- } else {
- cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
- }
- CY_UNLOCK(info, flags);
- }
- if (clear & TIOCM_RTS) {
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
- } else {
- cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
- }
- CY_UNLOCK(info, flags);
- }
- if (set & TIOCM_DTR){
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
- } else {
- cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
- }
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ int card, chip, channel, index;
+ void __iomem *base_addr;
+ unsigned long flags;
+ struct FIRM_ID __iomem *firm_id;
+ struct ZFW_CTRL __iomem *zfw_ctrl;
+ struct BOARD_CTRL __iomem *board_ctrl;
+ struct CH_CTRL __iomem *ch_ctrl;
+ int retval;
+
+ if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+ return -ENODEV;
+
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+ if (set & TIOCM_RTS) {
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ CyDTR);
+ } else {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ CyRTS);
+ }
+ CY_UNLOCK(info, flags);
+ }
+ if (clear & TIOCM_RTS) {
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ ~CyDTR);
+ } else {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ ~CyRTS);
+ }
+ CY_UNLOCK(info, flags);
+ }
+ if (set & TIOCM_DTR) {
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ CyRTS);
+ } else {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ CyDTR);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info raising DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc:set_modem_info raising DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr + (CyMSVR1 << index)),
+ cy_readb(base_addr + (CyMSVR2 << index)));
#endif
- CY_UNLOCK(info, flags);
- }
- if (clear & TIOCM_DTR) {
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
- } else {
- cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
- }
+ CY_UNLOCK(info, flags);
+ }
+ if (clear & TIOCM_DTR) {
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ ~CyRTS);
+ } else {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ ~CyDTR);
+ }
#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info dropping DTR\n");
- printk(" status: 0x%x, 0x%x\n",
- cy_readb(base_addr+(CyMSVR1<<index)),
- cy_readb(base_addr+(CyMSVR2<<index)));
+ printk("cyc:set_modem_info dropping DTR\n");
+ printk(" status: 0x%x, 0x%x\n",
+ cy_readb(base_addr + (CyMSVR1 << index)),
+ cy_readb(base_addr + (CyMSVR2 << index)));
#endif
- CY_UNLOCK(info, flags);
- }
- } else {
- base_addr = cy_card[card].base_addr;
-
- firm_id = cy_card[card].base_addr + ID_ADDRESS;
- if (ISZLOADED(cy_card[card])) {
- zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
- board_ctrl = &zfw_ctrl->board_ctrl;
- ch_ctrl = zfw_ctrl->ch_ctrl;
-
- if (set & TIOCM_RTS){
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS);
- CY_UNLOCK(info, flags);
- }
- if (clear & TIOCM_RTS) {
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS);
- CY_UNLOCK(info, flags);
- }
- if (set & TIOCM_DTR){
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
+ CY_UNLOCK(info, flags);
+ }
+ } else {
+ base_addr = cy_card[card].base_addr;
+
+ firm_id = cy_card[card].base_addr + ID_ADDRESS;
+ if (ISZLOADED(cy_card[card])) {
+ zfw_ctrl = cy_card[card].base_addr +
+ (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+ board_ctrl = &zfw_ctrl->board_ctrl;
+ ch_ctrl = zfw_ctrl->ch_ctrl;
+
+ if (set & TIOCM_RTS) {
+ CY_LOCK(info, flags);
+ cy_writel(&ch_ctrl[channel].rs_control,
+ cy_readl(&ch_ctrl[channel].
+ rs_control) | C_RS_RTS);
+ CY_UNLOCK(info, flags);
+ }
+ if (clear & TIOCM_RTS) {
+ CY_LOCK(info, flags);
+ cy_writel(&ch_ctrl[channel].rs_control,
+ cy_readl(&ch_ctrl[channel].
+ rs_control) & ~C_RS_RTS);
+ CY_UNLOCK(info, flags);
+ }
+ if (set & TIOCM_DTR) {
+ CY_LOCK(info, flags);
+ cy_writel(&ch_ctrl[channel].rs_control,
+ cy_readl(&ch_ctrl[channel].
+ rs_control) | C_RS_DTR);
#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info raising Z DTR\n");
+ printk("cyc:set_modem_info raising Z DTR\n");
#endif
- CY_UNLOCK(info, flags);
- }
- if (clear & TIOCM_DTR) {
- CY_LOCK(info, flags);
- cy_writel(&ch_ctrl[channel].rs_control,
- cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
+ CY_UNLOCK(info, flags);
+ }
+ if (clear & TIOCM_DTR) {
+ CY_LOCK(info, flags);
+ cy_writel(&ch_ctrl[channel].rs_control,
+ cy_readl(&ch_ctrl[channel].
+ rs_control) & ~C_RS_DTR);
#ifdef CY_DEBUG_DTR
- printk("cyc:set_modem_info clearing Z DTR\n");
+ printk("cyc:set_modem_info clearing Z DTR\n");
#endif
- CY_UNLOCK(info, flags);
- }
- }else{
- return -ENODEV;
- }
- CY_LOCK(info, flags);
- retval = cyz_issue_cmd(&cy_card[info->card],
- channel, C_CM_IOCTLM,0L);
- if (retval != 0){
- printk("cyc:set_modem_info retval on ttyC%d was %x\n",
- info->line, retval);
+ CY_UNLOCK(info, flags);
+ }
+ } else {
+ return -ENODEV;
+ }
+ CY_LOCK(info, flags);
+ retval = cyz_issue_cmd(&cy_card[info->card],
+ channel, C_CM_IOCTLM, 0L);
+ if (retval != 0) {
+ printk("cyc:set_modem_info retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
+ CY_UNLOCK(info, flags);
}
- CY_UNLOCK(info, flags);
- }
- return 0;
-} /* cy_tiocmset */
+ return 0;
+} /* cy_tiocmset */
/*
* cy_break() --- routine which turns the break handling on or off
*/
-static void
-cy_break(struct tty_struct *tty, int break_state)
+static void cy_break(struct tty_struct *tty, int break_state)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, "cy_break"))
- return;
-
- CY_LOCK(info, flags);
- if (!IS_CYC_Z(cy_card[info->card])) {
- /* Let the transmit ISR take care of this (since it
- requires stuffing characters into the output stream).
- */
- if (break_state == -1) {
- if (!info->breakon) {
- info->breakon = 1;
- if (!info->xmit_cnt) {
- CY_UNLOCK(info, flags);
- start_xmit(info);
- CY_LOCK(info, flags);
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
+
+ if (serial_paranoia_check(info, tty->name, "cy_break"))
+ return;
+
+ CY_LOCK(info, flags);
+ if (!IS_CYC_Z(cy_card[info->card])) {
+ /* Let the transmit ISR take care of this (since it
+ requires stuffing characters into the output stream).
+ */
+ if (break_state == -1) {
+ if (!info->breakon) {
+ info->breakon = 1;
+ if (!info->xmit_cnt) {
+ CY_UNLOCK(info, flags);
+ start_xmit(info);
+ CY_LOCK(info, flags);
+ }
+ }
+ } else {
+ if (!info->breakoff) {
+ info->breakoff = 1;
+ if (!info->xmit_cnt) {
+ CY_UNLOCK(info, flags);
+ start_xmit(info);
+ CY_LOCK(info, flags);
+ }
+ }
}
- }
} else {
- if (!info->breakoff) {
- info->breakoff = 1;
- if (!info->xmit_cnt) {
- CY_UNLOCK(info, flags);
- start_xmit(info);
- CY_LOCK(info, flags);
+ int retval;
+
+ if (break_state == -1) {
+ retval = cyz_issue_cmd(&cy_card[info->card],
+ info->line - cy_card[info->card].first_line,
+ C_CM_SET_BREAK, 0L);
+ if (retval != 0) {
+ printk("cyc:cy_break (set) retval on ttyC%d "
+ "was %x\n", info->line, retval);
+ }
+ } else {
+ retval = cyz_issue_cmd(&cy_card[info->card],
+ info->line - cy_card[info->card].first_line,
+ C_CM_CLR_BREAK, 0L);
+ if (retval != 0) {
+ printk("cyc:cy_break (clr) retval on ttyC%d "
+ "was %x\n", info->line, retval);
+ }
}
- }
- }
- } else {
- int retval;
-
- if (break_state == -1) {
- retval = cyz_issue_cmd(&cy_card[info->card],
- (info->line) - (cy_card[info->card].first_line),
- C_CM_SET_BREAK, 0L);
- if (retval != 0) {
- printk("cyc:cy_break (set) retval on ttyC%d was %x\n",
- info->line, retval);
- }
- } else {
- retval = cyz_issue_cmd(&cy_card[info->card],
- (info->line) - (cy_card[info->card].first_line),
- C_CM_CLR_BREAK, 0L);
- if (retval != 0) {
- printk("cyc:cy_break (clr) retval on ttyC%d was %x\n",
- info->line, retval);
- }
}
- }
- CY_UNLOCK(info, flags);
-} /* cy_break */
+ CY_UNLOCK(info, flags);
+} /* cy_break */
static int
-get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
+get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
{
- if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
- return -EFAULT;
- info->mon.int_count = 0;
- info->mon.char_count = 0;
- info->mon.char_max = 0;
- info->mon.char_last = 0;
- return 0;
-}/* get_mon_info */
-
+ if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+ return -EFAULT;
+ info->mon.int_count = 0;
+ info->mon.char_count = 0;
+ info->mon.char_max = 0;
+ info->mon.char_last = 0;
+ return 0;
+} /* get_mon_info */
-static int
-set_threshold(struct cyclades_port * info, unsigned long value)
+static int set_threshold(struct cyclades_port *info, unsigned long value)
{
- void __iomem *base_addr;
- int card,channel,chip,index;
- unsigned long flags;
-
- card = info->card;
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
- info->cor3 &= ~CyREC_FIFO;
- info->cor3 |= value & CyREC_FIFO;
+ void __iomem *base_addr;
+ int card, channel, chip, index;
+ unsigned long flags;
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
- cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index);
- CY_UNLOCK(info, flags);
- } else {
- // Nothing to do!
- }
- return 0;
-}/* set_threshold */
+ card = info->card;
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+ info->cor3 &= ~CyREC_FIFO;
+ info->cor3 |= value & CyREC_FIFO;
-static int
-get_threshold(struct cyclades_port * info, unsigned long __user *value)
-{
- void __iomem *base_addr;
- int card,channel,chip,index;
- unsigned long tmp;
-
- card = info->card;
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
- tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
- return put_user(tmp,value);
- } else {
- // Nothing to do!
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
+ cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index);
+ CY_UNLOCK(info, flags);
+ } else {
+ /* Nothing to do! */
+ }
return 0;
- }
-}/* get_threshold */
-
+} /* set_threshold */
static int
-set_default_threshold(struct cyclades_port * info, unsigned long value)
+get_threshold(struct cyclades_port *info, unsigned long __user * value)
{
- info->default_threshold = value & 0x0f;
- return 0;
-}/* set_default_threshold */
+ void __iomem *base_addr;
+ int card, channel, chip, index;
+ unsigned long tmp;
+ card = info->card;
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+ tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
+ return put_user(tmp, value);
+ } else {
+ /* Nothing to do! */
+ return 0;
+ }
+} /* get_threshold */
static int
-get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
+set_default_threshold(struct cyclades_port *info, unsigned long value)
{
- return put_user(info->default_threshold,value);
-}/* get_default_threshold */
-
+ info->default_threshold = value & 0x0f;
+ return 0;
+} /* set_default_threshold */
static int
-set_timeout(struct cyclades_port * info, unsigned long value)
+get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
{
- void __iomem *base_addr;
- int card,channel,chip,index;
- unsigned long flags;
-
- card = info->card;
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
+ return put_user(info->default_threshold, value);
+} /* get_default_threshold */
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyRTPR<<index), value & 0xff);
- CY_UNLOCK(info, flags);
- } else {
- // Nothing to do!
- }
- return 0;
-}/* set_timeout */
+static int set_timeout(struct cyclades_port *info, unsigned long value)
+{
+ void __iomem *base_addr;
+ int card, channel, chip, index;
+ unsigned long flags;
+ card = info->card;
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
-static int
-get_timeout(struct cyclades_port * info, unsigned long __user *value)
-{
- void __iomem *base_addr;
- int card,channel,chip,index;
- unsigned long tmp;
-
- card = info->card;
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
- tmp = cy_readb(base_addr+(CyRTPR<<index));
- return put_user(tmp,value);
- } else {
- // Nothing to do!
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyRTPR << index), value & 0xff);
+ CY_UNLOCK(info, flags);
+ } else {
+ /* Nothing to do! */
+ }
return 0;
- }
-}/* get_timeout */
-
+} /* set_timeout */
-static int
-set_default_timeout(struct cyclades_port * info, unsigned long value)
+static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
{
- info->default_timeout = value & 0xff;
- return 0;
-}/* set_default_timeout */
+ void __iomem *base_addr;
+ int card, channel, chip, index;
+ unsigned long tmp;
+ card = info->card;
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr =
+ cy_card[card].base_addr + (cy_chip_offset[chip] << index);
+
+ tmp = cy_readb(base_addr + (CyRTPR << index));
+ return put_user(tmp, value);
+ } else {
+ /* Nothing to do! */
+ return 0;
+ }
+} /* get_timeout */
+
+static int set_default_timeout(struct cyclades_port *info, unsigned long value)
+{
+ info->default_timeout = value & 0xff;
+ return 0;
+} /* set_default_timeout */
static int
-get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
+get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
{
- return put_user(info->default_timeout,value);
-}/* get_default_timeout */
+ return put_user(info->default_timeout, value);
+} /* get_default_timeout */
/*
* This routine allows the tty driver to implement device-
@@ -3915,184 +4015,193 @@ get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
* not recognized by the driver, it should return ENOIOCTLCMD.
*/
static int
-cy_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
+cy_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
- struct cyclades_icount cprev, cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
- int ret_val = 0;
- unsigned long flags;
- void __user *argp = (void __user *)arg;
-
- if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
- return -ENODEV;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_icount cprev, cnow; /* kernel counter temps */
+ struct serial_icounter_struct __user *p_cuser; /* user space */
+ int ret_val = 0;
+ unsigned long flags;
+ void __user *argp = (void __user *)arg;
+
+ if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
+ return -ENODEV;
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
- info->line, cmd, arg); /* */
+ printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */
#endif
- switch (cmd) {
- case CYGETMON:
- ret_val = get_mon_info(info, argp);
- break;
- case CYGETTHRESH:
- ret_val = get_threshold(info, argp);
- break;
- case CYSETTHRESH:
- ret_val = set_threshold(info, arg);
- break;
- case CYGETDEFTHRESH:
- ret_val = get_default_threshold(info, argp);
- break;
- case CYSETDEFTHRESH:
- ret_val = set_default_threshold(info, arg);
- break;
- case CYGETTIMEOUT:
- ret_val = get_timeout(info, argp);
- break;
- case CYSETTIMEOUT:
- ret_val = set_timeout(info, arg);
- break;
- case CYGETDEFTIMEOUT:
- ret_val = get_default_timeout(info, argp);
- break;
- case CYSETDEFTIMEOUT:
- ret_val = set_default_timeout(info, arg);
- break;
+ switch (cmd) {
+ case CYGETMON:
+ ret_val = get_mon_info(info, argp);
+ break;
+ case CYGETTHRESH:
+ ret_val = get_threshold(info, argp);
+ break;
+ case CYSETTHRESH:
+ ret_val = set_threshold(info, arg);
+ break;
+ case CYGETDEFTHRESH:
+ ret_val = get_default_threshold(info, argp);
+ break;
+ case CYSETDEFTHRESH:
+ ret_val = set_default_threshold(info, arg);
+ break;
+ case CYGETTIMEOUT:
+ ret_val = get_timeout(info, argp);
+ break;
+ case CYSETTIMEOUT:
+ ret_val = set_timeout(info, arg);
+ break;
+ case CYGETDEFTIMEOUT:
+ ret_val = get_default_timeout(info, argp);
+ break;
+ case CYSETDEFTIMEOUT:
+ ret_val = set_default_timeout(info, arg);
+ break;
case CYSETRFLOW:
- info->rflow = (int)arg;
- ret_val = 0;
- break;
+ info->rflow = (int)arg;
+ ret_val = 0;
+ break;
case CYGETRFLOW:
- ret_val = info->rflow;
- break;
+ ret_val = info->rflow;
+ break;
case CYSETRTSDTR_INV:
- info->rtsdtr_inv = (int)arg;
- ret_val = 0;
- break;
+ info->rtsdtr_inv = (int)arg;
+ ret_val = 0;
+ break;
case CYGETRTSDTR_INV:
- ret_val = info->rtsdtr_inv;
- break;
+ ret_val = info->rtsdtr_inv;
+ break;
case CYGETCARDINFO:
- if (copy_to_user(argp, &cy_card[info->card],
- sizeof (struct cyclades_card))) {
- ret_val = -EFAULT;
+ if (copy_to_user(argp, &cy_card[info->card],
+ sizeof(struct cyclades_card))) {
+ ret_val = -EFAULT;
+ break;
+ }
+ ret_val = 0;
break;
- }
- ret_val = 0;
- break;
case CYGETCD1400VER:
- ret_val = info->chip_rev;
- break;
+ ret_val = info->chip_rev;
+ break;
#ifndef CONFIG_CYZ_INTR
case CYZSETPOLLCYCLE:
- cyz_polling_cycle = (arg * HZ) / 1000;
- ret_val = 0;
- break;
+ cyz_polling_cycle = (arg * HZ) / 1000;
+ ret_val = 0;
+ break;
case CYZGETPOLLCYCLE:
- ret_val = (cyz_polling_cycle * 1000) / HZ;
- break;
-#endif /* CONFIG_CYZ_INTR */
+ ret_val = (cyz_polling_cycle * 1000) / HZ;
+ break;
+#endif /* CONFIG_CYZ_INTR */
case CYSETWAIT:
- info->closing_wait = (unsigned short)arg * HZ/100;
- ret_val = 0;
- break;
+ info->closing_wait = (unsigned short)arg *HZ / 100;
+ ret_val = 0;
+ break;
case CYGETWAIT:
- ret_val = info->closing_wait / (HZ/100);
- break;
- case TIOCGSERIAL:
- ret_val = get_serial_info(info, argp);
- break;
- case TIOCSSERIAL:
- ret_val = set_serial_info(info, argp);
- break;
- case TIOCSERGETLSR: /* Get line status register */
- ret_val = get_lsr_info(info, argp);
- break;
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
+ ret_val = info->closing_wait / (HZ / 100);
+ break;
+ case TIOCGSERIAL:
+ ret_val = get_serial_info(info, argp);
+ break;
+ case TIOCSSERIAL:
+ ret_val = set_serial_info(info, argp);
+ break;
+ case TIOCSERGETLSR: /* Get line status register */
+ ret_val = get_lsr_info(info, argp);
+ break;
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
case TIOCMIWAIT:
- CY_LOCK(info, flags);
- /* note the counters on entry */
- cprev = info->icount;
- CY_UNLOCK(info, flags);
- while (1) {
- interruptible_sleep_on(&info->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current)) {
- return -ERESTARTSYS;
- }
-
CY_LOCK(info, flags);
- cnow = info->icount; /* atomic copy */
+ /* note the counters on entry */
+ cprev = info->icount;
CY_UNLOCK(info, flags);
+ while (1) {
+ interruptible_sleep_on(&info->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ return -ERESTARTSYS;
+ }
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
- return -EIO; /* no change => error */
- }
- if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
+ CY_LOCK(info, flags);
+ cnow = info->icount; /* atomic copy */
+ CY_UNLOCK(info, flags);
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+ return -EIO; /* no change => error */
+ }
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
case TIOCGICOUNT:
- CY_LOCK(info, flags);
- cnow = info->icount;
- CY_UNLOCK(info, flags);
- p_cuser = argp;
- ret_val = put_user(cnow.cts, &p_cuser->cts);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.dsr, &p_cuser->dsr);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.rng, &p_cuser->rng);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.dcd, &p_cuser->dcd);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.rx, &p_cuser->rx);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.tx, &p_cuser->tx);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.frame, &p_cuser->frame);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.overrun, &p_cuser->overrun);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.parity, &p_cuser->parity);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.brk, &p_cuser->brk);
- if (ret_val) return ret_val;
- ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
- if (ret_val) return ret_val;
- ret_val = 0;
- break;
- default:
- ret_val = -ENOIOCTLCMD;
- }
+ CY_LOCK(info, flags);
+ cnow = info->icount;
+ CY_UNLOCK(info, flags);
+ p_cuser = argp;
+ ret_val = put_user(cnow.cts, &p_cuser->cts);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.dsr, &p_cuser->dsr);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.rng, &p_cuser->rng);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.dcd, &p_cuser->dcd);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.rx, &p_cuser->rx);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.tx, &p_cuser->tx);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.frame, &p_cuser->frame);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.overrun, &p_cuser->overrun);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.parity, &p_cuser->parity);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.brk, &p_cuser->brk);
+ if (ret_val)
+ return ret_val;
+ ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+ if (ret_val)
+ return ret_val;
+ ret_val = 0;
+ break;
+ default:
+ ret_val = -ENOIOCTLCMD;
+ }
#ifdef CY_DEBUG_OTHER
- printk(" cyc:cy_ioctl done\n");
+ printk(" cyc:cy_ioctl done\n");
#endif
- return ret_val;
-} /* cy_ioctl */
-
+ return ret_val;
+} /* cy_ioctl */
/*
* This routine allows the tty driver to be notified when
@@ -4100,66 +4209,64 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
* well-designed tty driver should be prepared to accept the case
* where old == NULL, and try to do something rational.
*/
-static void
-cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
+static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_set_termios ttyC%d\n", info->line);
+ printk("cyc:cy_set_termios ttyC%d\n", info->line);
#endif
- if ((tty->termios->c_cflag == old_termios->c_cflag) &&
- ((tty->termios->c_iflag & (IXON|IXANY)) ==
- (old_termios->c_iflag & (IXON|IXANY))))
- return;
- set_line_char(info);
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- cy_start(tty);
- }
+ if (tty->termios->c_cflag == old_termios->c_cflag &&
+ (tty->termios->c_iflag & (IXON | IXANY)) ==
+ (old_termios->c_iflag & (IXON | IXANY)))
+ return;
+ set_line_char(info);
+
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ cy_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);
+ /*
+ * 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
-
- return;
-} /* cy_set_termios */
+} /* cy_set_termios */
/* This function is used to send a high-priority XON/XOFF character to
the device.
*/
-static void
-cy_send_xchar (struct tty_struct *tty, char ch)
+static void cy_send_xchar(struct tty_struct *tty, char ch)
{
- struct cyclades_port *info = (struct cyclades_port *) tty->driver_data;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
int card, channel;
- if (serial_paranoia_check (info, tty->name, "cy_send_xchar"))
+ if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
return;
- info->x_char = ch;
+ info->x_char = ch;
if (ch)
- cy_start (tty);
+ cy_start(tty);
card = info->card;
channel = info->line - cy_card[card].first_line;
- if (IS_CYC_Z (cy_card[card])) {
- if (ch == STOP_CHAR (tty))
- cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXOFF, 0L);
- else if (ch == START_CHAR (tty))
- cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXON, 0L);
+ if (IS_CYC_Z(cy_card[card])) {
+ if (ch == STOP_CHAR(tty))
+ cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF,
+ 0L);
+ else if (ch == START_CHAR(tty))
+ cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON,
+ 0L);
}
}
@@ -4167,260 +4274,248 @@ cy_send_xchar (struct tty_struct *tty, char ch)
that incoming characters should be throttled because the input
buffers are close to full.
*/
-static void
-cy_throttle(struct tty_struct * tty)
+static void cy_throttle(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- unsigned long flags;
- void __iomem *base_addr;
- int card,chip,channel,index;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
#ifdef CY_DEBUG_THROTTLE
- char buf[64];
+ char buf[64];
- printk("cyc:throttle %s: %d....ttyC%d\n",
- tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty), info->line);
+ printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty), info->line);
#endif
- if (serial_paranoia_check(info, tty->name, "cy_throttle")){
- return;
- }
-
- card = info->card;
-
- if (I_IXOFF(tty)) {
- if (!IS_CYC_Z (cy_card[card]))
- cy_send_xchar (tty, STOP_CHAR (tty));
- else
- info->throttle = 1;
- }
-
- if (tty->termios->c_cflag & CRTSCTS) {
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
- } else {
- cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
- }
- CY_UNLOCK(info, flags);
- } else {
- info->throttle = 1;
- }
- }
+ if (serial_paranoia_check(info, tty->name, "cy_throttle")) {
+ return;
+ }
- return;
-} /* cy_throttle */
+ card = info->card;
+
+ if (I_IXOFF(tty)) {
+ if (!IS_CYC_Z(cy_card[card]))
+ cy_send_xchar(tty, STOP_CHAR(tty));
+ else
+ info->throttle = 1;
+ }
+ if (tty->termios->c_cflag & CRTSCTS) {
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = cy_card[card].base_addr +
+ (cy_chip_offset[chip] << index);
+
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ ~CyDTR);
+ } else {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ ~CyRTS);
+ }
+ CY_UNLOCK(info, flags);
+ } else {
+ info->throttle = 1;
+ }
+ }
+} /* cy_throttle */
/*
* This routine notifies the tty driver that it should signal
* that characters can now be sent to the tty without fear of
* overrunning the input buffers of the line disciplines.
*/
-static void
-cy_unthrottle(struct tty_struct * tty)
+static void cy_unthrottle(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- unsigned long flags;
- void __iomem *base_addr;
- int card,chip,channel,index;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ unsigned long flags;
+ void __iomem *base_addr;
+ int card, chip, channel, index;
#ifdef CY_DEBUG_THROTTLE
- char buf[64];
-
- printk("cyc:unthrottle %s: %d....ttyC%d\n",
- tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty), info->line);
-#endif
+ char buf[64];
- if (serial_paranoia_check(info, tty->name, "cy_unthrottle")){
- return;
- }
+ printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty), info->line);
+#endif
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- cy_send_xchar (tty, START_CHAR (tty));
- }
-
- if (tty->termios->c_cflag & CRTSCTS) {
- card = info->card;
- channel = info->line - cy_card[card].first_line;
- if (!IS_CYC_Z(cy_card[card])) {
- chip = channel>>2;
- channel &= 0x03;
- index = cy_card[card].bus_index;
- base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
-
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
- if (info->rtsdtr_inv) {
- cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
- } else {
- cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
- }
- CY_UNLOCK(info, flags);
- } else {
- info->throttle = 0;
+ if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) {
+ return;
}
- }
- return;
-} /* cy_unthrottle */
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ cy_send_xchar(tty, START_CHAR(tty));
+ }
+ if (tty->termios->c_cflag & CRTSCTS) {
+ card = info->card;
+ channel = info->line - cy_card[card].first_line;
+ if (!IS_CYC_Z(cy_card[card])) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ index = cy_card[card].bus_index;
+ base_addr = cy_card[card].base_addr +
+ (cy_chip_offset[chip] << index);
+
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char) channel);
+ if (info->rtsdtr_inv) {
+ cy_writeb(base_addr + (CyMSVR2 << index),
+ CyDTR);
+ } else {
+ cy_writeb(base_addr + (CyMSVR1 << index),
+ CyRTS);
+ }
+ CY_UNLOCK(info, flags);
+ } else {
+ info->throttle = 0;
+ }
+ }
+} /* cy_unthrottle */
/* cy_start and cy_stop provide software output flow control as a
function of XON/XOFF, software CTS, and other such stuff.
*/
-static void
-cy_stop(struct tty_struct *tty)
+static void cy_stop(struct tty_struct *tty)
{
- struct cyclades_card *cinfo;
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- void __iomem *base_addr;
- int chip,channel,index;
- unsigned long flags;
+ struct cyclades_card *cinfo;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ void __iomem *base_addr;
+ int chip, channel, index;
+ unsigned long flags;
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_stop ttyC%d\n", info->line); /* */
+ printk("cyc:cy_stop ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_stop"))
- return;
-
- cinfo = &cy_card[info->card];
- channel = info->line - cinfo->first_line;
- if (!IS_CYC_Z(*cinfo)) {
- index = cinfo->bus_index;
- chip = channel>>2;
- channel &= 0x03;
- base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
-
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index),
- (u_char)(channel & 0x0003)); /* index channel */
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
- CY_UNLOCK(info, flags);
- } else {
- // Nothing to do!
- }
+ if (serial_paranoia_check(info, tty->name, "cy_stop"))
+ return;
- return;
-} /* cy_stop */
+ cinfo = &cy_card[info->card];
+ channel = info->line - cinfo->first_line;
+ if (!IS_CYC_Z(*cinfo)) {
+ index = cinfo->bus_index;
+ chip = channel >> 2;
+ channel &= 0x03;
+ base_addr = cy_card[info->card].base_addr +
+ (cy_chip_offset[chip] << index);
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index),
+ (u_char)(channel & 0x0003)); /* index channel */
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+ CY_UNLOCK(info, flags);
+ } else {
+ /* Nothing to do! */
+ }
+} /* cy_stop */
-static void
-cy_start(struct tty_struct *tty)
+static void cy_start(struct tty_struct *tty)
{
- struct cyclades_card *cinfo;
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- void __iomem *base_addr;
- int chip,channel,index;
- unsigned long flags;
+ struct cyclades_card *cinfo;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ void __iomem *base_addr;
+ int chip, channel, index;
+ unsigned long flags;
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_start ttyC%d\n", info->line); /* */
+ printk("cyc:cy_start ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_start"))
- return;
-
- cinfo = &cy_card[info->card];
- channel = info->line - cinfo->first_line;
- index = cinfo->bus_index;
- if (!IS_CYC_Z(*cinfo)) {
- chip = channel>>2;
- channel &= 0x03;
- base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
-
- CY_LOCK(info, flags);
- cy_writeb(base_addr+(CyCAR<<index),
- (u_char)(channel & 0x0003)); /* index channel */
- cy_writeb(base_addr+(CySRER<<index),
- cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
- CY_UNLOCK(info, flags);
- } else {
- // Nothing to do!
- }
+ if (serial_paranoia_check(info, tty->name, "cy_start"))
+ return;
- return;
-} /* cy_start */
+ cinfo = &cy_card[info->card];
+ channel = info->line - cinfo->first_line;
+ index = cinfo->bus_index;
+ if (!IS_CYC_Z(*cinfo)) {
+ chip = channel >> 2;
+ channel &= 0x03;
+ base_addr = cy_card[info->card].base_addr +
+ (cy_chip_offset[chip] << index);
+ CY_LOCK(info, flags);
+ cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */
+ cy_writeb(base_addr + (CySRER << index),
+ cy_readb(base_addr + (CySRER << index)) | CyTxRdy);
+ CY_UNLOCK(info, flags);
+ } else {
+ /* Nothing to do! */
+ }
+} /* cy_start */
-static void
-cy_flush_buffer(struct tty_struct *tty)
+static void cy_flush_buffer(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
- int card, channel, retval;
- unsigned long flags;
-
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ int card, channel, retval;
+ unsigned long flags;
+
#ifdef CY_DEBUG_IO
- printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */
+ printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
- return;
-
- card = info->card;
- channel = (info->line) - (cy_card[card].first_line);
+ if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+ return;
- CY_LOCK(info, flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- CY_UNLOCK(info, flags);
+ card = info->card;
+ channel = (info->line) - (cy_card[card].first_line);
- if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board
- buffers as well */
CY_LOCK(info, flags);
- retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
- if (retval != 0) {
- printk("cyc: flush_buffer retval on ttyC%d was %x\n",
- info->line, retval);
- }
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
CY_UNLOCK(info, flags);
- }
- tty_wakeup(tty);
- wake_up_interruptible(&tty->write_wait);
-} /* cy_flush_buffer */
+ if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board
+ buffers as well */
+ CY_LOCK(info, flags);
+ retval =
+ cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
+ if (retval != 0) {
+ printk("cyc: flush_buffer retval on ttyC%d was %x\n",
+ info->line, retval);
+ }
+ CY_UNLOCK(info, flags);
+ }
+ tty_wakeup(tty);
+ wake_up_interruptible(&tty->write_wait);
+} /* cy_flush_buffer */
/*
* cy_hangup() --- called by tty_hangup() when a hangup is signaled.
*/
-static void
-cy_hangup(struct tty_struct *tty)
+static void cy_hangup(struct tty_struct *tty)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+
#ifdef CY_DEBUG_OTHER
- printk("cyc:cy_hangup ttyC%d\n", info->line); /* */
+ printk("cyc:cy_hangup ttyC%d\n", info->line); /* */
#endif
- if (serial_paranoia_check(info, tty->name, "cy_hangup"))
- return;
+ if (serial_paranoia_check(info, tty->name, "cy_hangup"))
+ return;
- cy_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- info->count = 0;
+ cy_flush_buffer(tty);
+ shutdown(info);
+ info->event = 0;
+ info->count = 0;
#ifdef CY_DEBUG_COUNT
- printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
+ printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
#endif
- info->tty = NULL;
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- wake_up_interruptible(&info->open_wait);
-} /* cy_hangup */
-
+ info->tty = NULL;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ wake_up_interruptible(&info->open_wait);
+} /* cy_hangup */
/*
* ---------------------------------------------------------------------
@@ -4433,82 +4528,84 @@ cy_hangup(struct tty_struct *tty)
/* initialize chips on Cyclom-Y card -- return number of valid
chips (which is number of ports/4) */
static unsigned short __init
-cyy_init_card(void __iomem *true_base_addr,int index)
+cyy_init_card(void __iomem * true_base_addr, int index)
{
- unsigned int chip_number;
- void __iomem *base_addr;
-
- cy_writeb(true_base_addr+(Cy_HwReset<<index), 0);
- /* Cy_HwReset is 0x1400 */
- cy_writeb(true_base_addr+(Cy_ClrIntr<<index), 0);
- /* Cy_ClrIntr is 0x1800 */
- udelay(500L);
-
- for(chip_number=0; chip_number<CyMAX_CHIPS_PER_CARD; chip_number++){
- base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index);
- mdelay(1);
- if(cy_readb(base_addr+(CyCCR<<index)) != 0x00){
- /*************
- printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
- chip_number, (unsigned long)base_addr);
- *************/
- return chip_number;
- }
-
- cy_writeb(base_addr+(CyGFRCR<<index), 0);
- udelay(10L);
-
- /* The Cyclom-16Y does not decode address bit 9 and therefore
- cannot distinguish between references to chip 0 and a non-
- existent chip 4. If the preceding clearing of the supposed
- chip 4 GFRCR register appears at chip 0, there is no chip 4
- and this must be a Cyclom-16Y, not a Cyclom-32Ye.
- */
- if (chip_number == 4
- && cy_readb(true_base_addr
- + (cy_chip_offset[0]<<index)
- + (CyGFRCR<<index)) == 0){
- return chip_number;
- }
-
- cy_writeb(base_addr+(CyCCR<<index), CyCHIP_RESET);
- mdelay(1);
-
- if(cy_readb(base_addr+(CyGFRCR<<index)) == 0x00){
- /*
- printk(" chip #%d at %#6lx is not responding ",
- chip_number, (unsigned long)base_addr);
- printk("(GFRCR stayed 0)\n",
- */
- return chip_number;
- }
- if((0xf0 & (cy_readb(base_addr+(CyGFRCR<<index)))) != 0x40){
- /*
- printk(" chip #%d at %#6lx is not valid (GFRCR == %#2x)\n",
- chip_number, (unsigned long)base_addr,
- base_addr[CyGFRCR<<index]);
- */
- return chip_number;
- }
- cy_writeb(base_addr+(CyGCR<<index), CyCH0_SERIAL);
- if (cy_readb(base_addr+(CyGFRCR<<index)) >= CD1400_REV_J){
- /* It is a CD1400 rev. J or later */
- /* Impossible to reach 5ms with this chip.
- Changed to 2ms instead (f = 500 Hz). */
- cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_60_2MS);
- } else {
- /* f = 200 Hz */
- cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_25_5MS);
- }
+ unsigned int chip_number;
+ void __iomem *base_addr;
+
+ cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
+ /* Cy_HwReset is 0x1400 */
+ cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
+ /* Cy_ClrIntr is 0x1800 */
+ udelay(500L);
+
+ for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; chip_number++) {
+ base_addr =
+ true_base_addr + (cy_chip_offset[chip_number] << index);
+ mdelay(1);
+ if (cy_readb(base_addr + (CyCCR << index)) != 0x00) {
+ /*************
+ printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
+ chip_number, (unsigned long)base_addr);
+ *************/
+ return chip_number;
+ }
+
+ cy_writeb(base_addr + (CyGFRCR << index), 0);
+ udelay(10L);
+
+ /* The Cyclom-16Y does not decode address bit 9 and therefore
+ cannot distinguish between references to chip 0 and a non-
+ existent chip 4. If the preceding clearing of the supposed
+ chip 4 GFRCR register appears at chip 0, there is no chip 4
+ and this must be a Cyclom-16Y, not a Cyclom-32Ye.
+ */
+ if (chip_number == 4 && cy_readb(true_base_addr +
+ (cy_chip_offset[0] << index) +
+ (CyGFRCR << index)) == 0) {
+ return chip_number;
+ }
+
+ cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
+ mdelay(1);
+
+ if (cy_readb(base_addr + (CyGFRCR << index)) == 0x00) {
+ /*
+ printk(" chip #%d at %#6lx is not responding ",
+ chip_number, (unsigned long)base_addr);
+ printk("(GFRCR stayed 0)\n",
+ */
+ return chip_number;
+ }
+ if ((0xf0 & (cy_readb(base_addr + (CyGFRCR << index)))) !=
+ 0x40) {
+ /*
+ printk(" chip #%d at %#6lx is not valid (GFRCR == "
+ "%#2x)\n",
+ chip_number, (unsigned long)base_addr,
+ base_addr[CyGFRCR<<index]);
+ */
+ return chip_number;
+ }
+ cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
+ if (cy_readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
+ /* It is a CD1400 rev. J or later */
+ /* Impossible to reach 5ms with this chip.
+ Changed to 2ms instead (f = 500 Hz). */
+ cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
+ } else {
+ /* f = 200 Hz */
+ cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
+ }
- /*
- printk(" chip #%d at %#6lx is rev 0x%2x\n",
- chip_number, (unsigned long)base_addr,
- cy_readb(base_addr+(CyGFRCR<<index)));
- */
- }
- return chip_number;
-} /* cyy_init_card */
+ /*
+ printk(" chip #%d at %#6lx is rev 0x%2x\n",
+ chip_number, (unsigned long)base_addr,
+ cy_readb(base_addr+(CyGFRCR<<index)));
+ */
+ }
+ return chip_number;
+} /* cyy_init_card */
/*
* ---------------------------------------------------------------------
@@ -4516,126 +4613,124 @@ cyy_init_card(void __iomem *true_base_addr,int index)
* sets global variables and return the number of ISA boards found.
* ---------------------------------------------------------------------
*/
-static int __init
-cy_detect_isa(void)
+static int __init cy_detect_isa(void)
{
#ifdef CONFIG_ISA
- unsigned short cy_isa_irq,nboard;
- void __iomem *cy_isa_address;
- unsigned short i,j,cy_isa_nchan;
+ unsigned short cy_isa_irq, nboard;
+ void __iomem *cy_isa_address;
+ unsigned short i, j, cy_isa_nchan;
#ifdef MODULE
- int isparam = 0;
+ int isparam = 0;
#endif
- nboard = 0;
+ nboard = 0;
#ifdef MODULE
/* Check for module parameters */
- for(i = 0 ; i < NR_CARDS; i++) {
- if (maddr[i] || i) {
- isparam = 1;
- cy_isa_addresses[i] = maddr[i];
- }
- if (!maddr[i])
- break;
+ for (i = 0; i < NR_CARDS; i++) {
+ if (maddr[i] || i) {
+ isparam = 1;
+ cy_isa_addresses[i] = maddr[i];
+ }
+ if (!maddr[i])
+ break;
}
#endif
- /* scan the address table probing for Cyclom-Y/ISA boards */
- for (i = 0 ; i < NR_ISA_ADDRS ; i++) {
- unsigned int isa_address = cy_isa_addresses[i];
- if (isa_address == 0x0000) {
- return(nboard);
- }
+ /* scan the address table probing for Cyclom-Y/ISA boards */
+ for (i = 0; i < NR_ISA_ADDRS; i++) {
+ unsigned int isa_address = cy_isa_addresses[i];
+ if (isa_address == 0x0000) {
+ return nboard;
+ }
- /* probe for CD1400... */
+ /* probe for CD1400... */
cy_isa_address = ioremap(isa_address, CyISA_Ywin);
- cy_isa_nchan = CyPORTS_PER_CHIP *
- cyy_init_card(cy_isa_address,0);
- if (cy_isa_nchan == 0) {
- continue;
- }
-
+ cy_isa_nchan = CyPORTS_PER_CHIP *
+ cyy_init_card(cy_isa_address, 0);
+ if (cy_isa_nchan == 0) {
+ continue;
+ }
#ifdef MODULE
if (isparam && irq[i])
- cy_isa_irq = irq[i];
+ cy_isa_irq = irq[i];
else
#endif
- /* find out the board's irq by probing */
- cy_isa_irq = detect_isa_irq(cy_isa_address);
- if (cy_isa_irq == 0) {
- printk("Cyclom-Y/ISA found at 0x%lx ",
- (unsigned long) cy_isa_address);
- printk("but the IRQ could not be detected.\n");
- continue;
- }
-
- if((cy_next_channel+cy_isa_nchan) > NR_PORTS) {
- printk("Cyclom-Y/ISA found at 0x%lx ",
- (unsigned long) cy_isa_address);
- printk("but no more channels are available.\n");
- printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
- return(nboard);
- }
- /* fill the next cy_card structure available */
- for (j = 0 ; j < NR_CARDS ; j++) {
- if (cy_card[j].base_addr == 0) break;
- }
- if (j == NR_CARDS) { /* no more cy_cards available */
- printk("Cyclom-Y/ISA found at 0x%lx ",
- (unsigned long) cy_isa_address);
- printk("but no more cards can be used .\n");
- printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
- return(nboard);
- }
-
- /* allocate IRQ */
- if(request_irq(cy_isa_irq, cyy_interrupt,
- IRQF_DISABLED, "Cyclom-Y", &cy_card[j]))
- {
- printk("Cyclom-Y/ISA found at 0x%lx ",
- (unsigned long) cy_isa_address);
- printk("but could not allocate IRQ#%d.\n",
- cy_isa_irq);
- return(nboard);
- }
-
- /* set cy_card */
- cy_card[j].base_addr = cy_isa_address;
- cy_card[j].ctl_addr = NULL;
- cy_card[j].irq = (int) cy_isa_irq;
- cy_card[j].bus_index = 0;
- cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = cy_isa_nchan/4;
- nboard++;
-
- /* print message */
- printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ",
- j+1, (unsigned long) cy_isa_address,
- (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
- cy_isa_irq);
- printk("%d channels starting from port %d.\n",
- cy_isa_nchan, cy_next_channel);
- cy_next_channel += cy_isa_nchan;
- }
- return(nboard);
+ /* find out the board's irq by probing */
+ cy_isa_irq = detect_isa_irq(cy_isa_address);
+ if (cy_isa_irq == 0) {
+ printk("Cyclom-Y/ISA found at 0x%lx ",
+ (unsigned long)cy_isa_address);
+ printk("but the IRQ could not be detected.\n");
+ continue;
+ }
+
+ if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
+ printk("Cyclom-Y/ISA found at 0x%lx ",
+ (unsigned long)cy_isa_address);
+ printk("but no more channels are available.\n");
+ printk("Change NR_PORTS in cyclades.c and recompile "
+ "kernel.\n");
+ return nboard;
+ }
+ /* fill the next cy_card structure available */
+ for (j = 0; j < NR_CARDS; j++) {
+ if (cy_card[j].base_addr == 0)
+ break;
+ }
+ if (j == NR_CARDS) { /* no more cy_cards available */
+ printk("Cyclom-Y/ISA found at 0x%lx ",
+ (unsigned long)cy_isa_address);
+ printk("but no more cards can be used .\n");
+ printk("Change NR_CARDS in cyclades.c and recompile "
+ "kernel.\n");
+ return nboard;
+ }
+
+ /* allocate IRQ */
+ if (request_irq(cy_isa_irq, cyy_interrupt,
+ IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
+ printk("Cyclom-Y/ISA found at 0x%lx ",
+ (unsigned long)cy_isa_address);
+ printk("but could not allocate IRQ#%d.\n", cy_isa_irq);
+ return nboard;
+ }
+
+ /* set cy_card */
+ cy_card[j].base_addr = cy_isa_address;
+ cy_card[j].ctl_addr = NULL;
+ cy_card[j].irq = (int)cy_isa_irq;
+ cy_card[j].bus_index = 0;
+ cy_card[j].first_line = cy_next_channel;
+ cy_card[j].num_chips = cy_isa_nchan / 4;
+ nboard++;
+
+ /* print message */
+ printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ",
+ j + 1, (unsigned long)cy_isa_address,
+ (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
+ cy_isa_irq);
+ printk("%d channels starting from port %d.\n",
+ cy_isa_nchan, cy_next_channel);
+ cy_next_channel += cy_isa_nchan;
+ }
+ return nboard;
#else
- return(0);
-#endif /* CONFIG_ISA */
-} /* cy_detect_isa */
+ return 0;
+#endif /* CONFIG_ISA */
+} /* cy_detect_isa */
-static void
-plx_init(void __iomem *addr, uclong initctl)
+static void plx_init(void __iomem * addr, uclong initctl)
{
- /* Reset PLX */
- cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
- udelay(100L);
- cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
-
- /* Reload Config. Registers from EEPROM */
- cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
- udelay(100L);
- cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
+ /* Reset PLX */
+ cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
+ udelay(100L);
+ cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000);
+
+ /* Reload Config. Registers from EEPROM */
+ cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000);
+ udelay(100L);
+ cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000);
}
/*
@@ -4644,43 +4739,42 @@ plx_init(void __iomem *addr, uclong initctl)
* sets global variables and return the number of PCI boards found.
* ---------------------------------------------------------------------
*/
-static int __init
-cy_detect_pci(void)
+static int __init cy_detect_pci(void)
{
#ifdef CONFIG_PCI
- struct pci_dev *pdev = NULL;
- unsigned char cyy_rev_id;
- unsigned char cy_pci_irq = 0;
- uclong cy_pci_phys0, cy_pci_phys2;
- void __iomem *cy_pci_addr0, *cy_pci_addr2;
- unsigned short i,j,cy_pci_nchan, plx_ver;
- unsigned short device_id,dev_index = 0;
- uclong mailbox;
- uclong ZeIndex = 0;
- void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
- uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
- unsigned char Ze_irq[NR_CARDS];
- struct pci_dev *Ze_pdev[NR_CARDS];
-
- for (i = 0; i < NR_CARDS; i++) {
- /* look for a Cyclades card by vendor and device id */
- while((device_id = cy_pci_dev_id[dev_index]) != 0) {
- if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
- device_id, pdev)) == NULL) {
- dev_index++; /* try next device id */
- } else {
- break; /* found a board */
- }
- }
+ struct pci_dev *pdev = NULL;
+ unsigned char cyy_rev_id;
+ unsigned char cy_pci_irq = 0;
+ uclong cy_pci_phys0, cy_pci_phys2;
+ void __iomem *cy_pci_addr0, *cy_pci_addr2;
+ unsigned short i, j, cy_pci_nchan, plx_ver;
+ unsigned short device_id, dev_index = 0;
+ uclong mailbox;
+ uclong ZeIndex = 0;
+ void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
+ uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
+ unsigned char Ze_irq[NR_CARDS];
+ struct pci_dev *Ze_pdev[NR_CARDS];
+
+ for (i = 0; i < NR_CARDS; i++) {
+ /* look for a Cyclades card by vendor and device id */
+ while ((device_id = cy_pci_dev_id[dev_index]) != 0) {
+ if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
+ device_id, pdev)) == NULL) {
+ dev_index++; /* try next device id */
+ } else {
+ break; /* found a board */
+ }
+ }
if (device_id == 0)
- break;
+ break;
if (pci_enable_device(pdev))
- continue;
+ continue;
- /* read PCI configuration area */
+ /* read PCI configuration area */
cy_pci_irq = pdev->irq;
cy_pci_phys0 = pci_resource_start(pdev, 0);
cy_pci_phys2 = pci_resource_start(pdev, 2);
@@ -4688,482 +4782,497 @@ cy_detect_pci(void)
device_id &= ~PCI_DEVICE_ID_MASK;
- if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
- || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
+ if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+ device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
#ifdef CY_PCI_DEBUG
- printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
- pdev->bus->number, pdev->devfn);
- printk("rev_id=%d) IRQ%d\n",
- cyy_rev_id, (int)cy_pci_irq);
- printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n",
- (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+ printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
+ pdev->bus->number, pdev->devfn);
+ printk("rev_id=%d) IRQ%d\n",
+ cyy_rev_id, (int)cy_pci_irq);
+ printk("Cyclom-Y/PCI:found winaddr=0x%lx "
+ "ctladdr=0x%lx\n",
+ (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
#endif
- if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
- printk(" Warning: PCI I/O bit incorrectly set. "
- "Ignoring it...\n");
- pdev->resource[2].flags &= ~IORESOURCE_IO;
- }
-
- /* Although we don't use this I/O region, we should
- request it from the kernel anyway, to avoid problems
- with other drivers accessing it. */
- if (pci_request_regions(pdev, "Cyclom-Y") != 0) {
- printk(KERN_ERR "cyclades: failed to reserve PCI resources\n");
- continue;
- }
+ if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+ printk(" Warning: PCI I/O bit incorrectly "
+ "set. Ignoring it...\n");
+ pdev->resource[2].flags &= ~IORESOURCE_IO;
+ }
+ /* Although we don't use this I/O region, we should
+ request it from the kernel anyway, to avoid problems
+ with other drivers accessing it. */
+ if (pci_request_regions(pdev, "Cyclom-Y") != 0) {
+ printk(KERN_ERR "cyclades: failed to reserve "
+ "PCI resources\n");
+ continue;
+ }
#if defined(__alpha__)
- if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
- printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
- pdev->bus->number, pdev->devfn);
- printk("rev_id=%d) IRQ%d\n",
- cyy_rev_id, (int)cy_pci_irq);
- printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n",
- (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
- printk("Cyclom-Y/PCI not supported for low addresses in "
- "Alpha systems.\n");
- i--;
- continue;
- }
+ if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
+ printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
+ pdev->bus->number, pdev->devfn);
+ printk("rev_id=%d) IRQ%d\n",
+ cyy_rev_id, (int)cy_pci_irq);
+ printk("Cyclom-Y/PCI:found winaddr=0x%lx "
+ "ctladdr=0x%lx\n",
+ (ulong)cy_pci_phys2,
+ (ulong)cy_pci_phys0);
+ printk("Cyclom-Y/PCI not supported for low "
+ "addresses in Alpha systems.\n");
+ i--;
+ continue;
+ }
#endif
- cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
- cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
+ cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
+ cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
#ifdef CY_PCI_DEBUG
- printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
- (u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
+ printk("Cyclom-Y/PCI: relocate winaddr=0x%lx "
+ "ctladdr=0x%lx\n",
+ (u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
#endif
- cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP *
- cyy_init_card(cy_pci_addr2, 1));
- if(cy_pci_nchan == 0) {
- printk("Cyclom-Y PCI host card with ");
- printk("no Serial-Modules at 0x%lx.\n",
- (ulong) cy_pci_phys2);
- i--;
- continue;
- }
- if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
- printk("Cyclom-Y/PCI found at 0x%lx ",
- (ulong) cy_pci_phys2);
- printk("but no channels are available.\n");
- printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
- return(i);
- }
- /* fill the next cy_card structure available */
- for (j = 0 ; j < NR_CARDS ; j++) {
- if (cy_card[j].base_addr == 0) break;
- }
- if (j == NR_CARDS) { /* no more cy_cards available */
- printk("Cyclom-Y/PCI found at 0x%lx ",
- (ulong) cy_pci_phys2);
- printk("but no more cards can be used.\n");
- printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
- return(i);
- }
-
- /* allocate IRQ */
- if(request_irq(cy_pci_irq, cyy_interrupt,
- IRQF_SHARED, "Cyclom-Y", &cy_card[j]))
- {
- printk("Cyclom-Y/PCI found at 0x%lx ",
- (ulong) cy_pci_phys2);
- printk("but could not allocate IRQ%d.\n",
- cy_pci_irq);
- return(i);
- }
-
- /* set cy_card */
- cy_card[j].base_phys = (ulong)cy_pci_phys2;
- cy_card[j].ctl_phys = (ulong)cy_pci_phys0;
- cy_card[j].base_addr = cy_pci_addr2;
- cy_card[j].ctl_addr = cy_pci_addr0;
- cy_card[j].irq = (int) cy_pci_irq;
- cy_card[j].bus_index = 1;
- cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = cy_pci_nchan/4;
- cy_card[j].pdev = pdev;
-
- /* enable interrupts in the PCI interface */
- plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
- switch (plx_ver) {
- case PLX_9050:
-
- cy_writeb(cy_pci_addr0+0x4c, 0x43);
- break;
-
- case PLX_9060:
- case PLX_9080:
- default: /* Old boards, use PLX_9060 */
-
- plx_init(cy_pci_addr0, 0x6c);
- /* For some yet unknown reason, once the PLX9060 reloads
- the EEPROM, the IRQ is lost and, thus, we have to
- re-write it to the PCI config. registers.
- This will remain here until we find a permanent fix. */
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq);
-
- cy_writew(cy_pci_addr0+0x68,
- cy_readw(cy_pci_addr0+0x68)|0x0900);
- break;
- }
+ cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP *
+ cyy_init_card(cy_pci_addr2, 1));
+ if (cy_pci_nchan == 0) {
+ printk("Cyclom-Y PCI host card with ");
+ printk("no Serial-Modules at 0x%lx.\n",
+ (ulong) cy_pci_phys2);
+ i--;
+ continue;
+ }
+ if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
+ printk("Cyclom-Y/PCI found at 0x%lx ",
+ (ulong) cy_pci_phys2);
+ printk("but no channels are available.\n");
+ printk("Change NR_PORTS in cyclades.c and "
+ "recompile kernel.\n");
+ return i;
+ }
+ /* fill the next cy_card structure available */
+ for (j = 0; j < NR_CARDS; j++) {
+ if (cy_card[j].base_addr == 0)
+ break;
+ }
+ if (j == NR_CARDS) { /* no more cy_cards available */
+ printk("Cyclom-Y/PCI found at 0x%lx ",
+ (ulong) cy_pci_phys2);
+ printk("but no more cards can be used.\n");
+ printk("Change NR_CARDS in cyclades.c and "
+ "recompile kernel.\n");
+ return i;
+ }
+
+ /* allocate IRQ */
+ if (request_irq(cy_pci_irq, cyy_interrupt,
+ IRQF_SHARED, "Cyclom-Y", &cy_card[j])) {
+ printk("Cyclom-Y/PCI found at 0x%lx ",
+ (ulong) cy_pci_phys2);
+ printk("but could not allocate IRQ%d.\n",
+ cy_pci_irq);
+ return i;
+ }
- /* print message */
- printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
- j+1,
- (ulong)cy_pci_phys2,
- (ulong)(cy_pci_phys2 + CyPCI_Ywin - 1),
- (int)cy_pci_irq);
- printk("%d channels starting from port %d.\n",
- cy_pci_nchan, cy_next_channel);
-
- cy_next_channel += cy_pci_nchan;
- }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){
- /* print message */
- printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
- pdev->bus->number, pdev->devfn);
- printk("rev_id=%d) IRQ%d\n",
- cyy_rev_id, (int)cy_pci_irq);
- printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
- (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
- printk("Cyclades-Z/PCI not supported for low addresses\n");
- break;
- }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){
+ /* set cy_card */
+ cy_card[j].base_phys = (ulong) cy_pci_phys2;
+ cy_card[j].ctl_phys = (ulong) cy_pci_phys0;
+ cy_card[j].base_addr = cy_pci_addr2;
+ cy_card[j].ctl_addr = cy_pci_addr0;
+ cy_card[j].irq = (int)cy_pci_irq;
+ cy_card[j].bus_index = 1;
+ cy_card[j].first_line = cy_next_channel;
+ cy_card[j].num_chips = cy_pci_nchan / 4;
+ cy_card[j].pdev = pdev;
+
+ /* enable interrupts in the PCI interface */
+ plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
+ switch (plx_ver) {
+ case PLX_9050:
+
+ cy_writeb(cy_pci_addr0 + 0x4c, 0x43);
+ break;
+
+ case PLX_9060:
+ case PLX_9080:
+ default: /* Old boards, use PLX_9060 */
+
+ plx_init(cy_pci_addr0, 0x6c);
+ /* For some yet unknown reason, once the PLX9060 reloads
+ the EEPROM, the IRQ is lost and, thus, we have to
+ re-write it to the PCI config. registers.
+ This will remain here until we find a permanent
+ fix. */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
+ cy_pci_irq);
+
+ cy_writew(cy_pci_addr0 + 0x68,
+ cy_readw(cy_pci_addr0 +
+ 0x68) | 0x0900);
+ break;
+ }
+
+ /* print message */
+ printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
+ j + 1, (ulong)cy_pci_phys2,
+ (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1),
+ (int)cy_pci_irq);
+ printk("%d channels starting from port %d.\n",
+ cy_pci_nchan, cy_next_channel);
+
+ cy_next_channel += cy_pci_nchan;
+ } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
+ /* print message */
+ printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
+ pdev->bus->number, pdev->devfn);
+ printk("rev_id=%d) IRQ%d\n",
+ cyy_rev_id, (int)cy_pci_irq);
+ printk("Cyclades-Z/PCI: found winaddr=0x%lx "
+ "ctladdr=0x%lx\n",
+ (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+ printk("Cyclades-Z/PCI not supported for low "
+ "addresses\n");
+ break;
+ } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
#ifdef CY_PCI_DEBUG
- printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
- pdev->bus->number, pdev->devfn);
- printk("rev_id=%d) IRQ%d\n",
- cyy_rev_id, (int)cy_pci_irq);
- printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
- (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
+ printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
+ pdev->bus->number, pdev->devfn);
+ printk("rev_id=%d) IRQ%d\n",
+ cyy_rev_id, (int)cy_pci_irq);
+ printk("Cyclades-Z/PCI: found winaddr=0x%lx "
+ "ctladdr=0x%lx\n",
+ (ulong) cy_pci_phys2, (ulong) cy_pci_phys0);
#endif
- cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
-
- /* Disable interrupts on the PLX before resetting it */
- cy_writew(cy_pci_addr0+0x68,
- cy_readw(cy_pci_addr0+0x68) & ~0x0900);
-
- plx_init(cy_pci_addr0, 0x6c);
- /* For some yet unknown reason, once the PLX9060 reloads
- the EEPROM, the IRQ is lost and, thus, we have to
- re-write it to the PCI config. registers.
- This will remain here until we find a permanent fix. */
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq);
-
- mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
- cy_pci_addr0)->mail_box_0);
-
- if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
- printk(" Warning: PCI I/O bit incorrectly set. "
- "Ignoring it...\n");
- pdev->resource[2].flags &= ~IORESOURCE_IO;
- }
+ cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
+
+ /* Disable interrupts on the PLX before resetting it */
+ cy_writew(cy_pci_addr0 + 0x68,
+ cy_readw(cy_pci_addr0 + 0x68) & ~0x0900);
+
+ plx_init(cy_pci_addr0, 0x6c);
+ /* For some yet unknown reason, once the PLX9060 reloads
+ the EEPROM, the IRQ is lost and, thus, we have to
+ re-write it to the PCI config. registers.
+ This will remain here until we find a permanent
+ fix. */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
+ cy_pci_irq);
+
+ mailbox =
+ (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
+ cy_pci_addr0)->mail_box_0);
+
+ if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+ printk(" Warning: PCI I/O bit incorrectly "
+ "set. Ignoring it...\n");
+ pdev->resource[2].flags &= ~IORESOURCE_IO;
+ }
- /* Although we don't use this I/O region, we should
- request it from the kernel anyway, to avoid problems
- with other drivers accessing it. */
- if (pci_request_regions(pdev, "Cyclades-Z") != 0) {
- printk(KERN_ERR "cyclades: failed to reserve PCI resources\n");
- continue;
- }
-
- if (mailbox == ZE_V1) {
- cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win);
- if (ZeIndex == NR_CARDS) {
- printk("Cyclades-Ze/PCI found at 0x%lx ",
- (ulong)cy_pci_phys2);
- printk("but no more cards can be used.\n");
- printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
- } else {
- Ze_phys0[ZeIndex] = cy_pci_phys0;
- Ze_phys2[ZeIndex] = cy_pci_phys2;
- Ze_addr0[ZeIndex] = cy_pci_addr0;
- Ze_addr2[ZeIndex] = cy_pci_addr2;
- Ze_irq[ZeIndex] = cy_pci_irq;
- Ze_pdev[ZeIndex] = pdev;
- ZeIndex++;
- }
- i--;
- continue;
- } else {
- cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin);
- }
+ /* Although we don't use this I/O region, we should
+ request it from the kernel anyway, to avoid problems
+ with other drivers accessing it. */
+ if (pci_request_regions(pdev, "Cyclades-Z") != 0) {
+ printk(KERN_ERR "cyclades: failed to reserve "
+ "PCI resources\n");
+ continue;
+ }
+
+ if (mailbox == ZE_V1) {
+ cy_pci_addr2 = ioremap(cy_pci_phys2,
+ CyPCI_Ze_win);
+ if (ZeIndex == NR_CARDS) {
+ printk("Cyclades-Ze/PCI found at "
+ "0x%lx but no more cards can "
+ "be used.\nChange NR_CARDS in "
+ "cyclades.c and recompile "
+ "kernel.\n",
+ (ulong)cy_pci_phys2);
+ } else {
+ Ze_phys0[ZeIndex] = cy_pci_phys0;
+ Ze_phys2[ZeIndex] = cy_pci_phys2;
+ Ze_addr0[ZeIndex] = cy_pci_addr0;
+ Ze_addr2[ZeIndex] = cy_pci_addr2;
+ Ze_irq[ZeIndex] = cy_pci_irq;
+ Ze_pdev[ZeIndex] = pdev;
+ ZeIndex++;
+ }
+ i--;
+ continue;
+ } else {
+ cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin);
+ }
#ifdef CY_PCI_DEBUG
- printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
- (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
- if (mailbox == ZO_V1) {
- cy_writel(&((struct RUNTIME_9060 *)
- (cy_pci_addr0))->loc_addr_base, WIN_CREG);
- PAUSE
- printk("Cyclades-8Zo/PCI: FPGA id %lx, ver %lx\n",
- (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *)
- (cy_pci_addr2))->fpga_id)),
- (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *)
- (cy_pci_addr2))->fpga_version)));
- cy_writel(&((struct RUNTIME_9060 *)
- (cy_pci_addr0))->loc_addr_base, WIN_RAM);
- } else {
- printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n");
- }
+ printk("Cyclades-Z/PCI: relocate winaddr=0x%lx "
+ "ctladdr=0x%lx\n",
+ (ulong) cy_pci_addr2, (ulong) cy_pci_addr0);
+ if (mailbox == ZO_V1) {
+ cy_writel(&((struct RUNTIME_9060 *)
+ (cy_pci_addr0))->loc_addr_base,
+ WIN_CREG);
+ PAUSE;
+ printk("Cyclades-8Zo/PCI: FPGA id %lx, ver "
+ "%lx\n", (ulong) (0xff &
+ cy_readl(&((struct CUSTOM_REG *)
+ (cy_pci_addr2))->fpga_id)),
+ (ulong)(0xff &
+ cy_readl(&((struct CUSTOM_REG *)
+ (cy_pci_addr2))->
+ fpga_version)));
+ cy_writel(&((struct RUNTIME_9060 *)
+ (cy_pci_addr0))->loc_addr_base,
+ WIN_RAM);
+ } else {
+ printk("Cyclades-Z/PCI: New Cyclades-Z board. "
+ "FPGA not loaded\n");
+ }
#endif
- /* The following clears the firmware id word. This ensures
- that the driver will not attempt to talk to the board
- until it has been properly initialized.
- */
- PAUSE
- if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
- cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
-
- /* This must be a Cyclades-8Zo/PCI. The extendable
- version will have a different device_id and will
- be allocated its maximum number of ports. */
- cy_pci_nchan = 8;
-
- if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
- printk("Cyclades-8Zo/PCI found at 0x%lx ",
- (ulong)cy_pci_phys2);
- printk("but no channels are available.\n");
- printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
- return(i);
- }
-
- /* fill the next cy_card structure available */
- for (j = 0 ; j < NR_CARDS ; j++) {
- if (cy_card[j].base_addr == 0) break;
- }
- if (j == NR_CARDS) { /* no more cy_cards available */
- printk("Cyclades-8Zo/PCI found at 0x%lx ",
- (ulong)cy_pci_phys2);
- printk("but no more cards can be used.\n");
- printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
- return(i);
- }
+ /* The following clears the firmware id word. This
+ ensures that the driver will not attempt to talk to
+ the board until it has been properly initialized.
+ */
+ PAUSE;
+ if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
+ cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
+
+ /* This must be a Cyclades-8Zo/PCI. The extendable
+ version will have a different device_id and will
+ be allocated its maximum number of ports. */
+ cy_pci_nchan = 8;
+
+ if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
+ printk("Cyclades-8Zo/PCI found at 0x%lx but"
+ "no channels are available.\nChange "
+ "NR_PORTS in cyclades.c and recompile "
+ "kernel.\n", (ulong)cy_pci_phys2);
+ return i;
+ }
+ /* fill the next cy_card structure available */
+ for (j = 0; j < NR_CARDS; j++) {
+ if (cy_card[j].base_addr == 0)
+ break;
+ }
+ if (j == NR_CARDS) { /* no more cy_cards available */
+ printk("Cyclades-8Zo/PCI found at 0x%lx but"
+ "no more cards can be used.\nChange "
+ "NR_CARDS in cyclades.c and recompile "
+ "kernel.\n", (ulong)cy_pci_phys2);
+ return i;
+ }
+#ifdef CONFIG_CYZ_INTR
+ /* allocate IRQ only if board has an IRQ */
+ if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) {
+ if (request_irq(cy_pci_irq, cyz_interrupt,
+ IRQF_SHARED, "Cyclades-Z",
+ &cy_card[j])) {
+ printk("Cyclom-8Zo/PCI found at 0x%lx "
+ "but could not allocate "
+ "IRQ%d.\n", (ulong)cy_pci_phys2,
+ cy_pci_irq);
+ return i;
+ }
+ }
+#endif /* CONFIG_CYZ_INTR */
+
+ /* set cy_card */
+ cy_card[j].base_phys = cy_pci_phys2;
+ cy_card[j].ctl_phys = cy_pci_phys0;
+ cy_card[j].base_addr = cy_pci_addr2;
+ cy_card[j].ctl_addr = cy_pci_addr0;
+ cy_card[j].irq = (int)cy_pci_irq;
+ cy_card[j].bus_index = 1;
+ cy_card[j].first_line = cy_next_channel;
+ cy_card[j].num_chips = -1;
+ cy_card[j].pdev = pdev;
+
+ /* print message */
#ifdef CONFIG_CYZ_INTR
- /* allocate IRQ only if board has an IRQ */
- if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
- if(request_irq(cy_pci_irq, cyz_interrupt,
- IRQF_SHARED, "Cyclades-Z", &cy_card[j]))
- {
- printk("Cyclom-8Zo/PCI found at 0x%lx ",
- (ulong) cy_pci_phys2);
- printk("but could not allocate IRQ%d.\n",
- cy_pci_irq);
- return(i);
- }
+ /* don't report IRQ if board is no IRQ */
+ if ((cy_pci_irq != 0) && (cy_pci_irq != 255))
+ printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, "
+ "IRQ%d, ", j + 1, (ulong)cy_pci_phys2,
+ (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1),
+ (int)cy_pci_irq);
+ else
+#endif /* CONFIG_CYZ_INTR */
+ printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ",
+ j + 1, (ulong)cy_pci_phys2,
+ (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1));
+
+ printk("%d channels starting from port %d.\n",
+ cy_pci_nchan, cy_next_channel);
+ cy_next_channel += cy_pci_nchan;
}
-#endif /* CONFIG_CYZ_INTR */
-
-
- /* set cy_card */
- cy_card[j].base_phys = cy_pci_phys2;
- cy_card[j].ctl_phys = cy_pci_phys0;
- cy_card[j].base_addr = cy_pci_addr2;
- cy_card[j].ctl_addr = cy_pci_addr0;
- cy_card[j].irq = (int) cy_pci_irq;
- cy_card[j].bus_index = 1;
- cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = -1;
- cy_card[j].pdev = pdev;
+ }
- /* print message */
-#ifdef CONFIG_CYZ_INTR
- /* don't report IRQ if board is no IRQ */
- if( (cy_pci_irq != 0) && (cy_pci_irq != 255) )
- printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
- j+1,(ulong)cy_pci_phys2,
- (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1),
- (int)cy_pci_irq);
- else
-#endif /* CONFIG_CYZ_INTR */
- printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ",
- j+1,(ulong)cy_pci_phys2,
- (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1));
-
- printk("%d channels starting from port %d.\n",
- cy_pci_nchan,cy_next_channel);
- cy_next_channel += cy_pci_nchan;
- }
- }
-
- for (; ZeIndex != 0 && i < NR_CARDS; i++) {
- cy_pci_phys0 = Ze_phys0[0];
- cy_pci_phys2 = Ze_phys2[0];
- cy_pci_addr0 = Ze_addr0[0];
- cy_pci_addr2 = Ze_addr2[0];
- cy_pci_irq = Ze_irq[0];
- pdev = Ze_pdev[0];
- for (j = 0 ; j < ZeIndex-1 ; j++) {
- Ze_phys0[j] = Ze_phys0[j+1];
- Ze_phys2[j] = Ze_phys2[j+1];
- Ze_addr0[j] = Ze_addr0[j+1];
- Ze_addr2[j] = Ze_addr2[j+1];
- Ze_irq[j] = Ze_irq[j+1];
- Ze_pdev[j] = Ze_pdev[j+1];
- }
- ZeIndex--;
- mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
- cy_pci_addr0)->mail_box_0);
+ for (; ZeIndex != 0 && i < NR_CARDS; i++) {
+ cy_pci_phys0 = Ze_phys0[0];
+ cy_pci_phys2 = Ze_phys2[0];
+ cy_pci_addr0 = Ze_addr0[0];
+ cy_pci_addr2 = Ze_addr2[0];
+ cy_pci_irq = Ze_irq[0];
+ pdev = Ze_pdev[0];
+ for (j = 0; j < ZeIndex - 1; j++) {
+ Ze_phys0[j] = Ze_phys0[j + 1];
+ Ze_phys2[j] = Ze_phys2[j + 1];
+ Ze_addr0[j] = Ze_addr0[j + 1];
+ Ze_addr2[j] = Ze_addr2[j + 1];
+ Ze_irq[j] = Ze_irq[j + 1];
+ Ze_pdev[j] = Ze_pdev[j + 1];
+ }
+ ZeIndex--;
+ mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *)
+ cy_pci_addr0)->mail_box_0);
#ifdef CY_PCI_DEBUG
- printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
- (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
- printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n");
+ printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
+ (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
+ printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not "
+ "loaded\n");
#endif
- PAUSE
- /* This must be the new Cyclades-Ze/PCI. */
- cy_pci_nchan = ZE_V1_NPORTS;
-
- if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
- printk("Cyclades-Ze/PCI found at 0x%lx ",
- (ulong)cy_pci_phys2);
- printk("but no channels are available.\n");
- printk("Change NR_PORTS in cyclades.c and recompile kernel.\n");
- return(i);
- }
-
- /* fill the next cy_card structure available */
- for (j = 0 ; j < NR_CARDS ; j++) {
- if (cy_card[j].base_addr == 0) break;
- }
- if (j == NR_CARDS) { /* no more cy_cards available */
- printk("Cyclades-Ze/PCI found at 0x%lx ",
- (ulong)cy_pci_phys2);
- printk("but no more cards can be used.\n");
- printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
- return(i);
- }
+ PAUSE;
+ /* This must be the new Cyclades-Ze/PCI. */
+ cy_pci_nchan = ZE_V1_NPORTS;
+
+ if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) {
+ printk("Cyclades-Ze/PCI found at 0x%lx but no channels "
+ "are available.\nChange NR_PORTS in cyclades.c "
+ "and recompile kernel.\n",
+ (ulong) cy_pci_phys2);
+ return i;
+ }
+ /* fill the next cy_card structure available */
+ for (j = 0; j < NR_CARDS; j++) {
+ if (cy_card[j].base_addr == 0)
+ break;
+ }
+ if (j == NR_CARDS) { /* no more cy_cards available */
+ printk("Cyclades-Ze/PCI found at 0x%lx but no more "
+ "cards can be used.\nChange NR_CARDS in "
+ "cyclades.c and recompile kernel.\n",
+ (ulong) cy_pci_phys2);
+ return i;
+ }
#ifdef CONFIG_CYZ_INTR
- /* allocate IRQ only if board has an IRQ */
- if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
- if(request_irq(cy_pci_irq, cyz_interrupt,
- IRQF_SHARED, "Cyclades-Z", &cy_card[j]))
- {
- printk("Cyclom-Ze/PCI found at 0x%lx ",
- (ulong) cy_pci_phys2);
- printk("but could not allocate IRQ%d.\n",
- cy_pci_irq);
- return(i);
- }
+ /* allocate IRQ only if board has an IRQ */
+ if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) {
+ if (request_irq(cy_pci_irq, cyz_interrupt,
+ IRQF_SHARED, "Cyclades-Z",
+ &cy_card[j])) {
+ printk("Cyclom-Ze/PCI found at 0x%lx ",
+ (ulong) cy_pci_phys2);
+ printk("but could not allocate IRQ%d.\n",
+ cy_pci_irq);
+ return i;
+ }
}
-#endif /* CONFIG_CYZ_INTR */
-
- /* set cy_card */
- cy_card[j].base_phys = cy_pci_phys2;
- cy_card[j].ctl_phys = cy_pci_phys0;
- cy_card[j].base_addr = cy_pci_addr2;
- cy_card[j].ctl_addr = cy_pci_addr0;
- cy_card[j].irq = (int) cy_pci_irq;
- cy_card[j].bus_index = 1;
- cy_card[j].first_line = cy_next_channel;
- cy_card[j].num_chips = -1;
+#endif /* CONFIG_CYZ_INTR */
+
+ /* set cy_card */
+ cy_card[j].base_phys = cy_pci_phys2;
+ cy_card[j].ctl_phys = cy_pci_phys0;
+ cy_card[j].base_addr = cy_pci_addr2;
+ cy_card[j].ctl_addr = cy_pci_addr0;
+ cy_card[j].irq = (int)cy_pci_irq;
+ cy_card[j].bus_index = 1;
+ cy_card[j].first_line = cy_next_channel;
+ cy_card[j].num_chips = -1;
cy_card[j].pdev = pdev;
- /* print message */
+ /* print message */
#ifdef CONFIG_CYZ_INTR
/* don't report IRQ if board is no IRQ */
- if( (cy_pci_irq != 0) && (cy_pci_irq != 255) )
- printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
- j+1,(ulong)cy_pci_phys2,
- (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1),
- (int)cy_pci_irq);
+ if ((cy_pci_irq != 0) && (cy_pci_irq != 255))
+ printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
+ j + 1, (ulong) cy_pci_phys2,
+ (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1),
+ (int)cy_pci_irq);
else
-#endif /* CONFIG_CYZ_INTR */
- printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ",
- j+1,(ulong)cy_pci_phys2,
- (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1));
-
- printk("%d channels starting from port %d.\n",
- cy_pci_nchan,cy_next_channel);
- cy_next_channel += cy_pci_nchan;
- }
+#endif /* CONFIG_CYZ_INTR */
+ printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ",
+ j + 1, (ulong) cy_pci_phys2,
+ (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1));
+
+ printk("%d channels starting from port %d.\n",
+ cy_pci_nchan, cy_next_channel);
+ cy_next_channel += cy_pci_nchan;
+ }
if (ZeIndex != 0) {
- printk("Cyclades-Ze/PCI found at 0x%x ",
- (unsigned int) Ze_phys2[0]);
- printk("but no more cards can be used.\n");
- printk("Change NR_CARDS in cyclades.c and recompile kernel.\n");
+ printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be "
+ "used.\nChange NR_CARDS in cyclades.c and recompile "
+ "kernel.\n", (unsigned int)Ze_phys2[0]);
}
- return(i);
+ return i;
#else
- return(0);
-#endif /* ifdef CONFIG_PCI */
-} /* cy_detect_pci */
-
+ return 0;
+#endif /* ifdef CONFIG_PCI */
+} /* cy_detect_pci */
/*
* This routine prints out the appropriate serial driver version number
* and identifies which options were configured into this driver.
*/
-static inline void
-show_version(void)
+static inline void show_version(void)
{
- char *rcsvers, *rcsdate, *tmp;
- rcsvers = strchr(rcsid, ' '); rcsvers++;
- tmp = strchr(rcsvers, ' '); *tmp++ = '\0';
- rcsdate = strchr(tmp, ' '); rcsdate++;
- tmp = strrchr(rcsdate, ' '); *tmp = '\0';
- printk("Cyclades driver %s %s\n",
- rcsvers, rcsdate);
- printk(" built %s %s\n",
- __DATE__, __TIME__);
-} /* show_version */
-
-static int
+ printk("Cyclades driver " CY_VERSION "\n");
+ printk(" built %s %s\n", __DATE__, __TIME__);
+} /* show_version */
+
+static int
cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
- int *eof, void *data)
+ int *eof, void *data)
{
- struct cyclades_port *info;
- int i;
- int len=0;
- off_t begin=0;
- off_t pos=0;
- int size;
- __u32 cur_jifs = jiffies;
-
- size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn IdleIn Overruns Ldisc\n");
-
- pos += size;
- len += size;
-
- /* Output one line for each known port */
- for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) {
- info = &cy_port[i];
-
- if (info->count)
- size = sprintf(buf+len,
- "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n",
- info->line,
- JIFFIES_DIFF(info->idle_stats.in_use, cur_jifs) / HZ,
- info->idle_stats.xmit_bytes,
- JIFFIES_DIFF(info->idle_stats.xmit_idle, cur_jifs) / HZ,
- info->idle_stats.recv_bytes,
- JIFFIES_DIFF(info->idle_stats.recv_idle, cur_jifs) / HZ,
- info->idle_stats.overruns,
- (long) info->tty->ldisc.num);
- else
- size = sprintf(buf+len,
- "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n",
- info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
+ struct cyclades_port *info;
+ int i;
+ int len = 0;
+ off_t begin = 0;
+ off_t pos = 0;
+ int size;
+ __u32 cur_jifs = jiffies;
+
+ size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn "
+ "IdleIn Overruns Ldisc\n");
+
+ pos += size;
len += size;
- pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
+ /* Output one line for each known port */
+ for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) {
+ info = &cy_port[i];
+
+ if (info->count)
+ size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
+ "%8lu %9lu %6ld\n", info->line,
+ (cur_jifs - info->idle_stats.in_use) / HZ,
+ info->idle_stats.xmit_bytes,
+ (cur_jifs - info->idle_stats.xmit_idle) / HZ,
+ info->idle_stats.recv_bytes,
+ (cur_jifs - info->idle_stats.recv_idle) / HZ,
+ info->idle_stats.overruns,
+ (long)info->tty->ldisc.num);
+ else
+ size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu "
+ "%8lu %9lu %6ld\n",
+ info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
+ len += size;
+ pos = begin + len;
+
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ goto done;
}
- if (pos > offset + length)
- goto done;
- }
- *eof = 1;
+ *eof = 1;
done:
- *start = buf + (offset - begin); /* Start of wanted data */
- len -= (offset - begin); /* Start slop */
- if (len > length)
- len = length; /* Ending slop */
- if (len < 0)
- len = 0;
- return len;
+ *start = buf + (offset - begin); /* Start of wanted data */
+ len -= (offset - begin); /* Start slop */
+ if (len > length)
+ len = length; /* Ending slop */
+ if (len < 0)
+ len = 0;
+ return len;
}
/* The serial driver boot-time initialization code!
@@ -5185,290 +5294,288 @@ done:
*/
static const struct tty_operations cy_ops = {
- .open = cy_open,
- .close = cy_close,
- .write = cy_write,
- .put_char = cy_put_char,
- .flush_chars = cy_flush_chars,
- .write_room = cy_write_room,
- .chars_in_buffer = cy_chars_in_buffer,
- .flush_buffer = cy_flush_buffer,
- .ioctl = cy_ioctl,
- .throttle = cy_throttle,
- .unthrottle = cy_unthrottle,
- .set_termios = cy_set_termios,
- .stop = cy_stop,
- .start = cy_start,
- .hangup = cy_hangup,
- .break_ctl = cy_break,
- .wait_until_sent = cy_wait_until_sent,
- .read_proc = cyclades_get_proc_info,
- .tiocmget = cy_tiocmget,
- .tiocmset = cy_tiocmset,
+ .open = cy_open,
+ .close = cy_close,
+ .write = cy_write,
+ .put_char = cy_put_char,
+ .flush_chars = cy_flush_chars,
+ .write_room = cy_write_room,
+ .chars_in_buffer = cy_chars_in_buffer,
+ .flush_buffer = cy_flush_buffer,
+ .ioctl = cy_ioctl,
+ .throttle = cy_throttle,
+ .unthrottle = cy_unthrottle,
+ .set_termios = cy_set_termios,
+ .stop = cy_stop,
+ .start = cy_start,
+ .hangup = cy_hangup,
+ .break_ctl = cy_break,
+ .wait_until_sent = cy_wait_until_sent,
+ .read_proc = cyclades_get_proc_info,
+ .tiocmget = cy_tiocmget,
+ .tiocmset = cy_tiocmset,
};
-static int __init
-cy_init(void)
+static int __init cy_init(void)
{
- struct cyclades_port *info;
- struct cyclades_card *cinfo;
- int number_z_boards = 0;
- int board,port,i,index;
- unsigned long mailbox;
- unsigned short chip_number;
- int nports;
-
- cy_serial_driver = alloc_tty_driver(NR_PORTS);
- if (!cy_serial_driver)
- return -ENOMEM;
- show_version();
-
- /* Initialize the tty_driver structure */
-
- cy_serial_driver->owner = THIS_MODULE;
- cy_serial_driver->driver_name = "cyclades";
- cy_serial_driver->name = "ttyC";
- cy_serial_driver->major = CYCLADES_MAJOR;
- cy_serial_driver->minor_start = 0;
- cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
- cy_serial_driver->init_termios = tty_std_termios;
- cy_serial_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(cy_serial_driver, &cy_ops);
-
- if (tty_register_driver(cy_serial_driver))
- panic("Couldn't register Cyclades serial driver\n");
-
- for (i = 0; i < NR_CARDS; i++) {
- /* base_addr=0 indicates board not found */
- cy_card[i].base_addr = NULL;
- }
-
- /* the code below is responsible to find the boards. Each different
- type of board has its own detection routine. If a board is found,
- the next cy_card structure available is set by the detection
- routine. These functions are responsible for checking the
- availability of cy_card and cy_port data structures and updating
- the cy_next_channel. */
-
- /* look for isa boards */
- cy_isa_nboard = cy_detect_isa();
-
- /* look for pci boards */
- cy_pci_nboard = cy_detect_pci();
-
- cy_nboard = cy_isa_nboard + cy_pci_nboard;
-
- /* invalidate remaining cy_card structures */
- for (i = 0 ; i < NR_CARDS ; i++) {
- if (cy_card[i].base_addr == 0) {
- cy_card[i].first_line = -1;
- cy_card[i].ctl_addr = NULL;
- cy_card[i].irq = 0;
- cy_card[i].bus_index = 0;
- cy_card[i].first_line = 0;
- cy_card[i].num_chips = 0;
- }
- }
- /* invalidate remaining cy_port structures */
- for (i = cy_next_channel ; i < NR_PORTS ; i++) {
- cy_port[i].line = -1;
- cy_port[i].magic = -1;
- }
-
- /* initialize per-port data structures for each valid board found */
- for (board = 0 ; board < cy_nboard ; board++) {
- cinfo = &cy_card[board];
- if (cinfo->num_chips == -1) { /* Cyclades-Z */
- number_z_boards++;
- mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
- cy_card[board].ctl_addr)->mail_box_0);
- nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
- cinfo->intr_enabled = 0;
- cinfo->nports = 0; /* Will be correctly set later, after
- Z FW is loaded */
- spin_lock_init(&cinfo->card_lock);
- for (port = cinfo->first_line ;
- port < cinfo->first_line + nports;
- port++)
- {
- info = &cy_port[port];
- info->magic = CYCLADES_MAGIC;
- info->type = PORT_STARTECH;
- info->card = board;
- info->line = port;
- info->chip_rev = 0;
- info->flags = STD_COM_FLAGS;
- info->tty = NULL;
- if (mailbox == ZO_V1)
- info->xmit_fifo_size = CYZ_FIFO_SIZE;
- else
- info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
- info->cor1 = 0;
- info->cor2 = 0;
- info->cor3 = 0;
- info->cor4 = 0;
- info->cor5 = 0;
- info->tbpr = 0;
- info->tco = 0;
- info->rbpr = 0;
- info->rco = 0;
- info->custom_divisor = 0;
- info->close_delay = 5*HZ/10;
- info->closing_wait = CLOSING_WAIT_DELAY;
- info->icount.cts = info->icount.dsr =
- info->icount.rng = info->icount.dcd = 0;
- info->icount.rx = info->icount.tx = 0;
- info->icount.frame = info->icount.parity = 0;
- info->icount.overrun = info->icount.brk = 0;
- info->x_char = 0;
- info->event = 0;
- info->count = 0;
- info->blocked_open = 0;
- info->default_threshold = 0;
- info->default_timeout = 0;
- INIT_WORK(&info->tqueue, do_softint);
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- init_waitqueue_head(&info->shutdown_wait);
- init_waitqueue_head(&info->delta_msr_wait);
- /* info->session */
- /* info->pgrp */
- info->read_status_mask = 0;
- /* info->timeout */
- /* Bentson's vars */
- info->jiffies[0] = 0;
- info->jiffies[1] = 0;
- info->jiffies[2] = 0;
- info->rflush_count = 0;
+ struct cyclades_port *info;
+ struct cyclades_card *cinfo;
+ int number_z_boards = 0;
+ int board, port, i, index;
+ unsigned long mailbox;
+ unsigned short chip_number;
+ int nports;
+
+ cy_serial_driver = alloc_tty_driver(NR_PORTS);
+ if (!cy_serial_driver)
+ return -ENOMEM;
+ show_version();
+
+ /* Initialize the tty_driver structure */
+
+ cy_serial_driver->owner = THIS_MODULE;
+ cy_serial_driver->driver_name = "cyclades";
+ cy_serial_driver->name = "ttyC";
+ cy_serial_driver->major = CYCLADES_MAJOR;
+ cy_serial_driver->minor_start = 0;
+ cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+ cy_serial_driver->init_termios = tty_std_termios;
+ cy_serial_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(cy_serial_driver, &cy_ops);
+
+ if (tty_register_driver(cy_serial_driver))
+ panic("Couldn't register Cyclades serial driver\n");
+
+ for (i = 0; i < NR_CARDS; i++) {
+ /* base_addr=0 indicates board not found */
+ cy_card[i].base_addr = NULL;
+ }
+
+ /* the code below is responsible to find the boards. Each different
+ type of board has its own detection routine. If a board is found,
+ the next cy_card structure available is set by the detection
+ routine. These functions are responsible for checking the
+ availability of cy_card and cy_port data structures and updating
+ the cy_next_channel. */
+
+ /* look for isa boards */
+ cy_isa_nboard = cy_detect_isa();
+
+ /* look for pci boards */
+ cy_pci_nboard = cy_detect_pci();
+
+ cy_nboard = cy_isa_nboard + cy_pci_nboard;
+
+ /* invalidate remaining cy_card structures */
+ for (i = 0; i < NR_CARDS; i++) {
+ if (cy_card[i].base_addr == 0) {
+ cy_card[i].first_line = -1;
+ cy_card[i].ctl_addr = NULL;
+ cy_card[i].irq = 0;
+ cy_card[i].bus_index = 0;
+ cy_card[i].first_line = 0;
+ cy_card[i].num_chips = 0;
+ }
+ }
+ /* invalidate remaining cy_port structures */
+ for (i = cy_next_channel; i < NR_PORTS; i++) {
+ cy_port[i].line = -1;
+ cy_port[i].magic = -1;
+ }
+
+ /* initialize per-port data structures for each valid board found */
+ for (board = 0; board < cy_nboard; board++) {
+ cinfo = &cy_card[board];
+ if (cinfo->num_chips == -1) { /* Cyclades-Z */
+ number_z_boards++;
+ mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
+ cy_card[board].ctl_addr)->
+ mail_box_0);
+ nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
+ cinfo->intr_enabled = 0;
+ cinfo->nports = 0; /* Will be correctly set later, after
+ Z FW is loaded */
+ spin_lock_init(&cinfo->card_lock);
+ for (port = cinfo->first_line;
+ port < cinfo->first_line + nports; port++) {
+ info = &cy_port[port];
+ info->magic = CYCLADES_MAGIC;
+ info->type = PORT_STARTECH;
+ info->card = board;
+ info->line = port;
+ info->chip_rev = 0;
+ info->flags = STD_COM_FLAGS;
+ info->tty = NULL;
+ if (mailbox == ZO_V1)
+ info->xmit_fifo_size = CYZ_FIFO_SIZE;
+ else
+ info->xmit_fifo_size =
+ 4 * CYZ_FIFO_SIZE;
+ info->cor1 = 0;
+ info->cor2 = 0;
+ info->cor3 = 0;
+ info->cor4 = 0;
+ info->cor5 = 0;
+ info->tbpr = 0;
+ info->tco = 0;
+ info->rbpr = 0;
+ info->rco = 0;
+ info->custom_divisor = 0;
+ info->close_delay = 5 * HZ / 10;
+ info->closing_wait = CLOSING_WAIT_DELAY;
+ info->icount.cts = info->icount.dsr =
+ info->icount.rng = info->icount.dcd = 0;
+ info->icount.rx = info->icount.tx = 0;
+ info->icount.frame = info->icount.parity = 0;
+ info->icount.overrun = info->icount.brk = 0;
+ info->x_char = 0;
+ info->event = 0;
+ info->count = 0;
+ info->blocked_open = 0;
+ info->default_threshold = 0;
+ info->default_timeout = 0;
+ INIT_WORK(&info->tqueue, do_softint);
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->shutdown_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+ /* info->session */
+ /* info->pgrp */
+ info->read_status_mask = 0;
+ /* info->timeout */
+ /* Bentson's vars */
+ info->jiffies[0] = 0;
+ info->jiffies[1] = 0;
+ info->jiffies[2] = 0;
+ info->rflush_count = 0;
#ifdef CONFIG_CYZ_INTR
- init_timer(&cyz_rx_full_timer[port]);
- cyz_rx_full_timer[port].function = NULL;
+ init_timer(&cyz_rx_full_timer[port]);
+ cyz_rx_full_timer[port].function = NULL;
#endif
- }
- continue;
- }else{ /* Cyclom-Y of some kind*/
- index = cinfo->bus_index;
- spin_lock_init(&cinfo->card_lock);
- cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
- for (port = cinfo->first_line ;
- port < cinfo->first_line + cinfo->nports ;
- port++)
- {
- info = &cy_port[port];
- info->magic = CYCLADES_MAGIC;
- info->type = PORT_CIRRUS;
- info->card = board;
- info->line = port;
- info->flags = STD_COM_FLAGS;
- info->tty = NULL;
- info->xmit_fifo_size = CyMAX_CHAR_FIFO;
- info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS;
- info->cor2 = CyETC;
- info->cor3 = 0x08; /* _very_ small rcv threshold */
- info->cor4 = 0;
- info->cor5 = 0;
- info->custom_divisor = 0;
- info->close_delay = 5*HZ/10;
- info->closing_wait = CLOSING_WAIT_DELAY;
- info->icount.cts = info->icount.dsr =
- info->icount.rng = info->icount.dcd = 0;
- info->icount.rx = info->icount.tx = 0;
- info->icount.frame = info->icount.parity = 0;
- info->icount.overrun = info->icount.brk = 0;
- chip_number = (port - cinfo->first_line) / 4;
- if ((info->chip_rev =
- cy_readb(cinfo->base_addr +
- (cy_chip_offset[chip_number]<<index) +
- (CyGFRCR<<index))) >= CD1400_REV_J) {
- /* It is a CD1400 rev. J or later */
- info->tbpr = baud_bpr_60[13]; /* Tx BPR */
- info->tco = baud_co_60[13]; /* Tx CO */
- info->rbpr = baud_bpr_60[13]; /* Rx BPR */
- info->rco = baud_co_60[13]; /* Rx CO */
- info->rflow = 0;
- info->rtsdtr_inv = 1;
- } else {
- info->tbpr = baud_bpr_25[13]; /* Tx BPR */
- info->tco = baud_co_25[13]; /* Tx CO */
- info->rbpr = baud_bpr_25[13]; /* Rx BPR */
- info->rco = baud_co_25[13]; /* Rx CO */
- info->rflow = 0;
- info->rtsdtr_inv = 0;
- }
- info->x_char = 0;
- info->event = 0;
- info->count = 0;
- info->blocked_open = 0;
- info->default_threshold = 0;
- info->default_timeout = 0;
- INIT_WORK(&info->tqueue, do_softint);
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- init_waitqueue_head(&info->shutdown_wait);
- init_waitqueue_head(&info->delta_msr_wait);
- /* info->session */
- /* info->pgrp */
- info->read_status_mask =
- CyTIMEOUT| CySPECHAR| CyBREAK
- | CyPARITY| CyFRAME| CyOVERRUN;
- /* info->timeout */
- }
- }
- }
+ }
+ continue;
+ } else { /* Cyclom-Y of some kind */
+ index = cinfo->bus_index;
+ spin_lock_init(&cinfo->card_lock);
+ cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
+ for (port = cinfo->first_line;
+ port < cinfo->first_line + cinfo->nports; port++) {
+ info = &cy_port[port];
+ info->magic = CYCLADES_MAGIC;
+ info->type = PORT_CIRRUS;
+ info->card = board;
+ info->line = port;
+ info->flags = STD_COM_FLAGS;
+ info->tty = NULL;
+ info->xmit_fifo_size = CyMAX_CHAR_FIFO;
+ info->cor1 =
+ CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
+ info->cor2 = CyETC;
+ info->cor3 = 0x08; /* _very_ small rcv threshold */
+ info->cor4 = 0;
+ info->cor5 = 0;
+ info->custom_divisor = 0;
+ info->close_delay = 5 * HZ / 10;
+ info->closing_wait = CLOSING_WAIT_DELAY;
+ info->icount.cts = info->icount.dsr =
+ info->icount.rng = info->icount.dcd = 0;
+ info->icount.rx = info->icount.tx = 0;
+ info->icount.frame = info->icount.parity = 0;
+ info->icount.overrun = info->icount.brk = 0;
+ chip_number = (port - cinfo->first_line) / 4;
+ if ((info->chip_rev =
+ cy_readb(cinfo->base_addr +
+ (cy_chip_offset[chip_number] <<
+ index) + (CyGFRCR << index))) >=
+ CD1400_REV_J) {
+ /* It is a CD1400 rev. J or later */
+ info->tbpr = baud_bpr_60[13]; /* Tx BPR */
+ info->tco = baud_co_60[13]; /* Tx CO */
+ info->rbpr = baud_bpr_60[13]; /* Rx BPR */
+ info->rco = baud_co_60[13]; /* Rx CO */
+ info->rflow = 0;
+ info->rtsdtr_inv = 1;
+ } else {
+ info->tbpr = baud_bpr_25[13]; /* Tx BPR */
+ info->tco = baud_co_25[13]; /* Tx CO */
+ info->rbpr = baud_bpr_25[13]; /* Rx BPR */
+ info->rco = baud_co_25[13]; /* Rx CO */
+ info->rflow = 0;
+ info->rtsdtr_inv = 0;
+ }
+ info->x_char = 0;
+ info->event = 0;
+ info->count = 0;
+ info->blocked_open = 0;
+ info->default_threshold = 0;
+ info->default_timeout = 0;
+ INIT_WORK(&info->tqueue, do_softint);
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->shutdown_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+ /* info->session */
+ /* info->pgrp */
+ info->read_status_mask =
+ CyTIMEOUT | CySPECHAR | CyBREAK
+ | CyPARITY | CyFRAME | CyOVERRUN;
+ /* info->timeout */
+ }
+ }
+ }
#ifndef CONFIG_CYZ_INTR
- if (number_z_boards && !cyz_timeron){
- cyz_timeron++;
- cyz_timerlist.expires = jiffies + 1;
- add_timer(&cyz_timerlist);
+ if (number_z_boards && !cyz_timeron) {
+ cyz_timeron++;
+ cyz_timerlist.expires = jiffies + 1;
+ add_timer(&cyz_timerlist);
#ifdef CY_PCI_DEBUG
- printk("Cyclades-Z polling initialized\n");
+ printk("Cyclades-Z polling initialized\n");
#endif
- }
-#endif /* CONFIG_CYZ_INTR */
+ }
+#endif /* CONFIG_CYZ_INTR */
+
+ return 0;
- return 0;
-
-} /* cy_init */
+} /* cy_init */
-static void __exit
-cy_cleanup_module(void)
+static void __exit cy_cleanup_module(void)
{
- int i, e1;
+ int i, e1;
#ifndef CONFIG_CYZ_INTR
- if (cyz_timeron){
- cyz_timeron = 0;
- del_timer(&cyz_timerlist);
- }
+ if (cyz_timeron){
+ cyz_timeron = 0;
+ del_timer(&cyz_timerlist);
+ }
#endif /* CONFIG_CYZ_INTR */
- if ((e1 = tty_unregister_driver(cy_serial_driver)))
- printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
- e1);
+ if ((e1 = tty_unregister_driver(cy_serial_driver)))
+ printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
+ e1);
- put_tty_driver(cy_serial_driver);
+ put_tty_driver(cy_serial_driver);
- for (i = 0; i < NR_CARDS; i++) {
- if (cy_card[i].base_addr) {
- iounmap(cy_card[i].base_addr);
- if (cy_card[i].ctl_addr)
- iounmap(cy_card[i].ctl_addr);
- if (cy_card[i].irq
+ for (i = 0; i < NR_CARDS; i++) {
+ if (cy_card[i].base_addr) {
+ iounmap(cy_card[i].base_addr);
+ if (cy_card[i].ctl_addr)
+ iounmap(cy_card[i].ctl_addr);
+ if (cy_card[i].irq
#ifndef CONFIG_CYZ_INTR
- && cy_card[i].num_chips != -1 /* not a Z card */
+ && cy_card[i].num_chips != -1 /* not a Z card */
#endif /* CONFIG_CYZ_INTR */
- )
- free_irq(cy_card[i].irq, &cy_card[i]);
+ )
+ free_irq(cy_card[i].irq, &cy_card[i]);
#ifdef CONFIG_PCI
- if (cy_card[i].pdev)
- pci_release_regions(cy_card[i].pdev);
+ if (cy_card[i].pdev)
+ pci_release_regions(cy_card[i].pdev);
#endif
- }
- }
+ }
+ }
} /* cy_cleanup_module */
module_init(cy_init);
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 5642ac43e0f..8db9041e306 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -117,6 +117,14 @@ typedef struct drm_clip_rect {
} drm_clip_rect_t;
/**
+ * Drawable information.
+ */
+typedef struct drm_drawable_info {
+ unsigned int num_rects;
+ drm_clip_rect_t *rects;
+} drm_drawable_info_t;
+
+/**
* Texture region,
*/
typedef struct drm_tex_region {
@@ -348,7 +356,8 @@ typedef struct drm_buf_desc {
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
_DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
- _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */
+ _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */
+ _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
} flags;
unsigned long agp_start; /**<
* Start address of where the AGP buffers are
@@ -444,6 +453,20 @@ typedef struct drm_draw {
} drm_draw_t;
/**
+ * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
+ */
+typedef enum {
+ DRM_DRAWABLE_CLIPRECTS,
+} drm_drawable_info_type_t;
+
+typedef struct drm_update_draw {
+ drm_drawable_t handle;
+ unsigned int type;
+ unsigned int num;
+ unsigned long long data;
+} drm_update_draw_t;
+
+/**
* DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
*/
typedef struct drm_auth {
@@ -465,10 +488,14 @@ typedef struct drm_irq_busid {
typedef enum {
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
+ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
} drm_vblank_seq_type_t;
-#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
+#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
+ _DRM_VBLANK_NEXTONMISS)
struct drm_wait_vblank_request {
drm_vblank_seq_type_t type;
@@ -623,6 +650,8 @@ typedef struct drm_set_version {
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
+#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t)
+
/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x79.
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 7690a59ace0..6dcdceb8120 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -97,6 +97,7 @@
#define DRIVER_IRQ_VBL 0x100
#define DRIVER_DMA_QUEUE 0x200
#define DRIVER_FB_DMA 0x400
+#define DRIVER_IRQ_VBL2 0x800
/***********************************************************************/
/** \name Begin the DRM... */
@@ -430,7 +431,8 @@ typedef struct drm_device_dma {
enum {
_DRM_DMA_USE_AGP = 0x01,
_DRM_DMA_USE_SG = 0x02,
- _DRM_DMA_USE_FB = 0x04
+ _DRM_DMA_USE_FB = 0x04,
+ _DRM_DMA_USE_PCI_RO = 0x08
} flags;
} drm_device_dma_t;
@@ -559,9 +561,9 @@ struct drm_driver {
int (*context_dtor) (struct drm_device * dev, int context);
int (*kernel_context_switch) (struct drm_device * dev, int old,
int new);
- void (*kernel_context_switch_unlock) (struct drm_device * dev,
- drm_lock_t *lock);
+ void (*kernel_context_switch_unlock) (struct drm_device * dev);
int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
+ int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence);
int (*dri_library_name) (struct drm_device *dev, char *buf);
/**
@@ -708,9 +710,13 @@ typedef struct drm_device {
wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
atomic_t vbl_received;
+ atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
spinlock_t vbl_lock;
drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
+ drm_vbl_sig_t vbl_sigs2; /**< signals to send on secondary VBLANK */
unsigned int vbl_pending;
+ spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
+ void (*locked_tasklet_func)(struct drm_device *dev);
/*@} */
cycles_t ctx_start;
@@ -738,6 +744,15 @@ typedef struct drm_device {
drm_local_map_t *agp_buffer_map;
unsigned int agp_buffer_token;
drm_head_t primary; /**< primary screen head */
+
+ /** \name Drawable information */
+ /*@{ */
+ spinlock_t drw_lock;
+ unsigned int drw_bitfield_length;
+ u32 *drw_bitfield;
+ unsigned int drw_info_length;
+ drm_drawable_info_t **drw_info;
+ /*@} */
} drm_device_t;
static __inline__ int drm_core_check_feature(struct drm_device *dev,
@@ -885,6 +900,10 @@ extern int drm_adddraw(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_rmdraw(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
+ drm_drawable_t id);
/* Authentication IOCTL support (drm_auth.h) */
extern int drm_getmagic(struct inode *inode, struct file *filp,
@@ -949,6 +968,7 @@ extern int drm_wait_vblank(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
extern void drm_vbl_send_signals(drm_device_t * dev);
+extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*));
/* AGP/GART support (drm_agpsupport.h) */
extern drm_agp_head_t *drm_agp_init(drm_device_t * dev);
@@ -1122,9 +1142,5 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area);
extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
-#ifndef pci_pretty_name
-#define pci_pretty_name(dev) ""
-#endif
-
#endif /* __KERNEL__ */
#endif
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 6eafff13dab..9f65f5697ba 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -887,6 +887,9 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
request->count = entry->buf_count;
request->size = size;
+ if (request->flags & _DRM_PCI_BUFFER_RO)
+ dma->flags = _DRM_DMA_USE_PCI_RO;
+
atomic_dec(&dev->buf_alloc);
return 0;
@@ -1471,9 +1474,10 @@ int drm_freebufs(struct inode *inode, struct file *filp,
* \param arg pointer to a drm_buf_map structure.
* \return zero on success or a negative number on failure.
*
- * Maps the AGP or SG buffer region with do_mmap(), and copies information
- * about each buffer into user space. The PCI buffers are already mapped on the
- * addbufs_pci() call.
+ * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
+ * about each buffer into user space. For PCI buffers, it calls do_mmap() with
+ * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
+ * drm_mmap_dma().
*/
int drm_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
index f4f9db6c7ed..31673903607 100644
--- a/drivers/char/drm/drm_core.h
+++ b/drivers/char/drm/drm_core.h
@@ -24,11 +24,11 @@
#define CORE_NAME "drm"
#define CORE_DESC "DRM shared core routines"
-#define CORE_DATE "20051102"
+#define CORE_DATE "20060810"
#define DRM_IF_MAJOR 1
-#define DRM_IF_MINOR 2
+#define DRM_IF_MINOR 3
#define CORE_MAJOR 1
-#define CORE_MINOR 0
-#define CORE_PATCHLEVEL 1
+#define CORE_MINOR 1
+#define CORE_PATCHLEVEL 0
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
index 7857453c4f4..de37d5f7456 100644
--- a/drivers/char/drm/drm_drawable.c
+++ b/drivers/char/drm/drm_drawable.c
@@ -4,6 +4,7 @@
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
+ * \author Michel Dänzer <michel@tungstengraphics.com>
*/
/*
@@ -11,6 +12,7 @@
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -35,22 +37,294 @@
#include "drmP.h"
-/** No-op. */
-int drm_adddraw(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+/**
+ * Allocate drawable ID and memory to store information about it.
+ */
+int drm_adddraw(DRM_IOCTL_ARGS)
{
+ DRM_DEVICE;
+ unsigned long irqflags;
+ int i, j;
+ u32 *bitfield = dev->drw_bitfield;
+ unsigned int bitfield_length = dev->drw_bitfield_length;
+ drm_drawable_info_t **info = dev->drw_info;
+ unsigned int info_length = dev->drw_info_length;
drm_draw_t draw;
- draw.handle = 0; /* NOOP */
+ for (i = 0, j = 0; i < bitfield_length; i++) {
+ if (bitfield[i] == ~0)
+ continue;
+
+ for (; j < 8 * sizeof(*bitfield); j++)
+ if (!(bitfield[i] & (1 << j)))
+ goto done;
+ }
+done:
+
+ if (i == bitfield_length) {
+ bitfield_length++;
+
+ bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
+ DRM_MEM_BUFS);
+
+ if (!bitfield) {
+ DRM_ERROR("Failed to allocate new drawable bitfield\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
+ info_length += 8 * sizeof(*bitfield);
+
+ info = drm_alloc(info_length * sizeof(*info),
+ DRM_MEM_BUFS);
+
+ if (!info) {
+ DRM_ERROR("Failed to allocate new drawable info"
+ " array\n");
+
+ drm_free(bitfield,
+ bitfield_length * sizeof(*bitfield),
+ DRM_MEM_BUFS);
+ return DRM_ERR(ENOMEM);
+ }
+ }
+
+ bitfield[i] = 0;
+ }
+
+ draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
DRM_DEBUG("%d\n", draw.handle);
- if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw)))
- return -EFAULT;
+
+ spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+ bitfield[i] |= 1 << j;
+ info[draw.handle - 1] = NULL;
+
+ if (bitfield != dev->drw_bitfield) {
+ memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
+ sizeof(*bitfield));
+ drm_free(dev->drw_bitfield, sizeof(*bitfield) *
+ dev->drw_bitfield_length, DRM_MEM_BUFS);
+ dev->drw_bitfield = bitfield;
+ dev->drw_bitfield_length = bitfield_length;
+ }
+
+ if (info != dev->drw_info) {
+ memcpy(info, dev->drw_info, dev->drw_info_length *
+ sizeof(*info));
+ drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
+ DRM_MEM_BUFS);
+ dev->drw_info = info;
+ dev->drw_info_length = info_length;
+ }
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+ DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+
return 0;
}
-/** No-op. */
-int drm_rmdraw(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+/**
+ * Free drawable ID and memory to store information about it.
+ */
+int drm_rmdraw(DRM_IOCTL_ARGS)
{
- return 0; /* NOOP */
+ DRM_DEVICE;
+ drm_draw_t draw;
+ int id, idx;
+ unsigned int shift;
+ unsigned long irqflags;
+ u32 *bitfield = dev->drw_bitfield;
+ unsigned int bitfield_length = dev->drw_bitfield_length;
+ drm_drawable_info_t **info = dev->drw_info;
+ unsigned int info_length = dev->drw_info_length;
+
+ DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
+ sizeof(draw));
+
+ id = draw.handle - 1;
+ idx = id / (8 * sizeof(*bitfield));
+ shift = id % (8 * sizeof(*bitfield));
+
+ if (idx < 0 || idx >= bitfield_length ||
+ !(bitfield[idx] & (1 << shift))) {
+ DRM_DEBUG("No such drawable %d\n", draw.handle);
+ return 0;
+ }
+
+ spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+ bitfield[idx] &= ~(1 << shift);
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+ if (info[id]) {
+ drm_free(info[id]->rects, info[id]->num_rects *
+ sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
+ }
+
+ /* Can we shrink the arrays? */
+ if (idx == bitfield_length - 1) {
+ while (idx >= 0 && !bitfield[idx])
+ --idx;
+
+ bitfield_length = idx + 1;
+
+ if (idx != id / (8 * sizeof(*bitfield)))
+ bitfield = drm_alloc(bitfield_length *
+ sizeof(*bitfield), DRM_MEM_BUFS);
+
+ if (!bitfield && bitfield_length) {
+ bitfield = dev->drw_bitfield;
+ bitfield_length = dev->drw_bitfield_length;
+ }
+ }
+
+ if (bitfield != dev->drw_bitfield) {
+ info_length = 8 * sizeof(*bitfield) * bitfield_length;
+
+ info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS);
+
+ if (!info && info_length) {
+ info = dev->drw_info;
+ info_length = dev->drw_info_length;
+ }
+
+ spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+ memcpy(bitfield, dev->drw_bitfield, bitfield_length *
+ sizeof(*bitfield));
+ drm_free(dev->drw_bitfield, sizeof(*bitfield) *
+ dev->drw_bitfield_length, DRM_MEM_BUFS);
+ dev->drw_bitfield = bitfield;
+ dev->drw_bitfield_length = bitfield_length;
+
+ if (info != dev->drw_info) {
+ memcpy(info, dev->drw_info, info_length *
+ sizeof(*info));
+ drm_free(dev->drw_info, sizeof(*info) *
+ dev->drw_info_length, DRM_MEM_BUFS);
+ dev->drw_info = info;
+ dev->drw_info_length = info_length;
+ }
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ }
+
+ DRM_DEBUG("%d\n", draw.handle);
+ return 0;
+}
+
+int drm_update_drawable_info(DRM_IOCTL_ARGS) {
+ DRM_DEVICE;
+ drm_update_draw_t update;
+ unsigned int id, idx, shift;
+ u32 *bitfield = dev->drw_bitfield;
+ unsigned long irqflags, bitfield_length = dev->drw_bitfield_length;
+ drm_drawable_info_t *info;
+ drm_clip_rect_t *rects;
+ int err;
+
+ DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
+ sizeof(update));
+
+ id = update.handle - 1;
+ idx = id / (8 * sizeof(*bitfield));
+ shift = id % (8 * sizeof(*bitfield));
+
+ if (idx < 0 || idx >= bitfield_length ||
+ !(bitfield[idx] & (1 << shift))) {
+ DRM_ERROR("No such drawable %d\n", update.handle);
+ return DRM_ERR(EINVAL);
+ }
+
+ info = dev->drw_info[id];
+
+ if (!info) {
+ info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
+
+ if (!info) {
+ DRM_ERROR("Failed to allocate drawable info memory\n");
+ return DRM_ERR(ENOMEM);
+ }
+ }
+
+ switch (update.type) {
+ case DRM_DRAWABLE_CLIPRECTS:
+ if (update.num != info->num_rects) {
+ rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+ DRM_MEM_BUFS);
+ } else
+ rects = info->rects;
+
+ if (update.num && !rects) {
+ DRM_ERROR("Failed to allocate cliprect memory\n");
+ err = DRM_ERR(ENOMEM);
+ goto error;
+ }
+
+ if (update.num && DRM_COPY_FROM_USER(rects,
+ (drm_clip_rect_t __user *)
+ (unsigned long)update.data,
+ update.num *
+ sizeof(*rects))) {
+ DRM_ERROR("Failed to copy cliprects from userspace\n");
+ err = DRM_ERR(EFAULT);
+ goto error;
+ }
+
+ spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+ if (rects != info->rects) {
+ drm_free(info->rects, info->num_rects *
+ sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ }
+
+ info->rects = rects;
+ info->num_rects = update.num;
+ dev->drw_info[id] = info;
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+ DRM_DEBUG("Updated %d cliprects for drawable %d\n",
+ info->num_rects, id);
+ break;
+ default:
+ DRM_ERROR("Invalid update type %d\n", update.type);
+ return DRM_ERR(EINVAL);
+ }
+
+ return 0;
+
+error:
+ if (!dev->drw_info[id])
+ drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+ else if (rects != dev->drw_info[id]->rects)
+ drm_free(rects, update.num *
+ sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+
+ return err;
+}
+
+/**
+ * Caller must hold the drawable spinlock!
+ */
+drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
+ u32 *bitfield = dev->drw_bitfield;
+ unsigned int idx, shift;
+
+ id--;
+ idx = id / (8 * sizeof(*bitfield));
+ shift = id % (8 * sizeof(*bitfield));
+
+ if (idx < 0 || idx >= dev->drw_bitfield_length ||
+ !(bitfield[idx] & (1 << shift))) {
+ DRM_DEBUG("No such drawable %d\n", id);
+ return NULL;
+ }
+
+ return dev->drw_info[id];
}
+EXPORT_SYMBOL(drm_get_drawable_info);
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index b366c5b1bd1..a70af0de445 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -116,6 +116,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
};
#define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
@@ -151,6 +153,18 @@ int drm_lastclose(drm_device_t * dev)
if (dev->irq_enabled)
drm_irq_uninstall(dev);
+ /* Free drawable information memory */
+ for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
+ i++) {
+ drm_drawable_info_t *info = drm_get_drawable_info(dev, i);
+
+ if (info) {
+ drm_free(info->rects, info->num_rects *
+ sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+ }
+ }
+
mutex_lock(&dev->struct_mutex);
del_timer(&dev->timer);
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index d4f87452008..fafeb34f89d 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -102,7 +102,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
&version->desc))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_VERSION, (unsigned long)version);
if (err)
return err;
@@ -143,7 +143,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
&u->unique))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
if (err)
return err;
@@ -172,7 +172,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
&u->unique))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
}
@@ -203,7 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
if (__put_user(idx, &map->offset))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_GET_MAP, (unsigned long)map);
if (err)
return err;
@@ -244,7 +244,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
|| __put_user(m32.flags, &map->flags))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_ADD_MAP, (unsigned long)map);
if (err)
return err;
@@ -282,7 +282,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
if (__put_user((void *)(unsigned long)handle, &map->handle))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RM_MAP, (unsigned long)map);
}
@@ -312,7 +312,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
if (__put_user(idx, &client->idx))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_GET_CLIENT, (unsigned long)client);
if (err)
return err;
@@ -349,7 +349,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_GET_STATS, (unsigned long)stats);
if (err)
return err;
@@ -393,7 +393,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
|| __put_user(agp_start, &buf->agp_start))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
if (err)
return err;
@@ -425,7 +425,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
|| __put_user(b32.high_mark, &buf->high_mark))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
}
@@ -467,7 +467,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
|| __put_user(list, &request->list))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_INFO_BUFS, (unsigned long)request);
if (err)
return err;
@@ -529,7 +529,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
|| __put_user(list, &request->list))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_MAP_BUFS, (unsigned long)request);
if (err)
return err;
@@ -576,7 +576,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
&request->list))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_FREE_BUFS, (unsigned long)request);
}
@@ -603,7 +603,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
&request->handle))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
}
@@ -626,7 +626,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
if (__put_user(ctx_id, &request->ctx_id))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
if (err)
return err;
@@ -662,7 +662,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
&res->contexts))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RES_CTX, (unsigned long)res);
if (err)
return err;
@@ -716,7 +716,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
&d->request_sizes))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_DMA, (unsigned long)d);
if (err)
return err;
@@ -749,7 +749,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
if (put_user(m32.mode, &mode->mode))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
}
@@ -779,7 +779,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_INFO, (unsigned long)info);
if (err)
return err;
@@ -825,7 +825,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
|| __put_user(req32.type, &request->type))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
if (err)
return err;
@@ -833,7 +833,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
if (__get_user(req32.handle, &request->handle)
|| __get_user(req32.physical, &request->physical)
|| copy_to_user(argp, &req32, sizeof(req32))) {
- drm_ioctl(file->f_dentry->d_inode, file,
+ drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_FREE, (unsigned long)request);
return -EFAULT;
}
@@ -854,7 +854,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
|| __put_user(handle, &request->handle))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_FREE, (unsigned long)request);
}
@@ -879,7 +879,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
|| __put_user(req32.offset, &request->offset))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_BIND, (unsigned long)request);
}
@@ -896,7 +896,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
|| __put_user(handle, &request->handle))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
}
#endif /* __OS_HAS_AGP */
@@ -921,7 +921,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
|| __put_user(x, &request->size))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_SG_ALLOC, (unsigned long)request);
if (err)
return err;
@@ -948,7 +948,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
|| __put_user(x << PAGE_SHIFT, &request->handle))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_SG_FREE, (unsigned long)request);
}
@@ -988,7 +988,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
|| __put_user(req32.request.signal, &request->request.signal))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
if (err)
return err;
@@ -1060,7 +1060,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (fn != NULL)
ret = (*fn) (filp, cmd, arg);
else
- ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 4553a3a1e49..9d00c51fe2c 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -121,6 +121,7 @@ static int drm_irq_install(drm_device_t * dev)
spin_lock_init(&dev->vbl_lock);
INIT_LIST_HEAD(&dev->vbl_sigs.head);
+ INIT_LIST_HEAD(&dev->vbl_sigs2.head);
dev->vbl_pending = 0;
}
@@ -175,6 +176,8 @@ int drm_irq_uninstall(drm_device_t * dev)
free_irq(dev->irq, dev);
+ dev->locked_tasklet_func = NULL;
+
return 0;
}
@@ -247,10 +250,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
drm_wait_vblank_t vblwait;
struct timeval now;
int ret = 0;
- unsigned int flags;
-
- if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
- return -EINVAL;
+ unsigned int flags, seq;
if (!dev->irq)
return -EINVAL;
@@ -258,9 +258,26 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
if (copy_from_user(&vblwait, argp, sizeof(vblwait)))
return -EFAULT;
- switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) {
+ if (vblwait.request.type &
+ ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
+ DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
+ vblwait.request.type,
+ (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
+ return -EINVAL;
+ }
+
+ flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+
+ if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
+ DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+ return -EINVAL;
+
+ seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+ : &dev->vbl_received);
+
+ switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
case _DRM_VBLANK_RELATIVE:
- vblwait.request.sequence += atomic_read(&dev->vbl_received);
+ vblwait.request.sequence += seq;
vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
case _DRM_VBLANK_ABSOLUTE:
break;
@@ -268,26 +285,30 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
return -EINVAL;
}
- flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+ if ((flags & _DRM_VBLANK_NEXTONMISS) &&
+ (seq - vblwait.request.sequence) <= (1<<23)) {
+ vblwait.request.sequence = seq + 1;
+ }
if (flags & _DRM_VBLANK_SIGNAL) {
unsigned long irqflags;
+ drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+ ? &dev->vbl_sigs2 : &dev->vbl_sigs;
drm_vbl_sig_t *vbl_sig;
- vblwait.reply.sequence = atomic_read(&dev->vbl_received);
-
spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Check if this task has already scheduled the same signal
* for the same vblank sequence number; nothing to be done in
* that case
*/
- list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) {
+ list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
if (vbl_sig->sequence == vblwait.request.sequence
&& vbl_sig->info.si_signo == vblwait.request.signal
&& vbl_sig->task == current) {
spin_unlock_irqrestore(&dev->vbl_lock,
irqflags);
+ vblwait.reply.sequence = seq;
goto done;
}
}
@@ -315,11 +336,16 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
spin_lock_irqsave(&dev->vbl_lock, irqflags);
- list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head);
+ list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+ vblwait.reply.sequence = seq;
} else {
- if (dev->driver->vblank_wait)
+ if (flags & _DRM_VBLANK_SECONDARY) {
+ if (dev->driver->vblank_wait2)
+ ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence);
+ } else if (dev->driver->vblank_wait)
ret =
dev->driver->vblank_wait(dev,
&vblwait.request.sequence);
@@ -347,25 +373,32 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
*/
void drm_vbl_send_signals(drm_device_t * dev)
{
- struct list_head *list, *tmp;
- drm_vbl_sig_t *vbl_sig;
- unsigned int vbl_seq = atomic_read(&dev->vbl_received);
unsigned long flags;
+ int i;
spin_lock_irqsave(&dev->vbl_lock, flags);
- list_for_each_safe(list, tmp, &dev->vbl_sigs.head) {
- vbl_sig = list_entry(list, drm_vbl_sig_t, head);
- if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
- vbl_sig->info.si_code = vbl_seq;
- send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info,
- vbl_sig->task);
+ for (i = 0; i < 2; i++) {
+ struct list_head *list, *tmp;
+ drm_vbl_sig_t *vbl_sig;
+ drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+ unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
+ &dev->vbl_received);
+
+ list_for_each_safe(list, tmp, &vbl_sigs->head) {
+ vbl_sig = list_entry(list, drm_vbl_sig_t, head);
+ if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+ vbl_sig->info.si_code = vbl_seq;
+ send_sig_info(vbl_sig->info.si_signo,
+ &vbl_sig->info, vbl_sig->task);
- list_del(list);
+ list_del(list);
- drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER);
+ drm_free(vbl_sig, sizeof(*vbl_sig),
+ DRM_MEM_DRIVER);
- dev->vbl_pending--;
+ dev->vbl_pending--;
+ }
}
}
@@ -373,3 +406,77 @@ void drm_vbl_send_signals(drm_device_t * dev)
}
EXPORT_SYMBOL(drm_vbl_send_signals);
+
+/**
+ * Tasklet wrapper function.
+ *
+ * \param data DRM device in disguise.
+ *
+ * Attempts to grab the HW lock and calls the driver callback on success. On
+ * failure, leave the lock marked as contended so the callback can be called
+ * from drm_unlock().
+ */
+static void drm_locked_tasklet_func(unsigned long data)
+{
+ drm_device_t *dev = (drm_device_t*)data;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+ if (!dev->locked_tasklet_func ||
+ !drm_lock_take(&dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT)) {
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+ return;
+ }
+
+ dev->lock.lock_time = jiffies;
+ atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+
+ dev->locked_tasklet_func(dev);
+
+ drm_lock_free(dev, &dev->lock.hw_lock->lock,
+ DRM_KERNEL_CONTEXT);
+
+ dev->locked_tasklet_func = NULL;
+
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+}
+
+/**
+ * Schedule a tasklet to call back a driver hook with the HW lock held.
+ *
+ * \param dev DRM device.
+ * \param func Driver callback.
+ *
+ * This is intended for triggering actions that require the HW lock from an
+ * interrupt handler. The lock will be grabbed ASAP after the interrupt handler
+ * completes. Note that the callback may be called from interrupt or process
+ * context, it must not make any assumptions about this. Also, the HW lock will
+ * be held with the kernel context or any client context.
+ */
+void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*))
+{
+ unsigned long irqflags;
+ static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) ||
+ test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state))
+ return;
+
+ spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+ if (dev->locked_tasklet_func) {
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+ return;
+ }
+
+ dev->locked_tasklet_func = func;
+
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
+ drm_tasklet.data = (unsigned long)dev;
+
+ tasklet_hi_schedule(&drm_tasklet);
+}
+EXPORT_SYMBOL(drm_locked_tasklet);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index f9e45303498..e9993ba461a 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -155,6 +155,7 @@ int drm_unlock(struct inode *inode, struct file *filp,
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_lock_t lock;
+ unsigned long irqflags;
if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
return -EFAULT;
@@ -165,13 +166,23 @@ int drm_unlock(struct inode *inode, struct file *filp,
return -EINVAL;
}
+ spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+ if (dev->locked_tasklet_func) {
+ dev->locked_tasklet_func(dev);
+
+ dev->locked_tasklet_func = NULL;
+ }
+
+ spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
/* kernel_context_switch isn't used by any of the x86 drm
* modules but is required by the Sparc driver.
*/
if (dev->driver->kernel_context_switch_unlock)
- dev->driver->kernel_context_switch_unlock(dev, &lock);
+ dev->driver->kernel_context_switch_unlock(dev);
else {
drm_lock_transfer(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT);
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 7b1d4e8659b..120d10256fe 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -60,6 +60,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
int retcode;
spin_lock_init(&dev->count_lock);
+ spin_lock_init(&dev->drw_lock);
+ spin_lock_init(&dev->tasklet_lock);
init_timer(&dev->timer);
mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex);
@@ -209,14 +211,16 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
if (!dev)
return -ENOMEM;
- pci_enable_device(pdev);
+ ret = pci_enable_device(pdev);
+ if (ret)
+ 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;
+ goto err_g2;
}
if ((ret = drm_get_head(dev, &dev->primary)))
- goto err_g1;
+ goto err_g2;
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
driver->name, driver->major, driver->minor, driver->patchlevel,
@@ -224,7 +228,9 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
return 0;
- err_g1:
+err_g2:
+ pci_disable_device(pdev);
+err_g1:
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
return ret;
}
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index ba4b8de83cf..cc8e2ebe128 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -45,8 +45,8 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
int err;
class = class_create(owner, name);
- if (!class) {
- err = -ENOMEM;
+ if (IS_ERR(class)) {
+ err = PTR_ERR(class);
goto err_out;
}
@@ -113,8 +113,8 @@ struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
MKDEV(DRM_MAJOR, head->minor),
&(head->dev->pdev)->dev,
"card%d", head->minor);
- if (!class_dev) {
- err = -ENOMEM;
+ if (IS_ERR(class_dev)) {
+ err = PTR_ERR(class_dev);
goto err_out;
}
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index ae2691942dd..b9cfc077f6b 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -473,6 +473,22 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
}
unlock_kernel();
+ if (!capable(CAP_SYS_ADMIN) &&
+ (dma->flags & _DRM_DMA_USE_PCI_RO)) {
+ vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+#if defined(__i386__) || defined(__x86_64__)
+ pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+#else
+ /* Ye gads this is ugly. With more thought
+ we could move this up higher and use
+ `protection_map' instead. */
+ vma->vm_page_prot =
+ __pgprot(pte_val
+ (pte_wrprotect
+ (__pte(pgprot_val(vma->vm_page_prot)))));
+#endif
+ }
+
vma->vm_ops = &drm_vm_dma_ops;
vma->vm_flags |= VM_RESERVED; /* Don't swap */
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index fb7913ff528..9354ce3b009 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -162,6 +162,7 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+ dev_priv->cpp = init->cpp;
dev_priv->back_offset = init->back_offset;
dev_priv->front_offset = init->front_offset;
dev_priv->current_page = 0;
@@ -782,6 +783,7 @@ drm_ioctl_desc_t i915_ioctls[] = {
[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
+ [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 6af83e613f2..96a468886a7 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -104,6 +104,15 @@ typedef struct _drm_i915_sarea {
unsigned int depth_tiled;
unsigned int rotated_tiled;
unsigned int rotated2_tiled;
+
+ int pipeA_x;
+ int pipeA_y;
+ int pipeA_w;
+ int pipeA_h;
+ int pipeB_x;
+ int pipeB_y;
+ int pipeB_w;
+ int pipeB_h;
} drm_i915_sarea_t;
/* Flags for perf_boxes
@@ -132,6 +141,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_DESTROY_HEAP 0x0c
#define DRM_I915_SET_VBLANK_PIPE 0x0d
#define DRM_I915_GET_VBLANK_PIPE 0x0e
+#define DRM_I915_VBLANK_SWAP 0x0f
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -148,6 +158,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -243,4 +254,12 @@ typedef struct drm_i915_vblank_pipe {
int pipe;
} drm_i915_vblank_pipe_t;
+/* Schedule buffer swap at given vertical blank:
+ */
+typedef struct drm_i915_vblank_swap {
+ drm_drawable_t drawable;
+ drm_vblank_seq_type_t seqtype;
+ unsigned int sequence;
+} drm_i915_vblank_swap_t;
+
#endif /* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 8e2e6095c4b..85bcc276f80 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -44,12 +44,14 @@ static struct drm_driver driver = {
*/
.driver_features =
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
+ DRIVER_IRQ_VBL2,
.load = i915_driver_load,
.lastclose = i915_driver_lastclose,
.preclose = i915_driver_preclose,
.device_is_agp = i915_driver_device_is_agp,
.vblank_wait = i915_driver_vblank_wait,
+ .vblank_wait2 = i915_driver_vblank_wait2,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index fdc2bf19271..93cdcfe6aa8 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -46,9 +46,11 @@
* 1.3: Add vblank support
* 1.4: Fix cmdbuffer path, add heap destroy
* 1.5: Add vblank pipe configuration
+ * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
+ * - Support vertical blank on secondary display pipe
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 5
+#define DRIVER_MINOR 6
#define DRIVER_PATCHLEVEL 0
typedef struct _drm_i915_ring_buffer {
@@ -71,6 +73,13 @@ struct mem_block {
DRMFILE filp; /* 0: free, -1: heap, other: real files */
};
+typedef struct _drm_i915_vbl_swap {
+ struct list_head head;
+ drm_drawable_t drw_id;
+ unsigned int pipe;
+ unsigned int sequence;
+} drm_i915_vbl_swap_t;
+
typedef struct drm_i915_private {
drm_local_map_t *sarea;
drm_local_map_t *mmio_map;
@@ -83,6 +92,7 @@ typedef struct drm_i915_private {
dma_addr_t dma_status_page;
unsigned long counter;
+ unsigned int cpp;
int back_offset;
int front_offset;
int current_page;
@@ -98,6 +108,10 @@ typedef struct drm_i915_private {
struct mem_block *agp_heap;
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
int vblank_pipe;
+
+ spinlock_t swaps_lock;
+ drm_i915_vbl_swap_t vbl_swaps;
+ unsigned int swaps_pending;
} drm_i915_private_t;
extern drm_ioctl_desc_t i915_ioctls[];
@@ -117,12 +131,14 @@ extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
extern void i915_driver_irq_uninstall(drm_device_t * dev);
extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
+extern int i915_vblank_swap(DRM_IOCTL_ARGS);
/* i915_mem.c */
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
@@ -256,6 +272,10 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+
#define MI_BATCH_BUFFER ((0x30<<23)|1)
#define MI_BATCH_BUFFER_START (0x31<<23)
#define MI_BATCH_BUFFER_END (0xA<<23)
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
index 296248cdc76..1fe68a251b7 100644
--- a/drivers/char/drm/i915_ioc32.c
+++ b/drivers/char/drm/i915_ioc32.c
@@ -66,7 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
&batchbuffer->cliprects))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_I915_BATCHBUFFER,
(unsigned long)batchbuffer);
}
@@ -102,7 +102,7 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
&cmdbuffer->cliprects))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
}
@@ -125,7 +125,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
&request->irq_seq))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
}
typedef struct drm_i915_getparam32 {
@@ -149,7 +149,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd,
&request->value))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
}
@@ -178,7 +178,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
&request->region_offset))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_I915_ALLOC, (unsigned long)request);
}
@@ -215,7 +215,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (fn != NULL)
ret = (*fn) (filp, cmd, arg);
else
- ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 0d4a162aa38..78c1ae28f17 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -37,6 +37,178 @@
#define MAX_NOPID ((u32)~0)
+/**
+ * Emit blits for scheduled buffer swaps.
+ *
+ * This function will be called with the HW lock held.
+ */
+static void i915_vblank_tasklet(drm_device_t *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long irqflags;
+ struct list_head *list, *tmp, hits, *hit;
+ int nhits, nrects, slice[2], upper[2], lower[2], i;
+ unsigned counter[2] = { atomic_read(&dev->vbl_received),
+ atomic_read(&dev->vbl_received2) };
+ drm_drawable_info_t *drw;
+ drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ u32 cpp = dev_priv->cpp;
+ u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB)
+ : XY_SRC_COPY_BLT_CMD;
+ u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
+ (cpp << 23) | (1 << 24);
+ RING_LOCALS;
+
+ DRM_DEBUG("\n");
+
+ INIT_LIST_HEAD(&hits);
+
+ nhits = nrects = 0;
+
+ spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+ /* Find buffer swaps scheduled for this vertical blank */
+ list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
+ drm_i915_vbl_swap_t *vbl_swap =
+ list_entry(list, drm_i915_vbl_swap_t, head);
+
+ if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+ continue;
+
+ list_del(list);
+ dev_priv->swaps_pending--;
+
+ spin_unlock(&dev_priv->swaps_lock);
+ spin_lock(&dev->drw_lock);
+
+ drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
+
+ if (!drw) {
+ spin_unlock(&dev->drw_lock);
+ drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+ spin_lock(&dev_priv->swaps_lock);
+ continue;
+ }
+
+ list_for_each(hit, &hits) {
+ drm_i915_vbl_swap_t *swap_cmp =
+ list_entry(hit, drm_i915_vbl_swap_t, head);
+ drm_drawable_info_t *drw_cmp =
+ drm_get_drawable_info(dev, swap_cmp->drw_id);
+
+ if (drw_cmp &&
+ drw_cmp->rects[0].y1 > drw->rects[0].y1) {
+ list_add_tail(list, hit);
+ break;
+ }
+ }
+
+ spin_unlock(&dev->drw_lock);
+
+ /* List of hits was empty, or we reached the end of it */
+ if (hit == &hits)
+ list_add_tail(list, hits.prev);
+
+ nhits++;
+
+ spin_lock(&dev_priv->swaps_lock);
+ }
+
+ if (nhits == 0) {
+ spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+ return;
+ }
+
+ spin_unlock(&dev_priv->swaps_lock);
+
+ i915_kernel_lost_context(dev);
+
+ BEGIN_LP_RING(6);
+
+ OUT_RING(GFX_OP_DRAWRECT_INFO);
+ OUT_RING(0);
+ OUT_RING(0);
+ OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+ OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+
+ sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+
+ upper[0] = upper[1] = 0;
+ slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
+ slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
+ lower[0] = sarea_priv->pipeA_y + slice[0];
+ lower[1] = sarea_priv->pipeB_y + slice[0];
+
+ spin_lock(&dev->drw_lock);
+
+ /* Emit blits for buffer swaps, partitioning both outputs into as many
+ * slices as there are buffer swaps scheduled in order to avoid tearing
+ * (based on the assumption that a single buffer swap would always
+ * complete before scanout starts).
+ */
+ for (i = 0; i++ < nhits;
+ upper[0] = lower[0], lower[0] += slice[0],
+ upper[1] = lower[1], lower[1] += slice[1]) {
+ if (i == nhits)
+ lower[0] = lower[1] = sarea_priv->height;
+
+ list_for_each(hit, &hits) {
+ drm_i915_vbl_swap_t *swap_hit =
+ list_entry(hit, drm_i915_vbl_swap_t, head);
+ drm_clip_rect_t *rect;
+ int num_rects, pipe;
+ unsigned short top, bottom;
+
+ drw = drm_get_drawable_info(dev, swap_hit->drw_id);
+
+ if (!drw)
+ continue;
+
+ rect = drw->rects;
+ pipe = swap_hit->pipe;
+ top = upper[pipe];
+ bottom = lower[pipe];
+
+ for (num_rects = drw->num_rects; num_rects--; rect++) {
+ int y1 = max(rect->y1, top);
+ int y2 = min(rect->y2, bottom);
+
+ if (y1 >= y2)
+ continue;
+
+ BEGIN_LP_RING(8);
+
+ OUT_RING(cmd);
+ OUT_RING(pitchropcpp);
+ OUT_RING((y1 << 16) | rect->x1);
+ OUT_RING((y2 << 16) | rect->x2);
+ OUT_RING(sarea_priv->front_offset);
+ OUT_RING((y1 << 16) | rect->x1);
+ OUT_RING(pitchropcpp & 0xffff);
+ OUT_RING(sarea_priv->back_offset);
+
+ ADVANCE_LP_RING();
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+ list_for_each_safe(hit, tmp, &hits) {
+ drm_i915_vbl_swap_t *swap_hit =
+ list_entry(hit, drm_i915_vbl_swap_t, head);
+
+ list_del(hit);
+
+ drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
+ }
+}
+
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
drm_device_t *dev = (drm_device_t *) arg;
@@ -60,9 +232,26 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
DRM_WAKEUP(&dev_priv->irq_queue);
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
- atomic_inc(&dev->vbl_received);
+ int vblank_pipe = dev_priv->vblank_pipe;
+
+ if ((vblank_pipe &
+ (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
+ == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
+ if (temp & VSYNC_PIPEA_FLAG)
+ atomic_inc(&dev->vbl_received);
+ if (temp & VSYNC_PIPEB_FLAG)
+ atomic_inc(&dev->vbl_received2);
+ } else if (((temp & VSYNC_PIPEA_FLAG) &&
+ (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+ ((temp & VSYNC_PIPEB_FLAG) &&
+ (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
+ atomic_inc(&dev->vbl_received);
+
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
+
+ if (dev_priv->swaps_pending > 0)
+ drm_locked_tasklet(dev, i915_vblank_tasklet);
}
return IRQ_HANDLED;
@@ -120,7 +309,8 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
return ret;
}
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+ atomic_t *counter)
{
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned int cur_vblank;
@@ -132,7 +322,7 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
}
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
+ (((cur_vblank = atomic_read(counter))
- *sequence) <= (1<<23)));
*sequence = cur_vblank;
@@ -141,6 +331,16 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
}
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+ return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+}
+
+int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+{
+ return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+}
+
/* Needs the lock as it touches the ring.
*/
int i915_irq_emit(DRM_IOCTL_ARGS)
@@ -189,7 +389,7 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
return i915_wait_irq(dev, irqwait.irq_seq);
}
-static int i915_enable_interrupt (drm_device_t *dev)
+static void i915_enable_interrupt (drm_device_t *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u16 flag;
@@ -199,13 +399,8 @@ static int i915_enable_interrupt (drm_device_t *dev)
flag |= VSYNC_PIPEA_FLAG;
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
flag |= VSYNC_PIPEB_FLAG;
- if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
- DRM_ERROR("%s called with invalid pipe 0x%x\n",
- __FUNCTION__, dev_priv->vblank_pipe);
- return DRM_ERR(EINVAL);
- }
+
I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
- return 0;
}
/* Set the vblank monitor pipe
@@ -224,8 +419,17 @@ int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
sizeof(pipe));
+ if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
+ DRM_ERROR("%s called with invalid pipe 0x%x\n",
+ __FUNCTION__, pipe.pipe);
+ return DRM_ERR(EINVAL);
+ }
+
dev_priv->vblank_pipe = pipe.pipe;
- return i915_enable_interrupt (dev);
+
+ i915_enable_interrupt (dev);
+
+ return 0;
}
int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
@@ -251,6 +455,118 @@ int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
return 0;
}
+/**
+ * Schedule buffer swap at given vertical blank.
+ */
+int i915_vblank_swap(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_vblank_swap_t swap;
+ drm_i915_vbl_swap_t *vbl_swap;
+ unsigned int pipe, seqtype, curseq;
+ unsigned long irqflags;
+ struct list_head *list;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __func__);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (dev_priv->sarea_priv->rotation) {
+ DRM_DEBUG("Rotation not supported\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
+ sizeof(swap));
+
+ if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+ _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
+ DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
+ return DRM_ERR(EINVAL);
+ }
+
+ pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+
+ seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+
+ if (!(dev_priv->vblank_pipe & (1 << pipe))) {
+ DRM_ERROR("Invalid pipe %d\n", pipe);
+ return DRM_ERR(EINVAL);
+ }
+
+ spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+ if (!drm_get_drawable_info(dev, swap.drawable)) {
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable);
+ return DRM_ERR(EINVAL);
+ }
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+ curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+
+ if (seqtype == _DRM_VBLANK_RELATIVE)
+ swap.sequence += curseq;
+
+ if ((curseq - swap.sequence) <= (1<<23)) {
+ if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
+ swap.sequence = curseq + 1;
+ } else {
+ DRM_DEBUG("Missed target sequence\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+
+ spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+ list_for_each(list, &dev_priv->vbl_swaps.head) {
+ vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+
+ if (vbl_swap->drw_id == swap.drawable &&
+ vbl_swap->pipe == pipe &&
+ vbl_swap->sequence == swap.sequence) {
+ spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+ DRM_DEBUG("Already scheduled\n");
+ return 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+ if (dev_priv->swaps_pending >= 100) {
+ DRM_DEBUG("Too many swaps queued\n");
+ return DRM_ERR(EBUSY);
+ }
+
+ vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER);
+
+ if (!vbl_swap) {
+ DRM_ERROR("Failed to allocate memory to queue swap\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ DRM_DEBUG("\n");
+
+ vbl_swap->drw_id = swap.drawable;
+ vbl_swap->pipe = pipe;
+ vbl_swap->sequence = swap.sequence;
+
+ spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+ list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head);
+ dev_priv->swaps_pending++;
+
+ spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+ DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
+ sizeof(swap));
+
+ return 0;
+}
+
/* drm_dma.h hooks
*/
void i915_driver_irq_preinstall(drm_device_t * dev)
@@ -266,6 +582,12 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+ dev_priv->swaps_pending = 0;
+
+ if (!dev_priv->vblank_pipe)
+ dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
i915_enable_interrupt(dev);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
index 54a18eb2fc0..30d00478dde 100644
--- a/drivers/char/drm/mga_ioc32.c
+++ b/drivers/char/drm/mga_ioc32.c
@@ -100,7 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd,
if (err)
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_MGA_INIT, (unsigned long)init);
}
@@ -125,7 +125,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
&getparam->value))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
}
@@ -166,7 +166,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
|| __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
return -EFAULT;
- err = drm_ioctl(file->f_dentry->d_inode, file,
+ err = drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_MGA_DMA_BOOTSTRAP,
(unsigned long)dma_bootstrap);
if (err)
@@ -224,7 +224,7 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (fn != NULL)
ret = (*fn) (filp, cmd, arg);
else
- ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 5d835b006f5..6e8af313f2b 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -1,7 +1,8 @@
/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
*/
-/* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+/*
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 94abffb2cca..f1efb49de8d 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -1,7 +1,8 @@
/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
* Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
*/
-/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
index 9dd6d4116e4..d3cb676eee8 100644
--- a/drivers/char/drm/r128_ioc32.c
+++ b/drivers/char/drm/r128_ioc32.c
@@ -95,7 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd,
&init->agp_textures_offset))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_R128_INIT, (unsigned long)init);
}
@@ -129,7 +129,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd,
&depth->mask))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
}
@@ -153,7 +153,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd,
&stipple->mask))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
}
@@ -178,7 +178,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd,
&getparam->value))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
}
@@ -214,7 +214,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (fn != NULL)
ret = (*fn) (filp, cmd, arg);
else
- ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index a080cdd6081..17b11e7d8f3 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -1,7 +1,8 @@
/* r128_state.c -- State support for r128 -*- linux-c -*-
* Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
*/
-/* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index d14477ba367..032a022ec6a 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -242,26 +242,6 @@ static __inline__ int r300_check_range(unsigned reg, int count)
return 0;
}
-/*
- * we expect offsets passed to the framebuffer to be either within video
- * memory or within AGP space
- */
-static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
- u32 offset)
-{
- /* we realy want to check against end of video aperture
- but this value is not being kept.
- This code is correct for now (does the same thing as the
- code that sets MC_FB_LOCATION) in radeon_cp.c */
- if (offset >= dev_priv->fb_location &&
- offset < (dev_priv->fb_location + dev_priv->fb_size))
- return 0;
- if (offset >= dev_priv->gart_vm_start &&
- offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
- return 0;
- return 1;
-}
-
static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
dev_priv,
drm_radeon_kcmd_buffer_t
@@ -290,7 +270,7 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
case MARK_SAFE:
break;
case MARK_CHECK_OFFSET:
- if (r300_check_offset(dev_priv, (u32) values[i])) {
+ if (!radeon_check_offset(dev_priv, (u32) values[i])) {
DRM_ERROR
("Offset failed range check (reg=%04x sz=%d)\n",
reg, sz);
@@ -452,7 +432,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
i = 1;
while ((k < narrays) && (i < (count + 1))) {
i++; /* skip attribute field */
- if (r300_check_offset(dev_priv, payload[i])) {
+ if (!radeon_check_offset(dev_priv, payload[i])) {
DRM_ERROR
("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
k, i);
@@ -463,7 +443,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
if (k == narrays)
break;
/* have one more to process, they come in pairs */
- if (r300_check_offset(dev_priv, payload[i])) {
+ if (!radeon_check_offset(dev_priv, payload[i])) {
DRM_ERROR
("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
k, i);
@@ -508,7 +488,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
| RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[2] << 10;
- ret = r300_check_offset(dev_priv, offset);
+ ret = !radeon_check_offset(dev_priv, offset);
if (ret) {
DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
return DRM_ERR(EINVAL);
@@ -518,7 +498,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
(cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[3] << 10;
- ret = r300_check_offset(dev_priv, offset);
+ ret = !radeon_check_offset(dev_priv, offset);
if (ret) {
DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
return DRM_ERR(EINVAL);
@@ -551,7 +531,7 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
return DRM_ERR(EINVAL);
}
- ret = r300_check_offset(dev_priv, cmd[2]);
+ ret = !radeon_check_offset(dev_priv, cmd[2]);
if (ret) {
DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
return DRM_ERR(EINVAL);
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index f45cd7f147a..8b105f1460a 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -303,6 +303,21 @@ extern int radeon_no_wb;
extern drm_ioctl_desc_t radeon_ioctls[];
extern int radeon_max_ioctl;
+/* Check whether the given hardware address is inside the framebuffer or the
+ * GART area.
+ */
+static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
+ u64 off)
+{
+ u32 fb_start = dev_priv->fb_location;
+ u32 fb_end = fb_start + dev_priv->fb_size - 1;
+ u32 gart_start = dev_priv->gart_vm_start;
+ u32 gart_end = gart_start + dev_priv->gart_size - 1;
+
+ return ((off >= fb_start && off <= fb_end) ||
+ (off >= gart_start && off <= gart_end));
+}
+
/* radeon_cp.c */
extern int radeon_cp_init(DRM_IOCTL_ARGS);
extern int radeon_cp_start(DRM_IOCTL_ARGS);
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index 0ccfd3618ff..1f1f9cc055a 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -92,7 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
&init->gart_textures_offset))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
}
@@ -125,7 +125,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
&clr->depth_boxes))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
}
@@ -149,7 +149,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
&request->mask))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
}
@@ -204,7 +204,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
&image->data))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
}
@@ -238,7 +238,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
&request->prim))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
}
@@ -268,7 +268,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
&request->boxes))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
}
@@ -293,7 +293,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
&request->value))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
}
@@ -322,7 +322,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
&request->region_offset))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
}
@@ -345,7 +345,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
&request->irq_seq))
return -EFAULT;
- return drm_ioctl(file->f_dentry->d_inode, file,
+ return drm_ioctl(file->f_path.dentry->d_inode, file,
DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
}
@@ -386,7 +386,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (fn != NULL)
ret = (*fn) (filp, cmd, arg);
else
- ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index d60519de887..3ff0baa2fbf 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -1,5 +1,5 @@
-/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*-
- *
+/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
+/*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
index 030a6fad0d8..517cad8b6e3 100644
--- a/drivers/char/drm/radeon_mem.c
+++ b/drivers/char/drm/radeon_mem.c
@@ -1,5 +1,5 @@
-/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*-
- *
+/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */
+/*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 6e04fdd732a..938eccb78cc 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -43,10 +43,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
u32 *offset)
{
u64 off = *offset;
- u32 fb_start = dev_priv->fb_location;
- u32 fb_end = fb_start + dev_priv->fb_size - 1;
- u32 gart_start = dev_priv->gart_vm_start;
- u32 gart_end = gart_start + dev_priv->gart_size - 1;
+ u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
struct drm_radeon_driver_file_fields *radeon_priv;
/* Hrm ... the story of the offset ... So this function converts
@@ -66,8 +63,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
/* First, the best case, the offset already lands in either the
* framebuffer or the GART mapped space
*/
- if ((off >= fb_start && off <= fb_end) ||
- (off >= gart_start && off <= gart_end))
+ if (radeon_check_offset(dev_priv, off))
return 0;
/* Ok, that didn't happen... now check if we have a zero based
@@ -81,11 +77,10 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
/* Finally, assume we aimed at a GART offset if beyond the fb */
if (off > fb_end)
- off = off - fb_end - 1 + gart_start;
+ off = off - fb_end - 1 + dev_priv->gart_vm_start;
/* Now recheck and fail if out of bounds */
- if ((off >= fb_start && off <= fb_end) ||
- (off >= gart_start && off <= gart_end)) {
+ if (radeon_check_offset(dev_priv, off)) {
DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
*offset = off;
return 0;
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index a9a84f88df5..b94fab55680 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -963,8 +963,8 @@ static int savage_bci_event_emit(DRM_IOCTL_ARGS)
event.count = savage_bci_emit_event(dev_priv, event.flags);
event.count |= dev_priv->event_wrap << 16;
- DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *) data)->
- count, event.count, sizeof(event.count));
+ DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *) data,
+ event, sizeof(event));
return 0;
}
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 9b1bf60ffbe..06f2dbf1771 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -201,7 +201,7 @@ static int dsp56k_upload(u_char __user *bin, int len)
static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int dev = iminor(inode) & 0x0f;
switch(dev)
@@ -264,7 +264,7 @@ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int dev = iminor(inode) & 0x0f;
switch(dev)
@@ -420,7 +420,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
#if 0
static unsigned int dsp56k_poll(struct file *file, poll_table *wait)
{
- int dev = iminor(file->f_dentry->d_inode) & 0x0f;
+ int dev = iminor(file->f_path.dentry->d_inode) & 0x0f;
switch(dev)
{
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index 5e82c3bad2e..d4005e94fe5 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -122,7 +122,7 @@ static void dtlk_timer_tick(unsigned long data);
static ssize_t dtlk_read(struct file *file, char __user *buf,
size_t count, loff_t * ppos)
{
- unsigned int minor = iminor(file->f_dentry->d_inode);
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
char ch;
int i = 0, retries;
@@ -174,7 +174,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf,
}
#endif
- if (iminor(file->f_dentry->d_inode) != DTLK_MINOR)
+ if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR)
return -EINVAL;
while (1) {
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 7c71eb77980..a0f822c9d74 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -199,7 +199,7 @@ static int pc_ioctl(struct tty_struct *, struct file *,
unsigned int, unsigned long);
static int info_ioctl(struct tty_struct *, struct file *,
unsigned int, unsigned long);
-static void pc_set_termios(struct tty_struct *, struct termios *);
+static void pc_set_termios(struct tty_struct *, struct ktermios *);
static void do_softint(struct work_struct *work);
static void pc_stop(struct tty_struct *);
static void pc_start(struct tty_struct *);
@@ -1236,6 +1236,8 @@ static int __init pc_init(void)
pc_driver->init_termios.c_oflag = 0;
pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
pc_driver->init_termios.c_lflag = 0;
+ pc_driver->init_termios.c_ispeed = 9600;
+ pc_driver->init_termios.c_ospeed = 9600;
pc_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(pc_driver, &pc_ops);
@@ -1250,6 +1252,8 @@ static int __init pc_init(void)
pc_info->init_termios.c_oflag = 0;
pc_info->init_termios.c_lflag = 0;
pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+ pc_info->init_termios.c_ispeed = 9600;
+ pc_info->init_termios.c_ospeed = 9600;
pc_info->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(pc_info, &info_ops);
@@ -1999,7 +2003,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
{ /* Begin epcaparam */
unsigned int cmdHead;
- struct termios *ts;
+ struct ktermios *ts;
struct board_chan __iomem *bc;
unsigned mval, hflow, cflag, iflag;
@@ -2114,7 +2118,7 @@ static void receive_data(struct channel *ch)
{ /* Begin receive_data */
unchar *rptr;
- struct termios *ts = NULL;
+ struct ktermios *ts = NULL;
struct tty_struct *tty;
struct board_chan __iomem *bc;
int dataToRead, wrapgap, bytesAvailable;
@@ -2362,12 +2366,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
switch (cmd)
{ /* Begin switch cmd */
+#if 0 /* Handled by calling layer properly */
case TCGETS:
- if (copy_to_user(argp, tty->termios, sizeof(struct termios)))
+ if (copy_to_user(argp, tty->termios, sizeof(struct ktermios)))
return -EFAULT;
return 0;
case TCGETA:
return get_termio(tty, argp);
+#endif
case TCSBRK: /* SVID version: non-zero arg --> no break */
retval = tty_check_change(tty);
if (retval)
@@ -2536,7 +2542,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
/* --------------------- Begin pc_set_termios ----------------------- */
-static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{ /* Begin pc_set_termios */
struct channel *ch;
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 93b55196251..d1bfbaa2aa0 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1915,7 +1915,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
return 0;
}
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
unsigned long flags;
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 87127e49c0d..e769811e741 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -718,11 +718,11 @@ static unsigned int gs_baudrates[] = {
void gs_set_termios (struct tty_struct * tty,
- struct termios * old_termios)
+ struct ktermios * old_termios)
{
struct gs_port *port;
int baudrate, tmp, rv;
- struct termios *tiosp;
+ struct ktermios *tiosp;
func_enter();
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index d090622f1de..207f7343ba6 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -192,11 +192,13 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
* that will cause echoing or we'll go into recursive loop echoing chars back
* and forth with the console drivers.
*/
-static struct termios hvcs_tty_termios = {
+static struct ktermios hvcs_tty_termios = {
.c_iflag = IGNBRK | IGNPAR,
.c_oflag = OPOST,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
- .c_cc = INIT_C_CC
+ .c_cc = INIT_C_CC,
+ .c_ispeed = 38400,
+ .c_ospeed = 38400
};
/*
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 82a41d5b4ed..d7806834fc1 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -1161,6 +1161,8 @@ static int __init hvsi_init(void)
hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
hvsi_driver->init_termios = tty_std_termios;
hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+ hvsi_driver->init_termios.c_ispeed = 9600;
+ hvsi_driver->init_termios.c_ospeed = 9600;
hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvsi_driver, &hvsi_ops);
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
index 71e4e0f3fd5..556fd81fa81 100644
--- a/drivers/char/hw_random/amd-rng.c
+++ b/drivers/char/hw_random/amd-rng.c
@@ -144,7 +144,7 @@ static void __exit mod_exit(void)
hwrng_unregister(&amd_rng);
}
-subsys_initcall(mod_init);
+module_init(mod_init);
module_exit(mod_exit);
MODULE_AUTHOR("The Linux Kernel team");
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index d37ced0d132..8e8658dcd2e 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -125,7 +125,7 @@ static void __exit mod_exit(void)
iounmap(mem);
}
-subsys_initcall(mod_init);
+module_init(mod_init);
module_exit(mod_exit);
MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 8efbc9c0e54..f22e78e3c70 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -143,6 +143,11 @@ static const struct pci_device_id pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, pci_tbl);
+static __initdata int no_fwh_detect;
+module_param(no_fwh_detect, int, 0);
+MODULE_PARM_DESC(no_fwh_detect, "Skip FWH detection:\n"
+ " positive value - skip if FWH space locked read-only\n"
+ " negative value - skip always");
static inline u8 hwstatus_get(void __iomem *mem)
{
@@ -240,6 +245,11 @@ static int __init mod_init(void)
if (!dev)
goto out; /* Device not found. */
+ if (no_fwh_detect < 0) {
+ pci_dev_put(dev);
+ goto fwh_done;
+ }
+
/* Check for Intel 82802 */
if (dev->device < 0x2640) {
fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
@@ -252,6 +262,23 @@ static int __init mod_init(void)
pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
+ if ((bios_cntl_val &
+ (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
+ == BIOS_CNTL_LOCK_ENABLE_MASK) {
+ static __initdata /*const*/ char warning[] =
+ KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+ KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+ KERN_WARNING PFX "you are certain that your system has a functional\n"
+ KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
+
+ pci_dev_put(dev);
+ if (no_fwh_detect)
+ goto fwh_done;
+ printk(warning);
+ err = -EBUSY;
+ goto out;
+ }
+
mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
if (mem == NULL) {
pci_dev_put(dev);
@@ -280,8 +307,7 @@ static int __init mod_init(void)
pci_write_config_byte(dev,
fwh_dec_en1_off,
fwh_dec_en1_val | FWH_F8_EN_MASK);
- if (!(bios_cntl_val &
- (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+ if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK))
pci_write_config_byte(dev,
bios_cntl_off,
bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
@@ -315,6 +341,8 @@ static int __init mod_init(void)
goto out;
}
+fwh_done:
+
err = -ENOMEM;
mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
if (!mem)
@@ -350,7 +378,7 @@ static void __exit mod_exit(void)
iounmap(mem);
}
-subsys_initcall(mod_init);
+module_init(mod_init);
module_exit(mod_exit);
MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
index c9caff57db8..bab43ca32ac 100644
--- a/drivers/char/hw_random/ixp4xx-rng.c
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -64,7 +64,7 @@ static void __exit ixp4xx_rng_exit(void)
iounmap(rng_base);
}
-subsys_initcall(ixp4xx_rng_init);
+module_init(ixp4xx_rng_init);
module_exit(ixp4xx_rng_exit);
MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index 0e786b617bb..9ebf84d1865 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -176,7 +176,7 @@ static void __exit mod_exit(void)
hwrng_unregister(&via_rng);
}
-subsys_initcall(mod_init);
+module_init(mod_init);
module_exit(mod_exit);
MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets");
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h
index 5eabe47b0bc..433305062fb 100644
--- a/drivers/char/ip2/i2ellis.h
+++ b/drivers/char/ip2/i2ellis.h
@@ -606,9 +606,9 @@ static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);
// code and returning.
//
#define COMPLETE(pB,code) \
- if(1){ \
+ do { \
pB->i2eError = code; \
return (code == I2EE_GOOD);\
- }
+ } while (0)
#endif // I2ELLIS_H
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index cda2459c1d6..7c70310a49b 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -177,7 +177,7 @@ static int ip2_write_room(PTTY);
static int ip2_chars_in_buf(PTTY);
static void ip2_flush_buffer(PTTY);
static int ip2_ioctl(PTTY, struct file *, UINT, ULONG);
-static void ip2_set_termios(PTTY, struct termios *);
+static void ip2_set_termios(PTTY, struct ktermios *);
static void ip2_set_line_discipline(PTTY);
static void ip2_throttle(PTTY);
static void ip2_unthrottle(PTTY);
@@ -198,7 +198,7 @@ static void do_status(struct work_struct *);
static void ip2_wait_until_sent(PTTY,int);
-static void set_params (i2ChanStrPtr, struct termios *);
+static void set_params (i2ChanStrPtr, struct ktermios *);
static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
@@ -2398,7 +2398,7 @@ set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
/* */
/******************************************************************************/
static void
-ip2_set_termios( PTTY tty, struct termios *old_termios )
+ip2_set_termios( PTTY tty, struct ktermios *old_termios )
{
i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
@@ -2440,11 +2440,11 @@ ip2_set_line_discipline ( PTTY tty )
/* change. */
/******************************************************************************/
static void
-set_params( i2ChanStrPtr pCh, struct termios *o_tios )
+set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
{
tcflag_t cflag, iflag, lflag;
char stop_char, start_char;
- struct termios dummy;
+ struct ktermios dummy;
lflag = pCh->pTTY->termios->c_lflag;
cflag = pCh->pTTY->termios->c_cflag;
@@ -2700,7 +2700,7 @@ static
ssize_t
ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
{
- unsigned int minor = iminor(pFile->f_dentry->d_inode);
+ unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
int rc = 0;
#ifdef IP2DEBUG_IPL
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 6c59baa887a..e736119b649 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -37,8 +37,10 @@
#define BT_DEBUG_ENABLE 1 /* Generic messages */
#define BT_DEBUG_MSG 2 /* Prints all request/response buffers */
#define BT_DEBUG_STATES 4 /* Verbose look at state changes */
+/* BT_DEBUG_OFF must be zero to correspond to the default uninitialized
+ value */
-static int bt_debug = BT_DEBUG_OFF;
+static int bt_debug; /* 0 == BT_DEBUG_OFF */
module_param(bt_debug, int, 0644);
MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 375d3378eec..ff2d052177c 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -798,7 +798,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
if (copy_to_user(precv64, &recv64, sizeof(recv64)))
return -EFAULT;
- rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep,
((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
? IPMICTL_RECEIVE_MSG
: IPMICTL_RECEIVE_MSG_TRUNC),
@@ -815,7 +815,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
return rc;
}
default:
- return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+ return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg);
}
}
#endif
@@ -834,7 +834,7 @@ static const struct file_operations ipmi_fops = {
#define DEVICE_NAME "ipmidev"
-static int ipmi_major = 0;
+static int ipmi_major;
module_param(ipmi_major, int, 0);
MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
" default, or if you set it to zero, it will choose the next"
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 5703ee28e1c..53582b53da9 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -53,10 +53,10 @@
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
-static int initialized = 0;
+static int initialized;
#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_ipmi_root = NULL;
+static struct proc_dir_entry *proc_ipmi_root;
#endif /* CONFIG_PROC_FS */
/* Remain in auto-maintenance mode for this amount of time (in ms). */
@@ -2142,8 +2142,7 @@ cleanup_bmc_device(struct kref *ref)
bmc = container_of(ref, struct bmc_device, refcount);
remove_files(bmc);
- if (bmc->dev)
- platform_device_unregister(bmc->dev);
+ platform_device_unregister(bmc->dev);
kfree(bmc);
}
@@ -2341,8 +2340,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
while (ipmi_find_bmc_prod_dev_id(&ipmidriver,
bmc->id.product_id,
- bmc->id.device_id))
- {
+ bmc->id.device_id)) {
if (!warn_printed) {
printk(KERN_WARNING PFX
"This machine has two different BMCs"
@@ -3651,8 +3649,6 @@ static void ipmi_timeout_handler(long timeout_period)
unsigned long flags;
int i;
- INIT_LIST_HEAD(&timeouts);
-
rcu_read_lock();
list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
/* See if any waiting messages need to be processed. */
@@ -3673,6 +3669,7 @@ static void ipmi_timeout_handler(long timeout_period)
/* Go through the seq table and find any messages that
have timed out, putting them in the timeouts
list. */
+ INIT_LIST_HEAD(&timeouts);
spin_lock_irqsave(&intf->seq_lock, flags);
for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
check_msg_timeout(intf, &(intf->seq_table[i]),
@@ -4043,7 +4040,7 @@ static void send_panic_events(char *str)
}
#endif /* CONFIG_IPMI_PANIC_EVENT */
-static int has_panicked = 0;
+static int has_panicked;
static int panic_event(struct notifier_block *this,
unsigned long event,
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 597eb4f88b8..9d23136e598 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -58,10 +58,10 @@ static int poweroff_powercycle;
static int ifnum_to_use = -1;
/* Our local state. */
-static int ready = 0;
+static int ready;
static ipmi_user_t ipmi_user;
static int ipmi_ifnum;
-static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;
+static void (*specific_poweroff_func)(ipmi_user_t user);
/* Holds the old poweroff function so we can restore it on removal. */
static void (*old_poweroff_func)(void);
@@ -182,7 +182,7 @@ static int ipmi_request_in_rc_mode(ipmi_user_t user,
#define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1
#define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051
-static void (*atca_oem_poweroff_hook)(ipmi_user_t user) = NULL;
+static void (*atca_oem_poweroff_hook)(ipmi_user_t user);
static void pps_poweroff_atca (ipmi_user_t user)
{
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 81a0c89598e..f1afd26a509 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -845,7 +845,7 @@ static void request_events(void *send_info)
atomic_set(&smi_info->req_events, 1);
}
-static int initialized = 0;
+static int initialized;
static void smi_timeout(unsigned long data)
{
@@ -1018,17 +1018,17 @@ 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 num_regspacings;
static int regsizes[SI_MAX_PARMS];
-static int num_regsizes = 0;
+static int num_regsizes;
static int regshifts[SI_MAX_PARMS];
-static int num_regshifts = 0;
+static int num_regshifts;
static int slave_addrs[SI_MAX_PARMS];
-static int num_slave_addrs = 0;
+static int num_slave_addrs;
#define IPMI_IO_ADDR_SPACE 0
#define IPMI_MEM_ADDR_SPACE 1
-static char *addr_space_to_str[] = { "I/O", "mem" };
+static char *addr_space_to_str[] = { "i/o", "mem" };
static int hotmod_handler(const char *val, struct kernel_param *kp);
@@ -1397,20 +1397,7 @@ static struct hotmod_vals hotmod_as[] = {
{ "i/o", IPMI_IO_ADDR_SPACE },
{ NULL }
};
-static int ipmi_strcasecmp(const char *s1, const char *s2)
-{
- while (*s1 || *s2) {
- if (!*s1)
- return -1;
- if (!*s2)
- return 1;
- if (*s1 != *s2)
- return *s1 - *s2;
- s1++;
- s2++;
- }
- return 0;
-}
+
static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr)
{
char *s;
@@ -1424,7 +1411,7 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr)
*s = '\0';
s++;
for (i = 0; hotmod_ops[i].name; i++) {
- if (ipmi_strcasecmp(*curr, v[i].name) == 0) {
+ if (strcmp(*curr, v[i].name) == 0) {
*val = v[i].val;
*curr = s;
return 0;
@@ -1435,10 +1422,34 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr)
return -EINVAL;
}
+static int check_hotmod_int_op(const char *curr, const char *option,
+ const char *name, int *val)
+{
+ char *n;
+
+ if (strcmp(curr, name) == 0) {
+ if (!option) {
+ printk(KERN_WARNING PFX
+ "No option given for '%s'\n",
+ curr);
+ return -EINVAL;
+ }
+ *val = simple_strtoul(option, &n, 0);
+ if ((*n != '\0') || (*option == '\0')) {
+ printk(KERN_WARNING PFX
+ "Bad option given for '%s'\n",
+ curr);
+ return -EINVAL;
+ }
+ return 1;
+ }
+ return 0;
+}
+
static int hotmod_handler(const char *val, struct kernel_param *kp)
{
char *str = kstrdup(val, GFP_KERNEL);
- int rv = -EINVAL;
+ int rv;
char *next, *curr, *s, *n, *o;
enum hotmod_op op;
enum si_type si_type;
@@ -1450,13 +1461,15 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
int irq;
int ipmb;
int ival;
+ int len;
struct smi_info *info;
if (!str)
return -ENOMEM;
/* Kill any trailing spaces, as we can get a "\n" from echo. */
- ival = strlen(str) - 1;
+ len = strlen(str);
+ ival = len - 1;
while ((ival >= 0) && isspace(str[ival])) {
str[ival] = '\0';
ival--;
@@ -1513,35 +1526,37 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
*o = '\0';
o++;
}
-#define HOTMOD_INT_OPT(name, val) \
- if (ipmi_strcasecmp(curr, name) == 0) { \
- if (!o) { \
- printk(KERN_WARNING PFX \
- "No option given for '%s'\n", \
- curr); \
- goto out; \
- } \
- val = simple_strtoul(o, &n, 0); \
- if ((*n != '\0') || (*o == '\0')) { \
- printk(KERN_WARNING PFX \
- "Bad option given for '%s'\n", \
- curr); \
- goto out; \
- } \
- }
-
- HOTMOD_INT_OPT("rsp", regspacing)
- else HOTMOD_INT_OPT("rsi", regsize)
- else HOTMOD_INT_OPT("rsh", regshift)
- else HOTMOD_INT_OPT("irq", irq)
- else HOTMOD_INT_OPT("ipmb", ipmb)
- else {
- printk(KERN_WARNING PFX
- "Invalid hotmod option '%s'\n",
- curr);
+ rv = check_hotmod_int_op(curr, o, "rsp", &regspacing);
+ if (rv < 0)
goto out;
- }
-#undef HOTMOD_INT_OPT
+ else if (rv)
+ continue;
+ rv = check_hotmod_int_op(curr, o, "rsi", &regsize);
+ if (rv < 0)
+ goto out;
+ else if (rv)
+ continue;
+ rv = check_hotmod_int_op(curr, o, "rsh", &regshift);
+ if (rv < 0)
+ goto out;
+ else if (rv)
+ continue;
+ rv = check_hotmod_int_op(curr, o, "irq", &irq);
+ if (rv < 0)
+ goto out;
+ else if (rv)
+ continue;
+ rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb);
+ if (rv < 0)
+ goto out;
+ else if (rv)
+ continue;
+
+ rv = -EINVAL;
+ printk(KERN_WARNING PFX
+ "Invalid hotmod option '%s'\n",
+ curr);
+ goto out;
}
if (op == HM_ADD) {
@@ -1590,6 +1605,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
mutex_unlock(&smi_infos_lock);
}
}
+ rv = len;
out:
kfree(str);
return rv;
@@ -1610,11 +1626,11 @@ static __devinit void hardcode_find_bmc(void)
info->addr_source = "hardcoded";
- if (!si_type[i] || ipmi_strcasecmp(si_type[i], "kcs") == 0) {
+ if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
info->si_type = SI_KCS;
- } else if (ipmi_strcasecmp(si_type[i], "smic") == 0) {
+ } else if (strcmp(si_type[i], "smic") == 0) {
info->si_type = SI_SMIC;
- } else if (ipmi_strcasecmp(si_type[i], "bt") == 0) {
+ } else if (strcmp(si_type[i], "bt") == 0) {
info->si_type = SI_BT;
} else {
printk(KERN_WARNING
@@ -1668,7 +1684,7 @@ static __devinit void hardcode_find_bmc(void)
/* Once we get an ACPI failure, we don't try any more, because we go
through the tables sequentially. Once we don't find a table, there
are no more. */
-static int acpi_failure = 0;
+static int acpi_failure;
/* For GPE-type interrupts. */
static u32 ipmi_acpi_gpe(void *context)
@@ -1779,7 +1795,6 @@ struct SPMITable {
static __devinit int try_init_acpi(struct SPMITable *spmi)
{
struct smi_info *info;
- char *io_type;
u8 addr_space;
if (spmi->IPMIlegacy != 1) {
@@ -1843,11 +1858,9 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
info->io.regshift = spmi->addr.register_bit_offset;
if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
- io_type = "memory";
info->io_setup = mem_setup;
info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
- io_type = "I/O";
info->io_setup = port_setup;
info->io.addr_type = IPMI_MEM_ADDR_SPACE;
} else {
@@ -2773,8 +2786,7 @@ static __devinit int init_ipmi_si(void)
#endif
#ifdef CONFIG_ACPI
- if (si_trydefaults)
- acpi_find_bmc();
+ acpi_find_bmc();
#endif
#ifdef CONFIG_PCI
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 90fb2a54191..6b634e8d951 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -134,14 +134,14 @@
static int nowayout = WATCHDOG_NOWAYOUT;
-static ipmi_user_t watchdog_user = NULL;
+static ipmi_user_t watchdog_user;
static int watchdog_ifnum;
/* Default the timeout to 10 seconds. */
static int timeout = 10;
/* The pre-timeout is disabled by default. */
-static int pretimeout = 0;
+static int pretimeout;
/* Default action is to reset the board on a timeout. */
static unsigned char action_val = WDOG_TIMEOUT_RESET;
@@ -156,10 +156,10 @@ static unsigned char preop_val = WDOG_PREOP_NONE;
static char preop[16] = "preop_none";
static DEFINE_SPINLOCK(ipmi_read_lock);
-static char data_to_read = 0;
+static char data_to_read;
static DECLARE_WAIT_QUEUE_HEAD(read_q);
-static struct fasync_struct *fasync_q = NULL;
-static char pretimeout_since_last_heartbeat = 0;
+static struct fasync_struct *fasync_q;
+static char pretimeout_since_last_heartbeat;
static char expect_close;
static int ifnum_to_use = -1;
@@ -177,7 +177,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf);
/* If true, the driver will start running as soon as it is configured
and ready. */
-static int start_now = 0;
+static int start_now;
static int set_param_int(const char *val, struct kernel_param *kp)
{
@@ -216,13 +216,13 @@ static int set_param_str(const char *val, struct kernel_param *kp)
{
action_fn fn = (action_fn) kp->arg;
int rv = 0;
- char *dup, *s;
+ char valcp[16];
+ char *s;
- dup = kstrdup(val, GFP_KERNEL);
- if (!dup)
- return -ENOMEM;
+ strncpy(valcp, val, 16);
+ valcp[15] = '\0';
- s = strstrip(dup);
+ s = strstrip(valcp);
down_read(&register_sem);
rv = fn(s, NULL);
@@ -235,7 +235,6 @@ static int set_param_str(const char *val, struct kernel_param *kp)
out_unlock:
up_read(&register_sem);
- kfree(dup);
return rv;
}
@@ -300,16 +299,16 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
/* If shutting down via IPMI, we ignore the heartbeat. */
-static int ipmi_ignore_heartbeat = 0;
+static int ipmi_ignore_heartbeat;
/* Is someone using the watchdog? Only one user is allowed. */
-static unsigned long ipmi_wdog_open = 0;
+static unsigned long ipmi_wdog_open;
/* If set to 1, the heartbeat command will set the state to reset and
start the timer. The timer doesn't normally run when the driver is
first opened until the heartbeat is set the first time, this
variable is used to accomplish this. */
-static int ipmi_start_timer_on_heartbeat = 0;
+static int ipmi_start_timer_on_heartbeat;
/* IPMI version of the BMC. */
static unsigned char ipmi_version_major;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 1637c1d9a4b..01084abffdd 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -172,12 +172,14 @@ static struct pci_driver isicom_driver = {
static int prev_card = 3; /* start servicing isi_card[0] */
static struct tty_driver *isicom_normal;
-static struct timer_list tx;
+static DECLARE_COMPLETION(isi_timerdone);
static char re_schedule = 1;
static void isicom_tx(unsigned long _data);
static void isicom_start(struct tty_struct *tty);
+static DEFINE_TIMER(tx, isicom_tx, 0, 0);
+
/* baud index mappings from linux defns to isi */
static signed char linuxb_to_isib[] = {
@@ -193,9 +195,9 @@ struct isi_board {
unsigned short shift_count;
struct isi_port * ports;
signed char count;
- unsigned char isa;
spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */
unsigned long flags;
+ unsigned int index;
};
struct isi_port {
@@ -228,6 +230,20 @@ static struct isi_port isi_ports[PORT_COUNT];
* it wants to talk.
*/
+static inline int WaitTillCardIsFree(u16 base)
+{
+ unsigned int count = 0;
+ unsigned int a = in_atomic(); /* do we run under spinlock? */
+
+ while (!(inw(base + 0xe) & 0x1) && count++ < 100)
+ if (a)
+ mdelay(1);
+ else
+ msleep(1);
+
+ return !(inw(base + 0xe) & 0x1);
+}
+
static int lock_card(struct isi_board *card)
{
char retries;
@@ -274,69 +290,71 @@ static void unlock_card(struct isi_board *card)
* ISI Card specific ops ...
*/
+/* card->lock HAS to be held */
static void raise_dtr(struct isi_port *port)
{
struct isi_board *card = port->card;
unsigned long base = card->base;
u16 channel = port->channel;
- if (!lock_card(card))
+ if (WaitTillCardIsFree(base))
return;
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0504, base);
InterruptTheCard(base);
port->status |= ISI_DTR;
- unlock_card(card);
}
+/* card->lock HAS to be held */
static inline void drop_dtr(struct isi_port *port)
{
struct isi_board *card = port->card;
unsigned long base = card->base;
u16 channel = port->channel;
- if (!lock_card(card))
+ if (WaitTillCardIsFree(base))
return;
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0404, base);
InterruptTheCard(base);
port->status &= ~ISI_DTR;
- unlock_card(card);
}
+/* card->lock HAS to be held */
static inline void raise_rts(struct isi_port *port)
{
struct isi_board *card = port->card;
unsigned long base = card->base;
u16 channel = port->channel;
- if (!lock_card(card))
+ if (WaitTillCardIsFree(base))
return;
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0a04, base);
InterruptTheCard(base);
port->status |= ISI_RTS;
- unlock_card(card);
}
+
+/* card->lock HAS to be held */
static inline void drop_rts(struct isi_port *port)
{
struct isi_board *card = port->card;
unsigned long base = card->base;
u16 channel = port->channel;
- if (!lock_card(card))
+ if (WaitTillCardIsFree(base))
return;
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0804, base);
InterruptTheCard(base);
port->status &= ~ISI_RTS;
- unlock_card(card);
}
+/* card->lock MUST NOT be held */
static inline void raise_dtr_rts(struct isi_port *port)
{
struct isi_board *card = port->card;
@@ -353,35 +371,20 @@ static inline void raise_dtr_rts(struct isi_port *port)
unlock_card(card);
}
+/* card->lock HAS to be held */
static void drop_dtr_rts(struct isi_port *port)
{
struct isi_board *card = port->card;
unsigned long base = card->base;
u16 channel = port->channel;
- if (!lock_card(card))
+ if (WaitTillCardIsFree(base))
return;
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0c04, base);
InterruptTheCard(base);
port->status &= ~(ISI_RTS | ISI_DTR);
- unlock_card(card);
-}
-
-static inline void kill_queue(struct isi_port *port, short queue)
-{
- struct isi_board *card = port->card;
- unsigned long base = card->base;
- u16 channel = port->channel;
-
- if (!lock_card(card))
- return;
-
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw((queue << 8) | 0x06, base);
- InterruptTheCard(base);
- unlock_card(card);
}
/*
@@ -514,17 +517,11 @@ static void isicom_tx(unsigned long _data)
/* schedule another tx for hopefully in about 10ms */
sched_again:
if (!re_schedule) {
- re_schedule = 2;
+ complete(&isi_timerdone);
return;
}
- init_timer(&tx);
- tx.expires = jiffies + HZ/100;
- tx.data = 0;
- tx.function = isicom_tx;
- add_timer(&tx);
-
- return;
+ mod_timer(&tx, jiffies + msecs_to_jiffies(10));
}
/* Interrupt handlers */
@@ -562,14 +559,12 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
base = card->base;
spin_lock(&card->card_lock);
- if (card->isa == NO) {
- /*
- * disable any interrupts from the PCI card and lower the
- * interrupt line
- */
- outw(0x8000, base+0x04);
- ClearInterrupt(base);
- }
+ /*
+ * disable any interrupts from the PCI card and lower the
+ * interrupt line
+ */
+ outw(0x8000, base+0x04);
+ ClearInterrupt(base);
inw(base); /* get the dummy word out */
header = inw(base);
@@ -579,19 +574,13 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
if (channel + 1 > card->port_count) {
printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
"%d(channel) > port_count.\n", base, channel+1);
- if (card->isa)
- ClearInterrupt(base);
- else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
spin_unlock(&card->card_lock);
return IRQ_HANDLED;
}
port = card->ports + channel;
if (!(port->flags & ASYNC_INITIALIZED)) {
- if (card->isa)
- ClearInterrupt(base);
- else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
return IRQ_HANDLED;
}
@@ -604,10 +593,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
}
if (byte_count & 0x01)
inw(base);
- if (card->isa == YES)
- ClearInterrupt(base);
- else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
spin_unlock(&card->card_lock);
return IRQ_HANDLED;
}
@@ -708,10 +694,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
}
tty_flip_buffer_push(tty);
}
- if (card->isa == YES)
- ClearInterrupt(base);
- else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
return IRQ_HANDLED;
}
@@ -762,7 +745,7 @@ static void isicom_config_port(struct isi_port *port)
else
raise_dtr(port);
- if (lock_card(card)) {
+ if (WaitTillCardIsFree(base) == 0) {
outw(0x8000 | (channel << shift_count) |0x03, base);
outw(linuxb_to_isib[baud] << 8 | 0x03, base);
channel_setup = 0;
@@ -790,7 +773,6 @@ static void isicom_config_port(struct isi_port *port)
}
outw(channel_setup, base);
InterruptTheCard(base);
- unlock_card(card);
}
if (C_CLOCAL(tty))
port->flags &= ~ASYNC_CHECK_CD;
@@ -809,12 +791,11 @@ static void isicom_config_port(struct isi_port *port)
if (I_IXOFF(tty))
flow_ctrl |= ISICOM_INITIATE_XONXOFF;
- if (lock_card(card)) {
+ if (WaitTillCardIsFree(base) == 0) {
outw(0x8000 | (channel << shift_count) |0x04, base);
outw(flow_ctrl << 8 | 0x05, base);
outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
InterruptTheCard(base);
- unlock_card(card);
}
/* rx enabled -> enable port for rx on the card */
@@ -839,10 +820,9 @@ static inline void isicom_setup_board(struct isi_board *bp)
}
port = bp->ports;
bp->status |= BOARD_ACTIVE;
- spin_unlock_irqrestore(&bp->card_lock, flags);
for (channel = 0; channel < bp->port_count; channel++, port++)
drop_dtr_rts(port);
- return;
+ spin_unlock_irqrestore(&bp->card_lock, flags);
}
static int isicom_setup_port(struct isi_port *port)
@@ -875,7 +855,12 @@ static int isicom_setup_port(struct isi_port *port)
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
/* discard any residual data */
- kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
+ if (WaitTillCardIsFree(card->base) == 0) {
+ outw(0x8000 | (port->channel << card->shift_count) | 0x02,
+ card->base);
+ outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
+ InterruptTheCard(card->base);
+ }
isicom_config_port(port);
port->flags |= ASYNC_INITIALIZED;
@@ -964,8 +949,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
{
struct isi_port *port;
struct isi_board *card;
- unsigned int line, board;
- int error;
+ unsigned int board;
+ int error, line;
line = tty->index;
if (line < 0 || line > PORT_COUNT-1)
@@ -1001,28 +986,22 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
static inline void isicom_shutdown_board(struct isi_board *bp)
{
- unsigned long flags;
-
- spin_lock_irqsave(&bp->card_lock, flags);
if (bp->status & BOARD_ACTIVE) {
bp->status &= ~BOARD_ACTIVE;
}
- spin_unlock_irqrestore(&bp->card_lock, flags);
}
+/* card->lock HAS to be held */
static void isicom_shutdown_port(struct isi_port *port)
{
struct isi_board *card = port->card;
struct tty_struct *tty;
- unsigned long flags;
tty = port->tty;
- spin_lock_irqsave(&card->card_lock, flags);
- if (!(port->flags & ASYNC_INITIALIZED)) {
- spin_unlock_irqrestore(&card->card_lock, flags);
+ if (!(port->flags & ASYNC_INITIALIZED))
return;
- }
+
if (port->xmit_buf) {
free_page((unsigned long) port->xmit_buf);
port->xmit_buf = NULL;
@@ -1030,7 +1009,6 @@ static void isicom_shutdown_port(struct isi_port *port)
port->flags &= ~ASYNC_INITIALIZED;
/* 3rd October 2000 : Vinayak P Risbud */
port->tty = NULL;
- spin_unlock_irqrestore(&card->card_lock, flags);
/*Fix done by Anil .S on 30-04-2001
remote login through isi port has dtr toggle problem
@@ -1276,10 +1254,12 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct isi_port *port = tty->driver_data;
+ unsigned long flags;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
+ spin_lock_irqsave(&port->card->card_lock, flags);
if (set & TIOCM_RTS)
raise_rts(port);
if (set & TIOCM_DTR)
@@ -1289,6 +1269,7 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
drop_rts(port);
if (clear & TIOCM_DTR)
drop_dtr(port);
+ spin_unlock_irqrestore(&port->card->card_lock, flags);
return 0;
}
@@ -1321,7 +1302,10 @@ static int isicom_set_serial_info(struct isi_port *port,
(newinfo.flags & ASYNC_FLAGS));
}
if (reconfig_port) {
+ unsigned long flags;
+ spin_lock_irqsave(&port->card->card_lock, flags);
isicom_config_port(port);
+ spin_unlock_irqrestore(&port->card->card_lock, flags);
}
return 0;
}
@@ -1399,9 +1383,10 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
/* set_termios et all */
static void isicom_set_termios(struct tty_struct *tty,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct isi_port *port = tty->driver_data;
+ unsigned long flags;
if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
return;
@@ -1410,7 +1395,9 @@ static void isicom_set_termios(struct tty_struct *tty,
tty->termios->c_iflag == old_termios->c_iflag)
return;
+ spin_lock_irqsave(&port->card->card_lock, flags);
isicom_config_port(port);
+ spin_unlock_irqrestore(&port->card->card_lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
@@ -1487,11 +1474,15 @@ static void do_isicom_hangup(struct work_struct *work)
static void isicom_hangup(struct tty_struct *tty)
{
struct isi_port *port = tty->driver_data;
+ unsigned long flags;
if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
return;
+ spin_lock_irqsave(&port->card->card_lock, flags);
isicom_shutdown_port(port);
+ spin_unlock_irqrestore(&port->card->card_lock, flags);
+
port->count = 0;
port->flags &= ~ASYNC_NORMAL_ACTIVE;
port->tty = NULL;
@@ -1520,37 +1511,6 @@ static void isicom_flush_buffer(struct tty_struct *tty)
* Driver init and deinit functions
*/
-static int __devinit isicom_register_ioregion(struct pci_dev *pdev,
- const unsigned int index)
-{
- struct isi_board *board = pci_get_drvdata(pdev);
-
- if (!board->base)
- return -EINVAL;
-
- if (!request_region(board->base, 16, ISICOM_NAME)) {
- dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
- "will be disabled.\n", board->base, board->base + 15,
- index + 1);
- return -EBUSY;
- }
-
- return 0;
-}
-
-static void isicom_unregister_ioregion(struct pci_dev *pdev)
-{
- struct isi_board *board = pci_get_drvdata(pdev);
-
- if (!board->base)
- return;
-
- release_region(board->base, 16);
- dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n",
- board->base, board->base + 15);
- board->base = 0;
-}
-
static const struct tty_operations isicom_ops = {
.open = isicom_open,
.close = isicom_close,
@@ -1571,70 +1531,6 @@ static const struct tty_operations isicom_ops = {
.tiocmset = isicom_tiocmset,
};
-static int __devinit isicom_register_tty_driver(void)
-{
- int error = -ENOMEM;
-
- /* tty driver structure initialization */
- isicom_normal = alloc_tty_driver(PORT_COUNT);
- if (!isicom_normal)
- goto end;
-
- isicom_normal->owner = THIS_MODULE;
- isicom_normal->name = "ttyM";
- isicom_normal->major = ISICOM_NMAJOR;
- isicom_normal->minor_start = 0;
- isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
- isicom_normal->subtype = SERIAL_TYPE_NORMAL;
- isicom_normal->init_termios = tty_std_termios;
- isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
- CLOCAL;
- isicom_normal->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(isicom_normal, &isicom_ops);
-
- if ((error = tty_register_driver(isicom_normal))) {
- pr_dbg("Couldn't register the dialin driver, error=%d\n",
- error);
- put_tty_driver(isicom_normal);
- }
-end:
- return error;
-}
-
-static void isicom_unregister_tty_driver(void)
-{
- int error;
-
- if ((error = tty_unregister_driver(isicom_normal)))
- pr_dbg("couldn't unregister normal driver, error=%d.\n", error);
-
- put_tty_driver(isicom_normal);
-}
-
-static int __devinit isicom_register_isr(struct pci_dev *pdev,
- const unsigned int index)
-{
- struct isi_board *board = pci_get_drvdata(pdev);
- unsigned long irqflags = IRQF_DISABLED;
- int retval = -EINVAL;
-
- if (!board->base)
- goto end;
-
- if (board->isa == NO)
- irqflags |= IRQF_SHARED;
-
- retval = request_irq(board->irq, isicom_interrupt, irqflags,
- ISICOM_NAME, board);
- if (retval < 0)
- dev_warn(&pdev->dev, "Could not install handler at Irq %d. "
- "Card%d will be disabled.\n", board->irq, index + 1);
- else
- retval = 0;
-end:
- return retval;
-}
-
static int __devinit reset_card(struct pci_dev *pdev,
const unsigned int card, unsigned int *signature)
{
@@ -1656,36 +1552,23 @@ static int __devinit reset_card(struct pci_dev *pdev,
*signature = inw(base + 0x4) & 0xff;
- if (board->isa == YES) {
- if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) {
- dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
- inw(base + 0x2), inw(base + 0xe));
- dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure "
- "(Possible bad I/O Port Address 0x%lx).\n",
- card + 1, base);
- retval = -EIO;
- goto end;
- }
- } else {
- portcount = inw(base + 0x2);
- if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
- (portcount != 4) && (portcount != 8))) {
- dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
- inw(base + 0x2), inw(base + 0xe));
- dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
- "(Possible bad I/O Port Address 0x%lx).\n",
- card + 1, base);
- retval = -EIO;
- goto end;
- }
+ portcount = inw(base + 0x2);
+ if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
+ (portcount != 4) && (portcount != 8))) {
+ dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+ inw(base + 0x2), inw(base + 0xe));
+ dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
+ "(Possible bad I/O Port Address 0x%lx).\n",
+ card + 1, base);
+ retval = -EIO;
+ goto end;
}
switch (*signature) {
case 0xa5:
case 0xbb:
case 0xdd:
- board->port_count = (board->isa == NO && portcount == 4) ? 4 :
- 8;
+ board->port_count = (portcount == 4) ? 4 : 8;
board->shift_count = 12;
break;
case 0xcc:
@@ -1704,16 +1587,6 @@ end:
return retval;
}
-static inline int WaitTillCardIsFree(u16 base)
-{
- unsigned long count = 0;
-
- while (!(inw(base + 0xe) & 0x1) && count++ < 100)
- msleep(5);
-
- return !(inw(base + 0xe) & 0x1);
-}
-
static int __devinit load_firmware(struct pci_dev *pdev,
const unsigned int index, const unsigned int signature)
{
@@ -1831,6 +1704,11 @@ static int __devinit load_firmware(struct pci_dev *pdev,
}
data = kmalloc(word_count * 2, GFP_KERNEL);
+ if (data == NULL) {
+ dev_err(&pdev->dev, "Card%d, firmware upload "
+ "failed, not enough memory\n", index + 1);
+ goto errrelfw;
+ }
inw(base);
insw(base, data, word_count);
InterruptTheCard(base);
@@ -1879,8 +1757,6 @@ end:
/*
* Insmod can set static symbols so keep these static
*/
-static int io[4];
-static int irq[4];
static int card;
static int __devinit isicom_probe(struct pci_dev *pdev,
@@ -1906,20 +1782,29 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
break;
}
+ board->index = index;
board->base = ioaddr;
board->irq = pciirq;
- board->isa = NO;
card++;
pci_set_drvdata(pdev, board);
- retval = isicom_register_ioregion(pdev, index);
- if (retval < 0)
+ retval = pci_request_region(pdev, 3, ISICOM_NAME);
+ if (retval) {
+ dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
+ "will be disabled.\n", board->base, board->base + 15,
+ index + 1);
+ retval = -EBUSY;
goto err;
+ }
- retval = isicom_register_isr(pdev, index);
- if (retval < 0)
+ retval = request_irq(board->irq, isicom_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
+ if (retval < 0) {
+ dev_err(&pdev->dev, "Could not install handler at Irq %d. "
+ "Card%d will be disabled.\n", board->irq, index + 1);
goto errunrr;
+ }
retval = reset_card(pdev, index, &signature);
if (retval < 0)
@@ -1929,12 +1814,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
if (retval < 0)
goto errunri;
+ for (index = 0; index < board->port_count; index++)
+ tty_register_device(isicom_normal, board->index * 16 + index,
+ &pdev->dev);
+
return 0;
errunri:
free_irq(board->irq, board);
errunrr:
- isicom_unregister_ioregion(pdev);
+ pci_release_region(pdev, 3);
err:
board->base = 0;
return retval;
@@ -1943,18 +1832,21 @@ err:
static void __devexit isicom_remove(struct pci_dev *pdev)
{
struct isi_board *board = pci_get_drvdata(pdev);
+ unsigned int i;
+
+ for (i = 0; i < board->port_count; i++)
+ tty_unregister_device(isicom_normal, board->index * 16 + i);
free_irq(board->irq, board);
- isicom_unregister_ioregion(pdev);
+ pci_release_region(pdev, 3);
}
-static int __devinit isicom_setup(void)
+static int __init isicom_init(void)
{
int retval, idx, channel;
struct isi_port *port;
card = 0;
- memset(isi_ports, 0, sizeof(isi_ports));
for(idx = 0; idx < BOARD_COUNT; idx++) {
port = &isi_ports[idx * 16];
@@ -1975,66 +1867,65 @@ static int __devinit isicom_setup(void)
}
isi_card[idx].base = 0;
isi_card[idx].irq = 0;
-
- if (!io[idx])
- continue;
-
- if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4 ||
- irq[idx] == 5 || irq[idx] == 7 ||
- irq[idx] == 10 || irq[idx] == 11 ||
- irq[idx] == 12 || irq[idx] == 15) {
- printk(KERN_ERR "ISICOM: ISA not supported yet.\n");
- retval = -EINVAL;
- goto error;
- } else
- printk(KERN_ERR "ISICOM: Irq %d unsupported. "
- "Disabling Card%d...\n", irq[idx], idx + 1);
}
- retval = isicom_register_tty_driver();
- if (retval < 0)
+ /* tty driver structure initialization */
+ isicom_normal = alloc_tty_driver(PORT_COUNT);
+ if (!isicom_normal) {
+ retval = -ENOMEM;
goto error;
+ }
+
+ isicom_normal->owner = THIS_MODULE;
+ isicom_normal->name = "ttyM";
+ isicom_normal->major = ISICOM_NMAJOR;
+ isicom_normal->minor_start = 0;
+ isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
+ isicom_normal->subtype = SERIAL_TYPE_NORMAL;
+ isicom_normal->init_termios = tty_std_termios;
+ isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
+ isicom_normal->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(isicom_normal, &isicom_ops);
+
+ retval = tty_register_driver(isicom_normal);
+ if (retval) {
+ pr_dbg("Couldn't register the dialin driver\n");
+ goto err_puttty;
+ }
retval = pci_register_driver(&isicom_driver);
if (retval < 0) {
printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
- goto errtty;
+ goto err_unrtty;
}
- init_timer(&tx);
- tx.expires = jiffies + 1;
- tx.data = 0;
- tx.function = isicom_tx;
- re_schedule = 1;
- add_timer(&tx);
+ mod_timer(&tx, jiffies + 1);
return 0;
-errtty:
- isicom_unregister_tty_driver();
+err_unrtty:
+ tty_unregister_driver(isicom_normal);
+err_puttty:
+ put_tty_driver(isicom_normal);
error:
return retval;
}
static void __exit isicom_exit(void)
{
- unsigned int index = 0;
-
re_schedule = 0;
- while (re_schedule != 2 && index++ < 100)
- msleep(10);
+ wait_for_completion_timeout(&isi_timerdone, HZ);
pci_unregister_driver(&isicom_driver);
- isicom_unregister_tty_driver();
+ tty_unregister_driver(isicom_normal);
+ put_tty_driver(isicom_normal);
}
-module_init(isicom_setup);
+module_init(isicom_init);
module_exit(isicom_exit);
MODULE_AUTHOR("MultiTech");
MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
MODULE_LICENSE("GPL");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for the cards");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for the cards");
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 8f591945ebd..68645d35187 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -14,14 +14,6 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You 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.
*/
/*****************************************************************************/
@@ -41,6 +33,7 @@
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/eisa.h>
+#include <linux/ctype.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -61,21 +54,10 @@
#define BRD_BRUMBY4 2
#define BRD_ONBOARD2 3
#define BRD_ONBOARD 4
-#define BRD_BRUMBY8 5
-#define BRD_BRUMBY16 6
#define BRD_ONBOARDE 7
-#define BRD_ONBOARD32 9
-#define BRD_ONBOARD2_32 10
-#define BRD_ONBOARDRS 11
-#define BRD_EASYIO 20
-#define BRD_ECH 21
-#define BRD_ECHMC 22
#define BRD_ECP 23
#define BRD_ECPE 24
#define BRD_ECPMC 25
-#define BRD_ECHPCI 26
-#define BRD_ECH64PCI 27
-#define BRD_EASYIOPCI 28
#define BRD_ECPPCI 29
#define BRD_BRUMBY BRD_BRUMBY4
@@ -119,20 +101,16 @@
* interrupt is required.
*/
-typedef struct {
+struct stlconf {
int brdtype;
int ioaddr1;
int ioaddr2;
unsigned long memaddr;
int irq;
int irqtype;
-} stlconf_t;
-
-static stlconf_t stli_brdconf[] = {
- /*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
};
-static int stli_nrbrds = ARRAY_SIZE(stli_brdconf);
+static unsigned int stli_nrbrds;
/* stli_lock must NOT be taken holding brd_lock */
static spinlock_t stli_lock; /* TTY logic lock */
@@ -194,9 +172,11 @@ static struct tty_struct *stli_txcooktty;
* with this termios initially. Basically all it defines is a raw port
* at 9600 baud, 8 data bits, no parity, 1 stop bit.
*/
-static struct termios stli_deftermios = {
+static struct ktermios stli_deftermios = {
.c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
.c_cc = INIT_C_CC,
+ .c_ispeed = 9600,
+ .c_ospeed = 9600,
};
/*
@@ -205,13 +185,12 @@ static struct termios stli_deftermios = {
*/
static comstats_t stli_comstats;
static combrd_t stli_brdstats;
-static asystats_t stli_cdkstats;
-static stlibrd_t stli_dummybrd;
-static stliport_t stli_dummyport;
+static struct asystats stli_cdkstats;
/*****************************************************************************/
-static stlibrd_t *stli_brds[STL_MAXBRDS];
+static DEFINE_MUTEX(stli_brdslock);
+static struct stlibrd *stli_brds[STL_MAXBRDS];
static int stli_shared;
@@ -223,6 +202,7 @@ static int stli_shared;
*/
#define BST_FOUND 0x1
#define BST_STARTED 0x2
+#define BST_PROBED 0x4
/*
* Define the set of port state flags. These are marked for internal
@@ -255,18 +235,18 @@ static char *stli_brdnames[] = {
"Brumby",
"Brumby",
"ONboard-EI",
- (char *) NULL,
+ NULL,
"ONboard",
"ONboard-MC",
"ONboard-MC",
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
"EasyIO",
"EC8/32-AT",
"EC8/32-MC",
@@ -304,12 +284,10 @@ static char **stli_brdsp[] = {
* parse any module arguments.
*/
-typedef struct stlibrdtype {
+static struct stlibrdtype {
char *name;
int type;
-} stlibrdtype_t;
-
-static stlibrdtype_t stli_brdstr[] = {
+} stli_brdstr[] = {
{ "stallion", BRD_STALLION },
{ "1", BRD_STALLION },
{ "brumby", BRD_BRUMBY },
@@ -379,6 +357,7 @@ MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
module_param_array(board3, charp, NULL, 0);
MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
+#if STLI_EISAPROBE != 0
/*
* Set up a default memory address table for EISA board probing.
* The default addresses are all bellow 1Mbyte, which has to be the
@@ -396,14 +375,11 @@ static unsigned long stli_eisamemprobeaddrs[] = {
};
static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
+#endif
/*
* Define the Stallion PCI vendor and device IDs.
*/
-#ifdef CONFIG_PCI
-#ifndef PCI_VENDOR_ID_STALLION
-#define PCI_VENDOR_ID_STALLION 0x124d
-#endif
#ifndef PCI_DEVICE_ID_ECRA
#define PCI_DEVICE_ID_ECRA 0x0004
#endif
@@ -414,7 +390,7 @@ static struct pci_device_id istallion_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
-#endif /* CONFIG_PCI */
+static struct pci_driver stli_pcidriver;
/*****************************************************************************/
@@ -615,22 +591,10 @@ MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
/*****************************************************************************/
/*
- * Define some handy local macros...
- */
-#undef MIN
-#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
-
-#undef TOLOWER
-#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
-
-/*****************************************************************************/
-
-/*
* Prototype all functions in this driver!
*/
-static int stli_parsebrd(stlconf_t *confp, char **argp);
-static int stli_init(void);
+static int stli_parsebrd(struct stlconf *confp, char **argp);
static int stli_open(struct tty_struct *tty, struct file *filp);
static void stli_close(struct tty_struct *tty, struct file *filp);
static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
@@ -639,7 +603,7 @@ static void stli_flushchars(struct tty_struct *tty);
static int stli_writeroom(struct tty_struct *tty);
static int stli_charsinbuffer(struct tty_struct *tty);
static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void stli_settermios(struct tty_struct *tty, struct termios *old);
+static void stli_settermios(struct tty_struct *tty, struct ktermios *old);
static void stli_throttle(struct tty_struct *tty);
static void stli_unthrottle(struct tty_struct *tty);
static void stli_stop(struct tty_struct *tty);
@@ -649,86 +613,84 @@ static void stli_breakctl(struct tty_struct *tty, int state);
static void stli_waituntilsent(struct tty_struct *tty, int timeout);
static void stli_sendxchar(struct tty_struct *tty, char ch);
static void stli_hangup(struct tty_struct *tty);
-static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos);
+static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos);
-static int stli_brdinit(stlibrd_t *brdp);
-static int stli_startbrd(stlibrd_t *brdp);
+static int stli_brdinit(struct stlibrd *brdp);
+static int stli_startbrd(struct stlibrd *brdp);
static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
-static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp);
+static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
static void stli_poll(unsigned long arg);
-static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp);
-static int stli_initopen(stlibrd_t *brdp, stliport_t *portp);
-static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait);
-static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait);
-static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp);
+static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
+static int stli_initopen(struct stlibrd *brdp, struct stliport *portp);
+static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
+static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
+static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);
static void stli_dohangup(struct work_struct *);
-static int stli_setport(stliport_t *portp);
-static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp);
-static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp);
+static int stli_setport(struct stliport *portp);
+static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
+static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
static long stli_mktiocm(unsigned long sigvalue);
-static void stli_read(stlibrd_t *brdp, stliport_t *portp);
-static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp);
-static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp);
+static void stli_read(struct stlibrd *brdp, struct stliport *portp);
+static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
+static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp);
static int stli_getbrdstats(combrd_t __user *bp);
-static int stli_getportstats(stliport_t *portp, comstats_t __user *cp);
-static int stli_portcmdstats(stliport_t *portp);
-static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp);
-static int stli_getportstruct(stliport_t __user *arg);
-static int stli_getbrdstruct(stlibrd_t __user *arg);
-static stlibrd_t *stli_allocbrd(void);
-
-static void stli_ecpinit(stlibrd_t *brdp);
-static void stli_ecpenable(stlibrd_t *brdp);
-static void stli_ecpdisable(stlibrd_t *brdp);
-static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_ecpreset(stlibrd_t *brdp);
-static void stli_ecpintr(stlibrd_t *brdp);
-static void stli_ecpeiinit(stlibrd_t *brdp);
-static void stli_ecpeienable(stlibrd_t *brdp);
-static void stli_ecpeidisable(stlibrd_t *brdp);
-static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_ecpeireset(stlibrd_t *brdp);
-static void stli_ecpmcenable(stlibrd_t *brdp);
-static void stli_ecpmcdisable(stlibrd_t *brdp);
-static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_ecpmcreset(stlibrd_t *brdp);
-static void stli_ecppciinit(stlibrd_t *brdp);
-static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_ecppcireset(stlibrd_t *brdp);
-
-static void stli_onbinit(stlibrd_t *brdp);
-static void stli_onbenable(stlibrd_t *brdp);
-static void stli_onbdisable(stlibrd_t *brdp);
-static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_onbreset(stlibrd_t *brdp);
-static void stli_onbeinit(stlibrd_t *brdp);
-static void stli_onbeenable(stlibrd_t *brdp);
-static void stli_onbedisable(stlibrd_t *brdp);
-static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_onbereset(stlibrd_t *brdp);
-static void stli_bbyinit(stlibrd_t *brdp);
-static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_bbyreset(stlibrd_t *brdp);
-static void stli_stalinit(stlibrd_t *brdp);
-static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
-static void stli_stalreset(stlibrd_t *brdp);
-
-static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
-
-static int stli_initecp(stlibrd_t *brdp);
-static int stli_initonb(stlibrd_t *brdp);
-static int stli_eisamemprobe(stlibrd_t *brdp);
-static int stli_initports(stlibrd_t *brdp);
-
-#ifdef CONFIG_PCI
-static int stli_initpcibrd(int brdtype, struct pci_dev *devp);
+static int stli_getportstats(struct stliport *portp, comstats_t __user *cp);
+static int stli_portcmdstats(struct stliport *portp);
+static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
+static int stli_getportstruct(struct stliport __user *arg);
+static int stli_getbrdstruct(struct stlibrd __user *arg);
+static struct stlibrd *stli_allocbrd(void);
+
+static void stli_ecpinit(struct stlibrd *brdp);
+static void stli_ecpenable(struct stlibrd *brdp);
+static void stli_ecpdisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_ecpreset(struct stlibrd *brdp);
+static void stli_ecpintr(struct stlibrd *brdp);
+static void stli_ecpeiinit(struct stlibrd *brdp);
+static void stli_ecpeienable(struct stlibrd *brdp);
+static void stli_ecpeidisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_ecpeireset(struct stlibrd *brdp);
+static void stli_ecpmcenable(struct stlibrd *brdp);
+static void stli_ecpmcdisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_ecpmcreset(struct stlibrd *brdp);
+static void stli_ecppciinit(struct stlibrd *brdp);
+static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_ecppcireset(struct stlibrd *brdp);
+
+static void stli_onbinit(struct stlibrd *brdp);
+static void stli_onbenable(struct stlibrd *brdp);
+static void stli_onbdisable(struct stlibrd *brdp);
+static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_onbreset(struct stlibrd *brdp);
+static void stli_onbeinit(struct stlibrd *brdp);
+static void stli_onbeenable(struct stlibrd *brdp);
+static void stli_onbedisable(struct stlibrd *brdp);
+static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_onbereset(struct stlibrd *brdp);
+static void stli_bbyinit(struct stlibrd *brdp);
+static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_bbyreset(struct stlibrd *brdp);
+static void stli_stalinit(struct stlibrd *brdp);
+static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void stli_stalreset(struct stlibrd *brdp);
+
+static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
+
+static int stli_initecp(struct stlibrd *brdp);
+static int stli_initonb(struct stlibrd *brdp);
+#if STLI_EISAPROBE != 0
+static int stli_eisamemprobe(struct stlibrd *brdp);
#endif
+static int stli_initports(struct stlibrd *brdp);
/*****************************************************************************/
@@ -766,136 +728,19 @@ static int stli_timeron;
static struct class *istallion_class;
-/*
- * Loadable module initialization stuff.
- */
-
-static int __init istallion_module_init(void)
-{
- stli_init();
- return 0;
-}
-
-/*****************************************************************************/
-
-static void __exit istallion_module_exit(void)
-{
- stlibrd_t *brdp;
- stliport_t *portp;
- int i, j;
-
- printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
- stli_drvversion);
-
- /*
- * Free up all allocated resources used by the ports. This includes
- * memory and interrupts.
- */
- if (stli_timeron) {
- stli_timeron = 0;
- del_timer_sync(&stli_timerlist);
- }
-
- i = tty_unregister_driver(stli_serial);
- if (i) {
- printk("STALLION: failed to un-register tty driver, "
- "errno=%d\n", -i);
- return;
- }
- put_tty_driver(stli_serial);
- for (i = 0; i < 4; i++)
- class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
- class_destroy(istallion_class);
- if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
- printk("STALLION: failed to un-register serial memory device, "
- "errno=%d\n", -i);
-
- kfree(stli_txcookbuf);
-
- for (i = 0; (i < stli_nrbrds); i++) {
- if ((brdp = stli_brds[i]) == NULL)
- continue;
- for (j = 0; (j < STL_MAXPORTS); j++) {
- portp = brdp->ports[j];
- if (portp != NULL) {
- if (portp->tty != NULL)
- tty_hangup(portp->tty);
- kfree(portp);
- }
- }
-
- iounmap(brdp->membase);
- if (brdp->iosize > 0)
- release_region(brdp->iobase, brdp->iosize);
- kfree(brdp);
- stli_brds[i] = NULL;
- }
-}
-
-module_init(istallion_module_init);
-module_exit(istallion_module_exit);
-
-/*****************************************************************************/
-
-/*
- * Check for any arguments passed in on the module load command line.
- */
-
-static void stli_argbrds(void)
+static void stli_cleanup_ports(struct stlibrd *brdp)
{
- stlconf_t conf;
- stlibrd_t *brdp;
- int i;
-
- for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) {
- memset(&conf, 0, sizeof(conf));
- if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
- continue;
- if ((brdp = stli_allocbrd()) == NULL)
- continue;
- stli_nrbrds = i + 1;
- brdp->brdnr = i;
- brdp->brdtype = conf.brdtype;
- brdp->iobase = conf.ioaddr1;
- brdp->memaddr = conf.memaddr;
- stli_brdinit(brdp);
- }
-}
-
-/*****************************************************************************/
-
-/*
- * Convert an ascii string number into an unsigned long.
- */
-
-static unsigned long stli_atol(char *str)
-{
- unsigned long val;
- int base, c;
- char *sp;
-
- val = 0;
- sp = str;
- if ((*sp == '0') && (*(sp+1) == 'x')) {
- base = 16;
- sp += 2;
- } else if (*sp == '0') {
- base = 8;
- sp++;
- } else {
- base = 10;
- }
-
- for (; (*sp != 0); sp++) {
- c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
- if ((c < 0) || (c >= base)) {
- printk("STALLION: invalid argument %s\n", str);
- val = 0;
- break;
+ struct stliport *portp;
+ unsigned int j;
+
+ for (j = 0; j < STL_MAXPORTS; j++) {
+ portp = brdp->ports[j];
+ if (portp != NULL) {
+ if (portp->tty != NULL)
+ tty_hangup(portp->tty);
+ kfree(portp);
}
- val = (val * base) + c;
}
- return(val);
}
/*****************************************************************************/
@@ -904,16 +749,16 @@ static unsigned long stli_atol(char *str)
* Parse the supplied argument string, into the board conf struct.
*/
-static int stli_parsebrd(stlconf_t *confp, char **argp)
+static int stli_parsebrd(struct stlconf *confp, char **argp)
{
+ unsigned int i;
char *sp;
- int i;
if (argp[0] == NULL || *argp[0] == 0)
return 0;
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
- *sp = TOLOWER(*sp);
+ *sp = tolower(*sp);
for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
@@ -926,9 +771,9 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
confp->brdtype = stli_brdstr[i].type;
if (argp[1] != NULL && *argp[1] != 0)
- confp->ioaddr1 = stli_atol(argp[1]);
+ confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
if (argp[2] != NULL && *argp[2] != 0)
- confp->memaddr = stli_atol(argp[2]);
+ confp->memaddr = simple_strtoul(argp[2], NULL, 0);
return(1);
}
@@ -936,10 +781,10 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
static int stli_open(struct tty_struct *tty, struct file *filp)
{
- stlibrd_t *brdp;
- stliport_t *portp;
- unsigned int minordev;
- int brdnr, portnr, rc;
+ struct stlibrd *brdp;
+ struct stliport *portp;
+ unsigned int minordev, brdnr, portnr;
+ int rc;
minordev = tty->index;
brdnr = MINOR2BRD(minordev);
@@ -951,7 +796,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
if ((brdp->state & BST_STARTED) == 0)
return -ENODEV;
portnr = MINOR2PORT(minordev);
- if ((portnr < 0) || (portnr > brdp->nrports))
+ if (portnr > brdp->nrports)
return -ENODEV;
portp = brdp->ports[portnr];
@@ -1031,8 +876,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
static void stli_close(struct tty_struct *tty, struct file *filp)
{
- stlibrd_t *brdp;
- stliport_t *portp;
+ struct stlibrd *brdp;
+ struct stliport *portp;
unsigned long flags;
portp = tty->driver_data;
@@ -1109,7 +954,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
* this still all happens pretty quickly.
*/
-static int stli_initopen(stlibrd_t *brdp, stliport_t *portp)
+static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
{
struct tty_struct *tty;
asynotify_t nt;
@@ -1157,7 +1002,7 @@ static int stli_initopen(stlibrd_t *brdp, stliport_t *portp)
* to overlap.
*/
-static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
+static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
{
cdkhdr_t __iomem *hdrp;
cdkctrl_t __iomem *cp;
@@ -1228,7 +1073,7 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i
* wait is true then must have user context (to sleep).
*/
-static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
+static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
{
cdkhdr_t __iomem *hdrp;
cdkctrl_t __iomem *cp;
@@ -1292,7 +1137,7 @@ static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg,
* to complete (as opposed to initiating the command then returning).
*/
-static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
{
wait_event_interruptible(portp->raw_wait,
!test_bit(ST_CMDING, &portp->state));
@@ -1318,16 +1163,16 @@ static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, v
* waiting for the command to complete - so must have user context.
*/
-static int stli_setport(stliport_t *portp)
+static int stli_setport(struct stliport *portp)
{
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
asyport_t aport;
if (portp == NULL)
return -ENODEV;
if (portp->tty == NULL)
return -ENODEV;
- if (portp->brdnr < 0 && portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return -ENODEV;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1344,7 +1189,7 @@ static int stli_setport(stliport_t *portp)
* maybe because if we are clocal then we don't need to wait...
*/
-static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp)
+static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp)
{
unsigned long flags;
int rc, doclocal;
@@ -1409,8 +1254,8 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
unsigned char __iomem *bits;
unsigned char __iomem *shbuf;
unsigned char *chbuf;
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned int len, stlen, head, tail, size;
unsigned long flags;
@@ -1419,7 +1264,7 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
portp = tty->driver_data;
if (portp == NULL)
return 0;
- if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+ if (portp->brdnr >= stli_nrbrds)
return 0;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1445,12 +1290,12 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
stlen = len;
}
- len = MIN(len, count);
+ len = min(len, (unsigned int)count);
count = 0;
shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
while (len > 0) {
- stlen = MIN(len, stlen);
+ stlen = min(len, stlen);
memcpy_toio(shbuf + head, chbuf, stlen);
chbuf += stlen;
len -= stlen;
@@ -1516,8 +1361,8 @@ static void stli_flushchars(struct tty_struct *tty)
unsigned char __iomem *bits;
cdkasy_t __iomem *ap;
struct tty_struct *cooktty;
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned int len, stlen, head, tail, size, count, cooksize;
unsigned char *buf;
unsigned char __iomem *shbuf;
@@ -1541,7 +1386,7 @@ static void stli_flushchars(struct tty_struct *tty)
portp = tty->driver_data;
if (portp == NULL)
return;
- if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+ if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1564,13 +1409,13 @@ static void stli_flushchars(struct tty_struct *tty)
stlen = len;
}
- len = MIN(len, cooksize);
+ len = min(len, cooksize);
count = 0;
shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
buf = stli_txcookbuf;
while (len > 0) {
- stlen = MIN(len, stlen);
+ stlen = min(len, stlen);
memcpy_toio(shbuf + head, buf, stlen);
buf += stlen;
len -= stlen;
@@ -1604,8 +1449,8 @@ static void stli_flushchars(struct tty_struct *tty)
static int stli_writeroom(struct tty_struct *tty)
{
cdkasyrq_t __iomem *rp;
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned int head, tail, len;
unsigned long flags;
@@ -1619,7 +1464,7 @@ static int stli_writeroom(struct tty_struct *tty)
portp = tty->driver_data;
if (portp == NULL)
return 0;
- if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+ if (portp->brdnr >= stli_nrbrds)
return 0;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1657,8 +1502,8 @@ static int stli_writeroom(struct tty_struct *tty)
static int stli_charsinbuffer(struct tty_struct *tty)
{
cdkasyrq_t __iomem *rp;
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned int head, tail, len;
unsigned long flags;
@@ -1667,7 +1512,7 @@ static int stli_charsinbuffer(struct tty_struct *tty)
portp = tty->driver_data;
if (portp == NULL)
return 0;
- if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+ if (portp->brdnr >= stli_nrbrds)
return 0;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1695,10 +1540,10 @@ static int stli_charsinbuffer(struct tty_struct *tty)
* Generate the serial struct info.
*/
-static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp)
+static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
{
struct serial_struct sio;
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
memset(&sio, 0, sizeof(struct serial_struct));
sio.type = PORT_UNKNOWN;
@@ -1728,7 +1573,7 @@ static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp)
* just quietly ignore any requests to change irq, etc.
*/
-static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp)
+static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp)
{
struct serial_struct sio;
int rc;
@@ -1759,13 +1604,13 @@ static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp)
static int stli_tiocmget(struct tty_struct *tty, struct file *file)
{
- stliport_t *portp = tty->driver_data;
- stlibrd_t *brdp;
+ struct stliport *portp = tty->driver_data;
+ struct stlibrd *brdp;
int rc;
if (portp == NULL)
return -ENODEV;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return 0;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1783,13 +1628,13 @@ static int stli_tiocmget(struct tty_struct *tty, struct file *file)
static int stli_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- stliport_t *portp = tty->driver_data;
- stlibrd_t *brdp;
+ struct stliport *portp = tty->driver_data;
+ struct stlibrd *brdp;
int rts = -1, dtr = -1;
if (portp == NULL)
return -ENODEV;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return 0;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1814,8 +1659,8 @@ static int stli_tiocmset(struct tty_struct *tty, struct file *file,
static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned int ival;
int rc;
void __user *argp = (void __user *)arg;
@@ -1823,7 +1668,7 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
portp = tty->driver_data;
if (portp == NULL)
return -ENODEV;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return 0;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1889,11 +1734,11 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
* Looks like it is true for the current ttys implementation..!!
*/
-static void stli_settermios(struct tty_struct *tty, struct termios *old)
+static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
{
- stliport_t *portp;
- stlibrd_t *brdp;
- struct termios *tiosp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
+ struct ktermios *tiosp;
asyport_t aport;
if (tty == NULL)
@@ -1901,7 +1746,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old)
portp = tty->driver_data;
if (portp == NULL)
return;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -1937,7 +1782,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old)
static void stli_throttle(struct tty_struct *tty)
{
- stliport_t *portp = tty->driver_data;
+ struct stliport *portp = tty->driver_data;
if (portp == NULL)
return;
set_bit(ST_RXSTOP, &portp->state);
@@ -1953,7 +1798,7 @@ static void stli_throttle(struct tty_struct *tty)
static void stli_unthrottle(struct tty_struct *tty)
{
- stliport_t *portp = tty->driver_data;
+ struct stliport *portp = tty->driver_data;
if (portp == NULL)
return;
clear_bit(ST_RXSTOP, &portp->state);
@@ -1992,7 +1837,7 @@ static void stli_start(struct tty_struct *tty)
static void stli_dohangup(struct work_struct *ugly_api)
{
- stliport_t *portp = container_of(ugly_api, stliport_t, tqhangup);
+ struct stliport *portp = container_of(ugly_api, struct stliport, tqhangup);
if (portp->tty != NULL) {
tty_hangup(portp->tty);
}
@@ -2009,14 +1854,14 @@ static void stli_dohangup(struct work_struct *ugly_api)
static void stli_hangup(struct tty_struct *tty)
{
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned long flags;
portp = tty->driver_data;
if (portp == NULL)
return;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -2062,14 +1907,14 @@ static void stli_hangup(struct tty_struct *tty)
static void stli_flushbuffer(struct tty_struct *tty)
{
- stliport_t *portp;
- stlibrd_t *brdp;
+ struct stliport *portp;
+ struct stlibrd *brdp;
unsigned long ftype, flags;
portp = tty->driver_data;
if (portp == NULL)
return;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -2099,14 +1944,14 @@ static void stli_flushbuffer(struct tty_struct *tty)
static void stli_breakctl(struct tty_struct *tty, int state)
{
- stlibrd_t *brdp;
- stliport_t *portp;
+ struct stlibrd *brdp;
+ struct stliport *portp;
long arg;
portp = tty->driver_data;
if (portp == NULL)
return;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -2120,7 +1965,7 @@ static void stli_breakctl(struct tty_struct *tty, int state)
static void stli_waituntilsent(struct tty_struct *tty, int timeout)
{
- stliport_t *portp;
+ struct stliport *portp;
unsigned long tend;
if (tty == NULL)
@@ -2146,14 +1991,14 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)
static void stli_sendxchar(struct tty_struct *tty, char ch)
{
- stlibrd_t *brdp;
- stliport_t *portp;
+ struct stlibrd *brdp;
+ struct stliport *portp;
asyctrl_t actrl;
portp = tty->driver_data;
if (portp == NULL)
return;
- if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+ if (portp->brdnr >= stli_nrbrds)
return;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
@@ -2181,7 +2026,7 @@ static void stli_sendxchar(struct tty_struct *tty, char ch)
* short then padded with spaces).
*/
-static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos)
+static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos)
{
char *sp, *uart;
int rc, cnt;
@@ -2244,9 +2089,9 @@ static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *p
static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- stlibrd_t *brdp;
- stliport_t *portp;
- int brdnr, portnr, totalport;
+ struct stlibrd *brdp;
+ struct stliport *portp;
+ unsigned int brdnr, portnr, totalport;
int curoff, maxoff;
char *pos;
@@ -2316,7 +2161,7 @@ stli_readdone:
* entry point)
*/
-static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
{
cdkhdr_t __iomem *hdrp;
cdkctrl_t __iomem *cp;
@@ -2352,7 +2197,7 @@ static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd
spin_unlock_irqrestore(&brd_lock, flags);
}
-static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
{
unsigned long flags;
@@ -2371,7 +2216,7 @@ static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd,
* more chars to unload.
*/
-static void stli_read(stlibrd_t *brdp, stliport_t *portp)
+static void stli_read(struct stlibrd *brdp, struct stliport *portp)
{
cdkasyrq_t __iomem *rp;
char __iomem *shbuf;
@@ -2406,7 +2251,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp)
while (len > 0) {
unsigned char *cptr;
- stlen = MIN(len, stlen);
+ stlen = min(len, stlen);
tty_prepare_flip_string(tty, &cptr, stlen);
memcpy_fromio(cptr, shbuf + tail, stlen);
len -= stlen;
@@ -2433,7 +2278,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp)
* difficult to deal with them here.
*/
-static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp)
+static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
{
int cmd;
@@ -2481,7 +2326,7 @@ static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp)
* then port is still busy, otherwise no longer busy.
*/
-static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
+static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
{
cdkasy_t __iomem *ap;
cdkctrl_t __iomem *cp;
@@ -2628,9 +2473,9 @@ static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
* at the cdk header structure.
*/
-static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp)
+static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
{
- stliport_t *portp;
+ struct stliport *portp;
unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
unsigned char __iomem *slavep;
@@ -2697,11 +2542,10 @@ static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp)
static void stli_poll(unsigned long arg)
{
cdkhdr_t __iomem *hdrp;
- stlibrd_t *brdp;
- int brdnr;
+ struct stlibrd *brdp;
+ unsigned int brdnr;
- stli_timerlist.expires = STLI_TIMEOUT;
- add_timer(&stli_timerlist);
+ mod_timer(&stli_timerlist, STLI_TIMEOUT);
/*
* Check each board and do any servicing required.
@@ -2730,7 +2574,7 @@ static void stli_poll(unsigned long arg)
* the slave.
*/
-static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
+static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp)
{
memset(pp, 0, sizeof(asyport_t));
@@ -2879,13 +2723,13 @@ static long stli_mktiocm(unsigned long sigvalue)
* we need to do here is set up the appropriate per port data structures.
*/
-static int stli_initports(stlibrd_t *brdp)
+static int stli_initports(struct stlibrd *brdp)
{
- stliport_t *portp;
- int i, panelnr, panelport;
+ struct stliport *portp;
+ unsigned int i, panelnr, panelport;
for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
- portp = kzalloc(sizeof(stliport_t), GFP_KERNEL);
+ portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
if (!portp) {
printk("STALLION: failed to allocate port structure\n");
continue;
@@ -2919,7 +2763,7 @@ static int stli_initports(stlibrd_t *brdp)
* All the following routines are board specific hardware operations.
*/
-static void stli_ecpinit(stlibrd_t *brdp)
+static void stli_ecpinit(struct stlibrd *brdp)
{
unsigned long memconf;
@@ -2934,21 +2778,21 @@ static void stli_ecpinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void stli_ecpenable(stlibrd_t *brdp)
+static void stli_ecpenable(struct stlibrd *brdp)
{
outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
}
/*****************************************************************************/
-static void stli_ecpdisable(stlibrd_t *brdp)
+static void stli_ecpdisable(struct stlibrd *brdp)
{
outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
}
/*****************************************************************************/
-static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
unsigned char val;
@@ -2969,7 +2813,7 @@ static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, in
/*****************************************************************************/
-static void stli_ecpreset(stlibrd_t *brdp)
+static void stli_ecpreset(struct stlibrd *brdp)
{
outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
udelay(10);
@@ -2979,7 +2823,7 @@ static void stli_ecpreset(stlibrd_t *brdp)
/*****************************************************************************/
-static void stli_ecpintr(stlibrd_t *brdp)
+static void stli_ecpintr(struct stlibrd *brdp)
{
outb(0x1, brdp->iobase);
}
@@ -2990,7 +2834,7 @@ static void stli_ecpintr(stlibrd_t *brdp)
* The following set of functions act on ECP EISA boards.
*/
-static void stli_ecpeiinit(stlibrd_t *brdp)
+static void stli_ecpeiinit(struct stlibrd *brdp)
{
unsigned long memconf;
@@ -3008,21 +2852,21 @@ static void stli_ecpeiinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void stli_ecpeienable(stlibrd_t *brdp)
+static void stli_ecpeienable(struct stlibrd *brdp)
{
outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
}
/*****************************************************************************/
-static void stli_ecpeidisable(stlibrd_t *brdp)
+static void stli_ecpeidisable(struct stlibrd *brdp)
{
outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
}
/*****************************************************************************/
-static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
unsigned char val;
@@ -3046,7 +2890,7 @@ static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset,
/*****************************************************************************/
-static void stli_ecpeireset(stlibrd_t *brdp)
+static void stli_ecpeireset(struct stlibrd *brdp)
{
outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
udelay(10);
@@ -3060,21 +2904,21 @@ static void stli_ecpeireset(stlibrd_t *brdp)
* The following set of functions act on ECP MCA boards.
*/
-static void stli_ecpmcenable(stlibrd_t *brdp)
+static void stli_ecpmcenable(struct stlibrd *brdp)
{
outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
}
/*****************************************************************************/
-static void stli_ecpmcdisable(stlibrd_t *brdp)
+static void stli_ecpmcdisable(struct stlibrd *brdp)
{
outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
}
/*****************************************************************************/
-static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
unsigned char val;
@@ -3095,7 +2939,7 @@ static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset,
/*****************************************************************************/
-static void stli_ecpmcreset(stlibrd_t *brdp)
+static void stli_ecpmcreset(struct stlibrd *brdp)
{
outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
udelay(10);
@@ -3109,7 +2953,7 @@ static void stli_ecpmcreset(stlibrd_t *brdp)
* The following set of functions act on ECP PCI boards.
*/
-static void stli_ecppciinit(stlibrd_t *brdp)
+static void stli_ecppciinit(struct stlibrd *brdp)
{
outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
udelay(10);
@@ -3119,7 +2963,7 @@ static void stli_ecppciinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
unsigned char val;
@@ -3140,7 +2984,7 @@ static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset,
/*****************************************************************************/
-static void stli_ecppcireset(stlibrd_t *brdp)
+static void stli_ecppcireset(struct stlibrd *brdp)
{
outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
udelay(10);
@@ -3154,7 +2998,7 @@ static void stli_ecppcireset(stlibrd_t *brdp)
* The following routines act on ONboards.
*/
-static void stli_onbinit(stlibrd_t *brdp)
+static void stli_onbinit(struct stlibrd *brdp)
{
unsigned long memconf;
@@ -3171,21 +3015,21 @@ static void stli_onbinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void stli_onbenable(stlibrd_t *brdp)
+static void stli_onbenable(struct stlibrd *brdp)
{
outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
}
/*****************************************************************************/
-static void stli_onbdisable(stlibrd_t *brdp)
+static void stli_onbdisable(struct stlibrd *brdp)
{
outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
}
/*****************************************************************************/
-static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
@@ -3202,7 +3046,7 @@ static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, in
/*****************************************************************************/
-static void stli_onbreset(stlibrd_t *brdp)
+static void stli_onbreset(struct stlibrd *brdp)
{
outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
udelay(10);
@@ -3216,7 +3060,7 @@ static void stli_onbreset(stlibrd_t *brdp)
* The following routines act on ONboard EISA.
*/
-static void stli_onbeinit(stlibrd_t *brdp)
+static void stli_onbeinit(struct stlibrd *brdp)
{
unsigned long memconf;
@@ -3236,21 +3080,21 @@ static void stli_onbeinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void stli_onbeenable(stlibrd_t *brdp)
+static void stli_onbeenable(struct stlibrd *brdp)
{
outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
}
/*****************************************************************************/
-static void stli_onbedisable(stlibrd_t *brdp)
+static void stli_onbedisable(struct stlibrd *brdp)
{
outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
}
/*****************************************************************************/
-static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
unsigned char val;
@@ -3274,7 +3118,7 @@ static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, i
/*****************************************************************************/
-static void stli_onbereset(stlibrd_t *brdp)
+static void stli_onbereset(struct stlibrd *brdp)
{
outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
udelay(10);
@@ -3288,7 +3132,7 @@ static void stli_onbereset(stlibrd_t *brdp)
* The following routines act on Brumby boards.
*/
-static void stli_bbyinit(stlibrd_t *brdp)
+static void stli_bbyinit(struct stlibrd *brdp)
{
outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
udelay(10);
@@ -3300,7 +3144,7 @@ static void stli_bbyinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
void __iomem *ptr;
unsigned char val;
@@ -3315,7 +3159,7 @@ static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, in
/*****************************************************************************/
-static void stli_bbyreset(stlibrd_t *brdp)
+static void stli_bbyreset(struct stlibrd *brdp)
{
outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
udelay(10);
@@ -3329,7 +3173,7 @@ static void stli_bbyreset(stlibrd_t *brdp)
* The following routines act on original old Stallion boards.
*/
-static void stli_stalinit(stlibrd_t *brdp)
+static void stli_stalinit(struct stlibrd *brdp)
{
outb(0x1, brdp->iobase);
mdelay(1000);
@@ -3337,7 +3181,7 @@ static void stli_stalinit(stlibrd_t *brdp)
/*****************************************************************************/
-static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
+static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
{
BUG_ON(offset > brdp->memsize);
return brdp->membase + (offset % STAL_PAGESIZE);
@@ -3345,7 +3189,7 @@ static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, i
/*****************************************************************************/
-static void stli_stalreset(stlibrd_t *brdp)
+static void stli_stalreset(struct stlibrd *brdp)
{
u32 __iomem *vecp;
@@ -3362,21 +3206,22 @@ static void stli_stalreset(stlibrd_t *brdp)
* board types.
*/
-static int stli_initecp(stlibrd_t *brdp)
+static int stli_initecp(struct stlibrd *brdp)
{
cdkecpsig_t sig;
cdkecpsig_t __iomem *sigsp;
unsigned int status, nxtid;
char *name;
- int panelnr, nrports;
+ int retval, panelnr, nrports;
- if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
- return -EIO;
-
- if ((brdp->iobase == 0) || (brdp->memaddr == 0))
- {
- release_region(brdp->iobase, brdp->iosize);
- return -ENODEV;
+ if ((brdp->iobase == 0) || (brdp->memaddr == 0)) {
+ retval = -ENODEV;
+ goto err;
+ }
+
+ if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
+ retval = -EIO;
+ goto err;
}
brdp->iosize = ECP_IOSIZE;
@@ -3388,7 +3233,6 @@ static int stli_initecp(stlibrd_t *brdp)
*/
switch (brdp->brdtype) {
case BRD_ECP:
- brdp->membase = (void *) brdp->memaddr;
brdp->memsize = ECP_MEMSIZE;
brdp->pagesize = ECP_ATPAGESIZE;
brdp->init = stli_ecpinit;
@@ -3402,7 +3246,6 @@ static int stli_initecp(stlibrd_t *brdp)
break;
case BRD_ECPE:
- brdp->membase = (void *) brdp->memaddr;
brdp->memsize = ECP_MEMSIZE;
brdp->pagesize = ECP_EIPAGESIZE;
brdp->init = stli_ecpeiinit;
@@ -3416,7 +3259,6 @@ static int stli_initecp(stlibrd_t *brdp)
break;
case BRD_ECPMC:
- brdp->membase = (void *) brdp->memaddr;
brdp->memsize = ECP_MEMSIZE;
brdp->pagesize = ECP_MCPAGESIZE;
brdp->init = NULL;
@@ -3430,7 +3272,6 @@ static int stli_initecp(stlibrd_t *brdp)
break;
case BRD_ECPPCI:
- brdp->membase = (void *) brdp->memaddr;
brdp->memsize = ECP_PCIMEMSIZE;
brdp->pagesize = ECP_PCIPAGESIZE;
brdp->init = stli_ecppciinit;
@@ -3444,8 +3285,8 @@ static int stli_initecp(stlibrd_t *brdp)
break;
default:
- release_region(brdp->iobase, brdp->iosize);
- return -EINVAL;
+ retval = -EINVAL;
+ goto err_reg;
}
/*
@@ -3457,10 +3298,9 @@ static int stli_initecp(stlibrd_t *brdp)
EBRDINIT(brdp);
brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
- if (brdp->membase == NULL)
- {
- release_region(brdp->iobase, brdp->iosize);
- return -ENOMEM;
+ if (brdp->membase == NULL) {
+ retval = -ENOMEM;
+ goto err_reg;
}
/*
@@ -3473,12 +3313,9 @@ static int stli_initecp(stlibrd_t *brdp)
memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
EBRDDISABLE(brdp);
- if (sig.magic != cpu_to_le32(ECP_MAGIC))
- {
- release_region(brdp->iobase, brdp->iosize);
- iounmap(brdp->membase);
- brdp->membase = NULL;
- return -ENODEV;
+ if (sig.magic != cpu_to_le32(ECP_MAGIC)) {
+ retval = -ENODEV;
+ goto err_unmap;
}
/*
@@ -3503,6 +3340,13 @@ static int stli_initecp(stlibrd_t *brdp)
brdp->state |= BST_FOUND;
return 0;
+err_unmap:
+ iounmap(brdp->membase);
+ brdp->membase = NULL;
+err_reg:
+ release_region(brdp->iobase, brdp->iosize);
+err:
+ return retval;
}
/*****************************************************************************/
@@ -3512,23 +3356,27 @@ static int stli_initecp(stlibrd_t *brdp)
* This handles only these board types.
*/
-static int stli_initonb(stlibrd_t *brdp)
+static int stli_initonb(struct stlibrd *brdp)
{
cdkonbsig_t sig;
cdkonbsig_t __iomem *sigsp;
char *name;
- int i;
+ int i, retval;
/*
* Do a basic sanity check on the IO and memory addresses.
*/
- if (brdp->iobase == 0 || brdp->memaddr == 0)
- return -ENODEV;
+ if (brdp->iobase == 0 || brdp->memaddr == 0) {
+ retval = -ENODEV;
+ goto err;
+ }
brdp->iosize = ONB_IOSIZE;
- if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
- return -EIO;
+ if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
+ retval = -EIO;
+ goto err;
+ }
/*
* Based on the specific board type setup the common vars to access
@@ -3537,10 +3385,7 @@ static int stli_initonb(stlibrd_t *brdp)
*/
switch (brdp->brdtype) {
case BRD_ONBOARD:
- case BRD_ONBOARD32:
case BRD_ONBOARD2:
- case BRD_ONBOARD2_32:
- case BRD_ONBOARDRS:
brdp->memsize = ONB_MEMSIZE;
brdp->pagesize = ONB_ATPAGESIZE;
brdp->init = stli_onbinit;
@@ -3571,8 +3416,6 @@ static int stli_initonb(stlibrd_t *brdp)
break;
case BRD_BRUMBY4:
- case BRD_BRUMBY8:
- case BRD_BRUMBY16:
brdp->memsize = BBY_MEMSIZE;
brdp->pagesize = BBY_PAGESIZE;
brdp->init = stli_bbyinit;
@@ -3599,8 +3442,8 @@ static int stli_initonb(stlibrd_t *brdp)
break;
default:
- release_region(brdp->iobase, brdp->iosize);
- return -EINVAL;
+ retval = -EINVAL;
+ goto err_reg;
}
/*
@@ -3612,10 +3455,9 @@ static int stli_initonb(stlibrd_t *brdp)
EBRDINIT(brdp);
brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
- if (brdp->membase == NULL)
- {
- release_region(brdp->iobase, brdp->iosize);
- return -ENOMEM;
+ if (brdp->membase == NULL) {
+ retval = -ENOMEM;
+ goto err_reg;
}
/*
@@ -3631,12 +3473,9 @@ static int stli_initonb(stlibrd_t *brdp)
if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
- sig.magic3 != cpu_to_le16(ONB_MAGIC3))
- {
- release_region(brdp->iobase, brdp->iosize);
- iounmap(brdp->membase);
- brdp->membase = NULL;
- return -ENODEV;
+ sig.magic3 != cpu_to_le16(ONB_MAGIC3)) {
+ retval = -ENODEV;
+ goto err_unmap;
}
/*
@@ -3658,6 +3497,13 @@ static int stli_initonb(stlibrd_t *brdp)
brdp->state |= BST_FOUND;
return 0;
+err_unmap:
+ iounmap(brdp->membase);
+ brdp->membase = NULL;
+err_reg:
+ release_region(brdp->iobase, brdp->iosize);
+err:
+ return retval;
}
/*****************************************************************************/
@@ -3668,14 +3514,15 @@ static int stli_initonb(stlibrd_t *brdp)
* read in the memory map, and get the show on the road...
*/
-static int stli_startbrd(stlibrd_t *brdp)
+static int stli_startbrd(struct stlibrd *brdp)
{
cdkhdr_t __iomem *hdrp;
cdkmem_t __iomem *memp;
cdkasy_t __iomem *ap;
unsigned long flags;
- stliport_t *portp;
- int portnr, nrdevs, i, rc = 0;
+ unsigned int portnr, nrdevs, i;
+ struct stliport *portp;
+ int rc = 0;
u32 memoff;
spin_lock_irqsave(&brd_lock, flags);
@@ -3762,8 +3609,7 @@ stli_donestartup:
if (! stli_timeron) {
stli_timeron++;
- stli_timerlist.expires = STLI_TIMEOUT;
- add_timer(&stli_timerlist);
+ mod_timer(&stli_timerlist, STLI_TIMEOUT);
}
return rc;
@@ -3775,49 +3621,32 @@ stli_donestartup:
* Probe and initialize the specified board.
*/
-static int __init stli_brdinit(stlibrd_t *brdp)
+static int __devinit stli_brdinit(struct stlibrd *brdp)
{
- stli_brds[brdp->brdnr] = brdp;
+ int retval;
switch (brdp->brdtype) {
case BRD_ECP:
case BRD_ECPE:
case BRD_ECPMC:
case BRD_ECPPCI:
- stli_initecp(brdp);
+ retval = stli_initecp(brdp);
break;
case BRD_ONBOARD:
case BRD_ONBOARDE:
case BRD_ONBOARD2:
- case BRD_ONBOARD32:
- case BRD_ONBOARD2_32:
- case BRD_ONBOARDRS:
case BRD_BRUMBY4:
- case BRD_BRUMBY8:
- case BRD_BRUMBY16:
case BRD_STALLION:
- stli_initonb(brdp);
+ retval = stli_initonb(brdp);
break;
- case BRD_EASYIO:
- case BRD_ECH:
- case BRD_ECHMC:
- case BRD_ECHPCI:
- printk(KERN_ERR "STALLION: %s board type not supported in "
- "this driver\n", stli_brdnames[brdp->brdtype]);
- return -ENODEV;
default:
printk(KERN_ERR "STALLION: board=%d is unknown board "
"type=%d\n", brdp->brdnr, brdp->brdtype);
- return -ENODEV;
+ retval = -ENODEV;
}
- if ((brdp->state & BST_FOUND) == 0) {
- printk(KERN_ERR "STALLION: %s board not found, board=%d "
- "io=%x mem=%x\n",
- stli_brdnames[brdp->brdtype], brdp->brdnr,
- brdp->iobase, (int) brdp->memaddr);
- return -ENODEV;
- }
+ if (retval)
+ return retval;
stli_initports(brdp);
printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x "
@@ -3827,6 +3656,7 @@ static int __init stli_brdinit(stlibrd_t *brdp)
return 0;
}
+#if STLI_EISAPROBE != 0
/*****************************************************************************/
/*
@@ -3834,7 +3664,7 @@ static int __init stli_brdinit(stlibrd_t *brdp)
* might be. This is a bit if hack, but it is the best we can do.
*/
-static int stli_eisamemprobe(stlibrd_t *brdp)
+static int stli_eisamemprobe(struct stlibrd *brdp)
{
cdkecpsig_t ecpsig, __iomem *ecpsigp;
cdkonbsig_t onbsig, __iomem *onbsigp;
@@ -3920,10 +3750,11 @@ static int stli_eisamemprobe(stlibrd_t *brdp)
}
return 0;
}
+#endif
static int stli_getbrdnr(void)
{
- int i;
+ unsigned int i;
for (i = 0; i < STL_MAXBRDS; i++) {
if (!stli_brds[i]) {
@@ -3935,6 +3766,7 @@ static int stli_getbrdnr(void)
return -1;
}
+#if STLI_EISAPROBE != 0
/*****************************************************************************/
/*
@@ -3949,9 +3781,9 @@ static int stli_getbrdnr(void)
static int stli_findeisabrds(void)
{
- stlibrd_t *brdp;
- unsigned int iobase, eid;
- int i;
+ struct stlibrd *brdp;
+ unsigned int iobase, eid, i;
+ int brdnr, found = 0;
/*
* Firstly check if this is an EISA system. If this is not an EISA system then
@@ -3989,9 +3821,11 @@ static int stli_findeisabrds(void)
* Allocate a board structure and initialize it.
*/
if ((brdp = stli_allocbrd()) == NULL)
- return -ENOMEM;
- if ((brdp->brdnr = stli_getbrdnr()) < 0)
- return -ENOMEM;
+ return found ? : -ENOMEM;
+ brdnr = stli_getbrdnr();
+ if (brdnr < 0)
+ return found ? : -ENOMEM;
+ brdp->brdnr = (unsigned int)brdnr;
eid = inb(iobase + 0xc82);
if (eid == ECP_EISAID)
brdp->brdtype = BRD_ECPE;
@@ -4003,11 +3837,24 @@ static int stli_findeisabrds(void)
outb(0x1, (iobase + 0xc84));
if (stli_eisamemprobe(brdp))
outb(0, (iobase + 0xc84));
- stli_brdinit(brdp);
+ if (stli_brdinit(brdp) < 0) {
+ kfree(brdp);
+ continue;
+ }
+
+ stli_brds[brdp->brdnr] = brdp;
+ found++;
+
+ for (i = 0; i < brdp->nrports; i++)
+ tty_register_device(stli_serial,
+ brdp->brdnr * STL_MAXPORTS + i, NULL);
}
- return 0;
+ return found;
}
+#else
+static inline int stli_findeisabrds(void) { return 0; }
+#endif
/*****************************************************************************/
@@ -4017,72 +3864,104 @@ static int stli_findeisabrds(void)
/*****************************************************************************/
-#ifdef CONFIG_PCI
-
/*
* We have a Stallion board. Allocate a board structure and
* initialize it. Read its IO and MEMORY resources from PCI
* configuration space.
*/
-static int stli_initpcibrd(int brdtype, struct pci_dev *devp)
+static int __devinit stli_pciprobe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- stlibrd_t *brdp;
-
- if (pci_enable_device(devp))
- return -EIO;
- if ((brdp = stli_allocbrd()) == NULL)
- return -ENOMEM;
- if ((brdp->brdnr = stli_getbrdnr()) < 0) {
+ struct stlibrd *brdp;
+ unsigned int i;
+ int brdnr, retval = -EIO;
+
+ retval = pci_enable_device(pdev);
+ if (retval)
+ goto err;
+ brdp = stli_allocbrd();
+ if (brdp == NULL) {
+ retval = -ENOMEM;
+ goto err;
+ }
+ mutex_lock(&stli_brdslock);
+ brdnr = stli_getbrdnr();
+ if (brdnr < 0) {
printk(KERN_INFO "STALLION: too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
- return 0;
+ mutex_unlock(&stli_brdslock);
+ retval = -EIO;
+ goto err_fr;
}
- brdp->brdtype = brdtype;
+ brdp->brdnr = (unsigned int)brdnr;
+ stli_brds[brdp->brdnr] = brdp;
+ mutex_unlock(&stli_brdslock);
+ brdp->brdtype = BRD_ECPPCI;
/*
* We have all resources from the board, so lets setup the actual
* board structure now.
*/
- brdp->iobase = pci_resource_start(devp, 3);
- brdp->memaddr = pci_resource_start(devp, 2);
- stli_brdinit(brdp);
+ brdp->iobase = pci_resource_start(pdev, 3);
+ brdp->memaddr = pci_resource_start(pdev, 2);
+ retval = stli_brdinit(brdp);
+ if (retval)
+ goto err_null;
+
+ brdp->state |= BST_PROBED;
+ pci_set_drvdata(pdev, brdp);
+
+ EBRDENABLE(brdp);
+ brdp->enable = NULL;
+ brdp->disable = NULL;
+
+ for (i = 0; i < brdp->nrports; i++)
+ tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i,
+ &pdev->dev);
return 0;
+err_null:
+ stli_brds[brdp->brdnr] = NULL;
+err_fr:
+ kfree(brdp);
+err:
+ return retval;
}
-/*****************************************************************************/
+static void stli_pciremove(struct pci_dev *pdev)
+{
+ struct stlibrd *brdp = pci_get_drvdata(pdev);
-/*
- * Find all Stallion PCI boards that might be installed. Initialize each
- * one as it is found.
- */
+ stli_cleanup_ports(brdp);
-static int stli_findpcibrds(void)
-{
- struct pci_dev *dev = NULL;
+ iounmap(brdp->membase);
+ if (brdp->iosize > 0)
+ release_region(brdp->iobase, brdp->iosize);
- while ((dev = pci_get_device(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA, dev))) {
- stli_initpcibrd(BRD_ECPPCI, dev);
- }
- return 0;
+ stli_brds[brdp->brdnr] = NULL;
+ kfree(brdp);
}
-#endif
-
+static struct pci_driver stli_pcidriver = {
+ .name = "istallion",
+ .id_table = istallion_pci_tbl,
+ .probe = stli_pciprobe,
+ .remove = __devexit_p(stli_pciremove)
+};
/*****************************************************************************/
/*
* Allocate a new board structure. Fill out the basic info in it.
*/
-static stlibrd_t *stli_allocbrd(void)
+static struct stlibrd *stli_allocbrd(void)
{
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
- brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL);
+ brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
if (!brdp) {
printk(KERN_ERR "STALLION: failed to allocate memory "
- "(size=%Zd)\n", sizeof(stlibrd_t));
+ "(size=%Zd)\n", sizeof(struct stlibrd));
return NULL;
}
brdp->magic = STLI_BOARDMAGIC;
@@ -4098,43 +3977,37 @@ static stlibrd_t *stli_allocbrd(void)
static int stli_initbrds(void)
{
- stlibrd_t *brdp, *nxtbrdp;
- stlconf_t *confp;
- int i, j;
-
- if (stli_nrbrds > STL_MAXBRDS) {
- printk(KERN_INFO "STALLION: too many boards in configuration "
- "table, truncating to %d\n", STL_MAXBRDS);
- stli_nrbrds = STL_MAXBRDS;
- }
+ struct stlibrd *brdp, *nxtbrdp;
+ struct stlconf conf;
+ unsigned int i, j, found = 0;
+ int retval;
-/*
- * Firstly scan the list of static boards configured. Allocate
- * resources and initialize the boards as found. If this is a
- * module then let the module args override static configuration.
- */
- for (i = 0; (i < stli_nrbrds); i++) {
- confp = &stli_brdconf[i];
- stli_parsebrd(confp, stli_brdsp[i]);
+ for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
+ stli_nrbrds++) {
+ memset(&conf, 0, sizeof(conf));
+ if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
+ continue;
if ((brdp = stli_allocbrd()) == NULL)
- return -ENOMEM;
- brdp->brdnr = i;
- brdp->brdtype = confp->brdtype;
- brdp->iobase = confp->ioaddr1;
- brdp->memaddr = confp->memaddr;
- stli_brdinit(brdp);
+ continue;
+ brdp->brdnr = stli_nrbrds;
+ brdp->brdtype = conf.brdtype;
+ brdp->iobase = conf.ioaddr1;
+ brdp->memaddr = conf.memaddr;
+ if (stli_brdinit(brdp) < 0) {
+ kfree(brdp);
+ continue;
+ }
+ stli_brds[brdp->brdnr] = brdp;
+ found++;
+
+ for (i = 0; i < brdp->nrports; i++)
+ tty_register_device(stli_serial,
+ brdp->brdnr * STL_MAXPORTS + i, NULL);
}
-/*
- * Static configuration table done, so now use dynamic methods to
- * see if any more boards should be configured.
- */
- stli_argbrds();
- if (STLI_EISAPROBE)
- stli_findeisabrds();
-#ifdef CONFIG_PCI
- stli_findpcibrds();
-#endif
+ retval = stli_findeisabrds();
+ if (retval > 0)
+ found += retval;
/*
* All found boards are initialized. Now for a little optimization, if
@@ -4174,7 +4047,16 @@ static int stli_initbrds(void)
}
}
+ retval = pci_register_driver(&stli_pcidriver);
+ if (retval && found == 0) {
+ printk(KERN_ERR "Neither isa nor eisa cards found nor pci "
+ "driver can be registered!\n");
+ goto err;
+ }
+
return 0;
+err:
+ return retval;
}
/*****************************************************************************/
@@ -4189,12 +4071,13 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
{
unsigned long flags;
void __iomem *memptr;
- stlibrd_t *brdp;
- int brdnr, size, n;
+ struct stlibrd *brdp;
+ unsigned int brdnr;
+ int size, n;
void *p;
loff_t off = *offp;
- brdnr = iminor(fp->f_dentry->d_inode);
+ brdnr = iminor(fp->f_path.dentry->d_inode);
if (brdnr >= stli_nrbrds)
return -ENODEV;
brdp = stli_brds[brdnr];
@@ -4205,7 +4088,7 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
if (off >= brdp->memsize || off + count < off)
return 0;
- size = MIN(count, (brdp->memsize - off));
+ size = min(count, (size_t)(brdp->memsize - off));
/*
* Copy the data a page at a time
@@ -4219,8 +4102,8 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof
spin_lock_irqsave(&brd_lock, flags);
EBRDENABLE(brdp);
memptr = EBRDGETMEMPTR(brdp, off);
- n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
- n = MIN(n, PAGE_SIZE);
+ n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+ n = min(n, (int)PAGE_SIZE);
memcpy_fromio(p, memptr, n);
EBRDDISABLE(brdp);
spin_unlock_irqrestore(&brd_lock, flags);
@@ -4252,13 +4135,14 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
{
unsigned long flags;
void __iomem *memptr;
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
char __user *chbuf;
- int brdnr, size, n;
+ unsigned int brdnr;
+ int size, n;
void *p;
loff_t off = *offp;
- brdnr = iminor(fp->f_dentry->d_inode);
+ brdnr = iminor(fp->f_path.dentry->d_inode);
if (brdnr >= stli_nrbrds)
return -ENODEV;
@@ -4271,7 +4155,7 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
return 0;
chbuf = (char __user *) buf;
- size = MIN(count, (brdp->memsize - off));
+ size = min(count, (size_t)(brdp->memsize - off));
/*
* Copy the data a page at a time
@@ -4282,8 +4166,8 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou
return -ENOMEM;
while (size > 0) {
- n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
- n = MIN(n, PAGE_SIZE);
+ n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+ n = min(n, (int)PAGE_SIZE);
if (copy_from_user(p, chbuf, n)) {
if (count == 0)
count = -EFAULT;
@@ -4313,8 +4197,8 @@ out:
static int stli_getbrdstats(combrd_t __user *bp)
{
- stlibrd_t *brdp;
- int i;
+ struct stlibrd *brdp;
+ unsigned int i;
if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
return -EFAULT;
@@ -4350,19 +4234,20 @@ static int stli_getbrdstats(combrd_t __user *bp)
* Resolve the referenced port number into a port struct pointer.
*/
-static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
+static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
+ unsigned int portnr)
{
- stlibrd_t *brdp;
- int i;
+ struct stlibrd *brdp;
+ unsigned int i;
- if (brdnr < 0 || brdnr >= STL_MAXBRDS)
+ if (brdnr >= STL_MAXBRDS)
return NULL;
brdp = stli_brds[brdnr];
if (brdp == NULL)
return NULL;
for (i = 0; (i < panelnr); i++)
portnr += brdp->panels[i];
- if ((portnr < 0) || (portnr >= brdp->nrports))
+ if (portnr >= brdp->nrports)
return NULL;
return brdp->ports[portnr];
}
@@ -4375,10 +4260,10 @@ static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
* what port to get stats for (used through board control device).
*/
-static int stli_portcmdstats(stliport_t *portp)
+static int stli_portcmdstats(struct stliport *portp)
{
unsigned long flags;
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
int rc;
memset(&stli_comstats, 0, sizeof(comstats_t));
@@ -4449,9 +4334,9 @@ static int stli_portcmdstats(stliport_t *portp)
* what port to get stats for (used through board control device).
*/
-static int stli_getportstats(stliport_t *portp, comstats_t __user *cp)
+static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
{
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
int rc;
if (!portp) {
@@ -4480,9 +4365,9 @@ static int stli_getportstats(stliport_t *portp, comstats_t __user *cp)
* Clear the port stats structure. We also return it zeroed out...
*/
-static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp)
+static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
{
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
int rc;
if (!portp) {
@@ -4519,17 +4404,18 @@ static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp)
* Return the entire driver ports structure to a user app.
*/
-static int stli_getportstruct(stliport_t __user *arg)
+static int stli_getportstruct(struct stliport __user *arg)
{
- stliport_t *portp;
+ struct stliport stli_dummyport;
+ struct stliport *portp;
- if (copy_from_user(&stli_dummyport, arg, sizeof(stliport_t)))
+ if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
return -EFAULT;
portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
stli_dummyport.portnr);
if (!portp)
return -ENODEV;
- if (copy_to_user(arg, portp, sizeof(stliport_t)))
+ if (copy_to_user(arg, portp, sizeof(struct stliport)))
return -EFAULT;
return 0;
}
@@ -4540,18 +4426,19 @@ static int stli_getportstruct(stliport_t __user *arg)
* Return the entire driver board structure to a user app.
*/
-static int stli_getbrdstruct(stlibrd_t __user *arg)
+static int stli_getbrdstruct(struct stlibrd __user *arg)
{
- stlibrd_t *brdp;
+ struct stlibrd stli_dummybrd;
+ struct stlibrd *brdp;
- if (copy_from_user(&stli_dummybrd, arg, sizeof(stlibrd_t)))
+ if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
return -EFAULT;
- if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS))
+ if (stli_dummybrd.brdnr >= STL_MAXBRDS)
return -ENODEV;
brdp = stli_brds[stli_dummybrd.brdnr];
if (!brdp)
return -ENODEV;
- if (copy_to_user(arg, brdp, sizeof(stlibrd_t)))
+ if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
return -EFAULT;
return 0;
}
@@ -4566,7 +4453,7 @@ static int stli_getbrdstruct(stlibrd_t __user *arg)
static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
{
- stlibrd_t *brdp;
+ struct stlibrd *brdp;
int brdnr, rc, done;
void __user *argp = (void __user *)arg;
@@ -4665,46 +4552,53 @@ static const struct tty_operations stli_ops = {
};
/*****************************************************************************/
+/*
+ * Loadable module initialization stuff.
+ */
+
+static void istallion_cleanup_isa(void)
+{
+ struct stlibrd *brdp;
+ unsigned int j;
+
+ for (j = 0; (j < stli_nrbrds); j++) {
+ if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED))
+ continue;
+
+ stli_cleanup_ports(brdp);
-static int __init stli_init(void)
+ iounmap(brdp->membase);
+ if (brdp->iosize > 0)
+ release_region(brdp->iobase, brdp->iosize);
+ kfree(brdp);
+ stli_brds[j] = NULL;
+ }
+}
+
+static int __init istallion_module_init(void)
{
- int i;
+ unsigned int i;
+ int retval;
+
printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
spin_lock_init(&stli_lock);
spin_lock_init(&brd_lock);
- stli_initbrds();
-
- stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
- if (!stli_serial)
- return -ENOMEM;
-
-/*
- * Allocate a temporary write buffer.
- */
stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
- if (!stli_txcookbuf)
+ if (!stli_txcookbuf) {
printk(KERN_ERR "STALLION: failed to allocate memory "
"(size=%d)\n", STLI_TXBUFSIZE);
+ retval = -ENOMEM;
+ goto err;
+ }
-/*
- * Set up a character driver for the shared memory region. We need this
- * to down load the slave code image. Also it is a useful debugging tool.
- */
- if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
- printk(KERN_ERR "STALLION: failed to register serial memory "
- "device\n");
-
- istallion_class = class_create(THIS_MODULE, "staliomem");
- for (i = 0; i < 4; i++)
- class_device_create(istallion_class, NULL,
- MKDEV(STL_SIOMEMMAJOR, i),
- NULL, "staliomem%d", i);
+ stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+ if (!stli_serial) {
+ retval = -ENOMEM;
+ goto err_free;
+ }
-/*
- * Set up the tty driver structure and register us as a driver.
- */
stli_serial->owner = THIS_MODULE;
stli_serial->driver_name = stli_drvname;
stli_serial->name = stli_serialname;
@@ -4713,15 +4607,79 @@ static int __init stli_init(void)
stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
stli_serial->subtype = SERIAL_TYPE_NORMAL;
stli_serial->init_termios = stli_deftermios;
- stli_serial->flags = TTY_DRIVER_REAL_RAW;
+ stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_set_operations(stli_serial, &stli_ops);
- if (tty_register_driver(stli_serial)) {
- put_tty_driver(stli_serial);
+ retval = tty_register_driver(stli_serial);
+ if (retval) {
printk(KERN_ERR "STALLION: failed to register serial driver\n");
- return -EBUSY;
+ goto err_ttyput;
}
+
+ retval = stli_initbrds();
+ if (retval)
+ goto err_ttyunr;
+
+/*
+ * Set up a character driver for the shared memory region. We need this
+ * to down load the slave code image. Also it is a useful debugging tool.
+ */
+ retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
+ if (retval) {
+ printk(KERN_ERR "STALLION: failed to register serial memory "
+ "device\n");
+ goto err_deinit;
+ }
+
+ istallion_class = class_create(THIS_MODULE, "staliomem");
+ for (i = 0; i < 4; i++)
+ class_device_create(istallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
+
return 0;
+err_deinit:
+ pci_unregister_driver(&stli_pcidriver);
+ istallion_cleanup_isa();
+err_ttyunr:
+ tty_unregister_driver(stli_serial);
+err_ttyput:
+ put_tty_driver(stli_serial);
+err_free:
+ kfree(stli_txcookbuf);
+err:
+ return retval;
}
/*****************************************************************************/
+
+static void __exit istallion_module_exit(void)
+{
+ unsigned int j;
+
+ printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
+ stli_drvversion);
+
+ if (stli_timeron) {
+ stli_timeron = 0;
+ del_timer_sync(&stli_timerlist);
+ }
+
+ unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+
+ for (j = 0; j < 4; j++)
+ class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR,
+ j));
+ class_destroy(istallion_class);
+
+ pci_unregister_driver(&stli_pcidriver);
+ istallion_cleanup_isa();
+
+ tty_unregister_driver(stli_serial);
+ put_tty_driver(stli_serial);
+
+ kfree(stli_txcookbuf);
+}
+
+module_init(istallion_module_init);
+module_exit(istallion_module_exit);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 20b6c8b3024..7a6c1c0b7a9 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -710,7 +710,7 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
{
- static const char *cur_chars = "BDCA";
+ static const char cur_chars[] = "BDCA";
if (up_flag)
return;
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index da601fd6c07..d649abbf085 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -459,7 +459,7 @@ static int lcd_ioctl(struct inode *inode, struct file *file,
(&display, (struct lcd_display *) arg,
sizeof(struct lcd_display)))
return -EFAULT;
- rom = (unsigned char *) kmalloc((128), GFP_ATOMIC);
+ rom = kmalloc((128), GFP_ATOMIC);
if (rom == NULL) {
printk(KERN_ERR LCD "kmalloc() failed in %s\n",
__FUNCTION__);
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 1ecea7d448f..b51d08be0bc 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -296,7 +296,7 @@ static int lp_wait_ready(int minor, int nonblock)
static ssize_t lp_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
- unsigned int minor = iminor(file->f_dentry->d_inode);
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
struct parport *port = lp_table[minor].dev->port;
char *kbuf = lp_table[minor].lp_buffer;
ssize_t retv = 0;
@@ -415,7 +415,7 @@ 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);
+ unsigned int minor=iminor(file->f_path.dentry->d_inode);
struct parport *port = lp_table[minor].dev->port;
ssize_t retval = 0;
char *kbuf = lp_table[minor].lp_buffer;
@@ -525,7 +525,7 @@ static int lp_open(struct inode * inode, struct file * file)
return -EIO;
}
}
- lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
+ lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
if (!lp_table[minor].lp_buffer) {
LP_F(minor) &= ~LP_BUSY;
return -ENOMEM;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index e67eef4867b..f5c160caf9f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -293,8 +293,8 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
{
unsigned long pfn;
- /* Turn a pfn offset into an absolute pfn */
- pfn = PFN_DOWN(virt_to_phys((void *)PAGE_OFFSET)) + vma->vm_pgoff;
+ /* Turn a kernel-virtual address into a physical page frame */
+ pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
/*
* RED-PEN: on some architectures there is more mapped memory
@@ -646,7 +646,8 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size)
count = size;
zap_page_range(vma, addr, count, NULL);
- zeromap_page_range(vma, addr, count, PAGE_COPY);
+ if (zeromap_page_range(vma, addr, count, PAGE_COPY))
+ break;
size -= count;
buf += count;
@@ -713,11 +714,14 @@ out:
static int mmap_zero(struct file * file, struct vm_area_struct * vma)
{
+ int err;
+
if (vma->vm_flags & VM_SHARED)
return shmem_zero_setup(vma);
- if (zeromap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
- return -EAGAIN;
- return 0;
+ err = zeromap_page_range(vma, vma->vm_start,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ BUG_ON(err == -EEXIST);
+ return err;
}
#else /* CONFIG_MMU */
static ssize_t read_zero(struct file * file, char * buf,
@@ -774,7 +778,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
{
loff_t ret;
- mutex_lock(&file->f_dentry->d_inode->i_mutex);
+ mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
switch (orig) {
case 0:
file->f_pos = offset;
@@ -789,7 +793,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
default:
ret = -EINVAL;
}
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return ret;
}
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 8b316953173..f391a24a1b4 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -234,7 +234,7 @@ static void moxa_put_char(struct tty_struct *, unsigned char);
static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
static void moxa_throttle(struct tty_struct *);
static void moxa_unthrottle(struct tty_struct *);
-static void moxa_set_termios(struct tty_struct *, struct termios *);
+static void moxa_set_termios(struct tty_struct *, struct ktermios *);
static void moxa_stop(struct tty_struct *);
static void moxa_start(struct tty_struct *);
static void moxa_hangup(struct tty_struct *);
@@ -261,7 +261,7 @@ static void MoxaPortEnable(int);
static void MoxaPortDisable(int);
static long MoxaPortGetMaxBaud(int);
static long MoxaPortSetBaud(int, long);
-static int MoxaPortSetTermio(int, struct termios *, speed_t);
+static int MoxaPortSetTermio(int, struct ktermios *, speed_t);
static int MoxaPortGetLineOut(int, int *, int *);
static void MoxaPortLineCtrl(int, int, int);
static void MoxaPortFlowCtrl(int, int, int, int, int, int);
@@ -355,6 +355,8 @@ static int __init moxa_init(void)
moxaDriver->init_termios.c_oflag = 0;
moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
moxaDriver->init_termios.c_lflag = 0;
+ moxaDriver->init_termios.c_ispeed = 9600;
+ moxaDriver->init_termios.c_ospeed = 9600;
moxaDriver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(moxaDriver, &moxa_ops);
@@ -864,7 +866,7 @@ static void moxa_unthrottle(struct tty_struct *tty)
}
static void moxa_set_termios(struct tty_struct *tty,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
@@ -978,7 +980,7 @@ static void moxa_poll(unsigned long ignored)
static void set_tty_param(struct tty_struct *tty)
{
- register struct termios *ts;
+ register struct ktermios *ts;
struct moxa_str *ch;
int rts, cts, txflow, rxflow, xany;
@@ -1149,7 +1151,7 @@ static void shut_down(struct moxa_str *ch)
static void receive_data(struct moxa_str *ch)
{
struct tty_struct *tp;
- struct termios *ts;
+ struct ktermios *ts;
unsigned long flags;
ts = NULL;
@@ -1912,9 +1914,9 @@ int MoxaPortsOfCard(int cardno)
*
* Function 12: Configure the port.
* Syntax:
- * int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud);
+ * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
* int port : port number (0 - 127)
- * struct termios * termio : termio structure pointer
+ * struct ktermios * termio : termio structure pointer
* speed_t baud : baud rate
*
* return: -1 : this port is invalid or termio == NULL
@@ -2195,7 +2197,7 @@ long MoxaPortSetBaud(int port, long baud)
return (baud);
}
-int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud)
+int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
{
void __iomem *ofsAddr;
tcflag_t cflag;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 5ed2486b758..83f604b1929 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -328,8 +328,8 @@ struct mxser_struct {
int xmit_tail;
int xmit_cnt;
struct work_struct tqueue;
- struct termios normal_termios;
- struct termios callout_termios;
+ struct ktermios normal_termios;
+ struct ktermios callout_termios;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
wait_queue_head_t delta_msr_wait;
@@ -364,8 +364,8 @@ static int mxserBoardCAP[MXSER_BOARDS] = {
static struct tty_driver *mxvar_sdriver;
static struct mxser_struct mxvar_table[MXSER_PORTS];
static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];
-static struct termios *mxvar_termios[MXSER_PORTS + 1];
-static struct termios *mxvar_termios_locked[MXSER_PORTS + 1];
+static struct ktermios *mxvar_termios[MXSER_PORTS + 1];
+static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1];
static struct mxser_log mxvar_log;
static int mxvar_diagflag;
static unsigned char mxser_msr[MXSER_PORTS + 1];
@@ -402,7 +402,7 @@ static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
static int mxser_ioctl_special(unsigned int, void __user *);
static void mxser_throttle(struct tty_struct *);
static void mxser_unthrottle(struct tty_struct *);
-static void mxser_set_termios(struct tty_struct *, struct termios *);
+static void mxser_set_termios(struct tty_struct *, struct ktermios *);
static void mxser_stop(struct tty_struct *);
static void mxser_start(struct tty_struct *);
static void mxser_hangup(struct tty_struct *);
@@ -414,7 +414,7 @@ static void mxser_check_modem_status(struct mxser_struct *, int);
static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
static int mxser_startup(struct mxser_struct *);
static void mxser_shutdown(struct mxser_struct *);
-static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
+static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios);
static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *);
static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *);
static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *);
@@ -515,6 +515,7 @@ static void __exit mxser_module_exit(void)
if (pdev != NULL) { /* PCI */
release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
+ pci_dev_put(pdev);
} else {
release_region(mxsercfg[i].ioaddr[0], 8 * mxsercfg[i].ports);
release_region(mxsercfg[i].vector, 1);
@@ -556,7 +557,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
n = board * MXSER_PORTS_PER_BOARD;
info = &mxvar_table[n];
/*if (verbose) */ {
- printk(KERN_DEBUG " ttyM%d - ttyM%d ",
+ printk(KERN_DEBUG " ttyMI%d - ttyMI%d ",
n, n + hwconf->ports - 1);
printk(" max. baud rate = %d bps.\n",
hwconf->MaxCanSetBaudRate[0]);
@@ -716,8 +717,9 @@ static int mxser_init(void)
/* Initialize the tty_driver structure */
memset(mxvar_sdriver, 0, sizeof(struct tty_driver));
+ mxvar_sdriver->owner = THIS_MODULE;
mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
- mxvar_sdriver->name = "ttyM";
+ mxvar_sdriver->name = "ttyMI";
mxvar_sdriver->major = ttymajor;
mxvar_sdriver->minor_start = 0;
mxvar_sdriver->num = MXSER_PORTS + 1;
@@ -725,6 +727,8 @@ static int mxser_init(void)
mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
mxvar_sdriver->init_termios = tty_std_termios;
mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+ mxvar_sdriver->init_termios.c_ispeed = 9600;
+ mxvar_sdriver->init_termios.c_ospeed = 9600;
mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(mxvar_sdriver, &mxser_ops);
mxvar_sdriver->ttys = mxvar_tty;
@@ -839,9 +843,9 @@ static int mxser_init(void)
index = 0;
b = 0;
while (b < n) {
- pdev = pci_find_device(mxser_pcibrds[b].vendor,
+ pdev = pci_get_device(mxser_pcibrds[b].vendor,
mxser_pcibrds[b].device, pdev);
- if (pdev == NULL) {
+ if (pdev == NULL) {
b++;
continue;
}
@@ -893,6 +897,9 @@ static int mxser_init(void)
if (mxser_initbrd(m, &hwconf) < 0)
continue;
m++;
+ /* Keep an extra reference if we succeeded. It will
+ be returned at unload time */
+ pci_dev_get(pdev);
}
}
#endif
@@ -994,7 +1001,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
mxser_change_speed(info, NULL);
}
- info->session = current->signal->session;
+ info->session = process_session(current);
info->pgrp = process_group(current);
/*
@@ -1745,7 +1752,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
/* MX_UNLOCK(&info->slock); */
}
-static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct mxser_struct *info = tty->driver_data;
unsigned long flags;
@@ -2537,7 +2544,7 @@ static void mxser_shutdown(struct mxser_struct *info)
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static int mxser_change_speed(struct mxser_struct *info, struct termios *old_termios)
+static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_termios)
{
unsigned cflag, cval, fcr;
int ret = 0;
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
new file mode 100644
index 00000000000..1bb030b3a51
--- /dev/null
+++ b/drivers/char/mxser_new.c
@@ -0,0 +1,2813 @@
+/*
+ * mxser.c -- MOXA Smartio/Industio family multiport serial driver.
+ *
+ * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com.tw).
+ * Copyright (C) 2006 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * This code is loosely based on the 1.8 moxa driver which is based on
+ * Linux serial driver, written by Linus Torvalds, Theodore T'so and
+ * others.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
+ * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com.
+ * - Fixed x86_64 cleanness
+ * - Fixed sleep with spinlock held in mxser_send_break
+ */
+
+#include <linux/module.h>
+#include <linux/autoconf.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/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/gfp.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#include "mxser_new.h"
+
+#define MXSER_VERSION "2.0"
+#define MXSERMAJOR 174
+#define MXSERCUMAJOR 175
+
+#define MXSER_EVENT_TXLOW 1
+
+#define MXSER_BOARDS 4 /* Max. boards */
+#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */
+#define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
+#define MXSER_ISR_PASS_LIMIT 99999L
+
+#define MXSER_ERR_IOADDR -1
+#define MXSER_ERR_IRQ -2
+#define MXSER_ERR_IRQ_CONFLIT -3
+#define MXSER_ERR_VECTOR -4
+
+#define WAKEUP_CHARS 256
+
+#define UART_MCR_AFE 0x20
+#define UART_LSR_SPECIAL 0x1E
+
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
+ IXON|IXOFF))
+
+#define C168_ASIC_ID 1
+#define C104_ASIC_ID 2
+#define C102_ASIC_ID 0xB
+#define CI132_ASIC_ID 4
+#define CI134_ASIC_ID 3
+#define CI104J_ASIC_ID 5
+
+#define MXSER_HIGHBAUD 1
+#define MXSER_HAS2 2
+
+/* This is only for PCI */
+static const struct {
+ int type;
+ int tx_fifo;
+ int rx_fifo;
+ int xmit_fifo_size;
+ int rx_high_water;
+ int rx_trigger;
+ int rx_low_water;
+ long max_baud;
+} Gpci_uart_info[] = {
+ {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}
+};
+#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info)
+
+struct mxser_cardinfo {
+ unsigned int nports;
+ char *name;
+ unsigned int flags;
+};
+
+static const struct mxser_cardinfo mxser_cards[] = {
+ { 8, "C168 series", }, /* C168-ISA */
+ { 4, "C104 series", }, /* C104-ISA */
+ { 4, "CI-104J series", }, /* CI104J */
+ { 8, "C168H/PCI series", }, /* C168-PCI */
+ { 4, "C104H/PCI series", }, /* C104-PCI */
+ { 4, "C102 series", MXSER_HAS2 }, /* C102-ISA */
+ { 4, "CI-132 series", MXSER_HAS2 }, /* CI132 */
+ { 4, "CI-134 series", }, /* CI134 */
+ { 2, "CP-132 series", }, /* CP132 */
+ { 4, "CP-114 series", }, /* CP114 */
+ { 4, "CT-114 series", }, /* CT114 */
+ { 2, "CP-102 series", MXSER_HIGHBAUD }, /* CP102 */
+ { 4, "CP-104U series", }, /* CP104U */
+ { 8, "CP-168U series", }, /* CP168U */
+ { 2, "CP-132U series", }, /* CP132U */
+ { 4, "CP-134U series", }, /* CP134U */
+ { 4, "CP-104JU series", }, /* CP104JU */
+ { 8, "Moxa UC7000 Serial", }, /* RC7000 */
+ { 8, "CP-118U series", }, /* CP118U */
+ { 2, "CP-102UL series", }, /* CP102UL */
+ { 2, "CP-102U series", }, /* CP102U */
+ { 8, "CP-118EL series", }, /* CP118EL */
+ { 8, "CP-168EL series", }, /* CP168EL */
+ { 4, "CP-104EL series", } /* CP104EL */
+};
+
+/* driver_data correspond to the lines in the structure above
+ see also ISA probe function before you change something */
+static struct pci_device_id mxser_pcibrds[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168),
+ .driver_data = 3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104),
+ .driver_data = 4 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132),
+ .driver_data = 8 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114),
+ .driver_data = 9 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114),
+ .driver_data = 10 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102),
+ .driver_data = 11 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U),
+ .driver_data = 12 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U),
+ .driver_data = 13 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U),
+ .driver_data = 14 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U),
+ .driver_data = 15 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU),
+ .driver_data = 16 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000),
+ .driver_data = 17 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U),
+ .driver_data = 18 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL),
+ .driver_data = 19 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U),
+ .driver_data = 20 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL),
+ .driver_data = 21 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL),
+ .driver_data = 22 },
+ { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL),
+ .driver_data = 23 },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
+
+static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
+static int ttymajor = MXSERMAJOR;
+static int calloutmajor = MXSERCUMAJOR;
+
+/* Variables for insmod */
+
+MODULE_AUTHOR("Casper Yang");
+MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
+module_param_array(ioaddr, int, NULL, 0);
+module_param(ttymajor, int, 0);
+MODULE_LICENSE("GPL");
+
+struct mxser_log {
+ int tick;
+ unsigned long rxcnt[MXSER_PORTS];
+ unsigned long txcnt[MXSER_PORTS];
+};
+
+
+struct mxser_mon {
+ unsigned long rxcnt;
+ unsigned long txcnt;
+ unsigned long up_rxcnt;
+ unsigned long up_txcnt;
+ int modem_status;
+ unsigned char hold_reason;
+};
+
+struct mxser_mon_ext {
+ unsigned long rx_cnt[32];
+ unsigned long tx_cnt[32];
+ unsigned long up_rxcnt[32];
+ unsigned long up_txcnt[32];
+ int modem_status[32];
+
+ long baudrate[32];
+ int databits[32];
+ int stopbits[32];
+ int parity[32];
+ int flowctrl[32];
+ int fifo[32];
+ int iftype[32];
+};
+
+struct mxser_board;
+
+struct mxser_port {
+ struct mxser_board *board;
+ struct tty_struct *tty;
+
+ unsigned long ioaddr;
+ unsigned long opmode_ioaddr;
+ int max_baud;
+
+ int rx_high_water;
+ int rx_trigger; /* Rx fifo trigger level */
+ int rx_low_water;
+ int baud_base; /* max. speed */
+ long realbaud;
+ int type; /* UART type */
+ int flags; /* defined in tty.h */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+
+ int x_char; /* xon/xoff character */
+ int IER; /* Interrupt Enable Register */
+ int MCR; /* Modem control register */
+
+ unsigned char stop_rx;
+ unsigned char ldisc_stop_rx;
+
+ int custom_divisor;
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned char err_shadow;
+ unsigned long event;
+
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ struct async_icount icount; /* kernel counters for 4 input interrupts */
+ int timeout;
+
+ int read_status_mask;
+ int ignore_status_mask;
+ int xmit_fifo_size;
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+
+ struct ktermios normal_termios;
+ struct ktermios callout_termios;
+
+ struct mxser_mon mon_data;
+
+ spinlock_t slock;
+ struct work_struct tqueue;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+ wait_queue_head_t delta_msr_wait;
+};
+
+struct mxser_board {
+ unsigned int idx;
+ int irq;
+ const struct mxser_cardinfo *info;
+ unsigned long vector;
+ unsigned long vector_mask;
+
+ int chip_flag;
+ int uart_type;
+
+ struct mxser_port ports[MXSER_PORTS_PER_BOARD];
+};
+
+struct mxser_mstatus {
+ tcflag_t cflag;
+ int cts;
+ int dsr;
+ int ri;
+ int dcd;
+};
+
+static struct mxser_mstatus GMStatus[MXSER_PORTS];
+
+static int mxserBoardCAP[MXSER_BOARDS] = {
+ 0, 0, 0, 0
+ /* 0x180, 0x280, 0x200, 0x320 */
+};
+
+static struct mxser_board mxser_boards[MXSER_BOARDS];
+static struct tty_driver *mxvar_sdriver;
+static struct mxser_log mxvar_log;
+static int mxvar_diagflag;
+static unsigned char mxser_msr[MXSER_PORTS + 1];
+static struct mxser_mon_ext mon_data_ext;
+static int mxser_set_baud_method[MXSER_PORTS + 1];
+static spinlock_t gm_lock;
+
+#ifdef CONFIG_PCI
+static int CheckIsMoxaMust(int io)
+{
+ u8 oldmcr, hwid;
+ int i;
+
+ outb(0, io + UART_LCR);
+ DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
+ oldmcr = inb(io + UART_MCR);
+ outb(0, io + UART_MCR);
+ SET_MOXA_MUST_XON1_VALUE(io, 0x11);
+ if ((hwid = inb(io + UART_MCR)) != 0) {
+ outb(oldmcr, io + UART_MCR);
+ return MOXA_OTHER_UART;
+ }
+
+ GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
+ for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
+ if (hwid == Gpci_uart_info[i].type)
+ return (int)hwid;
+ }
+ return MOXA_OTHER_UART;
+}
+#endif
+
+static void process_txrx_fifo(struct mxser_port *info)
+{
+ int i;
+
+ if ((info->type == PORT_16450) || (info->type == PORT_8250)) {
+ info->rx_trigger = 1;
+ info->rx_high_water = 1;
+ info->rx_low_water = 1;
+ info->xmit_fifo_size = 1;
+ } else
+ for (i = 0; i < UART_INFO_NUM; i++)
+ if (info->board->chip_flag == Gpci_uart_info[i].type) {
+ info->rx_trigger = Gpci_uart_info[i].rx_trigger;
+ info->rx_low_water = Gpci_uart_info[i].rx_low_water;
+ info->rx_high_water = Gpci_uart_info[i].rx_high_water;
+ info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;
+ break;
+ }
+}
+
+static void mxser_do_softint(struct work_struct *work)
+{
+ struct mxser_port *info = container_of(work, struct mxser_port, tqueue);
+ struct tty_struct *tty = info->tty;
+
+ if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event))
+ tty_wakeup(tty);
+}
+
+static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
+{
+ unsigned char status = 0;
+
+ status = inb(baseaddr + UART_MSR);
+
+ mxser_msr[port] &= 0x0F;
+ mxser_msr[port] |= status;
+ status = mxser_msr[port];
+ if (mode)
+ mxser_msr[port] = 0;
+
+ return status;
+}
+
+static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct mxser_port *port)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+ int do_clocal = 0;
+ unsigned long flags;
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ test_bit(TTY_IO_ERROR, &tty->flags)) {
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+
+ /*
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, port->count is dropped by one, so that
+ * mxser_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+ add_wait_queue(&port->open_wait, &wait);
+
+ spin_lock_irqsave(&port->slock, flags);
+ if (!tty_hung_up_p(filp))
+ port->count--;
+ spin_unlock_irqrestore(&port->slock, flags);
+ port->blocked_open++;
+ while (1) {
+ spin_lock_irqsave(&port->slock, flags);
+ outb(inb(port->ioaddr + UART_MCR) |
+ UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR);
+ spin_unlock_irqrestore(&port->slock, flags);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!(port->flags & ASYNC_CLOSING) &&
+ (do_clocal ||
+ (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&port->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ port->count++;
+ port->blocked_open--;
+ if (retval)
+ return retval;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+}
+
+static int mxser_set_baud(struct mxser_port *info, long newspd)
+{
+ int quot = 0;
+ unsigned char cval;
+ int ret = 0;
+ unsigned long flags;
+
+ if (!info->tty || !info->tty->termios)
+ return ret;
+
+ if (!(info->ioaddr))
+ return ret;
+
+ if (newspd > info->max_baud)
+ return 0;
+
+ info->realbaud = newspd;
+ if (newspd == 134) {
+ quot = (2 * info->baud_base / 269);
+ } else if (newspd) {
+ quot = info->baud_base / newspd;
+ if (quot == 0)
+ quot = 1;
+ } else {
+ quot = 0;
+ }
+
+ info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
+ info->timeout += HZ / 50; /* Add .02 seconds of slop */
+
+ if (quot) {
+ spin_lock_irqsave(&info->slock, flags);
+ info->MCR |= UART_MCR_DTR;
+ outb(info->MCR, info->ioaddr + UART_MCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+ } else {
+ spin_lock_irqsave(&info->slock, flags);
+ info->MCR &= ~UART_MCR_DTR;
+ outb(info->MCR, info->ioaddr + UART_MCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+ return ret;
+ }
+
+ cval = inb(info->ioaddr + UART_LCR);
+
+ outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */
+
+ outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */
+ outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
+ outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
+
+
+ return ret;
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static int mxser_change_speed(struct mxser_port *info,
+ struct ktermios *old_termios)
+{
+ unsigned cflag, cval, fcr;
+ int ret = 0;
+ unsigned char status;
+ long baud;
+ unsigned long flags;
+
+ if (!info->tty || !info->tty->termios)
+ return ret;
+ cflag = info->tty->termios->c_cflag;
+ if (!(info->ioaddr))
+ return ret;
+
+ if (mxser_set_baud_method[info->tty->index] == 0) {
+ baud = tty_get_baud_rate(info->tty);
+ mxser_set_baud(info, baud);
+ }
+
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5:
+ cval = 0x00;
+ break;
+ case CS6:
+ cval = 0x01;
+ break;
+ case CS7:
+ cval = 0x02;
+ break;
+ case CS8:
+ cval = 0x03;
+ break;
+ default:
+ cval = 0x00;
+ break; /* too keep GCC shut... */
+ }
+ if (cflag & CSTOPB)
+ cval |= 0x04;
+ if (cflag & PARENB)
+ cval |= UART_LCR_PARITY;
+ if (!(cflag & PARODD))
+ cval |= UART_LCR_EPAR;
+ if (cflag & CMSPAR)
+ cval |= UART_LCR_SPAR;
+
+ if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
+ if (info->board->chip_flag) {
+ fcr = UART_FCR_ENABLE_FIFO;
+ fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+ SET_MOXA_MUST_FIFO_VALUE(info);
+ } else
+ fcr = 0;
+ } else {
+ fcr = UART_FCR_ENABLE_FIFO;
+ if (info->board->chip_flag) {
+ fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+ SET_MOXA_MUST_FIFO_VALUE(info);
+ } else {
+ switch (info->rx_trigger) {
+ case 1:
+ fcr |= UART_FCR_TRIGGER_1;
+ break;
+ case 4:
+ fcr |= UART_FCR_TRIGGER_4;
+ break;
+ case 8:
+ fcr |= UART_FCR_TRIGGER_8;
+ break;
+ default:
+ fcr |= UART_FCR_TRIGGER_14;
+ break;
+ }
+ }
+ }
+
+ /* CTS flow control flag and modem status interrupts */
+ info->IER &= ~UART_IER_MSI;
+ info->MCR &= ~UART_MCR_AFE;
+ if (cflag & CRTSCTS) {
+ info->flags |= ASYNC_CTS_FLOW;
+ info->IER |= UART_IER_MSI;
+ if ((info->type == PORT_16550A) || (info->board->chip_flag)) {
+ info->MCR |= UART_MCR_AFE;
+ } else {
+ status = inb(info->ioaddr + UART_MSR);
+ if (info->tty->hw_stopped) {
+ if (status & UART_MSR_CTS) {
+ info->tty->hw_stopped = 0;
+ if (info->type != PORT_16550A &&
+ !info->board->chip_flag) {
+ outb(info->IER & ~UART_IER_THRI,
+ info->ioaddr +
+ UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr +
+ UART_IER);
+ }
+ set_bit(MXSER_EVENT_TXLOW, &info->event);
+ schedule_work(&info->tqueue); }
+ } else {
+ if (!(status & UART_MSR_CTS)) {
+ info->tty->hw_stopped = 1;
+ if ((info->type != PORT_16550A) &&
+ (!info->board->chip_flag)) {
+ info->IER &= ~UART_IER_THRI;
+ outb(info->IER, info->ioaddr +
+ UART_IER);
+ }
+ }
+ }
+ }
+ } else {
+ info->flags &= ~ASYNC_CTS_FLOW;
+ }
+ outb(info->MCR, info->ioaddr + UART_MCR);
+ if (cflag & CLOCAL) {
+ info->flags &= ~ASYNC_CHECK_CD;
+ } else {
+ info->flags |= ASYNC_CHECK_CD;
+ info->IER |= UART_IER_MSI;
+ }
+ outb(info->IER, info->ioaddr + UART_IER);
+
+ /*
+ * Set up parity check flag
+ */
+ info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (I_INPCK(info->tty))
+ info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= UART_LSR_BI;
+
+ info->ignore_status_mask = 0;
+
+ if (I_IGNBRK(info->tty)) {
+ info->ignore_status_mask |= UART_LSR_BI;
+ info->read_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignore parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (I_IGNPAR(info->tty)) {
+ info->ignore_status_mask |=
+ UART_LSR_OE |
+ UART_LSR_PE |
+ UART_LSR_FE;
+ info->read_status_mask |=
+ UART_LSR_OE |
+ UART_LSR_PE |
+ UART_LSR_FE;
+ }
+ }
+ if (info->board->chip_flag) {
+ spin_lock_irqsave(&info->slock, flags);
+ SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
+ SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
+ if (I_IXON(info->tty)) {
+ ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+ } else {
+ DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+ }
+ if (I_IXOFF(info->tty)) {
+ ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+ } else {
+ DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+ }
+ spin_unlock_irqrestore(&info->slock, flags);
+ }
+
+
+ outb(fcr, info->ioaddr + UART_FCR); /* set fcr */
+ outb(cval, info->ioaddr + UART_LCR);
+
+ return ret;
+}
+
+static void mxser_check_modem_status(struct mxser_port *port, int status)
+{
+ /* update input line counters */
+ if (status & UART_MSR_TERI)
+ port->icount.rng++;
+ if (status & UART_MSR_DDSR)
+ port->icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ port->icount.dcd++;
+ if (status & UART_MSR_DCTS)
+ port->icount.cts++;
+ port->mon_data.modem_status = status;
+ wake_up_interruptible(&port->delta_msr_wait);
+
+ if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+ if (status & UART_MSR_DCD)
+ wake_up_interruptible(&port->open_wait);
+ schedule_work(&port->tqueue);
+ }
+
+ if (port->flags & ASYNC_CTS_FLOW) {
+ if (port->tty->hw_stopped) {
+ if (status & UART_MSR_CTS) {
+ port->tty->hw_stopped = 0;
+
+ if ((port->type != PORT_16550A) &&
+ (!port->board->chip_flag)) {
+ outb(port->IER & ~UART_IER_THRI,
+ port->ioaddr + UART_IER);
+ port->IER |= UART_IER_THRI;
+ outb(port->IER, port->ioaddr +
+ UART_IER);
+ }
+ set_bit(MXSER_EVENT_TXLOW, &port->event);
+ schedule_work(&port->tqueue);
+ }
+ } else {
+ if (!(status & UART_MSR_CTS)) {
+ port->tty->hw_stopped = 1;
+ if (port->type != PORT_16550A &&
+ !port->board->chip_flag) {
+ port->IER &= ~UART_IER_THRI;
+ outb(port->IER, port->ioaddr +
+ UART_IER);
+ }
+ }
+ }
+ }
+}
+
+static int mxser_startup(struct mxser_port *info)
+{
+ unsigned long page;
+ unsigned long flags;
+
+ page = __get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&info->slock, flags);
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ free_page(page);
+ spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
+ }
+
+ if (!info->ioaddr || !info->type) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ free_page(page);
+ spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
+ }
+ if (info->xmit_buf)
+ free_page(page);
+ else
+ info->xmit_buf = (unsigned char *) page;
+
+ /*
+ * Clear the FIFO buffers and disable them
+ * (they will be reenabled in mxser_change_speed())
+ */
+ if (info->board->chip_flag)
+ outb((UART_FCR_CLEAR_RCVR |
+ UART_FCR_CLEAR_XMIT |
+ MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
+ else
+ outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+ info->ioaddr + UART_FCR);
+
+ /*
+ * At this point there's no way the LSR could still be 0xFF;
+ * if it is, then bail out, because there's likely no UART
+ * here.
+ */
+ if (inb(info->ioaddr + UART_LSR) == 0xff) {
+ spin_unlock_irqrestore(&info->slock, flags);
+ if (capable(CAP_SYS_ADMIN)) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ return 0;
+ } else
+ return -ENODEV;
+ }
+
+ /*
+ * Clear the interrupt registers.
+ */
+ (void) inb(info->ioaddr + UART_LSR);
+ (void) inb(info->ioaddr + UART_RX);
+ (void) inb(info->ioaddr + UART_IIR);
+ (void) inb(info->ioaddr + UART_MSR);
+
+ /*
+ * Now, initialize the UART
+ */
+ outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */
+ info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+ outb(info->MCR, info->ioaddr + UART_MCR);
+
+ /*
+ * Finally, enable interrupts
+ */
+ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+
+ if (info->board->chip_flag)
+ info->IER |= MOXA_MUST_IER_EGDAI;
+ outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */
+
+ /*
+ * And clear the interrupt registers again for luck.
+ */
+ (void) inb(info->ioaddr + UART_LSR);
+ (void) inb(info->ioaddr + UART_RX);
+ (void) inb(info->ioaddr + UART_IIR);
+ (void) inb(info->ioaddr + UART_MSR);
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+ /*
+ * and set the speed of the serial port
+ */
+ spin_unlock_irqrestore(&info->slock, flags);
+ mxser_change_speed(info, NULL);
+
+ info->flags |= ASYNC_INITIALIZED;
+ return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts maybe disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void mxser_shutdown(struct mxser_port *info)
+{
+ unsigned long flags;
+
+ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+
+ spin_lock_irqsave(&info->slock, flags);
+
+ /*
+ * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+ * here so the queue might never be waken up
+ */
+ wake_up_interruptible(&info->delta_msr_wait);
+
+ /*
+ * Free the IRQ, if necessary
+ */
+ if (info->xmit_buf) {
+ free_page((unsigned long) info->xmit_buf);
+ info->xmit_buf = NULL;
+ }
+
+ info->IER = 0;
+ outb(0x00, info->ioaddr + UART_IER);
+
+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+ info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
+ outb(info->MCR, info->ioaddr + UART_MCR);
+
+ /* clear Rx/Tx FIFO's */
+ if (info->board->chip_flag)
+ outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
+ MOXA_MUST_FCR_GDA_MODE_ENABLE,
+ info->ioaddr + UART_FCR);
+ else
+ outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+ info->ioaddr + UART_FCR);
+
+ /* read data port to reset things */
+ (void) inb(info->ioaddr + UART_RX);
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ASYNC_INITIALIZED;
+
+ if (info->board->chip_flag)
+ SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int mxser_open(struct tty_struct *tty, struct file *filp)
+{
+ struct mxser_port *info;
+ int retval, line;
+
+ /* initialize driver_data in case something fails */
+ tty->driver_data = NULL;
+
+ line = tty->index;
+ if (line == MXSER_PORTS)
+ return 0;
+ if (line < 0 || line > MXSER_PORTS)
+ return -ENODEV;
+ info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD];
+ if (!info->ioaddr)
+ return -ENODEV;
+
+ tty->driver_data = info;
+ info->tty = tty;
+ /*
+ * Start up serial port
+ */
+ info->count++;
+ retval = mxser_startup(info);
+ if (retval)
+ return retval;
+
+ retval = mxser_block_til_ready(tty, filp, info);
+ if (retval)
+ return retval;
+
+ if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver->subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = info->normal_termios;
+ else
+ *tty->termios = info->callout_termios;
+ mxser_change_speed(info, NULL);
+ }
+
+ info->session = process_session(current);
+ info->pgrp = process_group(current);
+
+ /* unmark here for very high baud rate (ex. 921600 bps) used */
+ tty->low_latency = 1;
+ return 0;
+}
+
+/*
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ */
+static void mxser_close(struct tty_struct *tty, struct file *filp)
+{
+ struct mxser_port *info = tty->driver_data;
+
+ unsigned long timeout;
+ unsigned long flags;
+
+ if (tty->index == MXSER_PORTS)
+ return;
+ if (!info)
+ return;
+
+ spin_lock_irqsave(&info->slock, flags);
+
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&info->slock, flags);
+ return;
+ }
+ 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(KERN_ERR "mxser_close: bad serial port count; "
+ "tty->count is 1, info->count is %d\n", info->count);
+ info->count = 1;
+ }
+ if (--info->count < 0) {
+ printk(KERN_ERR "mxser_close: bad serial port count for "
+ "ttys%d: %d\n", tty->index, info->count);
+ info->count = 0;
+ }
+ if (info->count) {
+ spin_unlock_irqrestore(&info->slock, flags);
+ return;
+ }
+ info->flags |= ASYNC_CLOSING;
+ spin_unlock_irqrestore(&info->slock, flags);
+ /*
+ * Save the termios structure, since this port may have
+ * separate termios for callout and dialin.
+ */
+ if (info->flags & ASYNC_NORMAL_ACTIVE)
+ info->normal_termios = *tty->termios;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->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.
+ */
+ info->IER &= ~UART_IER_RLSI;
+ if (info->board->chip_flag)
+ info->IER &= ~MOXA_MUST_RECV_ISR;
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ outb(info->IER, info->ioaddr + UART_IER);
+ /*
+ * Before we drop DTR, make sure the UART transmitter
+ * has completely drained; this is especially
+ * important if there is a transmit FIFO!
+ */
+ timeout = jiffies + HZ;
+ while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
+ schedule_timeout_interruptible(5);
+ if (time_after(jiffies, timeout))
+ break;
+ }
+ }
+ mxser_shutdown(info);
+
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = NULL;
+ if (info->blocked_open) {
+ if (info->close_delay)
+ schedule_timeout_interruptible(info->close_delay);
+ wake_up_interruptible(&info->open_wait);
+ }
+
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+
+}
+
+static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+ int c, total = 0;
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ if (!info->xmit_buf)
+ return 0;
+
+ while (1) {
+ c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;
+
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ spin_lock_irqsave(&info->slock, flags);
+ info->xmit_head = (info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE - 1);
+ info->xmit_cnt += c;
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ buf += c;
+ count -= c;
+ total += c;
+ }
+
+ if (info->xmit_cnt && !tty->stopped) {
+ if (!tty->hw_stopped ||
+ (info->type == PORT_16550A) ||
+ (info->board->chip_flag)) {
+ spin_lock_irqsave(&info->slock, flags);
+ outb(info->IER & ~UART_IER_THRI, info->ioaddr +
+ UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+ spin_unlock_irqrestore(&info->slock, flags);
+ }
+ }
+ return total;
+}
+
+static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ if (!info->xmit_buf)
+ return;
+
+ if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
+ return;
+
+ spin_lock_irqsave(&info->slock, flags);
+ info->xmit_buf[info->xmit_head++] = ch;
+ info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+ info->xmit_cnt++;
+ spin_unlock_irqrestore(&info->slock, flags);
+ if (!tty->stopped) {
+ if (!tty->hw_stopped ||
+ (info->type == PORT_16550A) ||
+ info->board->chip_flag) {
+ spin_lock_irqsave(&info->slock, flags);
+ outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+ spin_unlock_irqrestore(&info->slock, flags);
+ }
+ }
+}
+
+
+static void mxser_flush_chars(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ if (info->xmit_cnt <= 0 ||
+ tty->stopped ||
+ !info->xmit_buf ||
+ (tty->hw_stopped &&
+ (info->type != PORT_16550A) &&
+ (!info->board->chip_flag)
+ ))
+ return;
+
+ spin_lock_irqsave(&info->slock, flags);
+
+ outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static int mxser_write_room(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+ int ret;
+
+ ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+static int mxser_chars_in_buffer(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+ return info->xmit_cnt;
+}
+
+static void mxser_flush_buffer(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+ char fcr;
+ unsigned long flags;
+
+
+ spin_lock_irqsave(&info->slock, flags);
+ info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+ fcr = inb(info->ioaddr + UART_FCR);
+ outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+ info->ioaddr + UART_FCR);
+ outb(fcr, info->ioaddr + UART_FCR);
+
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ tty_wakeup(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * friends of mxser_ioctl()
+ * ------------------------------------------------------------
+ */
+static int mxser_get_serial_info(struct mxser_port *info,
+ struct serial_struct __user *retinfo)
+{
+ struct serial_struct tmp;
+
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = info->type;
+ tmp.line = info->tty->index;
+ tmp.port = info->ioaddr;
+ tmp.irq = info->board->irq;
+ tmp.flags = info->flags;
+ tmp.baud_base = info->baud_base;
+ tmp.close_delay = info->close_delay;
+ tmp.closing_wait = info->closing_wait;
+ tmp.custom_divisor = info->custom_divisor;
+ tmp.hub6 = 0;
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+static int mxser_set_serial_info(struct mxser_port *info,
+ struct serial_struct __user *new_info)
+{
+ struct serial_struct new_serial;
+ unsigned int flags;
+ int retval = 0;
+
+ if (!new_info || !info->ioaddr)
+ return -EFAULT;
+ if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+ return -EFAULT;
+
+ if ((new_serial.irq != info->board->irq) ||
+ (new_serial.port != info->ioaddr) ||
+ (new_serial.custom_divisor != info->custom_divisor) ||
+ (new_serial.baud_base != info->baud_base))
+ return -EPERM;
+
+ flags = info->flags & ASYNC_SPD_MASK;
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((new_serial.baud_base != info->baud_base) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
+ } else {
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+ info->flags = ((info->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS));
+ info->close_delay = new_serial.close_delay * HZ / 100;
+ info->closing_wait = new_serial.closing_wait * HZ / 100;
+ info->tty->low_latency =
+ (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ info->tty->low_latency = 0;
+ }
+
+ info->type = new_serial.type;
+
+ process_txrx_fifo(info);
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ if (flags != (info->flags & ASYNC_SPD_MASK))
+ mxser_change_speed(info, NULL);
+ } else
+ retval = mxser_startup(info);
+
+ return retval;
+}
+
+/*
+ * mxser_get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int mxser_get_lsr_info(struct mxser_port *info,
+ unsigned int __user *value)
+{
+ unsigned char status;
+ unsigned int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ status = inb(info->ioaddr + UART_LSR);
+ spin_unlock_irqrestore(&info->slock, flags);
+ result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+ return put_user(result, value);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void mxser_send_break(struct mxser_port *info, int duration)
+{
+ unsigned long flags;
+
+ if (!info->ioaddr)
+ return;
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_lock_irqsave(&info->slock, flags);
+ outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
+ info->ioaddr + UART_LCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+ schedule_timeout(duration);
+ spin_lock_irqsave(&info->slock, flags);
+ outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
+ info->ioaddr + UART_LCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned char control, status;
+ unsigned long flags;
+
+
+ if (tty->index == MXSER_PORTS)
+ return -ENOIOCTLCMD;
+ if (test_bit(TTY_IO_ERROR, &tty->flags))
+ return -EIO;
+
+ control = info->MCR;
+
+ spin_lock_irqsave(&info->slock, flags);
+ status = inb(info->ioaddr + UART_MSR);
+ if (status & UART_MSR_ANY_DELTA)
+ mxser_check_modem_status(info, status);
+ spin_unlock_irqrestore(&info->slock, flags);
+ return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
+ ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
+ ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+ ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
+ ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+ ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+}
+
+static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+
+ if (tty->index == MXSER_PORTS)
+ return -ENOIOCTLCMD;
+ if (test_bit(TTY_IO_ERROR, &tty->flags))
+ return -EIO;
+
+ spin_lock_irqsave(&info->slock, flags);
+
+ if (set & TIOCM_RTS)
+ info->MCR |= UART_MCR_RTS;
+ if (set & TIOCM_DTR)
+ info->MCR |= UART_MCR_DTR;
+
+ if (clear & TIOCM_RTS)
+ info->MCR &= ~UART_MCR_RTS;
+ if (clear & TIOCM_DTR)
+ info->MCR &= ~UART_MCR_DTR;
+
+ outb(info->MCR, info->ioaddr + UART_MCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
+}
+
+static int mxser_program_mode(int port)
+{
+ int id, i, j, n;
+
+ spin_lock(&gm_lock);
+ outb(0, port);
+ outb(0, port);
+ outb(0, port);
+ (void)inb(port);
+ (void)inb(port);
+ outb(0, port);
+ (void)inb(port);
+ spin_unlock(&gm_lock);
+
+ id = inb(port + 1) & 0x1F;
+ if ((id != C168_ASIC_ID) &&
+ (id != C104_ASIC_ID) &&
+ (id != C102_ASIC_ID) &&
+ (id != CI132_ASIC_ID) &&
+ (id != CI134_ASIC_ID) &&
+ (id != CI104J_ASIC_ID))
+ return -1;
+ for (i = 0, j = 0; i < 4; i++) {
+ n = inb(port + 2);
+ if (n == 'M') {
+ j = 1;
+ } else if ((j == 1) && (n == 1)) {
+ j = 2;
+ break;
+ } else
+ j = 0;
+ }
+ if (j != 2)
+ id = -2;
+ return id;
+}
+
+static void mxser_normal_mode(int port)
+{
+ int i, n;
+
+ outb(0xA5, port + 1);
+ outb(0x80, port + 3);
+ outb(12, port + 0); /* 9600 bps */
+ outb(0, port + 1);
+ outb(0x03, port + 3); /* 8 data bits */
+ outb(0x13, port + 4); /* loop back mode */
+ for (i = 0; i < 16; i++) {
+ n = inb(port + 5);
+ if ((n & 0x61) == 0x60)
+ break;
+ if ((n & 1) == 1)
+ (void)inb(port);
+ }
+ outb(0x00, port + 4);
+}
+
+#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */
+#define CHIP_DO 0x02 /* Serial Data Output in Eprom */
+#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */
+#define CHIP_DI 0x08 /* Serial Data Input in Eprom */
+#define EN_CCMD 0x000 /* Chip's command register */
+#define EN0_RSARLO 0x008 /* Remote start address reg 0 */
+#define EN0_RSARHI 0x009 /* Remote start address reg 1 */
+#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */
+#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */
+#define EN0_DCFG 0x00E /* Data configuration reg WR */
+#define EN0_PORT 0x010 /* Rcv missed frame error counter RD */
+#define ENC_PAGE0 0x000 /* Select page 0 of chip registers */
+#define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */
+static int mxser_read_register(int port, unsigned short *regs)
+{
+ int i, k, value, id;
+ unsigned int j;
+
+ id = mxser_program_mode(port);
+ if (id < 0)
+ return id;
+ for (i = 0; i < 14; i++) {
+ k = (i & 0x3F) | 0x180;
+ for (j = 0x100; j > 0; j >>= 1) {
+ outb(CHIP_CS, port);
+ if (k & j) {
+ outb(CHIP_CS | CHIP_DO, port);
+ outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */
+ } else {
+ outb(CHIP_CS, port);
+ outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */
+ }
+ }
+ (void)inb(port);
+ value = 0;
+ for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
+ outb(CHIP_CS, port);
+ outb(CHIP_CS | CHIP_SK, port);
+ if (inb(port) & CHIP_DI)
+ value |= j;
+ }
+ regs[i] = value;
+ outb(0, port);
+ }
+ mxser_normal_mode(port);
+ return id;
+}
+
+static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+{
+ struct mxser_port *port;
+ int result, status;
+ unsigned int i, j;
+
+ switch (cmd) {
+ case MOXA_GET_CONF:
+/* if (copy_to_user(argp, mxsercfg,
+ sizeof(struct mxser_hwconf) * 4))
+ return -EFAULT;
+ return 0;*/
+ return -ENXIO;
+ case MOXA_GET_MAJOR:
+ if (copy_to_user(argp, &ttymajor, sizeof(int)))
+ return -EFAULT;
+ return 0;
+
+ case MOXA_GET_CUMAJOR:
+ if (copy_to_user(argp, &calloutmajor, sizeof(int)))
+ return -EFAULT;
+ return 0;
+
+ case MOXA_CHKPORTENABLE:
+ result = 0;
+
+ for (i = 0; i < MXSER_BOARDS; i++)
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
+ if (mxser_boards[i].ports[j].ioaddr)
+ result |= (1 << i);
+
+ return put_user(result, (unsigned long __user *)argp);
+ case MOXA_GETDATACOUNT:
+ if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
+ return -EFAULT;
+ return 0;
+ case MOXA_GETMSTATUS:
+ for (i = 0; i < MXSER_BOARDS; i++)
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+ port = &mxser_boards[i].ports[j];
+
+ GMStatus[i].ri = 0;
+ if (!port->ioaddr) {
+ GMStatus[i].dcd = 0;
+ GMStatus[i].dsr = 0;
+ GMStatus[i].cts = 0;
+ continue;
+ }
+
+ if (!port->tty || !port->tty->termios)
+ GMStatus[i].cflag =
+ port->normal_termios.c_cflag;
+ else
+ GMStatus[i].cflag =
+ port->tty->termios->c_cflag;
+
+ status = inb(port->ioaddr + UART_MSR);
+ if (status & 0x80 /*UART_MSR_DCD */ )
+ GMStatus[i].dcd = 1;
+ else
+ GMStatus[i].dcd = 0;
+
+ if (status & 0x20 /*UART_MSR_DSR */ )
+ GMStatus[i].dsr = 1;
+ else
+ GMStatus[i].dsr = 0;
+
+
+ if (status & 0x10 /*UART_MSR_CTS */ )
+ GMStatus[i].cts = 1;
+ else
+ GMStatus[i].cts = 0;
+ }
+ if (copy_to_user(argp, GMStatus,
+ sizeof(struct mxser_mstatus) * MXSER_PORTS))
+ return -EFAULT;
+ return 0;
+ case MOXA_ASPP_MON_EXT: {
+ int status, p, shiftbit;
+ unsigned long opmode;
+ unsigned cflag, iflag;
+
+ for (i = 0; i < MXSER_BOARDS; i++)
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+ port = &mxser_boards[i].ports[j];
+ if (!port->ioaddr)
+ continue;
+
+ status = mxser_get_msr(port->ioaddr, 0, i);
+
+ if (status & UART_MSR_TERI)
+ port->icount.rng++;
+ if (status & UART_MSR_DDSR)
+ port->icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ port->icount.dcd++;
+ if (status & UART_MSR_DCTS)
+ port->icount.cts++;
+
+ port->mon_data.modem_status = status;
+ mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt;
+ mon_data_ext.tx_cnt[i] = port->mon_data.txcnt;
+ mon_data_ext.up_rxcnt[i] =
+ port->mon_data.up_rxcnt;
+ mon_data_ext.up_txcnt[i] =
+ port->mon_data.up_txcnt;
+ mon_data_ext.modem_status[i] =
+ port->mon_data.modem_status;
+ mon_data_ext.baudrate[i] = port->realbaud;
+
+ if (!port->tty || !port->tty->termios) {
+ cflag = port->normal_termios.c_cflag;
+ iflag = port->normal_termios.c_iflag;
+ } else {
+ cflag = port->tty->termios->c_cflag;
+ iflag = port->tty->termios->c_iflag;
+ }
+
+ mon_data_ext.databits[i] = cflag & CSIZE;
+
+ mon_data_ext.stopbits[i] = cflag & CSTOPB;
+
+ mon_data_ext.parity[i] =
+ cflag & (PARENB | PARODD | CMSPAR);
+
+ mon_data_ext.flowctrl[i] = 0x00;
+
+ if (cflag & CRTSCTS)
+ mon_data_ext.flowctrl[i] |= 0x03;
+
+ if (iflag & (IXON | IXOFF))
+ mon_data_ext.flowctrl[i] |= 0x0C;
+
+ if (port->type == PORT_16550A)
+ mon_data_ext.fifo[i] = 1;
+ else
+ mon_data_ext.fifo[i] = 0;
+
+ p = i % 4;
+ shiftbit = p * 2;
+ opmode = inb(port->opmode_ioaddr) >> shiftbit;
+ opmode &= OP_MODE_MASK;
+
+ mon_data_ext.iftype[i] = opmode;
+
+ }
+ if (copy_to_user(argp, &mon_data_ext,
+ sizeof(mon_data_ext)))
+ return -EFAULT;
+
+ return 0;
+
+ } default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct mxser_port *info = tty->driver_data;
+ struct async_icount cprev, cnow; /* kernel counter temps */
+ struct serial_icounter_struct __user *p_cuser;
+ unsigned long templ;
+ unsigned long flags;
+ void __user *argp = (void __user *)arg;
+ int retval;
+
+ if (tty->index == MXSER_PORTS)
+ return mxser_ioctl_special(cmd, argp);
+
+ if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
+ int p;
+ unsigned long opmode;
+ static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
+ int shiftbit;
+ unsigned char val, mask;
+
+ p = tty->index % 4;
+ if (cmd == MOXA_SET_OP_MODE) {
+ if (get_user(opmode, (int __user *) argp))
+ return -EFAULT;
+ if (opmode != RS232_MODE &&
+ opmode != RS485_2WIRE_MODE &&
+ opmode != RS422_MODE &&
+ opmode != RS485_4WIRE_MODE)
+ return -EFAULT;
+ mask = ModeMask[p];
+ shiftbit = p * 2;
+ val = inb(info->opmode_ioaddr);
+ val &= mask;
+ val |= (opmode << shiftbit);
+ outb(val, info->opmode_ioaddr);
+ } else {
+ shiftbit = p * 2;
+ opmode = inb(info->opmode_ioaddr) >> shiftbit;
+ opmode &= OP_MODE_MASK;
+ if (copy_to_user(argp, &opmode, sizeof(int)))
+ return -EFAULT;
+ }
+ return 0;
+ }
+
+ if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+ test_bit(TTY_IO_ERROR, &tty->flags))
+ return -EIO;
+
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+ mxser_send_break(info, HZ / 4); /* 1/4 second */
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
+ return 0;
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
+ case TIOCSSOFTCAR:
+ if (get_user(templ, (unsigned long __user *) argp))
+ return -EFAULT;
+ arg = templ;
+ tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+ return 0;
+ case TIOCGSERIAL:
+ return mxser_get_serial_info(info, argp);
+ case TIOCSSERIAL:
+ return mxser_set_serial_info(info, argp);
+ case TIOCSERGETLSR: /* Get line status register */
+ return mxser_get_lsr_info(info, argp);
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+ case TIOCMIWAIT: {
+ DECLARE_WAITQUEUE(wait, current);
+ int ret;
+ spin_lock_irqsave(&info->slock, flags);
+ cprev = info->icount; /* note the counters on entry */
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ add_wait_queue(&info->delta_msr_wait, &wait);
+ while (1) {
+ spin_lock_irqsave(&info->slock, flags);
+ cnow = info->icount; /* atomic copy */
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (((arg & TIOCM_RNG) &&
+ (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) &&
+ (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) &&
+ (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) &&
+ (cnow.cts != cprev.cts))) {
+ ret = 0;
+ break;
+ }
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ cprev = cnow;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->delta_msr_wait, &wait);
+ break;
+ }
+ /* NOTREACHED */
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+ case TIOCGICOUNT:
+ spin_lock_irqsave(&info->slock, flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->slock, flags);
+ p_cuser = argp;
+ if (put_user(cnow.frame, &p_cuser->frame))
+ return -EFAULT;
+ if (put_user(cnow.brk, &p_cuser->brk))
+ return -EFAULT;
+ if (put_user(cnow.overrun, &p_cuser->overrun))
+ return -EFAULT;
+ if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
+ return -EFAULT;
+ if (put_user(cnow.parity, &p_cuser->parity))
+ return -EFAULT;
+ if (put_user(cnow.rx, &p_cuser->rx))
+ return -EFAULT;
+ if (put_user(cnow.tx, &p_cuser->tx))
+ return -EFAULT;
+ put_user(cnow.cts, &p_cuser->cts);
+ put_user(cnow.dsr, &p_cuser->dsr);
+ put_user(cnow.rng, &p_cuser->rng);
+ put_user(cnow.dcd, &p_cuser->dcd);
+ return 0;
+ case MOXA_HighSpeedOn:
+ return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
+ case MOXA_SDS_RSTICOUNTER:
+ info->mon_data.rxcnt = 0;
+ info->mon_data.txcnt = 0;
+ return 0;
+ case MOXA_ASPP_SETBAUD:{
+ long baud;
+ if (get_user(baud, (long __user *)argp))
+ return -EFAULT;
+ mxser_set_baud(info, baud);
+ return 0;
+ }
+ case MOXA_ASPP_GETBAUD:
+ if (copy_to_user(argp, &info->realbaud, sizeof(long)))
+ return -EFAULT;
+
+ return 0;
+
+ case MOXA_ASPP_OQUEUE:{
+ int len, lsr;
+
+ len = mxser_chars_in_buffer(tty);
+
+ lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
+
+ len += (lsr ? 0 : 1);
+
+ if (copy_to_user(argp, &len, sizeof(int)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case MOXA_ASPP_MON: {
+ int mcr, status;
+
+ status = mxser_get_msr(info->ioaddr, 1, tty->index);
+ mxser_check_modem_status(info, status);
+
+ mcr = inb(info->ioaddr + UART_MCR);
+ if (mcr & MOXA_MUST_MCR_XON_FLAG)
+ info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
+ else
+ info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;
+
+ if (mcr & MOXA_MUST_MCR_TX_XON)
+ info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;
+ else
+ info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
+
+ if (info->tty->hw_stopped)
+ info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
+ else
+ info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
+
+ if (copy_to_user(argp, &info->mon_data,
+ sizeof(struct mxser_mon)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case MOXA_ASPP_LSTATUS: {
+ if (copy_to_user(argp, &info->err_shadow,
+ sizeof(unsigned char)))
+ return -EFAULT;
+
+ info->err_shadow = 0;
+ return 0;
+ }
+ case MOXA_SET_BAUD_METHOD: {
+ int method;
+
+ if (get_user(method, (int __user *)argp))
+ return -EFAULT;
+ mxser_set_baud_method[tty->index] = method;
+ if (copy_to_user(argp, &method, sizeof(int)))
+ return -EFAULT;
+
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static void mxser_stoprx(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+
+ info->ldisc_stop_rx = 1;
+ if (I_IXOFF(tty)) {
+ if (info->board->chip_flag) {
+ info->IER &= ~MOXA_MUST_RECV_ISR;
+ outb(info->IER, info->ioaddr + UART_IER);
+ } else {
+ info->x_char = STOP_CHAR(tty);
+ outb(0, info->ioaddr + UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+ }
+ }
+
+ if (info->tty->termios->c_cflag & CRTSCTS) {
+ info->MCR &= ~UART_MCR_RTS;
+ outb(info->MCR, info->ioaddr + UART_MCR);
+ }
+}
+
+/*
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ */
+static void mxser_throttle(struct tty_struct *tty)
+{
+ mxser_stoprx(tty);
+}
+
+static void mxser_unthrottle(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+
+ /* startrx */
+ info->ldisc_stop_rx = 0;
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else {
+ if (info->board->chip_flag) {
+ info->IER |= MOXA_MUST_RECV_ISR;
+ outb(info->IER, info->ioaddr + UART_IER);
+ } else {
+ info->x_char = START_CHAR(tty);
+ outb(0, info->ioaddr + UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+ }
+ }
+ }
+
+ if (info->tty->termios->c_cflag & CRTSCTS) {
+ info->MCR |= UART_MCR_RTS;
+ outb(info->MCR, info->ioaddr + UART_MCR);
+ }
+}
+
+/*
+ * mxser_stop() and mxser_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ */
+static void mxser_stop(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ if (info->IER & UART_IER_THRI) {
+ info->IER &= ~UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+ }
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_start(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ if (info->xmit_cnt && info->xmit_buf) {
+ outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+ info->IER |= UART_IER_THRI;
+ outb(info->IER, info->ioaddr + UART_IER);
+ }
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ if ((tty->termios->c_cflag != old_termios->c_cflag) ||
+ (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+
+ mxser_change_speed(info, old_termios);
+
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ mxser_start(tty);
+ }
+ }
+
+ /* Handle sw stopped */
+ if ((old_termios->c_iflag & IXON) &&
+ !(tty->termios->c_iflag & IXON)) {
+ tty->stopped = 0;
+
+ if (info->board->chip_flag) {
+ spin_lock_irqsave(&info->slock, flags);
+ DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+ spin_unlock_irqrestore(&info->slock, flags);
+ }
+
+ mxser_start(tty);
+ }
+}
+
+/*
+ * mxser_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+ int lsr;
+
+ if (info->type == PORT_UNKNOWN)
+ return;
+
+ if (info->xmit_fifo_size == 0)
+ return; /* Just in case.... */
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+ if (timeout && timeout < char_time)
+ char_time = timeout;
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than info->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*info->timeout.
+ */
+ if (!timeout || timeout > 2 * info->timeout)
+ timeout = 2 * info->timeout;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
+ timeout, char_time);
+ printk("jiff=%lu...", jiffies);
+#endif
+ while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+ schedule_timeout_interruptible(char_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+ set_current_state(TASK_RUNNING);
+
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * This routine is called by tty_hangup() when a hangup is signaled.
+ */
+void mxser_hangup(struct tty_struct *tty)
+{
+ struct mxser_port *info = tty->driver_data;
+
+ mxser_flush_buffer(tty);
+ mxser_shutdown(info);
+ info->event = 0;
+ info->count = 0;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->tty = NULL;
+ wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * mxser_rs_break() --- routine which turns the break handling on or off
+ */
+static void mxser_rs_break(struct tty_struct *tty, int break_state)
+{
+ struct mxser_port *info = tty->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ if (break_state == -1)
+ outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
+ info->ioaddr + UART_LCR);
+ else
+ outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
+ info->ioaddr + UART_LCR);
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_receive_chars(struct mxser_port *port, int *status)
+{
+ struct tty_struct *tty = port->tty;
+ unsigned char ch, gdl;
+ int ignored = 0;
+ int cnt = 0;
+ int recv_room;
+ int max = 256;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->slock, flags);
+
+ recv_room = tty->receive_room;
+ if ((recv_room == 0) && (!port->ldisc_stop_rx))
+ mxser_stoprx(tty);
+
+ if (port->board->chip_flag != MOXA_OTHER_UART) {
+
+ if (*status & UART_LSR_SPECIAL)
+ goto intr_old;
+ if (port->board->chip_flag == MOXA_MUST_MU860_HWID &&
+ (*status & MOXA_MUST_LSR_RERR))
+ goto intr_old;
+ if (*status & MOXA_MUST_LSR_RERR)
+ goto intr_old;
+
+ gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
+
+ if (port->board->chip_flag == MOXA_MUST_MU150_HWID)
+ gdl &= MOXA_MUST_GDL_MASK;
+ if (gdl >= recv_room) {
+ if (!port->ldisc_stop_rx)
+ mxser_stoprx(tty);
+ }
+ while (gdl--) {
+ ch = inb(port->ioaddr + UART_RX);
+ tty_insert_flip_char(tty, ch, 0);
+ cnt++;
+ }
+ goto end_intr;
+ }
+intr_old:
+
+ do {
+ if (max-- < 0)
+ break;
+
+ ch = inb(port->ioaddr + UART_RX);
+ if (port->board->chip_flag && (*status & UART_LSR_OE))
+ outb(0x23, port->ioaddr + UART_FCR);
+ *status &= port->read_status_mask;
+ if (*status & port->ignore_status_mask) {
+ if (++ignored > 100)
+ break;
+ } else {
+ char flag = 0;
+ if (*status & UART_LSR_SPECIAL) {
+ if (*status & UART_LSR_BI) {
+ flag = TTY_BREAK;
+ port->icount.brk++;
+
+ if (port->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (*status & UART_LSR_PE) {
+ flag = TTY_PARITY;
+ port->icount.parity++;
+ } else if (*status & UART_LSR_FE) {
+ flag = TTY_FRAME;
+ port->icount.frame++;
+ } else if (*status & UART_LSR_OE) {
+ flag = TTY_OVERRUN;
+ port->icount.overrun++;
+ }
+ }
+ tty_insert_flip_char(tty, ch, flag);
+ cnt++;
+ if (cnt >= recv_room) {
+ if (!port->ldisc_stop_rx)
+ mxser_stoprx(tty);
+ break;
+ }
+
+ }
+
+ if (port->board->chip_flag)
+ break;
+
+ *status = inb(port->ioaddr + UART_LSR);
+ } while (*status & UART_LSR_DR);
+
+end_intr:
+ mxvar_log.rxcnt[port->tty->index] += cnt;
+ port->mon_data.rxcnt += cnt;
+ port->mon_data.up_rxcnt += cnt;
+ spin_unlock_irqrestore(&port->slock, flags);
+
+ tty_flip_buffer_push(tty);
+}
+
+static void mxser_transmit_chars(struct mxser_port *port)
+{
+ int count, cnt;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->slock, flags);
+
+ if (port->x_char) {
+ outb(port->x_char, port->ioaddr + UART_TX);
+ port->x_char = 0;
+ mxvar_log.txcnt[port->tty->index]++;
+ port->mon_data.txcnt++;
+ port->mon_data.up_txcnt++;
+ port->icount.tx++;
+ goto unlock;
+ }
+
+ if (port->xmit_buf == 0)
+ goto unlock;
+
+ if ((port->xmit_cnt <= 0) || port->tty->stopped ||
+ (port->tty->hw_stopped &&
+ (port->type != PORT_16550A) &&
+ (!port->board->chip_flag))) {
+ port->IER &= ~UART_IER_THRI;
+ outb(port->IER, port->ioaddr + UART_IER);
+ goto unlock;
+ }
+
+ cnt = port->xmit_cnt;
+ count = port->xmit_fifo_size;
+ do {
+ outb(port->xmit_buf[port->xmit_tail++],
+ port->ioaddr + UART_TX);
+ port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+ if (--port->xmit_cnt <= 0)
+ break;
+ } while (--count > 0);
+ mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt);
+
+ port->mon_data.txcnt += (cnt - port->xmit_cnt);
+ port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
+ port->icount.tx += (cnt - port->xmit_cnt);
+
+ if (port->xmit_cnt < WAKEUP_CHARS) {
+ set_bit(MXSER_EVENT_TXLOW, &port->event);
+ schedule_work(&port->tqueue);
+ }
+ if (port->xmit_cnt <= 0) {
+ port->IER &= ~UART_IER_THRI;
+ outb(port->IER, port->ioaddr + UART_IER);
+ }
+unlock:
+ spin_unlock_irqrestore(&port->slock, flags);
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t mxser_interrupt(int irq, void *dev_id)
+{
+ int status, iir, i;
+ struct mxser_board *brd = NULL;
+ struct mxser_port *port;
+ int max, irqbits, bits, msr;
+ int pass_counter = 0;
+ unsigned int int_cnt;
+ int handled = IRQ_NONE;
+
+ for (i = 0; i < MXSER_BOARDS; i++)
+ if (dev_id == &mxser_boards[i]) {
+ brd = dev_id;
+ break;
+ }
+
+ if (i == MXSER_BOARDS)
+ goto irq_stop;
+ if (brd == NULL)
+ goto irq_stop;
+ max = brd->info->nports;
+ while (1) {
+ irqbits = inb(brd->vector) & brd->vector_mask;
+ if (irqbits == brd->vector_mask)
+ break;
+
+ handled = IRQ_HANDLED;
+ for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+ if (irqbits == brd->vector_mask)
+ break;
+ if (bits & irqbits)
+ continue;
+ port = &brd->ports[i];
+
+ int_cnt = 0;
+ do {
+ iir = inb(port->ioaddr + UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ break;
+ iir &= MOXA_MUST_IIR_MASK;
+ if (!port->tty) {
+ status = inb(port->ioaddr + UART_LSR);
+ outb(0x27, port->ioaddr + UART_FCR);
+ inb(port->ioaddr + UART_MSR);
+ break;
+ }
+
+ status = inb(port->ioaddr + UART_LSR);
+
+ if (status & UART_LSR_PE)
+ port->err_shadow |= NPPI_NOTIFY_PARITY;
+ if (status & UART_LSR_FE)
+ port->err_shadow |= NPPI_NOTIFY_FRAMING;
+ if (status & UART_LSR_OE)
+ port->err_shadow |=
+ NPPI_NOTIFY_HW_OVERRUN;
+ if (status & UART_LSR_BI)
+ port->err_shadow |= NPPI_NOTIFY_BREAK;
+
+ if (port->board->chip_flag) {
+ if (iir == MOXA_MUST_IIR_GDA ||
+ iir == MOXA_MUST_IIR_RDA ||
+ iir == MOXA_MUST_IIR_RTO ||
+ iir == MOXA_MUST_IIR_LSR)
+ mxser_receive_chars(port,
+ &status);
+
+ } else {
+ status &= port->read_status_mask;
+ if (status & UART_LSR_DR)
+ mxser_receive_chars(port,
+ &status);
+ }
+ msr = inb(port->ioaddr + UART_MSR);
+ if (msr & UART_MSR_ANY_DELTA)
+ mxser_check_modem_status(port, msr);
+
+ if (port->board->chip_flag) {
+ if (iir == 0x02 && (status &
+ UART_LSR_THRE))
+ mxser_transmit_chars(port);
+ } else {
+ if (status & UART_LSR_THRE)
+ mxser_transmit_chars(port);
+ }
+ } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
+ }
+ if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
+ break; /* Prevent infinite loops */
+ }
+
+irq_stop:
+ return handled;
+}
+
+static const struct tty_operations mxser_ops = {
+ .open = mxser_open,
+ .close = mxser_close,
+ .write = mxser_write,
+ .put_char = mxser_put_char,
+ .flush_chars = mxser_flush_chars,
+ .write_room = mxser_write_room,
+ .chars_in_buffer = mxser_chars_in_buffer,
+ .flush_buffer = mxser_flush_buffer,
+ .ioctl = mxser_ioctl,
+ .throttle = mxser_throttle,
+ .unthrottle = mxser_unthrottle,
+ .set_termios = mxser_set_termios,
+ .stop = mxser_stop,
+ .start = mxser_start,
+ .hangup = mxser_hangup,
+ .break_ctl = mxser_rs_break,
+ .wait_until_sent = mxser_wait_until_sent,
+ .tiocmget = mxser_tiocmget,
+ .tiocmset = mxser_tiocmset,
+};
+
+/*
+ * The MOXA Smartio/Industio serial driver boot-time initialization code!
+ */
+
+static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
+ unsigned int irq)
+{
+ if (irq)
+ free_irq(brd->irq, brd);
+ if (pdev != NULL) { /* PCI */
+#ifdef CONFIG_PCI
+ pci_release_region(pdev, 2);
+ pci_release_region(pdev, 3);
+ pci_dev_put(pdev);
+#endif
+ } else {
+ release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+ release_region(brd->vector, 1);
+ }
+}
+
+static int __devinit mxser_initbrd(struct mxser_board *brd,
+ struct pci_dev *pdev)
+{
+ struct mxser_port *info;
+ unsigned int i;
+ int retval;
+
+ printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud);
+
+ for (i = 0; i < brd->info->nports; i++) {
+ info = &brd->ports[i];
+ info->board = brd;
+ info->stop_rx = 0;
+ info->ldisc_stop_rx = 0;
+
+ /* Enhance mode enabled here */
+ if (brd->chip_flag != MOXA_OTHER_UART)
+ ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr);
+
+ info->flags = ASYNC_SHARE_IRQ;
+ info->type = brd->uart_type;
+
+ process_txrx_fifo(info);
+
+ info->custom_divisor = info->baud_base * 16;
+ info->close_delay = 5 * HZ / 10;
+ info->closing_wait = 30 * HZ;
+ INIT_WORK(&info->tqueue, mxser_do_softint);
+ info->normal_termios = mxvar_sdriver->init_termios;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+ memset(&info->mon_data, 0, sizeof(struct mxser_mon));
+ info->err_shadow = 0;
+ spin_lock_init(&info->slock);
+
+ /* before set INT ISR, disable all int */
+ outb(inb(info->ioaddr + UART_IER) & 0xf0,
+ info->ioaddr + UART_IER);
+ }
+ /*
+ * Allocate the IRQ if necessary
+ */
+
+ retval = request_irq(brd->irq, mxser_interrupt,
+ (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED :
+ IRQF_DISABLED, "mxser", brd);
+ if (retval) {
+ printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
+ "conflict with another device.\n",
+ brd->info->name, brd->irq);
+ /* We hold resources, we need to release them. */
+ mxser_release_res(brd, pdev, 0);
+ return retval;
+ }
+ return 0;
+}
+
+static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
+{
+ int id, i, bits;
+ unsigned short regs[16], irq;
+ unsigned char scratch, scratch2;
+
+ brd->chip_flag = MOXA_OTHER_UART;
+
+ id = mxser_read_register(cap, regs);
+ switch (id) {
+ case C168_ASIC_ID:
+ brd->info = &mxser_cards[0];
+ break;
+ case C104_ASIC_ID:
+ brd->info = &mxser_cards[1];
+ break;
+ case CI104J_ASIC_ID:
+ brd->info = &mxser_cards[2];
+ break;
+ case C102_ASIC_ID:
+ brd->info = &mxser_cards[5];
+ break;
+ case CI132_ASIC_ID:
+ brd->info = &mxser_cards[6];
+ break;
+ case CI134_ASIC_ID:
+ brd->info = &mxser_cards[7];
+ break;
+ default:
+ return 0;
+ }
+
+ irq = 0;
+ /* some ISA cards have 2 ports, but we want to see them as 4-port (why?)
+ Flag-hack checks if configuration should be read as 2-port here. */
+ if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) {
+ irq = regs[9] & 0xF000;
+ irq = irq | (irq >> 4);
+ if (irq != (regs[9] & 0xFF00))
+ return MXSER_ERR_IRQ_CONFLIT;
+ } else if (brd->info->nports == 4) {
+ irq = regs[9] & 0xF000;
+ irq = irq | (irq >> 4);
+ irq = irq | (irq >> 8);
+ if (irq != regs[9])
+ return MXSER_ERR_IRQ_CONFLIT;
+ } else if (brd->info->nports == 8) {
+ irq = regs[9] & 0xF000;
+ irq = irq | (irq >> 4);
+ irq = irq | (irq >> 8);
+ if ((irq != regs[9]) || (irq != regs[10]))
+ return MXSER_ERR_IRQ_CONFLIT;
+ }
+
+ if (!irq)
+ return MXSER_ERR_IRQ;
+ brd->irq = ((int)(irq & 0xF000) >> 12);
+ for (i = 0; i < 8; i++)
+ brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
+ if ((regs[12] & 0x80) == 0)
+ return MXSER_ERR_VECTOR;
+ brd->vector = (int)regs[11]; /* interrupt vector */
+ if (id == 1)
+ brd->vector_mask = 0x00FF;
+ else
+ brd->vector_mask = 0x000F;
+ for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
+ if (regs[12] & bits) {
+ brd->ports[i].baud_base = 921600;
+ brd->ports[i].max_baud = 921600;
+ } else {
+ brd->ports[i].baud_base = 115200;
+ brd->ports[i].max_baud = 115200;
+ }
+ }
+ scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
+ outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
+ outb(0, cap + UART_EFR); /* EFR is the same as FCR */
+ outb(scratch2, cap + UART_LCR);
+ outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
+ scratch = inb(cap + UART_IIR);
+
+ if (scratch & 0xC0)
+ brd->uart_type = PORT_16550A;
+ else
+ brd->uart_type = PORT_16450;
+ if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
+ "mxser(IO)"))
+ return MXSER_ERR_IOADDR;
+ if (!request_region(brd->vector, 1, "mxser(vector)")) {
+ release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+ return MXSER_ERR_VECTOR;
+ }
+ return brd->info->nports;
+}
+
+static int __devinit mxser_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+#ifdef CONFIG_PCI
+ struct mxser_board *brd;
+ unsigned int i, j;
+ unsigned long ioaddress;
+ int retval = -EINVAL;
+
+ for (i = 0; i < MXSER_BOARDS; i++)
+ if (mxser_boards[i].info == NULL)
+ break;
+
+ if (i >= MXSER_BOARDS) {
+ printk(KERN_ERR "Too many Smartio/Industio family boards found "
+ "(maximum %d), board not configured\n", MXSER_BOARDS);
+ goto err;
+ }
+
+ brd = &mxser_boards[i];
+ brd->idx = i * MXSER_PORTS_PER_BOARD;
+ printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n",
+ mxser_cards[ent->driver_data].name,
+ pdev->bus->number, PCI_SLOT(pdev->devfn));
+
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
+ goto err;
+ }
+
+ /* io address */
+ ioaddress = pci_resource_start(pdev, 2);
+ retval = pci_request_region(pdev, 2, "mxser(IO)");
+ if (retval)
+ goto err;
+
+ brd->info = &mxser_cards[ent->driver_data];
+ for (i = 0; i < brd->info->nports; i++)
+ brd->ports[i].ioaddr = ioaddress + 8 * i;
+
+ /* vector */
+ ioaddress = pci_resource_start(pdev, 3);
+ retval = pci_request_region(pdev, 3, "mxser(vector)");
+ if (retval)
+ goto err_relio;
+ brd->vector = ioaddress;
+
+ /* irq */
+ brd->irq = pdev->irq;
+
+ brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr);
+ brd->uart_type = PORT_16550A;
+ brd->vector_mask = 0;
+
+ for (i = 0; i < brd->info->nports; i++) {
+ for (j = 0; j < UART_INFO_NUM; j++) {
+ if (Gpci_uart_info[j].type == brd->chip_flag) {
+ brd->ports[i].max_baud =
+ Gpci_uart_info[j].max_baud;
+
+ /* exception....CP-102 */
+ if (brd->info->flags & MXSER_HIGHBAUD)
+ brd->ports[i].max_baud = 921600;
+ break;
+ }
+ }
+ }
+
+ if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
+ for (i = 0; i < brd->info->nports; i++) {
+ if (i < 4)
+ brd->ports[i].opmode_ioaddr = ioaddress + 4;
+ else
+ brd->ports[i].opmode_ioaddr = ioaddress + 0x0c;
+ }
+ outb(0, ioaddress + 4); /* default set to RS232 mode */
+ outb(0, ioaddress + 0x0c); /* default set to RS232 mode */
+ }
+
+ for (i = 0; i < brd->info->nports; i++) {
+ brd->vector_mask |= (1 << i);
+ brd->ports[i].baud_base = 921600;
+ }
+
+ /* mxser_initbrd will hook ISR. */
+ if (mxser_initbrd(brd, pdev) < 0)
+ goto err_relvec;
+
+ for (i = 0; i < brd->info->nports; i++)
+ tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
+
+ pci_set_drvdata(pdev, brd);
+
+ return 0;
+err_relvec:
+ pci_release_region(pdev, 3);
+err_relio:
+ pci_release_region(pdev, 2);
+ brd->info = NULL;
+err:
+ return retval;
+#else
+ return -ENODEV;
+#endif
+}
+
+static void __devexit mxser_remove(struct pci_dev *pdev)
+{
+ struct mxser_board *brd = pci_get_drvdata(pdev);
+ unsigned int i;
+
+ for (i = 0; i < brd->info->nports; i++)
+ tty_unregister_device(mxvar_sdriver, brd->idx + i);
+
+ mxser_release_res(brd, pdev, 1);
+}
+
+static struct pci_driver mxser_driver = {
+ .name = "mxser",
+ .id_table = mxser_pcibrds,
+ .probe = mxser_probe,
+ .remove = __devexit_p(mxser_remove)
+};
+
+static int __init mxser_module_init(void)
+{
+ struct mxser_board *brd;
+ unsigned long cap;
+ unsigned int i, m, isaloop;
+ int retval, b;
+
+ pr_debug("Loading module mxser ...\n");
+
+ mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
+ if (!mxvar_sdriver)
+ return -ENOMEM;
+ spin_lock_init(&gm_lock);
+
+ printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
+ MXSER_VERSION);
+
+ /* Initialize the tty_driver structure */
+ mxvar_sdriver->owner = THIS_MODULE;
+ mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
+ mxvar_sdriver->name = "ttyMI";
+ mxvar_sdriver->major = ttymajor;
+ mxvar_sdriver->minor_start = 0;
+ mxvar_sdriver->num = MXSER_PORTS + 1;
+ mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
+ mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
+ mxvar_sdriver->init_termios = tty_std_termios;
+ mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+ mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(mxvar_sdriver, &mxser_ops);
+
+ retval = tty_register_driver(mxvar_sdriver);
+ if (retval) {
+ printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family "
+ "tty driver !\n");
+ goto err_put;
+ }
+
+ mxvar_diagflag = 0;
+
+ m = 0;
+ /* Start finding ISA boards here */
+ for (isaloop = 0; isaloop < 2; isaloop++)
+ for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
+ if (!isaloop)
+ cap = mxserBoardCAP[b]; /* predefined */
+ else
+ cap = ioaddr[b]; /* module param */
+
+ if (!cap)
+ continue;
+
+ brd = &mxser_boards[m];
+ retval = mxser_get_ISA_conf(cap, brd);
+
+ if (retval != 0)
+ printk(KERN_INFO "Found MOXA %s board "
+ "(CAP=0x%x)\n",
+ brd->info->name, ioaddr[b]);
+
+ if (retval <= 0) {
+ if (retval == MXSER_ERR_IRQ)
+ printk(KERN_ERR "Invalid interrupt "
+ "number, board not "
+ "configured\n");
+ else if (retval == MXSER_ERR_IRQ_CONFLIT)
+ printk(KERN_ERR "Invalid interrupt "
+ "number, board not "
+ "configured\n");
+ else if (retval == MXSER_ERR_VECTOR)
+ printk(KERN_ERR "Invalid interrupt "
+ "vector, board not "
+ "configured\n");
+ else if (retval == MXSER_ERR_IOADDR)
+ printk(KERN_ERR "Invalid I/O address, "
+ "board not configured\n");
+
+ brd->info = NULL;
+ continue;
+ }
+
+ /* mxser_initbrd will hook ISR. */
+ if (mxser_initbrd(brd, NULL) < 0) {
+ brd->info = NULL;
+ continue;
+ }
+
+ brd->idx = m * MXSER_PORTS_PER_BOARD;
+ for (i = 0; i < brd->info->nports; i++)
+ tty_register_device(mxvar_sdriver, brd->idx + i,
+ NULL);
+
+ m++;
+ }
+
+ retval = pci_register_driver(&mxser_driver);
+ if (retval) {
+ printk(KERN_ERR "Can't register pci driver\n");
+ if (!m) {
+ retval = -ENODEV;
+ goto err_unr;
+ } /* else: we have some ISA cards under control */
+ }
+
+ pr_debug("Done.\n");
+
+ return 0;
+err_unr:
+ tty_unregister_driver(mxvar_sdriver);
+err_put:
+ put_tty_driver(mxvar_sdriver);
+ return retval;
+}
+
+static void __exit mxser_module_exit(void)
+{
+ unsigned int i, j;
+
+ pr_debug("Unloading module mxser ...\n");
+
+ pci_unregister_driver(&mxser_driver);
+
+ for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
+ if (mxser_boards[i].info != NULL)
+ for (j = 0; j < mxser_boards[i].info->nports; j++)
+ tty_unregister_device(mxvar_sdriver,
+ mxser_boards[i].idx + j);
+ tty_unregister_driver(mxvar_sdriver);
+ put_tty_driver(mxvar_sdriver);
+
+ for (i = 0; i < MXSER_BOARDS; i++)
+ if (mxser_boards[i].info != NULL)
+ mxser_release_res(&mxser_boards[i], NULL, 1);
+
+ pr_debug("Done.\n");
+}
+
+module_init(mxser_module_init);
+module_exit(mxser_module_exit);
diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h
new file mode 100644
index 00000000000..a08f0ecb09b
--- /dev/null
+++ b/drivers/char/mxser_new.h
@@ -0,0 +1,450 @@
+#ifndef _MXSER_H
+#define _MXSER_H
+
+/*
+ * Semi-public control interfaces
+ */
+
+/*
+ * MOXA ioctls
+ */
+
+#define MOXA 0x400
+#define MOXA_GETDATACOUNT (MOXA + 23)
+#define MOXA_GET_CONF (MOXA + 35)
+#define MOXA_DIAGNOSE (MOXA + 50)
+#define MOXA_CHKPORTENABLE (MOXA + 60)
+#define MOXA_HighSpeedOn (MOXA + 61)
+#define MOXA_GET_MAJOR (MOXA + 63)
+#define MOXA_GET_CUMAJOR (MOXA + 64)
+#define MOXA_GETMSTATUS (MOXA + 65)
+#define MOXA_SET_OP_MODE (MOXA + 66)
+#define MOXA_GET_OP_MODE (MOXA + 67)
+
+#define RS232_MODE 0
+#define RS485_2WIRE_MODE 1
+#define RS422_MODE 2
+#define RS485_4WIRE_MODE 3
+#define OP_MODE_MASK 3
+// above add by Victor Yu. 01-05-2004
+
+#define TTY_THRESHOLD_THROTTLE 128
+
+#define LO_WATER (TTY_FLIPBUF_SIZE)
+#define HI_WATER (TTY_FLIPBUF_SIZE*2*3/4)
+
+// added by James. 03-11-2004.
+#define MOXA_SDS_GETICOUNTER (MOXA + 68)
+#define MOXA_SDS_RSTICOUNTER (MOXA + 69)
+// (above) added by James.
+
+#define MOXA_ASPP_OQUEUE (MOXA + 70)
+#define MOXA_ASPP_SETBAUD (MOXA + 71)
+#define MOXA_ASPP_GETBAUD (MOXA + 72)
+#define MOXA_ASPP_MON (MOXA + 73)
+#define MOXA_ASPP_LSTATUS (MOXA + 74)
+#define MOXA_ASPP_MON_EXT (MOXA + 75)
+#define MOXA_SET_BAUD_METHOD (MOXA + 76)
+
+
+/* --------------------------------------------------- */
+
+#define NPPI_NOTIFY_PARITY 0x01
+#define NPPI_NOTIFY_FRAMING 0x02
+#define NPPI_NOTIFY_HW_OVERRUN 0x04
+#define NPPI_NOTIFY_SW_OVERRUN 0x08
+#define NPPI_NOTIFY_BREAK 0x10
+
+#define NPPI_NOTIFY_CTSHOLD 0x01 // Tx hold by CTS low
+#define NPPI_NOTIFY_DSRHOLD 0x02 // Tx hold by DSR low
+#define NPPI_NOTIFY_XOFFHOLD 0x08 // Tx hold by Xoff received
+#define NPPI_NOTIFY_XOFFXENT 0x10 // Xoff Sent
+
+//CheckIsMoxaMust return value
+#define MOXA_OTHER_UART 0x00
+#define MOXA_MUST_MU150_HWID 0x01
+#define MOXA_MUST_MU860_HWID 0x02
+
+// follow just for Moxa Must chip define.
+//
+// when LCR register (offset 0x03) write following value,
+// the Must chip will enter enchance mode. And write value
+// on EFR (offset 0x02) bit 6,7 to change bank.
+#define MOXA_MUST_ENTER_ENCHANCE 0xBF
+
+// when enhance mode enable, access on general bank register
+#define MOXA_MUST_GDL_REGISTER 0x07
+#define MOXA_MUST_GDL_MASK 0x7F
+#define MOXA_MUST_GDL_HAS_BAD_DATA 0x80
+
+#define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO
+// enchance register bank select and enchance mode setting register
+// when LCR register equal to 0xBF
+#define MOXA_MUST_EFR_REGISTER 0x02
+// enchance mode enable
+#define MOXA_MUST_EFR_EFRB_ENABLE 0x10
+// enchance reister bank set 0, 1, 2
+#define MOXA_MUST_EFR_BANK0 0x00
+#define MOXA_MUST_EFR_BANK1 0x40
+#define MOXA_MUST_EFR_BANK2 0x80
+#define MOXA_MUST_EFR_BANK3 0xC0
+#define MOXA_MUST_EFR_BANK_MASK 0xC0
+
+// set XON1 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XON1_REGISTER 0x04
+
+// set XON2 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XON2_REGISTER 0x05
+
+// set XOFF1 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XOFF1_REGISTER 0x06
+
+// set XOFF2 value register, when LCR=0xBF and change to bank0
+#define MOXA_MUST_XOFF2_REGISTER 0x07
+
+#define MOXA_MUST_RBRTL_REGISTER 0x04
+#define MOXA_MUST_RBRTH_REGISTER 0x05
+#define MOXA_MUST_RBRTI_REGISTER 0x06
+#define MOXA_MUST_THRTL_REGISTER 0x07
+#define MOXA_MUST_ENUM_REGISTER 0x04
+#define MOXA_MUST_HWID_REGISTER 0x05
+#define MOXA_MUST_ECR_REGISTER 0x06
+#define MOXA_MUST_CSR_REGISTER 0x07
+
+// good data mode enable
+#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20
+// only good data put into RxFIFO
+#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10
+
+// enable CTS interrupt
+#define MOXA_MUST_IER_ECTSI 0x80
+// enable RTS interrupt
+#define MOXA_MUST_IER_ERTSI 0x40
+// enable Xon/Xoff interrupt
+#define MOXA_MUST_IER_XINT 0x20
+// enable GDA interrupt
+#define MOXA_MUST_IER_EGDAI 0x10
+
+#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI)
+
+// GDA interrupt pending
+#define MOXA_MUST_IIR_GDA 0x1C
+#define MOXA_MUST_IIR_RDA 0x04
+#define MOXA_MUST_IIR_RTO 0x0C
+#define MOXA_MUST_IIR_LSR 0x06
+
+// recieved Xon/Xoff or specical interrupt pending
+#define MOXA_MUST_IIR_XSC 0x10
+
+// RTS/CTS change state interrupt pending
+#define MOXA_MUST_IIR_RTSCTS 0x20
+#define MOXA_MUST_IIR_MASK 0x3E
+
+#define MOXA_MUST_MCR_XON_FLAG 0x40
+#define MOXA_MUST_MCR_XON_ANY 0x80
+#define MOXA_MUST_MCR_TX_XON 0x08
+
+
+// software flow control on chip mask value
+#define MOXA_MUST_EFR_SF_MASK 0x0F
+// send Xon1/Xoff1
+#define MOXA_MUST_EFR_SF_TX1 0x08
+// send Xon2/Xoff2
+#define MOXA_MUST_EFR_SF_TX2 0x04
+// send Xon1,Xon2/Xoff1,Xoff2
+#define MOXA_MUST_EFR_SF_TX12 0x0C
+// don't send Xon/Xoff
+#define MOXA_MUST_EFR_SF_TX_NO 0x00
+// Tx software flow control mask
+#define MOXA_MUST_EFR_SF_TX_MASK 0x0C
+// don't receive Xon/Xoff
+#define MOXA_MUST_EFR_SF_RX_NO 0x00
+// receive Xon1/Xoff1
+#define MOXA_MUST_EFR_SF_RX1 0x02
+// receive Xon2/Xoff2
+#define MOXA_MUST_EFR_SF_RX2 0x01
+// receive Xon1,Xon2/Xoff1,Xoff2
+#define MOXA_MUST_EFR_SF_RX12 0x03
+// Rx software flow control mask
+#define MOXA_MUST_EFR_SF_RX_MASK 0x03
+
+//#define MOXA_MUST_MIN_XOFFLIMIT 66
+//#define MOXA_MUST_MIN_XONLIMIT 20
+//#define ID1_RX_TRIG 120
+
+
+#define CHECK_MOXA_MUST_XOFFLIMIT(info) { \
+ if ( (info)->IsMoxaMustChipFlag && \
+ (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \
+ (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \
+ (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \
+ } \
+}
+
+#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK0; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK0; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK0; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK0; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+//#define MOXA_MUST_RBRL_VALUE 4
+#define SET_MOXA_MUST_FIFO_VALUE(info) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((info)->ioaddr+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR); \
+ __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK1; \
+ outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER); \
+ outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER); \
+ outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER); \
+ outb(__oldlcr, (info)->ioaddr+UART_LCR); \
+}
+
+
+
+#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK2; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
+ __efr |= MOXA_MUST_EFR_BANK2; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_MASK; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_MASK; \
+ __efr |= MOXA_MUST_EFR_SF_TX1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
+ __efr |= MOXA_MUST_EFR_SF_TX1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_MASK; \
+ __efr |= MOXA_MUST_EFR_SF_RX1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
+ __efr |= MOXA_MUST_EFR_SF_RX1; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
+ u8 __oldlcr, __efr; \
+ __oldlcr = inb((baseio)+UART_LCR); \
+ outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
+ __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
+ __efr &= ~MOXA_MUST_EFR_SF_MASK; \
+ __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \
+ outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
+ outb(__oldlcr, (baseio)+UART_LCR); \
+}
+
+#define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
+ u8 __oldmcr; \
+ __oldmcr = inb((baseio)+UART_MCR); \
+ __oldmcr |= MOXA_MUST_MCR_XON_ANY; \
+ outb(__oldmcr, (baseio)+UART_MCR); \
+}
+
+#define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
+ u8 __oldmcr; \
+ __oldmcr = inb((baseio)+UART_MCR); \
+ __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \
+ outb(__oldmcr, (baseio)+UART_MCR); \
+}
+
+#define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER)
+
+
+#ifndef INIT_WORK
+#define INIT_WORK(_work, _func, _data){ \
+ _data->tqueue.routine = _func;\
+ _data->tqueue.data = _data;\
+ }
+#endif
+
+#endif
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 203dc2b661d..dc6d4184145 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -125,8 +125,8 @@ static void transmit_block(struct r3964_info *pInfo);
static void receive_char(struct r3964_info *pInfo, const unsigned char c);
static void receive_error(struct r3964_info *pInfo, const char flag);
static void on_timeout(unsigned long priv);
-static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg);
-static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf);
+static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg);
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf);
static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
int error_code, struct r3964_block_header *pBlock);
static struct r3964_message* remove_msg(struct r3964_info *pInfo,
@@ -142,7 +142,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
const unsigned char * buf, size_t nr);
static int r3964_ioctl(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg);
-static void r3964_set_termios(struct tty_struct *tty, struct termios * old);
+static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old);
static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
struct poll_table_struct *wait);
static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
@@ -829,7 +829,7 @@ static void on_timeout(unsigned long priv)
}
static struct r3964_client_info *findClient(
- struct r3964_info *pInfo, pid_t pid)
+ struct r3964_info *pInfo, struct pid *pid)
{
struct r3964_client_info *pClient;
@@ -843,7 +843,7 @@ static struct r3964_client_info *findClient(
return NULL;
}
-static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
+static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
{
struct r3964_client_info *pClient;
struct r3964_client_info **ppClient;
@@ -858,7 +858,7 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
if(pClient->pid == pid)
{
- TRACE_PS("removing client %d from client list", pid);
+ TRACE_PS("removing client %d from client list", pid_nr(pid));
*ppClient = pClient->next;
while(pClient->msg_count)
{
@@ -869,6 +869,7 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
TRACE_M("enable_signals - msg kfree %p",pMsg);
}
}
+ put_pid(pClient->pid);
kfree(pClient);
TRACE_M("enable_signals - kfree %p",pClient);
return 0;
@@ -892,10 +893,10 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
if(pClient==NULL)
return -ENOMEM;
- TRACE_PS("add client %d to client list", pid);
+ TRACE_PS("add client %d to client list", pid_nr(pid));
spin_lock_init(&pClient->lock);
pClient->sig_flags=arg;
- pClient->pid = pid;
+ pClient->pid = get_pid(pid);
pClient->next=pInfo->firstClient;
pClient->first_msg = NULL;
pClient->last_msg = NULL;
@@ -908,7 +909,7 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
return 0;
}
-static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char __user *buf)
+static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf)
{
struct r3964_client_info *pClient;
struct r3964_block_header *block;
@@ -1005,7 +1006,7 @@ queue_the_message:
/* Send SIGIO signal to client process: */
if(pClient->sig_flags & R3964_USE_SIGIO)
{
- kill_proc(pClient->pid, SIGIO, 1);
+ kill_pid(pClient->pid, SIGIO, 1);
}
}
@@ -1042,7 +1043,7 @@ static void remove_client_block(struct r3964_info *pInfo,
{
struct r3964_block_header *block;
- TRACE_PS("remove_client_block PID %d", pClient->pid);
+ TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
block=pClient->next_block_to_read;
if(block)
@@ -1157,6 +1158,7 @@ static void r3964_close(struct tty_struct *tty)
TRACE_M("r3964_close - msg kfree %p",pMsg);
}
}
+ put_pid(pClient->pid);
kfree(pClient);
TRACE_M("r3964_close - client kfree %p",pClient);
pClient=pNext;
@@ -1193,12 +1195,11 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
struct r3964_client_message theMsg;
DECLARE_WAITQUEUE (wait, current);
- int pid = current->pid;
int count;
TRACE_L("read()");
- pClient=findClient(pInfo, pid);
+ pClient=findClient(pInfo, task_pid(current));
if(pClient)
{
pMsg = remove_msg(pInfo, pClient);
@@ -1252,7 +1253,6 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
struct r3964_block_header *pHeader;
struct r3964_client_info *pClient;
unsigned char *new_data;
- int pid;
TRACE_L("write request, %d characters", count);
/*
@@ -1295,9 +1295,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
pHeader->locks = 0;
pHeader->owner = NULL;
- pid=current->pid;
-
- pClient=findClient(pInfo, pid);
+ pClient=findClient(pInfo, task_pid(current));
if(pClient)
{
pHeader->owner = pClient;
@@ -1328,7 +1326,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file,
switch(cmd)
{
case R3964_ENABLE_SIGNALS:
- return enable_signals(pInfo, current->pid, arg);
+ return enable_signals(pInfo, task_pid(current), arg);
case R3964_SETPRIORITY:
if(arg<R3964_MASTER || arg>R3964_SLAVE)
return -EINVAL;
@@ -1341,13 +1339,13 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file,
pInfo->flags &= ~R3964_BCC;
return 0;
case R3964_READ_TELEGRAM:
- return read_telegram(pInfo, current->pid, (unsigned char __user *)arg);
+ return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg);
default:
return -ENOIOCTLCMD;
}
}
-static void r3964_set_termios(struct tty_struct *tty, struct termios * old)
+static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old)
{
TRACE_L("set_termios");
}
@@ -1357,7 +1355,6 @@ static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
struct poll_table_struct *wait)
{
struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
- int pid=current->pid;
struct r3964_client_info *pClient;
struct r3964_message *pMsg=NULL;
unsigned long flags;
@@ -1365,7 +1362,7 @@ static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
TRACE_L("POLL");
- pClient=findClient(pInfo,pid);
+ pClient=findClient(pInfo, task_pid(current));
if(pClient)
{
poll_wait(file, &pInfo->read_wait, wait);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 603b9ade5eb..2bdb0144a22 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -994,7 +994,7 @@ int is_ignored(int sig)
* when the ldisc is closed.
*/
-static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
+static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
{
if (!tty)
return;
@@ -1151,7 +1151,6 @@ static int copy_from_read_buf(struct tty_struct *tty,
n = min(*nr, n);
spin_unlock_irqrestore(&tty->read_lock, flags);
if (n) {
- mb();
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
n -= retval;
spin_lock_irqsave(&tty->read_lock, flags);
diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c
index 4d47d79bcea..808d44e9a32 100644
--- a/drivers/char/nsc_gpio.c
+++ b/drivers/char/nsc_gpio.c
@@ -41,7 +41,7 @@ void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index)
ssize_t nsc_gpio_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
- unsigned m = iminor(file->f_dentry->d_inode);
+ unsigned m = iminor(file->f_path.dentry->d_inode);
struct nsc_gpio_ops *amp = file->private_data;
struct device *dev = amp->dev;
size_t i;
@@ -104,7 +104,7 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data,
ssize_t nsc_gpio_read(struct file *file, char __user * buf,
size_t len, loff_t * ppos)
{
- unsigned m = iminor(file->f_dentry->d_inode);
+ unsigned m = iminor(file->f_path.dentry->d_inode);
int value;
struct nsc_gpio_ops *amp = file->private_data;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 74d21c1c104..f108c136800 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -541,7 +541,7 @@ static int mgslpc_probe(struct pcmcia_device *link)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_attach\n");
- info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
+ info = kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
if (!info) {
printk("Error can't allocate device instance data\n");
return -ENOMEM;
@@ -2375,7 +2375,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
* tty pointer to tty structure
* termios pointer to buffer to hold returned old termios
*/
-static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index c1e3dd837fc..4abd1eff61d 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -106,7 +106,7 @@ static inline void pp_enable_irq (struct pp_struct *pp)
static ssize_t pp_read (struct file * file, char __user * buf, size_t count,
loff_t * ppos)
{
- unsigned int minor = iminor(file->f_dentry->d_inode);
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
struct pp_struct *pp = file->private_data;
char * kbuffer;
ssize_t bytes_read = 0;
@@ -189,7 +189,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count,
static ssize_t pp_write (struct file * file, const char __user * buf,
size_t count, loff_t * ppos)
{
- unsigned int minor = iminor(file->f_dentry->d_inode);
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
struct pp_struct *pp = file->private_data;
char * kbuffer;
ssize_t bytes_written = 0;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 80d3eedd7f9..c07a1b5cd05 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -218,7 +218,7 @@ out:
return retval;
}
-static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
tty->termios->c_cflag &= ~(CSIZE | PARENB);
tty->termios->c_cflag |= (CS8 | CREAD);
@@ -272,6 +272,8 @@ static void __init legacy_pty_init(void)
pty_driver->init_termios.c_oflag = 0;
pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
pty_driver->init_termios.c_lflag = 0;
+ pty_driver->init_termios.c_ispeed = 38400;
+ pty_driver->init_termios.c_ospeed = 38400;
pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
pty_driver->other = pty_slave_driver;
tty_set_operations(pty_driver, &pty_ops);
@@ -286,6 +288,8 @@ static void __init legacy_pty_init(void)
pty_slave_driver->subtype = PTY_TYPE_SLAVE;
pty_slave_driver->init_termios = tty_std_termios;
pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+ pty_slave_driver->init_termios.c_ispeed = 38400;
+ pty_slave_driver->init_termios.c_ospeed = 38400;
pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
TTY_DRIVER_REAL_RAW;
pty_slave_driver->other = pty_driver;
@@ -366,6 +370,8 @@ static void __init unix98_pty_init(void)
ptm_driver->init_termios.c_oflag = 0;
ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
ptm_driver->init_termios.c_lflag = 0;
+ ptm_driver->init_termios.c_ispeed = 38400;
+ ptm_driver->init_termios.c_ospeed = 38400;
ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
ptm_driver->other = pts_driver;
@@ -381,6 +387,8 @@ static void __init unix98_pty_init(void)
pts_driver->subtype = PTY_TYPE_SLAVE;
pts_driver->init_termios = tty_std_termios;
pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+ pts_driver->init_termios.c_ispeed = 38400;
+ pts_driver->init_termios.c_ospeed = 38400;
pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
pts_driver->other = ptm_driver;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 4c6782a1ecd..13d0b1350a6 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1048,7 +1048,7 @@ random_write(struct file * file, const char __user * buffer,
if (p == buffer) {
return (ssize_t)ret;
} else {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
inode->i_mtime = current_fs_time(inode->i_sb);
mark_inode_dirty(inode);
return (ssize_t)(p - buffer);
@@ -1203,7 +1203,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
unsigned char tmp_uuid[16], *uuid;
unsigned int len;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 3b32313f6eb..645e20a06ec 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -75,7 +75,7 @@ static int raw_open(struct inode *inode, struct file *filp)
filp->f_flags |= O_DIRECT;
filp->f_mapping = bdev->bd_inode->i_mapping;
if (++raw_devices[minor].inuse == 1)
- filp->f_dentry->d_inode->i_mapping =
+ filp->f_path.dentry->d_inode->i_mapping =
bdev->bd_inode->i_mapping;
filp->private_data = bdev;
mutex_unlock(&raw_mutex);
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 167ebc84e8d..245f03195b7 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -556,7 +556,7 @@ struct CmdBlk *RIOGetCmdBlk(void)
{
struct CmdBlk *CmdBlkP;
- CmdBlkP = (struct CmdBlk *)kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
+ CmdBlkP = kmalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
if (CmdBlkP)
memset(CmdBlkP, 0, sizeof(struct CmdBlk));
return CmdBlkP;
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 0a77bfcd5b5..e2a94bfb2a4 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1539,7 +1539,7 @@ static void rc_hangup(struct tty_struct * tty)
wake_up_interruptible(&port->open_wait);
}
-static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
{
struct riscom_port *port = (struct riscom_port *)tty->driver_data;
unsigned long flags;
@@ -1614,6 +1614,8 @@ static inline int rc_init_drivers(void)
riscom_driver->init_termios = tty_std_termios;
riscom_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ riscom_driver->init_termios.c_ispeed = 9600;
+ riscom_driver->init_termios.c_ospeed = 9600;
riscom_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(riscom_driver, &riscom_ops);
if ((error = tty_register_driver(riscom_driver))) {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index bac80056f7e..e94a62e30fc 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -712,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
* user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
*/
static void configure_r_port(struct r_port *info,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
unsigned cflag;
unsigned long flags;
@@ -1017,7 +1017,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
/*
* Info->count is now 1; so it's safe to sleep now.
*/
- info->session = current->signal->session;
+ info->session = process_session(current);
info->pgrp = process_group(current);
if ((info->flags & ROCKET_INITIALIZED) == 0) {
@@ -1194,7 +1194,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
}
static void rp_set_termios(struct tty_struct *tty,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct r_port *info = (struct r_port *) tty->driver_data;
CHANNEL_t *cp;
@@ -2214,7 +2214,7 @@ static int __init init_PCI(int boards_found)
int count = 0;
/* Work through the PCI device list, pulling out ours */
- while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
+ while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
if (register_PCI(count + boards_found, dev))
count++;
}
@@ -2436,6 +2436,8 @@ static int __init rp_init(void)
rocket_driver->init_termios = tty_std_termios;
rocket_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ rocket_driver->init_termios.c_ispeed = 9600;
+ rocket_driver->init_termios.c_ospeed = 9600;
#ifdef ROCKET_SOFT_FLOW
rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
#endif
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 66a7385bc34..664f36c98e6 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -113,7 +113,12 @@ static int rtc_has_irq = 1;
#define hpet_set_rtc_irq_bit(arg) 0
#define hpet_rtc_timer_init() do { } while (0)
#define hpet_rtc_dropped_irq() 0
-static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;}
+#ifdef RTC_IRQ
+static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
+{
+ return 0;
+}
+#endif
#else
extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
#endif
@@ -165,7 +170,9 @@ static void mask_rtc_irq_bit(unsigned char bit)
}
#endif
+#ifdef CONFIG_PROC_FS
static int rtc_proc_open(struct inode *inode, struct file *file);
+#endif
/*
* Bits in rtc_status. (6 bits of room for future expansion)
@@ -906,6 +913,7 @@ static struct miscdevice rtc_dev = {
.fops = &rtc_fops,
};
+#ifdef CONFIG_PROC_FS
static const struct file_operations rtc_proc_fops = {
.owner = THIS_MODULE,
.open = rtc_proc_open,
@@ -913,14 +921,13 @@ static const struct file_operations rtc_proc_fops = {
.llseek = seq_lseek,
.release = single_release,
};
-
-#if defined(RTC_IRQ) && !defined(__sparc__)
-static irq_handler_t rtc_int_handler_ptr;
#endif
static int __init rtc_init(void)
{
+#ifdef CONFIG_PROC_FS
struct proc_dir_entry *ent;
+#endif
#if defined(__alpha__) || defined(__mips__)
unsigned int year, ctrl;
char *guess = NULL;
@@ -932,9 +939,11 @@ static int __init rtc_init(void)
struct sparc_isa_bridge *isa_br;
struct sparc_isa_device *isa_dev;
#endif
-#endif
-#ifndef __sparc__
+#else
void *r;
+#ifdef RTC_IRQ
+ irq_handler_t rtc_int_handler_ptr;
+#endif
#endif
#ifdef __sparc__
@@ -958,6 +967,7 @@ static int __init rtc_init(void)
}
}
#endif
+ rtc_has_irq = 0;
printk(KERN_ERR "rtc_init: no PC rtc found\n");
return -EIO;
@@ -972,6 +982,7 @@ found:
* PCI Slot 2 INTA# (and some INTx# in Slot 1).
*/
if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
+ rtc_has_irq = 0;
printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
return -EIO;
}
@@ -982,6 +993,9 @@ no_irq:
else
r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
if (!r) {
+#ifdef RTC_IRQ
+ rtc_has_irq = 0;
+#endif
printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
(long)(RTC_PORT(0)));
return -EIO;
@@ -996,6 +1010,7 @@ no_irq:
if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
+ rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
if (RTC_IOMAPPED)
release_region(RTC_PORT(0), RTC_IO_EXTENT);
@@ -1012,21 +1027,19 @@ no_irq:
if (misc_register(&rtc_dev)) {
#ifdef RTC_IRQ
free_irq(RTC_IRQ, NULL);
+ rtc_has_irq = 0;
#endif
release_region(RTC_PORT(0), RTC_IO_EXTENT);
return -ENODEV;
}
+#ifdef CONFIG_PROC_FS
ent = create_proc_entry("driver/rtc", 0, NULL);
- if (!ent) {
-#ifdef RTC_IRQ
- free_irq(RTC_IRQ, NULL);
+ if (ent)
+ ent->proc_fops = &rtc_proc_fops;
+ else
+ printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
#endif
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- misc_deregister(&rtc_dev);
- return -ENOMEM;
- }
- ent->proc_fops = &rtc_proc_fops;
#if defined(__alpha__) || defined(__mips__)
rtc_freq = HZ;
@@ -1159,6 +1172,7 @@ static void rtc_dropped_irq(unsigned long data)
}
#endif
+#ifdef CONFIG_PROC_FS
/*
* Info exported via "/proc/driver/rtc".
*/
@@ -1243,6 +1257,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, rtc_proc_show, NULL);
}
+#endif
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
{
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 4217d38caef..75de5f66517 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -695,6 +695,8 @@ static int a2232_init_drivers(void)
a2232_driver->init_termios = tty_std_termios;
a2232_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ a2232_driver->init_termios.c_ispeed = 9600;
+ a2232_driver->init_termios.c_ospeed = 9600;
a2232_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(a2232_driver, &a2232_ops);
if ((error = tty_register_driver(a2232_driver))) {
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 9ba13af234b..af50d32ae2c 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -1695,7 +1695,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
static void
-cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
+cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios)
{
struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index fc87070f186..17d54e1331b 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -979,7 +979,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
}
if (ret > 0) {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
inode->i_atime = current_fs_time(inode->i_sb);
}
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 99137ab66b6..20946f5127e 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -2311,7 +2311,7 @@ static void sx_hangup(struct tty_struct * tty)
}
-static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
@@ -2400,6 +2400,8 @@ static int sx_init_drivers(void)
specialix_driver->init_termios = tty_std_termios;
specialix_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ specialix_driver->init_termios.c_ispeed = 9600;
+ specialix_driver->init_termios.c_ospeed = 9600;
specialix_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(specialix_driver, &sx_ops);
@@ -2475,7 +2477,7 @@ static int __init specialix_init(void)
i++;
continue;
}
- pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+ pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
PCI_DEVICE_ID_SPECIALIX_IO8,
pdev);
if (!pdev) break;
@@ -2491,6 +2493,9 @@ static int __init specialix_init(void)
if (!sx_probe(&sx_board[i]))
found ++;
}
+ /* May exit pci_get sequence early with lots of boards */
+ if (pdev != NULL)
+ pci_dev_put(pdev);
}
#endif
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 5e2de62bce7..e45113a7a47 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -41,13 +41,12 @@
#include <linux/smp_lock.h>
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/ctype.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PCI
#include <linux/pci.h>
-#endif
/*****************************************************************************/
@@ -63,45 +62,16 @@
#define BRD_ECH64PCI 27
#define BRD_EASYIOPCI 28
-/*
- * Define a configuration structure to hold the board configuration.
- * Need to set this up in the code (for now) with the boards that are
- * to be configured into the system. This is what needs to be modified
- * when adding/removing/modifying boards. Each line entry in the
- * stl_brdconf[] array is a board. Each line contains io/irq/memory
- * ranges for that board (as well as what type of board it is).
- * Some examples:
- * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
- * This line would configure an EasyIO board (4 or 8, no difference),
- * at io address 2a0 and irq 10.
- * Another example:
- * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 },
- * This line will configure an EasyConnection 8/32 board at primary io
- * address 2a8, secondary io address 280 and irq 12.
- * Enter as many lines into this array as you want (only the first 4
- * will actually be used!). Any combination of EasyIO and EasyConnection
- * boards can be specified. EasyConnection 8/32 boards can share their
- * secondary io addresses between each other.
- *
- * NOTE: there is no need to put any entries in this table for PCI
- * boards. They will be found automatically by the driver - provided
- * PCI BIOS32 support is compiled into the kernel.
- */
-
-typedef struct {
- int brdtype;
+struct stlconf {
+ unsigned int brdtype;
int ioaddr1;
int ioaddr2;
unsigned long memaddr;
int irq;
int irqtype;
-} stlconf_t;
-
-static stlconf_t stl_brdconf[] = {
- /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
};
-static int stl_nrbrds = ARRAY_SIZE(stl_brdconf);
+static unsigned int stl_nrbrds;
/*****************************************************************************/
@@ -143,34 +113,30 @@ static struct tty_driver *stl_serial;
* with this termios initially. Basically all it defines is a raw port
* at 9600, 8 data bits, 1 stop bit.
*/
-static struct termios stl_deftermios = {
+static struct ktermios stl_deftermios = {
.c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
.c_cc = INIT_C_CC,
+ .c_ispeed = 9600,
+ .c_ospeed = 9600,
};
/*
- * Define global stats structures. Not used often, and can be
- * re-used for each stats call.
- */
-static comstats_t stl_comstats;
-static combrd_t stl_brdstats;
-static stlbrd_t stl_dummybrd;
-static stlport_t stl_dummyport;
-
-/*
* Define global place to put buffer overflow characters.
*/
static char stl_unwanted[SC26198_RXFIFOSIZE];
/*****************************************************************************/
-static stlbrd_t *stl_brds[STL_MAXBRDS];
+static DEFINE_MUTEX(stl_brdslock);
+static struct stlbrd *stl_brds[STL_MAXBRDS];
/*
* Per board state flags. Used with the state field of the board struct.
* Not really much here!
*/
#define BRD_FOUND 0x1
+#define STL_PROBED 0x2
+
/*
* Define the port structure istate flags. These set of flags are
@@ -187,32 +153,32 @@ static stlbrd_t *stl_brds[STL_MAXBRDS];
* referencing boards when printing trace and stuff.
*/
static char *stl_brdnames[] = {
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
"EasyIO",
"EC8/32-AT",
"EC8/32-MC",
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
+ NULL,
+ NULL,
+ NULL,
"EC8/32-PCI",
"EC8/64-PCI",
"EasyIO-PCI",
@@ -225,7 +191,7 @@ static char *stl_brdnames[] = {
* load line. These allow for easy board definitions, and easy
* modification of the io, memory and irq resoucres.
*/
-static int stl_nargs = 0;
+static unsigned int stl_nargs;
static char *board0[4];
static char *board1[4];
static char *board2[4];
@@ -243,12 +209,10 @@ static char **stl_brdsp[] = {
* parse any module arguments.
*/
-typedef struct stlbrdtype {
+static struct {
char *name;
int type;
-} stlbrdtype_t;
-
-static stlbrdtype_t stl_brdstr[] = {
+} stl_brdstr[] = {
{ "easyio", BRD_EASYIO },
{ "eio", BRD_EASYIO },
{ "20", BRD_EASYIO },
@@ -282,9 +246,6 @@ static stlbrdtype_t stl_brdstr[] = {
/*
* Define the module agruments.
*/
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
-MODULE_LICENSE("GPL");
module_param_array(board0, charp, &stl_nargs, 0);
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
@@ -386,8 +347,6 @@ static spinlock_t stallion_lock; /* Guard the tty driver */
/*****************************************************************************/
-#ifdef CONFIG_PCI
-
/*
* Define the Stallion PCI vendor and device IDs.
*/
@@ -407,22 +366,19 @@ static spinlock_t stallion_lock; /* Guard the tty driver */
/*
* Define structure to hold all Stallion PCI boards.
*/
-typedef struct stlpcibrd {
- unsigned short vendid;
- unsigned short devid;
- int brdtype;
-} stlpcibrd_t;
-
-static stlpcibrd_t stl_pcibrds[] = {
- { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI },
- { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI },
- { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI },
- { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
-};
-
-static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
-#endif
+static struct pci_device_id stl_pcibrds[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
+ .driver_data = BRD_ECH64PCI },
+ { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
+ .driver_data = BRD_EASYIOPCI },
+ { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
+ .driver_data = BRD_ECHPCI },
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
+ .driver_data = BRD_ECHPCI },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, stl_pcibrds);
/*****************************************************************************/
@@ -442,134 +398,74 @@ static unsigned int stl_baudrates[] = {
9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
};
-/*
- * Define some handy local macros...
- */
-#undef MIN
-#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
-
-#undef TOLOWER
-#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
-
/*****************************************************************************/
/*
* Declare all those functions in this driver!
*/
-static void stl_argbrds(void);
-static int stl_parsebrd(stlconf_t *confp, char **argp);
-
-static unsigned long stl_atol(char *str);
-
-static int stl_init(void);
-static int stl_open(struct tty_struct *tty, struct file *filp);
-static void stl_close(struct tty_struct *tty, struct file *filp);
-static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void stl_putchar(struct tty_struct *tty, unsigned char ch);
-static void stl_flushchars(struct tty_struct *tty);
-static int stl_writeroom(struct tty_struct *tty);
-static int stl_charsinbuffer(struct tty_struct *tty);
-static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void stl_settermios(struct tty_struct *tty, struct termios *old);
-static void stl_throttle(struct tty_struct *tty);
-static void stl_unthrottle(struct tty_struct *tty);
-static void stl_stop(struct tty_struct *tty);
-static void stl_start(struct tty_struct *tty);
-static void stl_flushbuffer(struct tty_struct *tty);
-static void stl_breakctl(struct tty_struct *tty, int state);
-static void stl_waituntilsent(struct tty_struct *tty, int timeout);
-static void stl_sendxchar(struct tty_struct *tty, char ch);
-static void stl_hangup(struct tty_struct *tty);
static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
-static int stl_portinfo(stlport_t *portp, int portnr, char *pos);
-static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data);
-
-static int stl_brdinit(stlbrd_t *brdp);
-static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-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);
-static int stl_getportstats(stlport_t *portp, comstats_t __user *cp);
-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 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(struct work_struct *);
-static stlbrd_t *stl_allocbrd(void);
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
-
-static inline int stl_initbrds(void);
-static inline int stl_initeio(stlbrd_t *brdp);
-static inline int stl_initech(stlbrd_t *brdp);
-static inline int stl_getbrdnr(void);
-
-#ifdef CONFIG_PCI
-static inline int stl_findpcibrds(void);
-static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp);
-#endif
+static int stl_brdinit(struct stlbrd *brdp);
+static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
+static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
+static int stl_waitcarrier(struct stlport *portp, struct file *filp);
/*
* CD1400 uart specific handling functions.
*/
-static void stl_cd1400setreg(stlport_t *portp, int regnr, int value);
-static int stl_cd1400getreg(stlport_t *portp, int regnr);
-static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value);
-static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
-static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp);
-static int stl_cd1400getsignals(stlport_t *portp);
-static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts);
-static void stl_cd1400ccrwait(stlport_t *portp);
-static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx);
-static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx);
-static void stl_cd1400disableintrs(stlport_t *portp);
-static void stl_cd1400sendbreak(stlport_t *portp, int len);
-static void stl_cd1400flowctrl(stlport_t *portp, int state);
-static void stl_cd1400sendflow(stlport_t *portp, int state);
-static void stl_cd1400flush(stlport_t *portp);
-static int stl_cd1400datastate(stlport_t *portp);
-static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);
-static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);
-static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);
-static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);
-static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);
-
-static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr);
+static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
+static int stl_cd1400getreg(struct stlport *portp, int regnr);
+static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
+static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
+static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
+static int stl_cd1400getsignals(struct stlport *portp);
+static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
+static void stl_cd1400ccrwait(struct stlport *portp);
+static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
+static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
+static void stl_cd1400disableintrs(struct stlport *portp);
+static void stl_cd1400sendbreak(struct stlport *portp, int len);
+static void stl_cd1400flowctrl(struct stlport *portp, int state);
+static void stl_cd1400sendflow(struct stlport *portp, int state);
+static void stl_cd1400flush(struct stlport *portp);
+static int stl_cd1400datastate(struct stlport *portp);
+static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
+static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
+static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
+static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
+static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
+
+static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
/*
* SC26198 uart specific handling functions.
*/
-static void stl_sc26198setreg(stlport_t *portp, int regnr, int value);
-static int stl_sc26198getreg(stlport_t *portp, int regnr);
-static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value);
-static int stl_sc26198getglobreg(stlport_t *portp, int regnr);
-static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp);
-static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
-static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp);
-static int stl_sc26198getsignals(stlport_t *portp);
-static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts);
-static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx);
-static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx);
-static void stl_sc26198disableintrs(stlport_t *portp);
-static void stl_sc26198sendbreak(stlport_t *portp, int len);
-static void stl_sc26198flowctrl(stlport_t *portp, int state);
-static void stl_sc26198sendflow(stlport_t *portp, int state);
-static void stl_sc26198flush(stlport_t *portp);
-static int stl_sc26198datastate(stlport_t *portp);
-static void stl_sc26198wait(stlport_t *portp);
-static void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty);
-static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase);
-static void stl_sc26198txisr(stlport_t *port);
-static void stl_sc26198rxisr(stlport_t *port, unsigned int iack);
-static void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch);
-static void stl_sc26198rxbadchars(stlport_t *portp);
-static void stl_sc26198otherisr(stlport_t *port, unsigned int iack);
+static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
+static int stl_sc26198getreg(struct stlport *portp, int regnr);
+static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
+static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
+static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
+static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
+static int stl_sc26198getsignals(struct stlport *portp);
+static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
+static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
+static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
+static void stl_sc26198disableintrs(struct stlport *portp);
+static void stl_sc26198sendbreak(struct stlport *portp, int len);
+static void stl_sc26198flowctrl(struct stlport *portp, int state);
+static void stl_sc26198sendflow(struct stlport *portp, int state);
+static void stl_sc26198flush(struct stlport *portp);
+static int stl_sc26198datastate(struct stlport *portp);
+static void stl_sc26198wait(struct stlport *portp);
+static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
+static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
+static void stl_sc26198txisr(struct stlport *port);
+static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
+static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
+static void stl_sc26198rxbadchars(struct stlport *portp);
+static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
/*****************************************************************************/
@@ -577,20 +473,20 @@ static void stl_sc26198otherisr(stlport_t *port, unsigned int iack);
* Generic UART support structure.
*/
typedef struct uart {
- int (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp);
- void (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);
- void (*setport)(stlport_t *portp, struct termios *tiosp);
- int (*getsignals)(stlport_t *portp);
- void (*setsignals)(stlport_t *portp, int dtr, int rts);
- void (*enablerxtx)(stlport_t *portp, int rx, int tx);
- void (*startrxtx)(stlport_t *portp, int rx, int tx);
- void (*disableintrs)(stlport_t *portp);
- void (*sendbreak)(stlport_t *portp, int len);
- void (*flowctrl)(stlport_t *portp, int state);
- void (*sendflow)(stlport_t *portp, int state);
- void (*flush)(stlport_t *portp);
- int (*datastate)(stlport_t *portp);
- void (*intr)(stlpanel_t *panelp, unsigned int iobase);
+ int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
+ void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+ void (*setport)(struct stlport *portp, struct ktermios *tiosp);
+ int (*getsignals)(struct stlport *portp);
+ void (*setsignals)(struct stlport *portp, int dtr, int rts);
+ void (*enablerxtx)(struct stlport *portp, int rx, int tx);
+ void (*startrxtx)(struct stlport *portp, int rx, int tx);
+ void (*disableintrs)(struct stlport *portp);
+ void (*sendbreak)(struct stlport *portp, int len);
+ void (*flowctrl)(struct stlport *portp, int state);
+ void (*sendflow)(struct stlport *portp, int state);
+ void (*flush)(struct stlport *portp);
+ int (*datastate)(struct stlport *portp);
+ void (*intr)(struct stlpanel *panelp, unsigned int iobase);
} uart_t;
/*
@@ -712,184 +608,35 @@ static const struct file_operations stl_fsiomem = {
.ioctl = stl_memioctl,
};
-/*****************************************************************************/
-
static struct class *stallion_class;
/*
- * Loadable module initialization stuff.
- */
-
-static int __init stallion_module_init(void)
-{
- stl_init();
- return 0;
-}
-
-/*****************************************************************************/
-
-static void __exit stallion_module_exit(void)
-{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
- stlport_t *portp;
- int i, j, k;
-
-#ifdef DEBUG
- printk("cleanup_module()\n");
-#endif
-
- printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
- stl_drvversion);
-
-/*
- * Free up all allocated resources used by the ports. This includes
- * memory and interrupts. As part of this process we will also do
- * a hangup on every open port - to try to flush out any processes
- * hanging onto ports.
- */
- i = tty_unregister_driver(stl_serial);
- put_tty_driver(stl_serial);
- if (i) {
- printk("STALLION: failed to un-register tty driver, "
- "errno=%d\n", -i);
- return;
- }
- for (i = 0; i < 4; i++)
- class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
- if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
- printk("STALLION: failed to un-register serial memory device, "
- "errno=%d\n", -i);
- class_destroy(stallion_class);
-
- 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)
- continue;
- for (k = 0; (k < STL_PORTSPERPANEL); k++) {
- portp = panelp->ports[k];
- if (portp == (stlport_t *) NULL)
- continue;
- if (portp->tty != (struct tty_struct *) NULL)
- stl_hangup(portp->tty);
- kfree(portp->tx.buf);
- kfree(portp);
- }
- kfree(panelp);
- }
-
- release_region(brdp->ioaddr1, brdp->iosize1);
- if (brdp->iosize2 > 0)
- release_region(brdp->ioaddr2, brdp->iosize2);
-
- kfree(brdp);
- stl_brds[i] = (stlbrd_t *) NULL;
- }
-}
-
-module_init(stallion_module_init);
-module_exit(stallion_module_exit);
-
-/*****************************************************************************/
-
-/*
* Check for any arguments passed in on the module load command line.
*/
-static void stl_argbrds(void)
-{
- stlconf_t conf;
- stlbrd_t *brdp;
- int i;
-
-#ifdef DEBUG
- printk("stl_argbrds()\n");
-#endif
-
- for (i = stl_nrbrds; (i < stl_nargs); i++) {
- memset(&conf, 0, sizeof(conf));
- if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
- continue;
- if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
- continue;
- stl_nrbrds = i + 1;
- brdp->brdnr = i;
- brdp->brdtype = conf.brdtype;
- brdp->ioaddr1 = conf.ioaddr1;
- brdp->ioaddr2 = conf.ioaddr2;
- brdp->irq = conf.irq;
- brdp->irqtype = conf.irqtype;
- stl_brdinit(brdp);
- }
-}
-
-/*****************************************************************************/
-
-/*
- * Convert an ascii string number into an unsigned long.
- */
-
-static unsigned long stl_atol(char *str)
-{
- unsigned long val;
- int base, c;
- char *sp;
-
- val = 0;
- sp = str;
- if ((*sp == '0') && (*(sp+1) == 'x')) {
- base = 16;
- sp += 2;
- } else if (*sp == '0') {
- base = 8;
- sp++;
- } else {
- base = 10;
- }
-
- for (; (*sp != 0); sp++) {
- c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
- if ((c < 0) || (c >= base)) {
- printk("STALLION: invalid argument %s\n", str);
- val = 0;
- break;
- }
- val = (val * base) + c;
- }
- return val;
-}
-
/*****************************************************************************/
/*
* Parse the supplied argument string, into the board conf struct.
*/
-static int stl_parsebrd(stlconf_t *confp, char **argp)
+static int __init stl_parsebrd(struct stlconf *confp, char **argp)
{
char *sp;
- int i;
+ unsigned int i;
-#ifdef DEBUG
- printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
-#endif
+ pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
- if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
+ if ((argp[0] == NULL) || (*argp[0] == 0))
return 0;
- for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
- *sp = TOLOWER(*sp);
+ for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
+ *sp = tolower(*sp);
- for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
+ for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
break;
- }
+
if (i == ARRAY_SIZE(stl_brdstr)) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
return 0;
@@ -898,16 +645,16 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
confp->brdtype = stl_brdstr[i].type;
i = 1;
- if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
- confp->ioaddr1 = stl_atol(argp[i]);
+ if ((argp[i] != NULL) && (*argp[i] != 0))
+ confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
i++;
if (confp->brdtype == BRD_ECH) {
- if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
- confp->ioaddr2 = stl_atol(argp[i]);
+ if ((argp[i] != NULL) && (*argp[i] != 0))
+ confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
i++;
}
- if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
- confp->irq = stl_atol(argp[i]);
+ if ((argp[i] != NULL) && (*argp[i] != 0))
+ confp->irq = simple_strtoul(argp[i], NULL, 0);
return 1;
}
@@ -917,14 +664,14 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
* Allocate a new board structure. Fill out the basic info in it.
*/
-static stlbrd_t *stl_allocbrd(void)
+static struct stlbrd *stl_allocbrd(void)
{
- stlbrd_t *brdp;
+ struct stlbrd *brdp;
- brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
+ brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
if (!brdp) {
printk("STALLION: failed to allocate memory (size=%Zd)\n",
- sizeof(stlbrd_t));
+ sizeof(struct stlbrd));
return NULL;
}
@@ -936,26 +683,23 @@ static stlbrd_t *stl_allocbrd(void)
static int stl_open(struct tty_struct *tty, struct file *filp)
{
- stlport_t *portp;
- stlbrd_t *brdp;
- unsigned int minordev;
- int brdnr, panelnr, portnr, rc;
-
-#ifdef DEBUG
- printk("stl_open(tty=%x,filp=%x): device=%s\n", (int) tty,
- (int) filp, tty->name);
-#endif
+ struct stlport *portp;
+ struct stlbrd *brdp;
+ unsigned int minordev, brdnr, panelnr;
+ int portnr, rc;
+
+ pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
minordev = tty->index;
brdnr = MINOR2BRD(minordev);
if (brdnr >= stl_nrbrds)
return -ENODEV;
brdp = stl_brds[brdnr];
- if (brdp == (stlbrd_t *) NULL)
+ if (brdp == NULL)
return -ENODEV;
minordev = MINOR2PORT(minordev);
- for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
- if (brdp->panels[panelnr] == (stlpanel_t *) NULL)
+ for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
+ if (brdp->panels[panelnr] == NULL)
break;
if (minordev < brdp->panels[panelnr]->nrports) {
portnr = minordev;
@@ -967,7 +711,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
portp = brdp->panels[panelnr]->ports[portnr];
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return -ENODEV;
/*
@@ -1013,10 +757,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
* previous opens still in effect. If we are a normal serial device
* then also we might have to wait for carrier.
*/
- if (!(filp->f_flags & O_NONBLOCK)) {
+ if (!(filp->f_flags & O_NONBLOCK))
if ((rc = stl_waitcarrier(portp, filp)) != 0)
return rc;
- }
+
portp->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
@@ -1029,14 +773,12 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
* maybe because if we are clocal then we don't need to wait...
*/
-static int stl_waitcarrier(stlport_t *portp, struct file *filp)
+static int stl_waitcarrier(struct stlport *portp, struct file *filp)
{
unsigned long flags;
int rc, doclocal;
-#ifdef DEBUG
- printk("stl_waitcarrier(portp=%x,filp=%x)\n", (int) portp, (int) filp);
-#endif
+ pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
rc = 0;
doclocal = 0;
@@ -1062,9 +804,8 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
break;
}
if (((portp->flags & ASYNC_CLOSING) == 0) &&
- (doclocal || (portp->sigs & TIOCM_CD))) {
+ (doclocal || (portp->sigs & TIOCM_CD)))
break;
- }
if (signal_pending(current)) {
rc = -ERESTARTSYS;
break;
@@ -1083,17 +824,61 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
/*****************************************************************************/
+static void stl_flushbuffer(struct tty_struct *tty)
+{
+ struct stlport *portp;
+
+ pr_debug("stl_flushbuffer(tty=%p)\n", tty);
+
+ if (tty == NULL)
+ return;
+ portp = tty->driver_data;
+ if (portp == NULL)
+ return;
+
+ stl_flush(portp);
+ tty_wakeup(tty);
+}
+
+/*****************************************************************************/
+
+static void stl_waituntilsent(struct tty_struct *tty, int timeout)
+{
+ struct stlport *portp;
+ unsigned long tend;
+
+ pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
+
+ if (tty == NULL)
+ return;
+ portp = tty->driver_data;
+ if (portp == NULL)
+ return;
+
+ if (timeout == 0)
+ timeout = HZ;
+ tend = jiffies + timeout;
+
+ while (stl_datastate(portp)) {
+ if (signal_pending(current))
+ break;
+ msleep_interruptible(20);
+ if (time_after_eq(jiffies, tend))
+ break;
+ }
+}
+
+/*****************************************************************************/
+
static void stl_close(struct tty_struct *tty, struct file *filp)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_close(tty=%x,filp=%x)\n", (int) tty, (int) filp);
-#endif
+ pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
spin_lock_irqsave(&stallion_lock, flags);
@@ -1136,17 +921,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
stl_enablerxtx(portp, 0, 0);
stl_flushbuffer(tty);
portp->istate = 0;
- if (portp->tx.buf != (char *) NULL) {
+ if (portp->tx.buf != NULL) {
kfree(portp->tx.buf);
- portp->tx.buf = (char *) NULL;
- portp->tx.head = (char *) NULL;
- portp->tx.tail = (char *) NULL;
+ portp->tx.buf = NULL;
+ portp->tx.head = NULL;
+ portp->tx.tail = NULL;
}
set_bit(TTY_IO_ERROR, &tty->flags);
tty_ldisc_flush(tty);
tty->closing = 0;
- portp->tty = (struct tty_struct *) NULL;
+ portp->tty = NULL;
if (portp->openwaitcnt) {
if (portp->close_delay)
@@ -1167,20 +952,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned int len, stlen;
unsigned char *chbuf;
char *head, *tail;
-#ifdef DEBUG
- printk("stl_write(tty=%x,buf=%x,count=%d)\n",
- (int) tty, (int) buf, count);
-#endif
+ pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return 0;
- if (portp->tx.buf == (char *) NULL)
+ if (portp->tx.buf == NULL)
return 0;
/*
@@ -1201,10 +983,10 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
stlen = len;
}
- len = MIN(len, count);
+ len = min(len, (unsigned int)count);
count = 0;
while (len > 0) {
- stlen = MIN(len, stlen);
+ stlen = min(len, stlen);
memcpy(head, chbuf, stlen);
len -= stlen;
chbuf += stlen;
@@ -1227,20 +1009,18 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
static void stl_putchar(struct tty_struct *tty, unsigned char ch)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned int len;
char *head, *tail;
-#ifdef DEBUG
- printk("stl_putchar(tty=%x,ch=%x)\n", (int) tty, (int) ch);
-#endif
+ pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
- if (portp->tx.buf == (char *) NULL)
+ if (portp->tx.buf == NULL)
return;
head = portp->tx.head;
@@ -1267,18 +1047,16 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch)
static void stl_flushchars(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_flushchars(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_flushchars(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
- if (portp->tx.buf == (char *) NULL)
+ if (portp->tx.buf == NULL)
return;
stl_startrxtx(portp, -1, 1);
@@ -1288,24 +1066,22 @@ static void stl_flushchars(struct tty_struct *tty)
static int stl_writeroom(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
char *head, *tail;
-#ifdef DEBUG
- printk("stl_writeroom(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_writeroom(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return 0;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return 0;
- if (portp->tx.buf == (char *) NULL)
+ if (portp->tx.buf == NULL)
return 0;
head = portp->tx.head;
tail = portp->tx.tail;
- return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
+ return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
}
/*****************************************************************************/
@@ -1321,20 +1097,18 @@ static int stl_writeroom(struct tty_struct *tty)
static int stl_charsinbuffer(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned int size;
char *head, *tail;
-#ifdef DEBUG
- printk("stl_charsinbuffer(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return 0;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return 0;
- if (portp->tx.buf == (char *) NULL)
+ if (portp->tx.buf == NULL)
return 0;
head = portp->tx.head;
@@ -1351,14 +1125,12 @@ static int stl_charsinbuffer(struct tty_struct *tty)
* Generate the serial struct info.
*/
-static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp)
+static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
{
struct serial_struct sio;
- stlbrd_t *brdp;
+ struct stlbrd *brdp;
-#ifdef DEBUG
- printk("stl_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
-#endif
+ pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
memset(&sio, 0, sizeof(struct serial_struct));
sio.line = portp->portnr;
@@ -1378,7 +1150,7 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp)
}
brdp = stl_brds[portp->brdnr];
- if (brdp != (stlbrd_t *) NULL)
+ if (brdp != NULL)
sio.irq = brdp->irq;
return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
@@ -1392,13 +1164,11 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp)
* just quietly ignore any requests to change irq, etc.
*/
-static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
+static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
{
struct serial_struct sio;
-#ifdef DEBUG
- printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
-#endif
+ pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
return -EFAULT;
@@ -1424,12 +1194,12 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
static int stl_tiocmget(struct tty_struct *tty, struct file *file)
{
- stlport_t *portp;
+ struct stlport *portp;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return -ENODEV;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
@@ -1440,13 +1210,13 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
static int stl_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- stlport_t *portp;
+ struct stlport *portp;
int rts = -1, dtr = -1;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return -ENODEV;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
@@ -1466,27 +1236,24 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned int ival;
int rc;
void __user *argp = (void __user *)arg;
-#ifdef DEBUG
- printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n",
- (int) tty, (int) file, cmd, (int) arg);
-#endif
+ pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
+ arg);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return -ENODEV;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
+ (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
- }
rc = 0;
@@ -1531,19 +1298,37 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
/*****************************************************************************/
-static void stl_settermios(struct tty_struct *tty, struct termios *old)
+/*
+ * Start the transmitter again. Just turn TX interrupts back on.
+ */
+
+static void stl_start(struct tty_struct *tty)
{
- stlport_t *portp;
- struct termios *tiosp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old);
-#endif
+ pr_debug("stl_start(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
+ return;
+ stl_startrxtx(portp, -1, 1);
+}
+
+/*****************************************************************************/
+
+static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
+{
+ struct stlport *portp;
+ struct ktermios *tiosp;
+
+ pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
+
+ if (tty == NULL)
+ return;
+ portp = tty->driver_data;
+ if (portp == NULL)
return;
tiosp = tty->termios;
@@ -1571,16 +1356,14 @@ static void stl_settermios(struct tty_struct *tty, struct termios *old)
static void stl_throttle(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_throttle(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_throttle(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
stl_flowctrl(portp, 0);
}
@@ -1593,16 +1376,14 @@ static void stl_throttle(struct tty_struct *tty)
static void stl_unthrottle(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_unthrottle(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_unthrottle(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
stl_flowctrl(portp, 1);
}
@@ -1616,16 +1397,14 @@ static void stl_unthrottle(struct tty_struct *tty)
static void stl_stop(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_stop(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_stop(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
stl_startrxtx(portp, -1, 0);
}
@@ -1633,28 +1412,6 @@ static void stl_stop(struct tty_struct *tty)
/*****************************************************************************/
/*
- * Start the transmitter again. Just turn TX interrupts back on.
- */
-
-static void stl_start(struct tty_struct *tty)
-{
- stlport_t *portp;
-
-#ifdef DEBUG
- printk("stl_start(tty=%x)\n", (int) tty);
-#endif
-
- if (tty == (struct tty_struct *) NULL)
- return;
- portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
- return;
- stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-/*
* Hangup this port. This is pretty much like closing the port, only
* a little more brutal. No waiting for data to drain. Shutdown the
* port and maybe drop signals.
@@ -1662,16 +1419,14 @@ static void stl_start(struct tty_struct *tty)
static void stl_hangup(struct tty_struct *tty)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_hangup(tty=%x)\n", (int) tty);
-#endif
+ pr_debug("stl_hangup(tty=%p)\n", tty);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
portp->flags &= ~ASYNC_INITIALIZED;
@@ -1682,13 +1437,13 @@ static void stl_hangup(struct tty_struct *tty)
stl_flushbuffer(tty);
portp->istate = 0;
set_bit(TTY_IO_ERROR, &tty->flags);
- if (portp->tx.buf != (char *) NULL) {
+ if (portp->tx.buf != NULL) {
kfree(portp->tx.buf);
- portp->tx.buf = (char *) NULL;
- portp->tx.head = (char *) NULL;
- portp->tx.tail = (char *) NULL;
+ portp->tx.buf = NULL;
+ portp->tx.head = NULL;
+ portp->tx.tail = NULL;
}
- portp->tty = (struct tty_struct *) NULL;
+ portp->tty = NULL;
portp->flags &= ~ASYNC_NORMAL_ACTIVE;
portp->refcount = 0;
wake_up_interruptible(&portp->open_wait);
@@ -1696,38 +1451,16 @@ static void stl_hangup(struct tty_struct *tty)
/*****************************************************************************/
-static void stl_flushbuffer(struct tty_struct *tty)
-{
- stlport_t *portp;
-
-#ifdef DEBUG
- printk("stl_flushbuffer(tty=%x)\n", (int) tty);
-#endif
-
- if (tty == (struct tty_struct *) NULL)
- return;
- portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
- return;
-
- stl_flush(portp);
- tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
static void stl_breakctl(struct tty_struct *tty, int state)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state);
-#endif
+ pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
stl_sendbreak(portp, ((state == -1) ? 1 : 2));
@@ -1735,48 +1468,16 @@ static void stl_breakctl(struct tty_struct *tty, int state)
/*****************************************************************************/
-static void stl_waituntilsent(struct tty_struct *tty, int timeout)
-{
- stlport_t *portp;
- unsigned long tend;
-
-#ifdef DEBUG
- printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout);
-#endif
-
- if (tty == (struct tty_struct *) NULL)
- return;
- portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
- return;
-
- if (timeout == 0)
- timeout = HZ;
- tend = jiffies + timeout;
-
- while (stl_datastate(portp)) {
- if (signal_pending(current))
- break;
- msleep_interruptible(20);
- if (time_after_eq(jiffies, tend))
- break;
- }
-}
-
-/*****************************************************************************/
-
static void stl_sendxchar(struct tty_struct *tty, char ch)
{
- stlport_t *portp;
+ struct stlport *portp;
-#ifdef DEBUG
- printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);
-#endif
+ pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
portp = tty->driver_data;
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
if (ch == STOP_CHAR(tty))
@@ -1797,7 +1498,7 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)
* short then padded with spaces).
*/
-static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
+static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
{
char *sp;
int sigs, cnt;
@@ -1826,7 +1527,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
*sp = ' ';
sp += cnt;
- for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
+ for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
*sp++ = ' ';
if (cnt >= MAXLINE)
pos[(MAXLINE - 2)] = '+';
@@ -1843,18 +1544,15 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
- stlport_t *portp;
- int brdnr, panelnr, portnr, totalport;
- int curoff, maxoff;
+ struct stlbrd *brdp;
+ struct stlpanel *panelp;
+ struct stlport *portp;
+ unsigned int brdnr, panelnr, portnr;
+ int totalport, curoff, maxoff;
char *pos;
-#ifdef DEBUG
- printk("stl_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x,"
- "data=%x\n", (int) page, (int) start, (int) off, count,
- (int) eof, (int) data);
-#endif
+ pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
+ "data=%p\n", page, start, off, count, eof, data);
pos = page;
totalport = 0;
@@ -1873,9 +1571,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
* We scan through for each board, panel and port. The offset is
* calculated on the fly, and irrelevant ports are skipped.
*/
- for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
+ for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
brdp = stl_brds[brdnr];
- if (brdp == (stlbrd_t *) NULL)
+ if (brdp == NULL)
continue;
if (brdp->state == 0)
continue;
@@ -1887,9 +1585,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
}
totalport = brdnr * STL_MAXPORTS;
- for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
+ for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
panelp = brdp->panels[panelnr];
- if (panelp == (stlpanel_t *) NULL)
+ if (panelp == NULL)
continue;
maxoff = curoff + (panelp->nrports * MAXLINE);
@@ -1899,10 +1597,10 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
continue;
}
- for (portnr = 0; (portnr < panelp->nrports); portnr++,
+ for (portnr = 0; portnr < panelp->nrports; portnr++,
totalport++) {
portp = panelp->ports[portnr];
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
continue;
if (off >= (curoff += MAXLINE))
continue;
@@ -1917,7 +1615,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
stl_readdone:
*start = page;
- return (pos - page);
+ return pos - page;
}
/*****************************************************************************/
@@ -1929,11 +1627,9 @@ stl_readdone:
static irqreturn_t stl_intr(int irq, void *dev_id)
{
- stlbrd_t *brdp = (stlbrd_t *) dev_id;
+ struct stlbrd *brdp = dev_id;
-#ifdef DEBUG
- printk("stl_intr(brdp=%x,irq=%d)\n", (int) brdp, irq);
-#endif
+ pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
return IRQ_RETVAL((* brdp->isr)(brdp));
}
@@ -1944,9 +1640,9 @@ static irqreturn_t stl_intr(int irq, void *dev_id)
* Interrupt service routine for EasyIO board types.
*/
-static int stl_eiointr(stlbrd_t *brdp)
+static int stl_eiointr(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
+ struct stlpanel *panelp;
unsigned int iobase;
int handled = 0;
@@ -1967,18 +1663,17 @@ static int stl_eiointr(stlbrd_t *brdp)
* Interrupt service routine for ECH-AT board types.
*/
-static int stl_echatintr(stlbrd_t *brdp)
+static int stl_echatintr(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
- unsigned int ioaddr;
- int bnknr;
+ struct stlpanel *panelp;
+ unsigned int ioaddr, 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++) {
+ for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
panelp = brdp->bnk2panel[bnknr];
@@ -1998,16 +1693,15 @@ static int stl_echatintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-MCA board types.
*/
-static int stl_echmcaintr(stlbrd_t *brdp)
+static int stl_echmcaintr(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
- unsigned int ioaddr;
- int bnknr;
+ struct stlpanel *panelp;
+ unsigned int ioaddr, bnknr;
int handled = 0;
while (inb(brdp->iostatus) & ECH_INTRPEND) {
handled = 1;
- for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+ for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
panelp = brdp->bnk2panel[bnknr];
@@ -2024,16 +1718,15 @@ static int stl_echmcaintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-PCI board types.
*/
-static int stl_echpciintr(stlbrd_t *brdp)
+static int stl_echpciintr(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
- unsigned int ioaddr;
- int bnknr, recheck;
+ struct stlpanel *panelp;
+ unsigned int ioaddr, bnknr, recheck;
int handled = 0;
while (1) {
recheck = 0;
- for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+ for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2055,16 +1748,15 @@ static int stl_echpciintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-8/64-PCI board types.
*/
-static int stl_echpci64intr(stlbrd_t *brdp)
+static int stl_echpci64intr(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
- unsigned int ioaddr;
- int bnknr;
+ struct stlpanel *panelp;
+ unsigned int ioaddr, bnknr;
int handled = 0;
while (inb(brdp->ioctrl) & 0x1) {
handled = 1;
- for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
+ for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
panelp = brdp->bnk2panel[bnknr];
@@ -2083,35 +1775,32 @@ static int stl_echpci64intr(stlbrd_t *brdp)
*/
static void stl_offintr(struct work_struct *work)
{
- stlport_t *portp = container_of(work, stlport_t, tqueue);
+ struct stlport *portp = container_of(work, struct stlport, tqueue);
struct tty_struct *tty;
unsigned int oldsigs;
-#ifdef DEBUG
- printk("stl_offintr(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_offintr(portp=%p)\n", portp);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
tty = portp->tty;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
lock_kernel();
- if (test_bit(ASYI_TXLOW, &portp->istate)) {
+ if (test_bit(ASYI_TXLOW, &portp->istate))
tty_wakeup(tty);
- }
+
if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
clear_bit(ASYI_DCDCHANGE, &portp->istate);
oldsigs = portp->sigs;
portp->sigs = stl_getsignals(portp);
if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
wake_up_interruptible(&portp->open_wait);
- if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
+ if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
if (portp->flags & ASYNC_CHECK_CD)
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
- }
}
unlock_kernel();
}
@@ -2122,14 +1811,13 @@ static void stl_offintr(struct work_struct *work)
* Initialize all the ports on a panel.
*/
-static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
+static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
{
- stlport_t *portp;
- int chipmask, i;
+ struct stlport *portp;
+ unsigned int i;
+ int chipmask;
-#ifdef DEBUG
- printk("stl_initports(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
-#endif
+ pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
chipmask = stl_panelinit(brdp, panelp);
@@ -2137,11 +1825,11 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
* All UART's are initialized (if found!). Now go through and setup
* each ports data structures.
*/
- for (i = 0; (i < panelp->nrports); i++) {
- portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
+ for (i = 0; i < panelp->nrports; i++) {
+ portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
if (!portp) {
printk("STALLION: failed to allocate memory "
- "(size=%Zd)\n", sizeof(stlport_t));
+ "(size=%Zd)\n", sizeof(struct stlport));
break;
}
@@ -2164,7 +1852,30 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
stl_portinit(brdp, panelp, portp);
}
- return(0);
+ return 0;
+}
+
+static void stl_cleanup_panels(struct stlbrd *brdp)
+{
+ struct stlpanel *panelp;
+ struct stlport *portp;
+ unsigned int j, k;
+
+ for (j = 0; j < STL_MAXPANELS; j++) {
+ panelp = brdp->panels[j];
+ if (panelp == NULL)
+ continue;
+ for (k = 0; k < STL_PORTSPERPANEL; k++) {
+ portp = panelp->ports[k];
+ if (portp == NULL)
+ continue;
+ if (portp->tty != NULL)
+ stl_hangup(portp->tty);
+ kfree(portp->tx.buf);
+ kfree(portp);
+ }
+ kfree(panelp);
+ }
}
/*****************************************************************************/
@@ -2173,16 +1884,14 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
* Try to find and initialize an EasyIO board.
*/
-static inline int stl_initeio(stlbrd_t *brdp)
+static int __devinit stl_initeio(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
+ struct stlpanel *panelp;
unsigned int status;
char *name;
- int rc;
+ int retval;
-#ifdef DEBUG
- printk("stl_initeio(brdp=%x)\n", (int) brdp);
-#endif
+ pr_debug("stl_initeio(brdp=%p)\n", brdp);
brdp->ioctrl = brdp->ioaddr1 + 1;
brdp->iostatus = brdp->ioaddr1 + 2;
@@ -2207,18 +1916,20 @@ static inline int stl_initeio(stlbrd_t *brdp)
(stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
printk("STALLION: invalid irq=%d for brd=%d\n",
brdp->irq, brdp->brdnr);
- return(-EINVAL);
+ retval = -EINVAL;
+ goto err;
}
outb((stl_vecmap[brdp->irq] | EIO_0WS |
((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
brdp->ioctrl);
}
+ retval = -EBUSY;
if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
"%x conflicts with another device\n", brdp->brdnr,
brdp->ioaddr1);
- return(-EBUSY);
+ goto err;
}
if (brdp->iosize2 > 0)
@@ -2229,8 +1940,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
printk(KERN_WARNING "STALLION: Warning, also "
"releasing board %d I/O address %x \n",
brdp->brdnr, brdp->ioaddr1);
- release_region(brdp->ioaddr1, brdp->iosize1);
- return(-EBUSY);
+ goto err_rel1;
}
/*
@@ -2239,6 +1949,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
brdp->clk = CD1400_CLK;
brdp->isr = stl_eiointr;
+ retval = -ENODEV;
switch (status & EIO_IDBITMASK) {
case EIO_8PORTM:
brdp->clk = CD1400_CLK8M;
@@ -2262,11 +1973,11 @@ static inline int stl_initeio(stlbrd_t *brdp)
brdp->nrports = 16;
break;
default:
- return(-ENODEV);
+ goto err_rel2;
}
break;
default:
- return(-ENODEV);
+ goto err_rel2;
}
/*
@@ -2274,11 +1985,12 @@ static inline int stl_initeio(stlbrd_t *brdp)
* can complete the setup.
*/
- panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+ panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
if (!panelp) {
printk(KERN_WARNING "STALLION: failed to allocate memory "
- "(size=%Zd)\n", sizeof(stlpanel_t));
- return -ENOMEM;
+ "(size=%Zd)\n", sizeof(struct stlpanel));
+ retval = -ENOMEM;
+ goto err_rel2;
}
panelp->magic = STL_PANELMAGIC;
@@ -2288,10 +2000,10 @@ static inline int stl_initeio(stlbrd_t *brdp)
panelp->iobase = brdp->ioaddr1;
panelp->hwid = status;
if ((status & EIO_IDBITMASK) == EIO_MK3) {
- panelp->uartp = (void *) &stl_sc26198uart;
+ panelp->uartp = &stl_sc26198uart;
panelp->isr = stl_sc26198intr;
} else {
- panelp->uartp = (void *) &stl_cd1400uart;
+ panelp->uartp = &stl_cd1400uart;
panelp->isr = stl_cd1400eiointr;
}
@@ -2302,11 +2014,20 @@ static inline int stl_initeio(stlbrd_t *brdp)
if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
printk("STALLION: failed to register interrupt "
"routine for %s irq=%d\n", name, brdp->irq);
- rc = -ENODEV;
- } else {
- rc = 0;
+ retval = -ENODEV;
+ goto err_fr;
}
- return rc;
+
+ return 0;
+err_fr:
+ stl_cleanup_panels(brdp);
+err_rel2:
+ if (brdp->iosize2 > 0)
+ release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+ release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+ return retval;
}
/*****************************************************************************/
@@ -2316,16 +2037,14 @@ static inline int stl_initeio(stlbrd_t *brdp)
* dealing with all types of ECH board.
*/
-static inline int stl_initech(stlbrd_t *brdp)
+static int __devinit stl_initech(struct stlbrd *brdp)
{
- stlpanel_t *panelp;
- unsigned int status, nxtid, ioaddr, conflict;
- int panelnr, banknr, i;
+ struct stlpanel *panelp;
+ unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
+ int retval;
char *name;
-#ifdef DEBUG
- printk("stl_initech(brdp=%x)\n", (int) brdp);
-#endif
+ pr_debug("stl_initech(brdp=%p)\n", brdp);
status = 0;
conflict = 0;
@@ -2342,20 +2061,23 @@ static inline int stl_initech(stlbrd_t *brdp)
brdp->ioctrl = brdp->ioaddr1 + 1;
brdp->iostatus = brdp->ioaddr1 + 1;
status = inb(brdp->iostatus);
- if ((status & ECH_IDBITMASK) != ECH_ID)
- return(-ENODEV);
+ if ((status & ECH_IDBITMASK) != ECH_ID) {
+ retval = -ENODEV;
+ goto err;
+ }
if ((brdp->irq < 0) || (brdp->irq > 15) ||
(stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
printk("STALLION: invalid irq=%d for brd=%d\n",
brdp->irq, brdp->brdnr);
- return(-EINVAL);
+ retval = -EINVAL;
+ goto err;
}
status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
status |= (stl_vecmap[brdp->irq] << 1);
outb((status | ECH_BRDRESET), brdp->ioaddr1);
brdp->ioctrlval = ECH_INTENABLE |
((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
- for (i = 0; (i < 10); i++)
+ for (i = 0; i < 10; i++)
outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
brdp->iosize1 = 2;
brdp->iosize2 = 32;
@@ -2368,13 +2090,16 @@ static inline int stl_initech(stlbrd_t *brdp)
brdp->ioctrl = brdp->ioaddr1 + 0x20;
brdp->iostatus = brdp->ioctrl;
status = inb(brdp->iostatus);
- if ((status & ECH_IDBITMASK) != ECH_ID)
- return(-ENODEV);
+ if ((status & ECH_IDBITMASK) != ECH_ID) {
+ retval = -ENODEV;
+ goto err;
+ }
if ((brdp->irq < 0) || (brdp->irq > 15) ||
(stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
printk("STALLION: invalid irq=%d for brd=%d\n",
brdp->irq, brdp->brdnr);
- return(-EINVAL);
+ retval = -EINVAL;
+ goto err;
}
outb(ECHMC_BRDRESET, brdp->ioctrl);
outb(ECHMC_INTENABLE, brdp->ioctrl);
@@ -2401,19 +2126,20 @@ static inline int stl_initech(stlbrd_t *brdp)
default:
printk("STALLION: unknown board type=%d\n", brdp->brdtype);
- return(-EINVAL);
- break;
+ retval = -EINVAL;
+ goto err;
}
/*
* Check boards for possible IO address conflicts and return fail status
* if an IO conflict found.
*/
+ retval = -EBUSY;
if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
"%x conflicts with another device\n", brdp->brdnr,
brdp->ioaddr1);
- return(-EBUSY);
+ goto err;
}
if (brdp->iosize2 > 0)
@@ -2424,8 +2150,7 @@ static inline int stl_initech(stlbrd_t *brdp)
printk(KERN_WARNING "STALLION: Warning, also "
"releasing board %d I/O address %x \n",
brdp->brdnr, brdp->ioaddr1);
- release_region(brdp->ioaddr1, brdp->iosize1);
- return(-EBUSY);
+ goto err_rel1;
}
/*
@@ -2440,19 +2165,19 @@ static inline int stl_initech(stlbrd_t *brdp)
panelnr = 0;
nxtid = 0;
- for (i = 0; (i < STL_MAXPANELS); i++) {
+ for (i = 0; i < STL_MAXPANELS; i++) {
if (brdp->brdtype == BRD_ECHPCI) {
outb(nxtid, brdp->ioctrl);
ioaddr = brdp->ioaddr2;
}
status = inb(ioaddr + ECH_PNLSTATUS);
if ((status & ECH_PNLIDMASK) != nxtid)
- break;
- panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+ goto err_fr;
+ panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
if (!panelp) {
printk("STALLION: failed to allocate memory "
- "(size=%Zd)\n", sizeof(stlpanel_t));
- break;
+ "(size=%Zd)\n", sizeof(struct stlpanel));
+ goto err_fr;
}
panelp->magic = STL_PANELMAGIC;
panelp->brdnr = brdp->brdnr;
@@ -2465,7 +2190,7 @@ static inline int stl_initech(stlbrd_t *brdp)
brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
if (status & ECH_PNLXPID) {
- panelp->uartp = (void *) &stl_sc26198uart;
+ panelp->uartp = &stl_sc26198uart;
panelp->isr = stl_sc26198intr;
if (status & ECH_PNL16PORT) {
panelp->nrports = 16;
@@ -2473,11 +2198,10 @@ static inline int stl_initech(stlbrd_t *brdp)
brdp->bnkpageaddr[banknr] = nxtid;
brdp->bnkstataddr[banknr++] = ioaddr + 4 +
ECH_PNLSTATUS;
- } else {
+ } else
panelp->nrports = 8;
- }
} else {
- panelp->uartp = (void *) &stl_cd1400uart;
+ panelp->uartp = &stl_cd1400uart;
panelp->isr = stl_cd1400echintr;
if (status & ECH_PNL16PORT) {
panelp->nrports = 16;
@@ -2500,7 +2224,7 @@ static inline int stl_initech(stlbrd_t *brdp)
brdp->panels[panelnr++] = panelp;
if ((brdp->brdtype != BRD_ECHPCI) &&
(ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
- break;
+ goto err_fr;
}
brdp->nrpanels = panelnr;
@@ -2512,12 +2236,19 @@ static inline int stl_initech(stlbrd_t *brdp)
if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
printk("STALLION: failed to register interrupt "
"routine for %s irq=%d\n", name, brdp->irq);
- i = -ENODEV;
- } else {
- i = 0;
+ retval = -ENODEV;
+ goto err_fr;
}
- return(i);
+ return 0;
+err_fr:
+ stl_cleanup_panels(brdp);
+ if (brdp->iosize2 > 0)
+ release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+ release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+ return retval;
}
/*****************************************************************************/
@@ -2529,48 +2260,61 @@ static inline int stl_initech(stlbrd_t *brdp)
* since the initial search and setup is very different.
*/
-static int __init stl_brdinit(stlbrd_t *brdp)
+static int __devinit stl_brdinit(struct stlbrd *brdp)
{
- int i;
+ int i, retval;
-#ifdef DEBUG
- printk("stl_brdinit(brdp=%x)\n", (int) brdp);
-#endif
+ pr_debug("stl_brdinit(brdp=%p)\n", brdp);
switch (brdp->brdtype) {
case BRD_EASYIO:
case BRD_EASYIOPCI:
- stl_initeio(brdp);
+ retval = stl_initeio(brdp);
+ if (retval)
+ goto err;
break;
case BRD_ECH:
case BRD_ECHMC:
case BRD_ECHPCI:
case BRD_ECH64PCI:
- stl_initech(brdp);
+ retval = stl_initech(brdp);
+ if (retval)
+ goto err;
break;
default:
printk("STALLION: board=%d is unknown board type=%d\n",
brdp->brdnr, brdp->brdtype);
- return(ENODEV);
+ retval = -ENODEV;
+ goto err;
}
- stl_brds[brdp->brdnr] = brdp;
if ((brdp->state & BRD_FOUND) == 0) {
printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
stl_brdnames[brdp->brdtype], brdp->brdnr,
brdp->ioaddr1, brdp->irq);
- return(ENODEV);
+ goto err_free;
}
- for (i = 0; (i < STL_MAXPANELS); i++)
- if (brdp->panels[i] != (stlpanel_t *) NULL)
+ for (i = 0; i < STL_MAXPANELS; i++)
+ if (brdp->panels[i] != NULL)
stl_initports(brdp, brdp->panels[i]);
printk("STALLION: %s found, board=%d io=%x irq=%d "
"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
brdp->nrports);
- return(0);
+
+ return 0;
+err_free:
+ free_irq(brdp->irq, brdp);
+
+ stl_cleanup_panels(brdp);
+
+ release_region(brdp->ioaddr1, brdp->iosize1);
+ if (brdp->iosize2 > 0)
+ release_region(brdp->ioaddr2, brdp->iosize2);
+err:
+ return retval;
}
/*****************************************************************************/
@@ -2579,59 +2323,62 @@ static int __init stl_brdinit(stlbrd_t *brdp)
* Find the next available board number that is free.
*/
-static inline int stl_getbrdnr(void)
+static int __devinit stl_getbrdnr(void)
{
- int i;
+ unsigned int i;
- for (i = 0; (i < STL_MAXBRDS); i++) {
- if (stl_brds[i] == (stlbrd_t *) NULL) {
+ for (i = 0; i < STL_MAXBRDS; i++)
+ if (stl_brds[i] == NULL) {
if (i >= stl_nrbrds)
stl_nrbrds = i + 1;
- return(i);
+ return i;
}
- }
- return(-1);
+
+ return -1;
}
/*****************************************************************************/
-
-#ifdef CONFIG_PCI
-
/*
* We have a Stallion board. Allocate a board structure and
* initialize it. Read its IO and IRQ resources from PCI
* configuration space.
*/
-static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
+static int __devinit stl_pciprobe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- stlbrd_t *brdp;
-
-#ifdef DEBUG
- printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
- devp->bus->number, devp->devfn);
-#endif
-
- if (pci_enable_device(devp))
- return(-EIO);
- if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
- return(-ENOMEM);
- if ((brdp->brdnr = stl_getbrdnr()) < 0) {
- printk("STALLION: too many boards found, "
+ struct stlbrd *brdp;
+ unsigned int i, brdtype = ent->driver_data;
+ int brdnr, retval = -ENODEV;
+
+ if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
+ goto err;
+
+ dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
+ pdev->vendor, pdev->device, pdev->class);
+
+ retval = pci_enable_device(pdev);
+ if (retval)
+ goto err;
+ brdp = stl_allocbrd();
+ if (brdp == NULL) {
+ retval = -ENOMEM;
+ goto err;
+ }
+ mutex_lock(&stl_brdslock);
+ brdnr = stl_getbrdnr();
+ if (brdnr < 0) {
+ dev_err(&pdev->dev, "too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
- return(0);
+ mutex_unlock(&stl_brdslock);
+ goto err_fr;
}
- brdp->brdtype = brdtype;
+ brdp->brdnr = (unsigned int)brdnr;
+ stl_brds[brdp->brdnr] = brdp;
+ mutex_unlock(&stl_brdslock);
-/*
- * Different Stallion boards use the BAR registers in different ways,
- * so set up io addresses based on board type.
- */
-#ifdef DEBUG
- printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__,
- pci_resource_start(devp, 0), pci_resource_start(devp, 1),
- pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
-#endif
+ brdp->brdtype = brdtype;
+ brdp->state |= STL_PROBED;
/*
* We have all resources from the board, so let's setup the actual
@@ -2639,120 +2386,70 @@ static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
*/
switch (brdtype) {
case BRD_ECHPCI:
- brdp->ioaddr2 = pci_resource_start(devp, 0);
- brdp->ioaddr1 = pci_resource_start(devp, 1);
+ brdp->ioaddr2 = pci_resource_start(pdev, 0);
+ brdp->ioaddr1 = pci_resource_start(pdev, 1);
break;
case BRD_ECH64PCI:
- brdp->ioaddr2 = pci_resource_start(devp, 2);
- brdp->ioaddr1 = pci_resource_start(devp, 1);
+ brdp->ioaddr2 = pci_resource_start(pdev, 2);
+ brdp->ioaddr1 = pci_resource_start(pdev, 1);
break;
case BRD_EASYIOPCI:
- brdp->ioaddr1 = pci_resource_start(devp, 2);
- brdp->ioaddr2 = pci_resource_start(devp, 1);
+ brdp->ioaddr1 = pci_resource_start(pdev, 2);
+ brdp->ioaddr2 = pci_resource_start(pdev, 1);
break;
default:
- printk("STALLION: unknown PCI board type=%d\n", brdtype);
+ dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
break;
}
- brdp->irq = devp->irq;
- stl_brdinit(brdp);
-
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Find all Stallion PCI boards that might be installed. Initialize each
- * one as it is found.
- */
-
+ brdp->irq = pdev->irq;
+ retval = stl_brdinit(brdp);
+ if (retval)
+ goto err_null;
-static inline int stl_findpcibrds(void)
-{
- struct pci_dev *dev = NULL;
- int i, rc;
-
-#ifdef DEBUG
- printk("stl_findpcibrds()\n");
-#endif
+ pci_set_drvdata(pdev, brdp);
- for (i = 0; (i < stl_nrpcibrds); i++)
- while ((dev = pci_find_device(stl_pcibrds[i].vendid,
- stl_pcibrds[i].devid, dev))) {
-
-/*
- * Found a device on the PCI bus that has our vendor and
- * device ID. Need to check now that it is really us.
- */
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
- continue;
-
- rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
- if (rc)
- return(rc);
- }
+ for (i = 0; i < brdp->nrports; i++)
+ tty_register_device(stl_serial,
+ brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
- return(0);
+ return 0;
+err_null:
+ stl_brds[brdp->brdnr] = NULL;
+err_fr:
+ kfree(brdp);
+err:
+ return retval;
}
-#endif
-
-/*****************************************************************************/
-
-/*
- * Scan through all the boards in the configuration and see what we
- * can find. Handle EIO and the ECH boards a little differently here
- * since the initial search and setup is too different.
- */
-
-static inline int stl_initbrds(void)
+static void __devexit stl_pciremove(struct pci_dev *pdev)
{
- stlbrd_t *brdp;
- stlconf_t *confp;
- int i;
+ struct stlbrd *brdp = pci_get_drvdata(pdev);
+ unsigned int i;
-#ifdef DEBUG
- printk("stl_initbrds()\n");
-#endif
+ free_irq(brdp->irq, brdp);
- if (stl_nrbrds > STL_MAXBRDS) {
- printk("STALLION: too many boards in configuration table, "
- "truncating to %d\n", STL_MAXBRDS);
- stl_nrbrds = STL_MAXBRDS;
- }
+ stl_cleanup_panels(brdp);
-/*
- * Firstly scan the list of static boards configured. Allocate
- * resources and initialize the boards as found.
- */
- for (i = 0; (i < stl_nrbrds); i++) {
- confp = &stl_brdconf[i];
- stl_parsebrd(confp, stl_brdsp[i]);
- if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
- return(-ENOMEM);
- brdp->brdnr = i;
- brdp->brdtype = confp->brdtype;
- brdp->ioaddr1 = confp->ioaddr1;
- brdp->ioaddr2 = confp->ioaddr2;
- brdp->irq = confp->irq;
- brdp->irqtype = confp->irqtype;
- stl_brdinit(brdp);
- }
+ release_region(brdp->ioaddr1, brdp->iosize1);
+ if (brdp->iosize2 > 0)
+ release_region(brdp->ioaddr2, brdp->iosize2);
-/*
- * Find any dynamically supported boards. That is via module load
- * line options or auto-detected on the PCI bus.
- */
- stl_argbrds();
-#ifdef CONFIG_PCI
- stl_findpcibrds();
-#endif
+ for (i = 0; i < brdp->nrports; i++)
+ tty_unregister_device(stl_serial,
+ brdp->brdnr * STL_MAXPORTS + i);
- return(0);
+ stl_brds[brdp->brdnr] = NULL;
+ kfree(brdp);
}
+static struct pci_driver stl_pcidriver = {
+ .name = "stallion",
+ .id_table = stl_pcibrds,
+ .probe = stl_pciprobe,
+ .remove = __devexit_p(stl_pciremove)
+};
+
/*****************************************************************************/
/*
@@ -2761,17 +2458,18 @@ static inline int stl_initbrds(void)
static int stl_getbrdstats(combrd_t __user *bp)
{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
- int i;
+ combrd_t stl_brdstats;
+ struct stlbrd *brdp;
+ struct stlpanel *panelp;
+ unsigned int i;
if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
return -EFAULT;
if (stl_brdstats.brd >= STL_MAXBRDS)
- return(-ENODEV);
+ return -ENODEV;
brdp = stl_brds[stl_brdstats.brd];
- if (brdp == (stlbrd_t *) NULL)
- return(-ENODEV);
+ if (brdp == NULL)
+ return -ENODEV;
memset(&stl_brdstats, 0, sizeof(combrd_t));
stl_brdstats.brd = brdp->brdnr;
@@ -2783,7 +2481,7 @@ static int stl_getbrdstats(combrd_t __user *bp)
stl_brdstats.irq = brdp->irq;
stl_brdstats.nrpanels = brdp->nrpanels;
stl_brdstats.nrports = brdp->nrports;
- for (i = 0; (i < brdp->nrpanels); i++) {
+ for (i = 0; i < brdp->nrpanels; i++) {
panelp = brdp->panels[i];
stl_brdstats.panels[i].panel = i;
stl_brdstats.panels[i].hwid = panelp->hwid;
@@ -2799,24 +2497,24 @@ static int stl_getbrdstats(combrd_t __user *bp)
* Resolve the referenced port number into a port struct pointer.
*/
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
+static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
+ struct stlbrd *brdp;
+ struct stlpanel *panelp;
- if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
- return((stlport_t *) NULL);
+ if (brdnr < 0 || brdnr >= STL_MAXBRDS)
+ return NULL;
brdp = stl_brds[brdnr];
- if (brdp == (stlbrd_t *) NULL)
- return((stlport_t *) NULL);
- if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
- return((stlport_t *) NULL);
+ if (brdp == NULL)
+ return NULL;
+ if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
+ return NULL;
panelp = brdp->panels[panelnr];
- if (panelp == (stlpanel_t *) NULL)
- return((stlport_t *) NULL);
- if ((portnr < 0) || (portnr >= panelp->nrports))
- return((stlport_t *) NULL);
- return(panelp->ports[portnr]);
+ if (panelp == NULL)
+ return NULL;
+ if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
+ return NULL;
+ return panelp->ports[portnr];
}
/*****************************************************************************/
@@ -2827,8 +2525,9 @@ static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
* what port to get stats for (used through board control device).
*/
-static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
+static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
{
+ comstats_t stl_comstats;
unsigned char *head, *tail;
unsigned long flags;
@@ -2837,8 +2536,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
return -EFAULT;
portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
stl_comstats.port);
- if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ if (portp == NULL)
+ return -ENODEV;
}
portp->stats.state = portp->istate;
@@ -2853,25 +2552,24 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
portp->stats.rxbuffered = 0;
spin_lock_irqsave(&stallion_lock, flags);
- if (portp->tty != (struct tty_struct *) NULL) {
+ if (portp->tty != NULL)
if (portp->tty->driver_data == portp) {
portp->stats.ttystate = portp->tty->flags;
/* No longer available as a statistic */
portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
- if (portp->tty->termios != (struct termios *) NULL) {
+ if (portp->tty->termios != NULL) {
portp->stats.cflags = portp->tty->termios->c_cflag;
portp->stats.iflags = portp->tty->termios->c_iflag;
portp->stats.oflags = portp->tty->termios->c_oflag;
portp->stats.lflags = portp->tty->termios->c_lflag;
}
}
- }
spin_unlock_irqrestore(&stallion_lock, flags);
head = portp->tx.head;
tail = portp->tx.tail;
- portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
- (STL_TXBUFSIZE - (tail - head)));
+ portp->stats.txbuffered = (head >= tail) ? (head - tail) :
+ (STL_TXBUFSIZE - (tail - head));
portp->stats.signals = (unsigned long) stl_getsignals(portp);
@@ -2885,15 +2583,17 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
* Clear the port stats structure. We also return it zeroed out...
*/
-static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp)
+static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
{
+ comstats_t stl_comstats;
+
if (!portp) {
if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
return -EFAULT;
portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
stl_comstats.port);
- if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ if (portp == NULL)
+ return -ENODEV;
}
memset(&portp->stats, 0, sizeof(comstats_t));
@@ -2910,17 +2610,18 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp)
* Return the entire driver ports structure to a user app.
*/
-static int stl_getportstruct(stlport_t __user *arg)
+static int stl_getportstruct(struct stlport __user *arg)
{
- stlport_t *portp;
+ struct stlport stl_dummyport;
+ struct stlport *portp;
- if (copy_from_user(&stl_dummyport, arg, sizeof(stlport_t)))
+ if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
return -EFAULT;
portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
stl_dummyport.portnr);
if (!portp)
return -ENODEV;
- return copy_to_user(arg, portp, sizeof(stlport_t)) ? -EFAULT : 0;
+ return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
}
/*****************************************************************************/
@@ -2929,18 +2630,19 @@ static int stl_getportstruct(stlport_t __user *arg)
* Return the entire driver board structure to a user app.
*/
-static int stl_getbrdstruct(stlbrd_t __user *arg)
+static int stl_getbrdstruct(struct stlbrd __user *arg)
{
- stlbrd_t *brdp;
+ struct stlbrd stl_dummybrd;
+ struct stlbrd *brdp;
- if (copy_from_user(&stl_dummybrd, arg, sizeof(stlbrd_t)))
+ if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
return -EFAULT;
- if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
+ if (stl_dummybrd.brdnr >= STL_MAXBRDS)
return -ENODEV;
brdp = stl_brds[stl_dummybrd.brdnr];
if (!brdp)
- return(-ENODEV);
- return copy_to_user(arg, brdp, sizeof(stlbrd_t)) ? -EFAULT : 0;
+ return -ENODEV;
+ return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
}
/*****************************************************************************/
@@ -2956,14 +2658,11 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
int brdnr, rc;
void __user *argp = (void __user *)arg;
-#ifdef DEBUG
- printk("stl_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip,
- (int) fp, cmd, (int) arg);
-#endif
+ pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
brdnr = iminor(ip);
if (brdnr >= STL_MAXBRDS)
- return(-ENODEV);
+ return -ENODEV;
rc = 0;
switch (cmd) {
@@ -2987,7 +2686,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
break;
}
- return(rc);
+ return rc;
}
static const struct tty_operations stl_ops = {
@@ -3015,55 +2714,6 @@ static const struct tty_operations stl_ops = {
};
/*****************************************************************************/
-
-static int __init stl_init(void)
-{
- int i;
- printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
- spin_lock_init(&stallion_lock);
- spin_lock_init(&brd_lock);
-
- stl_initbrds();
-
- stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
- if (!stl_serial)
- return -1;
-
-/*
- * Set up a character driver for per board stuff. This is mainly used
- * to do stats ioctls on the ports.
- */
- if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
- printk("STALLION: failed to register serial board device\n");
-
- stallion_class = class_create(THIS_MODULE, "staliomem");
- for (i = 0; i < 4; i++)
- class_device_create(stallion_class, NULL,
- MKDEV(STL_SIOMEMMAJOR, i), NULL,
- "staliomem%d", i);
-
- stl_serial->owner = THIS_MODULE;
- stl_serial->driver_name = stl_drvname;
- stl_serial->name = "ttyE";
- stl_serial->major = STL_SERIALMAJOR;
- stl_serial->minor_start = 0;
- stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
- stl_serial->subtype = SERIAL_TYPE_NORMAL;
- stl_serial->init_termios = stl_deftermios;
- stl_serial->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(stl_serial, &stl_ops);
-
- if (tty_register_driver(stl_serial)) {
- put_tty_driver(stl_serial);
- printk("STALLION: failed to register serial driver\n");
- return -1;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
/* CD1400 HARDWARE FUNCTIONS */
/*****************************************************************************/
@@ -3073,21 +2723,21 @@ static int __init stl_init(void)
* (Maybe should make this inline...)
*/
-static int stl_cd1400getreg(stlport_t *portp, int regnr)
+static int stl_cd1400getreg(struct stlport *portp, int regnr)
{
outb((regnr + portp->uartaddr), portp->ioaddr);
return inb(portp->ioaddr + EREG_DATA);
}
-static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
+static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
{
- outb((regnr + portp->uartaddr), portp->ioaddr);
+ outb(regnr + portp->uartaddr, portp->ioaddr);
outb(value, portp->ioaddr + EREG_DATA);
}
-static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
+static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
{
- outb((regnr + portp->uartaddr), portp->ioaddr);
+ outb(regnr + portp->uartaddr, portp->ioaddr);
if (inb(portp->ioaddr + EREG_DATA) != value) {
outb(value, portp->ioaddr + EREG_DATA);
return 1;
@@ -3103,16 +2753,14 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
* identical when dealing with ports.
*/
-static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
+static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
{
unsigned int gfrcr;
int chipmask, i, j;
int nrchips, uartaddr, ioaddr;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
-#endif
+ pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(panelp->brdnr, panelp->pagenr);
@@ -3122,13 +2770,12 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
*/
chipmask = 0;
nrchips = panelp->nrports / CD1400_PORTS;
- for (i = 0; (i < nrchips); i++) {
+ for (i = 0; i < nrchips; i++) {
if (brdp->brdtype == BRD_ECHPCI) {
outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
ioaddr = panelp->iobase;
- } else {
+ } else
ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
- }
uartaddr = (i & 0x01) ? 0x080 : 0;
outb((GFRCR + uartaddr), ioaddr);
outb(0, (ioaddr + EREG_DATA));
@@ -3136,10 +2783,10 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
outb((GFRCR + uartaddr), ioaddr);
- for (j = 0; (j < CCR_MAXWAIT); j++) {
+ for (j = 0; j < CCR_MAXWAIT; j++)
if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
break;
- }
+
if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
printk("STALLION: cd1400 not responding, "
"brd=%d panel=%d chip=%d\n",
@@ -3162,16 +2809,14 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
* Initialize hardware specific port registers.
*/
-static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
+static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
- (int) brdp, (int) panelp, (int) portp);
-#endif
+ pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
+ panelp, portp);
- if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) ||
- (portp == (stlport_t *) NULL))
+ if ((brdp == NULL) || (panelp == NULL) ||
+ (portp == NULL))
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -3195,15 +2840,13 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po
* since it won't usually take too long to be ready.
*/
-static void stl_cd1400ccrwait(stlport_t *portp)
+static void stl_cd1400ccrwait(struct stlport *portp)
{
int i;
- for (i = 0; (i < CCR_MAXWAIT); i++) {
- if (stl_cd1400getreg(portp, CCR) == 0) {
+ for (i = 0; i < CCR_MAXWAIT; i++)
+ if (stl_cd1400getreg(portp, CCR) == 0)
return;
- }
- }
printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
portp->portnr, portp->panelnr, portp->brdnr);
@@ -3216,9 +2859,9 @@ static void stl_cd1400ccrwait(stlport_t *portp)
* settings.
*/
-static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
+static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
{
- stlbrd_t *brdp;
+ struct stlbrd *brdp;
unsigned long flags;
unsigned int clkdiv, baudrate;
unsigned char cor1, cor2, cor3;
@@ -3242,7 +2885,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
sreroff = 0;
brdp = stl_brds[portp->brdnr];
- if (brdp == (stlbrd_t *) NULL)
+ if (brdp == NULL)
return;
/*
@@ -3339,8 +2982,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
baudrate = STL_CD1400MAXBAUD;
if (baudrate > 0) {
- for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
- clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
+ for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
+ clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
if (clkdiv < 0x100)
break;
}
@@ -3355,9 +2998,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
mcor2 |= MCOR2_DCD;
sreron |= SRER_MODEM;
portp->flags |= ASYNC_CHECK_CD;
- } else {
+ } else
portp->flags &= ~ASYNC_CHECK_CD;
- }
/*
* Setup cd1400 enhanced modes if we can. In particular we want to
@@ -3382,18 +3024,16 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
* them all up.
*/
-#ifdef DEBUG
- printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
+ pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
portp->portnr, portp->panelnr, portp->brdnr);
- printk(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
+ pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
cor1, cor2, cor3, cor4, cor5);
- printk(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
+ pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
mcor1, mcor2, rtpr, sreron, sreroff);
- printk(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
- printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
+ pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
+ pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-#endif
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
@@ -3441,15 +3081,13 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
* Set the state of the DTR and RTS signals.
*/
-static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
+static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
{
unsigned char msvr1, msvr2;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n",
- (int) portp, dtr, rts);
-#endif
+ pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
+ portp, dtr, rts);
msvr1 = 0;
msvr2 = 0;
@@ -3475,15 +3113,13 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
* Return the state of the signals.
*/
-static int stl_cd1400getsignals(stlport_t *portp)
+static int stl_cd1400getsignals(struct stlport *portp)
{
unsigned char msvr1, msvr2;
unsigned long flags;
int sigs;
-#ifdef DEBUG
- printk("stl_cd1400getsignals(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
@@ -3513,15 +3149,13 @@ static int stl_cd1400getsignals(stlport_t *portp)
* Enable/Disable the Transmitter and/or Receiver.
*/
-static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
+static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
{
unsigned char ccr;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n",
- (int) portp, rx, tx);
-#endif
+ pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
+
ccr = 0;
if (tx == 0)
@@ -3549,15 +3183,12 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
* Start/stop the Transmitter and/or Receiver.
*/
-static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
+static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
{
unsigned char sreron, sreroff;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n",
- (int) portp, rx, tx);
-#endif
+ pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
sreron = 0;
sreroff = 0;
@@ -3589,13 +3220,12 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
* Disable all interrupts from this port.
*/
-static void stl_cd1400disableintrs(stlport_t *portp)
+static void stl_cd1400disableintrs(struct stlport *portp)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
+
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
@@ -3606,13 +3236,11 @@ static void stl_cd1400disableintrs(stlport_t *portp)
/*****************************************************************************/
-static void stl_cd1400sendbreak(stlport_t *portp, int len)
+static void stl_cd1400sendbreak(struct stlport *portp, int len)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len);
-#endif
+ pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
@@ -3633,19 +3261,17 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len)
* Take flow control actions...
*/
-static void stl_cd1400flowctrl(stlport_t *portp, int state)
+static void stl_cd1400flowctrl(struct stlport *portp, int state)
{
struct tty_struct *tty;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400flowctrl(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+ pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
tty = portp->tty;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -3697,19 +3323,17 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state)
* Send a flow control character...
*/
-static void stl_cd1400sendflow(stlport_t *portp, int state)
+static void stl_cd1400sendflow(struct stlport *portp, int state)
{
struct tty_struct *tty;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400sendflow(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+ pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
tty = portp->tty;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -3732,15 +3356,13 @@ static void stl_cd1400sendflow(stlport_t *portp, int state)
/*****************************************************************************/
-static void stl_cd1400flush(stlport_t *portp)
+static void stl_cd1400flush(struct stlport *portp)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_cd1400flush(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_cd1400flush(portp=%p)\n", portp);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -3763,13 +3385,11 @@ static void stl_cd1400flush(stlport_t *portp)
* maintains the busy port flag.
*/
-static int stl_cd1400datastate(stlport_t *portp)
+static int stl_cd1400datastate(struct stlport *portp)
{
-#ifdef DEBUG
- printk("stl_cd1400datastate(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return 0;
return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
@@ -3781,14 +3401,11 @@ static int stl_cd1400datastate(stlport_t *portp)
* Interrupt service routine for cd1400 EasyIO boards.
*/
-static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
+static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
{
unsigned char svrtype;
-#ifdef DEBUG
- printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n",
- (int) panelp, iobase);
-#endif
+ pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
spin_lock(&brd_lock);
outb(SVRR, iobase);
@@ -3814,14 +3431,11 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
* Interrupt service routine for cd1400 panels.
*/
-static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
+static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
{
unsigned char svrtype;
-#ifdef DEBUG
- printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp,
- iobase);
-#endif
+ pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
outb(SVRR, iobase);
svrtype = inb(iobase + EREG_DATA);
@@ -3843,7 +3457,7 @@ static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
* this is the only way to generate them on the cd1400.
*/
-static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
+static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
{
if (portp->brklen == 1) {
outb((COR2 + portp->uartaddr), ioaddr);
@@ -3885,16 +3499,14 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
* be NULL if the buffer has been freed.
*/
-static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
+static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
{
- stlport_t *portp;
+ struct stlport *portp;
int len, stlen;
char *head, *tail;
unsigned char ioack, srer;
-#ifdef DEBUG
- printk("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
+ pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
ioack = inb(ioaddr + EREG_TXACK);
if (((ioack & panelp->ackmask) != 0) ||
@@ -3933,9 +3545,9 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
}
outb(srer, (ioaddr + EREG_DATA));
} else {
- len = MIN(len, CD1400_TXFIFOSIZE);
+ len = min(len, CD1400_TXFIFOSIZE);
portp->stats.txtotal += len;
- stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
+ stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
outb((TDR + portp->uartaddr), ioaddr);
outsb((ioaddr + EREG_DATA), tail, stlen);
len -= stlen;
@@ -3966,17 +3578,15 @@ stl_txalldone:
* shutdown a port not in user context. Need to handle this case.
*/
-static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
+static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
{
- stlport_t *portp;
+ struct stlport *portp;
struct tty_struct *tty;
unsigned int ioack, len, buflen;
unsigned char status;
char ch;
-#ifdef DEBUG
- printk("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
+ pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
ioack = inb(ioaddr + EREG_RXACK);
if ((ioack & panelp->ackmask) != 0) {
@@ -3990,13 +3600,13 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
outb((RDCR + portp->uartaddr), ioaddr);
len = inb(ioaddr + EREG_DATA);
if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
- len = MIN(len, sizeof(stl_unwanted));
+ len = min(len, sizeof(stl_unwanted));
outb((RDSR + portp->uartaddr), ioaddr);
insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
portp->stats.rxlost += len;
portp->stats.rxtotal += len;
} else {
- len = MIN(len, buflen);
+ len = min(len, buflen);
if (len > 0) {
unsigned char *ptr;
outb((RDSR + portp->uartaddr), ioaddr);
@@ -4033,18 +3643,16 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
do_SAK(tty);
BRDENABLE(portp->brdnr, portp->pagenr);
}
- } else if (status & ST_PARITY) {
+ } else if (status & ST_PARITY)
status = TTY_PARITY;
- } else if (status & ST_FRAMING) {
+ else if (status & ST_FRAMING)
status = TTY_FRAME;
- } else if(status & ST_OVERRUN) {
+ else if(status & ST_OVERRUN)
status = TTY_OVERRUN;
- } else {
+ else
status = 0;
- }
- } else {
+ } else
status = 0;
- }
tty_insert_flip_char(tty, ch, status);
tty_schedule_flip(tty);
}
@@ -4066,15 +3674,13 @@ stl_rxalldone:
* processing routine.
*/
-static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
+static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned int ioack;
unsigned char misr;
-#ifdef DEBUG
- printk("stl_cd1400mdmisr(panelp=%x)\n", (int) panelp);
-#endif
+ pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
ioack = inb(ioaddr + EREG_MDACK);
if (((ioack & panelp->ackmask) != 0) ||
@@ -4106,19 +3712,19 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
* (Maybe should make this inline...)
*/
-static int stl_sc26198getreg(stlport_t *portp, int regnr)
+static int stl_sc26198getreg(struct stlport *portp, int regnr)
{
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
return inb(portp->ioaddr + XP_DATA);
}
-static void stl_sc26198setreg(stlport_t *portp, int regnr, int value)
+static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
{
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
outb(value, (portp->ioaddr + XP_DATA));
}
-static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
+static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
{
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
if (inb(portp->ioaddr + XP_DATA) != value) {
@@ -4134,14 +3740,14 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
* Functions to get and set the sc26198 global registers.
*/
-static int stl_sc26198getglobreg(stlport_t *portp, int regnr)
+static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
{
outb(regnr, (portp->ioaddr + XP_ADDR));
return inb(portp->ioaddr + XP_DATA);
}
#if 0
-static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value)
+static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
{
outb(regnr, (portp->ioaddr + XP_ADDR));
outb(value, (portp->ioaddr + XP_DATA));
@@ -4156,15 +3762,12 @@ static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value)
* identical when dealing with ports.
*/
-static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
+static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
{
int chipmask, i;
int nrchips, ioaddr;
-#ifdef DEBUG
- printk("stl_sc26198panelinit(brdp=%x,panelp=%x)\n",
- (int) brdp, (int) panelp);
-#endif
+ pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
BRDENABLE(panelp->brdnr, panelp->pagenr);
@@ -4176,7 +3779,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
if (brdp->brdtype == BRD_ECHPCI)
outb(panelp->pagenr, brdp->ioctrl);
- for (i = 0; (i < nrchips); i++) {
+ for (i = 0; i < nrchips; i++) {
ioaddr = panelp->iobase + (i * 4);
outb(SCCR, (ioaddr + XP_ADDR));
outb(CR_RESETALL, (ioaddr + XP_DATA));
@@ -4204,15 +3807,13 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
* Initialize hardware specific port registers.
*/
-static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
+static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
{
-#ifdef DEBUG
- printk("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n",
- (int) brdp, (int) panelp, (int) portp);
-#endif
+ pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
+ panelp, portp);
- if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) ||
- (portp == (stlport_t *) NULL))
+ if ((brdp == NULL) || (panelp == NULL) ||
+ (portp == NULL))
return;
portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
@@ -4232,9 +3833,9 @@ static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *p
* settings.
*/
-static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
+static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
{
- stlbrd_t *brdp;
+ struct stlbrd *brdp;
unsigned long flags;
unsigned int baudrate;
unsigned char mr0, mr1, mr2, clk;
@@ -4249,7 +3850,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
imroff = 0;
brdp = stl_brds[portp->brdnr];
- if (brdp == (stlbrd_t *) NULL)
+ if (brdp == NULL)
return;
/*
@@ -4298,9 +3899,8 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
mr1 |= (MR1_PARENB | MR1_PARODD);
else
mr1 |= (MR1_PARENB | MR1_PAREVEN);
- } else {
+ } else
mr1 |= MR1_PARNONE;
- }
mr1 |= MR1_ERRBLOCK;
@@ -4340,12 +3940,10 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
if (baudrate > STL_SC26198MAXBAUD)
baudrate = STL_SC26198MAXBAUD;
- if (baudrate > 0) {
- for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
+ if (baudrate > 0)
+ for (clk = 0; clk < SC26198_NRBAUDS; clk++)
if (baudrate <= sc26198_baudtable[clk])
break;
- }
- }
/*
* Check what form of modem signaling is required and set it up.
@@ -4367,9 +3965,9 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
if (tiosp->c_iflag & IXON) {
mr0 |= MR0_SWFTX | MR0_SWFT;
imron |= IR_XONXOFF;
- } else {
+ } else
imroff |= IR_XONXOFF;
- }
+
if (tiosp->c_iflag & IXOFF)
mr0 |= MR0_SWFRX;
@@ -4383,15 +3981,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
* them all up.
*/
-#ifdef DEBUG
- printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
+ pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
portp->portnr, portp->panelnr, portp->brdnr);
- printk(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
- printk(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
- printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
+ pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
+ pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
+ pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-#endif
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
@@ -4429,15 +4025,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
* Set the state of the DTR and RTS signals.
*/
-static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
+static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
{
unsigned char iopioron, iopioroff;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n",
- (int) portp, dtr, rts);
-#endif
+ pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
+ dtr, rts);
iopioron = 0;
iopioroff = 0;
@@ -4464,15 +4058,13 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
* Return the state of the signals.
*/
-static int stl_sc26198getsignals(stlport_t *portp)
+static int stl_sc26198getsignals(struct stlport *portp)
{
unsigned char ipr;
unsigned long flags;
int sigs;
-#ifdef DEBUG
- printk("stl_sc26198getsignals(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
@@ -4495,15 +4087,12 @@ static int stl_sc26198getsignals(stlport_t *portp)
* Enable/Disable the Transmitter and/or Receiver.
*/
-static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
+static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
{
unsigned char ccr;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n",
- (int) portp, rx, tx);
-#endif
+ pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
ccr = portp->crenable;
if (tx == 0)
@@ -4529,15 +4118,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
* Start/stop the Transmitter and/or Receiver.
*/
-static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
+static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
{
unsigned char imr;
unsigned long flags;
-#ifdef DEBUG
- printk("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n",
- (int) portp, rx, tx);
-#endif
+ pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
imr = portp->imr;
if (tx == 0)
@@ -4565,13 +4151,11 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
* Disable all interrupts from this port.
*/
-static void stl_sc26198disableintrs(stlport_t *portp)
+static void stl_sc26198disableintrs(struct stlport *portp)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
@@ -4583,22 +4167,20 @@ static void stl_sc26198disableintrs(stlport_t *portp)
/*****************************************************************************/
-static void stl_sc26198sendbreak(stlport_t *portp, int len)
+static void stl_sc26198sendbreak(struct stlport *portp, int len)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len);
-#endif
+ pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(portp->brdnr, portp->pagenr);
if (len == 1) {
stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
portp->stats.txbreaks++;
- } else {
+ } else
stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
- }
+
BRDDISABLE(portp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
}
@@ -4609,20 +4191,18 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len)
* Take flow control actions...
*/
-static void stl_sc26198flowctrl(stlport_t *portp, int state)
+static void stl_sc26198flowctrl(struct stlport *portp, int state)
{
struct tty_struct *tty;
unsigned long flags;
unsigned char mr0;
-#ifdef DEBUG
- printk("stl_sc26198flowctrl(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+ pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
tty = portp->tty;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -4680,20 +4260,18 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state)
* Send a flow control character.
*/
-static void stl_sc26198sendflow(stlport_t *portp, int state)
+static void stl_sc26198sendflow(struct stlport *portp, int state)
{
struct tty_struct *tty;
unsigned long flags;
unsigned char mr0;
-#ifdef DEBUG
- printk("stl_sc26198sendflow(portp=%x,state=%x)\n", (int) portp, state);
-#endif
+ pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
tty = portp->tty;
- if (tty == (struct tty_struct *) NULL)
+ if (tty == NULL)
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -4721,15 +4299,13 @@ static void stl_sc26198sendflow(stlport_t *portp, int state)
/*****************************************************************************/
-static void stl_sc26198flush(stlport_t *portp)
+static void stl_sc26198flush(struct stlport *portp)
{
unsigned long flags;
-#ifdef DEBUG
- printk("stl_sc26198flush(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_sc26198flush(portp=%p)\n", portp);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
spin_lock_irqsave(&brd_lock, flags);
@@ -4751,16 +4327,14 @@ static void stl_sc26198flush(stlport_t *portp)
* check the port statusy register to be sure.
*/
-static int stl_sc26198datastate(stlport_t *portp)
+static int stl_sc26198datastate(struct stlport *portp)
{
unsigned long flags;
unsigned char sr;
-#ifdef DEBUG
- printk("stl_sc26198datastate(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return 0;
if (test_bit(ASYI_TXBUSY, &portp->istate))
return 1;
@@ -4781,18 +4355,16 @@ static int stl_sc26198datastate(stlport_t *portp)
* to process a command...
*/
-static void stl_sc26198wait(stlport_t *portp)
+static void stl_sc26198wait(struct stlport *portp)
{
int i;
-#ifdef DEBUG
- printk("stl_sc26198wait(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_sc26198wait(portp=%p)\n", portp);
- if (portp == (stlport_t *) NULL)
+ if (portp == NULL)
return;
- for (i = 0; (i < 20); i++)
+ for (i = 0; i < 20; i++)
stl_sc26198getglobreg(portp, TSTR);
}
@@ -4804,7 +4376,7 @@ static void stl_sc26198wait(stlport_t *portp)
* automatic flow control modes of the sc26198.
*/
-static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty)
+static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
{
unsigned char mr0;
@@ -4822,9 +4394,9 @@ static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty)
* Interrupt service routine for sc26198 panels.
*/
-static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
+static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
{
- stlport_t *portp;
+ struct stlport *portp;
unsigned int iack;
spin_lock(&brd_lock);
@@ -4860,16 +4432,14 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
* be NULL if the buffer has been freed.
*/
-static void stl_sc26198txisr(stlport_t *portp)
+static void stl_sc26198txisr(struct stlport *portp)
{
unsigned int ioaddr;
unsigned char mr0;
int len, stlen;
char *head, *tail;
-#ifdef DEBUG
- printk("stl_sc26198txisr(portp=%x)\n", (int) portp);
-#endif
+ pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
ioaddr = portp->ioaddr;
head = portp->tx.head;
@@ -4894,9 +4464,9 @@ static void stl_sc26198txisr(stlport_t *portp)
outb(mr0, (ioaddr + XP_DATA));
}
} else {
- len = MIN(len, SC26198_TXFIFOSIZE);
+ len = min(len, SC26198_TXFIFOSIZE);
portp->stats.txtotal += len;
- stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
+ stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
outb(GTXFIFO, (ioaddr + XP_ADDR));
outsb((ioaddr + XP_DATA), tail, stlen);
len -= stlen;
@@ -4923,14 +4493,12 @@ static void stl_sc26198txisr(stlport_t *portp)
* shutdown a port not in user context. Need to handle this case.
*/
-static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
+static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
{
struct tty_struct *tty;
unsigned int len, buflen, ioaddr;
-#ifdef DEBUG
- printk("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack);
-#endif
+ pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
tty = portp->tty;
ioaddr = portp->ioaddr;
@@ -4939,13 +4507,13 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
- len = MIN(len, sizeof(stl_unwanted));
+ len = min(len, sizeof(stl_unwanted));
outb(GRXFIFO, (ioaddr + XP_ADDR));
insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
portp->stats.rxlost += len;
portp->stats.rxtotal += len;
} else {
- len = MIN(len, buflen);
+ len = min(len, buflen);
if (len > 0) {
unsigned char *ptr;
outb(GRXFIFO, (ioaddr + XP_ADDR));
@@ -4965,8 +4533,8 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
* flow control modes of the sc26198.
*/
if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
- if ((tty != (struct tty_struct *) NULL) &&
- (tty->termios != (struct termios *) NULL) &&
+ if ((tty != NULL) &&
+ (tty->termios != NULL) &&
(tty->termios->c_iflag & IXANY)) {
stl_sc26198txunflow(portp, tty);
}
@@ -4979,7 +4547,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
* Process an RX bad character.
*/
-static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch)
+static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
{
struct tty_struct *tty;
unsigned int ioaddr;
@@ -4996,7 +4564,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
if (status & SR_RXBREAK)
portp->stats.rxbreaks++;
- if ((tty != (struct tty_struct *) NULL) &&
+ if ((tty != NULL) &&
((portp->rxignoremsk & status) == 0)) {
if (portp->rxmarkmsk & status) {
if (status & SR_RXBREAK) {
@@ -5005,18 +4573,16 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
do_SAK(tty);
BRDENABLE(portp->brdnr, portp->pagenr);
}
- } else if (status & SR_RXPARITY) {
+ } else if (status & SR_RXPARITY)
status = TTY_PARITY;
- } else if (status & SR_RXFRAMING) {
+ else if (status & SR_RXFRAMING)
status = TTY_FRAME;
- } else if(status & SR_RXOVERRUN) {
+ else if(status & SR_RXOVERRUN)
status = TTY_OVERRUN;
- } else {
+ else
status = 0;
- }
- } else {
+ } else
status = 0;
- }
tty_insert_flip_char(tty, ch, status);
tty_schedule_flip(tty);
@@ -5037,7 +4603,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
* the FIFO).
*/
-static void stl_sc26198rxbadchars(stlport_t *portp)
+static void stl_sc26198rxbadchars(struct stlport *portp)
{
unsigned char status, mr1;
char ch;
@@ -5070,13 +4636,11 @@ static void stl_sc26198rxbadchars(stlport_t *portp)
* processing time.
*/
-static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
+static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
{
unsigned char cir, ipr, xisr;
-#ifdef DEBUG
- printk("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack);
-#endif
+ pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
cir = stl_sc26198getglobreg(portp, CIR);
@@ -5109,4 +4673,172 @@ static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
}
}
-/*****************************************************************************/
+static void stl_free_isabrds(void)
+{
+ struct stlbrd *brdp;
+ unsigned int i;
+
+ for (i = 0; i < stl_nrbrds; i++) {
+ if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
+ continue;
+
+ free_irq(brdp->irq, brdp);
+
+ stl_cleanup_panels(brdp);
+
+ release_region(brdp->ioaddr1, brdp->iosize1);
+ if (brdp->iosize2 > 0)
+ release_region(brdp->ioaddr2, brdp->iosize2);
+
+ kfree(brdp);
+ stl_brds[i] = NULL;
+ }
+}
+
+/*
+ * Loadable module initialization stuff.
+ */
+static int __init stallion_module_init(void)
+{
+ struct stlbrd *brdp;
+ struct stlconf conf;
+ unsigned int i, j;
+ int retval;
+
+ printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
+
+ spin_lock_init(&stallion_lock);
+ spin_lock_init(&brd_lock);
+
+/*
+ * Find any dynamically supported boards. That is via module load
+ * line options.
+ */
+ for (i = stl_nrbrds; i < stl_nargs; i++) {
+ memset(&conf, 0, sizeof(conf));
+ if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
+ continue;
+ if ((brdp = stl_allocbrd()) == NULL)
+ continue;
+ brdp->brdnr = i;
+ brdp->brdtype = conf.brdtype;
+ brdp->ioaddr1 = conf.ioaddr1;
+ brdp->ioaddr2 = conf.ioaddr2;
+ brdp->irq = conf.irq;
+ brdp->irqtype = conf.irqtype;
+ if (stl_brdinit(brdp))
+ kfree(brdp);
+ else {
+ for (j = 0; j < brdp->nrports; j++)
+ tty_register_device(stl_serial,
+ brdp->brdnr * STL_MAXPORTS + j, NULL);
+ stl_brds[brdp->brdnr] = brdp;
+ stl_nrbrds = i + 1;
+ }
+ }
+
+ /* this has to be _after_ isa finding because of locking */
+ retval = pci_register_driver(&stl_pcidriver);
+ if (retval && stl_nrbrds == 0)
+ goto err;
+
+ stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+ if (!stl_serial) {
+ retval = -ENOMEM;
+ goto err_pcidr;
+ }
+
+/*
+ * Set up a character driver for per board stuff. This is mainly used
+ * to do stats ioctls on the ports.
+ */
+ if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
+ printk("STALLION: failed to register serial board device\n");
+
+ stallion_class = class_create(THIS_MODULE, "staliomem");
+ if (IS_ERR(stallion_class)) {
+ retval = PTR_ERR(stallion_class);
+ goto err_reg;
+ }
+ for (i = 0; i < 4; i++)
+ class_device_create(stallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i), NULL,
+ "staliomem%d", i);
+
+ stl_serial->owner = THIS_MODULE;
+ stl_serial->driver_name = stl_drvname;
+ stl_serial->name = "ttyE";
+ stl_serial->major = STL_SERIALMAJOR;
+ stl_serial->minor_start = 0;
+ stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+ stl_serial->subtype = SERIAL_TYPE_NORMAL;
+ stl_serial->init_termios = stl_deftermios;
+ stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(stl_serial, &stl_ops);
+
+ retval = tty_register_driver(stl_serial);
+ if (retval) {
+ printk("STALLION: failed to register serial driver\n");
+ goto err_clsdev;
+ }
+
+ return 0;
+err_clsdev:
+ for (i = 0; i < 4; i++)
+ class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
+ class_destroy(stallion_class);
+err_reg:
+ unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+ put_tty_driver(stl_serial);
+err_pcidr:
+ pci_unregister_driver(&stl_pcidriver);
+ stl_free_isabrds();
+err:
+ return retval;
+}
+
+static void __exit stallion_module_exit(void)
+{
+ struct stlbrd *brdp;
+ unsigned int i, j;
+ int retval;
+
+ pr_debug("cleanup_module()\n");
+
+ printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
+ stl_drvversion);
+
+/*
+ * Free up all allocated resources used by the ports. This includes
+ * memory and interrupts. As part of this process we will also do
+ * a hangup on every open port - to try to flush out any processes
+ * hanging onto ports.
+ */
+ for (i = 0; i < stl_nrbrds; i++) {
+ if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
+ continue;
+ for (j = 0; j < brdp->nrports; j++)
+ tty_unregister_device(stl_serial,
+ brdp->brdnr * STL_MAXPORTS + j);
+ }
+ tty_unregister_driver(stl_serial);
+ put_tty_driver(stl_serial);
+
+ for (i = 0; i < 4; i++)
+ class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
+ if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
+ printk("STALLION: failed to un-register serial memory device, "
+ "errno=%d\n", -retval);
+ class_destroy(stallion_class);
+
+ pci_unregister_driver(&stl_pcidriver);
+
+ stl_free_isabrds();
+}
+
+module_init(stallion_module_init);
+module_exit(stallion_module_exit);
+
+MODULE_AUTHOR("Greg Ungerer");
+MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index cc10af08cb0..1da92a689ae 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -32,7 +32,6 @@
* USA.
*
* Revision history:
- * $Log: sx.c,v $
* Revision 1.33 2000/03/09 10:00:00 pvdl,wolff
* - Fixed module and port counting
* - Fixed signal handling
@@ -199,9 +198,7 @@
*
* */
-
-#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $"
-#define RCS_REV "$Revision: 1.33 $"
+#define SX_VERSION 1.33
#include <linux/module.h>
#include <linux/kdev_t.h>
@@ -217,6 +214,7 @@
#include <linux/fcntl.h>
#include <linux/major.h>
#include <linux/delay.h>
+#include <linux/eisa.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -240,7 +238,6 @@
#include <linux/generic_serial.h>
#include "sx.h"
-
/* I don't think that this driver can handle more than 256 ports on
one machine. You'll have to increase the number of boards in sx.h
if you want more than 4 boards. */
@@ -249,21 +246,12 @@
#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
#endif
-#ifdef CONFIG_PCI
-static struct pci_device_id sx_pci_tbl[] = {
- { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, PCI_ANY_ID, PCI_ANY_ID },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
-#endif /* CONFIG_PCI */
-
/* Configurable options:
(Don't be too sure that it'll work if you toggle them) */
/* Am I paranoid or not ? ;-) */
#undef SX_PARANOIA_CHECK
-
/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
Hz, but it is user configurable. I don't recommend going above 1000
Hz. The interrupt ratelimit might trigger if the interrupt is
@@ -277,7 +265,6 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
interrupt. Use polling. */
#undef IRQ_RATE_LIMIT
-
#if 0
/* Not implemented */
/*
@@ -286,35 +273,33 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
*/
#define SX_REPORT_FIFO
#define SX_REPORT_OVERRUN
-#endif
-
+#endif
/* Function prototypes */
-static void sx_disable_tx_interrupts (void * ptr);
-static void sx_enable_tx_interrupts (void * ptr);
-static void sx_disable_rx_interrupts (void * ptr);
-static void sx_enable_rx_interrupts (void * ptr);
-static int sx_get_CD (void * ptr);
-static void sx_shutdown_port (void * ptr);
-static int sx_set_real_termios (void *ptr);
-static void sx_close (void *ptr);
-static int sx_chars_in_buffer (void * ptr);
-static int sx_init_board (struct sx_board *board);
-static int sx_init_portstructs (int nboards, int nports);
-static int sx_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+static void sx_disable_tx_interrupts(void *ptr);
+static void sx_enable_tx_interrupts(void *ptr);
+static void sx_disable_rx_interrupts(void *ptr);
+static void sx_enable_rx_interrupts(void *ptr);
+static int sx_get_CD(void *ptr);
+static void sx_shutdown_port(void *ptr);
+static int sx_set_real_termios(void *ptr);
+static void sx_close(void *ptr);
+static int sx_chars_in_buffer(void *ptr);
+static int sx_init_board(struct sx_board *board);
+static int sx_init_portstructs(int nboards, int nports);
+static int sx_fw_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
static int sx_init_drivers(void);
-
static struct tty_driver *sx_driver;
+static DEFINE_MUTEX(sx_boards_lock);
static struct sx_board boards[SX_NBOARDS];
static struct sx_port *sx_ports;
static int sx_initialized;
static int sx_nports;
static int sx_debug;
-
/* You can have the driver poll your card.
- Set sx_poll to 1 to poll every timer tick (10ms on Intel).
This is used when the card cannot use an interrupt for some reason.
@@ -333,27 +318,36 @@ static int sx_slowpoll;
static int sx_maxints = 100;
+#ifdef CONFIG_ISA
+
/* These are the only open spaces in my computer. Yours may have more
or less.... -- REW
duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
*/
-static int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
- 0xc8000, 0xd8000, 0xe8000};
-static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
- 0xc8000, 0xd8000, 0xe8000, 0xa0000};
-static int si1_probe_addrs[]= { 0xd0000};
+static int sx_probe_addrs[] = {
+ 0xc0000, 0xd0000, 0xe0000,
+ 0xc8000, 0xd8000, 0xe8000
+};
+static int si_probe_addrs[] = {
+ 0xc0000, 0xd0000, 0xe0000,
+ 0xc8000, 0xd8000, 0xe8000, 0xa0000
+};
+static int si1_probe_addrs[] = {
+ 0xd0000
+};
#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+#endif
/* Set the mask to all-ones. This alas, only supports 32 interrupts.
Some architectures may need more. */
static int sx_irqmask = -1;
-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);
@@ -368,13 +362,12 @@ static struct real_driver sx_real_driver = {
sx_disable_rx_interrupts,
sx_enable_rx_interrupts,
sx_get_CD,
- sx_shutdown_port,
- sx_set_real_termios,
+ sx_shutdown_port,
+ sx_set_real_termios,
sx_chars_in_buffer,
sx_close,
};
-
/*
This driver can spew a whole lot of debugging output at you. If you
need maximum performance, you should disable the DEBUG define. To
@@ -385,23 +378,17 @@ static struct real_driver sx_real_driver = {
*/
#define DEBUG
-
#ifdef DEBUG
-#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
+#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
#else
-#define sx_dprintk(f, str...) /* nothing */
+#define sx_dprintk(f, str...) /* nothing */
#endif
+#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_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", \
- __FUNCTION__, port->line)
-
-
-
+#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
+ __FUNCTION__, port->line)
/*
* Firmware loader driver specific routines
@@ -409,31 +396,26 @@ static struct real_driver sx_real_driver = {
*/
static const struct file_operations sx_fw_fops = {
- .owner = THIS_MODULE,
- .ioctl = sx_fw_ioctl,
+ .owner = THIS_MODULE,
+ .ioctl = sx_fw_ioctl,
};
static struct miscdevice sx_fw_device = {
SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
};
-
-
-
-
#ifdef SX_PARANOIA_CHECK
/* This doesn't work. Who's paranoid around here? Not me! */
-static inline int sx_paranoia_check(struct sx_port const * port,
+static inline int sx_paranoia_check(struct sx_port const *port,
char *name, const char *routine)
{
+ static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
+ "number for device %s in %s\n";
+ static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
+ "device %s in %s\n";
- static const char *badmagic =
- KERN_ERR "sx: Warning: bad sx port magic number for device %s in %s\n";
- static const char *badinfo =
- KERN_ERR "sx: Warning: null sx port for device %s in %s\n";
-
if (!port) {
printk(badinfo, name, routine);
return 1;
@@ -456,23 +438,24 @@ static inline int sx_paranoia_check(struct sx_port const * port,
#define TIMEOUT_1 30
#define TIMEOUT_2 1000000
-
#ifdef DEBUG
static void my_hd_io(void __iomem *p, int len)
{
int i, j, ch;
unsigned char __iomem *addr = p;
- for (i=0;i<len;i+=16) {
- printk ("%p ", addr+i);
- for (j=0;j<16;j++) {
- printk ("%02x %s", readb(addr+j+i), (j==7)?" ":"");
+ for (i = 0; i < len; i += 16) {
+ printk("%p ", addr + i);
+ for (j = 0; j < 16; j++) {
+ printk("%02x %s", readb(addr + j + i),
+ (j == 7) ? " " : "");
}
- for (j=0;j<16;j++) {
- ch = readb(addr+j+i);
- printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+ for (j = 0; j < 16; j++) {
+ ch = readb(addr + j + i);
+ printk("%c", (ch < 0x20) ? '.' :
+ ((ch > 0x7f) ? '.' : ch));
}
- printk ("\n");
+ printk("\n");
}
}
static void my_hd(void *p, int len)
@@ -480,419 +463,468 @@ static void my_hd(void *p, int len)
int i, j, ch;
unsigned char *addr = p;
- for (i=0;i<len;i+=16) {
- printk ("%p ", addr+i);
- for (j=0;j<16;j++) {
- printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+ for (i = 0; i < len; i += 16) {
+ printk("%p ", addr + i);
+ for (j = 0; j < 16; j++) {
+ printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
}
- for (j=0;j<16;j++) {
- ch = addr[j+i];
- printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+ for (j = 0; j < 16; j++) {
+ ch = addr[j + i];
+ printk("%c", (ch < 0x20) ? '.' :
+ ((ch > 0x7f) ? '.' : ch));
}
- printk ("\n");
+ printk("\n");
}
}
#endif
-
-
/* This needs redoing for Alpha -- REW -- Done. */
-static inline void write_sx_byte (struct sx_board *board, int offset, u8 byte)
+static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
{
- writeb (byte, board->base+offset);
+ writeb(byte, board->base + offset);
}
-static inline u8 read_sx_byte (struct sx_board *board, int offset)
+static inline u8 read_sx_byte(struct sx_board *board, int offset)
{
- return readb (board->base+offset);
+ return readb(board->base + offset);
}
-
-static inline void write_sx_word (struct sx_board *board, int offset, u16 word)
+static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
{
- writew (word, board->base+offset);
+ writew(word, board->base + offset);
}
-static inline u16 read_sx_word (struct sx_board *board, int offset)
+static inline u16 read_sx_word(struct sx_board *board, int offset)
{
- return readw (board->base + offset);
+ return readw(board->base + offset);
}
-
-static int sx_busy_wait_eq (struct sx_board *board,
- int offset, int mask, int correctval)
+static int sx_busy_wait_eq(struct sx_board *board,
+ int offset, int mask, int correctval)
{
int i;
- func_enter ();
+ func_enter();
- for (i=0; i < TIMEOUT_1 ;i++)
- if ((read_sx_byte (board, offset) & mask) == correctval) {
- func_exit ();
+ for (i = 0; i < TIMEOUT_1; i++)
+ if ((read_sx_byte(board, offset) & mask) == correctval) {
+ func_exit();
return 1;
}
- for (i=0; i < TIMEOUT_2 ;i++) {
- if ((read_sx_byte (board, offset) & mask) == correctval) {
- func_exit ();
+ for (i = 0; i < TIMEOUT_2; i++) {
+ if ((read_sx_byte(board, offset) & mask) == correctval) {
+ func_exit();
return 1;
}
- udelay (1);
+ udelay(1);
}
- func_exit ();
+ func_exit();
return 0;
}
-
-static int sx_busy_wait_neq (struct sx_board *board,
- int offset, int mask, int badval)
+static int sx_busy_wait_neq(struct sx_board *board,
+ int offset, int mask, int badval)
{
int i;
- func_enter ();
+ func_enter();
- for (i=0; i < TIMEOUT_1 ;i++)
- if ((read_sx_byte (board, offset) & mask) != badval) {
- func_exit ();
+ for (i = 0; i < TIMEOUT_1; i++)
+ if ((read_sx_byte(board, offset) & mask) != badval) {
+ func_exit();
return 1;
}
- for (i=0; i < TIMEOUT_2 ;i++) {
- if ((read_sx_byte (board, offset) & mask) != badval) {
- func_exit ();
+ for (i = 0; i < TIMEOUT_2; i++) {
+ if ((read_sx_byte(board, offset) & mask) != badval) {
+ func_exit();
return 1;
}
- udelay (1);
+ udelay(1);
}
- func_exit ();
+ func_exit();
return 0;
}
-
-
/* 5.6.4 of 6210028 r2.3 */
-static int sx_reset (struct sx_board *board)
+static int sx_reset(struct sx_board *board)
{
- func_enter ();
+ func_enter();
- if (IS_SX_BOARD (board)) {
+ if (IS_SX_BOARD(board)) {
- write_sx_byte (board, SX_CONFIG, 0);
- write_sx_byte (board, SX_RESET, 1); /* Value doesn't matter */
+ write_sx_byte(board, SX_CONFIG, 0);
+ write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
- if (!sx_busy_wait_eq (board, SX_RESET_STATUS, 1, 0)) {
- printk (KERN_INFO "sx: Card doesn't respond to reset....\n");
+ if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
+ printk(KERN_INFO "sx: Card doesn't respond to "
+ "reset...\n");
return 0;
}
} else if (IS_EISA_BOARD(board)) {
- outb(board->irq<<4, board->eisa_base+0xc02);
+ outb(board->irq << 4, board->eisa_base + 0xc02);
} else if (IS_SI1_BOARD(board)) {
- write_sx_byte (board, SI1_ISA_RESET, 0); // value does not matter
+ write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/
} else {
/* Gory details of the SI/ISA board */
- write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
- write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
- write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
- write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
- write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
- write_sx_byte (board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
+ write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
+ write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
+ write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
+ write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
+ write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
+ write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
}
- func_exit ();
+ func_exit();
return 1;
}
-
/* This doesn't work on machines where "NULL" isn't 0 */
/* If you have one of those, someone will need to write
the equivalent of this, which will amount to about 3 lines. I don't
want to complicate this right now. -- REW
(See, I do write comments every now and then :-) */
-#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
-
-
-#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
-#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))
-#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))
+#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
+#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
+#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))
+#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))
#define sx_write_channel_byte(port, elem, val) \
- write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
+ write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
#define sx_read_channel_byte(port, elem) \
- read_sx_byte (port->board, CHAN_OFFSET (port, elem))
+ read_sx_byte (port->board, CHAN_OFFSET (port, elem))
#define sx_write_channel_word(port, elem, val) \
- write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
+ write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
#define sx_read_channel_word(port, elem) \
- read_sx_word (port->board, CHAN_OFFSET (port, elem))
-
+ read_sx_word (port->board, CHAN_OFFSET (port, elem))
#define sx_write_module_byte(board, addr, elem, val) \
- write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
+ write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
#define sx_read_module_byte(board, addr, elem) \
- read_sx_byte (board, MODU_OFFSET (board, addr, elem))
+ read_sx_byte (board, MODU_OFFSET (board, addr, elem))
#define sx_write_module_word(board, addr, elem, val) \
- write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
+ write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
#define sx_read_module_word(board, addr, elem) \
- read_sx_word (board, MODU_OFFSET (board, addr, elem))
-
+ read_sx_word (board, MODU_OFFSET (board, addr, elem))
#define sx_write_board_byte(board, elem, val) \
- write_sx_byte (board, BRD_OFFSET (board, elem), val)
+ write_sx_byte (board, BRD_OFFSET (board, elem), val)
#define sx_read_board_byte(board, elem) \
- read_sx_byte (board, BRD_OFFSET (board, elem))
+ read_sx_byte (board, BRD_OFFSET (board, elem))
#define sx_write_board_word(board, elem, val) \
- write_sx_word (board, BRD_OFFSET (board, elem), val)
+ write_sx_word (board, BRD_OFFSET (board, elem), val)
#define sx_read_board_word(board, elem) \
- read_sx_word (board, BRD_OFFSET (board, elem))
+ read_sx_word (board, BRD_OFFSET (board, elem))
-
-static int sx_start_board (struct sx_board *board)
+static int sx_start_board(struct sx_board *board)
{
- if (IS_SX_BOARD (board)) {
- write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
+ if (IS_SX_BOARD(board)) {
+ write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
} else if (IS_EISA_BOARD(board)) {
write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
- outb((board->irq<<4)|4, board->eisa_base+0xc02);
+ outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
} else if (IS_SI1_BOARD(board)) {
- write_sx_byte (board, SI1_ISA_RESET_CLEAR, 0);
- write_sx_byte (board, SI1_ISA_INTCL, 0);
+ write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
+ write_sx_byte(board, SI1_ISA_INTCL, 0);
} else {
/* Don't bug me about the clear_set.
I haven't the foggiest idea what it's about -- REW */
- write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
- write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+ write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
+ write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
}
return 1;
}
#define SX_IRQ_REG_VAL(board) \
- ((board->flags & SX_ISA_BOARD)?(board->irq << 4):0)
+ ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
/* Note. The SX register is write-only. Therefore, we have to enable the
bus too. This is a no-op, if you don't mess with this driver... */
-static int sx_start_interrupts (struct sx_board *board)
+static int sx_start_interrupts(struct sx_board *board)
{
/* Don't call this with board->irq == 0 */
if (IS_SX_BOARD(board)) {
- write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) |
- SX_CONF_BUSEN |
- SX_CONF_HOSTIRQ);
+ write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
+ SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
} else if (IS_EISA_BOARD(board)) {
- inb(board->eisa_base+0xc03);
+ inb(board->eisa_base + 0xc03);
} else if (IS_SI1_BOARD(board)) {
- write_sx_byte (board, SI1_ISA_INTCL,0);
- write_sx_byte (board, SI1_ISA_INTCL_CLEAR,0);
+ write_sx_byte(board, SI1_ISA_INTCL, 0);
+ write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
} else {
switch (board->irq) {
- case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
- case 12:write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);break;
- case 15:write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);break;
- default:printk (KERN_INFO "sx: SI/XIO card doesn't support interrupt %d.\n",
- board->irq);
- return 0;
+ case 11:
+ write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
+ break;
+ case 12:
+ write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
+ break;
+ case 15:
+ write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
+ break;
+ default:
+ printk(KERN_INFO "sx: SI/XIO card doesn't support "
+ "interrupt %d.\n", board->irq);
+ return 0;
}
- write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+ write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
}
return 1;
}
-
-static int sx_send_command (struct sx_port *port,
- int command, int mask, int newstat)
+static int sx_send_command(struct sx_port *port,
+ int command, int mask, int newstat)
{
- func_enter2 ();
- write_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat), command);
- func_exit ();
- return sx_busy_wait_eq (port->board, CHAN_OFFSET (port, hi_hstat), mask, newstat);
+ func_enter2();
+ write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
+ func_exit();
+ return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
+ newstat);
}
-
-static char *mod_type_s (int module_type)
+static char *mod_type_s(int module_type)
{
switch (module_type) {
- case TA4: return "TA4";
- case TA8: return "TA8";
- case TA4_ASIC: return "TA4_ASIC";
- case TA8_ASIC: return "TA8_ASIC";
- case MTA_CD1400:return "MTA_CD1400";
- case SXDC: return "SXDC";
- default:return "Unknown/invalid";
+ case TA4:
+ return "TA4";
+ case TA8:
+ return "TA8";
+ case TA4_ASIC:
+ return "TA4_ASIC";
+ case TA8_ASIC:
+ return "TA8_ASIC";
+ case MTA_CD1400:
+ return "MTA_CD1400";
+ case SXDC:
+ return "SXDC";
+ default:
+ return "Unknown/invalid";
}
}
-
-static char *pan_type_s (int pan_type)
+static char *pan_type_s(int pan_type)
{
switch (pan_type) {
- case MOD_RS232DB25: return "MOD_RS232DB25";
- case MOD_RS232RJ45: return "MOD_RS232RJ45";
- case MOD_RS422DB25: return "MOD_RS422DB25";
- case MOD_PARALLEL: return "MOD_PARALLEL";
- case MOD_2_RS232DB25: return "MOD_2_RS232DB25";
- case MOD_2_RS232RJ45: return "MOD_2_RS232RJ45";
- case MOD_2_RS422DB25: return "MOD_2_RS422DB25";
- case MOD_RS232DB25MALE: return "MOD_RS232DB25MALE";
- case MOD_2_PARALLEL: return "MOD_2_PARALLEL";
- case MOD_BLANK: return "empty";
- default:return "invalid";
+ case MOD_RS232DB25:
+ return "MOD_RS232DB25";
+ case MOD_RS232RJ45:
+ return "MOD_RS232RJ45";
+ case MOD_RS422DB25:
+ return "MOD_RS422DB25";
+ case MOD_PARALLEL:
+ return "MOD_PARALLEL";
+ case MOD_2_RS232DB25:
+ return "MOD_2_RS232DB25";
+ case MOD_2_RS232RJ45:
+ return "MOD_2_RS232RJ45";
+ case MOD_2_RS422DB25:
+ return "MOD_2_RS422DB25";
+ case MOD_RS232DB25MALE:
+ return "MOD_RS232DB25MALE";
+ case MOD_2_PARALLEL:
+ return "MOD_2_PARALLEL";
+ case MOD_BLANK:
+ return "empty";
+ default:
+ return "invalid";
}
}
-
-static int mod_compat_type (int module_type)
+static int mod_compat_type(int module_type)
{
return module_type >> 4;
}
static void sx_reconfigure_port(struct sx_port *port)
{
- if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
- if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
- printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
+ if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
+ if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+ printk(KERN_WARNING "sx: Sent reconfigure command, but "
+ "card didn't react.\n");
}
} else {
- sx_dprintk (SX_DEBUG_TERMIOS,
- "sx: Not sending reconfigure: port isn't open (%02x).\n",
- sx_read_channel_byte (port, hi_hstat));
- }
+ sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
+ "port isn't open (%02x).\n",
+ sx_read_channel_byte(port, hi_hstat));
+ }
}
-static void sx_setsignals (struct sx_port *port, int dtr, int rts)
+static void sx_setsignals(struct sx_port *port, int dtr, int rts)
{
int t;
- func_enter2 ();
+ func_enter2();
- t = sx_read_channel_byte (port, hi_op);
- if (dtr >= 0) t = dtr? (t | OP_DTR): (t & ~OP_DTR);
- if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS);
- sx_write_channel_byte (port, hi_op, t);
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
+ t = sx_read_channel_byte(port, hi_op);
+ if (dtr >= 0)
+ t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
+ if (rts >= 0)
+ t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
+ sx_write_channel_byte(port, hi_op, t);
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
- func_exit ();
+ func_exit();
}
-
-
-static int sx_getsignals (struct sx_port *port)
+static int sx_getsignals(struct sx_port *port)
{
- int i_stat,o_stat;
-
- o_stat = sx_read_channel_byte (port, hi_op);
- i_stat = sx_read_channel_byte (port, hi_ip);
-
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) %02x/%02x\n",
- (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
- port->c_dcd, sx_get_CD (port),
- sx_read_channel_byte (port, hi_ip),
- sx_read_channel_byte (port, hi_state));
-
- return (((o_stat & OP_DTR)?TIOCM_DTR:0) |
- ((o_stat & OP_RTS)?TIOCM_RTS:0) |
- ((i_stat & IP_CTS)?TIOCM_CTS:0) |
- ((i_stat & IP_DCD)?TIOCM_CAR:0) |
- ((i_stat & IP_DSR)?TIOCM_DSR:0) |
- ((i_stat & IP_RI)?TIOCM_RNG:0)
- );
+ int i_stat, o_stat;
+
+ o_stat = sx_read_channel_byte(port, hi_op);
+ i_stat = sx_read_channel_byte(port, hi_ip);
+
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
+ "%02x/%02x\n",
+ (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
+ port->c_dcd, sx_get_CD(port),
+ sx_read_channel_byte(port, hi_ip),
+ sx_read_channel_byte(port, hi_state));
+
+ return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
+ ((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
+ ((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
+ ((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
+ ((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
+ ((i_stat & IP_RI) ? TIOCM_RNG : 0));
}
-
-static void sx_set_baud (struct sx_port *port)
+static void sx_set_baud(struct sx_port *port)
{
int t;
if (port->board->ta_type == MOD_SXDC) {
switch (port->gs.baud) {
- /* Save some typing work... */
-#define e(x) case x:t= BAUD_ ## x ; break
- e(50);e(75);e(110);e(150);e(200);e(300);e(600);
- e(1200);e(1800);e(2000);e(2400);e(4800);e(7200);
- e(9600);e(14400);e(19200);e(28800);e(38400);
- e(56000);e(57600);e(64000);e(76800);e(115200);
- e(128000);e(150000);e(230400);e(256000);e(460800);
- e(921600);
- case 134 :t = BAUD_134_5; break;
- case 0 :t = -1;
- break;
+ /* Save some typing work... */
+#define e(x) case x: t = BAUD_ ## x; break
+ e(50);
+ e(75);
+ e(110);
+ e(150);
+ e(200);
+ e(300);
+ e(600);
+ e(1200);
+ e(1800);
+ e(2000);
+ e(2400);
+ e(4800);
+ e(7200);
+ e(9600);
+ e(14400);
+ e(19200);
+ e(28800);
+ e(38400);
+ e(56000);
+ e(57600);
+ e(64000);
+ e(76800);
+ e(115200);
+ e(128000);
+ e(150000);
+ e(230400);
+ e(256000);
+ e(460800);
+ e(921600);
+ case 134:
+ t = BAUD_134_5;
+ break;
+ case 0:
+ t = -1;
+ break;
default:
/* Can I return "invalid"? */
t = BAUD_9600;
- printk (KERN_INFO "sx: unsupported baud rate: %d.\n", port->gs.baud);
+ printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
+ port->gs.baud);
break;
}
#undef e
if (t > 0) {
- /* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
- sx_setsignals (port, 1, -1);
+/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
+ sx_setsignals(port, 1, -1);
/* XXX This is not TA & MTA compatible */
- sx_write_channel_byte (port, hi_csr, 0xff);
+ sx_write_channel_byte(port, hi_csr, 0xff);
- sx_write_channel_byte (port, hi_txbaud, t);
- sx_write_channel_byte (port, hi_rxbaud, t);
+ sx_write_channel_byte(port, hi_txbaud, t);
+ sx_write_channel_byte(port, hi_rxbaud, t);
} else {
- sx_setsignals (port, 0, -1);
+ sx_setsignals(port, 0, -1);
}
} else {
switch (port->gs.baud) {
-#define e(x) case x:t= CSR_ ## x ; break
- e(75);e(150);e(300);e(600);e(1200);e(2400);e(4800);
- e(1800);e(9600);
- e(19200);e(57600);e(38400);
- /* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
- case 110:
+#define e(x) case x: t = CSR_ ## x; break
+ e(75);
+ e(150);
+ e(300);
+ e(600);
+ e(1200);
+ e(2400);
+ e(4800);
+ e(1800);
+ e(9600);
+ e(19200);
+ e(57600);
+ e(38400);
+/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
+ case 110:
if (port->board->ta_type == MOD_TA) {
t = CSR_110;
break;
} else {
t = CSR_9600;
- printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud);
+ printk(KERN_INFO "sx: Unsupported baud rate: "
+ "%d.\n", port->gs.baud);
break;
}
- case 115200:
+ case 115200:
if (port->board->ta_type == MOD_TA) {
t = CSR_9600;
- printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud);
+ printk(KERN_INFO "sx: Unsupported baud rate: "
+ "%d.\n", port->gs.baud);
break;
} else {
t = CSR_110;
break;
}
- case 0 :t = -1;
- break;
+ case 0:
+ t = -1;
+ break;
default:
t = CSR_9600;
- printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud);
+ printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
+ port->gs.baud);
break;
}
#undef e
if (t >= 0) {
- sx_setsignals (port, 1, -1);
- sx_write_channel_byte (port, hi_csr, t * 0x11);
+ sx_setsignals(port, 1, -1);
+ sx_write_channel_byte(port, hi_csr, t * 0x11);
} else {
- sx_setsignals (port, 0, -1);
+ sx_setsignals(port, 0, -1);
}
}
}
-
/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
better. -- REW */
-static int sx_set_real_termios (void *ptr)
+static int sx_set_real_termios(void *ptr)
{
struct sx_port *port = ptr;
@@ -907,80 +939,83 @@ static int sx_set_real_termios (void *ptr)
belongs (next to the drop dtr if baud == 0) -- REW */
/* sx_setsignals (port, 1, -1); */
- sx_set_baud (port);
+ sx_set_baud(port);
#define CFLAG port->gs.tty->termios->c_cflag
- sx_write_channel_byte (port, hi_mr1,
- (C_PARENB (port->gs.tty)? MR1_WITH:MR1_NONE) |
- (C_PARODD (port->gs.tty)? MR1_ODD:MR1_EVEN) |
- (C_CRTSCTS(port->gs.tty)? MR1_RTS_RXFLOW:0) |
- (((CFLAG & CSIZE)==CS8) ? MR1_8_BITS:0) |
- (((CFLAG & CSIZE)==CS7) ? MR1_7_BITS:0) |
- (((CFLAG & CSIZE)==CS6) ? MR1_6_BITS:0) |
- (((CFLAG & CSIZE)==CS5) ? MR1_5_BITS:0) );
-
- sx_write_channel_byte (port, hi_mr2,
- (C_CRTSCTS(port->gs.tty)?MR2_CTS_TXFLOW:0) |
- (C_CSTOPB (port->gs.tty)?MR2_2_STOP:MR2_1_STOP));
+ sx_write_channel_byte(port, hi_mr1,
+ (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) |
+ (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) |
+ (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) |
+ (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
+ (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
+ (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
+ (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
+
+ sx_write_channel_byte(port, hi_mr2,
+ (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) |
+ (C_CSTOPB(port->gs.tty) ? MR2_2_STOP :
+ MR2_1_STOP));
switch (CFLAG & CSIZE) {
- case CS8:sx_write_channel_byte (port, hi_mask, 0xff);break;
- case CS7:sx_write_channel_byte (port, hi_mask, 0x7f);break;
- case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break;
- case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break;
+ case CS8:
+ sx_write_channel_byte(port, hi_mask, 0xff);
+ break;
+ case CS7:
+ sx_write_channel_byte(port, hi_mask, 0x7f);
+ break;
+ case CS6:
+ sx_write_channel_byte(port, hi_mask, 0x3f);
+ break;
+ case CS5:
+ sx_write_channel_byte(port, hi_mask, 0x1f);
+ break;
default:
- printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
+ printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
break;
}
- sx_write_channel_byte (port, hi_prtcl,
- (I_IXON (port->gs.tty)?SP_TXEN:0) |
- (I_IXOFF (port->gs.tty)?SP_RXEN:0) |
- (I_IXANY (port->gs.tty)?SP_TANY:0) |
- SP_DCEN);
+ sx_write_channel_byte(port, hi_prtcl,
+ (I_IXON(port->gs.tty) ? SP_TXEN : 0) |
+ (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) |
+ (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN);
- sx_write_channel_byte (port, hi_break,
- (I_IGNBRK(port->gs.tty)?BR_IGN:0 |
- I_BRKINT(port->gs.tty)?BR_INT:0));
+ sx_write_channel_byte(port, hi_break,
+ (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 |
+ I_BRKINT(port->gs.tty) ? BR_INT : 0));
- sx_write_channel_byte (port, hi_txon, START_CHAR (port->gs.tty));
- sx_write_channel_byte (port, hi_rxon, START_CHAR (port->gs.tty));
- sx_write_channel_byte (port, hi_txoff, STOP_CHAR (port->gs.tty));
- sx_write_channel_byte (port, hi_rxoff, STOP_CHAR (port->gs.tty));
+ sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty));
+ sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty));
+ sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty));
+ sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty));
sx_reconfigure_port(port);
/* Tell line discipline whether we will do input cooking */
- if(I_OTHER(port->gs.tty)) {
+ if (I_OTHER(port->gs.tty)) {
clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
} else {
set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
}
- sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
- port->gs.tty->termios->c_iflag,
- I_OTHER(port->gs.tty));
-
+ sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
+ port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty));
/* Tell line discipline whether we will do output cooking.
* If OPOST is set and no other output flags are set then we can do output
* processing. Even if only *one* other flag in the O_OTHER group is set
* we do cooking in software.
*/
- if(O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
+ if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
} else {
clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
}
- sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
- port->gs.tty->termios->c_oflag,
- O_OTHER(port->gs.tty));
+ sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
+ port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty));
/* port->c_dcd = sx_get_CD (port); */
- func_exit ();
+ func_exit();
return 0;
}
-
-
/* ********************************************************************** *
* the interrupt related routines *
* ********************************************************************** */
@@ -996,245 +1031,260 @@ static int sx_set_real_termios (void *ptr)
know I'm dead against that, but I think it is required in this
case. */
-
-static void sx_transmit_chars (struct sx_port *port)
+static void sx_transmit_chars(struct sx_port *port)
{
int c;
int tx_ip;
int txroom;
- func_enter2 ();
- sx_dprintk (SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
- port, port->gs.xmit_cnt);
+ func_enter2();
+ sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
+ port, port->gs.xmit_cnt);
- if (test_and_set_bit (SX_PORT_TRANSMIT_LOCK, &port->locks)) {
+ if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
return;
}
while (1) {
c = port->gs.xmit_cnt;
- sx_dprintk (SX_DEBUG_TRANSMIT, "Copying %d ", c);
- tx_ip = sx_read_channel_byte (port, hi_txipos);
+ sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
+ tx_ip = sx_read_channel_byte(port, hi_txipos);
/* Took me 5 minutes to deduce this formula.
Luckily it is literally in the manual in section 6.5.4.3.5 */
- txroom = (sx_read_channel_byte (port, hi_txopos) - tx_ip - 1) & 0xff;
+ txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
+ 0xff;
/* Don't copy more bytes than there is room for in the buffer */
if (c > txroom)
c = txroom;
- sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom );
+ sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
/* Don't copy past the end of the hardware transmit buffer */
- if (c > 0x100 - tx_ip)
+ if (c > 0x100 - tx_ip)
c = 0x100 - tx_ip;
- sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100-tx_ip );
+ sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
/* Don't copy pas the end of the source buffer */
- if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
+ if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
- sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%ld) \n",
- c, SERIAL_XMIT_SIZE- port->gs.xmit_tail);
-
- /* If for one reason or another, we can't copy more data, we're done! */
- if (c == 0) break;
+ sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
+ c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
+ /* If for one reason or another, we can't copy more data, we're
+ done! */
+ if (c == 0)
+ break;
- memcpy_toio (port->board->base + CHAN_OFFSET(port,hi_txbuf) + tx_ip,
- port->gs.xmit_buf + port->gs.xmit_tail, c);
+ memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
+ tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
/* Update the pointer in the card */
- sx_write_channel_byte (port, hi_txipos, (tx_ip+c) & 0xff);
+ sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
/* Update the kernel buffer end */
- port->gs.xmit_tail = (port->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1);
+ port->gs.xmit_tail = (port->gs.xmit_tail + c) &
+ (SERIAL_XMIT_SIZE - 1);
/* This one last. (this is essential)
- It would allow others to start putting more data into the buffer! */
+ It would allow others to start putting more data into the
+ buffer! */
port->gs.xmit_cnt -= c;
}
if (port->gs.xmit_cnt == 0) {
- sx_disable_tx_interrupts (port);
+ sx_disable_tx_interrupts(port);
}
if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
tty_wakeup(port->gs.tty);
- sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
- port->gs.wakeup_chars);
+ sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
+ port->gs.wakeup_chars);
}
- clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
- func_exit ();
+ clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
+ func_exit();
}
-
/* Note the symmetry between receiving chars and transmitting them!
Note: The kernel should have implemented both a receive buffer and
a transmit buffer. */
/* Inlined: Called only once. Remove the inline when you add another call */
-static inline void sx_receive_chars (struct sx_port *port)
+static inline void sx_receive_chars(struct sx_port *port)
{
int c;
int rx_op;
struct tty_struct *tty;
- int copied=0;
+ int copied = 0;
unsigned char *rp;
- func_enter2 ();
+ func_enter2();
tty = port->gs.tty;
while (1) {
- rx_op = sx_read_channel_byte (port, hi_rxopos);
- c = (sx_read_channel_byte (port, hi_rxipos) - rx_op) & 0xff;
+ rx_op = sx_read_channel_byte(port, hi_rxopos);
+ c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
- sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
+ sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
/* Don't copy past the end of the hardware receive buffer */
- if (rx_op + c > 0x100) c = 0x100 - rx_op;
+ if (rx_op + c > 0x100)
+ c = 0x100 - rx_op;
- sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
+ sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
/* Don't copy more bytes than there is room for in the buffer */
c = tty_prepare_flip_string(tty, &rp, c);
- sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
+ sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
/* If for one reason or another, we can't copy more data, we're done! */
- if (c == 0) break;
+ if (c == 0)
+ break;
- sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c,
- read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op),
- CHAN_OFFSET(port, hi_rxbuf));
- memcpy_fromio (rp,
- port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c);
+ sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
+ "%d at %lx\n", c, read_sx_byte(port->board,
+ CHAN_OFFSET(port, hi_rxbuf) + rx_op),
+ CHAN_OFFSET(port, hi_rxbuf));
+ memcpy_fromio(rp, port->board->base +
+ CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
/* This one last. ( Not essential.)
- It allows the card to start putting more data into the buffer!
+ It allows the card to start putting more data into the
+ buffer!
Update the pointer in the card */
- sx_write_channel_byte (port, hi_rxopos, (rx_op + c) & 0xff);
+ sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
copied += c;
}
if (copied) {
struct timeval tv;
- do_gettimeofday (&tv);
- sx_dprintk (SX_DEBUG_RECEIVE,
- "pushing flipq port %d (%3d chars): %d.%06d (%d/%d)\n",
- port->line, copied,
- (int) (tv.tv_sec % 60), (int)tv.tv_usec, tty->raw, tty->real_raw);
+ do_gettimeofday(&tv);
+ sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
+ "chars): %d.%06d (%d/%d)\n", port->line,
+ copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
+ tty->raw, tty->real_raw);
- /* Tell the rest of the system the news. Great news. New characters! */
- tty_flip_buffer_push (tty);
+ /* Tell the rest of the system the news. Great news. New
+ characters! */
+ tty_flip_buffer_push(tty);
/* tty_schedule_flip (tty); */
}
- func_exit ();
+ func_exit();
}
/* Inlined: it is called only once. Remove the inline if you add another
call */
-static inline void sx_check_modem_signals (struct sx_port *port)
+static inline void sx_check_modem_signals(struct sx_port *port)
{
int hi_state;
int c_dcd;
- hi_state = sx_read_channel_byte (port, hi_state);
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
- port->c_dcd, sx_get_CD (port));
+ hi_state = sx_read_channel_byte(port, hi_state);
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
+ port->c_dcd, sx_get_CD(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);
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
+ sx_write_channel_byte(port, hi_state, hi_state);
+ gs_got_break(&port->gs);
}
if (hi_state & ST_DCD) {
hi_state &= ~ST_DCD;
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
- sx_write_channel_byte (port, hi_state, hi_state);
- c_dcd = sx_get_CD (port);
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
+ sx_write_channel_byte(port, hi_state, hi_state);
+ c_dcd = sx_get_CD(port);
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
if (c_dcd != port->c_dcd) {
port->c_dcd = c_dcd;
- if (sx_get_CD (port)) {
+ if (sx_get_CD(port)) {
/* DCD went UP */
- if ((sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) &&
- !(port->gs.tty->termios->c_cflag & CLOCAL) ) {
- /* Are we blocking in open?*/
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n");
- wake_up_interruptible(&port->gs.open_wait);
+ if ((sx_read_channel_byte(port, hi_hstat) !=
+ HS_IDLE_CLOSED) &&
+ !(port->gs.tty->termios->
+ c_cflag & CLOCAL)) {
+ /* Are we blocking in open? */
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+ "active, unblocking open\n");
+ wake_up_interruptible(&port->gs.
+ open_wait);
} else {
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD raised. Ignoring.\n");
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+ "raised. Ignoring.\n");
}
} else {
/* DCD went down! */
- if (!(port->gs.tty->termios->c_cflag & CLOCAL) ) {
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n");
- tty_hangup (port->gs.tty);
+ if (!(port->gs.tty->termios->c_cflag & CLOCAL)){
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+ "dropped. hanging up....\n");
+ tty_hangup(port->gs.tty);
} else {
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. ignoring.\n");
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+ "dropped. ignoring.\n");
}
}
} else {
- sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us DCD changed, but it didn't.\n");
+ sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
+ "DCD changed, but it didn't.\n");
}
}
}
-
/* This is what an interrupt routine should look like.
* Small, elegant, clear.
*/
-static irqreturn_t sx_interrupt (int irq, void *ptr)
+static irqreturn_t sx_interrupt(int irq, void *ptr)
{
struct sx_board *board = ptr;
struct sx_port *port;
int i;
- func_enter ();
- sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq);
+ 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
not trivial.
- Rate limit goes before "recursive". Otherwise a series of
- recursive calls will hang the machine in the interrupt routine.
+ recursive calls will hang the machine in the interrupt routine.
- hardware twiddling goes before "recursive". Otherwise when we
- poll the card, and a recursive interrupt happens, we won't
- ack the card, so it might keep on interrupting us. (especially
- level sensitive interrupt systems like PCI).
+ poll the card, and a recursive interrupt happens, we won't
+ ack the card, so it might keep on interrupting us. (especially
+ level sensitive interrupt systems like PCI).
- Rate limit goes before hardware twiddling. Otherwise we won't
- catch a card that has gone bonkers.
+ catch a card that has gone bonkers.
- The "initialized" test goes after the hardware twiddling. Otherwise
- the card will stick us in the interrupt routine again.
+ the card will stick us in the interrupt routine again.
- The initialized test goes before recursive.
- */
-
-
+ */
#ifdef IRQ_RATE_LIMIT
/* Aaargh! I'm ashamed. This costs more lines-of-code than the
- actual interrupt routine!. (Well, used to when I wrote that comment) */
+ actual interrupt routine!. (Well, used to when I wrote that
+ comment) */
{
static int lastjif;
- static int nintr=0;
+ static int nintr = 0;
if (lastjif == jiffies) {
if (++nintr > IRQ_RATE_LIMIT) {
- free_irq (board->irq, board);
- printk (KERN_ERR "sx: Too many interrupts. Turning off interrupt %d.\n",
- board->irq);
+ free_irq(board->irq, board);
+ printk(KERN_ERR "sx: Too many interrupts. "
+ "Turning off interrupt %d.\n",
+ board->irq);
}
} else {
lastjif = jiffies;
@@ -1243,19 +1293,20 @@ static irqreturn_t sx_interrupt (int irq, void *ptr)
}
#endif
-
if (board->irq == irq) {
/* Tell the card we've noticed the interrupt. */
- sx_write_board_word (board, cc_int_pending, 0);
- if (IS_SX_BOARD (board)) {
- write_sx_byte (board, SX_RESET_IRQ, 1);
+ sx_write_board_word(board, cc_int_pending, 0);
+ if (IS_SX_BOARD(board)) {
+ write_sx_byte(board, SX_RESET_IRQ, 1);
} else if (IS_EISA_BOARD(board)) {
- inb(board->eisa_base+0xc03);
- write_sx_word(board, 8, 0);
+ inb(board->eisa_base + 0xc03);
+ write_sx_word(board, 8, 0);
} else {
- write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
- write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+ write_sx_byte(board, SI2_ISA_INTCLEAR,
+ SI2_ISA_INTCLEAR_CLEAR);
+ write_sx_byte(board, SI2_ISA_INTCLEAR,
+ SI2_ISA_INTCLEAR_SET);
}
}
@@ -1264,53 +1315,48 @@ static irqreturn_t sx_interrupt (int irq, void *ptr)
if (!(board->flags & SX_BOARD_INITIALIZED))
return IRQ_HANDLED;
- if (test_and_set_bit (SX_BOARD_INTR_LOCK, &board->locks)) {
- printk (KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
+ if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
+ printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
return IRQ_HANDLED;
}
- for (i=0;i<board->nports;i++) {
+ for (i = 0; i < board->nports; i++) {
port = &board->ports[i];
if (port->gs.flags & GS_ACTIVE) {
- if (sx_read_channel_byte (port, hi_state)) {
- sx_dprintk (SX_DEBUG_INTERRUPTS,
- "Port %d: modem signal change?... \n", i);
- sx_check_modem_signals (port);
+ if (sx_read_channel_byte(port, hi_state)) {
+ sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
+ "modem signal change?... \n",i);
+ sx_check_modem_signals(port);
}
if (port->gs.xmit_cnt) {
- sx_transmit_chars (port);
+ sx_transmit_chars(port);
}
if (!(port->gs.flags & SX_RX_THROTTLE)) {
- sx_receive_chars (port);
+ sx_receive_chars(port);
}
}
}
- clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
+ 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 ();
+ sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
+ board->irq);
+ func_exit();
return IRQ_HANDLED;
}
-
-static void sx_pollfunc (unsigned long data)
+static void sx_pollfunc(unsigned long data)
{
- struct sx_board *board = (struct sx_board *) data;
-
- func_enter ();
+ struct sx_board *board = (struct sx_board *)data;
- sx_interrupt (0, board);
+ func_enter();
- init_timer(&board->timer);
+ sx_interrupt(0, board);
- board->timer.expires = jiffies + sx_poll;
- add_timer (&board->timer);
- func_exit ();
+ mod_timer(&board->timer, jiffies + sx_poll);
+ func_exit();
}
-
-
/* ********************************************************************** *
* Here are the routines that actually *
* interface with the generic_serial driver *
@@ -1319,9 +1365,9 @@ static void sx_pollfunc (unsigned long data)
/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
/* Hmm. Ok I figured it out. You don't. */
-static void sx_disable_tx_interrupts (void * ptr)
+static void sx_disable_tx_interrupts(void *ptr)
{
- struct sx_port *port = ptr;
+ struct sx_port *port = ptr;
func_enter2();
port->gs.flags &= ~GS_TX_INTEN;
@@ -1329,30 +1375,28 @@ static void sx_disable_tx_interrupts (void * ptr)
func_exit();
}
-
-static void sx_enable_tx_interrupts (void * ptr)
+static void sx_enable_tx_interrupts(void *ptr)
{
- struct sx_port *port = ptr;
+ struct sx_port *port = ptr;
int data_in_buffer;
func_enter2();
/* First transmit the characters that we're supposed to */
- sx_transmit_chars (port);
+ sx_transmit_chars(port);
/* The sx card will never interrupt us if we don't fill the buffer
past 25%. So we keep considering interrupts off if that's the case. */
- data_in_buffer = (sx_read_channel_byte (port, hi_txipos) -
- sx_read_channel_byte (port, hi_txopos)) & 0xff;
+ data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
+ sx_read_channel_byte(port, hi_txopos)) & 0xff;
/* XXX Must be "HIGH_WATER" for SI card according to doc. */
- if (data_in_buffer < LOW_WATER)
+ if (data_in_buffer < LOW_WATER)
port->gs.flags &= ~GS_TX_INTEN;
func_exit();
}
-
-static void sx_disable_rx_interrupts (void * ptr)
+static void sx_disable_rx_interrupts(void *ptr)
{
/* struct sx_port *port = ptr; */
func_enter();
@@ -1360,7 +1404,7 @@ static void sx_disable_rx_interrupts (void * ptr)
func_exit();
}
-static void sx_enable_rx_interrupts (void * ptr)
+static void sx_enable_rx_interrupts(void *ptr)
{
/* struct sx_port *port = ptr; */
func_enter();
@@ -1368,55 +1412,48 @@ static void sx_enable_rx_interrupts (void * ptr)
func_exit();
}
-
/* Jeez. Isn't this simple? */
-static int sx_get_CD (void * ptr)
+static int sx_get_CD(void *ptr)
{
struct sx_port *port = ptr;
func_enter2();
func_exit();
- return ((sx_read_channel_byte (port, hi_ip) & IP_DCD) != 0);
+ return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0);
}
-
/* Jeez. Isn't this simple? */
-static int sx_chars_in_buffer (void * ptr)
+static int sx_chars_in_buffer(void *ptr)
{
struct sx_port *port = ptr;
func_enter2();
func_exit();
- return ((sx_read_channel_byte (port, hi_txipos) -
- sx_read_channel_byte (port, hi_txopos)) & 0xff);
+ return ((sx_read_channel_byte(port, hi_txipos) -
+ sx_read_channel_byte(port, hi_txopos)) & 0xff);
}
-
-static void sx_shutdown_port (void * ptr)
+static void sx_shutdown_port(void *ptr)
{
- struct sx_port *port = ptr;
+ struct sx_port *port = ptr;
func_enter();
- port->gs.flags &= ~ GS_ACTIVE;
+ port->gs.flags &= ~GS_ACTIVE;
if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
- sx_setsignals (port, 0, 0);
+ sx_setsignals(port, 0, 0);
sx_reconfigure_port(port);
}
func_exit();
}
-
-
-
-
/* ********************************************************************** *
* Here are the routines that actually *
* interface with the rest of the system *
* ********************************************************************** */
-static int sx_open (struct tty_struct * tty, struct file * filp)
+static int sx_open(struct tty_struct *tty, struct file *filp)
{
struct sx_port *port;
int retval, line;
@@ -1429,18 +1466,18 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
}
line = tty->index;
- sx_dprintk (SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, np=%d)\n",
- current->pid, line, tty, current->signal->tty, sx_nports);
+ sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
+ "np=%d)\n", current->pid, line, tty,
+ current->signal->tty, sx_nports);
if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
return -ENODEV;
- port = & sx_ports[line];
+ port = &sx_ports[line];
port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
- 1 -> 0 transition. */
+ 1 -> 0 transition. */
-
- sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
+ sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
spin_lock_irqsave(&port->gs.driver_lock, flags);
@@ -1449,13 +1486,13 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
port->gs.count++;
spin_unlock_irqrestore(&port->gs.driver_lock, flags);
- sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
+ sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
/*
* Start up serial port
*/
retval = gs_init_port(&port->gs);
- sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n");
+ sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
if (retval) {
port->gs.count--;
return retval;
@@ -1463,19 +1500,20 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
port->gs.flags |= GS_ACTIVE;
if (port->gs.count <= 1)
- sx_setsignals (port, 1,1);
+ sx_setsignals(port, 1, 1);
#if 0
if (sx_debug & SX_DEBUG_OPEN)
- my_hd (port, sizeof (*port));
+ my_hd(port, sizeof(*port));
#else
if (sx_debug & SX_DEBUG_OPEN)
- my_hd_io (port->board->base + port->ch_base, sizeof (*port));
+ my_hd_io(port->board->base + port->ch_base, sizeof(*port));
#endif
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");
+ 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);
@@ -1484,75 +1522,76 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
}
retval = gs_block_til_ready(port, filp);
- sx_dprintk (SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
- retval, port->gs.count);
+ sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
+ retval, port->gs.count);
if (retval) {
- /*
- * Don't lower gs.count here because sx_close() will be called later
- */
+/*
+ * Don't lower gs.count here because sx_close() will be called later
+ */
return retval;
}
/* tty->low_latency = 1; */
- port->c_dcd = sx_get_CD (port);
- sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+ port->c_dcd = sx_get_CD(port);
+ sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
func_exit();
return 0;
}
-
-static void sx_close (void *ptr)
+static void sx_close(void *ptr)
{
- struct sx_port *port = ptr;
+ struct sx_port *port = ptr;
/* Give the port 5 seconds to close down. */
- int to = 5 * HZ;
+ int to = 5 * HZ;
- func_enter ();
+ func_enter();
- sx_setsignals (port, 0, 0);
- sx_reconfigure_port(port);
- sx_send_command (port, HS_CLOSE, 0, 0);
+ sx_setsignals(port, 0, 0);
+ sx_reconfigure_port(port);
+ sx_send_command(port, HS_CLOSE, 0, 0);
- while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED))
+ 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
- "sx: sent the force_close command, but card didn't react\n");
+ 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 "sx: sent the force_close command, but "
+ "card didn't react\n");
} else
- sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n");
+ sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
+ "command.\n");
}
- sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
- 5 * HZ - to - 1, port->gs.count);
+ sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
+ 5 * HZ - to - 1, port->gs.count);
- if(port->gs.count) {
- sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
- //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
- //port->gs.count = 0;
+ if (port->gs.count) {
+ sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
+ port->gs.count);
+ /*printk("%s SETTING port count to zero: %p count: %d\n",
+ __FUNCTION__, port, port->gs.count);
+ port->gs.count = 0;*/
}
- func_exit ();
+ func_exit();
}
-
-
/* This is relatively thorough. But then again it is only 20 lines. */
-#define MARCHUP for (i=min;i<max;i++)
-#define MARCHDOWN for (i=max-1;i>=min;i--)
-#define W0 write_sx_byte (board, i, 0x55)
-#define W1 write_sx_byte (board, i, 0xaa)
-#define R0 if (read_sx_byte (board, i) != 0x55) return 1
-#define R1 if (read_sx_byte (board, i) != 0xaa) return 1
+#define MARCHUP for (i = min; i < max; i++)
+#define MARCHDOWN for (i = max - 1; i >= min; i--)
+#define W0 write_sx_byte(board, i, 0x55)
+#define W1 write_sx_byte(board, i, 0xaa)
+#define R0 if (read_sx_byte(board, i) != 0x55) return 1
+#define R1 if (read_sx_byte(board, i) != 0xaa) return 1
/* This memtest takes a human-noticable time. You normally only do it
once a boot, so I guess that it is worth it. */
-static int do_memtest (struct sx_board *board, int min, int max)
+static int do_memtest(struct sx_board *board, int min, int max)
{
int i;
@@ -1561,16 +1600,37 @@ static int do_memtest (struct sx_board *board, int min, int max)
intermittent errors. -- REW
(For the theory behind memory testing see:
Testing Semiconductor Memories by A.J. van de Goor.) */
- MARCHUP {W0;}
- MARCHUP {R0;W1;R1;W0;R0;W1;}
- MARCHUP {R1;W0;W1;}
- MARCHDOWN {R1;W0;W1;W0;}
- MARCHDOWN {R0;W1;W0;}
+ MARCHUP {
+ W0;
+ }
+ MARCHUP {
+ R0;
+ W1;
+ R1;
+ W0;
+ R0;
+ W1;
+ }
+ MARCHUP {
+ R1;
+ W0;
+ W1;
+ }
+ MARCHDOWN {
+ R1;
+ W0;
+ W1;
+ W0;
+ }
+ MARCHDOWN {
+ R0;
+ W1;
+ W0;
+ }
return 0;
}
-
#undef MARCHUP
#undef MARCHDOWN
#undef W0
@@ -1578,33 +1638,54 @@ static int do_memtest (struct sx_board *board, int min, int max)
#undef R0
#undef R1
-#define MARCHUP for (i=min;i<max;i+=2)
-#define MARCHDOWN for (i=max-1;i>=min;i-=2)
-#define W0 write_sx_word (board, i, 0x55aa)
-#define W1 write_sx_word (board, i, 0xaa55)
-#define R0 if (read_sx_word (board, i) != 0x55aa) return 1
-#define R1 if (read_sx_word (board, i) != 0xaa55) return 1
+#define MARCHUP for (i = min; i < max; i += 2)
+#define MARCHDOWN for (i = max - 1; i >= min; i -= 2)
+#define W0 write_sx_word(board, i, 0x55aa)
+#define W1 write_sx_word(board, i, 0xaa55)
+#define R0 if (read_sx_word(board, i) != 0x55aa) return 1
+#define R1 if (read_sx_word(board, i) != 0xaa55) return 1
#if 0
/* This memtest takes a human-noticable time. You normally only do it
once a boot, so I guess that it is worth it. */
-static int do_memtest_w (struct sx_board *board, int min, int max)
+static int do_memtest_w(struct sx_board *board, int min, int max)
{
int i;
- MARCHUP {W0;}
- MARCHUP {R0;W1;R1;W0;R0;W1;}
- MARCHUP {R1;W0;W1;}
- MARCHDOWN {R1;W0;W1;W0;}
- MARCHDOWN {R0;W1;W0;}
+ MARCHUP {
+ W0;
+ }
+ MARCHUP {
+ R0;
+ W1;
+ R1;
+ W0;
+ R0;
+ W1;
+ }
+ MARCHUP {
+ R1;
+ W0;
+ W1;
+ }
+ MARCHDOWN {
+ R1;
+ W0;
+ W1;
+ W0;
+ }
+ MARCHDOWN {
+ R0;
+ W1;
+ W0;
+ }
return 0;
}
#endif
-
-static int sx_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int sx_fw_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
int rc = 0;
int __user *descr = (int __user *)arg;
@@ -1616,7 +1697,7 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
func_enter();
-#if 0
+#if 0
/* Removed superuser check: Sysops can use the permissions on the device
file to restrict access. Recommendation: Root only. (root.root 600) */
if (!capable(CAP_SYS_ADMIN)) {
@@ -1624,103 +1705,115 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
}
#endif
- sx_dprintk (SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
+ sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
- if (!board) board = &boards[0];
+ if (!board)
+ board = &boards[0];
if (board->flags & SX_BOARD_PRESENT) {
- sx_dprintk (SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
- board->flags);
+ sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
+ board->flags);
} else {
- sx_dprintk (SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
- board->flags);
- for (i=0;i< SX_NBOARDS;i++)
- sx_dprintk (SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
- sx_dprintk (SX_DEBUG_FIRMWARE, "\n");
+ sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
+ board->flags);
+ for (i = 0; i < SX_NBOARDS; i++)
+ sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
+ sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
return -EIO;
}
switch (cmd) {
case SXIO_SET_BOARD:
- sx_dprintk (SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
- if (arg >= SX_NBOARDS) return -EIO;
- sx_dprintk (SX_DEBUG_FIRMWARE, "not out of range\n");
- if (!(boards[arg].flags & SX_BOARD_PRESENT)) return -EIO;
- sx_dprintk (SX_DEBUG_FIRMWARE, ".. and present!\n");
+ sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
+ if (arg >= SX_NBOARDS)
+ return -EIO;
+ sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
+ if (!(boards[arg].flags & SX_BOARD_PRESENT))
+ return -EIO;
+ sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
board = &boards[arg];
break;
case SXIO_GET_TYPE:
- rc = -ENOENT; /* If we manage to miss one, return error. */
- if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
- if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
- if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
- if (IS_SI1_BOARD (board)) rc = SX_TYPE_SI;
- if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
- sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
+ rc = -ENOENT; /* If we manage to miss one, return error. */
+ if (IS_SX_BOARD(board))
+ rc = SX_TYPE_SX;
+ if (IS_CF_BOARD(board))
+ rc = SX_TYPE_CF;
+ if (IS_SI_BOARD(board))
+ rc = SX_TYPE_SI;
+ if (IS_SI1_BOARD(board))
+ rc = SX_TYPE_SI;
+ if (IS_EISA_BOARD(board))
+ rc = SX_TYPE_SI;
+ sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
break;
case SXIO_DO_RAMTEST:
- if (sx_initialized) /* Already initialized: better not ramtest the board. */
+ if (sx_initialized) /* Already initialized: better not ramtest the board. */
return -EPERM;
- if (IS_SX_BOARD (board)) {
- rc = do_memtest (board, 0, 0x7000);
- if (!rc) rc = do_memtest (board, 0, 0x7000);
- /*if (!rc) rc = do_memtest_w (board, 0, 0x7000);*/
+ if (IS_SX_BOARD(board)) {
+ rc = do_memtest(board, 0, 0x7000);
+ if (!rc)
+ rc = do_memtest(board, 0, 0x7000);
+ /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
} else {
- rc = do_memtest (board, 0, 0x7ff8);
+ rc = do_memtest(board, 0, 0x7ff8);
/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
}
- sx_dprintk (SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", rc);
+ sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
+ rc);
break;
case SXIO_DOWNLOAD:
- if (sx_initialized) /* Already initialized */
+ if (sx_initialized) /* Already initialized */
return -EEXIST;
- if (!sx_reset (board))
+ if (!sx_reset(board))
return -EIO;
- sx_dprintk (SX_DEBUG_INIT, "reset the board...\n");
-
- tmp = kmalloc (SX_CHUNK_SIZE, GFP_USER);
- if (!tmp) return -ENOMEM;
- get_user (nbytes, descr++);
- get_user (offset, descr++);
- get_user (data, descr++);
+ sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
+
+ tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
+ if (!tmp)
+ return -ENOMEM;
+ get_user(nbytes, descr++);
+ get_user(offset, descr++);
+ get_user(data, descr++);
while (nbytes && data) {
- for (i=0;i<nbytes;i += SX_CHUNK_SIZE) {
- if (copy_from_user(tmp, (char __user *)data+i,
- (i + SX_CHUNK_SIZE >
- nbytes) ? nbytes - i :
- SX_CHUNK_SIZE)) {
- kfree (tmp);
+ for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
+ if (copy_from_user(tmp, (char __user *)data + i,
+ (i + SX_CHUNK_SIZE > nbytes) ?
+ nbytes - i : SX_CHUNK_SIZE)) {
+ kfree(tmp);
return -EFAULT;
}
- memcpy_toio(board->base2 + offset + i, tmp,
- (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
+ memcpy_toio(board->base2 + offset + i, tmp,
+ (i + SX_CHUNK_SIZE > nbytes) ?
+ nbytes - i : SX_CHUNK_SIZE);
}
- get_user (nbytes, descr++);
- get_user (offset, descr++);
- get_user (data, descr++);
+ get_user(nbytes, descr++);
+ get_user(offset, descr++);
+ get_user(data, descr++);
}
- kfree (tmp);
- sx_nports += sx_init_board (board);
+ kfree(tmp);
+ sx_nports += sx_init_board(board);
rc = sx_nports;
break;
case SXIO_INIT:
- if (sx_initialized) /* Already initialized */
+ if (sx_initialized) /* Already initialized */
return -EEXIST;
/* This is not allowed until all boards are initialized... */
- for (i=0;i<SX_NBOARDS;i++) {
- if ( (boards[i].flags & SX_BOARD_PRESENT) &&
- !(boards[i].flags & SX_BOARD_INITIALIZED))
+ for (i = 0; i < SX_NBOARDS; i++) {
+ if ((boards[i].flags & SX_BOARD_PRESENT) &&
+ !(boards[i].flags & SX_BOARD_INITIALIZED))
return -EIO;
}
- for (i=0;i<SX_NBOARDS;i++)
- if (!(boards[i].flags & SX_BOARD_PRESENT)) break;
-
- sx_dprintk (SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
- "%d channels, first board: %d ports\n",
- i, sx_nports, boards[0].nports);
- rc = sx_init_portstructs (i, sx_nports);
- sx_init_drivers ();
- if (rc >= 0)
+ for (i = 0; i < SX_NBOARDS; i++)
+ if (!(boards[i].flags & SX_BOARD_PRESENT))
+ break;
+
+ sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
+ "%d channels, first board: %d ports\n",
+ i, sx_nports, boards[0].nports);
+ rc = sx_init_portstructs(i, sx_nports);
+ sx_init_drivers();
+ if (rc >= 0)
sx_initialized++;
break;
case SXIO_SETDEBUG:
@@ -1737,32 +1830,32 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
rc = sx_nports;
break;
default:
- printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd);
+ printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
+ cmd);
break;
}
- func_exit ();
+ func_exit();
return rc;
}
-
-static void sx_break (struct tty_struct * tty, int flag)
+static void sx_break(struct tty_struct *tty, int flag)
{
struct sx_port *port = tty->driver_data;
int rv;
- func_enter ();
+ 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)));
+ 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 ();
+ func_exit();
}
-
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
{
struct sx_port *port = tty->driver_data;
@@ -1770,7 +1863,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
}
static int sx_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
struct sx_port *port = tty->driver_data;
int rts = -1, dtr = -1;
@@ -1789,8 +1882,8 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static int sx_ioctl (struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
int rc;
struct sx_port *port = tty->driver_data;
@@ -1803,10 +1896,10 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
switch (cmd) {
case TIOCGSOFTCAR:
rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
- (unsigned __user *) argp);
+ (unsigned __user *)argp);
break;
case TIOCSSOFTCAR:
- if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
+ if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) {
tty->termios->c_cflag =
(tty->termios->c_cflag & ~CLOCAL) |
(ival ? CLOCAL : 0);
@@ -1827,7 +1920,6 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
return rc;
}
-
/* The throttle/unthrottle scheme for the Specialix card is different
* from other drivers and deserves some explanation.
* The Specialix hardware takes care of XON/XOFF
@@ -1844,7 +1936,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
* flow control scheme is in use for that port. -- Simon Allen
*/
-static void sx_throttle (struct tty_struct * tty)
+static void sx_throttle(struct tty_struct *tty)
{
struct sx_port *port = (struct sx_port *)tty->driver_data;
@@ -1852,14 +1944,13 @@ static void sx_throttle (struct tty_struct * tty)
/* If the port is using any type of input flow
* control then throttle the port.
*/
- if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {
+ if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
port->gs.flags |= SX_RX_THROTTLE;
}
func_exit();
}
-
-static void sx_unthrottle (struct tty_struct * tty)
+static void sx_unthrottle(struct tty_struct *tty)
{
struct sx_port *port = (struct sx_port *)tty->driver_data;
@@ -1873,15 +1964,11 @@ static void sx_unthrottle (struct tty_struct * tty)
return;
}
-
/* ********************************************************************** *
* Here are the initialization routines. *
* ********************************************************************** */
-
-
-
-static int sx_init_board (struct sx_board *board)
+static int sx_init_board(struct sx_board *board)
{
int addr;
int chans;
@@ -1893,36 +1980,38 @@ static int sx_init_board (struct sx_board *board)
board->flags |= SX_BOARD_INITIALIZED;
- if (read_sx_byte (board, 0))
+ if (read_sx_byte(board, 0))
/* CF boards may need this. */
- write_sx_byte(board,0, 0);
+ write_sx_byte(board, 0, 0);
/* This resets the processor again, to make sure it didn't do any
foolish things while we were downloading the image */
- if (!sx_reset (board))
+ if (!sx_reset(board))
return 0;
- sx_start_board (board);
- udelay (10);
- if (!sx_busy_wait_neq (board, 0, 0xff, 0)) {
- printk (KERN_ERR "sx: Ooops. Board won't initialize.\n");
+ sx_start_board(board);
+ udelay(10);
+ if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
+ printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
return 0;
}
/* Ok. So now the processor on the card is running. It gathered
some info for us... */
- sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n");
- if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base, 0x10);
- sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n");
- if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base + 0x80, 0x30);
-
- sx_dprintk (SX_DEBUG_INIT,
- "init_status: %x, %dk memory, firmware V%x.%02x,\n",
- read_sx_byte (board, 0), read_sx_byte(board, 1),
- read_sx_byte (board, 5), read_sx_byte(board, 4));
-
- if (read_sx_byte (board, 0) == 0xff) {
- printk (KERN_INFO "sx: No modules found. Sorry.\n");
+ sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
+ if (sx_debug & SX_DEBUG_INIT)
+ my_hd_io(board->base, 0x10);
+ sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
+ if (sx_debug & SX_DEBUG_INIT)
+ my_hd_io(board->base + 0x80, 0x30);
+
+ sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
+ "V%x.%02x,\n",
+ read_sx_byte(board, 0), read_sx_byte(board, 1),
+ read_sx_byte(board, 5), read_sx_byte(board, 4));
+
+ if (read_sx_byte(board, 0) == 0xff) {
+ printk(KERN_INFO "sx: No modules found. Sorry.\n");
board->nports = 0;
return 0;
}
@@ -1930,82 +2019,97 @@ static int sx_init_board (struct sx_board *board)
chans = 0;
if (IS_SX_BOARD(board)) {
- sx_write_board_word (board, cc_int_count, sx_maxints);
+ sx_write_board_word(board, cc_int_count, sx_maxints);
} else {
if (sx_maxints)
- sx_write_board_word (board, cc_int_count, SI_PROCESSOR_CLOCK/8/sx_maxints);
+ sx_write_board_word(board, cc_int_count,
+ SI_PROCESSOR_CLOCK / 8 / sx_maxints);
}
/* grab the first module type... */
- /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
- board->ta_type = mod_compat_type (sx_read_module_byte (board, 0x80, mc_chip));
+ /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
+ board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
+ mc_chip));
/* XXX byteorder */
- for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) {
- type = sx_read_module_byte (board, addr, mc_chip);
- sx_dprintk (SX_DEBUG_INIT, "Module at %x: %d channels\n",
- addr, read_sx_byte (board, addr + 2));
-
- chans += sx_read_module_byte (board, addr, mc_type);
-
- sx_dprintk (SX_DEBUG_INIT, "module is an %s, which has %s/%s panels\n",
- mod_type_s (type),
- pan_type_s (sx_read_module_byte (board, addr, mc_mods) & 0xf),
- pan_type_s (sx_read_module_byte (board, addr, mc_mods) >> 4));
-
- sx_dprintk (SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC version: %x\n",
- sx_read_module_byte (board, addr, mc_rev1),
- sx_read_module_byte (board, addr, mc_rev2),
- sx_read_module_byte (board, addr, mc_mtaasic_rev));
+ for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
+ type = sx_read_module_byte(board, addr, mc_chip);
+ sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
+ addr, read_sx_byte(board, addr + 2));
+
+ chans += sx_read_module_byte(board, addr, mc_type);
+
+ sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
+ "panels\n",
+ mod_type_s(type),
+ pan_type_s(sx_read_module_byte(board, addr,
+ mc_mods) & 0xf),
+ pan_type_s(sx_read_module_byte(board, addr,
+ mc_mods) >> 4));
+
+ sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
+ "version: %x\n",
+ sx_read_module_byte(board, addr, mc_rev1),
+ sx_read_module_byte(board, addr, mc_rev2),
+ sx_read_module_byte(board, addr, mc_mtaasic_rev));
/* The following combinations are illegal: It should theoretically
work, but timing problems make the bus HANG. */
- if (mod_compat_type (type) != board->ta_type) {
- printk (KERN_ERR "sx: This is an invalid configuration.\n"
- "Don't mix TA/MTA/SXDC on the same hostadapter.\n");
- chans=0;
+ if (mod_compat_type(type) != board->ta_type) {
+ printk(KERN_ERR "sx: This is an invalid "
+ "configuration.\nDon't mix TA/MTA/SXDC on the "
+ "same hostadapter.\n");
+ chans = 0;
break;
}
- if ((IS_EISA_BOARD(board) ||
- IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) {
- printk (KERN_ERR "sx: This is an invalid configuration.\n"
- "Don't use SXDCs on an SI/XIO adapter.\n");
- chans=0;
+ if ((IS_EISA_BOARD(board) ||
+ IS_SI_BOARD(board)) &&
+ (mod_compat_type(type) == 4)) {
+ printk(KERN_ERR "sx: This is an invalid "
+ "configuration.\nDon't use SXDCs on an SI/XIO "
+ "adapter.\n");
+ chans = 0;
break;
}
-#if 0 /* Problem fixed: firmware 3.05 */
+#if 0 /* Problem fixed: firmware 3.05 */
if (IS_SX_BOARD(board) && (type == TA8)) {
/* There are some issues with the firmware and the DCD/RTS
lines. It might work if you tie them together or something.
- It might also work if you get a newer sx_firmware. Therefore
+ It might also work if you get a newer sx_firmware. Therefore
this is just a warning. */
- printk (KERN_WARNING "sx: The SX host doesn't work too well "
- "with the TA8 adapters.\nSpecialix is working on it.\n");
+ printk(KERN_WARNING
+ "sx: The SX host doesn't work too well "
+ "with the TA8 adapters.\nSpecialix is working on it.\n");
}
#endif
}
if (chans) {
- /* board->flags |= SX_BOARD_PRESENT; */
- if(board->irq > 0) {
+ if (board->irq > 0) {
/* fixed irq, probably PCI */
- if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
- if(request_irq(board->irq, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board)) {
- printk(KERN_ERR "sx: Cannot allocate irq %d.\n", board->irq);
+ if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
+ if (request_irq(board->irq, sx_interrupt,
+ IRQF_SHARED | IRQF_DISABLED,
+ "sx", board)) {
+ printk(KERN_ERR "sx: Cannot allocate "
+ "irq %d.\n", board->irq);
board->irq = 0;
}
} else
board->irq = 0;
- } else if(board->irq < 0 && sx_irqmask) {
+ } else if (board->irq < 0 && sx_irqmask) {
/* auto-allocate irq */
int irqnr;
- int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
- for(irqnr = 15; irqnr > 0; irqnr--)
- if(irqmask & (1 << irqnr))
- if(! request_irq(irqnr, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board))
+ int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
+ SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
+ for (irqnr = 15; irqnr > 0; irqnr--)
+ if (irqmask & (1 << irqnr))
+ if (!request_irq(irqnr, sx_interrupt,
+ IRQF_SHARED | IRQF_DISABLED,
+ "sx", board))
break;
- if(! irqnr)
+ if (!irqnr)
printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
board->irq = irqnr;
} else
@@ -2013,52 +2117,48 @@ static int sx_init_board (struct sx_board *board)
if (board->irq) {
/* Found a valid interrupt, start up interrupts! */
- sx_dprintk (SX_DEBUG_INIT, "Using irq %d.\n", board->irq);
- sx_start_interrupts (board);
+ sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
+ board->irq);
+ sx_start_interrupts(board);
board->poll = sx_slowpoll;
board->flags |= SX_IRQ_ALLOCATED;
} else {
/* no irq: setup board for polled operation */
board->poll = sx_poll;
- sx_dprintk (SX_DEBUG_INIT, "Using poll-interval %d.\n", board->poll);
+ sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
+ board->poll);
}
- /* The timer should be initialized anyway: That way we can safely
- del_timer it when the module is unloaded. */
- init_timer (&board->timer);
+ /* The timer should be initialized anyway: That way we can
+ safely del_timer it when the module is unloaded. */
+ setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
- if (board->poll) {
- board->timer.data = (unsigned long) board;
- board->timer.function = sx_pollfunc;
- board->timer.expires = jiffies + board->poll;
- add_timer (&board->timer);
- }
+ if (board->poll)
+ mod_timer(&board->timer, jiffies + board->poll);
} else {
board->irq = 0;
}
board->nports = chans;
- sx_dprintk (SX_DEBUG_INIT, "returning %d ports.", board->nports);
+ sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
func_exit();
return chans;
}
-
-static void printheader(void)
+static void __devinit printheader(void)
{
static int header_printed;
if (!header_printed) {
- printk (KERN_INFO "Specialix SX driver "
- "(C) 1998/1999 R.E.Wolff@BitWizard.nl \n");
- printk (KERN_INFO "sx: version %s\n", RCS_ID);
+ printk(KERN_INFO "Specialix SX driver "
+ "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
+ printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
header_printed = 1;
}
}
-
-static int probe_sx (struct sx_board *board)
+static int __devinit probe_sx(struct sx_board *board)
{
struct vpd_prom vpdp;
char *p;
@@ -2066,51 +2166,57 @@ static int probe_sx (struct sx_board *board)
func_enter();
- if (!IS_CF_BOARD (board)) {
- sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
- board->base + SX_VPD_ROM);
+ if (!IS_CF_BOARD(board)) {
+ sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
+ board->base + SX_VPD_ROM);
if (sx_debug & SX_DEBUG_PROBE)
my_hd_io(board->base + SX_VPD_ROM, 0x40);
- p = (char *) &vpdp;
- for (i=0;i< sizeof (struct vpd_prom);i++)
- *p++ = read_sx_byte (board, SX_VPD_ROM + i*2);
+ p = (char *)&vpdp;
+ for (i = 0; i < sizeof(struct vpd_prom); i++)
+ *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
if (sx_debug & SX_DEBUG_PROBE)
- my_hd (&vpdp, 0x20);
+ my_hd(&vpdp, 0x20);
- sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n");
+ sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
- if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
- sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n",
- vpdp.identifier);
+ if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
+ sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
+ "'%s'\n", vpdp.identifier);
return 0;
}
}
- printheader ();
-
- if (!IS_CF_BOARD (board)) {
- printk (KERN_DEBUG "sx: Found an SX board at %lx\n", board->hw_base);
- printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ",
- vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
- printk ( "Manufactured: %d/%d\n",
- 1970 + vpdp.myear, vpdp.mweek);
+ printheader();
+ if (!IS_CF_BOARD(board)) {
+ printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
+ board->hw_base);
+ printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
+ "uniq ID:%08x, ",
+ vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
+ printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
- if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) &&
- (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
- /* This might be a bit harsh. This was the primary reason the
- SX/ISA card didn't work at first... */
- printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n");
+ if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
+ SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
+ SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
+ /* This might be a bit harsh. This was the primary
+ reason the SX/ISA card didn't work at first... */
+ printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
+ "card. Sorry: giving up.\n");
return (0);
}
- if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
+ if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
+ SX_ISA_UNIQUEID1) {
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");
+ 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");
}
}
}
@@ -2118,17 +2224,15 @@ static int probe_sx (struct sx_board *board)
board->nports = -1;
/* This resets the processor, and keeps it off the bus. */
- if (!sx_reset (board))
+ if (!sx_reset(board))
return 0;
- sx_dprintk (SX_DEBUG_INIT, "reset the board...\n");
-
- board->flags |= SX_BOARD_PRESENT;
+ sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
func_exit();
return 1;
}
-
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
/* Specialix probes for this card at 32k increments from 640k to 16M.
I consider machines with less than 16M unlikely nowadays, so I'm
@@ -2136,28 +2240,27 @@ static int probe_sx (struct sx_board *board)
card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves
0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
-static int probe_si (struct sx_board *board)
+static int __devinit probe_si(struct sx_board *board)
{
int i;
func_enter();
- sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %p.\n", board->hw_base,
- board->base + SI2_ISA_ID_BASE);
+ sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
+ "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
if (sx_debug & SX_DEBUG_PROBE)
my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
if (!IS_EISA_BOARD(board)) {
- if( IS_SI1_BOARD(board) )
- {
- for (i=0;i<8;i++) {
- write_sx_byte (board, SI2_ISA_ID_BASE+7-i,i);
-
+ if (IS_SI1_BOARD(board)) {
+ for (i = 0; i < 8; i++) {
+ write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
+ }
}
- }
- for (i=0;i<8;i++) {
- if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
- func_exit ();
+ for (i = 0; i < 8; i++) {
+ if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
+ != i) {
+ func_exit();
return 0;
}
}
@@ -2167,20 +2270,20 @@ static int probe_si (struct sx_board *board)
but to prevent trouble, we'd better double check that we don't
have an SI1 board when we're probing for an SI2 board.... */
- write_sx_byte (board, SI2_ISA_ID_BASE,0x10);
- if ( IS_SI1_BOARD(board)) {
+ write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
+ if (IS_SI1_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;
+ 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;
+ if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
+ func_exit();
+ return 0;
}
}
@@ -2188,45 +2291,44 @@ static int probe_si (struct sx_board *board)
but to prevent trouble, we'd better double check that we don't
have an SI1 board when we're probing for an SI2 board.... */
- write_sx_byte (board, SI2_ISA_ID_BASE,0x10);
- if ( IS_SI1_BOARD(board)) {
+ write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
+ if (IS_SI1_BOARD(board)) {
/* This should be an SI1 board, which has this
location writable... */
- if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) {
+ if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
func_exit();
- return 0;
+ 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;
+ if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
+ func_exit();
+ return 0;
}
}
- printheader ();
+ printheader();
- printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
+ printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
/* Compared to the SX boards, it is a complete guess as to what
- this card is up to... */
+ this card is up to... */
board->nports = -1;
/* This resets the processor, and keeps it off the bus. */
- if (!sx_reset (board))
+ if (!sx_reset(board))
return 0;
- sx_dprintk (SX_DEBUG_INIT, "reset the board...\n");
-
- board->flags |= SX_BOARD_PRESENT;
+ sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
func_exit();
return 1;
}
+#endif
static const struct tty_operations sx_ops = {
.break_ctl = sx_break,
- .open = sx_open,
+ .open = sx_open,
.close = gs_close,
.write = gs_write,
.put_char = gs_put_char,
@@ -2261,34 +2363,23 @@ static int sx_init_drivers(void)
sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
sx_driver->subtype = SERIAL_TYPE_NORMAL;
sx_driver->init_termios = tty_std_termios;
- sx_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ sx_driver->init_termios.c_ispeed = 9600;
+ sx_driver->init_termios.c_ospeed = 9600;
sx_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(sx_driver, &sx_ops);
if ((error = tty_register_driver(sx_driver))) {
put_tty_driver(sx_driver);
printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
- error);
+ error);
return 1;
}
func_exit();
return 0;
}
-
-static void * ckmalloc (int size)
-{
- void *p;
-
- p = kmalloc(size, GFP_KERNEL);
- if (p)
- memset(p, 0, size);
- return p;
-}
-
-
-static int sx_init_portstructs (int nboards, int nports)
+static int sx_init_portstructs(int nboards, int nports)
{
struct sx_board *board;
struct sx_port *port;
@@ -2299,8 +2390,9 @@ static int sx_init_portstructs (int nboards, int nports)
func_enter();
/* Many drivers statically allocate the maximum number of ports
- There is no reason not to allocate them dynamically. Is there? -- REW */
- sx_ports = ckmalloc(nports * sizeof (struct sx_port));
+ There is no reason not to allocate them dynamically.
+ Is there? -- REW */
+ sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
if (!sx_ports)
return -ENOMEM;
@@ -2308,10 +2400,10 @@ static int sx_init_portstructs (int nboards, int nports)
for (i = 0; i < nboards; i++) {
board = &boards[i];
board->ports = port;
- for (j=0; j < boards[i].nports;j++) {
- sx_dprintk (SX_DEBUG_INIT, "initing port %d\n", j);
+ for (j = 0; j < boards[i].nports; j++) {
+ sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
port->gs.magic = SX_MAGIC;
- port->gs.close_delay = HZ/2;
+ port->gs.close_delay = HZ / 2;
port->gs.closing_wait = 30 * HZ;
port->board = board;
port->gs.rd = &sx_real_driver;
@@ -2323,8 +2415,8 @@ static int sx_init_portstructs (int nboards, int nports)
* Initializing wait queue
*/
init_waitqueue_head(&port->gs.open_wait);
- init_waitqueue_head(&port->gs.close_wait);
-
+ init_waitqueue_head(&port->gs.close_wait);
+
port++;
}
}
@@ -2335,28 +2427,36 @@ static int sx_init_portstructs (int nboards, int nports)
board = &boards[i];
board->port_base = portno;
/* Possibly the configuration was rejected. */
- sx_dprintk (SX_DEBUG_PROBE, "Board has %d channels\n", board->nports);
- if (board->nports <= 0) continue;
+ sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
+ board->nports);
+ if (board->nports <= 0)
+ continue;
/* XXX byteorder ?? */
- for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) {
- chans = sx_read_module_byte (board, addr, mc_type);
- sx_dprintk (SX_DEBUG_PROBE, "Module at %x: %d channels\n", addr, chans);
- sx_dprintk (SX_DEBUG_PROBE, "Port at");
- for (j=0;j<chans;j++) {
- /* The "sx-way" is the way it SHOULD be done. That way in the
- future, the firmware may for example pack the structures a bit
- more efficient. Neil tells me it isn't going to happen anytime
- soon though. */
+ for (addr = 0x80; addr != 0;
+ addr = read_sx_word(board, addr) & 0x7fff) {
+ chans = sx_read_module_byte(board, addr, mc_type);
+ sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
+ "channels\n", addr, chans);
+ sx_dprintk(SX_DEBUG_PROBE, "Port at");
+ for (j = 0; j < chans; j++) {
+ /* The "sx-way" is the way it SHOULD be done.
+ That way in the future, the firmware may for
+ example pack the structures a bit more
+ efficient. Neil tells me it isn't going to
+ happen anytime soon though. */
if (IS_SX_BOARD(board))
- port->ch_base = sx_read_module_word (board, addr+j*2, mc_chan_pointer);
+ port->ch_base = sx_read_module_word(
+ board, addr + j * 2,
+ mc_chan_pointer);
else
- port->ch_base = addr + 0x100 + 0x300*j;
+ port->ch_base = addr + 0x100 + 0x300 *j;
- sx_dprintk (SX_DEBUG_PROBE, " %x", port->ch_base);
+ sx_dprintk(SX_DEBUG_PROBE, " %x",
+ port->ch_base);
port->line = portno++;
port++;
}
- sx_dprintk (SX_DEBUG_PROBE, "\n");
+ sx_dprintk(SX_DEBUG_PROBE, "\n");
}
/* This has to be done earlier. */
/* board->flags |= SX_BOARD_INITIALIZED; */
@@ -2366,6 +2466,17 @@ static int sx_init_portstructs (int nboards, int nports)
return 0;
}
+static unsigned int sx_find_free_board(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < SX_NBOARDS; i++)
+ if (!(boards[i].flags & SX_BOARD_PRESENT))
+ break;
+
+ return i;
+}
+
static void __exit sx_release_drivers(void)
{
func_enter();
@@ -2374,6 +2485,124 @@ static void __exit sx_release_drivers(void)
func_exit();
}
+static void __devexit sx_remove_card(struct sx_board *board,
+ struct pci_dev *pdev)
+{
+ if (board->flags & SX_BOARD_INITIALIZED) {
+ /* The board should stop messing with us. (actually I mean the
+ interrupt) */
+ sx_reset(board);
+ if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
+ free_irq(board->irq, board);
+
+ /* It is safe/allowed to del_timer a non-active timer */
+ del_timer(&board->timer);
+ if (pdev) {
+#ifdef CONFIG_PCI
+ pci_iounmap(pdev, board->base);
+ pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
+#endif
+ } else {
+ iounmap(board->base);
+ release_region(board->hw_base, board->hw_len);
+ }
+
+ board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
+ }
+}
+
+#ifdef CONFIG_EISA
+
+static int __devinit sx_eisa_probe(struct device *dev)
+{
+ struct eisa_device *edev = to_eisa_device(dev);
+ struct sx_board *board;
+ unsigned long eisa_slot = edev->base_addr;
+ unsigned int i;
+ int retval = -EIO;
+
+ mutex_lock(&sx_boards_lock);
+ i = sx_find_free_board();
+ if (i == SX_NBOARDS) {
+ mutex_unlock(&sx_boards_lock);
+ goto err;
+ }
+ board = &boards[i];
+ board->flags |= SX_BOARD_PRESENT;
+ mutex_unlock(&sx_boards_lock);
+
+ dev_info(dev, "XIO : Signature found in EISA slot %lu, "
+ "Product %d Rev %d (REPORT THIS TO LKLM)\n",
+ eisa_slot >> 12,
+ inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
+ inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
+
+ board->eisa_base = eisa_slot;
+ board->flags &= ~SX_BOARD_TYPE;
+ board->flags |= SI_EISA_BOARD;
+
+ board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
+ inb(eisa_slot + 0xc00)) << 16;
+ board->hw_len = SI2_EISA_WINDOW_LEN;
+ if (!request_region(board->hw_base, board->hw_len, "sx")) {
+ dev_err(dev, "can't request region\n");
+ goto err_flag;
+ }
+ board->base2 =
+ board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+ if (!board->base) {
+ dev_err(dev, "can't remap memory\n");
+ goto err_reg;
+ }
+
+ sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
+ sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
+ board->irq = inb(eisa_slot + 0xc02) >> 4;
+ sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+
+ if (!probe_si(board))
+ goto err_unmap;
+
+ dev_set_drvdata(dev, board);
+
+ return 0;
+err_unmap:
+ iounmap(board->base);
+err_reg:
+ release_region(board->hw_base, board->hw_len);
+err_flag:
+ board->flags &= ~SX_BOARD_PRESENT;
+err:
+ return retval;
+}
+
+static int __devexit sx_eisa_remove(struct device *dev)
+{
+ struct sx_board *board = dev_get_drvdata(dev);
+
+ sx_remove_card(board, NULL);
+
+ return 0;
+}
+
+static struct eisa_device_id sx_eisa_tbl[] = {
+ { "SLX" },
+ { "" }
+};
+
+MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
+
+static struct eisa_driver sx_eisadriver = {
+ .id_table = sx_eisa_tbl,
+ .driver = {
+ .name = "sx",
+ .probe = sx_eisa_probe,
+ .remove = __devexit_p(sx_eisa_remove),
+ }
+};
+
+#endif
+
#ifdef CONFIG_PCI
/********************************************************
* Setting bit 17 in the CNTRL register of the PLX 9050 *
@@ -2386,233 +2615,270 @@ static void __exit sx_release_drivers(void)
EEprom. As the bit is read/write for the CPU, we can fix it here,
if we detect that it isn't set correctly. -- REW */
-static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board)
+static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
{
unsigned int hwbase;
void __iomem *rebase;
unsigned int t;
-#define CNTRL_REG_OFFSET 0x50
-#define CNTRL_REG_GOODVALUE 0x18260000
+#define CNTRL_REG_OFFSET 0x50
+#define CNTRL_REG_GOODVALUE 0x18260000
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
rebase = ioremap(hwbase, 0x80);
- t = readl (rebase + CNTRL_REG_OFFSET);
+ t = readl(rebase + CNTRL_REG_OFFSET);
if (t != CNTRL_REG_GOODVALUE) {
- printk (KERN_DEBUG "sx: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
- writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
+ printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
+ "%08x\n", t, CNTRL_REG_GOODVALUE);
+ writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
}
iounmap(rebase);
}
#endif
-
-static int __init sx_init(void)
+static int __devinit sx_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- int i;
- int found = 0;
- int eisa_slot;
+#ifdef CONFIG_PCI
struct sx_board *board;
+ unsigned int i, reg;
+ int retval = -EIO;
-#ifdef CONFIG_PCI
- struct pci_dev *pdev = NULL;
- unsigned int tint;
- unsigned short tshort;
-#endif
+ mutex_lock(&sx_boards_lock);
+ i = sx_find_free_board();
+ if (i == SX_NBOARDS) {
+ mutex_unlock(&sx_boards_lock);
+ goto err;
+ }
+ board = &boards[i];
+ board->flags |= SX_BOARD_PRESENT;
+ mutex_unlock(&sx_boards_lock);
- func_enter();
- sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug);
- if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) {
- printk (KERN_WARNING "sx: sx_debug is an address, instead of a value. "
- "Assuming -1.\n");
- printk ("(%p)\n", &sx_debug);
- sx_debug=-1;
+ retval = pci_enable_device(pdev);
+ if (retval)
+ goto err_flag;
+
+ board->flags &= ~SX_BOARD_TYPE;
+ board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
+ SX_CFPCI_BOARD;
+
+ /* CF boards use base address 3.... */
+ reg = IS_CF_BOARD(board) ? 3 : 2;
+ retval = pci_request_region(pdev, reg, "sx");
+ if (retval) {
+ dev_err(&pdev->dev, "can't request region\n");
+ goto err_flag;
+ }
+ board->hw_base = pci_resource_start(pdev, reg);
+ board->base2 =
+ board->base = pci_iomap(pdev, reg, WINDOW_LEN(board));
+ if (!board->base) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ goto err_reg;
}
- if (misc_register(&sx_fw_device) < 0) {
- printk(KERN_ERR "SX: Unable to register firmware loader driver.\n");
- return -EIO;
+ /* Most of the stuff on the CF board is offset by 0x18000 .... */
+ if (IS_CF_BOARD(board))
+ board->base += 0x18000;
+
+ board->irq = pdev->irq;
+
+ dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
+ board->irq, board->flags);
+
+ if (!probe_sx(board)) {
+ retval = -EIO;
+ goto err_unmap;
}
-#ifdef CONFIG_PCI
- while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- pdev))) {
- if (pci_enable_device(pdev))
- continue;
+ fix_sx_pci(pdev, board);
- /* Specialix has a whole bunch of cards with
- 0x2000 as the device ID. They say its because
- the standard requires it. Stupid standard. */
- /* It seems that reading a word doesn't work reliably on 2.0.
- Also, reading a non-aligned dword doesn't work. So we read the
- whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
- ourselves */
- /* I don't know why the define doesn't work, constant 0x2c does --REW */
- pci_read_config_dword (pdev, 0x2c, &tint);
- tshort = (tint >> 16) & 0xffff;
- sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
- /* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */
- if ((tshort != 0x0200) && (tshort != 0x0300)) {
- sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n",
- tshort);
- continue;
- }
- board = &boards[found];
+ pci_set_drvdata(pdev, board);
- board->flags &= ~SX_BOARD_TYPE;
- board->flags |= (tshort == 0x200)?SX_PCI_BOARD:
- SX_CFPCI_BOARD;
-
- /* CF boards use base address 3.... */
- if (IS_CF_BOARD (board))
- board->hw_base = pci_resource_start (pdev, 3);
- else
- board->hw_base = pci_resource_start (pdev, 2);
- board->base2 =
- board->base = ioremap(board->hw_base, WINDOW_LEN (board));
- if (!board->base) {
- printk(KERN_ERR "ioremap failed\n");
- /* XXX handle error */
- }
+ return 0;
+err_unmap:
+ pci_iounmap(pdev, board->base);
+err_reg:
+ pci_release_region(pdev, reg);
+err_flag:
+ board->flags &= ~SX_BOARD_PRESENT;
+err:
+ return retval;
+#else
+ return -ENODEV;
+#endif
+}
- /* Most of the stuff on the CF board is offset by
- 0x18000 .... */
- if (IS_CF_BOARD (board)) board->base += 0x18000;
+static void __devexit sx_pci_remove(struct pci_dev *pdev)
+{
+ struct sx_board *board = pci_get_drvdata(pdev);
- board->irq = pdev->irq;
+ sx_remove_card(board, pdev);
+}
- sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%p(%d) %x.\n",
- tint, boards[found].base, board->irq, board->flags);
+/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
+ its because the standard requires it. So check for SUBVENDOR_ID. */
+static struct pci_device_id sx_pci_tbl[] = {
+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
+ .subvendor = 0x0200,.subdevice = PCI_ANY_ID },
+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
+ .subvendor = 0x0300,.subdevice = PCI_ANY_ID },
+ { 0 }
+};
- if (probe_sx (board)) {
- found++;
- fix_sx_pci (pdev, board);
- } else
- iounmap(board->base2);
- }
+MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
+
+static struct pci_driver sx_pcidriver = {
+ .name = "sx",
+ .id_table = sx_pci_tbl,
+ .probe = sx_pci_probe,
+ .remove = __devexit_p(sx_pci_remove)
+};
+
+static int __init sx_init(void)
+{
+#ifdef CONFIG_EISA
+ int retval1;
+#endif
+#ifdef CONFIG_ISA
+ struct sx_board *board;
+ unsigned int i;
#endif
+ unsigned int found = 0;
+ int retval;
- for (i=0;i<NR_SX_ADDRS;i++) {
+ func_enter();
+ sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
+ sx_debug);
+ if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
+ printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
+ "value. Assuming -1.\n(%p)\n", &sx_debug);
+ sx_debug = -1;
+ }
+
+ if (misc_register(&sx_fw_device) < 0) {
+ printk(KERN_ERR "SX: Unable to register firmware loader "
+ "driver.\n");
+ return -EIO;
+ }
+#ifdef CONFIG_ISA
+ for (i = 0; i < NR_SX_ADDRS; i++) {
board = &boards[found];
board->hw_base = sx_probe_addrs[i];
+ board->hw_len = SX_WINDOW_LEN;
+ if (!request_region(board->hw_base, board->hw_len, "sx"))
+ continue;
board->base2 =
- board->base = ioremap(board->hw_base, SX_WINDOW_LEN);
+ board->base = ioremap(board->hw_base, board->hw_len);
+ if (!board->base)
+ goto err_sx_reg;
board->flags &= ~SX_BOARD_TYPE;
- board->flags |= SX_ISA_BOARD;
- board->irq = sx_irqmask?-1:0;
+ board->flags |= SX_ISA_BOARD;
+ board->irq = sx_irqmask ? -1 : 0;
- if (probe_sx (board)) {
+ if (probe_sx(board)) {
+ board->flags |= SX_BOARD_PRESENT;
found++;
} else {
iounmap(board->base);
+err_sx_reg:
+ release_region(board->hw_base, board->hw_len);
}
}
- for (i=0;i<NR_SI_ADDRS;i++) {
+ for (i = 0; i < NR_SI_ADDRS; i++) {
board = &boards[found];
board->hw_base = si_probe_addrs[i];
+ board->hw_len = SI2_ISA_WINDOW_LEN;
+ if (!request_region(board->hw_base, board->hw_len, "sx"))
+ continue;
board->base2 =
- board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
+ board->base = ioremap(board->hw_base, board->hw_len);
+ if (!board->base)
+ goto err_si_reg;
board->flags &= ~SX_BOARD_TYPE;
- board->flags |= SI_ISA_BOARD;
- board->irq = sx_irqmask ?-1:0;
+ board->flags |= SI_ISA_BOARD;
+ board->irq = sx_irqmask ? -1 : 0;
- if (probe_si (board)) {
+ if (probe_si(board)) {
+ board->flags |= SX_BOARD_PRESENT;
found++;
} else {
- iounmap (board->base);
+ iounmap(board->base);
+err_si_reg:
+ release_region(board->hw_base, board->hw_len);
}
}
- for (i=0;i<NR_SI1_ADDRS;i++) {
+ for (i = 0; i < NR_SI1_ADDRS; i++) {
board = &boards[found];
board->hw_base = si1_probe_addrs[i];
+ board->hw_len = SI1_ISA_WINDOW_LEN;
+ if (!request_region(board->hw_base, board->hw_len, "sx"))
+ continue;
board->base2 =
- board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN);
+ board->base = ioremap(board->hw_base, board->hw_len);
+ if (!board->base)
+ goto err_si1_reg;
board->flags &= ~SX_BOARD_TYPE;
- board->flags |= SI1_ISA_BOARD;
- board->irq = sx_irqmask ?-1:0;
+ board->flags |= SI1_ISA_BOARD;
+ board->irq = sx_irqmask ? -1 : 0;
- if (probe_si (board)) {
+ if (probe_si(board)) {
+ board->flags |= SX_BOARD_PRESENT;
found++;
} else {
- iounmap (board->base);
+ iounmap(board->base);
+err_si1_reg:
+ release_region(board->hw_base, board->hw_len);
}
}
+#endif
+#ifdef CONFIG_EISA
+ retval1 = eisa_driver_register(&sx_eisadriver);
+#endif
+ retval = pci_register_driver(&sx_pcidriver);
- sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n");
- for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000)
- {
- if((inb(eisa_slot+0xc80)==0x4d) &&
- (inb(eisa_slot+0xc81)==0x98))
- {
- sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n",
- "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83));
-
- board = &boards[found];
- board->eisa_base = eisa_slot;
- board->flags &= ~SX_BOARD_TYPE;
- board->flags |= SI_EISA_BOARD;
-
- board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16);
- board->base2 =
- board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
-
- sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
- sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
- board->irq = inb(board->eisa_base+0xc02)>>4;
- sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
-
- probe_si(board);
-
- found++;
- }
- }
if (found) {
- printk (KERN_INFO "sx: total of %d boards detected.\n", found);
- } else {
- misc_deregister(&sx_fw_device);
+ printk(KERN_INFO "sx: total of %d boards detected.\n", found);
+ retval = 0;
+ } else if (retval) {
+#ifdef CONFIG_EISA
+ retval = retval1;
+ if (retval1)
+#endif
+ misc_deregister(&sx_fw_device);
}
func_exit();
- return found?0:-EIO;
+ return retval;
}
-
-static void __exit sx_exit (void)
+static void __exit sx_exit(void)
{
- int i;
- struct sx_board *board;
+ int i;
func_enter();
- for (i = 0; i < SX_NBOARDS; i++) {
- board = &boards[i];
- if (board->flags & SX_BOARD_INITIALIZED) {
- sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %p\n", board->base);
- /* The board should stop messing with us.
- (actually I mean the interrupt) */
- sx_reset (board);
- if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
- free_irq (board->irq, board);
-
- /* It is safe/allowed to del_timer a non-active timer */
- del_timer (& board->timer);
- iounmap(board->base);
- }
- }
+#ifdef CONFIG_EISA
+ eisa_driver_unregister(&sx_eisadriver);
+#endif
+ pci_unregister_driver(&sx_pcidriver);
+
+ for (i = 0; i < SX_NBOARDS; i++)
+ sx_remove_card(&boards[i], NULL);
+
if (misc_deregister(&sx_fw_device) < 0) {
- printk (KERN_INFO "sx: couldn't deregister firmware loader device\n");
+ printk(KERN_INFO "sx: couldn't deregister firmware loader "
+ "device\n");
}
- sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized);
+ sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
+ sx_initialized);
if (sx_initialized)
- sx_release_drivers ();
+ sx_release_drivers();
- kfree (sx_ports);
+ kfree(sx_ports);
func_exit();
}
module_init(sx_init);
module_exit(sx_exit);
-
-
diff --git a/drivers/char/sx.h b/drivers/char/sx.h
index e01f83cbe29..432aad0a2dd 100644
--- a/drivers/char/sx.h
+++ b/drivers/char/sx.h
@@ -35,6 +35,7 @@ struct sx_board {
void __iomem *base;
void __iomem *base2;
unsigned long hw_base;
+ resource_size_t hw_len;
int eisa_base;
int port_base; /* Number of the first port */
struct sx_port *ports;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 645187b9141..3fa625db9e4 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -3060,7 +3060,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
*
* Return Value: None
*/
-static void mgsl_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
unsigned long flags;
@@ -4332,7 +4332,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
{
struct mgsl_struct *info;
- info = (struct mgsl_struct *)kmalloc(sizeof(struct mgsl_struct),
+ info = kmalloc(sizeof(struct mgsl_struct),
GFP_KERNEL);
if (!info) {
@@ -4405,6 +4405,8 @@ static int mgsl_init_tty(void)
serial_driver->init_termios = tty_std_termios;
serial_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->init_termios.c_ispeed = 9600;
+ serial_driver->init_termios.c_ospeed = 9600;
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &mgsl_ops);
if ((rc = tty_register_driver(serial_driver)) < 0) {
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e4730a7312b..792c79c315e 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -151,7 +151,7 @@ static struct tty_driver *serial_driver;
static int open(struct tty_struct *tty, struct file * filp);
static void close(struct tty_struct *tty, struct file * filp);
static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
static int write(struct tty_struct *tty, const unsigned char *buf, int count);
static void put_char(struct tty_struct *tty, unsigned char ch);
@@ -816,7 +816,7 @@ static void hangup(struct tty_struct *tty)
wake_up_interruptible(&info->open_wait);
}
-static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct slgt_info *info = tty->driver_data;
unsigned long flags;
@@ -3546,6 +3546,8 @@ static int __init slgt_init(void)
serial_driver->init_termios = tty_std_termios;
serial_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->init_termios.c_ispeed = 9600;
+ serial_driver->init_termios.c_ospeed = 9600;
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &ops);
if ((rc = tty_register_driver(serial_driver)) < 0) {
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 20a96ef250b..8f4d67afe5b 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -519,7 +519,7 @@ static struct tty_driver *serial_driver;
static int open(struct tty_struct *tty, struct file * filp);
static void close(struct tty_struct *tty, struct file * filp);
static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
static int write(struct tty_struct *tty, const unsigned char *buf, int count);
static void put_char(struct tty_struct *tty, unsigned char ch);
@@ -918,7 +918,7 @@ static void hangup(struct tty_struct *tty)
/* Set new termios settings
*/
-static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
unsigned long flags;
@@ -2730,7 +2730,7 @@ static int startup(SLMP_INFO * info)
return 0;
if (!info->tx_buf) {
- info->tx_buf = (unsigned char *)kmalloc(info->max_frame_size, GFP_KERNEL);
+ info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
if (!info->tx_buf) {
printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
__FILE__,__LINE__,info->device_name);
@@ -3798,7 +3798,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
{
SLMP_INFO *info;
- info = (SLMP_INFO *)kmalloc(sizeof(SLMP_INFO),
+ info = kmalloc(sizeof(SLMP_INFO),
GFP_KERNEL);
if (!info) {
@@ -4034,6 +4034,8 @@ static int __init synclinkmp_init(void)
serial_driver->init_termios = tty_std_termios;
serial_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->init_termios.c_ispeed = 9600;
+ serial_driver->init_termios.c_ospeed = 9600;
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &ops);
if ((rc = tty_register_driver(serial_driver)) < 0) {
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 05810c8d20b..7fd3cd5ddf2 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -41,7 +41,34 @@
#include <asm/irq_regs.h>
/* Whether we react on sysrq keys or just ignore them */
-int sysrq_enabled = 1;
+int __read_mostly __sysrq_enabled = 1;
+
+static int __read_mostly sysrq_always_enabled;
+
+int sysrq_on(void)
+{
+ return __sysrq_enabled || sysrq_always_enabled;
+}
+
+/*
+ * A value of 1 means 'all', other nonzero values are an op mask:
+ */
+static inline int sysrq_on_mask(int mask)
+{
+ return sysrq_always_enabled || __sysrq_enabled == 1 ||
+ (__sysrq_enabled & mask);
+}
+
+static int __init sysrq_always_enabled_setup(char *str)
+{
+ sysrq_always_enabled = 1;
+ printk(KERN_INFO "debug: sysrq always enabled.\n");
+
+ return 1;
+}
+
+__setup("sysrq_always_enabled", sysrq_always_enabled_setup);
+
static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
{
@@ -188,7 +215,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_showstate_blocked_op = {
.handler = sysrq_handle_showstate_blocked,
- .help_msg = "showBlockedTasks",
+ .help_msg = "shoW-blocked-tasks",
.action_msg = "Show Blocked State",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -288,15 +315,16 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
&sysrq_loglevel_op, /* 9 */
/*
- * Don't use for system provided sysrqs, it is handled specially on
- * sparc and will never arrive
+ * a: Don't use for system provided sysrqs, it is handled specially on
+ * sparc and will never arrive.
*/
NULL, /* a */
&sysrq_reboot_op, /* b */
- &sysrq_crashdump_op, /* c */
+ &sysrq_crashdump_op, /* c & ibm_emac driver debug */
&sysrq_showlocks_op, /* d */
&sysrq_term_op, /* e */
&sysrq_moom_op, /* f */
+ /* g: May be registered by ppc for kgdb */
NULL, /* g */
NULL, /* h */
&sysrq_kill_op, /* i */
@@ -305,18 +333,19 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
NULL, /* l */
&sysrq_showmem_op, /* m */
&sysrq_unrt_op, /* n */
- /* This will often be registered as 'Off' at init time */
+ /* o: This will often be registered as 'Off' at init time */
NULL, /* o */
&sysrq_showregs_op, /* p */
NULL, /* q */
- &sysrq_unraw_op, /* r */
+ &sysrq_unraw_op, /* r */
&sysrq_sync_op, /* s */
&sysrq_showstate_op, /* t */
&sysrq_mountro_op, /* u */
- /* May be assigned at init time by SMP VOYAGER */
+ /* v: May be registered at init time by SMP VOYAGER */
NULL, /* v */
- NULL, /* w */
- &sysrq_showstate_blocked_op, /* x */
+ &sysrq_showstate_blocked_op, /* w */
+ /* x: May be registered on ppc/powerpc for xmon */
+ NULL, /* x */
NULL, /* y */
NULL /* z */
};
@@ -379,8 +408,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
* 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)) {
+ if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
op_p->handler(key, tty);
@@ -414,9 +442,8 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
*/
void handle_sysrq(int key, struct tty_struct *tty)
{
- if (!sysrq_enabled)
- return;
- __handle_sysrq(key, tty, 1);
+ if (sysrq_on())
+ __handle_sysrq(key, tty, 1);
}
EXPORT_SYMBOL(handle_sysrq);
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index bb1bad4c18f..4c431cb7cf1 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -164,7 +164,7 @@ static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t le
unsigned int minor;
char value;
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
switch (minor) {
case 0:
value = get_led();
@@ -200,7 +200,7 @@ static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
int retval = 0;
char c;
- minor = iminor(file->f_dentry->d_inode);
+ minor = iminor(file->f_path.dentry->d_inode);
switch (minor) {
case 0:
type = TYPE_LED;
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 9df0ca1be0e..47fb20f6969 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -285,7 +285,7 @@ static ssize_t
tipar_write (struct file *file, const char __user *buf, size_t count,
loff_t * ppos)
{
- unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
+ unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
ssize_t n;
parport_claim_or_block(table[minor].dev);
@@ -313,7 +313,7 @@ static ssize_t
tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
{
int b = 0;
- unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR;
+ unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR;
ssize_t retval = 0;
ssize_t n = 0;
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 244d30a03fe..4fac2bdf621 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -186,6 +186,7 @@ static int got_event; /* if events processing have been done */
static void switchover_timeout(unsigned long data);
static struct timer_list switchover_timer =
TIMER_INITIALIZER(switchover_timeout , 0, 0);
+static unsigned long tlclk_timer_data;
static struct tlclk_alarms *alarm_events;
@@ -197,10 +198,19 @@ static irqreturn_t tlclk_interrupt(int irq, void *dev_id);
static DECLARE_WAIT_QUEUE_HEAD(wq);
+static unsigned long useflags;
+static DEFINE_MUTEX(tlclk_mutex);
+
static int tlclk_open(struct inode *inode, struct file *filp)
{
int result;
+ if (test_and_set_bit(0, &useflags))
+ return -EBUSY;
+ /* this legacy device is always one per system and it doesn't
+ * know how to handle multiple concurrent clients.
+ */
+
/* Make sure there is no interrupt pending while
* initialising interrupt handler */
inb(TLCLK_REG6);
@@ -221,6 +231,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
static int tlclk_release(struct inode *inode, struct file *filp)
{
free_irq(telclk_interrupt, tlclk_interrupt);
+ clear_bit(0, &useflags);
return 0;
}
@@ -230,26 +241,25 @@ static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
{
if (count < sizeof(struct tlclk_alarms))
return -EIO;
+ if (mutex_lock_interruptible(&tlclk_mutex))
+ return -EINTR;
+
wait_event_interruptible(wq, got_event);
- if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms)))
+ if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) {
+ mutex_unlock(&tlclk_mutex);
return -EFAULT;
+ }
memset(alarm_events, 0, sizeof(struct tlclk_alarms));
got_event = 0;
+ mutex_unlock(&tlclk_mutex);
return sizeof(struct tlclk_alarms);
}
-static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
- loff_t *f_pos)
-{
- return 0;
-}
-
static const struct file_operations tlclk_fops = {
.read = tlclk_read,
- .write = tlclk_write,
.open = tlclk_open,
.release = tlclk_release,
@@ -540,7 +550,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
switch (val) {
case CLK_8_592MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
break;
case CLK_11_184MHz:
SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
@@ -549,7 +559,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
break;
case CLK_44_736MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
break;
}
} else
@@ -807,8 +817,6 @@ static int __init tlclk_init(void)
&tlclk_attribute_group);
if (ret) {
printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n");
- sysfs_remove_group(&tlclk_device->dev.kobj,
- &tlclk_attribute_group);
goto out5;
}
@@ -841,11 +849,13 @@ static void __exit tlclk_cleanup(void)
static void switchover_timeout(unsigned long data)
{
- if ((data & 1)) {
- if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+ unsigned long flags = *(unsigned long *) data;
+
+ if ((flags & 1)) {
+ if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
alarm_events->switchover_primary++;
} else {
- if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+ if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
alarm_events->switchover_secondary++;
}
@@ -903,8 +913,9 @@ static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
/* TIMEOUT in ~10ms */
switchover_timer.expires = jiffies + msecs_to_jiffies(10);
- switchover_timer.data = inb(TLCLK_REG1);
- add_timer(&switchover_timer);
+ tlclk_timer_data = inb(TLCLK_REG1);
+ switchover_timer.data = (unsigned long) &tlclk_timer_data;
+ mod_timer(&switchover_timer, switchover_timer.expires);
} else {
got_event = 1;
wake_up(&wq);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index b3cfc8bc613..47a6eacb10b 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -109,13 +109,15 @@
#define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1
-struct termios tty_std_termios = { /* for the benefit of tty drivers */
+struct ktermios tty_std_termios = { /* for the benefit of tty drivers */
.c_iflag = ICRNL | IXON,
.c_oflag = OPOST | ONLCR,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
ECHOCTL | ECHOKE | IEXTEN,
- .c_cc = INIT_C_CC
+ .c_cc = INIT_C_CC,
+ .c_ispeed = 38400,
+ .c_ospeed = 38400
};
EXPORT_SYMBOL(tty_std_termios);
@@ -126,7 +128,7 @@ EXPORT_SYMBOL(tty_std_termios);
LIST_HEAD(tty_drivers); /* linked list of tty drivers */
-/* Semaphore to protect creating and releasing a tty. This is shared with
+/* Mutex to protect creating and releasing a tty. This is shared with
vt.c for deeply disgusting hack reasons */
DEFINE_MUTEX(tty_mutex);
EXPORT_SYMBOL(tty_mutex);
@@ -250,7 +252,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
"!= #fd's(%d) in %s\n",
tty->name, tty->count, count, routine);
return count;
- }
+ }
#endif
return 0;
}
@@ -259,18 +261,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
* Tty buffer allocation management
*/
-
-/**
- * tty_buffer_free_all - free buffers used by a tty
- * @tty: tty to free from
- *
- * Remove all the buffers pending on a tty whether queued with data
- * or in the free ring. Must be called when the tty is no longer in use
- *
- * Locking: none
- */
-
-
/**
* tty_buffer_free_all - free buffers used by a tty
* @tty: tty to free from
@@ -614,7 +604,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
* they are not on hot paths so a little discipline won't do
* any harm.
*
- * Locking: takes termios_sem
+ * Locking: takes termios_mutex
*/
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
@@ -915,7 +905,7 @@ static void tty_ldisc_enable(struct tty_struct *tty)
* context.
*
* Locking: takes tty_ldisc_lock.
- * called functions take termios_sem
+ * called functions take termios_mutex
*/
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -1251,6 +1241,22 @@ void tty_ldisc_flush(struct tty_struct *tty)
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/**
+ * tty_reset_termios - reset terminal state
+ * @tty: tty to reset
+ *
+ * Restore a terminal to the driver default state
+ */
+
+static void tty_reset_termios(struct tty_struct *tty)
+{
+ mutex_lock(&tty->termios_mutex);
+ *tty->termios = tty->driver->init_termios;
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+ mutex_unlock(&tty->termios_mutex);
+}
/**
* do_tty_hangup - actual handler for hangup events
@@ -1267,12 +1273,12 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
*
* Locking:
* BKL
- * redirect lock for undoing redirection
- * file list lock for manipulating list of ttys
- * tty_ldisc_lock from called functions
- * termios_sem resetting termios data
- * tasklist_lock to walk task list for hangup event
- *
+ * redirect lock for undoing redirection
+ * file list lock for manipulating list of ttys
+ * tty_ldisc_lock from called functions
+ * termios_mutex resetting termios data
+ * tasklist_lock to walk task list for hangup event
+ * ->siglock to protect ->signal/->sighand
*/
static void do_tty_hangup(struct work_struct *work)
{
@@ -1339,11 +1345,7 @@ static void do_tty_hangup(struct work_struct *work)
* N_TTY.
*/
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
- {
- mutex_lock(&tty->termios_mutex);
- *tty->termios = tty->driver->init_termios;
- mutex_unlock(&tty->termios_mutex);
- }
+ tty_reset_termios(tty);
/* Defer ldisc switch */
/* tty_deferred_ldisc_switch(N_TTY);
@@ -1354,14 +1356,18 @@ static void do_tty_hangup(struct work_struct *work)
read_lock(&tasklist_lock);
if (tty->session > 0) {
do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty)
p->signal->tty = NULL;
- if (!p->signal->leader)
+ if (!p->signal->leader) {
+ spin_unlock_irq(&p->sighand->siglock);
continue;
- group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
- group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ }
+ __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
if (tty->pgrp > 0)
p->signal->tty_old_pgrp = tty->pgrp;
+ spin_unlock_irq(&p->sighand->siglock);
} while_each_task_pid(tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);
@@ -1453,6 +1459,14 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
+static void session_clear_tty(pid_t session)
+{
+ struct task_struct *p;
+ do_each_task_pid(session, PIDTYPE_SID, p) {
+ proc_clear_tty(p);
+ } while_each_task_pid(session, PIDTYPE_SID, p);
+}
+
/**
* disassociate_ctty - disconnect controlling tty
* @on_exit: true if exiting so need to "hang up" the session
@@ -1469,31 +1483,35 @@ EXPORT_SYMBOL(tty_hung_up_p);
* The argument on_exit is set to 1 if called when a process is
* exiting; it is 0 if called by the ioctl TIOCNOTTY.
*
- * Locking: tty_mutex is taken to protect current->signal->tty
+ * Locking:
* BKL is taken for hysterical raisins
- * Tasklist lock is taken (under tty_mutex) to walk process
- * lists for the session.
+ * tty_mutex is taken to protect tty
+ * ->siglock is taken to protect ->signal/->sighand
+ * tasklist_lock is taken to walk process list for sessions
+ * ->siglock is taken to protect ->signal/->sighand
*/
void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
- struct task_struct *p;
int tty_pgrp = -1;
+ int session;
lock_kernel();
mutex_lock(&tty_mutex);
- tty = current->signal->tty;
+ tty = get_current_tty();
if (tty) {
tty_pgrp = tty->pgrp;
mutex_unlock(&tty_mutex);
+ /* XXX: here we race, there is nothing protecting tty */
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
} else {
- if (current->signal->tty_old_pgrp) {
- kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
- kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
+ pid_t old_pgrp = current->signal->tty_old_pgrp;
+ if (old_pgrp) {
+ kill_pg(old_pgrp, SIGHUP, on_exit);
+ kill_pg(old_pgrp, SIGCONT, on_exit);
}
mutex_unlock(&tty_mutex);
unlock_kernel();
@@ -1505,19 +1523,29 @@ void disassociate_ctty(int on_exit)
kill_pg(tty_pgrp, SIGCONT, on_exit);
}
- /* Must lock changes to tty_old_pgrp */
- mutex_lock(&tty_mutex);
+ spin_lock_irq(&current->sighand->siglock);
current->signal->tty_old_pgrp = 0;
- tty->session = 0;
- tty->pgrp = -1;
+ session = process_session(current);
+ spin_unlock_irq(&current->sighand->siglock);
+
+ mutex_lock(&tty_mutex);
+ /* It is possible that do_tty_hangup has free'd this tty */
+ tty = get_current_tty();
+ if (tty) {
+ tty->session = 0;
+ tty->pgrp = 0;
+ } else {
+#ifdef TTY_DEBUG_HANGUP
+ printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
+ " = NULL", tty);
+#endif
+ }
+ mutex_unlock(&tty_mutex);
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
- do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
+ session_clear_tty(session);
read_unlock(&tasklist_lock);
- mutex_unlock(&tty_mutex);
unlock_kernel();
}
@@ -1615,7 +1643,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
struct tty_ldisc *ld;
tty = (struct tty_struct *)file->private_data;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
@@ -1718,7 +1746,7 @@ static inline ssize_t do_tty_write(
cond_resched();
}
if (written) {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
inode->i_mtime = current_fs_time(inode->i_sb);
ret = written;
}
@@ -1749,7 +1777,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou
loff_t *ppos)
{
struct tty_struct * tty;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
ssize_t ret;
struct tty_ldisc *ld;
@@ -1856,8 +1884,8 @@ static int init_dev(struct tty_driver *driver, int idx,
struct tty_struct **ret_tty)
{
struct tty_struct *tty, *o_tty;
- struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
- struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
+ struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
+ struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
int retval = 0;
/* check whether we're reopening an existing tty */
@@ -1904,7 +1932,7 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*tp_loc) {
- tp = (struct termios *) kmalloc(sizeof(struct termios),
+ tp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
GFP_KERNEL);
if (!tp)
goto free_mem_out;
@@ -1912,11 +1940,11 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*ltp_loc) {
- ltp = (struct termios *) kmalloc(sizeof(struct termios),
+ ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
GFP_KERNEL);
if (!ltp)
goto free_mem_out;
- memset(ltp, 0, sizeof(struct termios));
+ memset(ltp, 0, sizeof(struct ktermios));
}
if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -1937,19 +1965,19 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*o_tp_loc) {
- o_tp = (struct termios *)
- kmalloc(sizeof(struct termios), GFP_KERNEL);
+ o_tp = (struct ktermios *)
+ kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_tp)
goto free_mem_out;
*o_tp = driver->other->init_termios;
}
if (!*o_ltp_loc) {
- o_ltp = (struct termios *)
- kmalloc(sizeof(struct termios), GFP_KERNEL);
+ o_ltp = (struct ktermios *)
+ kmalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_ltp)
goto free_mem_out;
- memset(o_ltp, 0, sizeof(struct termios));
+ memset(o_ltp, 0, sizeof(struct ktermios));
}
/*
@@ -1988,6 +2016,9 @@ static int init_dev(struct tty_driver *driver, int idx,
*ltp_loc = ltp;
tty->termios = *tp_loc;
tty->termios_locked = *ltp_loc;
+ /* Compatibility until drivers always set this */
+ tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
driver->refcount++;
tty->count++;
@@ -2090,7 +2121,7 @@ release_mem_out:
static void release_mem(struct tty_struct *tty, int idx)
{
struct tty_struct *o_tty;
- struct termios *tp;
+ struct ktermios *tp;
int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
if ((o_tty = tty->link) != NULL) {
@@ -2156,7 +2187,7 @@ static void release_dev(struct file * filp)
unsigned long flags;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev"))
return;
check_tty_count(tty, "release_dev");
@@ -2337,16 +2368,10 @@ static void release_dev(struct file * filp)
* tty.
*/
if (tty_closing || o_tty_closing) {
- struct task_struct *p;
-
read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ session_clear_tty(tty->session);
if (o_tty)
- do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
+ session_clear_tty(o_tty->session);
read_unlock(&tasklist_lock);
}
@@ -2443,9 +2468,9 @@ static void release_dev(struct file * filp)
* The termios state of a pty is reset on first open so that
* settings don't persist across reuse.
*
- * Locking: tty_mutex protects current->signal->tty, get_tty_driver and
- * init_dev work. tty->count should protect the rest.
- * task_lock is held to update task details for sessions
+ * Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ * tty->count should protect the rest.
+ * ->siglock protects ->signal/->sighand
*/
static int tty_open(struct inode * inode, struct file * filp)
@@ -2467,12 +2492,13 @@ retry_open:
mutex_lock(&tty_mutex);
if (device == MKDEV(TTYAUX_MAJOR,0)) {
- if (!current->signal->tty) {
+ tty = get_current_tty();
+ if (!tty) {
mutex_unlock(&tty_mutex);
return -ENXIO;
}
- driver = current->signal->tty->driver;
- index = current->signal->tty->index;
+ driver = tty->driver;
+ index = tty->index;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */
goto got_driver;
@@ -2547,17 +2573,16 @@ got_driver:
filp->f_op = &tty_fops;
goto retry_open;
}
+
+ mutex_lock(&tty_mutex);
+ spin_lock_irq(&current->sighand->siglock);
if (!noctty &&
current->signal->leader &&
!current->signal->tty &&
- tty->session == 0) {
- task_lock(current);
- current->signal->tty = tty;
- task_unlock(current);
- current->signal->tty_old_pgrp = 0;
- tty->session = current->signal->session;
- tty->pgrp = process_group(current);
- }
+ tty->session == 0)
+ __proc_set_tty(current, tty);
+ spin_unlock_irq(&current->sighand->siglock);
+ mutex_unlock(&tty_mutex);
return 0;
}
@@ -2672,7 +2697,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait)
int ret = 0;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
return 0;
ld = tty_ldisc_ref_wait(tty);
@@ -2688,7 +2713,7 @@ static int tty_fasync(int fd, struct file * filp, int on)
int retval;
tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
+ if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
return 0;
retval = fasync_helper(fd, filp, on, &tty->fasync);
@@ -2747,7 +2772,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
*
* Copies the kernel idea of the window size into the user buffer.
*
- * Locking: tty->termios_sem is taken to ensure the winsize data
+ * Locking: tty->termios_mutex is taken to ensure the winsize data
* is consistent.
*/
@@ -2774,8 +2799,8 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
* Locking:
* Called function use the console_sem is used to ensure we do
* not try and resize the console twice at once.
- * The tty->termios_sem is used to ensure we don't double
- * resize and get confused. Lock order - tty->termios.sem before
+ * The tty->termios_mutex is used to ensure we don't double
+ * resize and get confused. Lock order - tty->termios_mutex before
* console sem
*/
@@ -2880,25 +2905,28 @@ static int fionbio(struct file *file, int __user *p)
* leader to set this tty as the controlling tty for the session.
*
* Locking:
- * Takes tasklist lock internally to walk sessions
- * Takes task_lock() when updating signal->tty
* Takes tty_mutex() to protect tty instance
- *
+ * Takes tasklist_lock internally to walk sessions
+ * Takes ->siglock() when updating signal->tty
*/
static int tiocsctty(struct tty_struct *tty, int arg)
{
- struct task_struct *p;
-
+ int ret = 0;
if (current->signal->leader &&
- (current->signal->session == tty->session))
- return 0;
+ (process_session(current) == tty->session))
+ return ret;
+
+ mutex_lock(&tty_mutex);
/*
* The process must be a session leader and
* not have a controlling tty already.
*/
- if (!current->signal->leader || current->signal->tty)
- return -EPERM;
+ if (!current->signal->leader || current->signal->tty) {
+ ret = -EPERM;
+ goto unlock;
+ }
+
if (tty->session > 0) {
/*
* This tty is already the controlling
@@ -2908,24 +2936,18 @@ static int tiocsctty(struct tty_struct *tty, int arg)
/*
* Steal it away
*/
-
read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
- p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ session_clear_tty(tty->session);
read_unlock(&tasklist_lock);
- } else
- return -EPERM;
+ } else {
+ ret = -EPERM;
+ goto unlock;
+ }
}
- mutex_lock(&tty_mutex);
- task_lock(current);
- current->signal->tty = tty;
- task_unlock(current);
+ proc_set_tty(current, tty);
+unlock:
mutex_unlock(&tty_mutex);
- current->signal->tty_old_pgrp = 0;
- tty->session = current->signal->session;
- tty->pgrp = process_group(current);
- return 0;
+ return ret;
}
/**
@@ -2937,7 +2959,7 @@ static int tiocsctty(struct tty_struct *tty, int arg)
* Obtain the process group of the tty. If there is no process group
* return an error.
*
- * Locking: none. Reference to ->signal->tty is safe.
+ * Locking: none. Reference to current->signal->tty is safe.
*/
static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -2974,13 +2996,13 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return retval;
if (!current->signal->tty ||
(current->signal->tty != real_tty) ||
- (real_tty->session != current->signal->session))
+ (real_tty->session != process_session(current)))
return -ENOTTY;
if (get_user(pgrp, p))
return -EFAULT;
if (pgrp < 0)
return -EINVAL;
- if (session_of_pgrp(pgrp) != current->signal->session)
+ if (session_of_pgrp(pgrp) != process_session(current))
return -EPERM;
real_tty->pgrp = pgrp;
return 0;
@@ -2995,7 +3017,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
* Obtain the session id of the tty. If there is no session
* return an error.
*
- * Locking: none. Reference to ->signal->tty is safe.
+ * Locking: none. Reference to current->signal->tty is safe.
*/
static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3214,14 +3236,11 @@ int tty_ioctl(struct inode * inode, struct file * file,
clear_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
case TIOCNOTTY:
- /* FIXME: taks lock or tty_mutex ? */
if (current->signal->tty != tty)
return -ENOTTY;
if (current->signal->leader)
disassociate_ctty(0);
- task_lock(current);
- current->signal->tty = NULL;
- task_unlock(current);
+ proc_clear_tty(current);
return 0;
case TIOCSCTTY:
return tiocsctty(tty, arg);
@@ -3316,18 +3335,13 @@ static void __do_SAK(struct work_struct *work)
int session;
int i;
struct file *filp;
- struct tty_ldisc *disc;
struct fdtable *fdt;
if (!tty)
return;
- session = tty->session;
+ session = tty->session;
- /* We don't want an ldisc switch during this */
- disc = tty_ldisc_ref(tty);
- if (disc && disc->flush_buffer)
- disc->flush_buffer(tty);
- tty_ldisc_deref(disc);
+ tty_ldisc_flush(tty);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
@@ -3336,7 +3350,7 @@ static void __do_SAK(struct work_struct *work)
/* Kill the entire session */
do_each_task_pid(session, PIDTYPE_SID, p) {
printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): p->signal->session==tty->session\n",
+ " (%s): process_session(p)==tty->session\n",
p->pid, p->comm);
send_sig(SIGKILL, p, 1);
} while_each_task_pid(session, PIDTYPE_SID, p);
@@ -3346,7 +3360,7 @@ static void __do_SAK(struct work_struct *work)
do_each_thread(g, p) {
if (p->signal->tty == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): p->signal->session==tty->session\n",
+ " (%s): process_session(p)==tty->session\n",
p->pid, p->comm);
send_sig(SIGKILL, p, 1);
continue;
@@ -3456,84 +3470,6 @@ static void flush_to_ldisc(struct work_struct *work)
tty_ldisc_deref(disc);
}
-/*
- * Routine which returns the baud rate of the tty
- *
- * Note that the baud_table needs to be kept in sync with the
- * include/asm/termbits.h file.
- */
-static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800,
-#ifdef __sparc__
- 76800, 153600, 307200, 614400, 921600
-#else
- 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
- 2500000, 3000000, 3500000, 4000000
-#endif
-};
-
-static int n_baud_table = ARRAY_SIZE(baud_table);
-
-/**
- * tty_termios_baud_rate
- * @termios: termios structure
- *
- * Convert termios baud rate data into a speed. This should be called
- * with the termios lock held if this termios is a terminal termios
- * structure. May change the termios data.
- *
- * Locking: none
- */
-
-int tty_termios_baud_rate(struct termios *termios)
-{
- unsigned int cbaud;
-
- cbaud = termios->c_cflag & CBAUD;
-
- if (cbaud & CBAUDEX) {
- cbaud &= ~CBAUDEX;
-
- if (cbaud < 1 || cbaud + 15 > n_baud_table)
- termios->c_cflag &= ~CBAUDEX;
- else
- cbaud += 15;
- }
- return baud_table[cbaud];
-}
-
-EXPORT_SYMBOL(tty_termios_baud_rate);
-
-/**
- * tty_get_baud_rate - get tty bit rates
- * @tty: tty to query
- *
- * Returns the baud rate as an integer for this terminal. The
- * termios lock must be held by the caller and the terminal bit
- * flags may be updated.
- *
- * Locking: none
- */
-
-int tty_get_baud_rate(struct tty_struct *tty)
-{
- int baud = tty_termios_baud_rate(tty->termios);
-
- if (baud == 38400 && tty->alt_speed) {
- if (!tty->warned) {
- printk(KERN_WARNING "Use of setserial/setrocket to "
- "set SPD_* flags is deprecated\n");
- tty->warned = 1;
- }
- baud = tty->alt_speed;
- }
-
- return baud;
-}
-
-EXPORT_SYMBOL(tty_get_baud_rate);
-
/**
* tty_flip_buffer_push - terminal
* @tty: tty to push
@@ -3756,8 +3692,8 @@ int tty_register_driver(struct tty_driver *driver)
if (p) {
driver->ttys = (struct tty_struct **)p;
- driver->termios = (struct termios **)(p + driver->num);
- driver->termios_locked = (struct termios **)(p + driver->num * 2);
+ driver->termios = (struct ktermios **)(p + driver->num);
+ driver->termios_locked = (struct ktermios **)(p + driver->num * 2);
} else {
driver->ttys = NULL;
driver->termios = NULL;
@@ -3796,7 +3732,7 @@ EXPORT_SYMBOL(tty_register_driver);
int tty_unregister_driver(struct tty_driver *driver)
{
int i;
- struct termios *tp;
+ struct ktermios *tp;
void *p;
if (driver->refcount)
@@ -3834,9 +3770,53 @@ int tty_unregister_driver(struct tty_driver *driver)
cdev_del(&driver->cdev);
return 0;
}
-
EXPORT_SYMBOL(tty_unregister_driver);
+dev_t tty_devnum(struct tty_struct *tty)
+{
+ return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
+}
+EXPORT_SYMBOL(tty_devnum);
+
+void proc_clear_tty(struct task_struct *p)
+{
+ spin_lock_irq(&p->sighand->siglock);
+ p->signal->tty = NULL;
+ spin_unlock_irq(&p->sighand->siglock);
+}
+EXPORT_SYMBOL(proc_clear_tty);
+
+void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+ if (tty) {
+ tty->session = process_session(tsk);
+ tty->pgrp = process_group(tsk);
+ }
+ tsk->signal->tty = tty;
+ tsk->signal->tty_old_pgrp = 0;
+}
+
+void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+{
+ spin_lock_irq(&tsk->sighand->siglock);
+ __proc_set_tty(tsk, tty);
+ spin_unlock_irq(&tsk->sighand->siglock);
+}
+
+struct tty_struct *get_current_tty(void)
+{
+ struct tty_struct *tty;
+ WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
+ tty = current->signal->tty;
+ /*
+ * session->tty can be changed/cleared from under us, make sure we
+ * issue the load. The obtained pointer, when not NULL, is valid as
+ * long as we hold tty_mutex.
+ */
+ barrier();
+ return tty;
+}
+EXPORT_SYMBOL_GPL(get_current_tty);
/*
* Initialize the console device. This is called *early*, so
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 3b6fa7b0be8..dee47f40c6a 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -36,6 +36,7 @@
#define TERMIOS_FLUSH 1
#define TERMIOS_WAIT 2
#define TERMIOS_TERMIO 4
+#define TERMIOS_OLD 8
/**
@@ -84,9 +85,9 @@ stop_waiting:
EXPORT_SYMBOL(tty_wait_until_sent);
-static void unset_locked_termios(struct termios *termios,
- struct termios *old,
- struct termios *locked)
+static void unset_locked_termios(struct ktermios *termios,
+ struct ktermios *old,
+ struct ktermios *locked)
{
int i;
@@ -105,8 +106,204 @@ static void unset_locked_termios(struct termios *termios,
for (i=0; i < NCCS; i++)
termios->c_cc[i] = locked->c_cc[i] ?
old->c_cc[i] : termios->c_cc[i];
+ /* FIXME: What should we do for i/ospeed */
}
+/*
+ * Routine which returns the baud rate of the tty
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
+ */
+static const speed_t baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+ 76800, 153600, 307200, 614400, 921600
+#else
+ 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+ 2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+#ifndef __sparc__
+static const tcflag_t baud_bits[] = {
+ B0, B50, B75, B110, B134, B150, B200, B300, B600,
+ B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+ B57600, B115200, B230400, B460800, B500000, B576000,
+ B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
+ B3000000, B3500000, B4000000
+};
+#else
+static const tcflag_t baud_bits[] = {
+ B0, B50, B75, B110, B134, B150, B200, B300, B600,
+ B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+ B57600, B115200, B230400, B460800, B76800, B153600,
+ B307200, B614400, B921600
+};
+#endif
+
+static int n_baud_table = ARRAY_SIZE(baud_table);
+
+/**
+ * tty_termios_baud_rate
+ * @termios: termios structure
+ *
+ * Convert termios baud rate data into a speed. This should be called
+ * with the termios lock held if this termios is a terminal termios
+ * structure. May change the termios data. Device drivers can call this
+ * function but should use ->c_[io]speed directly as they are updated.
+ *
+ * Locking: none
+ */
+
+speed_t tty_termios_baud_rate(struct ktermios *termios)
+{
+ unsigned int cbaud;
+
+ cbaud = termios->c_cflag & CBAUD;
+
+#ifdef BOTHER
+ /* Magic token for arbitary speed via c_ispeed/c_ospeed */
+ if (cbaud == BOTHER)
+ return termios->c_ospeed;
+#endif
+ if (cbaud & CBAUDEX) {
+ cbaud &= ~CBAUDEX;
+
+ if (cbaud < 1 || cbaud + 15 > n_baud_table)
+ termios->c_cflag &= ~CBAUDEX;
+ else
+ cbaud += 15;
+ }
+ return baud_table[cbaud];
+}
+
+EXPORT_SYMBOL(tty_termios_baud_rate);
+
+/**
+ * tty_termios_input_baud_rate
+ * @termios: termios structure
+ *
+ * Convert termios baud rate data into a speed. This should be called
+ * with the termios lock held if this termios is a terminal termios
+ * structure. May change the termios data. Device drivers can call this
+ * function but should use ->c_[io]speed directly as they are updated.
+ *
+ * Locking: none
+ */
+
+speed_t tty_termios_input_baud_rate(struct ktermios *termios)
+{
+#ifdef IBSHIFT
+ unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
+
+ if (cbaud == B0)
+ return tty_termios_baud_rate(termios);
+
+ /* Magic token for arbitary speed via c_ispeed*/
+ if (cbaud == BOTHER)
+ return termios->c_ispeed;
+
+ if (cbaud & CBAUDEX) {
+ cbaud &= ~CBAUDEX;
+
+ if (cbaud < 1 || cbaud + 15 > n_baud_table)
+ termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
+ else
+ cbaud += 15;
+ }
+ return baud_table[cbaud];
+#else
+ return tty_termios_baud_rate(termios);
+#endif
+}
+
+EXPORT_SYMBOL(tty_termios_input_baud_rate);
+
+#ifdef BOTHER
+
+/**
+ * tty_termios_encode_baud_rate
+ * @termios: termios structure
+ * @ispeed: input speed
+ * @ospeed: output speed
+ *
+ * Encode the speeds set into the passed termios structure. This is
+ * used as a library helper for drivers os that they can report back
+ * the actual speed selected when it differs from the speed requested
+ *
+ * For now input and output speed must agree.
+ *
+ * Locking: Caller should hold termios lock. This is already held
+ * when calling this function from the driver termios handler.
+ */
+
+void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
+{
+ int i = 0;
+ int ifound = 0, ofound = 0;
+
+ termios->c_ispeed = ibaud;
+ termios->c_ospeed = obaud;
+
+ termios->c_cflag &= ~CBAUD;
+ /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/
+ if (termios->c_ispeed == termios->c_ospeed)
+ ifound = 1;
+
+ do {
+ if (obaud == baud_table[i]) {
+ termios->c_cflag |= baud_bits[i];
+ ofound = 1;
+ /* So that if ibaud == obaud we don't set it */
+ continue;
+ }
+ if (ibaud == baud_table[i]) {
+ termios->c_cflag |= (baud_bits[i] << IBSHIFT);
+ ifound = 1;
+ }
+ }
+ while(++i < n_baud_table);
+ if (!ofound)
+ termios->c_cflag |= BOTHER;
+ if (!ifound)
+ termios->c_cflag |= (BOTHER << IBSHIFT);
+}
+
+EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
+
+#endif
+
+/**
+ * tty_get_baud_rate - get tty bit rates
+ * @tty: tty to query
+ *
+ * Returns the baud rate as an integer for this terminal. The
+ * termios lock must be held by the caller and the terminal bit
+ * flags may be updated.
+ *
+ * Locking: none
+ */
+
+speed_t tty_get_baud_rate(struct tty_struct *tty)
+{
+ speed_t baud = tty_termios_baud_rate(tty->termios);
+
+ if (baud == 38400 && tty->alt_speed) {
+ if (!tty->warned) {
+ printk(KERN_WARNING "Use of setserial/setrocket to "
+ "set SPD_* flags is deprecated\n");
+ tty->warned = 1;
+ }
+ baud = tty->alt_speed;
+ }
+
+ return baud;
+}
+
+EXPORT_SYMBOL(tty_get_baud_rate);
+
/**
* change_termios - update termios values
* @tty: tty to update
@@ -119,10 +316,10 @@ static void unset_locked_termios(struct termios *termios,
* Locking: termios_sem
*/
-static void change_termios(struct tty_struct * tty, struct termios * new_termios)
+static void change_termios(struct tty_struct * tty, struct ktermios * new_termios)
{
int canon_change;
- struct termios old_termios = *tty->termios;
+ struct ktermios old_termios = *tty->termios;
struct tty_ldisc *ld;
/*
@@ -195,23 +392,39 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
{
- struct termios tmp_termios;
+ struct ktermios tmp_termios;
struct tty_ldisc *ld;
int retval = tty_check_change(tty);
if (retval)
return retval;
+ memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
+
if (opt & TERMIOS_TERMIO) {
- memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
if (user_termio_to_kernel_termios(&tmp_termios,
(struct termio __user *)arg))
return -EFAULT;
+#ifdef TCGETS2
+ } else if (opt & TERMIOS_OLD) {
+ if (user_termios_to_kernel_termios_1(&tmp_termios,
+ (struct termios __user *)arg))
+ return -EFAULT;
} else {
if (user_termios_to_kernel_termios(&tmp_termios,
- (struct termios __user *)arg))
+ (struct termios2 __user *)arg))
return -EFAULT;
}
+#else
+ } else if (user_termios_to_kernel_termios(&tmp_termios,
+ (struct termios __user *)arg))
+ return -EFAULT;
+#endif
+
+ /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed
+ so its unconditionally usable */
+ tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
+ tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
ld = tty_ldisc_ref(tty);
@@ -286,8 +499,8 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
struct sgttyb tmp;
mutex_lock(&tty->termios_mutex);
- tmp.sg_ispeed = 0;
- tmp.sg_ospeed = 0;
+ tmp.sg_ispeed = tty->termios->c_ispeed;
+ tmp.sg_ospeed = tty->termios->c_ospeed;
tmp.sg_erase = tty->termios->c_cc[VERASE];
tmp.sg_kill = tty->termios->c_cc[VKILL];
tmp.sg_flags = get_sgflags(tty);
@@ -296,7 +509,7 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
-static void set_sgflags(struct termios * termios, int flags)
+static void set_sgflags(struct ktermios * termios, int flags)
{
termios->c_iflag = ICRNL | IXON;
termios->c_oflag = 0;
@@ -337,7 +550,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
{
int retval;
struct sgttyb tmp;
- struct termios termios;
+ struct ktermios termios;
retval = tty_check_change(tty);
if (retval)
@@ -351,6 +564,10 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
termios.c_cc[VERASE] = tmp.sg_erase;
termios.c_cc[VKILL] = tmp.sg_kill;
set_sgflags(&termios, tmp.sg_flags);
+ /* Try and encode into Bfoo format */
+#ifdef BOTHER
+ tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed);
+#endif
mutex_unlock(&tty->termios_mutex);
change_termios(tty, &termios);
return 0;
@@ -481,16 +698,33 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
case TIOCSLTC:
return set_ltchars(real_tty, p);
#endif
+ case TCSETSF:
+ return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
+ case TCSETSW:
+ return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
+ case TCSETS:
+ return set_termios(real_tty, p, TERMIOS_OLD);
+#ifndef TCGETS2
case TCGETS:
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
return -EFAULT;
return 0;
- case TCSETSF:
+#else
+ case TCGETS:
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
+ return -EFAULT;
+ return 0;
+ case TCGETS2:
+ if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
+ return -EFAULT;
+ return 0;
+ case TCSETSF2:
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
- case TCSETSW:
+ case TCSETSW2:
return set_termios(real_tty, p, TERMIOS_WAIT);
- case TCSETS:
+ case TCSETS2:
return set_termios(real_tty, p, 0);
+#endif
case TCGETA:
return get_termio(real_tty, p);
case TCSETAF:
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index f442b574b44..26776517f04 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -72,7 +72,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
int size;
down(&con_buf_sem);
- size = vcs_size(file->f_dentry->d_inode);
+ size = vcs_size(file->f_path.dentry->d_inode);
switch (orig) {
default:
up(&con_buf_sem);
@@ -98,7 +98,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
static ssize_t
vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
unsigned int currcons = iminor(inode);
struct vc_data *vc;
long pos;
@@ -271,7 +271,7 @@ unlock_out:
static ssize_t
vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
unsigned int currcons = iminor(inode);
struct vc_data *vc;
long pos;
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index 6d2e314860d..8de6b95aeb8 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -42,6 +42,7 @@
#include <linux/tty_flip.h>
#include <linux/sysrq.h>
+#include <asm/firmware.h>
#include <asm/iseries/vio.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_call_event.h>
@@ -61,10 +62,7 @@
static DEFINE_SPINLOCK(consolelock);
static DEFINE_SPINLOCK(consoleloglock);
-#ifdef CONFIG_MAGIC_SYSRQ
static int vio_sysrq_pressed;
-extern int sysrq_enabled;
-#endif
#define VIOCHAR_NUM_BUF 16
@@ -936,8 +934,10 @@ static void vioHandleData(struct HvLpEvent *event)
*/
num_pushed = 0;
for (index = 0; index < cevent->len; index++) {
-#ifdef CONFIG_MAGIC_SYSRQ
- if (sysrq_enabled) {
+ /*
+ * Will be optimized away if !CONFIG_MAGIC_SYSRQ:
+ */
+ if (sysrq_on()) {
/* 0x0f is the ascii character for ^O */
if (cevent->data[index] == '\x0f') {
vio_sysrq_pressed = 1;
@@ -956,7 +956,6 @@ static void vioHandleData(struct HvLpEvent *event)
continue;
}
}
-#endif
/*
* The sysrq sequence isn't included in this check if
* sysrq is enabled and compiled into the kernel because
@@ -1062,6 +1061,9 @@ static int __init viocons_init2(void)
atomic_t wait_flag;
int rc;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
/* +2 for fudge */
rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
@@ -1147,6 +1149,9 @@ static int __init viocons_init(void)
{
int i;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
printk(VIOCONS_KERN_INFO "registering console\n");
for (i = 0; i < VTTY_PORTS; i++) {
port_info[i].lp = HvLpIndexInvalid;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 73c78bf75d7..9438512b17f 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -49,7 +49,7 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>
-
+#include <asm/firmware.h>
#include <asm/vio.h>
#include <asm/iseries/vio.h>
#include <asm/iseries/hv_lp_event.h>
@@ -442,7 +442,7 @@ static ssize_t viotap_write(struct file *file, const char *buf,
if (op == NULL)
return -ENOMEM;
- get_dev_info(file->f_dentry->d_inode, &devi);
+ get_dev_info(file->f_path.dentry->d_inode, &devi);
/*
* We need to make sure we can send a request. We use
@@ -532,7 +532,7 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count,
if (op == NULL)
return -ENOMEM;
- get_dev_info(file->f_dentry->d_inode, &devi);
+ get_dev_info(file->f_path.dentry->d_inode, &devi);
/*
* We need to make sure we can send a request. We use
@@ -612,7 +612,7 @@ static int viotap_ioctl(struct inode *inode, struct file *file,
if (op == NULL)
return -ENOMEM;
- get_dev_info(file->f_dentry->d_inode, &devi);
+ get_dev_info(file->f_path.dentry->d_inode, &devi);
down(&reqSem);
@@ -777,7 +777,7 @@ static int viotap_open(struct inode *inode, struct file *file)
if (op == NULL)
return -ENOMEM;
- get_dev_info(file->f_dentry->d_inode, &devi);
+ get_dev_info(file->f_path.dentry->d_inode, &devi);
/* Note: We currently only support one mode! */
if ((devi.devno >= viotape_numdev) || (devi.mode)) {
@@ -822,7 +822,7 @@ static int viotap_release(struct inode *inode, struct file *file)
return -ENOMEM;
init_completion(&op->com);
- get_dev_info(file->f_dentry->d_inode, &devi);
+ get_dev_info(file->f_path.dentry->d_inode, &devi);
if (devi.devno >= viotape_numdev) {
ret = -ENODEV;
@@ -997,6 +997,9 @@ int __init viotap_init(void)
int ret;
struct proc_dir_entry *e;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
op_struct_list = NULL;
if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) {
printk(VIOTAPE_KERN_WARN "couldn't allocate op structs\n");
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index d0b94dd1af6..e01317cb1a0 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -153,6 +153,8 @@ static int scc_init_drivers(void)
scc_driver->init_termios = tty_std_termios;
scc_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ scc_driver->init_termios.c_ispeed = 9600;
+ scc_driver->init_termios.c_ospeed = 9600;
scc_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(scc_driver, &scc_ops);
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 8e794930517..0cea8d4907d 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -125,30 +125,17 @@ static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
return data;
}
-static unsigned int startup_giuint_low_irq(unsigned int irq)
+static void ack_giuint_low(unsigned int irq)
{
- unsigned int pin;
-
- pin = GPIO_PIN_OF_IRQ(irq);
- giu_write(GIUINTSTATL, 1 << pin);
- giu_set(GIUINTENL, 1 << pin);
-
- return 0;
+ giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
}
-static void shutdown_giuint_low_irq(unsigned int irq)
+static void mask_giuint_low(unsigned int irq)
{
giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
}
-static void enable_giuint_low_irq(unsigned int irq)
-{
- giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-#define disable_giuint_low_irq shutdown_giuint_low_irq
-
-static void ack_giuint_low_irq(unsigned int irq)
+static void mask_ack_giuint_low(unsigned int irq)
{
unsigned int pin;
@@ -157,46 +144,30 @@ static void ack_giuint_low_irq(unsigned int irq)
giu_write(GIUINTSTATL, 1 << pin);
}
-static void end_giuint_low_irq(unsigned int irq)
+static void unmask_giuint_low(unsigned int irq)
{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+ giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
}
-static struct hw_interrupt_type giuint_low_irq_type = {
- .typename = "GIUINTL",
- .startup = startup_giuint_low_irq,
- .shutdown = shutdown_giuint_low_irq,
- .enable = enable_giuint_low_irq,
- .disable = disable_giuint_low_irq,
- .ack = ack_giuint_low_irq,
- .end = end_giuint_low_irq,
+static struct irq_chip giuint_low_irq_chip = {
+ .name = "GIUINTL",
+ .ack = ack_giuint_low,
+ .mask = mask_giuint_low,
+ .mask_ack = mask_ack_giuint_low,
+ .unmask = unmask_giuint_low,
};
-static unsigned int startup_giuint_high_irq(unsigned int irq)
+static void ack_giuint_high(unsigned int irq)
{
- unsigned int pin;
-
- pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
- giu_write(GIUINTSTATH, 1 << pin);
- giu_set(GIUINTENH, 1 << pin);
-
- return 0;
+ giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
}
-static void shutdown_giuint_high_irq(unsigned int irq)
+static void mask_giuint_high(unsigned int irq)
{
giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
}
-static void enable_giuint_high_irq(unsigned int irq)
-{
- giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-#define disable_giuint_high_irq shutdown_giuint_high_irq
-
-static void ack_giuint_high_irq(unsigned int irq)
+static void mask_ack_giuint_high(unsigned int irq)
{
unsigned int pin;
@@ -205,20 +176,17 @@ static void ack_giuint_high_irq(unsigned int irq)
giu_write(GIUINTSTATH, 1 << pin);
}
-static void end_giuint_high_irq(unsigned int irq)
+static void unmask_giuint_high(unsigned int irq)
{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+ giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
}
-static struct hw_interrupt_type giuint_high_irq_type = {
- .typename = "GIUINTH",
- .startup = startup_giuint_high_irq,
- .shutdown = shutdown_giuint_high_irq,
- .enable = enable_giuint_high_irq,
- .disable = disable_giuint_high_irq,
- .ack = ack_giuint_high_irq,
- .end = end_giuint_high_irq,
+static struct irq_chip giuint_high_irq_chip = {
+ .name = "GIUINTH",
+ .ack = ack_giuint_high,
+ .mask = mask_giuint_high,
+ .mask_ack = mask_ack_giuint_high,
+ .unmask = unmask_giuint_high,
};
static int giu_get_irq(unsigned int irq)
@@ -282,9 +250,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
break;
}
}
+ set_irq_chip_and_handler(GIU_IRQ(pin),
+ &giuint_low_irq_chip,
+ handle_edge_irq);
} else {
giu_clear(GIUINTTYPL, mask);
giu_clear(GIUINTHTSELL, mask);
+ set_irq_chip_and_handler(GIU_IRQ(pin),
+ &giuint_low_irq_chip,
+ handle_level_irq);
}
giu_write(GIUINTSTATL, mask);
} else if (pin < GIUINT_HIGH_MAX) {
@@ -311,9 +285,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
break;
}
}
+ set_irq_chip_and_handler(GIU_IRQ(pin),
+ &giuint_high_irq_chip,
+ handle_edge_irq);
} else {
giu_clear(GIUINTTYPH, mask);
giu_clear(GIUINTHTSELH, mask);
+ set_irq_chip_and_handler(GIU_IRQ(pin),
+ &giuint_high_irq_chip,
+ handle_level_irq);
}
giu_write(GIUINTSTATH, mask);
}
@@ -506,7 +486,7 @@ static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
unsigned int pin;
char value = '0';
- pin = iminor(file->f_dentry->d_inode);
+ pin = iminor(file->f_path.dentry->d_inode);
if (pin >= giu_nr_pins)
return -EBADF;
@@ -530,7 +510,7 @@ static ssize_t gpio_write(struct file *file, const char __user *data,
char c;
int retval = 0;
- pin = iminor(file->f_dentry->d_inode);
+ pin = iminor(file->f_path.dentry->d_inode);
if (pin >= giu_nr_pins)
return -EBADF;
@@ -617,10 +597,11 @@ static const struct file_operations gpio_fops = {
static int __devinit giu_probe(struct platform_device *dev)
{
unsigned long start, size, flags = 0;
- unsigned int nr_pins = 0;
+ unsigned int nr_pins = 0, trigger, i, pin;
struct resource *res1, *res2 = NULL;
void *base;
- int retval, i;
+ struct irq_chip *chip;
+ int retval;
switch (current_cpu_data.cputype) {
case CPU_VR4111:
@@ -688,11 +669,20 @@ static int __devinit giu_probe(struct platform_device *dev)
giu_write(GIUINTENL, 0);
giu_write(GIUINTENH, 0);
+ trigger = giu_read(GIUINTTYPH) << 16;
+ trigger |= giu_read(GIUINTTYPL);
for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
- if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
- irq_desc[i].chip = &giuint_low_irq_type;
+ pin = GPIO_PIN_OF_IRQ(i);
+ if (pin < GIUINT_HIGH_OFFSET)
+ chip = &giuint_low_irq_chip;
else
- irq_desc[i].chip = &giuint_high_irq_type;
+ chip = &giuint_high_irq_chip;
+
+ if (trigger & (1 << pin))
+ set_irq_chip_and_handler(i, chip, handle_edge_irq);
+ else
+ set_irq_chip_and_handler(i, chip, handle_level_irq);
+
}
return cascade_irq(GIUINT_IRQ, giu_get_irq);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index a8239dac994..06c32a3e3ca 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -784,7 +784,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;
- newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
+ newscreen = kmalloc(new_screen_size, GFP_USER);
if (!newscreen)
return -ENOMEM;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index ac5d60edbaf..dc8368ebb1a 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -129,7 +129,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str
!capable(CAP_SYS_RESOURCE))
return -EPERM;
- key_map = (ushort *) kmalloc(sizeof(plain_map),
+ key_map = kmalloc(sizeof(plain_map),
GFP_KERNEL);
if (!key_map)
return -ENOMEM;
@@ -259,7 +259,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
sz = 256;
while (sz < funcbufsize - funcbufleft + delta)
sz <<= 1;
- fnw = (char *) kmalloc(sz, GFP_KERNEL);
+ fnw = kmalloc(sz, GFP_KERNEL);
if(!fnw) {
ret = -ENOMEM;
goto reterr;
@@ -1087,7 +1087,7 @@ static void complete_change_console(struct vc_data *vc)
switch_screen(vc);
/*
- * This can't appear below a successful kill_proc(). If it did,
+ * This can't appear below a successful kill_pid(). If it did,
* then the *blank_screen operation could occur while X, having
* received acqsig, is waking up on another processor. This
* condition can lead to overlapping accesses to the VGA range
@@ -1110,7 +1110,7 @@ static void complete_change_console(struct vc_data *vc)
*/
if (vc->vt_mode.mode == VT_PROCESS) {
/*
- * Send the signal as privileged - kill_proc() will
+ * Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
@@ -1170,7 +1170,7 @@ void change_console(struct vc_data *new_vc)
vc = vc_cons[fg_console].d;
if (vc->vt_mode.mode == VT_PROCESS) {
/*
- * Send the signal as privileged - kill_proc() will
+ * Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
* is awry
*/
diff --git a/drivers/char/watchdog/at91rm9200_wdt.c b/drivers/char/watchdog/at91rm9200_wdt.c
index cb86967e2c5..38bd3737259 100644
--- a/drivers/char/watchdog/at91rm9200_wdt.c
+++ b/drivers/char/watchdog/at91rm9200_wdt.c
@@ -203,9 +203,9 @@ static int __init at91wdt_probe(struct platform_device *pdev)
{
int res;
- if (at91wdt_miscdev.dev)
+ if (at91wdt_miscdev.parent)
return -EBUSY;
- at91wdt_miscdev.dev = &pdev->dev;
+ at91wdt_miscdev.parent = &pdev->dev;
res = misc_register(&at91wdt_miscdev);
if (res)
@@ -221,7 +221,7 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
res = misc_deregister(&at91wdt_miscdev);
if (!res)
- at91wdt_miscdev.dev = NULL;
+ at91wdt_miscdev.parent = NULL;
return res;
}
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
index 3404a9c67f0..e88947f8fe5 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -347,7 +347,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
goto err_free;
}
- mpcore_wdt_miscdev.dev = &dev->dev;
+ mpcore_wdt_miscdev.parent = &dev->dev;
ret = misc_register(&mpcore_wdt_miscdev);
if (ret) {
dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
index 5dbd7dc2936..6c6f97332db 100644
--- a/drivers/char/watchdog/omap_wdt.c
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -290,7 +290,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev)
omap_wdt_disable();
omap_wdt_adjust_timeout(timer_margin);
- omap_wdt_miscdev.dev = &pdev->dev;
+ omap_wdt_miscdev.parent = &pdev->dev;
ret = misc_register(&omap_wdt_miscdev);
if (ret)
goto fail;
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 61138726b50..2da5ac99687 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -42,6 +42,7 @@
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/mutex.h>
+#include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
#ifdef CONFIG_USB_DEBUG
@@ -109,10 +110,6 @@ MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
#define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */
#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG
-/* Some defines that I like to be somewhere else like include/linux/usb_hid.h */
-#define HID_REQ_SET_REPORT 0x09
-#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
-
/* We can only use 1 card due to the /dev/watchdog restriction */
static int cards_found;
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c
index ec3909371c2..7576a13e86b 100644
--- a/drivers/char/watchdog/rm9k_wdt.c
+++ b/drivers/char/watchdog/rm9k_wdt.c
@@ -47,7 +47,7 @@
/* Function prototypes */
-static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *);
+static irqreturn_t wdt_gpi_irqhdl(int, void *);
static void wdt_gpi_start(void);
static void wdt_gpi_stop(void);
static void wdt_gpi_set_timeout(unsigned int);
@@ -94,8 +94,28 @@ module_param(nowayout, bool, 0444);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started");
+/* Kernel interfaces */
+static struct file_operations fops = {
+ .owner = THIS_MODULE,
+ .open = wdt_gpi_open,
+ .release = wdt_gpi_release,
+ .write = wdt_gpi_write,
+ .unlocked_ioctl = wdt_gpi_ioctl,
+};
+
+static struct miscdevice miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = wdt_gpi_name,
+ .fops = &fops,
+};
+
+static struct notifier_block wdt_gpi_shutdown = {
+ .notifier_call = wdt_gpi_notify,
+};
+
+
/* Interrupt handler */
-static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
+static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt)
{
if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1))
return IRQ_NONE;
@@ -312,26 +332,6 @@ wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused)
}
-/* Kernel interfaces */
-static struct file_operations fops = {
- .owner = THIS_MODULE,
- .open = wdt_gpi_open,
- .release = wdt_gpi_release,
- .write = wdt_gpi_write,
- .unlocked_ioctl = wdt_gpi_ioctl,
-};
-
-static struct miscdevice miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = wdt_gpi_name,
- .fops = &fops,
-};
-
-static struct notifier_block wdt_gpi_shutdown = {
- .notifier_call = wdt_gpi_notify,
-};
-
-
/* Init & exit procedures */
static const struct resource *
wdt_gpi_get_resource(struct platform_device *pdv, const char *name,
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 7fcb77a9d01..b6bcdbbf57b 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -77,11 +77,11 @@ static struct clocksource clocksource_acpi_pm = {
#ifdef CONFIG_PCI
-static int acpi_pm_good;
+static int __devinitdata acpi_pm_good;
static int __init acpi_pm_good_setup(char *__str)
{
- acpi_pm_good = 1;
- return 1;
+ acpi_pm_good = 1;
+ return 1;
}
__setup("acpi_pm_good", acpi_pm_good_setup);
@@ -142,6 +142,39 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
acpi_pm_check_graylist);
#endif
+#ifndef CONFIG_X86_64
+#include "mach_timer.h"
+#define PMTMR_EXPECTED_RATE \
+ ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10))
+/*
+ * Some boards have the PMTMR running way too fast. We check
+ * the PMTMR rate against PIT channel 2 to catch these cases.
+ */
+static int verify_pmtmr_rate(void)
+{
+ u32 value1, value2;
+ unsigned long count, delta;
+
+ mach_prepare_counter();
+ value1 = read_pmtmr();
+ mach_countup(&count);
+ value2 = read_pmtmr();
+ delta = (value2 - value1) & ACPI_PM_MASK;
+
+ /* Check that the PMTMR delta is within 5% of what we expect */
+ if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
+ delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
+ printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% "
+ "of normal - aborting.\n",
+ 100UL * delta / PMTMR_EXPECTED_RATE);
+ return -1;
+ }
+
+ return 0;
+}
+#else
+#define verify_pmtmr_rate() (0)
+#endif
static int __init init_acpi_pm_clocksource(void)
{
@@ -173,6 +206,9 @@ static int __init init_acpi_pm_clocksource(void)
return -ENODEV;
pm_good:
+ if (verify_pmtmr_rate() != 0)
+ return -ENODEV;
+
return clocksource_register(&clocksource_acpi_pm);
}
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 3ece6923134..5c9f67f98d1 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/connector.h>
#include <asm/atomic.h>
+#include <asm/unaligned.h>
#include <linux/cn_proc.h>
@@ -60,7 +61,7 @@ void proc_fork_connector(struct task_struct *task)
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
ev->what = PROC_EVENT_FORK;
ev->event_data.fork.parent_pid = task->real_parent->pid;
ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -88,7 +89,7 @@ void proc_exec_connector(struct task_struct *task)
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -124,7 +125,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
return;
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -146,7 +147,7 @@ void proc_exit_connector(struct task_struct *task)
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -181,7 +182,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
ev = (struct proc_event*)msg->data;
msg->seq = rcvd_seq;
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index b418b16e910..296f51002b5 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -34,7 +34,7 @@
void cn_queue_wrapper(struct work_struct *work)
{
struct cn_callback_entry *cbq =
- container_of(work, struct cn_callback_entry, work.work);
+ container_of(work, struct cn_callback_entry, work);
struct cn_callback_data *d = &cbq->data;
d->callback(d->callback_priv);
@@ -59,13 +59,12 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc
memcpy(&cbq->id.id, id, sizeof(struct cb_id));
cbq->data.callback = callback;
- INIT_DELAYED_WORK(&cbq->work, &cn_queue_wrapper);
+ INIT_WORK(&cbq->work, &cn_queue_wrapper);
return cbq;
}
static void cn_queue_free_callback(struct cn_callback_entry *cbq)
{
- cancel_delayed_work(&cbq->work);
flush_workqueue(cbq->pdev->cn_queue);
kfree(cbq);
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 5e7cd45d10e..a44db75bc25 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -135,17 +135,15 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
- if (likely(!test_bit(WORK_STRUCT_PENDING,
- &__cbq->work.work.management) &&
+ if (likely(!work_pending(&__cbq->work) &&
__cbq->data.ddata == NULL)) {
__cbq->data.callback_priv = msg;
__cbq->data.ddata = data;
__cbq->data.destruct_data = destruct_data;
- if (queue_delayed_work(
- dev->cbdev->cn_queue,
- &__cbq->work, 0))
+ if (queue_work(dev->cbdev->cn_queue,
+ &__cbq->work))
err = 0;
} else {
struct cn_callback_data *d;
@@ -159,12 +157,11 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
d->destruct_data = destruct_data;
d->free = __cbq;
- INIT_DELAYED_WORK(&__cbq->work,
- &cn_queue_wrapper);
+ INIT_WORK(&__cbq->work,
+ &cn_queue_wrapper);
- if (queue_delayed_work(
- dev->cbdev->cn_queue,
- &__cbq->work, 0))
+ if (queue_work(dev->cbdev->cn_queue,
+ &__cbq->work))
err = 0;
else {
kfree(__cbq);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 47ab42db122..a45cc89e387 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -29,7 +29,8 @@
#include <linux/completion.h>
#include <linux/mutex.h>
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
+ "cpufreq-core", msg)
/**
* The "cpufreq driver" - the arch- or hardware-dependent low
@@ -151,7 +152,8 @@ static void cpufreq_debug_disable_ratelimit(void)
spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
}
-void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt, ...)
+void cpufreq_debug_printk(unsigned int type, const char *prefix,
+ const char *fmt, ...)
{
char s[256];
va_list args;
@@ -161,7 +163,8 @@ void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt
WARN_ON(!prefix);
if (type & debug) {
spin_lock_irqsave(&disable_ratelimit_lock, flags);
- if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit()) {
+ if (!disable_ratelimit && debug_ratelimit
+ && !printk_ratelimit()) {
spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
return;
}
@@ -182,10 +185,12 @@ EXPORT_SYMBOL(cpufreq_debug_printk);
module_param(debug, uint, 0644);
-MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors.");
+MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core,"
+ " 2 to debug drivers, and 4 to debug governors.");
module_param(debug_ratelimit, uint, 0644);
-MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging: set to 0 to disable ratelimiting.");
+MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging:"
+ " set to 0 to disable ratelimiting.");
#else /* !CONFIG_CPU_FREQ_DEBUG */
@@ -219,17 +224,23 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
if (!l_p_j_ref_freq) {
l_p_j_ref = loops_per_jiffy;
l_p_j_ref_freq = ci->old;
- dprintk("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
+ dprintk("saving %lu as reference value for loops_per_jiffy;"
+ "freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
}
if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
(val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
- loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
- dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new);
+ loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
+ ci->new);
+ dprintk("scaling loops_per_jiffy to %lu"
+ "for frequency %u kHz\n", loops_per_jiffy, ci->new);
}
}
#else
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+{
+ return;
+}
#endif
@@ -316,7 +327,8 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_PERFORMANCE;
err = 0;
- } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
+ } else if (!strnicmp(str_governor, "powersave",
+ CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
err = 0;
}
@@ -328,7 +340,8 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
t = __find_governor(str_governor);
if (t == NULL) {
- char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor);
+ char *name = kasprintf(GFP_KERNEL, "cpufreq_%s",
+ str_governor);
if (name) {
int ret;
@@ -361,7 +374,8 @@ extern struct sysdev_class cpu_sysdev_class;
/**
- * cpufreq_per_cpu_attr_read() / show_##file_name() - print out cpufreq information
+ * cpufreq_per_cpu_attr_read() / show_##file_name() -
+ * print out cpufreq information
*
* Write out information from cpufreq_driver->policy[cpu]; object must be
* "unsigned int".
@@ -380,7 +394,8 @@ show_one(scaling_min_freq, min);
show_one(scaling_max_freq, max);
show_one(scaling_cur_freq, cur);
-static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
+static int __cpufreq_set_policy(struct cpufreq_policy *data,
+ struct cpufreq_policy *policy);
/**
* cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
@@ -416,7 +431,8 @@ store_one(scaling_max_freq,max);
/**
* show_cpuinfo_cur_freq - current CPU frequency as detected by hardware
*/
-static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, char *buf)
+static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
+ char *buf)
{
unsigned int cur_freq = cpufreq_get(policy->cpu);
if (!cur_freq)
@@ -428,7 +444,8 @@ static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, char *buf)
/**
* show_scaling_governor - show the current policy for the specified CPU
*/
-static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
+static ssize_t show_scaling_governor (struct cpufreq_policy * policy,
+ char *buf)
{
if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
return sprintf(buf, "powersave\n");
@@ -458,7 +475,8 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
if (ret != 1)
return -EINVAL;
- if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
+ if (cpufreq_parse_governor(str_governor, &new_policy.policy,
+ &new_policy.governor))
return -EINVAL;
lock_cpu_hotplug();
@@ -474,7 +492,10 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
unlock_cpu_hotplug();
- return ret ? ret : count;
+ if (ret)
+ return ret;
+ else
+ return count;
}
/**
@@ -488,7 +509,7 @@ static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
/**
* show_scaling_available_governors - show the available CPUfreq governors
*/
-static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
+static ssize_t show_scaling_available_governors (struct cpufreq_policy *policy,
char *buf)
{
ssize_t i = 0;
@@ -574,7 +595,11 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
policy = cpufreq_cpu_get(policy->cpu);
if (!policy)
return -EINVAL;
- ret = fattr->show ? fattr->show(policy,buf) : -EIO;
+ if (fattr->show)
+ ret = fattr->show(policy, buf);
+ else
+ ret = -EIO;
+
cpufreq_cpu_put(policy);
return ret;
}
@@ -588,7 +613,11 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
policy = cpufreq_cpu_get(policy->cpu);
if (!policy)
return -EINVAL;
- ret = fattr->store ? fattr->store(policy,buf,count) : -EIO;
+ if (fattr->store)
+ ret = fattr->store(policy, buf, count);
+ else
+ ret = -EIO;
+
cpufreq_cpu_put(policy);
return ret;
}
@@ -693,8 +722,13 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
dprintk("CPU already managed, adding link\n");
- sysfs_create_link(&sys_dev->kobj,
- &managed_policy->kobj, "cpufreq");
+ ret = sysfs_create_link(&sys_dev->kobj,
+ &managed_policy->kobj,
+ "cpufreq");
+ if (ret) {
+ mutex_unlock(&policy->lock);
+ goto err_out_driver_exit;
+ }
cpufreq_debug_enable_ratelimit();
mutex_unlock(&policy->lock);
@@ -741,8 +775,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
dprintk("CPU %u already managed, adding link\n", j);
cpufreq_cpu_get(cpu);
cpu_sys_dev = get_cpu_sysdev(j);
- sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
- "cpufreq");
+ ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
+ "cpufreq");
+ if (ret) {
+ mutex_unlock(&policy->lock);
+ goto err_out_unregister;
+ }
}
policy->governor = NULL; /* to assure that the starting sequence is
@@ -913,7 +951,8 @@ static void handle_update(struct work_struct *work)
* We adjust to current frequency first, and need to clean up later. So either call
* to cpufreq_update_policy() or schedule handle_update()).
*/
-static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int new_freq)
+static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
+ unsigned int new_freq)
{
struct cpufreq_freqs freqs;
@@ -929,7 +968,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
/**
- * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur
+ * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur
* @cpu: CPU number
*
* This is the last known freq, without actually getting it from the driver.
@@ -938,16 +977,16 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
unsigned int cpufreq_quick_get(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- unsigned int ret = 0;
+ unsigned int ret_freq = 0;
if (policy) {
mutex_lock(&policy->lock);
- ret = policy->cur;
+ ret_freq = policy->cur;
mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy);
}
- return (ret);
+ return (ret_freq);
}
EXPORT_SYMBOL(cpufreq_quick_get);
@@ -961,7 +1000,7 @@ EXPORT_SYMBOL(cpufreq_quick_get);
unsigned int cpufreq_get(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- unsigned int ret = 0;
+ unsigned int ret_freq = 0;
if (!policy)
return 0;
@@ -971,12 +1010,14 @@ unsigned int cpufreq_get(unsigned int cpu)
mutex_lock(&policy->lock);
- ret = cpufreq_driver->get(cpu);
+ ret_freq = cpufreq_driver->get(cpu);
- if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
- /* verify no discrepancy between actual and saved value exists */
- if (unlikely(ret != policy->cur)) {
- cpufreq_out_of_sync(cpu, policy->cur, ret);
+ if (ret_freq && policy->cur &&
+ !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
+ /* verify no discrepancy between actual and
+ saved value exists */
+ if (unlikely(ret_freq != policy->cur)) {
+ cpufreq_out_of_sync(cpu, policy->cur, ret_freq);
schedule_work(&policy->update);
}
}
@@ -986,7 +1027,7 @@ unsigned int cpufreq_get(unsigned int cpu)
out:
cpufreq_cpu_put(policy);
- return (ret);
+ return (ret_freq);
}
EXPORT_SYMBOL(cpufreq_get);
@@ -998,7 +1039,7 @@ EXPORT_SYMBOL(cpufreq_get);
static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
{
int cpu = sysdev->id;
- unsigned int ret = 0;
+ int ret = 0;
unsigned int cur_freq = 0;
struct cpufreq_policy *cpu_policy;
@@ -1080,7 +1121,7 @@ out:
static int cpufreq_resume(struct sys_device * sysdev)
{
int cpu = sysdev->id;
- unsigned int ret = 0;
+ int ret = 0;
struct cpufreq_policy *cpu_policy;
dprintk("resuming cpu %u\n", cpu);
@@ -1276,22 +1317,45 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
}
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
+int cpufreq_driver_getavg(struct cpufreq_policy *policy)
+{
+ int ret = 0;
+
+ policy = cpufreq_cpu_get(policy->cpu);
+ if (!policy)
+ return -EINVAL;
+
+ mutex_lock(&policy->lock);
+
+ if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
+ ret = cpufreq_driver->getavg(policy->cpu);
+
+ mutex_unlock(&policy->lock);
+
+ cpufreq_cpu_put(policy);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_getavg);
+
/*
* Locking: Must be called with the lock_cpu_hotplug() lock held
* when "event" is CPUFREQ_GOV_LIMITS
*/
-static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
+static int __cpufreq_governor(struct cpufreq_policy *policy,
+ unsigned int event)
{
int ret;
if (!try_module_get(policy->governor->owner))
return -EINVAL;
- dprintk("__cpufreq_governor for CPU %u, event %u\n", policy->cpu, event);
+ dprintk("__cpufreq_governor for CPU %u, event %u\n",
+ policy->cpu, event);
ret = policy->governor->governor(policy, event);
- /* we keep one module reference alive for each CPU governed by this CPU */
+ /* we keep one module reference alive for
+ each CPU governed by this CPU */
if ((event != CPUFREQ_GOV_START) || ret)
module_put(policy->governor->owner);
if ((event == CPUFREQ_GOV_STOP) && !ret)
@@ -1367,9 +1431,12 @@ EXPORT_SYMBOL(cpufreq_get_policy);
/*
+ * data : current policy.
+ * policy : policy to be set.
* Locking: Must be called with the lock_cpu_hotplug() lock held
*/
-static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy)
+static int __cpufreq_set_policy(struct cpufreq_policy *data,
+ struct cpufreq_policy *policy)
{
int ret = 0;
@@ -1377,7 +1444,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
policy->min, policy->max);
- memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
+ memcpy(&policy->cpuinfo, &data->cpuinfo,
+ sizeof(struct cpufreq_cpuinfo));
if (policy->min > data->min && policy->min > policy->max) {
ret = -EINVAL;
@@ -1410,7 +1478,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
data->min = policy->min;
data->max = policy->max;
- dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max);
+ dprintk("new min and max freqs are %u - %u kHz\n",
+ data->min, data->max);
if (cpufreq_driver->setpolicy) {
data->policy = policy->policy;
@@ -1431,10 +1500,12 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
data->governor = policy->governor;
if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
/* new governor failed, so re-start old one */
- dprintk("starting governor %s failed\n", data->governor->name);
+ dprintk("starting governor %s failed\n",
+ data->governor->name);
if (old_gov) {
data->governor = old_gov;
- __cpufreq_governor(data, CPUFREQ_GOV_START);
+ __cpufreq_governor(data,
+ CPUFREQ_GOV_START);
}
ret = -EINVAL;
goto error_out;
@@ -1524,7 +1595,8 @@ int cpufreq_update_policy(unsigned int cpu)
data->cur = policy.cur;
} else {
if (data->cur != policy.cur)
- cpufreq_out_of_sync(cpu, data->cur, policy.cur);
+ cpufreq_out_of_sync(cpu, data->cur,
+ policy.cur);
}
}
@@ -1626,8 +1698,10 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
/* if all ->init() calls failed, unregister */
if (ret) {
- dprintk("no CPU initialized for driver %s\n", driver_data->name);
- sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
+ dprintk("no CPU initialized for driver %s\n",
+ driver_data->name);
+ sysdev_driver_unregister(&cpu_sysdev_class,
+ &cpufreq_sysdev_driver);
spin_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_driver = NULL;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 5ef5ede5b88..eef0270c6f3 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -44,15 +44,17 @@
* latency of the processor. The governor will work on any processor with
* transition latency <= 10mS, using appropriate sampling
* rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
+ * For CPUs with transition latency > 10mS (mostly drivers
+ * with CPUFREQ_ETERNAL), this governor will not work.
* All times here are in uS.
*/
static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE_RATIO (2)
/* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+#define MIN_STAT_SAMPLING_RATE \
+ (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE \
+ (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
#define DEF_SAMPLING_DOWN_FACTOR (1)
@@ -103,11 +105,16 @@ static struct dbs_tuners dbs_tuners_ins = {
static inline unsigned int get_cpu_idle_time(unsigned int cpu)
{
- return kstat_cpu(cpu).cpustat.idle +
+ unsigned int add_nice = 0, ret;
+
+ if (dbs_tuners_ins.ignore_nice)
+ add_nice = kstat_cpu(cpu).cpustat.nice;
+
+ ret = kstat_cpu(cpu).cpustat.idle +
kstat_cpu(cpu).cpustat.iowait +
- ( dbs_tuners_ins.ignore_nice ?
- kstat_cpu(cpu).cpustat.nice :
- 0);
+ add_nice;
+
+ return ret;
}
/************************** sysfs interface ************************/
@@ -452,6 +459,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
unsigned int cpu = policy->cpu;
struct cpu_dbs_info_s *this_dbs_info;
unsigned int j;
+ int rc;
this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
@@ -468,6 +476,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break;
mutex_lock(&dbs_mutex);
+
+ rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
+ if (rc) {
+ mutex_unlock(&dbs_mutex);
+ return rc;
+ }
+
for_each_cpu_mask(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -480,7 +495,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
this_dbs_info->enable = 1;
this_dbs_info->down_skip = 0;
this_dbs_info->requested_freq = policy->cur;
- sysfs_create_group(&policy->kobj, &dbs_attr_group);
+
dbs_enable++;
/*
* Start the timerschedule work, when this governor
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index e1cc5113c2a..f697449327c 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -41,8 +41,10 @@
static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE_RATIO (2)
/* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
+#define MIN_STAT_SAMPLING_RATE \
+ (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE \
+ (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
@@ -206,7 +208,8 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
ret = sscanf(buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
+ if (ret != 1 || input > MAX_SAMPLING_RATE
+ || input < MIN_SAMPLING_RATE) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
}
@@ -397,8 +400,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
* policy. To be safe, we focus 10 points under the threshold.
*/
if (load < (dbs_tuners_ins.up_threshold - 10)) {
- unsigned int freq_next = (policy->cur * load) /
+ unsigned int freq_next, freq_cur;
+
+ freq_cur = cpufreq_driver_getavg(policy);
+ if (!freq_cur)
+ freq_cur = policy->cur;
+
+ freq_next = (freq_cur * load) /
(dbs_tuners_ins.up_threshold - 10);
+
if (!dbs_tuners_ins.powersave_bias) {
__cpufreq_driver_target(policy, freq_next,
CPUFREQ_RELATION_L);
@@ -472,6 +482,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
unsigned int cpu = policy->cpu;
struct cpu_dbs_info_s *this_dbs_info;
unsigned int j;
+ int rc;
this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
@@ -494,12 +505,23 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (dbs_enable == 1) {
kondemand_wq = create_workqueue("kondemand");
if (!kondemand_wq) {
- printk(KERN_ERR "Creation of kondemand failed\n");
+ printk(KERN_ERR
+ "Creation of kondemand failed\n");
dbs_enable--;
mutex_unlock(&dbs_mutex);
return -ENOSPC;
}
}
+
+ rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
+ if (rc) {
+ if (dbs_enable == 1)
+ destroy_workqueue(kondemand_wq);
+ dbs_enable--;
+ mutex_unlock(&dbs_mutex);
+ return rc;
+ }
+
for_each_cpu_mask(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -509,7 +531,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info->prev_cpu_wall = get_jiffies_64();
}
this_dbs_info->enable = 1;
- sysfs_create_group(&policy->kobj, &dbs_attr_group);
/*
* Start the timerschedule work, when this governor
* is used for first time
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index de91e3371ef..e8e1451ef1c 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -15,7 +15,8 @@
#include <linux/cpufreq.h>
#include <linux/init.h>
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg)
+#define dprintk(msg...) \
+ cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg)
static int cpufreq_governor_performance(struct cpufreq_policy *policy,
@@ -24,8 +25,10 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
switch (event) {
case CPUFREQ_GOV_START:
case CPUFREQ_GOV_LIMITS:
- dprintk("setting to %u kHz because of event %u\n", policy->max, event);
- __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
+ dprintk("setting to %u kHz because of event %u\n",
+ policy->max, event);
+ __cpufreq_driver_target(policy, policy->max,
+ CPUFREQ_RELATION_H);
break;
default:
break;
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 0a2596044e6..13fe06b94b0 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -15,7 +15,8 @@
#include <linux/cpufreq.h>
#include <linux/init.h>
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg)
+#define dprintk(msg...) \
+ cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg)
static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
unsigned int event)
@@ -23,8 +24,10 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
switch (event) {
case CPUFREQ_GOV_START:
case CPUFREQ_GOV_LIMITS:
- dprintk("setting to %u kHz because of event %u\n", policy->min, event);
- __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
+ dprintk("setting to %u kHz because of event %u\n",
+ policy->min, event);
+ __cpufreq_driver_target(policy, policy->min,
+ CPUFREQ_RELATION_L);
break;
default:
break;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index c2ecc599dc5..91ad342a605 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -285,6 +285,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
stat = cpufreq_stats_table[freq->cpu];
if (!stat)
return 0;
+
old_index = freq_table_get_index(stat, freq->old);
new_index = freq_table_get_index(stat, freq->new);
@@ -292,6 +293,9 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
if (old_index == new_index)
return 0;
+ if (old_index == -1 || new_index == -1)
+ return 0;
+
spin_lock(&cpufreq_stats_lock);
stat->last_index = new_index;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
@@ -351,8 +355,8 @@ __init cpufreq_stats_init(void)
register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
for_each_online_cpu(cpu) {
- cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE,
- (void *)(long)cpu);
+ cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier,
+ CPU_ONLINE, (void *)(long)cpu);
}
return 0;
}
@@ -368,14 +372,15 @@ __exit cpufreq_stats_exit(void)
unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
lock_cpu_hotplug();
for_each_online_cpu(cpu) {
- cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD,
- (void *)(long)cpu);
+ cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier,
+ CPU_DEAD, (void *)(long)cpu);
}
unlock_cpu_hotplug();
}
MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
-MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats through sysfs filesystem");
+MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats"
+ "through sysfs filesystem");
MODULE_LICENSE ("GPL");
module_init(cpufreq_stats_init);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index a06c204589c..2a4eb0bfaf3 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -131,19 +131,26 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
unsigned int event)
{
unsigned int cpu = policy->cpu;
+ int rc = 0;
+
switch (event) {
case CPUFREQ_GOV_START:
if (!cpu_online(cpu))
return -EINVAL;
BUG_ON(!policy->cur);
mutex_lock(&userspace_mutex);
+ rc = sysfs_create_file (&policy->kobj,
+ &freq_attr_scaling_setspeed.attr);
+ if (rc)
+ goto start_out;
+
cpu_is_managed[cpu] = 1;
cpu_min_freq[cpu] = policy->min;
cpu_max_freq[cpu] = policy->max;
cpu_cur_freq[cpu] = policy->cur;
cpu_set_freq[cpu] = policy->cur;
- sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
+start_out:
mutex_unlock(&userspace_mutex);
break;
case CPUFREQ_GOV_STOP:
@@ -180,7 +187,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
mutex_unlock(&userspace_mutex);
break;
}
- return 0;
+ return rc;
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 551f4ccf87f..e7490925fdc 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -9,7 +9,8 @@
#include <linux/init.h>
#include <linux/cpufreq.h>
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
+#define dprintk(msg...) \
+ cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
/*********************************************************************
* FREQUENCY TABLE HELPERS *
@@ -29,7 +30,8 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
continue;
}
- dprintk("table entry %u: %u kHz, %u index\n", i, freq, table[i].index);
+ dprintk("table entry %u: %u kHz, %u index\n",
+ i, freq, table[i].index);
if (freq < min_freq)
min_freq = freq;
if (freq > max_freq)
@@ -54,13 +56,14 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
unsigned int i;
unsigned int count = 0;
- dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
+ dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n",
+ policy->min, policy->max, policy->cpu);
if (!cpu_online(policy->cpu))
return -EINVAL;
- cpufreq_verify_within_limits(policy,
- policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
@@ -75,10 +78,11 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
if (!count)
policy->max = next_larger;
- cpufreq_verify_within_limits(policy,
- policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
- dprintk("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
+ dprintk("verification lead to (%u - %u kHz) for cpu %u\n",
+ policy->min, policy->max, policy->cpu);
return 0;
}
@@ -101,7 +105,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
};
unsigned int i;
- dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu);
+ dprintk("request for target %u kHz (relation: %u) for cpu %u\n",
+ target_freq, relation, policy->cpu);
switch (relation) {
case CPUFREQ_RELATION_H:
@@ -192,7 +197,10 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
}
struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
- .attr = { .name = "scaling_available_frequencies", .mode = 0444, .owner=THIS_MODULE },
+ .attr = { .name = "scaling_available_frequencies",
+ .mode = 0444,
+ .owner=THIS_MODULE
+ },
.show = show_available_freqs,
};
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e816535ab30..879250d3d06 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -53,7 +53,7 @@ config CRYPTO_DEV_PADLOCK_SHA
config CRYPTO_DEV_GEODE
tristate "Support for the Geode LX AES engine"
- depends on CRYPTO && X86_32
+ depends on CRYPTO && X86_32 && PCI
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
default m
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index ca4e67a022d..22b62b3cd14 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -266,7 +266,7 @@ static void fcp_report_map_done(fc_channel *fc, int i, int status)
printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
fc->state = FC_STATE_OFFLINE;
} else {
- fc->posmap = (fcp_posmap *)kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
+ fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
if (!fc->posmap) {
printk("FC: Not enough memory, offlining channel\n");
fc->state = FC_STATE_OFFLINE;
@@ -355,7 +355,7 @@ void fcp_register(fc_channel *fc, u8 type, int unregister)
for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
set_bit (i, fc->scsi_bitmap);
fc->scsi_free = fc->can_queue;
- fc->cmd_slots = (fcp_cmnd **)kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
+ fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
fc->abort_count = 0;
} else {
fc->scsi_name[0] = 0;
@@ -933,7 +933,7 @@ int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt)
DECLARE_MUTEX_LOCKED(sem);
if (!fc->rst_pkt) {
- fc->rst_pkt = (struct scsi_cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL);
+ fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL);
if (!fc->rst_pkt) return FAILED;
fcmd = FCP_CMND(fc->rst_pkt);
@@ -1107,7 +1107,7 @@ int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
logi *l;
int status;
- l = (logi *)kzalloc(2 * sizeof(logi), GFP_KERNEL);
+ l = kzalloc(2 * sizeof(logi), GFP_KERNEL);
if (!l) return -ENOMEM;
l->code = LS_PLOGI;
memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
@@ -1141,7 +1141,7 @@ int fc_do_prli(fc_channel *fc, unsigned char alpa)
prli *p;
int status;
- p = (prli *)kzalloc(2 * sizeof(prli), GFP_KERNEL);
+ p = kzalloc(2 * sizeof(prli), GFP_KERNEL);
if (!p) return -ENOMEM;
p->code = LS_PRLI;
p->params[0] = 0x08002000;
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 5ab5e393b88..c6281ccd4fe 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -122,8 +122,6 @@ struct efivar_entry {
struct kobject kobj;
};
-#define get_efivar_entry(n) list_entry(n, struct efivar_entry, list)
-
struct efivar_attribute {
struct attribute attr;
ssize_t (*show) (struct efivar_entry *entry, char *buf);
@@ -386,9 +384,6 @@ static struct sysfs_ops efivar_attr_ops = {
static void efivar_release(struct kobject *kobj)
{
struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj);
- spin_lock(&efivars_lock);
- list_del(&var->list);
- spin_unlock(&efivars_lock);
kfree(var);
}
@@ -430,9 +425,8 @@ static ssize_t
efivar_create(struct subsystem *sub, const char *buf, size_t count)
{
struct efi_variable *new_var = (struct efi_variable *)buf;
- struct efivar_entry *search_efivar = NULL;
+ struct efivar_entry *search_efivar, *n;
unsigned long strsize1, strsize2;
- struct list_head *pos, *n;
efi_status_t status = EFI_NOT_FOUND;
int found = 0;
@@ -444,8 +438,7 @@ efivar_create(struct subsystem *sub, const char *buf, size_t count)
/*
* Does this variable already exist?
*/
- list_for_each_safe(pos, n, &efivar_list) {
- search_efivar = get_efivar_entry(pos);
+ list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
strsize2 = utf8_strsize(new_var->VariableName, 1024);
if (strsize1 == strsize2 &&
@@ -490,9 +483,8 @@ static ssize_t
efivar_delete(struct subsystem *sub, const char *buf, size_t count)
{
struct efi_variable *del_var = (struct efi_variable *)buf;
- struct efivar_entry *search_efivar = NULL;
+ struct efivar_entry *search_efivar, *n;
unsigned long strsize1, strsize2;
- struct list_head *pos, *n;
efi_status_t status = EFI_NOT_FOUND;
int found = 0;
@@ -504,8 +496,7 @@ efivar_delete(struct subsystem *sub, const char *buf, size_t count)
/*
* Does this variable already exist?
*/
- list_for_each_safe(pos, n, &efivar_list) {
- search_efivar = get_efivar_entry(pos);
+ list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
strsize2 = utf8_strsize(del_var->VariableName, 1024);
if (strsize1 == strsize2 &&
@@ -537,9 +528,9 @@ efivar_delete(struct subsystem *sub, const char *buf, size_t count)
spin_unlock(&efivars_lock);
return -EIO;
}
+ list_del(&search_efivar->list);
/* We need to release this lock before unregistering. */
spin_unlock(&efivars_lock);
-
efivar_unregister(search_efivar);
/* It's dead Jim.... */
@@ -768,10 +759,14 @@ out_free:
static void __exit
efivars_exit(void)
{
- struct list_head *pos, *n;
+ struct efivar_entry *entry, *n;
- list_for_each_safe(pos, n, &efivar_list)
- efivar_unregister(get_efivar_entry(pos));
+ list_for_each_entry_safe(entry, n, &efivar_list, list) {
+ spin_lock(&efivars_lock);
+ list_del(&entry->list);
+ spin_unlock(&efivars_lock);
+ efivar_unregister(entry);
+ }
subsystem_unregister(&vars_subsys);
firmware_unregister(&efi_subsys);
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
new file mode 100644
index 00000000000..ec796ad087d
--- /dev/null
+++ b/drivers/hid/Kconfig
@@ -0,0 +1,26 @@
+#
+# HID driver configuration
+#
+menu "HID Devices"
+ depends on INPUT
+
+config HID
+ tristate "Generic HID support"
+ depends on INPUT
+ default y
+ ---help---
+ A human interface device (HID) is a type of computer device that
+ interacts directly with and takes input from humans. The term "HID"
+ most commonly used to refer to the USB-HID specification, but other
+ devices (such as, but not strictly limited to, Bluetooth) are
+ designed using HID specification (this involves certain keyboards,
+ mice, tablets, etc). This option compiles into kernel the generic
+ HID layer code (parser, usages, etc.), which can then be used by
+ transport-specific HID implementation (like USB or Bluetooth).
+
+ For docs and specs, see http://www.usb.org/developers/hidpage/
+
+ If unsure, say Y
+
+endmenu
+
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
new file mode 100644
index 00000000000..6432392110b
--- /dev/null
+++ b/drivers/hid/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the HID driver
+#
+
+# Multipart objects.
+hid-objs := hid-core.o hid-input.o
+
+# Optional parts of multipart objects.
+
+obj-$(CONFIG_HID) += hid.o
+
+ifeq ($(CONFIG_INPUT_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
new file mode 100644
index 00000000000..49f18f5b251
--- /dev/null
+++ b/drivers/hid/hid-core.c
@@ -0,0 +1,1000 @@
+/*
+ * HID support for Linux
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/slab.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <linux/input.h>
+#include <linux/wait.h>
+
+#undef DEBUG
+#undef DEBUG_DATA
+
+#include <linux/hid.h>
+#include <linux/hiddev.h>
+
+/*
+ * Version Information
+ */
+
+#define DRIVER_VERSION "v2.6"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
+#define DRIVER_DESC "HID core driver"
+#define DRIVER_LICENSE "GPL"
+
+/*
+ * Register a new report for a device.
+ */
+
+static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
+{
+ struct hid_report_enum *report_enum = device->report_enum + type;
+ struct hid_report *report;
+
+ if (report_enum->report_id_hash[id])
+ return report_enum->report_id_hash[id];
+
+ if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
+ return NULL;
+
+ if (id != 0)
+ report_enum->numbered = 1;
+
+ report->id = id;
+ report->type = type;
+ report->size = 0;
+ report->device = device;
+ report_enum->report_id_hash[id] = report;
+
+ list_add_tail(&report->list, &report_enum->report_list);
+
+ return report;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+{
+ struct hid_field *field;
+
+ if (report->maxfield == HID_MAX_FIELDS) {
+ dbg("too many fields in report");
+ return NULL;
+ }
+
+ if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
+
+ field->index = report->maxfield++;
+ report->field[field->index] = field;
+ field->usage = (struct hid_usage *)(field + 1);
+ field->value = (unsigned *)(field->usage + usages);
+ field->report = report;
+
+ return field;
+}
+
+/*
+ * Open a collection. The type/usage is pushed on the stack.
+ */
+
+static int open_collection(struct hid_parser *parser, unsigned type)
+{
+ struct hid_collection *collection;
+ unsigned usage;
+
+ usage = parser->local.usage[0];
+
+ if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
+ dbg("collection stack overflow");
+ return -1;
+ }
+
+ if (parser->device->maxcollection == parser->device->collection_size) {
+ collection = kmalloc(sizeof(struct hid_collection) *
+ 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);
+ memset(collection + parser->device->collection_size, 0,
+ sizeof(struct hid_collection) *
+ parser->device->collection_size);
+ kfree(parser->device->collection);
+ parser->device->collection = collection;
+ parser->device->collection_size *= 2;
+ }
+
+ parser->collection_stack[parser->collection_stack_ptr++] =
+ parser->device->maxcollection;
+
+ 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++;
+
+ return 0;
+}
+
+/*
+ * Close a collection.
+ */
+
+static int close_collection(struct hid_parser *parser)
+{
+ if (!parser->collection_stack_ptr) {
+ dbg("collection stack underflow");
+ return -1;
+ }
+ parser->collection_stack_ptr--;
+ return 0;
+}
+
+/*
+ * Climb up the stack, search for the specified collection type
+ * and return the usage.
+ */
+
+static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
+{
+ int n;
+ for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
+ if (parser->device->collection[parser->collection_stack[n]].type == type)
+ return parser->device->collection[parser->collection_stack[n]].usage;
+ return 0; /* we know nothing about this usage type */
+}
+
+/*
+ * Add a usage to the temporary parser table.
+ */
+
+static int hid_add_usage(struct hid_parser *parser, unsigned usage)
+{
+ if (parser->local.usage_index >= HID_MAX_USAGES) {
+ dbg("usage index exceeded");
+ return -1;
+ }
+ parser->local.usage[parser->local.usage_index] = usage;
+ parser->local.collection_index[parser->local.usage_index] =
+ parser->collection_stack_ptr ?
+ parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
+ parser->local.usage_index++;
+ return 0;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
+{
+ struct hid_report *report;
+ struct hid_field *field;
+ int usages;
+ unsigned offset;
+ int i;
+
+ if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
+ dbg("hid_register_report failed");
+ return -1;
+ }
+
+ if (parser->global.logical_maximum < parser->global.logical_minimum) {
+ dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+ return -1;
+ }
+
+ 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;
+
+ field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
+ field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
+ field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
+
+ for (i = 0; i < usages; i++) {
+ int j = i;
+ /* Duplicate the last usage we parsed if we have excess values */
+ if (i >= parser->local.usage_index)
+ j = parser->local.usage_index - 1;
+ field->usage[i].hid = parser->local.usage[j];
+ field->usage[i].collection_index =
+ parser->local.collection_index[j];
+ }
+
+ field->maxusage = usages;
+ field->flags = flags;
+ field->report_offset = offset;
+ field->report_type = report_type;
+ field->report_size = parser->global.report_size;
+ field->report_count = parser->global.report_count;
+ field->logical_minimum = parser->global.logical_minimum;
+ field->logical_maximum = parser->global.logical_maximum;
+ field->physical_minimum = parser->global.physical_minimum;
+ field->physical_maximum = parser->global.physical_maximum;
+ field->unit_exponent = parser->global.unit_exponent;
+ field->unit = parser->global.unit;
+
+ return 0;
+}
+
+/*
+ * Read data value from item.
+ */
+
+static u32 item_udata(struct hid_item *item)
+{
+ switch (item->size) {
+ case 1: return item->data.u8;
+ case 2: return item->data.u16;
+ case 4: return item->data.u32;
+ }
+ return 0;
+}
+
+static s32 item_sdata(struct hid_item *item)
+{
+ switch (item->size) {
+ case 1: return item->data.s8;
+ case 2: return item->data.s16;
+ case 4: return item->data.s32;
+ }
+ return 0;
+}
+
+/*
+ * Process a global item.
+ */
+
+static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
+{
+ switch (item->tag) {
+
+ case HID_GLOBAL_ITEM_TAG_PUSH:
+
+ if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
+ dbg("global enviroment stack overflow");
+ return -1;
+ }
+
+ memcpy(parser->global_stack + parser->global_stack_ptr++,
+ &parser->global, sizeof(struct hid_global));
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_POP:
+
+ if (!parser->global_stack_ptr) {
+ dbg("global enviroment stack underflow");
+ return -1;
+ }
+
+ memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
+ sizeof(struct hid_global));
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+ parser->global.usage_page = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+ parser->global.logical_minimum = item_sdata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+ if (parser->global.logical_minimum < 0)
+ parser->global.logical_maximum = item_sdata(item);
+ else
+ parser->global.logical_maximum = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+ parser->global.physical_minimum = item_sdata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+ if (parser->global.physical_minimum < 0)
+ parser->global.physical_maximum = item_sdata(item);
+ else
+ parser->global.physical_maximum = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+ parser->global.unit_exponent = item_sdata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_UNIT:
+ parser->global.unit = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+ if ((parser->global.report_size = item_udata(item)) > 32) {
+ dbg("invalid report_size %d", parser->global.report_size);
+ return -1;
+ }
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+ if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
+ dbg("invalid report_count %d", parser->global.report_count);
+ return -1;
+ }
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+ if ((parser->global.report_id = item_udata(item)) == 0) {
+ dbg("report_id 0 is invalid");
+ return -1;
+ }
+ return 0;
+
+ default:
+ dbg("unknown global tag 0x%x", item->tag);
+ return -1;
+ }
+}
+
+/*
+ * Process a local item.
+ */
+
+static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
+{
+ __u32 data;
+ unsigned n;
+
+ if (item->size == 0) {
+ dbg("item data expected for local item");
+ return -1;
+ }
+
+ data = item_udata(item);
+
+ switch (item->tag) {
+
+ case HID_LOCAL_ITEM_TAG_DELIMITER:
+
+ if (data) {
+ /*
+ * We treat items before the first delimiter
+ * as global to all usage sets (branch 0).
+ * In the moment we process only these global
+ * items and the first delimiter set.
+ */
+ if (parser->local.delimiter_depth != 0) {
+ dbg("nested delimiters");
+ return -1;
+ }
+ parser->local.delimiter_depth++;
+ parser->local.delimiter_branch++;
+ } else {
+ if (parser->local.delimiter_depth < 1) {
+ dbg("bogus close delimiter");
+ return -1;
+ }
+ parser->local.delimiter_depth--;
+ }
+ return 1;
+
+ case HID_LOCAL_ITEM_TAG_USAGE:
+
+ if (parser->local.delimiter_branch > 1) {
+ dbg("alternative usage ignored");
+ return 0;
+ }
+
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
+
+ return hid_add_usage(parser, data);
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+
+ if (parser->local.delimiter_branch > 1) {
+ dbg("alternative usage ignored");
+ return 0;
+ }
+
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
+
+ parser->local.usage_minimum = data;
+ return 0;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+
+ if (parser->local.delimiter_branch > 1) {
+ dbg("alternative usage ignored");
+ return 0;
+ }
+
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
+
+ for (n = parser->local.usage_minimum; n <= data; n++)
+ if (hid_add_usage(parser, n)) {
+ dbg("hid_add_usage failed\n");
+ return -1;
+ }
+ return 0;
+
+ default:
+
+ dbg("unknown local item tag 0x%x", item->tag);
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * Process a main item.
+ */
+
+static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
+{
+ __u32 data;
+ int ret;
+
+ data = item_udata(item);
+
+ switch (item->tag) {
+ case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+ ret = open_collection(parser, data & 0xff);
+ break;
+ case HID_MAIN_ITEM_TAG_END_COLLECTION:
+ ret = close_collection(parser);
+ break;
+ case HID_MAIN_ITEM_TAG_INPUT:
+ ret = hid_add_field(parser, HID_INPUT_REPORT, data);
+ break;
+ case HID_MAIN_ITEM_TAG_OUTPUT:
+ ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
+ break;
+ case HID_MAIN_ITEM_TAG_FEATURE:
+ ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
+ break;
+ default:
+ dbg("unknown main item tag 0x%x", item->tag);
+ ret = 0;
+ }
+
+ memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */
+
+ return ret;
+}
+
+/*
+ * Process a reserved item.
+ */
+
+static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
+{
+ dbg("reserved item type, tag 0x%x", item->tag);
+ return 0;
+}
+
+/*
+ * Free a report and all registered fields. The field->usage and
+ * field->value table's are allocated behind the field, so we need
+ * only to free(field) itself.
+ */
+
+static void hid_free_report(struct hid_report *report)
+{
+ unsigned n;
+
+ for (n = 0; n < report->maxfield; n++)
+ kfree(report->field[n]);
+ kfree(report);
+}
+
+/*
+ * Free a device structure, all reports, and all fields.
+ */
+
+void hid_free_device(struct hid_device *device)
+{
+ unsigned i,j;
+
+ for (i = 0; i < HID_REPORT_TYPES; i++) {
+ struct hid_report_enum *report_enum = device->report_enum + i;
+
+ for (j = 0; j < 256; j++) {
+ struct hid_report *report = report_enum->report_id_hash[j];
+ if (report)
+ hid_free_report(report);
+ }
+ }
+
+ kfree(device->rdesc);
+ kfree(device->collection);
+ kfree(device);
+}
+EXPORT_SYMBOL_GPL(hid_free_device);
+
+/*
+ * Fetch a report description item from the data stream. We support long
+ * items, though they are not used yet.
+ */
+
+static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+{
+ u8 b;
+
+ if ((end - start) <= 0)
+ return NULL;
+
+ b = *start++;
+
+ item->type = (b >> 2) & 3;
+ item->tag = (b >> 4) & 15;
+
+ if (item->tag == HID_ITEM_TAG_LONG) {
+
+ item->format = HID_ITEM_FORMAT_LONG;
+
+ if ((end - start) < 2)
+ return NULL;
+
+ item->size = *start++;
+ item->tag = *start++;
+
+ 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;
+
+ switch (item->size) {
+
+ case 0:
+ return start;
+
+ case 1:
+ if ((end - start) < 1)
+ return NULL;
+ item->data.u8 = *start++;
+ return start;
+
+ case 2:
+ if ((end - start) < 2)
+ return NULL;
+ item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
+ start = (__u8 *)((__le16 *)start + 1);
+ return start;
+
+ case 3:
+ item->size++;
+ if ((end - start) < 4)
+ return NULL;
+ item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
+ start = (__u8 *)((__le32 *)start + 1);
+ return start;
+ }
+
+ return NULL;
+}
+
+/*
+ * Parse a report description into a hid_device structure. Reports are
+ * enumerated, fields are attached to these reports.
+ */
+
+struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+{
+ struct hid_device *device;
+ struct hid_parser *parser;
+ struct hid_item item;
+ __u8 *end;
+ unsigned i;
+ static int (*dispatch_type[])(struct hid_parser *parser,
+ struct hid_item *item) = {
+ hid_parser_main,
+ hid_parser_global,
+ hid_parser_local,
+ hid_parser_reserved
+ };
+
+ if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
+ return NULL;
+
+ if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
+ HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
+ kfree(device);
+ return NULL;
+ }
+ device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+
+ for (i = 0; i < HID_REPORT_TYPES; i++)
+ INIT_LIST_HEAD(&device->report_enum[i].report_list);
+
+ if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) {
+ kfree(device->collection);
+ kfree(device);
+ return NULL;
+ }
+ memcpy(device->rdesc, start, size);
+ device->rsize = size;
+
+ if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+ kfree(device->rdesc);
+ kfree(device->collection);
+ kfree(device);
+ return NULL;
+ }
+ parser->device = device;
+
+ end = start + size;
+ while ((start = fetch_item(start, end, &item)) != NULL) {
+
+ if (item.format != HID_ITEM_FORMAT_SHORT) {
+ dbg("unexpected long global item");
+ kfree(device->collection);
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+
+ if (dispatch_type[item.type](parser, &item)) {
+ dbg("item %u %u %u %u parsing failed\n",
+ item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
+ kfree(device->collection);
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+
+ if (start == end) {
+ if (parser->collection_stack_ptr) {
+ dbg("unbalanced collection at end of report description");
+ kfree(device->collection);
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+ if (parser->local.delimiter_depth) {
+ dbg("unbalanced delimiter at end of report description");
+ kfree(device->collection);
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+ kfree(parser);
+ return device;
+ }
+ }
+
+ dbg("item fetching failed at offset %d\n", (int)(end - start));
+ kfree(device->collection);
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(hid_parse_report);
+
+/*
+ * Convert a signed n-bit integer to signed 32-bit integer. Common
+ * cases are done through the compiler, the screwed things has to be
+ * done by hand.
+ */
+
+static s32 snto32(__u32 value, unsigned n)
+{
+ switch (n) {
+ case 8: return ((__s8)value);
+ case 16: return ((__s16)value);
+ case 32: return ((__s32)value);
+ }
+ return value & (1 << (n - 1)) ? value | (-1 << n) : value;
+}
+
+/*
+ * Convert a signed 32-bit integer to a signed n-bit integer.
+ */
+
+static u32 s32ton(__s32 value, unsigned n)
+{
+ s32 a = value >> (n - 1);
+ if (a && a != -1)
+ return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
+ return value & ((1 << n) - 1);
+}
+
+/*
+ * Extract/implement a data field from/to a little endian report (bit array).
+ *
+ * Code sort-of follows HID spec:
+ * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
+ *
+ * While the USB HID spec allows unlimited length bit fields in "report
+ * descriptors", most devices never use more than 16 bits.
+ * One model of UPS is claimed to report "LINEV" as a 32-bit field.
+ * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
+ */
+
+static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+{
+ u64 x;
+
+ WARN_ON(n > 32);
+
+ report += offset >> 3; /* adjust byte index */
+ offset &= 7; /* now only need bit offset into one byte */
+ x = get_unaligned((u64 *) report);
+ x = le64_to_cpu(x);
+ x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
+ return (u32) x;
+}
+
+/*
+ * "implement" : set bits in a little endian bit stream.
+ * Same concepts as "extract" (see comments above).
+ * The data mangled in the bit stream remains in little endian
+ * order the whole time. It make more sense to talk about
+ * endianness of register values by considering a register
+ * a "cached" copy of the little endiad bit stream.
+ */
+static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
+{
+ u64 x;
+ u64 m = (1ULL << n) - 1;
+
+ WARN_ON(n > 32);
+
+ WARN_ON(value > m);
+ value &= m;
+
+ report += offset >> 3;
+ offset &= 7;
+
+ x = get_unaligned((u64 *)report);
+ x &= cpu_to_le64(~(m << offset));
+ x |= cpu_to_le64(((u64) value) << offset);
+ put_unaligned(x, (u64 *) report);
+}
+
+/*
+ * Search an array for a value.
+ */
+
+static __inline__ int search(__s32 *array, __s32 value, unsigned n)
+{
+ while (n--) {
+ if (*array++ == value)
+ return 0;
+ }
+ return -1;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
+{
+ hid_dump_input(usage, value);
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_hid_event(hid, field, usage, value);
+ if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event)
+ hid->hiddev_hid_event(hid, field, usage, value);
+}
+
+/*
+ * Analyse a received field, and fetch the data from it. The field
+ * content is stored for next report processing (we do differential
+ * reporting to the layer).
+ */
+
+void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
+{
+ unsigned n;
+ unsigned count = field->report_count;
+ unsigned offset = field->report_offset;
+ unsigned size = field->report_size;
+ __s32 min = field->logical_minimum;
+ __s32 max = field->logical_maximum;
+ __s32 *value;
+
+ if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
+ return;
+
+ for (n = 0; n < count; n++) {
+
+ value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
+ extract(data, offset + n * size, size);
+
+ if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
+ && value[n] >= min && value[n] <= max
+ && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+ goto exit;
+ }
+
+ for (n = 0; n < count; n++) {
+
+ if (HID_MAIN_ITEM_VARIABLE & field->flags) {
+ hid_process_event(hid, field, &field->usage[n], value[n], interrupt);
+ continue;
+ }
+
+ if (field->value[n] >= min && field->value[n] <= max
+ && field->usage[field->value[n] - min].hid
+ && search(value, field->value[n], count))
+ hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
+
+ if (value[n] >= min && value[n] <= max
+ && field->usage[value[n] - min].hid
+ && search(field->value, value[n], count))
+ hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
+ }
+
+ memcpy(field->value, value, count * sizeof(__s32));
+exit:
+ kfree(value);
+}
+EXPORT_SYMBOL_GPL(hid_input_field);
+
+/*
+ * Output the field into the report.
+ */
+
+static void hid_output_field(struct hid_field *field, __u8 *data)
+{
+ unsigned count = field->report_count;
+ unsigned offset = field->report_offset;
+ unsigned size = field->report_size;
+ unsigned n;
+
+ /* make sure the unused bits in the last byte are zeros */
+ if (count > 0 && size > 0)
+ data[(count*size-1)/8] = 0;
+
+ 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 */
+ implement(data, offset + n * size, size, field->value[n]);
+ }
+}
+
+/*
+ * Create a report.
+ */
+
+void hid_output_report(struct hid_report *report, __u8 *data)
+{
+ unsigned n;
+
+ if (report->id > 0)
+ *data++ = report->id;
+
+ for (n = 0; n < report->maxfield; n++)
+ hid_output_field(report->field[n], data);
+}
+EXPORT_SYMBOL_GPL(hid_output_report);
+
+/*
+ * Set a field value. The report this field belongs to has to be
+ * created and transferred to the device, to set this value in the
+ * device.
+ */
+
+int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
+{
+ unsigned size = field->report_size;
+
+ hid_dump_input(field->usage + offset, value);
+
+ if (offset >= field->report_count) {
+ dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+ hid_dump_field(field, 8);
+ return -1;
+ }
+ if (field->logical_minimum < 0) {
+ if (value != snto32(s32ton(value, size), size)) {
+ dbg("value %d is out of range", value);
+ return -1;
+ }
+ }
+ field->value[offset] = value;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hid_set_field);
+
+int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_report *report;
+ int n, rsize;
+
+ if (!hid)
+ return -ENODEV;
+
+ if (!size) {
+ dbg("empty report");
+ return -1;
+ }
+
+#ifdef DEBUG_DATA
+ printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+#endif
+
+ n = 0; /* Normally report number is 0 */
+ if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
+ n = *data++;
+ size--;
+ }
+
+#ifdef DEBUG_DATA
+ {
+ int i;
+ printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
+ for (i = 0; i < size; i++)
+ printk(" %02x", data[i]);
+ printk("\n");
+ }
+#endif
+
+ if (!(report = report_enum->report_id_hash[n])) {
+ dbg("undefined report_id %d received", n);
+ return -1;
+ }
+
+ rsize = ((report->size - 1) >> 3) + 1;
+
+ if (size < rsize) {
+ dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+ return -1;
+ }
+
+ if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+ hid->hiddev_report_event(hid, report);
+
+ for (n = 0; n < report->maxfield; n++)
+ hid_input_field(hid, report->field[n], data, interrupt);
+
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_report_event(hid, report);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hid_input_report);
+
+MODULE_LICENSE(DRIVER_LICENSE);
+
diff --git a/drivers/usb/input/hid-input.c b/drivers/hid/hid-input.c
index 68e7ebb978a..c7a6833f682 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -2,8 +2,9 @@
* $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
+ * Copyright (c) 2006 Jiri Kosina
*
- * USB HID to Linux Input mapping
+ * HID to Linux Input mapping
*/
/*
@@ -29,11 +30,15 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
-#include <linux/usb/input.h>
#undef DEBUG
-#include "hid.h"
+#include <linux/hid.h>
+
+static int hid_pb_fnmode = 1;
+module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
+MODULE_PARM_DESC(pb_fnmode,
+ "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
#define unk KEY_UNKNOWN
@@ -67,6 +72,7 @@ static const struct {
#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
+#define map_rel_clear(c) do { map_rel(c); clear_bit(c, bit); } while (0)
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
@@ -81,42 +87,42 @@ struct hidinput_key_translation {
static struct hidinput_key_translation powerbook_fn_keys[] = {
{ KEY_BACKSPACE, KEY_DELETE },
- { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
- { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
- { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
- { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
- { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
- { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
- { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
- { KEY_UP, KEY_PAGEUP },
- { KEY_DOWN, KEY_PAGEDOWN },
- { KEY_LEFT, KEY_HOME },
- { KEY_RIGHT, KEY_END },
+ { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
+ { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
+ { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
+ { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
+ { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
+ { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
+ { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
+ { KEY_UP, KEY_PAGEUP },
+ { KEY_DOWN, KEY_PAGEDOWN },
+ { KEY_LEFT, KEY_HOME },
+ { KEY_RIGHT, KEY_END },
{ }
};
static struct hidinput_key_translation powerbook_numlock_keys[] = {
- { KEY_J, KEY_KP1 },
- { KEY_K, KEY_KP2 },
- { KEY_L, KEY_KP3 },
- { KEY_U, KEY_KP4 },
- { KEY_I, KEY_KP5 },
- { KEY_O, KEY_KP6 },
- { KEY_7, KEY_KP7 },
- { KEY_8, KEY_KP8 },
- { KEY_9, KEY_KP9 },
- { KEY_M, KEY_KP0 },
- { KEY_DOT, KEY_KPDOT },
- { KEY_SLASH, KEY_KPPLUS },
+ { KEY_J, KEY_KP1 },
+ { KEY_K, KEY_KP2 },
+ { KEY_L, KEY_KP3 },
+ { KEY_U, KEY_KP4 },
+ { KEY_I, KEY_KP5 },
+ { KEY_O, KEY_KP6 },
+ { KEY_7, KEY_KP7 },
+ { KEY_8, KEY_KP8 },
+ { KEY_9, KEY_KP9 },
+ { KEY_M, KEY_KP0 },
+ { KEY_DOT, KEY_KPDOT },
+ { KEY_SLASH, KEY_KPPLUS },
{ KEY_SEMICOLON, KEY_KPMINUS },
- { KEY_P, KEY_KPASTERISK },
- { KEY_MINUS, KEY_KPEQUAL },
- { KEY_0, KEY_KPSLASH },
- { KEY_F6, KEY_NUMLOCK },
- { KEY_KPENTER, KEY_KPENTER },
+ { KEY_P, KEY_KPASTERISK },
+ { KEY_MINUS, KEY_KPEQUAL },
+ { KEY_0, KEY_KPSLASH },
+ { KEY_F6, KEY_NUMLOCK },
+ { KEY_KPENTER, KEY_KPENTER },
{ KEY_BACKSPACE, KEY_BACKSPACE },
{ }
};
@@ -127,11 +133,6 @@ static struct hidinput_key_translation powerbook_iso_keyboard[] = {
{ }
};
-static int usbhid_pb_fnmode = 1;
-module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
- "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
{
struct hidinput_key_translation *trans;
@@ -145,7 +146,7 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra
}
static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- struct hid_usage *usage, __s32 value)
+ struct hid_usage *usage, __s32 value)
{
struct hidinput_key_translation *trans;
@@ -158,7 +159,7 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
return 1;
}
- if (usbhid_pb_fnmode) {
+ if (hid_pb_fnmode) {
int do_translate;
trans = find_translation(powerbook_fn_keys, usage->code);
@@ -167,8 +168,8 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
do_translate = 1;
else if (trans->flags & POWERBOOK_FLAG_FKEY)
do_translate =
- (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
- (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
+ (hid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
+ (hid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
else
do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
@@ -185,7 +186,7 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
}
if (test_bit(usage->code, hid->pb_pressed_numlock) ||
- test_bit(LED_NUML, input->led)) {
+ test_bit(LED_NUML, input->led)) {
trans = find_translation(powerbook_numlock_keys, usage->code);
if (trans) {
@@ -227,10 +228,11 @@ static void hidinput_pb_setup(struct input_dev *input)
for (trans = powerbook_iso_keyboard; trans->from; trans++)
set_bit(trans->to, input->keybit);
+
}
#else
static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- struct hid_usage *usage, __s32 value)
+ struct hid_usage *usage, __s32 value)
{
return 0;
}
@@ -295,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
}
- map_key(code);
+ map_key_clear(code);
break;
@@ -346,9 +348,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
if (field->flags & HID_MAIN_ITEM_RELATIVE)
- map_rel(usage->hid & 0xf);
+ map_rel_clear(usage->hid & 0xf);
else
- map_abs(usage->hid & 0xf);
+ map_abs_clear(usage->hid & 0xf);
break;
case HID_GD_HATSWITCH:
@@ -366,9 +368,22 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_LED:
- if (((usage->hid - 1) & 0xffff) >= LED_MAX)
- goto ignore;
- map_led((usage->hid - 1) & 0xffff);
+
+ switch (usage->hid & 0xffff) { /* HID-Value: */
+ case 0x01: map_led (LED_NUML); break; /* "Num Lock" */
+ case 0x02: map_led (LED_CAPSL); break; /* "Caps Lock" */
+ case 0x03: map_led (LED_SCROLLL); break; /* "Scroll Lock" */
+ case 0x04: map_led (LED_COMPOSE); break; /* "Compose" */
+ case 0x05: map_led (LED_KANA); break; /* "Kana" */
+ case 0x27: map_led (LED_SLEEP); break; /* "Stand-By" */
+ case 0x4c: map_led (LED_SUSPEND); break; /* "System Suspend" */
+ case 0x09: map_led (LED_MUTE); break; /* "Mute" */
+ case 0x4b: map_led (LED_MISC); break; /* "Generic Indicator" */
+ case 0x19: map_led (LED_MAIL); break; /* "Message Waiting" */
+ case 0x4d: map_led (LED_CHARGING); break; /* "External Power Connected" */
+
+ default: goto ignore;
+ }
break;
case HID_UP_DIGITIZER:
@@ -418,12 +433,33 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x000: goto ignore;
case 0x034: map_key_clear(KEY_SLEEP); break;
case 0x036: map_key_clear(BTN_MISC); break;
+ case 0x040: map_key_clear(KEY_MENU); break;
case 0x045: map_key_clear(KEY_RADIO); break;
+
+ case 0x083: map_key_clear(KEY_LAST); break;
+ case 0x088: map_key_clear(KEY_PC); break;
+ case 0x089: map_key_clear(KEY_TV); break;
case 0x08a: map_key_clear(KEY_WWW); break;
+ case 0x08b: map_key_clear(KEY_DVD); break;
+ case 0x08c: map_key_clear(KEY_PHONE); break;
case 0x08d: map_key_clear(KEY_PROGRAM); break;
+ case 0x08e: map_key_clear(KEY_VIDEOPHONE); break;
+ case 0x08f: map_key_clear(KEY_GAMES); break;
+ case 0x090: map_key_clear(KEY_MEMO); break;
+ case 0x091: map_key_clear(KEY_CD); break;
+ case 0x092: map_key_clear(KEY_VCR); break;
+ case 0x093: map_key_clear(KEY_TUNER); break;
+ case 0x094: map_key_clear(KEY_EXIT); break;
case 0x095: map_key_clear(KEY_HELP); break;
+ case 0x096: map_key_clear(KEY_TAPE); break;
+ case 0x097: map_key_clear(KEY_TV2); break;
+ case 0x098: map_key_clear(KEY_SAT); break;
+ case 0x09a: map_key_clear(KEY_PVR); break;
+
case 0x09c: map_key_clear(KEY_CHANNELUP); break;
case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
+ case 0x0a0: map_key_clear(KEY_VCR2); break;
+
case 0x0b0: map_key_clear(KEY_PLAY); break;
case 0x0b1: map_key_clear(KEY_PAUSE); break;
case 0x0b2: map_key_clear(KEY_RECORD); break;
@@ -433,6 +469,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
case 0x0b7: map_key_clear(KEY_STOPCD); break;
case 0x0b8: map_key_clear(KEY_EJECTCD); break;
+
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
case 0x0e2: map_key_clear(KEY_MUTE); break;
@@ -440,11 +477,30 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
case 0x183: map_key_clear(KEY_CONFIG); break;
+ case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
+ case 0x185: map_key_clear(KEY_EDITOR); break;
+ case 0x186: map_key_clear(KEY_SPREADSHEET); break;
+ case 0x187: map_key_clear(KEY_GRAPHICSEDITOR); break;
+ case 0x188: map_key_clear(KEY_PRESENTATION); break;
+ case 0x189: map_key_clear(KEY_DATABASE); break;
case 0x18a: map_key_clear(KEY_MAIL); break;
+ case 0x18b: map_key_clear(KEY_NEWS); break;
+ case 0x18c: map_key_clear(KEY_VOICEMAIL); break;
+ case 0x18d: map_key_clear(KEY_ADDRESSBOOK); break;
+ case 0x18e: map_key_clear(KEY_CALENDAR); break;
+ case 0x191: map_key_clear(KEY_FINANCE); break;
case 0x192: map_key_clear(KEY_CALC); break;
case 0x194: map_key_clear(KEY_FILE); break;
+ case 0x196: map_key_clear(KEY_WWW); break;
+ case 0x19e: map_key_clear(KEY_COFFEE); break;
+ case 0x1a6: map_key_clear(KEY_HELP); break;
case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
+ case 0x1bc: map_key_clear(KEY_MESSENGER); break;
+ case 0x1bd: map_key_clear(KEY_INFO); break;
case 0x201: map_key_clear(KEY_NEW); break;
+ case 0x202: map_key_clear(KEY_OPEN); break;
+ case 0x203: map_key_clear(KEY_CLOSE); break;
+ case 0x204: map_key_clear(KEY_EXIT); break;
case 0x207: map_key_clear(KEY_SAVE); break;
case 0x208: map_key_clear(KEY_PRINT); break;
case 0x209: map_key_clear(KEY_PROPS); break;
@@ -459,10 +515,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x226: map_key_clear(KEY_STOP); break;
case 0x227: map_key_clear(KEY_REFRESH); break;
case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
+ case 0x22d: map_key_clear(KEY_ZOOMIN); break;
+ case 0x22e: map_key_clear(KEY_ZOOMOUT); break;
+ case 0x22f: map_key_clear(KEY_ZOOMRESET); break;
case 0x233: map_key_clear(KEY_SCROLLUP); break;
case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
- case 0x238: map_rel(REL_HWHEEL); break;
+ case 0x238: map_rel_clear(REL_HWHEEL); break;
+ case 0x25f: map_key_clear(KEY_CANCEL); break;
case 0x279: map_key_clear(KEY_REDO); break;
+
case 0x289: map_key_clear(KEY_REPLY); break;
case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
case 0x28c: map_key_clear(KEY_SEND); break;
@@ -581,6 +642,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|| ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
goto ignore;
+ if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) &&
+ usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE))
+ field->flags &= ~HID_MAIN_ITEM_RELATIVE;
+
set_bit(usage->type, input->evbit);
while (usage->code <= max && test_and_set_bit(usage->code, bit))
@@ -720,8 +785,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
list_for_each_entry(hidinput, &hid->inputs, list)
input_sync(hidinput->input);
}
+EXPORT_SYMBOL_GPL(hidinput_report_event);
-static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+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;
@@ -736,41 +802,7 @@ static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsign
}
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;
- int offset;
-
- if (type == EV_FF)
- return input_ff_event(dev, type, code, value);
-
- if (type != EV_LED)
- return -1;
-
- if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
- warn("event field not found");
- return -1;
- }
-
- hid_set_field(field, offset, value);
- hid_submit_report(hid, field->report, USB_DIR_OUT);
-
- return 0;
-}
-
-static int hidinput_open(struct input_dev *dev)
-{
- struct hid_device *hid = dev->private;
- return hid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
- struct hid_device *hid = dev->private;
- hid_close(hid);
-}
+EXPORT_SYMBOL_GPL(hidinput_find_field);
/*
* Register the input device; print a message.
@@ -780,7 +812,6 @@ static void hidinput_close(struct input_dev *dev)
int hidinput_connect(struct hid_device *hid)
{
- struct usb_device *dev = hid->dev;
struct hid_report *report;
struct hid_input *hidinput = NULL;
struct input_dev *input_dev;
@@ -814,16 +845,18 @@ int hidinput_connect(struct hid_device *hid)
}
input_dev->private = hid;
- input_dev->event = hidinput_input_event;
- input_dev->open = hidinput_open;
- input_dev->close = hidinput_close;
+ input_dev->event = hid->hidinput_input_event;
+ input_dev->open = hid->hidinput_open;
+ input_dev->close = hid->hidinput_close;
input_dev->name = hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
- usb_to_input_id(dev, &input_dev->id);
- input_dev->cdev.dev = &hid->intf->dev;
-
+ input_dev->id.bustype = hid->bus;
+ input_dev->id.vendor = hid->vendor;
+ input_dev->id.product = hid->product;
+ input_dev->id.version = hid->version;
+ input_dev->cdev.dev = hid->dev;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
}
@@ -845,16 +878,12 @@ int hidinput_connect(struct hid_device *hid)
}
}
- /* 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
- * only useful in this case, and not for multi-input quirks. */
- if (hidinput) {
- hid_ff_init(hid);
+ if (hidinput)
input_register_device(hidinput->input);
- }
return 0;
}
+EXPORT_SYMBOL_GPL(hidinput_connect);
void hidinput_disconnect(struct hid_device *hid)
{
@@ -866,3 +895,5 @@ void hidinput_disconnect(struct hid_device *hid)
kfree(hidinput);
}
}
+EXPORT_SYMBOL_GPL(hidinput_disconnect);
+
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e76d91906c9..891ef6d0b1b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -106,6 +106,31 @@ config SENSORS_K8TEMP
This driver can also be built as a module. If so, the module
will be called k8temp.
+config SENSORS_AMS
+ tristate "Apple Motion Sensor driver"
+ depends on HWMON && PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
+ help
+ Support for the motion sensor included in PowerBooks. Includes
+ implementations for PMU and I2C.
+
+ This driver can also be built as a module. If so, the module
+ will be called ams.
+
+config SENSORS_AMS_PMU
+ bool "PMU variant"
+ depends on SENSORS_AMS && ADB_PMU
+ default y
+ help
+ PMU variant of motion sensor, found in late 2005 PowerBooks.
+
+config SENSORS_AMS_I2C
+ bool "I2C variant"
+ depends on SENSORS_AMS && I2C
+ default y
+ help
+ I2C variant of motion sensor, found in early 2005 PowerBooks and
+ iBooks.
+
config SENSORS_ASB100
tristate "Asus ASB100 Bach"
depends on HWMON && I2C && EXPERIMENTAL
@@ -142,11 +167,12 @@ config SENSORS_DS1621
will be called ds1621.
config SENSORS_F71805F
- tristate "Fintek F71805F/FG"
+ tristate "Fintek F71805F/FG and F71872F/FG"
depends on HWMON && EXPERIMENTAL
help
If you say yes here you get support for hardware monitoring
- features of the Fintek F71805F/FG chips.
+ features of the Fintek F71805F/FG and F71872F/FG Super-I/O
+ chips.
This driver can also be built as a module. If so, the module
will be called f71805f.
@@ -353,6 +379,19 @@ config SENSORS_PC87360
This driver can also be built as a module. If so, the module
will be called pc87360.
+config SENSORS_PC87427
+ tristate "National Semiconductor PC87427"
+ depends on HWMON && EXPERIMENTAL
+ help
+ If you say yes here you get access to the hardware monitoring
+ functions of the National Semiconductor PC87427 Super-I/O chip.
+ The chip has two distinct logical devices, one for fan speed
+ monitoring and control, and one for voltage and temperature
+ monitoring. Only fan speed monitoring is supported right now.
+
+ This driver can also be built as a module. If so, the module
+ will be called pc87427.
+
config SENSORS_SIS5595
tristate "Silicon Integrated Systems Corp. SiS5595"
depends on HWMON && I2C && PCI && EXPERIMENTAL
@@ -474,6 +513,16 @@ config SENSORS_W83792D
This driver can also be built as a module. If so, the module
will be called w83792d.
+config SENSORS_W83793
+ tristate "Winbond W83793"
+ depends on HWMON && I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Winbond W83793
+ hardware monitoring chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called w83793.
+
config SENSORS_W83L785TS
tristate "Winbond W83L785TS-S"
depends on HWMON && I2C && EXPERIMENTAL
@@ -527,6 +576,9 @@ config SENSORS_HDAPS
This driver also provides an absolute input class device, allowing
the laptop to act as a pinball machine-esque joystick.
+ If your ThinkPad is not recognized by the driver, please update to latest
+ BIOS. This is especially the case for some R52 ThinkPads.
+
Say Y here if you have an applicable laptop and want to experience
the awesome power of hdaps.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index af01cc64f7d..31661124271 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_HWMON_VID) += hwmon-vid.o
obj-$(CONFIG_SENSORS_ASB100) += asb100.o
obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
obj-$(CONFIG_SENSORS_W83792D) += w83792d.o
+obj-$(CONFIG_SENSORS_W83793) += w83793.o
obj-$(CONFIG_SENSORS_W83781D) += w83781d.o
obj-$(CONFIG_SENSORS_W83791D) += w83791d.o
@@ -18,6 +19,7 @@ obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
+obj-$(CONFIG_SENSORS_AMS) += ams/
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
@@ -41,6 +43,7 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
+obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
diff --git a/drivers/hwmon/ams/Makefile b/drivers/hwmon/ams/Makefile
new file mode 100644
index 00000000000..41c95b2089d
--- /dev/null
+++ b/drivers/hwmon/ams/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Apple Motion Sensor driver
+#
+
+ams-y := ams-core.o ams-input.o
+ams-$(CONFIG_SENSORS_AMS_PMU) += ams-pmu.o
+ams-$(CONFIG_SENSORS_AMS_I2C) += ams-i2c.o
+obj-$(CONFIG_SENSORS_AMS) += ams.o
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c
new file mode 100644
index 00000000000..f1f0f5d0442
--- /dev/null
+++ b/drivers/hwmon/ams/ams-core.c
@@ -0,0 +1,265 @@
+/*
+ * Apple Motion Sensor driver
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/pmac_pfunc.h>
+#include <asm/of_platform.h>
+
+#include "ams.h"
+
+/* There is only one motion sensor per machine */
+struct ams ams_info;
+
+static unsigned int verbose;
+module_param(verbose, bool, 0644);
+MODULE_PARM_DESC(verbose, "Show free falls and shocks in kernel output");
+
+/* Call with ams_info.lock held! */
+void ams_sensors(s8 *x, s8 *y, s8 *z)
+{
+ u32 orient = ams_info.vflag? ams_info.orient1 : ams_info.orient2;
+
+ if (orient & 0x80)
+ /* X and Y swapped */
+ ams_info.get_xyz(y, x, z);
+ else
+ ams_info.get_xyz(x, y, z);
+
+ if (orient & 0x04)
+ *z = ~(*z);
+ if (orient & 0x02)
+ *y = ~(*y);
+ if (orient & 0x01)
+ *x = ~(*x);
+}
+
+static ssize_t ams_show_current(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s8 x, y, z;
+
+ mutex_lock(&ams_info.lock);
+ ams_sensors(&x, &y, &z);
+ mutex_unlock(&ams_info.lock);
+
+ return snprintf(buf, PAGE_SIZE, "%d %d %d\n", x, y, z);
+}
+
+static DEVICE_ATTR(current, S_IRUGO, ams_show_current, NULL);
+
+static void ams_handle_irq(void *data)
+{
+ enum ams_irq irq = *((enum ams_irq *)data);
+
+ spin_lock(&ams_info.irq_lock);
+
+ ams_info.worker_irqs |= irq;
+ schedule_work(&ams_info.worker);
+
+ spin_unlock(&ams_info.irq_lock);
+}
+
+static enum ams_irq ams_freefall_irq_data = AMS_IRQ_FREEFALL;
+static struct pmf_irq_client ams_freefall_client = {
+ .owner = THIS_MODULE,
+ .handler = ams_handle_irq,
+ .data = &ams_freefall_irq_data,
+};
+
+static enum ams_irq ams_shock_irq_data = AMS_IRQ_SHOCK;
+static struct pmf_irq_client ams_shock_client = {
+ .owner = THIS_MODULE,
+ .handler = ams_handle_irq,
+ .data = &ams_shock_irq_data,
+};
+
+/* Once hard disk parking is implemented in the kernel, this function can
+ * trigger it.
+ */
+static void ams_worker(struct work_struct *work)
+{
+ mutex_lock(&ams_info.lock);
+
+ if (ams_info.has_device) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+
+ if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
+ if (verbose)
+ printk(KERN_INFO "ams: freefall detected!\n");
+
+ ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;
+
+ /* we must call this with interrupts enabled */
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+ ams_info.clear_irq(AMS_IRQ_FREEFALL);
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+ }
+
+ if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
+ if (verbose)
+ printk(KERN_INFO "ams: shock detected!\n");
+
+ ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;
+
+ /* we must call this with interrupts enabled */
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+ ams_info.clear_irq(AMS_IRQ_SHOCK);
+ spin_lock_irqsave(&ams_info.irq_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&ams_info.irq_lock, flags);
+ }
+
+ mutex_unlock(&ams_info.lock);
+}
+
+/* Call with ams_info.lock held! */
+int ams_sensor_attach(void)
+{
+ int result;
+ u32 *prop;
+
+ /* Get orientation */
+ prop = (u32*)get_property(ams_info.of_node, "orientation", NULL);
+ if (!prop)
+ return -ENODEV;
+ ams_info.orient1 = *prop;
+ ams_info.orient2 = *(prop + 1);
+
+ /* Register freefall interrupt handler */
+ result = pmf_register_irq_client(ams_info.of_node,
+ "accel-int-1",
+ &ams_freefall_client);
+ if (result < 0)
+ return -ENODEV;
+
+ /* Reset saved irqs */
+ ams_info.worker_irqs = 0;
+
+ /* Register shock interrupt handler */
+ result = pmf_register_irq_client(ams_info.of_node,
+ "accel-int-2",
+ &ams_shock_client);
+ if (result < 0)
+ goto release_freefall;
+
+ /* Create device */
+ ams_info.of_dev = of_platform_device_create(ams_info.of_node, "ams", NULL);
+ if (!ams_info.of_dev) {
+ result = -ENODEV;
+ goto release_shock;
+ }
+
+ /* Create attributes */
+ result = device_create_file(&ams_info.of_dev->dev, &dev_attr_current);
+ if (result)
+ goto release_of;
+
+ ams_info.vflag = !!(ams_info.get_vendor() & 0x10);
+
+ /* Init input device */
+ result = ams_input_init();
+ if (result)
+ goto release_device_file;
+
+ return result;
+release_device_file:
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+release_of:
+ of_device_unregister(ams_info.of_dev);
+release_shock:
+ pmf_unregister_irq_client(&ams_shock_client);
+release_freefall:
+ pmf_unregister_irq_client(&ams_freefall_client);
+ return result;
+}
+
+int __init ams_init(void)
+{
+ struct device_node *np;
+
+ spin_lock_init(&ams_info.irq_lock);
+ mutex_init(&ams_info.lock);
+ INIT_WORK(&ams_info.worker, ams_worker);
+
+#ifdef CONFIG_SENSORS_AMS_I2C
+ np = of_find_node_by_name(NULL, "accelerometer");
+ if (np && device_is_compatible(np, "AAPL,accelerometer_1"))
+ /* Found I2C motion sensor */
+ return ams_i2c_init(np);
+#endif
+
+#ifdef CONFIG_SENSORS_AMS_PMU
+ np = of_find_node_by_name(NULL, "sms");
+ if (np && device_is_compatible(np, "sms"))
+ /* Found PMU motion sensor */
+ return ams_pmu_init(np);
+#endif
+
+ printk(KERN_ERR "ams: No motion sensor found.\n");
+
+ return -ENODEV;
+}
+
+void ams_exit(void)
+{
+ mutex_lock(&ams_info.lock);
+
+ if (ams_info.has_device) {
+ /* Remove input device */
+ ams_input_exit();
+
+ /* Shut down implementation */
+ ams_info.exit();
+
+ /* Flush interrupt worker
+ *
+ * We do this after ams_info.exit(), because an interrupt might
+ * have arrived before disabling them.
+ */
+ flush_scheduled_work();
+
+ /* Remove attributes */
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
+
+ /* Remove device */
+ of_device_unregister(ams_info.of_dev);
+
+ /* Remove handler */
+ pmf_unregister_irq_client(&ams_shock_client);
+ pmf_unregister_irq_client(&ams_freefall_client);
+ }
+
+ mutex_unlock(&ams_info.lock);
+}
+
+MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
+MODULE_DESCRIPTION("Apple Motion Sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(ams_init);
+module_exit(ams_exit);
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c
new file mode 100644
index 00000000000..0d24bdfea53
--- /dev/null
+++ b/drivers/hwmon/ams/ams-i2c.c
@@ -0,0 +1,299 @@
+/*
+ * Apple Motion Sensor driver (I2C variant)
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * Clean room implementation based on the reverse engineered Mac OS X driver by
+ * Johannes Berg <johannes@sipsolutions.net>, documentation available at
+ * http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "ams.h"
+
+/* AMS registers */
+#define AMS_COMMAND 0x00 /* command register */
+#define AMS_STATUS 0x01 /* status register */
+#define AMS_CTRL1 0x02 /* read control 1 (number of values) */
+#define AMS_CTRL2 0x03 /* read control 2 (offset?) */
+#define AMS_CTRL3 0x04 /* read control 3 (size of each value?) */
+#define AMS_DATA1 0x05 /* read data 1 */
+#define AMS_DATA2 0x06 /* read data 2 */
+#define AMS_DATA3 0x07 /* read data 3 */
+#define AMS_DATA4 0x08 /* read data 4 */
+#define AMS_DATAX 0x20 /* data X */
+#define AMS_DATAY 0x21 /* data Y */
+#define AMS_DATAZ 0x22 /* data Z */
+#define AMS_FREEFALL 0x24 /* freefall int control */
+#define AMS_SHOCK 0x25 /* shock int control */
+#define AMS_SENSLOW 0x26 /* sensitivity low limit */
+#define AMS_SENSHIGH 0x27 /* sensitivity high limit */
+#define AMS_CTRLX 0x28 /* control X */
+#define AMS_CTRLY 0x29 /* control Y */
+#define AMS_CTRLZ 0x2A /* control Z */
+#define AMS_UNKNOWN1 0x2B /* unknown 1 */
+#define AMS_UNKNOWN2 0x2C /* unknown 2 */
+#define AMS_UNKNOWN3 0x2D /* unknown 3 */
+#define AMS_VENDOR 0x2E /* vendor */
+
+/* AMS commands - use with the AMS_COMMAND register */
+enum ams_i2c_cmd {
+ AMS_CMD_NOOP = 0,
+ AMS_CMD_VERSION,
+ AMS_CMD_READMEM,
+ AMS_CMD_WRITEMEM,
+ AMS_CMD_ERASEMEM,
+ AMS_CMD_READEE,
+ AMS_CMD_WRITEEE,
+ AMS_CMD_RESET,
+ AMS_CMD_START,
+};
+
+static int ams_i2c_attach(struct i2c_adapter *adapter);
+static int ams_i2c_detach(struct i2c_adapter *adapter);
+
+static struct i2c_driver ams_i2c_driver = {
+ .driver = {
+ .name = "ams",
+ .owner = THIS_MODULE,
+ },
+ .attach_adapter = ams_i2c_attach,
+ .detach_adapter = ams_i2c_detach,
+};
+
+static s32 ams_i2c_read(u8 reg)
+{
+ return i2c_smbus_read_byte_data(&ams_info.i2c_client, reg);
+}
+
+static int ams_i2c_write(u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(&ams_info.i2c_client, reg, value);
+}
+
+static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
+{
+ s32 result;
+ int remaining = HZ / 20;
+
+ ams_i2c_write(AMS_COMMAND, cmd);
+ mdelay(5);
+
+ while (remaining) {
+ result = ams_i2c_read(AMS_COMMAND);
+ if (result == 0 || result & 0x80)
+ return 0;
+
+ remaining = schedule_timeout(remaining);
+ }
+
+ return -1;
+}
+
+static void ams_i2c_set_irq(enum ams_irq reg, char enable)
+{
+ if (reg & AMS_IRQ_FREEFALL) {
+ u8 val = ams_i2c_read(AMS_CTRLX);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_i2c_write(AMS_CTRLX, val);
+ }
+
+ if (reg & AMS_IRQ_SHOCK) {
+ u8 val = ams_i2c_read(AMS_CTRLY);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_i2c_write(AMS_CTRLY, val);
+ }
+
+ if (reg & AMS_IRQ_GLOBAL) {
+ u8 val = ams_i2c_read(AMS_CTRLZ);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_i2c_write(AMS_CTRLZ, val);
+ }
+}
+
+static void ams_i2c_clear_irq(enum ams_irq reg)
+{
+ if (reg & AMS_IRQ_FREEFALL)
+ ams_i2c_write(AMS_FREEFALL, 0);
+
+ if (reg & AMS_IRQ_SHOCK)
+ ams_i2c_write(AMS_SHOCK, 0);
+}
+
+static u8 ams_i2c_get_vendor(void)
+{
+ return ams_i2c_read(AMS_VENDOR);
+}
+
+static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
+{
+ *x = ams_i2c_read(AMS_DATAX);
+ *y = ams_i2c_read(AMS_DATAY);
+ *z = ams_i2c_read(AMS_DATAZ);
+}
+
+static int ams_i2c_attach(struct i2c_adapter *adapter)
+{
+ unsigned long bus;
+ int vmaj, vmin;
+ int result;
+
+ /* There can be only one */
+ if (unlikely(ams_info.has_device))
+ return -ENODEV;
+
+ if (strncmp(adapter->name, "uni-n", 5))
+ return -ENODEV;
+
+ bus = simple_strtoul(adapter->name + 6, NULL, 10);
+ if (bus != ams_info.i2c_bus)
+ return -ENODEV;
+
+ ams_info.i2c_client.addr = ams_info.i2c_address;
+ ams_info.i2c_client.adapter = adapter;
+ ams_info.i2c_client.driver = &ams_i2c_driver;
+ strcpy(ams_info.i2c_client.name, "Apple Motion Sensor");
+
+ if (ams_i2c_cmd(AMS_CMD_RESET)) {
+ printk(KERN_INFO "ams: Failed to reset the device\n");
+ return -ENODEV;
+ }
+
+ if (ams_i2c_cmd(AMS_CMD_START)) {
+ printk(KERN_INFO "ams: Failed to start the device\n");
+ return -ENODEV;
+ }
+
+ /* get version/vendor information */
+ ams_i2c_write(AMS_CTRL1, 0x02);
+ ams_i2c_write(AMS_CTRL2, 0x85);
+ ams_i2c_write(AMS_CTRL3, 0x01);
+
+ ams_i2c_cmd(AMS_CMD_READMEM);
+
+ vmaj = ams_i2c_read(AMS_DATA1);
+ vmin = ams_i2c_read(AMS_DATA2);
+ if (vmaj != 1 || vmin != 52) {
+ printk(KERN_INFO "ams: Incorrect device version (%d.%d)\n",
+ vmaj, vmin);
+ return -ENODEV;
+ }
+
+ ams_i2c_cmd(AMS_CMD_VERSION);
+
+ vmaj = ams_i2c_read(AMS_DATA1);
+ vmin = ams_i2c_read(AMS_DATA2);
+ if (vmaj != 0 || vmin != 1) {
+ printk(KERN_INFO "ams: Incorrect firmware version (%d.%d)\n",
+ vmaj, vmin);
+ return -ENODEV;
+ }
+
+ /* Disable interrupts */
+ ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+
+ result = ams_sensor_attach();
+ if (result < 0)
+ return result;
+
+ /* Set default values */
+ ams_i2c_write(AMS_SENSLOW, 0x15);
+ ams_i2c_write(AMS_SENSHIGH, 0x60);
+ ams_i2c_write(AMS_CTRLX, 0x08);
+ ams_i2c_write(AMS_CTRLY, 0x0F);
+ ams_i2c_write(AMS_CTRLZ, 0x4F);
+ ams_i2c_write(AMS_UNKNOWN1, 0x14);
+
+ /* Clear interrupts */
+ ams_i2c_clear_irq(AMS_IRQ_ALL);
+
+ ams_info.has_device = 1;
+
+ /* Enable interrupts */
+ ams_i2c_set_irq(AMS_IRQ_ALL, 1);
+
+ printk(KERN_INFO "ams: Found I2C based motion sensor\n");
+
+ return 0;
+}
+
+static int ams_i2c_detach(struct i2c_adapter *adapter)
+{
+ if (ams_info.has_device) {
+ /* Disable interrupts */
+ ams_i2c_set_irq(AMS_IRQ_ALL, 0);
+
+ /* Clear interrupts */
+ ams_i2c_clear_irq(AMS_IRQ_ALL);
+
+ printk(KERN_INFO "ams: Unloading\n");
+
+ ams_info.has_device = 0;
+ }
+
+ return 0;
+}
+
+static void ams_i2c_exit(void)
+{
+ i2c_del_driver(&ams_i2c_driver);
+}
+
+int __init ams_i2c_init(struct device_node *np)
+{
+ char *tmp_bus;
+ int result;
+ u32 *prop;
+
+ mutex_lock(&ams_info.lock);
+
+ /* Set implementation stuff */
+ ams_info.of_node = np;
+ ams_info.exit = ams_i2c_exit;
+ ams_info.get_vendor = ams_i2c_get_vendor;
+ ams_info.get_xyz = ams_i2c_get_xyz;
+ ams_info.clear_irq = ams_i2c_clear_irq;
+ ams_info.bustype = BUS_I2C;
+
+ /* look for bus either using "reg" or by path */
+ prop = (u32*)get_property(ams_info.of_node, "reg", NULL);
+ if (!prop) {
+ result = -ENODEV;
+
+ goto exit;
+ }
+
+ tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@");
+ if (tmp_bus)
+ ams_info.i2c_bus = *(tmp_bus + 9) - '0';
+ else
+ ams_info.i2c_bus = ((*prop) >> 8) & 0x0f;
+ ams_info.i2c_address = ((*prop) & 0xff) >> 1;
+
+ result = i2c_add_driver(&ams_i2c_driver);
+
+exit:
+ mutex_unlock(&ams_info.lock);
+
+ return result;
+}
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
new file mode 100644
index 00000000000..f126aa48513
--- /dev/null
+++ b/drivers/hwmon/ams/ams-input.c
@@ -0,0 +1,160 @@
+/*
+ * Apple Motion Sensor driver (joystick emulation)
+ *
+ * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.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.
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "ams.h"
+
+static unsigned int joystick;
+module_param(joystick, bool, 0644);
+MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
+
+static unsigned int invert;
+module_param(invert, bool, 0644);
+MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
+
+static int ams_input_kthread(void *data)
+{
+ s8 x, y, z;
+
+ while (!kthread_should_stop()) {
+ mutex_lock(&ams_info.lock);
+
+ ams_sensors(&x, &y, &z);
+
+ x -= ams_info.xcalib;
+ y -= ams_info.ycalib;
+ z -= ams_info.zcalib;
+
+ input_report_abs(ams_info.idev, ABS_X, invert ? -x : x);
+ input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y);
+ input_report_abs(ams_info.idev, ABS_Z, z);
+
+ input_sync(ams_info.idev);
+
+ mutex_unlock(&ams_info.lock);
+
+ msleep(25);
+ }
+
+ return 0;
+}
+
+static int ams_input_open(struct input_dev *dev)
+{
+ ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams");
+ return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0;
+}
+
+static void ams_input_close(struct input_dev *dev)
+{
+ kthread_stop(ams_info.kthread);
+}
+
+/* Call with ams_info.lock held! */
+static void ams_input_enable(void)
+{
+ s8 x, y, z;
+
+ if (ams_info.idev)
+ return;
+
+ ams_sensors(&x, &y, &z);
+ ams_info.xcalib = x;
+ ams_info.ycalib = y;
+ ams_info.zcalib = z;
+
+ ams_info.idev = input_allocate_device();
+ if (!ams_info.idev)
+ return;
+
+ ams_info.idev->name = "Apple Motion Sensor";
+ ams_info.idev->id.bustype = ams_info.bustype;
+ ams_info.idev->id.vendor = 0;
+ ams_info.idev->open = ams_input_open;
+ ams_info.idev->close = ams_input_close;
+ ams_info.idev->cdev.dev = &ams_info.of_dev->dev;
+
+ input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
+ input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
+ input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0);
+
+ set_bit(EV_ABS, ams_info.idev->evbit);
+ set_bit(EV_KEY, ams_info.idev->evbit);
+ set_bit(BTN_TOUCH, ams_info.idev->keybit);
+
+ if (input_register_device(ams_info.idev)) {
+ input_free_device(ams_info.idev);
+ ams_info.idev = NULL;
+ return;
+ }
+}
+
+/* Call with ams_info.lock held! */
+static void ams_input_disable(void)
+{
+ if (ams_info.idev) {
+ input_unregister_device(ams_info.idev);
+ ams_info.idev = NULL;
+ }
+}
+
+static ssize_t ams_input_show_joystick(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", joystick);
+}
+
+static ssize_t ams_input_store_joystick(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ if (sscanf(buf, "%d\n", &joystick) != 1)
+ return -EINVAL;
+
+ mutex_lock(&ams_info.lock);
+
+ if (joystick)
+ ams_input_enable();
+ else
+ ams_input_disable();
+
+ mutex_unlock(&ams_info.lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(joystick, S_IRUGO | S_IWUSR,
+ ams_input_show_joystick, ams_input_store_joystick);
+
+/* Call with ams_info.lock held! */
+int ams_input_init(void)
+{
+ int result;
+
+ result = device_create_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+
+ if (!result && joystick)
+ ams_input_enable();
+ return result;
+}
+
+/* Call with ams_info.lock held! */
+void ams_input_exit()
+{
+ ams_input_disable();
+ device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
+}
diff --git a/drivers/hwmon/ams/ams-pmu.c b/drivers/hwmon/ams/ams-pmu.c
new file mode 100644
index 00000000000..4636ae031a5
--- /dev/null
+++ b/drivers/hwmon/ams/ams-pmu.c
@@ -0,0 +1,207 @@
+/*
+ * Apple Motion Sensor driver (PMU variant)
+ *
+ * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.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.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+#include "ams.h"
+
+/* Attitude */
+#define AMS_X 0x00
+#define AMS_Y 0x01
+#define AMS_Z 0x02
+
+/* Not exactly known, maybe chip vendor */
+#define AMS_VENDOR 0x03
+
+/* Freefall registers */
+#define AMS_FF_CLEAR 0x04
+#define AMS_FF_ENABLE 0x05
+#define AMS_FF_LOW_LIMIT 0x06
+#define AMS_FF_DEBOUNCE 0x07
+
+/* Shock registers */
+#define AMS_SHOCK_CLEAR 0x08
+#define AMS_SHOCK_ENABLE 0x09
+#define AMS_SHOCK_HIGH_LIMIT 0x0a
+#define AMS_SHOCK_DEBOUNCE 0x0b
+
+/* Global interrupt and power control register */
+#define AMS_CONTROL 0x0c
+
+static u8 ams_pmu_cmd;
+
+static void ams_pmu_req_complete(struct adb_request *req)
+{
+ complete((struct completion *)req->arg);
+}
+
+/* Only call this function from task context */
+static void ams_pmu_set_register(u8 reg, u8 value)
+{
+ static struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+
+ req.arg = &req_complete;
+ if (pmu_request(&req, ams_pmu_req_complete, 4, ams_pmu_cmd, 0x00, reg, value))
+ return;
+
+ wait_for_completion(&req_complete);
+}
+
+/* Only call this function from task context */
+static u8 ams_pmu_get_register(u8 reg)
+{
+ static struct adb_request req;
+ DECLARE_COMPLETION(req_complete);
+
+ req.arg = &req_complete;
+ if (pmu_request(&req, ams_pmu_req_complete, 3, ams_pmu_cmd, 0x01, reg))
+ return 0;
+
+ wait_for_completion(&req_complete);
+
+ if (req.reply_len > 0)
+ return req.reply[0];
+ else
+ return 0;
+}
+
+/* Enables or disables the specified interrupts */
+static void ams_pmu_set_irq(enum ams_irq reg, char enable)
+{
+ if (reg & AMS_IRQ_FREEFALL) {
+ u8 val = ams_pmu_get_register(AMS_FF_ENABLE);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_pmu_set_register(AMS_FF_ENABLE, val);
+ }
+
+ if (reg & AMS_IRQ_SHOCK) {
+ u8 val = ams_pmu_get_register(AMS_SHOCK_ENABLE);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_pmu_set_register(AMS_SHOCK_ENABLE, val);
+ }
+
+ if (reg & AMS_IRQ_GLOBAL) {
+ u8 val = ams_pmu_get_register(AMS_CONTROL);
+ if (enable)
+ val |= 0x80;
+ else
+ val &= ~0x80;
+ ams_pmu_set_register(AMS_CONTROL, val);
+ }
+}
+
+static void ams_pmu_clear_irq(enum ams_irq reg)
+{
+ if (reg & AMS_IRQ_FREEFALL)
+ ams_pmu_set_register(AMS_FF_CLEAR, 0x00);
+
+ if (reg & AMS_IRQ_SHOCK)
+ ams_pmu_set_register(AMS_SHOCK_CLEAR, 0x00);
+}
+
+static u8 ams_pmu_get_vendor(void)
+{
+ return ams_pmu_get_register(AMS_VENDOR);
+}
+
+static void ams_pmu_get_xyz(s8 *x, s8 *y, s8 *z)
+{
+ *x = ams_pmu_get_register(AMS_X);
+ *y = ams_pmu_get_register(AMS_Y);
+ *z = ams_pmu_get_register(AMS_Z);
+}
+
+static void ams_pmu_exit(void)
+{
+ /* Disable interrupts */
+ ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+
+ /* Clear interrupts */
+ ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+ ams_info.has_device = 0;
+
+ printk(KERN_INFO "ams: Unloading\n");
+}
+
+int __init ams_pmu_init(struct device_node *np)
+{
+ u32 *prop;
+ int result;
+
+ mutex_lock(&ams_info.lock);
+
+ /* Set implementation stuff */
+ ams_info.of_node = np;
+ ams_info.exit = ams_pmu_exit;
+ ams_info.get_vendor = ams_pmu_get_vendor;
+ ams_info.get_xyz = ams_pmu_get_xyz;
+ ams_info.clear_irq = ams_pmu_clear_irq;
+ ams_info.bustype = BUS_HOST;
+
+ /* Get PMU command, should be 0x4e, but we can never know */
+ prop = (u32*)get_property(ams_info.of_node, "reg", NULL);
+ if (!prop) {
+ result = -ENODEV;
+ goto exit;
+ }
+ ams_pmu_cmd = ((*prop) >> 8) & 0xff;
+
+ /* Disable interrupts */
+ ams_pmu_set_irq(AMS_IRQ_ALL, 0);
+
+ /* Clear interrupts */
+ ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+ result = ams_sensor_attach();
+ if (result < 0)
+ goto exit;
+
+ /* Set default values */
+ ams_pmu_set_register(AMS_FF_LOW_LIMIT, 0x15);
+ ams_pmu_set_register(AMS_FF_ENABLE, 0x08);
+ ams_pmu_set_register(AMS_FF_DEBOUNCE, 0x14);
+
+ ams_pmu_set_register(AMS_SHOCK_HIGH_LIMIT, 0x60);
+ ams_pmu_set_register(AMS_SHOCK_ENABLE, 0x0f);
+ ams_pmu_set_register(AMS_SHOCK_DEBOUNCE, 0x14);
+
+ ams_pmu_set_register(AMS_CONTROL, 0x4f);
+
+ /* Clear interrupts */
+ ams_pmu_clear_irq(AMS_IRQ_ALL);
+
+ ams_info.has_device = 1;
+
+ /* Enable interrupts */
+ ams_pmu_set_irq(AMS_IRQ_ALL, 1);
+
+ printk(KERN_INFO "ams: Found PMU based motion sensor\n");
+
+ result = 0;
+
+exit:
+ mutex_unlock(&ams_info.lock);
+
+ return result;
+}
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
new file mode 100644
index 00000000000..240730e6bcd
--- /dev/null
+++ b/drivers/hwmon/ams/ams.h
@@ -0,0 +1,72 @@
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/of_device.h>
+
+enum ams_irq {
+ AMS_IRQ_FREEFALL = 0x01,
+ AMS_IRQ_SHOCK = 0x02,
+ AMS_IRQ_GLOBAL = 0x04,
+ AMS_IRQ_ALL =
+ AMS_IRQ_FREEFALL |
+ AMS_IRQ_SHOCK |
+ AMS_IRQ_GLOBAL,
+};
+
+struct ams {
+ /* Locks */
+ spinlock_t irq_lock;
+ struct mutex lock;
+
+ /* General properties */
+ struct device_node *of_node;
+ struct of_device *of_dev;
+ char has_device;
+ char vflag;
+ u32 orient1;
+ u32 orient2;
+
+ /* Interrupt worker */
+ struct work_struct worker;
+ u8 worker_irqs;
+
+ /* Implementation
+ *
+ * Only call these functions with the main lock held.
+ */
+ void (*exit)(void);
+
+ void (*get_xyz)(s8 *x, s8 *y, s8 *z);
+ u8 (*get_vendor)(void);
+
+ void (*clear_irq)(enum ams_irq reg);
+
+#ifdef CONFIG_SENSORS_AMS_I2C
+ /* I2C properties */
+ int i2c_bus;
+ int i2c_address;
+ struct i2c_client i2c_client;
+#endif
+
+ /* Joystick emulation */
+ struct task_struct *kthread;
+ struct input_dev *idev;
+ __u16 bustype;
+
+ /* calibrated null values */
+ int xcalib, ycalib, zcalib;
+};
+
+extern struct ams ams_info;
+
+extern void ams_sensors(s8 *x, s8 *y, s8 *z);
+extern int ams_sensor_attach(void);
+
+extern int ams_pmu_init(struct device_node *np);
+extern int ams_i2c_init(struct device_node *np);
+
+extern int ams_input_init(void);
+extern void ams_input_exit(void);
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index de17a72149d..a272cae8f60 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1,12 +1,15 @@
/*
- * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
- * hardware monitoring features
+ * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O
+ * chips integrated hardware monitoring features
* Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org>
*
* The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
* complete hardware monitoring features: voltage, fan and temperature
* sensors, and manual and automatic fan speed control.
*
+ * The F71872F/FG is almost the same, with two more voltages monitored,
+ * and 6 VID inputs.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -37,6 +40,7 @@
static struct platform_device *pdev;
#define DRVNAME "f71805f"
+enum kinds { f71805f, f71872f };
/*
* Super-I/O constants and functions
@@ -48,11 +52,13 @@ static struct platform_device *pdev;
#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
#define SIO_REG_DEVREV 0x22 /* Device revision */
#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
+#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */
#define SIO_REG_ENABLE 0x30 /* Logical device enable */
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
#define SIO_FINTEK_ID 0x1934
#define SIO_F71805F_ID 0x0406
+#define SIO_F71872F_ID 0x0341
static inline int
superio_inb(int base, int reg)
@@ -96,22 +102,25 @@ superio_exit(int base)
* ISA constants
*/
-#define REGION_LENGTH 2
-#define ADDR_REG_OFFSET 0
-#define DATA_REG_OFFSET 1
+#define REGION_LENGTH 8
+#define ADDR_REG_OFFSET 5
+#define DATA_REG_OFFSET 6
/*
* Registers
*/
-/* in nr from 0 to 8 (8-bit values) */
+/* in nr from 0 to 10 (8-bit values) */
#define F71805F_REG_IN(nr) (0x10 + (nr))
-#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
-#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
+#define F71805F_REG_IN_HIGH(nr) ((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E)
+#define F71805F_REG_IN_LOW(nr) ((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F)
/* fan nr from 0 to 2 (12-bit values, two registers) */
#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
+#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr))
#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
+#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr))
+#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr))
/* temp nr from 0 to 2 (8-bit values) */
#define F71805F_REG_TEMP(nr) (0x1B + (nr))
#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
@@ -122,6 +131,14 @@ superio_exit(int base)
/* status nr from 0 to 2 */
#define F71805F_REG_STATUS(nr) (0x36 + (nr))
+/* individual register bits */
+#define FAN_CTRL_DC_MODE 0x10
+#define FAN_CTRL_LATCH_FULL 0x08
+#define FAN_CTRL_MODE_MASK 0x03
+#define FAN_CTRL_MODE_SPEED 0x00
+#define FAN_CTRL_MODE_TEMPERATURE 0x01
+#define FAN_CTRL_MODE_MANUAL 0x02
+
/*
* Data structures and manipulation thereof
*/
@@ -138,12 +155,16 @@ struct f71805f_data {
unsigned long last_limits; /* In jiffies */
/* Register values */
- u8 in[9];
- u8 in_high[9];
- u8 in_low[9];
+ u8 in[11];
+ u8 in_high[11];
+ u8 in_low[11];
+ u16 has_in;
u16 fan[3];
u16 fan_low[3];
- u8 fan_enabled; /* Read once at init time */
+ u16 fan_target[3];
+ u8 fan_ctrl[3];
+ u8 pwm[3];
+ u8 pwm_freq[3];
u8 temp[3];
u8 temp_high[3];
u8 temp_hyst[3];
@@ -151,6 +172,11 @@ struct f71805f_data {
unsigned long alarms;
};
+struct f71805f_sio_data {
+ enum kinds kind;
+ u8 fnsel1;
+};
+
static inline long in_from_reg(u8 reg)
{
return (reg * 8);
@@ -200,6 +226,33 @@ static inline u16 fan_to_reg(long rpm)
return (1500000 / rpm);
}
+static inline unsigned long pwm_freq_from_reg(u8 reg)
+{
+ unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL;
+
+ reg &= 0x7f;
+ if (reg == 0)
+ reg++;
+ return clock / (reg << 8);
+}
+
+static inline u8 pwm_freq_to_reg(unsigned long val)
+{
+ if (val >= 187500) /* The highest we can do */
+ return 0x80;
+ if (val >= 1475) /* Use 48 MHz clock */
+ return 0x80 | (48000000UL / (val << 8));
+ if (val < 31) /* The lowest we can do */
+ return 0x7f;
+ else /* Use 1 MHz clock */
+ return 1000000UL / (val << 8);
+}
+
+static inline int pwm_mode_from_reg(u8 reg)
+{
+ return !(reg & FAN_CTRL_DC_MODE);
+}
+
static inline long temp_from_reg(u8 reg)
{
return (reg * 1000);
@@ -274,16 +327,21 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
/* Limit registers cache is refreshed after 60 seconds */
if (time_after(jiffies, data->last_updated + 60 * HZ)
|| !data->valid) {
- for (nr = 0; nr < 9; nr++) {
+ for (nr = 0; nr < 11; nr++) {
+ if (!(data->has_in & (1 << nr)))
+ continue;
data->in_high[nr] = f71805f_read8(data,
F71805F_REG_IN_HIGH(nr));
data->in_low[nr] = f71805f_read8(data,
F71805F_REG_IN_LOW(nr));
}
for (nr = 0; nr < 3; nr++) {
- if (data->fan_enabled & (1 << nr))
- data->fan_low[nr] = f71805f_read16(data,
- F71805F_REG_FAN_LOW(nr));
+ data->fan_low[nr] = f71805f_read16(data,
+ F71805F_REG_FAN_LOW(nr));
+ data->fan_target[nr] = f71805f_read16(data,
+ F71805F_REG_FAN_TARGET(nr));
+ data->pwm_freq[nr] = f71805f_read8(data,
+ F71805F_REG_PWM_FREQ(nr));
}
for (nr = 0; nr < 3; nr++) {
data->temp_high[nr] = f71805f_read8(data,
@@ -299,14 +357,19 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
/* Measurement registers cache is refreshed after 1 second */
if (time_after(jiffies, data->last_updated + HZ)
|| !data->valid) {
- for (nr = 0; nr < 9; nr++) {
+ for (nr = 0; nr < 11; nr++) {
+ if (!(data->has_in & (1 << nr)))
+ continue;
data->in[nr] = f71805f_read8(data,
F71805F_REG_IN(nr));
}
for (nr = 0; nr < 3; nr++) {
- if (data->fan_enabled & (1 << nr))
- data->fan[nr] = f71805f_read16(data,
- F71805F_REG_FAN(nr));
+ data->fan[nr] = f71805f_read16(data,
+ F71805F_REG_FAN(nr));
+ data->fan_ctrl[nr] = f71805f_read8(data,
+ F71805F_REG_FAN_CTRL(nr));
+ data->pwm[nr] = f71805f_read8(data,
+ F71805F_REG_PWM_DUTY(nr));
}
for (nr = 0; nr < 3; nr++) {
data->temp[nr] = f71805f_read8(data,
@@ -333,35 +396,43 @@ static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
- return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr]));
}
static ssize_t show_in0_max(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
- return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr]));
}
static ssize_t show_in0_min(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
- return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
+ return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr]));
}
static ssize_t set_in0_max(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock);
- data->in_high[0] = in0_to_reg(val);
- f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
+ data->in_high[nr] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -371,11 +442,13 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
mutex_lock(&data->update_lock);
- data->in_low[0] = in0_to_reg(val);
- f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
+ data->in_low[nr] = in0_to_reg(val);
+ f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -463,6 +536,16 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute
return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
}
+static ssize_t show_fan_target(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
+}
+
static ssize_t set_fan_min(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
@@ -479,6 +562,157 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
return count;
}
+static ssize_t set_fan_target(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->fan_target[nr] = fan_to_reg(val);
+ f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
+ data->fan_target[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", (int)data->pwm[nr]);
+}
+
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ int mode;
+
+ switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) {
+ case FAN_CTRL_MODE_SPEED:
+ mode = 3;
+ break;
+ case FAN_CTRL_MODE_TEMPERATURE:
+ mode = 2;
+ break;
+ default: /* MANUAL */
+ mode = 1;
+ }
+
+ return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t show_pwm_freq(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr]));
+}
+
+static ssize_t show_pwm_mode(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct f71805f_data *data = f71805f_update_device(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr]));
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ if (val > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->pwm[nr] = val;
+ f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static struct attribute *f71805f_attr_pwm[];
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ u8 reg;
+
+ if (val < 1 || val > 3)
+ return -EINVAL;
+
+ if (val > 1) { /* Automatic mode, user can't set PWM value */
+ if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
+ S_IRUGO))
+ dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1);
+ }
+
+ mutex_lock(&data->update_lock);
+ reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr))
+ & ~FAN_CTRL_MODE_MASK;
+ switch (val) {
+ case 1:
+ reg |= FAN_CTRL_MODE_MANUAL;
+ break;
+ case 2:
+ reg |= FAN_CTRL_MODE_TEMPERATURE;
+ break;
+ case 3:
+ reg |= FAN_CTRL_MODE_SPEED;
+ break;
+ }
+ data->fan_ctrl[nr] = reg;
+ f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg);
+ mutex_unlock(&data->update_lock);
+
+ if (val == 1) { /* Manual mode, user can set PWM value */
+ if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr],
+ S_IRUGO | S_IWUSR))
+ dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1);
+ }
+
+ return count;
+}
+
+static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71805f_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_freq[nr] = pwm_freq_to_reg(val);
+ f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
char *buf)
{
@@ -557,7 +791,7 @@ static ssize_t show_alarms_in(struct device *dev, struct device_attribute
{
struct f71805f_data *data = f71805f_update_device(dev);
- return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
+ return sprintf(buf, "%lu\n", data->alarms & 0x7ff);
}
static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
@@ -594,9 +828,11 @@ static ssize_t show_name(struct device *dev, struct device_attribute
return sprintf(buf, "%s\n", data->name);
}
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
-static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
-static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
+static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR,
+ show_in0_max, set_in0_max, 0);
+static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR,
+ show_in0_min, set_in0_min, 0);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 1);
@@ -637,16 +873,32 @@ static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
show_in_max, set_in_max, 8);
static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
show_in_min, set_in_min, 8);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9);
+static SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR,
+ show_in0_max, set_in0_max, 9);
+static SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR,
+ show_in0_min, set_in0_min, 9);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10);
+static SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR,
+ show_in0_max, set_in0_max, 10);
+static SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR,
+ show_in0_min, set_in0_min, 10);
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
+ show_fan_target, set_fan_target, 0);
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
+ show_fan_target, set_fan_target, 1);
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
show_fan_min, set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
+ show_fan_target, set_fan_target, 2);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
@@ -667,6 +919,27 @@ static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst, 2);
static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
+/* pwm (value) files are created read-only, write permission is
+ then added or removed dynamically as needed */
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+ show_pwm_enable, set_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR,
+ show_pwm_freq, set_pwm_freq, 0);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
+ show_pwm_enable, set_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR,
+ show_pwm_freq, set_pwm_freq, 1);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
+ show_pwm_enable, set_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
+ show_pwm_freq, set_pwm_freq, 2);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
+
static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
@@ -676,6 +949,8 @@ static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
@@ -689,9 +964,9 @@ static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static struct attribute *f71805f_attributes[] = {
- &dev_attr_in0_input.attr,
- &dev_attr_in0_max.attr,
- &dev_attr_in0_min.attr,
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in0_max.dev_attr.attr,
+ &sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
@@ -701,9 +976,6 @@ static struct attribute *f71805f_attributes[] = {
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in3_max.dev_attr.attr,
&sensor_dev_attr_in3_min.dev_attr.attr,
- &sensor_dev_attr_in4_input.dev_attr.attr,
- &sensor_dev_attr_in4_max.dev_attr.attr,
- &sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in5_max.dev_attr.attr,
&sensor_dev_attr_in5_min.dev_attr.attr,
@@ -713,9 +985,29 @@ static struct attribute *f71805f_attributes[] = {
&sensor_dev_attr_in7_input.dev_attr.attr,
&sensor_dev_attr_in7_max.dev_attr.attr,
&sensor_dev_attr_in7_min.dev_attr.attr,
- &sensor_dev_attr_in8_input.dev_attr.attr,
- &sensor_dev_attr_in8_max.dev_attr.attr,
- &sensor_dev_attr_in8_min.dev_attr.attr,
+
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan1_target.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_target.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_target.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_mode.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -734,11 +1026,9 @@ static struct attribute *f71805f_attributes[] = {
&sensor_dev_attr_in1_alarm.dev_attr.attr,
&sensor_dev_attr_in2_alarm.dev_attr.attr,
&sensor_dev_attr_in3_alarm.dev_attr.attr,
- &sensor_dev_attr_in4_alarm.dev_attr.attr,
&sensor_dev_attr_in5_alarm.dev_attr.attr,
&sensor_dev_attr_in6_alarm.dev_attr.attr,
&sensor_dev_attr_in7_alarm.dev_attr.attr,
- &sensor_dev_attr_in8_alarm.dev_attr.attr,
&dev_attr_alarms_in.attr,
&sensor_dev_attr_temp1_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_alarm.dev_attr.attr,
@@ -754,29 +1044,59 @@ static const struct attribute_group f71805f_group = {
.attrs = f71805f_attributes,
};
-static struct attribute *f71805f_attributes_fan[3][4] = {
+static struct attribute *f71805f_attributes_optin[4][5] = {
{
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &sensor_dev_attr_fan1_min.dev_attr.attr,
- &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in4_max.dev_attr.attr,
+ &sensor_dev_attr_in4_min.dev_attr.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ &sensor_dev_attr_in8_max.dev_attr.attr,
+ &sensor_dev_attr_in8_min.dev_attr.attr,
+ &sensor_dev_attr_in8_alarm.dev_attr.attr,
NULL
}, {
- &sensor_dev_attr_fan2_input.dev_attr.attr,
- &sensor_dev_attr_fan2_min.dev_attr.attr,
- &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_in9_input.dev_attr.attr,
+ &sensor_dev_attr_in9_max.dev_attr.attr,
+ &sensor_dev_attr_in9_min.dev_attr.attr,
+ &sensor_dev_attr_in9_alarm.dev_attr.attr,
NULL
}, {
- &sensor_dev_attr_fan3_input.dev_attr.attr,
- &sensor_dev_attr_fan3_min.dev_attr.attr,
- &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_in10_input.dev_attr.attr,
+ &sensor_dev_attr_in10_max.dev_attr.attr,
+ &sensor_dev_attr_in10_min.dev_attr.attr,
+ &sensor_dev_attr_in10_alarm.dev_attr.attr,
NULL
}
};
-static const struct attribute_group f71805f_group_fan[3] = {
- { .attrs = f71805f_attributes_fan[0] },
- { .attrs = f71805f_attributes_fan[1] },
- { .attrs = f71805f_attributes_fan[2] },
+static const struct attribute_group f71805f_group_optin[4] = {
+ { .attrs = f71805f_attributes_optin[0] },
+ { .attrs = f71805f_attributes_optin[1] },
+ { .attrs = f71805f_attributes_optin[2] },
+ { .attrs = f71805f_attributes_optin[3] },
+};
+
+/* We don't include pwm_freq files in the arrays above, because they must be
+ created conditionally (only if pwm_mode is 1 == PWM) */
+static struct attribute *f71805f_attributes_pwm_freq[] = {
+ &sensor_dev_attr_pwm1_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm2_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm3_freq.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group f71805f_group_pwm_freq = {
+ .attrs = f71805f_attributes_pwm_freq,
+};
+
+/* We also need an indexed access to pwmN files to toggle writability */
+static struct attribute *f71805f_attr_pwm[] = {
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
};
/*
@@ -798,18 +1118,30 @@ static void __devinit f71805f_init_device(struct f71805f_data *data)
/* Fan monitoring can be disabled. If it is, we won't be polling
the register values, and won't create the related sysfs files. */
for (i = 0; i < 3; i++) {
- reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
- if (!(reg & 0x80))
- data->fan_enabled |= (1 << i);
+ data->fan_ctrl[i] = f71805f_read8(data,
+ F71805F_REG_FAN_CTRL(i));
+ /* Clear latch full bit, else "speed mode" fan speed control
+ doesn't work */
+ if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
+ data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
+ f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
+ data->fan_ctrl[i]);
+ }
}
}
static int __devinit f71805f_probe(struct platform_device *pdev)
{
+ struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
struct f71805f_data *data;
struct resource *res;
int i, err;
+ static const char *names[] = {
+ "f71805f",
+ "f71872f",
+ };
+
if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Out of memory\n");
@@ -819,24 +1151,69 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
data->addr = res->start;
mutex_init(&data->lock);
- data->name = "f71805f";
+ data->name = names[sio_data->kind];
mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data);
+ /* Some voltage inputs depend on chip model and configuration */
+ switch (sio_data->kind) {
+ case f71805f:
+ data->has_in = 0x1ff;
+ break;
+ case f71872f:
+ data->has_in = 0x6ef;
+ if (sio_data->fnsel1 & 0x01)
+ data->has_in |= (1 << 4); /* in4 */
+ if (sio_data->fnsel1 & 0x02)
+ data->has_in |= (1 << 8); /* in8 */
+ break;
+ }
+
/* Initialize the F71805F chip */
f71805f_init_device(data);
/* Register sysfs interface files */
if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
goto exit_free;
- for (i = 0; i < 3; i++) {
- if (!(data->fan_enabled & (1 << i)))
- continue;
+ if (data->has_in & (1 << 4)) { /* in4 */
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &f71805f_group_optin[0])))
+ goto exit_remove_files;
+ }
+ if (data->has_in & (1 << 8)) { /* in8 */
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &f71805f_group_optin[1])))
+ goto exit_remove_files;
+ }
+ if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */
if ((err = sysfs_create_group(&pdev->dev.kobj,
- &f71805f_group_fan[i])))
+ &f71805f_group_optin[2])))
goto exit_remove_files;
}
+ if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &f71805f_group_optin[3])))
+ goto exit_remove_files;
+ }
+ for (i = 0; i < 3; i++) {
+ /* If control mode is PWM, create pwm_freq file */
+ if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
+ if ((err = sysfs_create_file(&pdev->dev.kobj,
+ f71805f_attributes_pwm_freq[i])))
+ goto exit_remove_files;
+ }
+ /* If PWM is in manual mode, add write permission */
+ if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
+ if ((err = sysfs_chmod_file(&pdev->dev.kobj,
+ f71805f_attr_pwm[i],
+ S_IRUGO | S_IWUSR))) {
+ dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
+ i + 1);
+ goto exit_remove_files;
+ }
+ }
+ }
data->class_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->class_dev)) {
@@ -849,8 +1226,9 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
exit_remove_files:
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
- for (i = 0; i < 3; i++)
- sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
+ for (i = 0; i < 4; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
exit_free:
platform_set_drvdata(pdev, NULL);
kfree(data);
@@ -866,8 +1244,9 @@ static int __devexit f71805f_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
- for (i = 0; i < 3; i++)
- sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
+ for (i = 0; i < 4; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
+ sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
kfree(data);
return 0;
@@ -882,7 +1261,8 @@ static struct platform_driver f71805f_driver = {
.remove = __devexit_p(f71805f_remove),
};
-static int __init f71805f_device_add(unsigned short address)
+static int __init f71805f_device_add(unsigned short address,
+ const struct f71805f_sio_data *sio_data)
{
struct resource res = {
.start = address,
@@ -906,26 +1286,45 @@ static int __init f71805f_device_add(unsigned short address)
goto exit_device_put;
}
+ pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data),
+ GFP_KERNEL);
+ if (!pdev->dev.platform_data) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+ goto exit_device_put;
+ }
+ memcpy(pdev->dev.platform_data, sio_data,
+ sizeof(struct f71805f_sio_data));
+
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
- goto exit_device_put;
+ goto exit_kfree_data;
}
return 0;
+exit_kfree_data:
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
exit_device_put:
platform_device_put(pdev);
exit:
return err;
}
-static int __init f71805f_find(int sioaddr, unsigned short *address)
+static int __init f71805f_find(int sioaddr, unsigned short *address,
+ struct f71805f_sio_data *sio_data)
{
int err = -ENODEV;
u16 devid;
+ static const char *names[] = {
+ "F71805F/FG",
+ "F71872F/FG",
+ };
+
superio_enter(sioaddr);
devid = superio_inw(sioaddr, SIO_REG_MANID);
@@ -933,7 +1332,15 @@ static int __init f71805f_find(int sioaddr, unsigned short *address)
goto exit;
devid = superio_inw(sioaddr, SIO_REG_DEVID);
- if (devid != SIO_F71805F_ID) {
+ switch (devid) {
+ case SIO_F71805F_ID:
+ sio_data->kind = f71805f;
+ break;
+ case SIO_F71872F_ID:
+ sio_data->kind = f71872f;
+ sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
+ break;
+ default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
"skipping\n");
goto exit;
@@ -952,10 +1359,12 @@ static int __init f71805f_find(int sioaddr, unsigned short *address)
"skipping\n");
goto exit;
}
+ *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
err = 0;
- printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
- *address, superio_inb(sioaddr, SIO_REG_DEVREV));
+ printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
+ names[sio_data->kind], *address,
+ superio_inb(sioaddr, SIO_REG_DEVREV));
exit:
superio_exit(sioaddr);
@@ -966,9 +1375,10 @@ static int __init f71805f_init(void)
{
int err;
unsigned short address;
+ struct f71805f_sio_data sio_data;
- if (f71805f_find(0x2e, &address)
- && f71805f_find(0x4e, &address))
+ if (f71805f_find(0x2e, &address, &sio_data)
+ && f71805f_find(0x4e, &address, &sio_data))
return -ENODEV;
err = platform_driver_register(&f71805f_driver);
@@ -976,7 +1386,7 @@ static int __init f71805f_init(void)
goto exit;
/* Sets global pdev as a side effect */
- err = f71805f_device_add(address);
+ err = f71805f_device_add(address, &sio_data);
if (err)
goto exit_driver;
@@ -990,13 +1400,16 @@ exit:
static void __exit f71805f_exit(void)
{
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
platform_device_unregister(pdev);
+
platform_driver_unregister(&f71805f_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("F71805F hardware monitoring driver");
+MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");
module_init(f71805f_init);
module_exit(f71805f_exit);
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index e8ef62b83d6..bf759ea545a 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -478,74 +478,64 @@ static struct attribute_group hdaps_attribute_group = {
/* Module stuff */
/* hdaps_dmi_match - found a match. return one, short-circuiting the hunt. */
-static int hdaps_dmi_match(struct dmi_system_id *id)
+static int __init hdaps_dmi_match(struct dmi_system_id *id)
{
printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
return 1;
}
/* hdaps_dmi_match_invert - found an inverted match. */
-static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+static int __init hdaps_dmi_match_invert(struct dmi_system_id *id)
{
hdaps_invert = 1;
printk(KERN_INFO "hdaps: inverting axis readings.\n");
return hdaps_dmi_match(id);
}
-#define HDAPS_DMI_MATCH_NORMAL(model) { \
- .ident = "IBM " model, \
+#define HDAPS_DMI_MATCH_NORMAL(vendor, model) { \
+ .ident = vendor " " model, \
.callback = hdaps_dmi_match, \
.matches = { \
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_BOARD_VENDOR, vendor), \
DMI_MATCH(DMI_PRODUCT_VERSION, model) \
} \
}
-#define HDAPS_DMI_MATCH_INVERT(model) { \
- .ident = "IBM " model, \
+#define HDAPS_DMI_MATCH_INVERT(vendor, model) { \
+ .ident = vendor " " model, \
.callback = hdaps_dmi_match_invert, \
.matches = { \
- DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), \
+ DMI_MATCH(DMI_BOARD_VENDOR, vendor), \
DMI_MATCH(DMI_PRODUCT_VERSION, model) \
} \
}
-#define HDAPS_DMI_MATCH_LENOVO(model) { \
- .ident = "Lenovo " model, \
- .callback = hdaps_dmi_match_invert, \
- .matches = { \
- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), \
- DMI_MATCH(DMI_PRODUCT_VERSION, model) \
- } \
-}
+/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
+ "ThinkPad T42p", so the order of the entries matters.
+ If your ThinkPad is not recognized, please update to latest
+ BIOS. This is especially the case for some R52 ThinkPads. */
+static struct dmi_system_id __initdata hdaps_whitelist[] = {
+ HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
+ HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
+ HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
+ HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"),
+ HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"),
+ HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
+ { .ident = NULL }
+};
static int __init hdaps_init(void)
{
int ret;
- /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
- "ThinkPad T42p", so the order of the entries matters */
- struct dmi_system_id hdaps_whitelist[] = {
- HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
- HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), /* R52 (1846AQG) */
- HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
- HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
- HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
- HDAPS_DMI_MATCH_LENOVO("ThinkPad T60"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
- HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
- HDAPS_DMI_MATCH_NORMAL("ThinkPad Z60m"),
- { .ident = NULL }
- };
-
if (!dmi_check_system(hdaps_whitelist)) {
printk(KERN_WARNING "hdaps: supported laptop not found!\n");
ret = -ENODEV;
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 9d67320e684..b80f6ed5acf 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -1,7 +1,7 @@
/*
hwmon-vid.c - VID/VRM/VRD voltage conversions
- Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+ Copyright (c) 2004 Rudolf Marek <r.marek@assembler.cz>
Partly imported from i2c-vid.h of the lm_sensors project
Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -93,7 +93,7 @@ int vid_from_reg(int val, u8 vrm)
case 110: /* Intel Conroe */
/* compute in uV, round to mV */
val &= 0xff;
- if(((val & 0x7e) == 0xfe) || (!(val & 0x7e)))
+ if (val < 0x02 || val > 0xb2)
return 0;
return((1600000 - (val - 2) * 6250 + 500) / 1000);
case 24: /* Opteron processor */
@@ -232,7 +232,7 @@ u8 vid_which_vrm(void)
EXPORT_SYMBOL(vid_from_reg);
EXPORT_SYMBOL(vid_which_vrm);
-MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
MODULE_DESCRIPTION("hwmon-vid driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 323ef06719c..1ed8b7e2c35 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -3,7 +3,7 @@
monitoring.
Supports: IT8705F Super I/O chip w/LPC interface
- IT8712F Super I/O chip w/LPC interface & SMBus
+ IT8712F Super I/O chip w/LPC interface
IT8716F Super I/O chip w/LPC interface
IT8718F Super I/O chip w/LPC interface
Sis950 A clone of the IT8705F
@@ -41,12 +41,8 @@
#include <asm/io.h>
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
static unsigned short isa_address;
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718);
+enum chips { it87, it8712, it8716, it8718 };
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
@@ -162,8 +158,6 @@ static u8 vid_value;
#define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2)
#define IT87_REG_TEMP_LOW(nr) (0x41 + (nr) * 2)
-#define IT87_REG_I2C_ADDR 0x48
-
#define IT87_REG_VIN_ENABLE 0x50
#define IT87_REG_TEMP_ENABLE 0x51
@@ -242,33 +236,22 @@ struct it87_data {
};
-static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
-static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
+static int it87_detect(struct i2c_adapter *adapter);
static int it87_detach_client(struct i2c_client *client);
static int it87_read_value(struct i2c_client *client, u8 reg);
-static int it87_write_value(struct i2c_client *client, u8 reg, u8 value);
+static void it87_write_value(struct i2c_client *client, u8 reg, 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);
-static struct i2c_driver it87_driver = {
- .driver = {
- .name = "it87",
- },
- .id = I2C_DRIVERID_IT87,
- .attach_adapter = it87_attach_adapter,
- .detach_client = it87_detach_client,
-};
-
static struct i2c_driver it87_isa_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "it87-isa",
},
- .attach_adapter = it87_isa_attach_adapter,
+ .attach_adapter = it87_detect,
.detach_client = it87_detach_client,
};
@@ -850,22 +833,6 @@ static const struct attribute_group it87_group_opt = {
.attrs = it87_attributes_opt,
};
-/* This function is called when:
- * it87_driver is inserted (when this module is loaded), for each
- available adapter
- * when a new adapter is inserted (and it87_driver is still present) */
-static int it87_attach_adapter(struct i2c_adapter *adapter)
-{
- if (!(adapter->class & I2C_CLASS_HWMON))
- return 0;
- return i2c_probe(adapter, &addr_data, it87_detect);
-}
-
-static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
-{
- return it87_detect(adapter, isa_address, -1);
-}
-
/* SuperIO detection - will change isa_address if a chip is found */
static int __init it87_find(unsigned short *address)
{
@@ -916,29 +883,20 @@ exit:
}
/* This function is called by i2c_probe */
-static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
+static int it87_detect(struct i2c_adapter *adapter)
{
- int i;
struct i2c_client *new_client;
struct it87_data *data;
int err = 0;
- const char *name = "";
- int is_isa = i2c_is_isa_adapter(adapter);
+ const char *name;
int enable_pwm_interface;
- if (!is_isa &&
- !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- goto ERROR0;
-
/* Reserve the ISA region */
- if (is_isa)
- if (!request_region(address, IT87_EXTENT,
- it87_isa_driver.driver.name))
- goto ERROR0;
-
- /* For now, we presume we have a valid client. We create the
- client structure, even though we cannot fill it completely yet.
- But it allows us to access it87_{read,write}_value. */
+ if (!request_region(isa_address, IT87_EXTENT,
+ it87_isa_driver.driver.name)){
+ err = -EBUSY;
+ goto ERROR0;
+ }
if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
err = -ENOMEM;
@@ -946,80 +904,46 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
}
new_client = &data->client;
- if (is_isa)
- mutex_init(&data->lock);
+ mutex_init(&data->lock);
i2c_set_clientdata(new_client, data);
- new_client->addr = address;
+ new_client->addr = isa_address;
new_client->adapter = adapter;
- new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
- new_client->flags = 0;
+ new_client->driver = &it87_isa_driver;
/* Now, we do the remaining detection. */
-
- if (kind < 0) {
- if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
- || (!is_isa
- && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) {
- err = -ENODEV;
- goto ERROR2;
- }
+ if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
+ || it87_read_value(new_client, IT87_REG_CHIPID) != 0x90) {
+ err = -ENODEV;
+ goto ERROR2;
}
/* Determine the chip type. */
- if (kind <= 0) {
- i = it87_read_value(new_client, IT87_REG_CHIPID);
- if (i == 0x90) {
- kind = it87;
- if (is_isa) {
- switch (chip_type) {
- case IT8712F_DEVID:
- kind = it8712;
- break;
- case IT8716F_DEVID:
- kind = it8716;
- break;
- case IT8718F_DEVID:
- kind = it8718;
- break;
- }
- }
- }
- else {
- if (kind == 0)
- dev_info(&adapter->dev,
- "Ignoring 'force' parameter for unknown chip at "
- "adapter %d, address 0x%02x\n",
- i2c_adapter_id(adapter), address);
- err = -ENODEV;
- goto ERROR2;
- }
- }
-
- if (kind == it87) {
- name = "it87";
- } else if (kind == it8712) {
+ switch (chip_type) {
+ case IT8712F_DEVID:
+ data->type = it8712;
name = "it8712";
- } else if (kind == it8716) {
+ break;
+ case IT8716F_DEVID:
+ data->type = it8716;
name = "it8716";
- } else if (kind == it8718) {
+ break;
+ case IT8718F_DEVID:
+ data->type = it8718;
name = "it8718";
+ break;
+ default:
+ data->type = it87;
+ name = "it87";
}
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
- data->type = kind;
- data->valid = 0;
mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR2;
- if (!is_isa)
- dev_info(&new_client->dev, "The I2C interface to IT87xxF "
- "hardware monitoring chips is deprecated. Please "
- "report if you still rely on it.\n");
-
/* Check PWM configuration */
enable_pwm_interface = it87_check_pwm(new_client);
@@ -1129,8 +1053,7 @@ ERROR3:
ERROR2:
kfree(data);
ERROR1:
- if (is_isa)
- release_region(address, IT87_EXTENT);
+ release_region(isa_address, IT87_EXTENT);
ERROR0:
return err;
}
@@ -1147,50 +1070,39 @@ static int it87_detach_client(struct i2c_client *client)
if ((err = i2c_detach_client(client)))
return err;
- if(i2c_is_isa_client(client))
- release_region(client->addr, IT87_EXTENT);
+ release_region(client->addr, IT87_EXTENT);
kfree(data);
return 0;
}
-/* The SMBus locks itself, but ISA access must be locked explicitly!
- We don't want to lock the whole ISA bus, so we lock each client
- separately.
+/* ISA access must be locked explicitly!
We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
would slow down the IT87 access and should not be necessary. */
static int it87_read_value(struct i2c_client *client, u8 reg)
{
struct it87_data *data = i2c_get_clientdata(client);
-
int res;
- if (i2c_is_isa_client(client)) {
- mutex_lock(&data->lock);
- outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
- res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
- mutex_unlock(&data->lock);
- return res;
- } else
- return i2c_smbus_read_byte_data(client, reg);
+
+ mutex_lock(&data->lock);
+ outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
+ res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
+ mutex_unlock(&data->lock);
+
+ return res;
}
-/* The SMBus locks itself, but ISA access muse be locked explicitly!
- We don't want to lock the whole ISA bus, so we lock each client
- separately.
+/* ISA access must be locked explicitly!
We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
would slow down the IT87 access and should not be necessary. */
-static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
+static void it87_write_value(struct i2c_client *client, u8 reg, u8 value)
{
struct it87_data *data = i2c_get_clientdata(client);
- if (i2c_is_isa_client(client)) {
- mutex_lock(&data->lock);
- outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
- outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
- mutex_unlock(&data->lock);
- return 0;
- } else
- return i2c_smbus_write_byte_data(client, reg, value);
+ mutex_lock(&data->lock);
+ outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
+ outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
+ mutex_unlock(&data->lock);
}
/* Return 1 if and only if the PWM interface is safe to use */
@@ -1426,26 +1338,14 @@ static int __init sm_it87_init(void)
{
int res;
- res = i2c_add_driver(&it87_driver);
- if (res)
+ if ((res = it87_find(&isa_address)))
return res;
-
- if (!it87_find(&isa_address)) {
- res = i2c_isa_add_driver(&it87_isa_driver);
- if (res) {
- i2c_del_driver(&it87_driver);
- return res;
- }
- }
-
- return 0;
+ return i2c_isa_add_driver(&it87_isa_driver);
}
static void __exit sm_it87_exit(void)
{
- if (isa_address)
- i2c_isa_del_driver(&it87_isa_driver);
- i2c_del_driver(&it87_driver);
+ i2c_isa_del_driver(&it87_isa_driver);
}
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index f58b64ed09e..5d8d0ca08fa 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -1,7 +1,7 @@
/*
* k8temp.c - Linux kernel module for hardware monitoring
*
- * Copyright (C) 2006 Rudolf Marek <r.marek@sh.cvut.cz>
+ * Copyright (C) 2006 Rudolf Marek <r.marek@assembler.cz>
*
* Inspired from the w83785 and amd756 drivers.
*
@@ -286,7 +286,7 @@ static void __exit k8temp_exit(void)
pci_unregister_driver(&k8temp_driver);
}
-MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
MODULE_DESCRIPTION("AMD K8 core temperature monitor");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 3b8b81984ad..c8a21be09d8 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1000,7 +1000,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
(i&0x02) ? "external" : "internal");
data->vid_conf = confreg[3];
- data->vrm = 90;
+ data->vrm = vid_which_vrm();
}
/* Fan clock dividers may be needed before any data is read */
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
new file mode 100644
index 00000000000..affa21a5ccf
--- /dev/null
+++ b/drivers/hwmon/pc87427.c
@@ -0,0 +1,627 @@
+/*
+ * pc87427.c - hardware monitoring driver for the
+ * National Semiconductor PC87427 Super-I/O chip
+ * Copyright (C) 2006 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Supports the following chips:
+ *
+ * Chip #vin #fan #pwm #temp devid
+ * PC87427 - 8 - - 0xF2
+ *
+ * This driver assumes that no more than one chip is present.
+ * Only fan inputs are supported so far, although the chip can do much more.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <asm/io.h>
+
+static struct platform_device *pdev;
+
+#define DRVNAME "pc87427"
+
+/* The lock mutex protects both the I/O accesses (needed because the
+ device is using banked registers) and the register cache (needed to keep
+ the data in the registers and the cache in sync at any time). */
+struct pc87427_data {
+ struct class_device *class_dev;
+ struct mutex lock;
+ int address[2];
+ const char *name;
+
+ unsigned long last_updated; /* in jiffies */
+ u8 fan_enabled; /* bit vector */
+ u16 fan[8]; /* register values */
+ u16 fan_min[8]; /* register values */
+ u8 fan_status[8]; /* register values */
+};
+
+/*
+ * Super-I/O registers and operations
+ */
+
+#define SIOREG_LDSEL 0x07 /* Logical device select */
+#define SIOREG_DEVID 0x20 /* Device ID */
+#define SIOREG_ACT 0x30 /* Device activation */
+#define SIOREG_MAP 0x50 /* I/O or memory mapping */
+#define SIOREG_IOBASE 0x60 /* I/O base address */
+
+static const u8 logdev[2] = { 0x09, 0x14 };
+static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
+#define LD_FAN 0
+#define LD_IN 1
+#define LD_TEMP 1
+
+static inline void superio_outb(int sioaddr, int reg, int val)
+{
+ outb(reg, sioaddr);
+ outb(val, sioaddr + 1);
+}
+
+static inline int superio_inb(int sioaddr, int reg)
+{
+ outb(reg, sioaddr);
+ return inb(sioaddr + 1);
+}
+
+static inline void superio_exit(int sioaddr)
+{
+ outb(0x02, sioaddr);
+ outb(0x02, sioaddr + 1);
+}
+
+/*
+ * Logical devices
+ */
+
+#define REGION_LENGTH 32
+#define PC87427_REG_BANK 0x0f
+#define BANK_FM(nr) (nr)
+#define BANK_FT(nr) (0x08 + (nr))
+#define BANK_FC(nr) (0x10 + (nr) * 2)
+
+/*
+ * I/O access functions
+ */
+
+/* ldi is the logical device index */
+static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
+{
+ return inb(data->address[ldi] + reg);
+}
+
+/* Must be called with data->lock held, except during init */
+static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
+ u8 bank, u8 reg)
+{
+ outb(bank, data->address[ldi] + PC87427_REG_BANK);
+ return inb(data->address[ldi] + reg);
+}
+
+/* Must be called with data->lock held, except during init */
+static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
+ u8 bank, u8 reg, u8 value)
+{
+ outb(bank, data->address[ldi] + PC87427_REG_BANK);
+ outb(value, data->address[ldi] + reg);
+}
+
+/*
+ * Fan registers and conversions
+ */
+
+/* fan data registers are 16-bit wide */
+#define PC87427_REG_FAN 0x12
+#define PC87427_REG_FAN_MIN 0x14
+#define PC87427_REG_FAN_STATUS 0x10
+
+#define FAN_STATUS_STALL (1 << 3)
+#define FAN_STATUS_LOSPD (1 << 1)
+#define FAN_STATUS_MONEN (1 << 0)
+
+/* Dedicated function to read all registers related to a given fan input.
+ This saves us quite a few locks and bank selections.
+ Must be called with data->lock held.
+ nr is from 0 to 7 */
+static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
+{
+ int iobase = data->address[LD_FAN];
+
+ outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
+ data->fan[nr] = inw(iobase + PC87427_REG_FAN);
+ data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
+ data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
+ /* Clear fan alarm bits */
+ outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
+}
+
+/* The 2 LSB of fan speed registers are used for something different.
+ The actual 2 LSB of the measurements are not available. */
+static inline unsigned long fan_from_reg(u16 reg)
+{
+ reg &= 0xfffc;
+ if (reg == 0x0000 || reg == 0xfffc)
+ return 0;
+ return 5400000UL / reg;
+}
+
+/* The 2 LSB of the fan speed limit registers are not significant. */
+static inline u16 fan_to_reg(unsigned long val)
+{
+ if (val < 83UL)
+ return 0xffff;
+ if (val >= 1350000UL)
+ return 0x0004;
+ return ((1350000UL + val / 2) / val) << 2;
+}
+
+/*
+ * Data interface
+ */
+
+static struct pc87427_data *pc87427_update_device(struct device *dev)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+ int i;
+
+ mutex_lock(&data->lock);
+ if (!time_after(jiffies, data->last_updated + HZ)
+ && data->last_updated)
+ goto done;
+
+ /* Fans */
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ pc87427_readall_fan(data, i);
+ }
+ data->last_updated = jiffies;
+
+done:
+ mutex_unlock(&data->lock);
+ return data;
+}
+
+static ssize_t show_fan_input(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
+}
+
+static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", !!(data->fan_status[nr]
+ & FAN_STATUS_LOSPD));
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct pc87427_data *data = pc87427_update_device(dev);
+ int nr = attr->index;
+
+ return sprintf(buf, "%d\n", !!(data->fan_status[nr]
+ & FAN_STATUS_STALL));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ int nr = attr->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int iobase = data->address[LD_FAN];
+
+ mutex_lock(&data->lock);
+ outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
+ /* The low speed limit registers are read-only while monitoring
+ is enabled, so we have to disable monitoring, then change the
+ limit, and finally enable monitoring again. */
+ outb(0, iobase + PC87427_REG_FAN_STATUS);
+ data->fan_min[nr] = fan_to_reg(val);
+ outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
+ outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 3);
+static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 4);
+static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 5);
+static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 6);
+static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
+ show_fan_min, set_fan_min, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
+
+static struct attribute *pc87427_attributes_fan[8][5] = {
+ {
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan1_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_min.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan4_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan5_input.dev_attr.attr,
+ &sensor_dev_attr_fan5_min.dev_attr.attr,
+ &sensor_dev_attr_fan5_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan5_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan6_input.dev_attr.attr,
+ &sensor_dev_attr_fan6_min.dev_attr.attr,
+ &sensor_dev_attr_fan6_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan6_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan7_input.dev_attr.attr,
+ &sensor_dev_attr_fan7_min.dev_attr.attr,
+ &sensor_dev_attr_fan7_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan7_fault.dev_attr.attr,
+ NULL
+ }, {
+ &sensor_dev_attr_fan8_input.dev_attr.attr,
+ &sensor_dev_attr_fan8_min.dev_attr.attr,
+ &sensor_dev_attr_fan8_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan8_fault.dev_attr.attr,
+ NULL
+ }
+};
+
+static const struct attribute_group pc87427_group_fan[8] = {
+ { .attrs = pc87427_attributes_fan[0] },
+ { .attrs = pc87427_attributes_fan[1] },
+ { .attrs = pc87427_attributes_fan[2] },
+ { .attrs = pc87427_attributes_fan[3] },
+ { .attrs = pc87427_attributes_fan[4] },
+ { .attrs = pc87427_attributes_fan[5] },
+ { .attrs = pc87427_attributes_fan[6] },
+ { .attrs = pc87427_attributes_fan[7] },
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+
+/*
+ * Device detection, attach and detach
+ */
+
+static void __devinit pc87427_init_device(struct device *dev)
+{
+ struct pc87427_data *data = dev_get_drvdata(dev);
+ int i;
+ u8 reg;
+
+ /* The FMC module should be ready */
+ reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
+ if (!(reg & 0x80))
+ dev_warn(dev, "FMC module not ready!\n");
+
+ /* Check which fans are enabled */
+ for (i = 0; i < 8; i++) {
+ reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
+ PC87427_REG_FAN_STATUS);
+ if (reg & FAN_STATUS_MONEN)
+ data->fan_enabled |= (1 << i);
+ }
+
+ if (!data->fan_enabled) {
+ dev_dbg(dev, "Enabling all fan inputs\n");
+ for (i = 0; i < 8; i++)
+ pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
+ PC87427_REG_FAN_STATUS,
+ FAN_STATUS_MONEN);
+ data->fan_enabled = 0xff;
+ }
+}
+
+static int __devinit pc87427_probe(struct platform_device *pdev)
+{
+ struct pc87427_data *data;
+ struct resource *res;
+ int i, err;
+
+ if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Out of memory\n");
+ goto exit;
+ }
+
+ /* This will need to be revisited when we add support for
+ temperature and voltage monitoring. */
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ data->address[0] = res->start;
+
+ mutex_init(&data->lock);
+ data->name = "pc87427";
+ platform_set_drvdata(pdev, data);
+ pc87427_init_device(&pdev->dev);
+
+ /* Register sysfs hooks */
+ if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
+ goto exit_kfree;
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &pc87427_group_fan[i])))
+ goto exit_remove_files;
+ }
+
+ data->class_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+ goto exit_remove_files;
+ }
+
+ return 0;
+
+exit_remove_files:
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
+ }
+exit_kfree:
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+exit:
+ return err;
+}
+
+static int __devexit pc87427_remove(struct platform_device *pdev)
+{
+ struct pc87427_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ platform_set_drvdata(pdev, NULL);
+ hwmon_device_unregister(data->class_dev);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < 8; i++) {
+ if (!(data->fan_enabled & (1 << i)))
+ continue;
+ sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
+ }
+ kfree(data);
+
+ return 0;
+}
+
+
+static struct platform_driver pc87427_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = pc87427_probe,
+ .remove = __devexit_p(pc87427_remove),
+};
+
+static int __init pc87427_device_add(unsigned short address)
+{
+ struct resource res = {
+ .start = address,
+ .end = address + REGION_LENGTH - 1,
+ .name = logdev_str[0],
+ .flags = IORESOURCE_IO,
+ };
+ int err;
+
+ pdev = platform_device_alloc(DRVNAME, address);
+ if (!pdev) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+ goto exit;
+ }
+
+ err = platform_device_add_resources(pdev, &res, 1);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device resource addition failed "
+ "(%d)\n", err);
+ goto exit_device_put;
+ }
+
+ err = platform_device_add(pdev);
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+ err);
+ goto exit_device_put;
+ }
+
+ return 0;
+
+exit_device_put:
+ platform_device_put(pdev);
+exit:
+ return err;
+}
+
+static int __init pc87427_find(int sioaddr, unsigned short *address)
+{
+ u16 val;
+ int i, err = 0;
+
+ /* Identify device */
+ val = superio_inb(sioaddr, SIOREG_DEVID);
+ if (val != 0xf2) { /* PC87427 */
+ err = -ENODEV;
+ goto exit;
+ }
+
+ for (i = 0; i < 2; i++) {
+ address[i] = 0;
+ /* Select logical device */
+ superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
+
+ val = superio_inb(sioaddr, SIOREG_ACT);
+ if (!(val & 0x01)) {
+ printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
+ "not activated\n", logdev[i]);
+ continue;
+ }
+
+ val = superio_inb(sioaddr, SIOREG_MAP);
+ if (val & 0x01) {
+ printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
+ "is memory-mapped, can't use\n", logdev[i]);
+ continue;
+ }
+
+ val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
+ | superio_inb(sioaddr, SIOREG_IOBASE + 1);
+ if (!val) {
+ printk(KERN_INFO DRVNAME ": I/O base address not set "
+ "for logical device 0x%02x\n", logdev[i]);
+ continue;
+ }
+ address[i] = val;
+ }
+
+exit:
+ superio_exit(sioaddr);
+ return err;
+}
+
+static int __init pc87427_init(void)
+{
+ int err;
+ unsigned short address[2];
+
+ if (pc87427_find(0x2e, address)
+ && pc87427_find(0x4e, address))
+ return -ENODEV;
+
+ /* For now the driver only handles fans so we only care about the
+ first address. */
+ if (!address[0])
+ return -ENODEV;
+
+ err = platform_driver_register(&pc87427_driver);
+ if (err)
+ goto exit;
+
+ /* Sets global pdev as a side effect */
+ err = pc87427_device_add(address[0]);
+ if (err)
+ goto exit_driver;
+
+ return 0;
+
+exit_driver:
+ platform_driver_unregister(&pc87427_driver);
+exit:
+ return err;
+}
+
+static void __exit pc87427_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&pc87427_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
+MODULE_LICENSE("GPL");
+
+module_init(pc87427_init);
+module_exit(pc87427_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 2257806d010..212a1558c63 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -3,7 +3,7 @@
the Winbond W83627EHF Super-I/O chip
Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
Copyright (C) 2006 Yuan Mu (Winbond),
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.cz>
David Hubbard <david.c.hubbard@gmail.com>
Shamelessly ripped from the w83627hf driver
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 4e108262576..b0fa296740d 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -3,7 +3,7 @@
monitoring
Copyright (C) 2004, 2005 Winbond Electronics Corp.
Chunhao Huang <DZShen@Winbond.com.tw>,
- Rudolf Marek <r.marek@sh.cvut.cz>
+ Rudolf Marek <r.marek@assembler.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
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
new file mode 100644
index 00000000000..253ffaf1568
--- /dev/null
+++ b/drivers/hwmon/w83793.c
@@ -0,0 +1,1702 @@
+/*
+ w83793.c - Linux kernel driver for hardware monitoring
+ Copyright (C) 2006 Winbond Electronics Corp.
+ Yuan Mu
+ Rudolf Marek <r.marek@assembler.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 - version 2.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*
+ Supports following chips:
+
+ Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ w83793 10 12 8 6 0x7b 0x5ca3 yes no
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83793);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+ "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
+
+/*
+ Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved
+ as ID, Bank Select registers
+*/
+#define W83793_REG_BANKSEL 0x00
+#define W83793_REG_VENDORID 0x0d
+#define W83793_REG_CHIPID 0x0e
+#define W83793_REG_DEVICEID 0x0f
+
+#define W83793_REG_CONFIG 0x40
+#define W83793_REG_MFC 0x58
+#define W83793_REG_FANIN_CTRL 0x5c
+#define W83793_REG_FANIN_SEL 0x5d
+#define W83793_REG_I2C_ADDR 0x0b
+#define W83793_REG_I2C_SUBADDR 0x0c
+#define W83793_REG_VID_INA 0x05
+#define W83793_REG_VID_INB 0x06
+#define W83793_REG_VID_LATCHA 0x07
+#define W83793_REG_VID_LATCHB 0x08
+#define W83793_REG_VID_CTRL 0x59
+
+static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f };
+
+#define TEMP_READ 0
+#define TEMP_CRIT 1
+#define TEMP_CRIT_HYST 2
+#define TEMP_WARN 3
+#define TEMP_WARN_HYST 4
+/* only crit and crit_hyst affect real-time alarm status
+ current crit crit_hyst warn warn_hyst */
+static u16 W83793_REG_TEMP[][5] = {
+ {0x1c, 0x78, 0x79, 0x7a, 0x7b},
+ {0x1d, 0x7c, 0x7d, 0x7e, 0x7f},
+ {0x1e, 0x80, 0x81, 0x82, 0x83},
+ {0x1f, 0x84, 0x85, 0x86, 0x87},
+ {0x20, 0x88, 0x89, 0x8a, 0x8b},
+ {0x21, 0x8c, 0x8d, 0x8e, 0x8f},
+};
+
+#define W83793_REG_TEMP_LOW_BITS 0x22
+
+#define W83793_REG_BEEP(index) (0x53 + (index))
+#define W83793_REG_ALARM(index) (0x4b + (index))
+
+#define W83793_REG_CLR_CHASSIS 0x4a /* SMI MASK4 */
+#define W83793_REG_IRQ_CTRL 0x50
+#define W83793_REG_OVT_CTRL 0x51
+#define W83793_REG_OVT_BEEP 0x52
+
+#define IN_READ 0
+#define IN_MAX 1
+#define IN_LOW 2
+static const u16 W83793_REG_IN[][3] = {
+ /* Current, High, Low */
+ {0x10, 0x60, 0x61}, /* Vcore A */
+ {0x11, 0x62, 0x63}, /* Vcore B */
+ {0x12, 0x64, 0x65}, /* Vtt */
+ {0x14, 0x6a, 0x6b}, /* VSEN1 */
+ {0x15, 0x6c, 0x6d}, /* VSEN2 */
+ {0x16, 0x6e, 0x6f}, /* +3VSEN */
+ {0x17, 0x70, 0x71}, /* +12VSEN */
+ {0x18, 0x72, 0x73}, /* 5VDD */
+ {0x19, 0x74, 0x75}, /* 5VSB */
+ {0x1a, 0x76, 0x77}, /* VBAT */
+};
+
+/* Low Bits of Vcore A/B Vtt Read/High/Low */
+static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 };
+static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 };
+static u8 scale_in_add[] = { 0, 0, 0, 0, 0, 0, 0, 150, 150, 0 };
+
+#define W83793_REG_FAN(index) (0x23 + 2 * (index)) /* High byte */
+#define W83793_REG_FAN_MIN(index) (0x90 + 2 * (index)) /* High byte */
+
+#define W83793_REG_PWM_DEFAULT 0xb2
+#define W83793_REG_PWM_ENABLE 0x207
+#define W83793_REG_PWM_UPTIME 0xc3 /* Unit in 0.1 second */
+#define W83793_REG_PWM_DOWNTIME 0xc4 /* Unit in 0.1 second */
+#define W83793_REG_TEMP_CRITICAL 0xc5
+
+#define PWM_DUTY 0
+#define PWM_START 1
+#define PWM_NONSTOP 2
+#define W83793_REG_PWM(index, nr) (((nr) == 0 ? 0xb3 : \
+ (nr) == 1 ? 0x220 : 0x218) + (index))
+
+/* bit field, fan1 is bit0, fan2 is bit1 ... */
+#define W83793_REG_TEMP_FAN_MAP(index) (0x201 + (index))
+#define W83793_REG_TEMP_TOL(index) (0x208 + (index))
+#define W83793_REG_TEMP_CRUISE(index) (0x210 + (index))
+#define W83793_REG_PWM_STOP_TIME(index) (0x228 + (index))
+#define W83793_REG_SF2_TEMP(index, nr) (0x230 + ((index) << 4) + (nr))
+#define W83793_REG_SF2_PWM(index, nr) (0x238 + ((index) << 4) + (nr))
+
+static inline unsigned long FAN_FROM_REG(u16 val)
+{
+ if ((val >= 0xfff) || (val == 0))
+ return 0;
+ return (1350000UL / val);
+}
+
+static inline u16 FAN_TO_REG(long rpm)
+{
+ if (rpm <= 0)
+ return 0x0fff;
+ return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
+}
+
+static inline unsigned long TIME_FROM_REG(u8 reg)
+{
+ return (reg * 100);
+}
+
+static inline u8 TIME_TO_REG(unsigned long val)
+{
+ return SENSORS_LIMIT((val + 50) / 100, 0, 0xff);
+}
+
+static inline long TEMP_FROM_REG(s8 reg)
+{
+ return (reg * 1000);
+}
+
+static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
+{
+ return SENSORS_LIMIT((val + (val < 0 ? -500 : 500)) / 1000, min, max);
+}
+
+struct w83793_data {
+ struct i2c_client client;
+ struct i2c_client *lm75[2];
+ struct class_device *class_dev;
+ struct mutex update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ unsigned long last_nonvolatile; /* In jiffies, last time we update the
+ nonvolatile registers */
+
+ u8 bank;
+ u8 vrm;
+ u8 vid[2];
+ u8 in[10][3]; /* Register value, read/high/low */
+ u8 in_low_bits[3]; /* Additional resolution for VCore A/B Vtt */
+
+ u16 has_fan; /* Only fan1- fan5 has own pins */
+ u16 fan[12]; /* Register value combine */
+ u16 fan_min[12]; /* Register value combine */
+
+ s8 temp[6][5]; /* current, crit, crit_hyst,warn, warn_hyst */
+ u8 temp_low_bits; /* Additional resolution TD1-TD4 */
+ u8 temp_mode[2]; /* byte 0: Temp D1-D4 mode each has 2 bits
+ byte 1: Temp R1,R2 mode, each has 1 bit */
+ u8 temp_critical; /* If reached all fan will be at full speed */
+ u8 temp_fan_map[6]; /* Temp controls which pwm fan, bit field */
+
+ u8 has_pwm;
+ u8 has_temp;
+ u8 has_vid;
+ u8 pwm_enable; /* Register value, each Temp has 1 bit */
+ u8 pwm_uptime; /* Register value */
+ u8 pwm_downtime; /* Register value */
+ u8 pwm_default; /* All fan default pwm, next poweron valid */
+ u8 pwm[8][3]; /* Register value */
+ u8 pwm_stop_time[8];
+ u8 temp_cruise[6];
+
+ u8 alarms[5]; /* realtime status registers */
+ u8 beeps[5];
+ u8 beep_enable;
+ u8 tolerance[3]; /* Temp tolerance(Smart Fan I/II) */
+ u8 sf2_pwm[6][7]; /* Smart FanII: Fan duty cycle */
+ u8 sf2_temp[6][7]; /* Smart FanII: Temp level point */
+};
+
+static u8 w83793_read_value(struct i2c_client *client, u16 reg);
+static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
+static int w83793_attach_adapter(struct i2c_adapter *adapter);
+static int w83793_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83793_detach_client(struct i2c_client *client);
+static void w83793_init_client(struct i2c_client *client);
+static void w83793_update_nonvolatile(struct device *dev);
+static struct w83793_data *w83793_update_device(struct device *dev);
+
+static struct i2c_driver w83793_driver = {
+ .driver = {
+ .name = "w83793",
+ },
+ .attach_adapter = w83793_attach_adapter,
+ .detach_client = w83793_detach_client,
+};
+
+static ssize_t
+show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+
+ return sprintf(buf, "%d\n", vid_from_reg(data->vid[index], data->vrm));
+}
+
+static ssize_t
+store_vrm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ data->vrm = simple_strtoul(buf, NULL, 10);
+ return count;
+}
+
+#define ALARM_STATUS 0
+#define BEEP_ENABLE 1
+static ssize_t
+show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index >> 3;
+ int bit = sensor_attr->index & 0x07;
+ u8 val;
+
+ if (ALARM_STATUS == nr) {
+ val = (data->alarms[index] >> (bit)) & 1;
+ } else { /* BEEP_ENABLE */
+ val = (data->beeps[index] >> (bit)) & 1;
+ }
+
+ return sprintf(buf, "%u\n", val);
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index >> 3;
+ int shift = sensor_attr->index & 0x07;
+ u8 beep_bit = 1 << shift;
+ u8 val;
+
+ val = simple_strtoul(buf, NULL, 10);
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->beeps[index] = w83793_read_value(client, W83793_REG_BEEP(index));
+ data->beeps[index] &= ~beep_bit;
+ data->beeps[index] |= val << shift;
+ w83793_write_value(client, W83793_REG_BEEP(index), data->beeps[index]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t
+show_beep_enable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ return sprintf(buf, "%u\n", (data->beep_enable >> 1) & 0x01);
+}
+
+static ssize_t
+store_beep_enable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u8 val = simple_strtoul(buf, NULL, 10);
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP)
+ & 0xfd;
+ data->beep_enable |= val << 1;
+ w83793_write_value(client, W83793_REG_OVT_BEEP, data->beep_enable);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+/* Write any value to clear chassis alarm */
+static ssize_t
+store_chassis_clear(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u8 val;
+
+ mutex_lock(&data->update_lock);
+ val = w83793_read_value(client, W83793_REG_CLR_CHASSIS);
+ val |= 0x80;
+ w83793_write_value(client, W83793_REG_CLR_CHASSIS, val);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+#define FAN_INPUT 0
+#define FAN_MIN 1
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ u16 val;
+
+ if (FAN_INPUT == nr) {
+ val = data->fan[index] & 0x0fff;
+ } else {
+ val = data->fan_min[index] & 0x0fff;
+ }
+
+ return sprintf(buf, "%lu\n", FAN_FROM_REG(val));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u16 val = FAN_TO_REG(simple_strtoul(buf, NULL, 10));
+
+ mutex_lock(&data->update_lock);
+ data->fan_min[index] = val;
+ w83793_write_value(client, W83793_REG_FAN_MIN(index),
+ (val >> 8) & 0xff);
+ w83793_write_value(client, W83793_REG_FAN_MIN(index) + 1, val & 0xff);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+#define PWM_DUTY 0
+#define PWM_START 1
+#define PWM_NONSTOP 2
+#define PWM_STOP_TIME 3
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ struct w83793_data *data = w83793_update_device(dev);
+ u16 val;
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+
+ if (PWM_STOP_TIME == nr)
+ val = TIME_FROM_REG(data->pwm_stop_time[index]);
+ else
+ val = (data->pwm[index][nr] & 0x3f) << 2;
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ u8 val;
+
+ mutex_lock(&data->update_lock);
+ if (PWM_STOP_TIME == nr) {
+ val = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+ data->pwm_stop_time[index] = val;
+ w83793_write_value(client, W83793_REG_PWM_STOP_TIME(index),
+ val);
+ } else {
+ val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff)
+ >> 2;
+ data->pwm[index][nr] =
+ w83793_read_value(client, W83793_REG_PWM(index, nr)) & 0xc0;
+ data->pwm[index][nr] |= val;
+ w83793_write_value(client, W83793_REG_PWM(index, nr),
+ data->pwm[index][nr]);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ long temp = TEMP_FROM_REG(data->temp[index][nr]);
+
+ if (TEMP_READ == nr && index < 4) { /* Only TD1-TD4 have low bits */
+ int low = ((data->temp_low_bits >> (index * 2)) & 0x03) * 250;
+ temp += temp > 0 ? low : -low;
+ }
+ return sprintf(buf, "%ld\n", temp);
+}
+
+static ssize_t
+store_temp(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ long tmp = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->temp[index][nr] = TEMP_TO_REG(tmp, -128, 127);
+ w83793_write_value(client, W83793_REG_TEMP[index][nr],
+ data->temp[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ TD1-TD4
+ each has 4 mode:(2 bits)
+ 0: Stop monitor
+ 1: Use internal temp sensor(default)
+ 2: Reserved
+ 3: Use sensor in Intel CPU and get result by PECI
+
+ TR1-TR2
+ each has 2 mode:(1 bit)
+ 0: Disable temp sensor monitor
+ 1: To enable temp sensors monitor
+*/
+
+/* 0 disable, 6 PECI */
+static u8 TO_TEMP_MODE[] = { 0, 0, 0, 6 };
+
+static ssize_t
+show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w83793_data *data = w83793_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+ u8 mask = (index < 4) ? 0x03 : 0x01;
+ u8 shift = (index < 4) ? (2 * index) : (index - 4);
+ u8 tmp;
+ index = (index < 4) ? 0 : 1;
+
+ tmp = (data->temp_mode[index] >> shift) & mask;
+
+ /* for the internal sensor, found out if diode or thermistor */
+ if (tmp == 1) {
+ tmp = index == 0 ? 3 : 4;
+ } else {
+ tmp = TO_TEMP_MODE[tmp];
+ }
+
+ return sprintf(buf, "%d\n", tmp);
+}
+
+static ssize_t
+store_temp_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int index = sensor_attr->index;
+ u8 mask = (index < 4) ? 0x03 : 0x01;
+ u8 shift = (index < 4) ? (2 * index) : (index - 4);
+ u8 val = simple_strtoul(buf, NULL, 10);
+
+ /* transform the sysfs interface values into table above */
+ if ((val == 6) && (index < 4)) {
+ val -= 3;
+ } else if ((val == 3 && index < 4)
+ || (val == 4 && index >= 4)) {
+ /* transform diode or thermistor into internal enable */
+ val = !!val;
+ } else {
+ return -EINVAL;
+ }
+
+ index = (index < 4) ? 0 : 1;
+ mutex_lock(&data->update_lock);
+ data->temp_mode[index] =
+ w83793_read_value(client, W83793_REG_TEMP_MODE[index]);
+ data->temp_mode[index] &= ~(mask << shift);
+ data->temp_mode[index] |= val << shift;
+ w83793_write_value(client, W83793_REG_TEMP_MODE[index],
+ data->temp_mode[index]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+#define SETUP_PWM_DEFAULT 0
+#define SETUP_PWM_UPTIME 1 /* Unit in 0.1s */
+#define SETUP_PWM_DOWNTIME 2 /* Unit in 0.1s */
+#define SETUP_TEMP_CRITICAL 3
+static ssize_t
+show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ struct w83793_data *data = w83793_update_device(dev);
+ u32 val = 0;
+
+ if (SETUP_PWM_DEFAULT == nr) {
+ val = (data->pwm_default & 0x3f) << 2;
+ } else if (SETUP_PWM_UPTIME == nr) {
+ val = TIME_FROM_REG(data->pwm_uptime);
+ } else if (SETUP_PWM_DOWNTIME == nr) {
+ val = TIME_FROM_REG(data->pwm_downtime);
+ } else if (SETUP_TEMP_CRITICAL == nr) {
+ val = TEMP_FROM_REG(data->temp_critical & 0x7f);
+ }
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_sf_setup(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+ if (SETUP_PWM_DEFAULT == nr) {
+ data->pwm_default =
+ w83793_read_value(client, W83793_REG_PWM_DEFAULT) & 0xc0;
+ data->pwm_default |= SENSORS_LIMIT(simple_strtoul(buf, NULL,
+ 10),
+ 0, 0xff) >> 2;
+ w83793_write_value(client, W83793_REG_PWM_DEFAULT,
+ data->pwm_default);
+ } else if (SETUP_PWM_UPTIME == nr) {
+ data->pwm_uptime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+ data->pwm_uptime += data->pwm_uptime == 0 ? 1 : 0;
+ w83793_write_value(client, W83793_REG_PWM_UPTIME,
+ data->pwm_uptime);
+ } else if (SETUP_PWM_DOWNTIME == nr) {
+ data->pwm_downtime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+ data->pwm_downtime += data->pwm_downtime == 0 ? 1 : 0;
+ w83793_write_value(client, W83793_REG_PWM_DOWNTIME,
+ data->pwm_downtime);
+ } else { /* SETUP_TEMP_CRITICAL */
+ data->temp_critical =
+ w83793_read_value(client, W83793_REG_TEMP_CRITICAL) & 0x80;
+ data->temp_critical |= TEMP_TO_REG(simple_strtol(buf, NULL, 10),
+ 0, 0x7f);
+ w83793_write_value(client, W83793_REG_TEMP_CRITICAL,
+ data->temp_critical);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ Temp SmartFan control
+ TEMP_FAN_MAP
+ Temp channel control which pwm fan, bitfield, bit 0 indicate pwm1...
+ It's possible two or more temp channels control the same fan, w83793
+ always prefers to pick the most critical request and applies it to
+ the related Fan.
+ It's possible one fan is not in any mapping of 6 temp channels, this
+ means the fan is manual mode
+
+ TEMP_PWM_ENABLE
+ Each temp channel has its own SmartFan mode, and temp channel
+ control fans that are set by TEMP_FAN_MAP
+ 0: SmartFanII mode
+ 1: Thermal Cruise Mode
+
+ TEMP_CRUISE
+ Target temperature in thermal cruise mode, w83793 will try to turn
+ fan speed to keep the temperature of target device around this
+ temperature.
+
+ TEMP_TOLERANCE
+ If Temp higher or lower than target with this tolerance, w83793
+ will take actions to speed up or slow down the fan to keep the
+ temperature within the tolerance range.
+*/
+
+#define TEMP_FAN_MAP 0
+#define TEMP_PWM_ENABLE 1
+#define TEMP_CRUISE 2
+#define TEMP_TOLERANCE 3
+static ssize_t
+show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ u32 val;
+
+ if (TEMP_FAN_MAP == nr) {
+ val = data->temp_fan_map[index];
+ } else if (TEMP_PWM_ENABLE == nr) {
+ /* +2 to transfrom into 2 and 3 to conform with sysfs intf */
+ val = ((data->pwm_enable >> index) & 0x01) + 2;
+ } else if (TEMP_CRUISE == nr) {
+ val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
+ } else { /* TEMP_TOLERANCE */
+ val = data->tolerance[index >> 1] >> ((index & 0x01) ? 4 : 0);
+ val = TEMP_FROM_REG(val & 0x0f);
+ }
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_sf_ctrl(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ mutex_lock(&data->update_lock);
+ if (TEMP_FAN_MAP == nr) {
+ val = simple_strtoul(buf, NULL, 10) & 0xff;
+ w83793_write_value(client, W83793_REG_TEMP_FAN_MAP(index), val);
+ data->temp_fan_map[index] = val;
+ } else if (TEMP_PWM_ENABLE == nr) {
+ val = simple_strtoul(buf, NULL, 10);
+ if (2 == val || 3 == val) {
+ data->pwm_enable =
+ w83793_read_value(client, W83793_REG_PWM_ENABLE);
+ if (val - 2)
+ data->pwm_enable |= 1 << index;
+ else
+ data->pwm_enable &= ~(1 << index);
+ w83793_write_value(client, W83793_REG_PWM_ENABLE,
+ data->pwm_enable);
+ } else {
+ mutex_unlock(&data->update_lock);
+ return -EINVAL;
+ }
+ } else if (TEMP_CRUISE == nr) {
+ data->temp_cruise[index] =
+ w83793_read_value(client, W83793_REG_TEMP_CRUISE(index));
+ val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+ data->temp_cruise[index] &= 0x80;
+ data->temp_cruise[index] |= val;
+
+ w83793_write_value(client, W83793_REG_TEMP_CRUISE(index),
+ data->temp_cruise[index]);
+ } else { /* TEMP_TOLERANCE */
+ int i = index >> 1;
+ u8 shift = (index & 0x01) ? 4 : 0;
+ data->tolerance[i] =
+ w83793_read_value(client, W83793_REG_TEMP_TOL(i));
+
+ val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x0f);
+ data->tolerance[i] &= ~(0x0f << shift);
+ data->tolerance[i] |= val << shift;
+ w83793_write_value(client, W83793_REG_TEMP_TOL(i),
+ data->tolerance[i]);
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+show_sf2_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+
+ return sprintf(buf, "%d\n", (data->sf2_pwm[index][nr] & 0x3f) << 2);
+}
+
+static ssize_t
+store_sf2_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2;
+
+ mutex_lock(&data->update_lock);
+ data->sf2_pwm[index][nr] =
+ w83793_read_value(client, W83793_REG_SF2_PWM(index, nr)) & 0xc0;
+ data->sf2_pwm[index][nr] |= val;
+ w83793_write_value(client, W83793_REG_SF2_PWM(index, nr),
+ data->sf2_pwm[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t
+show_sf2_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+
+ return sprintf(buf, "%ld\n",
+ TEMP_FROM_REG(data->sf2_temp[index][nr] & 0x7f));
+}
+
+static ssize_t
+store_sf2_temp(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ u8 val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+
+ mutex_lock(&data->update_lock);
+ data->sf2_temp[index][nr] =
+ w83793_read_value(client, W83793_REG_SF2_TEMP(index, nr)) & 0x80;
+ data->sf2_temp[index][nr] |= val;
+ w83793_write_value(client, W83793_REG_SF2_TEMP(index, nr),
+ data->sf2_temp[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/* only Vcore A/B and Vtt have additional 2 bits precision */
+static ssize_t
+show_in(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct w83793_data *data = w83793_update_device(dev);
+ u16 val = data->in[index][nr];
+
+ if (index < 3) {
+ val <<= 2;
+ val += (data->in_low_bits[nr] >> (index * 2)) & 0x3;
+ }
+ /* voltage inputs 5VDD and 5VSB needs 150mV offset */
+ val = val * scale_in[index] + scale_in_add[index];
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t
+store_in(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int index = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u32 val;
+
+ val =
+ (simple_strtoul(buf, NULL, 10) +
+ scale_in[index] / 2) / scale_in[index];
+ mutex_lock(&data->update_lock);
+ if (index > 2) {
+ /* fix the limit values of 5VDD and 5VSB to ALARM mechanism */
+ if (1 == nr || 2 == nr) {
+ val -= scale_in_add[index] / scale_in[index];
+ }
+ val = SENSORS_LIMIT(val, 0, 255);
+ } else {
+ val = SENSORS_LIMIT(val, 0, 0x3FF);
+ data->in_low_bits[nr] =
+ w83793_read_value(client, W83793_REG_IN_LOW_BITS[nr]);
+ data->in_low_bits[nr] &= ~(0x03 << (2 * index));
+ data->in_low_bits[nr] |= (val & 0x03) << (2 * index);
+ w83793_write_value(client, W83793_REG_IN_LOW_BITS[nr],
+ data->in_low_bits[nr]);
+ val >>= 2;
+ }
+ data->in[index][nr] = val;
+ w83793_write_value(client, W83793_REG_IN[index][nr],
+ data->in[index][nr]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+#define NOT_USED -1
+
+#define SENSOR_ATTR_IN(index) \
+ SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \
+ IN_READ, index), \
+ SENSOR_ATTR_2(in##index##_max, S_IRUGO | S_IWUSR, show_in, \
+ store_in, IN_MAX, index), \
+ SENSOR_ATTR_2(in##index##_min, S_IRUGO | S_IWUSR, show_in, \
+ store_in, IN_LOW, index), \
+ SENSOR_ATTR_2(in##index##_alarm, S_IRUGO, show_alarm_beep, \
+ NULL, ALARM_STATUS, index + ((index > 2) ? 1 : 0)), \
+ SENSOR_ATTR_2(in##index##_beep, S_IWUSR | S_IRUGO, \
+ show_alarm_beep, store_beep, BEEP_ENABLE, \
+ index + ((index > 2) ? 1 : 0))
+
+#define SENSOR_ATTR_FAN(index) \
+ SENSOR_ATTR_2(fan##index##_alarm, S_IRUGO, show_alarm_beep, \
+ NULL, ALARM_STATUS, index + 17), \
+ SENSOR_ATTR_2(fan##index##_beep, S_IWUSR | S_IRUGO, \
+ show_alarm_beep, store_beep, BEEP_ENABLE, index + 17), \
+ SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \
+ NULL, FAN_INPUT, index - 1), \
+ SENSOR_ATTR_2(fan##index##_min, S_IWUSR | S_IRUGO, \
+ show_fan, store_fan_min, FAN_MIN, index - 1)
+
+#define SENSOR_ATTR_PWM(index) \
+ SENSOR_ATTR_2(pwm##index, S_IWUSR | S_IRUGO, show_pwm, \
+ store_pwm, PWM_DUTY, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_nonstop, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_NONSTOP, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_start, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_START, index - 1), \
+ SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \
+ show_pwm, store_pwm, PWM_STOP_TIME, index - 1)
+
+#define SENSOR_ATTR_TEMP(index) \
+ SENSOR_ATTR_2(temp##index##_type, S_IRUGO | S_IWUSR, \
+ show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
+ SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
+ NULL, TEMP_READ, index - 1), \
+ SENSOR_ATTR_2(temp##index##_max, S_IRUGO | S_IWUSR, show_temp, \
+ store_temp, TEMP_CRIT, index - 1), \
+ SENSOR_ATTR_2(temp##index##_max_hyst, S_IRUGO | S_IWUSR, \
+ show_temp, store_temp, TEMP_CRIT_HYST, index - 1), \
+ SENSOR_ATTR_2(temp##index##_warn, S_IRUGO | S_IWUSR, show_temp, \
+ store_temp, TEMP_WARN, index - 1), \
+ SENSOR_ATTR_2(temp##index##_warn_hyst, S_IRUGO | S_IWUSR, \
+ show_temp, store_temp, TEMP_WARN_HYST, index - 1), \
+ SENSOR_ATTR_2(temp##index##_alarm, S_IRUGO, \
+ show_alarm_beep, NULL, ALARM_STATUS, index + 11), \
+ SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \
+ show_alarm_beep, store_beep, BEEP_ENABLE, index + 11), \
+ SENSOR_ATTR_2(temp##index##_auto_channels_pwm, \
+ S_IRUGO | S_IWUSR, show_sf_ctrl, store_sf_ctrl, \
+ TEMP_FAN_MAP, index - 1), \
+ SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \
+ show_sf_ctrl, store_sf_ctrl, TEMP_PWM_ENABLE, \
+ index - 1), \
+ SENSOR_ATTR_2(thermal_cruise##index, S_IRUGO | S_IWUSR, \
+ show_sf_ctrl, store_sf_ctrl, TEMP_CRUISE, index - 1), \
+ SENSOR_ATTR_2(tolerance##index, S_IRUGO | S_IWUSR, show_sf_ctrl,\
+ store_sf_ctrl, TEMP_TOLERANCE, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point1_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 0, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point2_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 1, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point3_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 2, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point4_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 3, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point5_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 4, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point6_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 5, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point7_pwm, S_IRUGO | S_IWUSR, \
+ show_sf2_pwm, store_sf2_pwm, 6, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point1_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 0, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point2_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 1, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point3_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 2, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point4_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 3, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point5_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 4, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point6_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 5, index - 1), \
+ SENSOR_ATTR_2(temp##index##_auto_point7_temp, S_IRUGO | S_IWUSR,\
+ show_sf2_temp, store_sf2_temp, 6, index - 1)
+
+static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
+ SENSOR_ATTR_IN(0),
+ SENSOR_ATTR_IN(1),
+ SENSOR_ATTR_IN(2),
+ SENSOR_ATTR_IN(3),
+ SENSOR_ATTR_IN(4),
+ SENSOR_ATTR_IN(5),
+ SENSOR_ATTR_IN(6),
+ SENSOR_ATTR_IN(7),
+ SENSOR_ATTR_IN(8),
+ SENSOR_ATTR_IN(9),
+ SENSOR_ATTR_FAN(1),
+ SENSOR_ATTR_FAN(2),
+ SENSOR_ATTR_FAN(3),
+ SENSOR_ATTR_FAN(4),
+ SENSOR_ATTR_FAN(5),
+ SENSOR_ATTR_PWM(1),
+ SENSOR_ATTR_PWM(2),
+ SENSOR_ATTR_PWM(3),
+};
+
+static struct sensor_device_attribute_2 w83793_temp[] = {
+ SENSOR_ATTR_TEMP(1),
+ SENSOR_ATTR_TEMP(2),
+ SENSOR_ATTR_TEMP(3),
+ SENSOR_ATTR_TEMP(4),
+ SENSOR_ATTR_TEMP(5),
+ SENSOR_ATTR_TEMP(6),
+};
+
+/* Fan6-Fan12 */
+static struct sensor_device_attribute_2 w83793_left_fan[] = {
+ SENSOR_ATTR_FAN(6),
+ SENSOR_ATTR_FAN(7),
+ SENSOR_ATTR_FAN(8),
+ SENSOR_ATTR_FAN(9),
+ SENSOR_ATTR_FAN(10),
+ SENSOR_ATTR_FAN(11),
+ SENSOR_ATTR_FAN(12),
+};
+
+/* Pwm4-Pwm8 */
+static struct sensor_device_attribute_2 w83793_left_pwm[] = {
+ SENSOR_ATTR_PWM(4),
+ SENSOR_ATTR_PWM(5),
+ SENSOR_ATTR_PWM(6),
+ SENSOR_ATTR_PWM(7),
+ SENSOR_ATTR_PWM(8),
+};
+
+static struct sensor_device_attribute_2 w83793_vid[] = {
+ SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
+ SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
+};
+
+static struct sensor_device_attribute_2 sda_single_files[] = {
+ SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
+ NOT_USED, NOT_USED),
+ SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
+ store_chassis_clear, ALARM_STATUS, 30),
+ SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable,
+ store_beep_enable, NOT_USED, NOT_USED),
+ SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_PWM_DEFAULT, NOT_USED),
+ SENSOR_ATTR_2(pwm_uptime, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_PWM_UPTIME, NOT_USED),
+ SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED),
+ SENSOR_ATTR_2(temp_critical, S_IWUSR | S_IRUGO, show_sf_setup,
+ store_sf_setup, SETUP_TEMP_CRITICAL, NOT_USED),
+};
+
+static void w83793_init_client(struct i2c_client *client)
+{
+ if (reset) {
+ w83793_write_value(client, W83793_REG_CONFIG, 0x80);
+ }
+
+ /* Start monitoring */
+ w83793_write_value(client, W83793_REG_CONFIG,
+ w83793_read_value(client, W83793_REG_CONFIG) | 0x01);
+
+}
+
+static int w83793_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_probe(adapter, &addr_data, w83793_detect);
+}
+
+static int w83793_detach_client(struct i2c_client *client)
+{
+ struct w83793_data *data = i2c_get_clientdata(client);
+ struct device *dev = &client->dev;
+ int err, i;
+
+ /* main client */
+ if (data) {
+ hwmon_device_unregister(data->class_dev);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+ device_remove_file(dev,
+ &w83793_sensor_attr_2[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+ device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+ device_remove_file(dev, &w83793_vid[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+ device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
+ device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+ device_remove_file(dev, &w83793_temp[i].dev_attr);
+ }
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ /* main client */
+ if (data)
+ kfree(data);
+ /* subclient */
+ else
+ kfree(client);
+
+ return 0;
+}
+
+static int
+w83793_create_subclient(struct i2c_adapter *adapter,
+ struct i2c_client *client, int addr,
+ struct i2c_client **sub_cli)
+{
+ int err = 0;
+ struct i2c_client *sub_client;
+
+ (*sub_cli) = sub_client =
+ kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!(sub_client)) {
+ return -ENOMEM;
+ }
+ sub_client->addr = 0x48 + addr;
+ i2c_set_clientdata(sub_client, NULL);
+ sub_client->adapter = adapter;
+ sub_client->driver = &w83793_driver;
+ strlcpy(sub_client->name, "w83793 subclient", I2C_NAME_SIZE);
+ if ((err = i2c_attach_client(sub_client))) {
+ dev_err(&client->dev, "subclient registration "
+ "at address 0x%x failed\n", sub_client->addr);
+ kfree(sub_client);
+ }
+ return err;
+}
+
+static int
+w83793_detect_subclients(struct i2c_adapter *adapter, int address,
+ int kind, struct i2c_client *client)
+{
+ int i, id, err;
+ u8 tmp;
+ struct w83793_data *data = i2c_get_clientdata(client);
+
+ id = i2c_adapter_id(adapter);
+ if (force_subclients[0] == id && force_subclients[1] == address) {
+ for (i = 2; i <= 3; i++) {
+ if (force_subclients[i] < 0x48
+ || force_subclients[i] > 0x4f) {
+ dev_err(&client->dev,
+ "invalid subclient "
+ "address %d; must be 0x48-0x4f\n",
+ force_subclients[i]);
+ err = -EINVAL;
+ goto ERROR_SC_0;
+ }
+ }
+ w83793_write_value(client, W83793_REG_I2C_SUBADDR,
+ (force_subclients[2] & 0x07) |
+ ((force_subclients[3] & 0x07) << 4));
+ }
+
+ tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
+ if (!(tmp & 0x08)) {
+ err =
+ w83793_create_subclient(adapter, client, tmp & 0x7,
+ &data->lm75[0]);
+ if (err < 0)
+ goto ERROR_SC_0;
+ }
+ if (!(tmp & 0x80)) {
+ if ((data->lm75[0] != NULL)
+ && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
+ dev_err(&client->dev,
+ "duplicate addresses 0x%x, "
+ "use force_subclients\n", data->lm75[0]->addr);
+ err = -ENODEV;
+ goto ERROR_SC_1;
+ }
+ err = w83793_create_subclient(adapter, client,
+ (tmp >> 4) & 0x7, &data->lm75[1]);
+ if (err < 0)
+ goto ERROR_SC_1;
+ }
+
+ return 0;
+
+ /* Undo inits in case of errors */
+
+ERROR_SC_1:
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ERROR_SC_0:
+ return err;
+}
+
+static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ int i;
+ u8 tmp, val;
+ struct i2c_client *client;
+ struct device *dev;
+ struct w83793_data *data;
+ int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
+ int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
+ int files_temp = ARRAY_SIZE(w83793_temp) / 6;
+ 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 w83793_{read,write}_value. */
+
+ if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ client = &data->client;
+ dev = &client->dev;
+ i2c_set_clientdata(client, data);
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &w83793_driver;
+
+ data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
+
+ /* Now, we do the remaining detection. */
+ if (kind < 0) {
+ tmp = data->bank & 0x80 ? 0x5c : 0xa3;
+ /* Check Winbond vendor ID */
+ if (tmp != i2c_smbus_read_byte_data(client,
+ W83793_REG_VENDORID)) {
+ pr_debug("w83793: Detection failed at check "
+ "vendor id\n");
+ err = -ENODEV;
+ goto free_mem;
+ }
+
+ /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
+ should match */
+ if ((data->bank & 0x07) == 0
+ && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) !=
+ (address << 1)) {
+ pr_debug("w83793: Detection failed at check "
+ "i2c addr\n");
+ err = -ENODEV;
+ goto free_mem;
+ }
+
+ }
+
+ /* We have either had a force parameter, or we have already detected the
+ Winbond. Determine the chip type now */
+
+ if (kind <= 0) {
+ if (0x7b == w83793_read_value(client, W83793_REG_CHIPID)) {
+ kind = w83793;
+ } else {
+ if (kind == 0)
+ dev_warn(&adapter->dev, "w83793: Ignoring "
+ "'force' parameter for unknown chip "
+ "at address 0x%02x\n", address);
+ err = -ENODEV;
+ goto free_mem;
+ }
+ }
+
+ /* Fill in the remaining client fields and put into the global list */
+ strlcpy(client->name, "w83793", I2C_NAME_SIZE);
+
+ mutex_init(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(client)))
+ goto free_mem;
+
+ if ((err = w83793_detect_subclients(adapter, address, kind, client)))
+ goto detach_client;
+
+ /* Initialize the chip */
+ w83793_init_client(client);
+
+ data->vrm = vid_which_vrm();
+ /*
+ Only fan 1-5 has their own input pins,
+ Pwm 1-3 has their own pins
+ */
+ data->has_fan = 0x1f;
+ data->has_pwm = 0x07;
+ tmp = w83793_read_value(client, W83793_REG_MFC);
+ val = w83793_read_value(client, W83793_REG_FANIN_CTRL);
+
+ /* check the function of pins 49-56 */
+ if (!(tmp & 0x80)) {
+ data->has_pwm |= 0x18; /* pwm 4,5 */
+ if (val & 0x01) { /* fan 6 */
+ data->has_fan |= 0x20;
+ data->has_pwm |= 0x20;
+ }
+ if (val & 0x02) { /* fan 7 */
+ data->has_fan |= 0x40;
+ data->has_pwm |= 0x40;
+ }
+ if (!(tmp & 0x40) && (val & 0x04)) { /* fan 8 */
+ data->has_fan |= 0x80;
+ data->has_pwm |= 0x80;
+ }
+ }
+
+ if (0x08 == (tmp & 0x0c)) {
+ if (val & 0x08) /* fan 9 */
+ data->has_fan |= 0x100;
+ if (val & 0x10) /* fan 10 */
+ data->has_fan |= 0x200;
+ }
+
+ if (0x20 == (tmp & 0x30)) {
+ if (val & 0x20) /* fan 11 */
+ data->has_fan |= 0x400;
+ if (val & 0x40) /* fan 12 */
+ data->has_fan |= 0x800;
+ }
+
+ if ((tmp & 0x01) && (val & 0x04)) { /* fan 8, second location */
+ data->has_fan |= 0x80;
+ data->has_pwm |= 0x80;
+ }
+
+ tmp = w83793_read_value(client, W83793_REG_FANIN_SEL);
+ if ((tmp & 0x01) && (val & 0x08)) { /* fan 9, second location */
+ data->has_fan |= 0x100;
+ }
+ if ((tmp & 0x02) && (val & 0x10)) { /* fan 10, second location */
+ data->has_fan |= 0x200;
+ }
+ if ((tmp & 0x04) && (val & 0x20)) { /* fan 11, second location */
+ data->has_fan |= 0x400;
+ }
+ if ((tmp & 0x08) && (val & 0x40)) { /* fan 12, second location */
+ data->has_fan |= 0x800;
+ }
+
+ /* check the temp1-6 mode, ignore former AMDSI selected inputs */
+ tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[0]);
+ if (tmp & 0x01)
+ data->has_temp |= 0x01;
+ if (tmp & 0x04)
+ data->has_temp |= 0x02;
+ if (tmp & 0x10)
+ data->has_temp |= 0x04;
+ if (tmp & 0x40)
+ data->has_temp |= 0x08;
+
+ tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[1]);
+ if (tmp & 0x01)
+ data->has_temp |= 0x10;
+ if (tmp & 0x02)
+ data->has_temp |= 0x20;
+
+ /* Detect the VID usage and ignore unused input */
+ tmp = w83793_read_value(client, W83793_REG_MFC);
+ if (!(tmp & 0x29))
+ data->has_vid |= 0x1; /* has VIDA */
+ if (tmp & 0x80)
+ data->has_vid |= 0x2; /* has VIDB */
+
+ /* Register sysfs hooks */
+ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
+ err = device_create_file(dev,
+ &w83793_sensor_attr_2[i].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) {
+ if (!(data->has_vid & (1 << i)))
+ continue;
+ err = device_create_file(dev, &w83793_vid[i].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
+ err = device_create_file(dev, &sda_single_files[i].dev_attr);
+ if (err)
+ goto exit_remove;
+
+ }
+
+ for (i = 0; i < 6; i++) {
+ int j;
+ if (!(data->has_temp & (1 << i)))
+ continue;
+ for (j = 0; j < files_temp; j++) {
+ err = device_create_file(dev,
+ &w83793_temp[(i) * files_temp
+ + j].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+ }
+
+ for (i = 5; i < 12; i++) {
+ int j;
+ if (!(data->has_fan & (1 << i)))
+ continue;
+ for (j = 0; j < files_fan; j++) {
+ err = device_create_file(dev,
+ &w83793_left_fan[(i - 5) * files_fan
+ + j].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+ }
+
+ for (i = 3; i < 8; i++) {
+ int j;
+ if (!(data->has_pwm & (1 << i)))
+ continue;
+ for (j = 0; j < files_pwm; j++) {
+ err = device_create_file(dev,
+ &w83793_left_pwm[(i - 3) * files_pwm
+ + j].dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+ }
+
+ data->class_dev = hwmon_device_register(dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_remove;
+ }
+
+ return 0;
+
+ /* Unregister sysfs hooks */
+
+exit_remove:
+ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+ device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+ device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+ device_remove_file(dev, &w83793_vid[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+ device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
+ device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+ for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+ device_remove_file(dev, &w83793_temp[i].dev_attr);
+
+ if (data->lm75[0] != NULL) {
+ i2c_detach_client(data->lm75[0]);
+ kfree(data->lm75[0]);
+ }
+ if (data->lm75[1] != NULL) {
+ i2c_detach_client(data->lm75[1]);
+ kfree(data->lm75[1]);
+ }
+detach_client:
+ i2c_detach_client(client);
+free_mem:
+ kfree(data);
+exit:
+ return err;
+}
+
+static void w83793_update_nonvolatile(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ int i, j;
+ /*
+ They are somewhat "stable" registers, and to update them everytime
+ takes so much time, it's just not worthy. Update them in a long
+ interval to avoid exception.
+ */
+ if (!(time_after(jiffies, data->last_nonvolatile + HZ * 300)
+ || !data->valid))
+ return;
+ /* update voltage limits */
+ for (i = 1; i < 3; i++) {
+ for (j = 0; j < ARRAY_SIZE(data->in); j++) {
+ data->in[j][i] =
+ w83793_read_value(client, W83793_REG_IN[j][i]);
+ }
+ data->in_low_bits[i] =
+ w83793_read_value(client, W83793_REG_IN_LOW_BITS[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
+ /* Update the Fan measured value and limits */
+ if (!(data->has_fan & (1 << i))) {
+ continue;
+ }
+ data->fan_min[i] =
+ w83793_read_value(client, W83793_REG_FAN_MIN(i)) << 8;
+ data->fan_min[i] |=
+ w83793_read_value(client, W83793_REG_FAN_MIN(i) + 1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) {
+ if (!(data->has_temp & (1 << i)))
+ continue;
+ data->temp_fan_map[i] =
+ w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i));
+ for (j = 1; j < 5; j++) {
+ data->temp[i][j] =
+ w83793_read_value(client, W83793_REG_TEMP[i][j]);
+ }
+ data->temp_cruise[i] =
+ w83793_read_value(client, W83793_REG_TEMP_CRUISE(i));
+ for (j = 0; j < 7; j++) {
+ data->sf2_pwm[i][j] =
+ w83793_read_value(client, W83793_REG_SF2_PWM(i, j));
+ data->sf2_temp[i][j] =
+ w83793_read_value(client,
+ W83793_REG_SF2_TEMP(i, j));
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->temp_mode); i++)
+ data->temp_mode[i] =
+ w83793_read_value(client, W83793_REG_TEMP_MODE[i]);
+
+ for (i = 0; i < ARRAY_SIZE(data->tolerance); i++) {
+ data->tolerance[i] =
+ w83793_read_value(client, W83793_REG_TEMP_TOL(i));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->pwm); i++) {
+ if (!(data->has_pwm & (1 << i)))
+ continue;
+ data->pwm[i][PWM_NONSTOP] =
+ w83793_read_value(client, W83793_REG_PWM(i, PWM_NONSTOP));
+ data->pwm[i][PWM_START] =
+ w83793_read_value(client, W83793_REG_PWM(i, PWM_START));
+ data->pwm_stop_time[i] =
+ w83793_read_value(client, W83793_REG_PWM_STOP_TIME(i));
+ }
+
+ data->pwm_default = w83793_read_value(client, W83793_REG_PWM_DEFAULT);
+ data->pwm_enable = w83793_read_value(client, W83793_REG_PWM_ENABLE);
+ data->pwm_uptime = w83793_read_value(client, W83793_REG_PWM_UPTIME);
+ data->pwm_downtime = w83793_read_value(client, W83793_REG_PWM_DOWNTIME);
+ data->temp_critical =
+ w83793_read_value(client, W83793_REG_TEMP_CRITICAL);
+ data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP);
+
+ for (i = 0; i < ARRAY_SIZE(data->beeps); i++) {
+ data->beeps[i] = w83793_read_value(client, W83793_REG_BEEP(i));
+ }
+
+ data->last_nonvolatile = jiffies;
+}
+
+static struct w83793_data *w83793_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83793_data *data = i2c_get_clientdata(client);
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ if (!(time_after(jiffies, data->last_updated + HZ * 2)
+ || !data->valid))
+ goto END;
+
+ /* Update the voltages measured value and limits */
+ for (i = 0; i < ARRAY_SIZE(data->in); i++)
+ data->in[i][IN_READ] =
+ w83793_read_value(client, W83793_REG_IN[i][IN_READ]);
+
+ data->in_low_bits[IN_READ] =
+ w83793_read_value(client, W83793_REG_IN_LOW_BITS[IN_READ]);
+
+ for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
+ if (!(data->has_fan & (1 << i))) {
+ continue;
+ }
+ data->fan[i] =
+ w83793_read_value(client, W83793_REG_FAN(i)) << 8;
+ data->fan[i] |=
+ w83793_read_value(client, W83793_REG_FAN(i) + 1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+ if (!(data->has_temp & (1 << i)))
+ continue;
+ data->temp[i][TEMP_READ] =
+ w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]);
+ }
+
+ data->temp_low_bits =
+ w83793_read_value(client, W83793_REG_TEMP_LOW_BITS);
+
+ for (i = 0; i < ARRAY_SIZE(data->pwm); i++) {
+ if (data->has_pwm & (1 << i))
+ data->pwm[i][PWM_DUTY] =
+ w83793_read_value(client,
+ W83793_REG_PWM(i, PWM_DUTY));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
+ data->alarms[i] =
+ w83793_read_value(client, W83793_REG_ALARM(i));
+ if (data->has_vid & 0x01)
+ data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
+ if (data->has_vid & 0x02)
+ data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
+ w83793_update_nonvolatile(dev);
+ data->last_updated = jiffies;
+ data->valid = 1;
+
+END:
+ mutex_unlock(&data->update_lock);
+ return data;
+}
+
+/* Ignore the possibility that somebody change bank outside the driver
+ Must be called with data->update_lock held, except during initialization */
+static u8 w83793_read_value(struct i2c_client *client, u16 reg)
+{
+ struct w83793_data *data = i2c_get_clientdata(client);
+ u8 res = 0xff;
+ u8 new_bank = reg >> 8;
+
+ new_bank |= data->bank & 0xfc;
+ if (data->bank != new_bank) {
+ if (i2c_smbus_write_byte_data
+ (client, W83793_REG_BANKSEL, new_bank) >= 0)
+ data->bank = new_bank;
+ else {
+ dev_err(&client->dev,
+ "set bank to %d failed, fall back "
+ "to bank %d, read reg 0x%x error\n",
+ new_bank, data->bank, reg);
+ res = 0x0; /* read 0x0 from the chip */
+ goto END;
+ }
+ }
+ res = i2c_smbus_read_byte_data(client, reg & 0xff);
+END:
+ return res;
+}
+
+/* Must be called with data->update_lock held, except during initialization */
+static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value)
+{
+ struct w83793_data *data = i2c_get_clientdata(client);
+ int res;
+ u8 new_bank = reg >> 8;
+
+ new_bank |= data->bank & 0xfc;
+ if (data->bank != new_bank) {
+ if ((res = i2c_smbus_write_byte_data
+ (client, W83793_REG_BANKSEL, new_bank)) >= 0)
+ data->bank = new_bank;
+ else {
+ dev_err(&client->dev,
+ "set bank to %d failed, fall back "
+ "to bank %d, write reg 0x%x error\n",
+ new_bank, data->bank, reg);
+ goto END;
+ }
+ }
+
+ res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
+END:
+ return res;
+}
+
+static int __init sensors_w83793_init(void)
+{
+ return i2c_add_driver(&w83793_driver);
+}
+
+static void __exit sensors_w83793_exit(void)
+{
+ i2c_del_driver(&w83793_driver);
+}
+
+MODULE_AUTHOR("Yuan Mu");
+MODULE_DESCRIPTION("w83793 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83793_init);
+module_exit(sensors_w83793_exit);
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index c034820615b..af0203409dd 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -38,17 +38,6 @@ config I2C_ALGOPCA
This support is also available as a module. If so, the module
will be called i2c-algo-pca.
-config I2C_ALGOITE
- tristate "ITE I2C Algorithm"
- depends on MIPS_ITE8172 && I2C
- help
- This supports the use of the ITE8172 I2C interface found on some MIPS
- systems. Say Y if you have one of these. You should also say Y for
- the ITE I2C peripheral driver support below.
-
- This support is also available as a module. If so, the module
- will be called i2c-algo-ite.
-
config I2C_ALGO8XX
tristate "MPC8xx CPM I2C interface"
depends on 8xx && I2C
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
index 208be04a3db..cac1051bd4f 100644
--- a/drivers/i2c/algos/Makefile
+++ b/drivers/i2c/algos/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
-obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 21c36bfb5e6..95aa5395a5b 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -540,15 +540,7 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
return i2c_add_adapter(adap);
}
-
-
-int i2c_bit_del_bus(struct i2c_adapter *adap)
-{
- return i2c_del_adapter(adap);
-}
-
EXPORT_SYMBOL(i2c_bit_add_bus);
-EXPORT_SYMBOL(i2c_bit_del_bus);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
deleted file mode 100644
index 70d8eefb5ef..00000000000
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- -------------------------------------------------------------------------
- i2c-algo-ite.c i2c driver algorithms for ITE adapters
-
- Hai-Pao Fan, MontaVista Software, Inc.
- hpfan@mvista.com or source@mvista.com
-
- Copyright 2000 MontaVista Software Inc.
-
- ---------------------------------------------------------------------------
- This file was highly leveraged from i2c-algo-pcf.c, which was created
- by Simon G. Vogl and Hans Berglund:
-
-
- Copyright (C) 1995-1997 Simon G. Vogl
- 1998-2000 Hans Berglund
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You 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. */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
- Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
- <mbailey@littlefeet-inc.com> */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-ite.h>
-#include "i2c-algo-ite.h"
-
-#define PM_DSR IT8172_PCI_IO_BASE + IT_PM_DSR
-#define PM_IBSR IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04
-#define GPIO_CCR IT8172_PCI_IO_BASE + IT_GPCCR
-
-#define DEB2(x) if (i2c_debug>=2) x
-#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
-#define DEF_TIMEOUT 16
-
-
-/* module parameters:
- */
-static int i2c_debug;
-static int iic_test; /* see if the line-setting functions work */
-
-/* --- setting states on the bus with the right timing: --------------- */
-
-#define get_clock(adap) adap->getclock(adap->data)
-#define iic_outw(adap, reg, val) adap->setiic(adap->data, reg, val)
-#define iic_inw(adap, reg) adap->getiic(adap->data, reg)
-
-
-/* --- other auxiliary functions -------------------------------------- */
-
-static void iic_start(struct i2c_algo_iic_data *adap)
-{
- iic_outw(adap,ITE_I2CHCR,ITE_CMD);
-}
-
-static void iic_stop(struct i2c_algo_iic_data *adap)
-{
- iic_outw(adap,ITE_I2CHCR,0);
- iic_outw(adap,ITE_I2CHSR,ITE_I2CHSR_TDI);
-}
-
-static void iic_reset(struct i2c_algo_iic_data *adap)
-{
- iic_outw(adap, PM_IBSR, iic_inw(adap, PM_IBSR) | 0x80);
-}
-
-
-static int wait_for_bb(struct i2c_algo_iic_data *adap)
-{
- int timeout = DEF_TIMEOUT;
- short status;
-
- status = iic_inw(adap, ITE_I2CHSR);
-#ifndef STUB_I2C
- while (timeout-- && (status & ITE_I2CHSR_HB)) {
- udelay(1000); /* How much is this? */
- status = iic_inw(adap, ITE_I2CHSR);
- }
-#endif
- if (timeout<=0) {
- printk(KERN_ERR "Timeout, host is busy\n");
- iic_reset(adap);
- }
- return(timeout<=0);
-}
-
-/* After we issue a transaction on the IIC bus, this function
- * is called. It puts this process to sleep until we get an interrupt from
- * from the controller telling us that the transaction we requested in complete.
- */
-static int wait_for_pin(struct i2c_algo_iic_data *adap, short *status) {
-
- int timeout = DEF_TIMEOUT;
-
- timeout = wait_for_bb(adap);
- if (timeout) {
- DEB2(printk("Timeout waiting for host not busy\n");)
- return -EIO;
- }
- timeout = DEF_TIMEOUT;
-
- *status = iic_inw(adap, ITE_I2CHSR);
-#ifndef STUB_I2C
- while (timeout-- && !(*status & ITE_I2CHSR_TDI)) {
- adap->waitforpin();
- *status = iic_inw(adap, ITE_I2CHSR);
- }
-#endif
- if (timeout <= 0)
- return(-1);
- else
- return(0);
-}
-
-static int wait_for_fe(struct i2c_algo_iic_data *adap, short *status)
-{
- int timeout = DEF_TIMEOUT;
-
- *status = iic_inw(adap, ITE_I2CFSR);
-#ifndef STUB_I2C
- while (timeout-- && (*status & ITE_I2CFSR_FE)) {
- udelay(1000);
- iic_inw(adap, ITE_I2CFSR);
- }
-#endif
- if (timeout <= 0)
- return(-1);
- else
- return(0);
-}
-
-static int iic_init (struct i2c_algo_iic_data *adap)
-{
- short i;
-
- /* Clear bit 7 to set I2C to normal operation mode */
- i=iic_inw(adap, PM_DSR)& 0xff7f;
- iic_outw(adap, PM_DSR, i);
-
- /* set IT_GPCCR port C bit 2&3 as function 2 */
- i = iic_inw(adap, GPIO_CCR) & 0xfc0f;
- iic_outw(adap,GPIO_CCR,i);
-
- /* Clear slave address/sub-address */
- iic_outw(adap,ITE_I2CSAR, 0);
- iic_outw(adap,ITE_I2CSSAR, 0);
-
- /* Set clock counter register */
- iic_outw(adap,ITE_I2CCKCNT, get_clock(adap));
-
- /* Set START/reSTART/STOP time registers */
- iic_outw(adap,ITE_I2CSHDR, 0x0a);
- iic_outw(adap,ITE_I2CRSUR, 0x0a);
- iic_outw(adap,ITE_I2CPSUR, 0x0a);
-
- /* Enable interrupts on completing the current transaction */
- iic_outw(adap,ITE_I2CHCR, ITE_I2CHCR_IE | ITE_I2CHCR_HCE);
-
- /* Clear transfer count */
- iic_outw(adap,ITE_I2CFBCR, 0x0);
-
- DEB2(printk("iic_init: Initialized IIC on ITE 0x%x\n",
- iic_inw(adap, ITE_I2CHSR)));
- return 0;
-}
-
-
-/*
- * Sanity check for the adapter hardware - check the reaction of
- * the bus lines only if it seems to be idle.
- */
-static int test_bus(struct i2c_algo_iic_data *adap, char *name) {
-#if 0
- int scl,sda;
- sda=getsda(adap);
- if (adap->getscl==NULL) {
- printk("test_bus: Warning: Adapter can't read from clock line - skipping test.\n");
- return 0;
- }
- scl=getscl(adap);
- printk("test_bus: Adapter: %s scl: %d sda: %d -- testing...\n",
- name,getscl(adap),getsda(adap));
- if (!scl || !sda ) {
- printk("test_bus: %s seems to be busy.\n",adap->name);
- goto bailout;
- }
- sdalo(adap);
- printk("test_bus:1 scl: %d sda: %d\n", getscl(adap),
- getsda(adap));
- if ( 0 != getsda(adap) ) {
- printk("test_bus: %s SDA stuck high!\n",name);
- sdahi(adap);
- goto bailout;
- }
- if ( 0 == getscl(adap) ) {
- printk("test_bus: %s SCL unexpected low while pulling SDA low!\n",
- name);
- goto bailout;
- }
- sdahi(adap);
- printk("test_bus:2 scl: %d sda: %d\n", getscl(adap),
- getsda(adap));
- if ( 0 == getsda(adap) ) {
- printk("test_bus: %s SDA stuck low!\n",name);
- sdahi(adap);
- goto bailout;
- }
- if ( 0 == getscl(adap) ) {
- printk("test_bus: %s SCL unexpected low while SDA high!\n",
- adap->name);
- goto bailout;
- }
- scllo(adap);
- printk("test_bus:3 scl: %d sda: %d\n", getscl(adap),
- getsda(adap));
- if ( 0 != getscl(adap) ) {
-
- sclhi(adap);
- goto bailout;
- }
- if ( 0 == getsda(adap) ) {
- printk("test_bus: %s SDA unexpected low while pulling SCL low!\n",
- name);
- goto bailout;
- }
- sclhi(adap);
- printk("test_bus:4 scl: %d sda: %d\n", getscl(adap),
- getsda(adap));
- if ( 0 == getscl(adap) ) {
- printk("test_bus: %s SCL stuck low!\n",name);
- sclhi(adap);
- goto bailout;
- }
- if ( 0 == getsda(adap) ) {
- printk("test_bus: %s SDA unexpected low while SCL high!\n",
- name);
- goto bailout;
- }
- printk("test_bus: %s passed test.\n",name);
- return 0;
-bailout:
- sdahi(adap);
- sclhi(adap);
- return -ENODEV;
-#endif
- return (0);
-}
-
-/* ----- Utility functions
- */
-
-
-/* Verify the device we want to talk to on the IIC bus really exists. */
-static inline int try_address(struct i2c_algo_iic_data *adap,
- unsigned int addr, int retries)
-{
- int i, ret = -1;
- short status;
-
- for (i=0;i<retries;i++) {
- iic_outw(adap, ITE_I2CSAR, addr);
- iic_start(adap);
- if (wait_for_pin(adap, &status) == 0) {
- if ((status & ITE_I2CHSR_DNE) == 0) {
- iic_stop(adap);
- iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
- ret=1;
- break; /* success! */
- }
- }
- iic_stop(adap);
- udelay(adap->udelay);
- }
- DEB2(if (i) printk("try_address: needed %d retries for 0x%x\n",i,
- addr));
- return ret;
-}
-
-
-static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,
- int count)
-{
- struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
- int wrcount=0, timeout;
- short status;
- int loops, remainder, i, j;
- union {
- char byte[2];
- unsigned short word;
- } tmp;
-
- iic_outw(adap, ITE_I2CSSAR, (unsigned short)buf[wrcount++]);
- count--;
- if (count == 0)
- return -EIO;
-
- loops = count / 32; /* 32-byte FIFO */
- remainder = count % 32;
-
- if(loops) {
- for(i=0; i<loops; i++) {
-
- iic_outw(adap, ITE_I2CFBCR, 32);
- for(j=0; j<32/2; j++) {
- tmp.byte[1] = buf[wrcount++];
- tmp.byte[0] = buf[wrcount++];
- iic_outw(adap, ITE_I2CFDR, tmp.word);
- }
-
- /* status FIFO overrun */
- iic_inw(adap, ITE_I2CFSR);
- iic_inw(adap, ITE_I2CFBCR);
-
- iic_outw(adap, ITE_I2CHCR, ITE_WRITE); /* Issue WRITE command */
-
- /* Wait for transmission to complete */
- timeout = wait_for_pin(adap, &status);
- if(timeout) {
- iic_stop(adap);
- printk("iic_sendbytes: %s write timeout.\n", i2c_adap->name);
- return -EREMOTEIO; /* got a better one ?? */
- }
- if (status & ITE_I2CHSR_DB) {
- iic_stop(adap);
- printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name);
- return -EREMOTEIO; /* got a better one ?? */
- }
- }
- }
- if(remainder) {
- iic_outw(adap, ITE_I2CFBCR, remainder);
- for(i=0; i<remainder/2; i++) {
- tmp.byte[1] = buf[wrcount++];
- tmp.byte[0] = buf[wrcount++];
- iic_outw(adap, ITE_I2CFDR, tmp.word);
- }
-
- /* status FIFO overrun */
- iic_inw(adap, ITE_I2CFSR);
- iic_inw(adap, ITE_I2CFBCR);
-
- iic_outw(adap, ITE_I2CHCR, ITE_WRITE); /* Issue WRITE command */
-
- timeout = wait_for_pin(adap, &status);
- if(timeout) {
- iic_stop(adap);
- printk("iic_sendbytes: %s write timeout.\n", i2c_adap->name);
- return -EREMOTEIO; /* got a better one ?? */
- }
-#ifndef STUB_I2C
- if (status & ITE_I2CHSR_DB) {
- iic_stop(adap);
- printk("iic_sendbytes: %s write error - no ack.\n", i2c_adap->name);
- return -EREMOTEIO; /* got a better one ?? */
- }
-#endif
- }
- iic_stop(adap);
- return wrcount;
-}
-
-
-static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count,
- int sread)
-{
- int rdcount=0, i, timeout;
- short status;
- struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
- int loops, remainder, j;
- union {
- char byte[2];
- unsigned short word;
- } tmp;
-
- loops = count / 32; /* 32-byte FIFO */
- remainder = count % 32;
-
- if(loops) {
- for(i=0; i<loops; i++) {
- iic_outw(adap, ITE_I2CFBCR, 32);
- if (sread)
- iic_outw(adap, ITE_I2CHCR, ITE_SREAD);
- else
- iic_outw(adap, ITE_I2CHCR, ITE_READ); /* Issue READ command */
-
- timeout = wait_for_pin(adap, &status);
- if(timeout) {
- iic_stop(adap);
- printk("iic_readbytes: %s read timeout.\n", i2c_adap->name);
- return (-1);
- }
-#ifndef STUB_I2C
- if (status & ITE_I2CHSR_DB) {
- iic_stop(adap);
- printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name);
- return (-1);
- }
-#endif
-
- timeout = wait_for_fe(adap, &status);
- if(timeout) {
- iic_stop(adap);
- printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name);
- return (-1);
- }
-
- for(j=0; j<32/2; j++) {
- tmp.word = iic_inw(adap, ITE_I2CFDR);
- buf[rdcount++] = tmp.byte[1];
- buf[rdcount++] = tmp.byte[0];
- }
-
- /* status FIFO underrun */
- iic_inw(adap, ITE_I2CFSR);
-
- }
- }
-
-
- if(remainder) {
- remainder=(remainder+1)/2 * 2;
- iic_outw(adap, ITE_I2CFBCR, remainder);
- if (sread)
- iic_outw(adap, ITE_I2CHCR, ITE_SREAD);
- else
- iic_outw(adap, ITE_I2CHCR, ITE_READ); /* Issue READ command */
-
- timeout = wait_for_pin(adap, &status);
- if(timeout) {
- iic_stop(adap);
- printk("iic_readbytes: %s read timeout.\n", i2c_adap->name);
- return (-1);
- }
-#ifndef STUB_I2C
- if (status & ITE_I2CHSR_DB) {
- iic_stop(adap);
- printk("iic_readbytes: %s read error - no ack.\n", i2c_adap->name);
- return (-1);
- }
-#endif
- timeout = wait_for_fe(adap, &status);
- if(timeout) {
- iic_stop(adap);
- printk("iic_readbytes: %s FIFO is empty\n", i2c_adap->name);
- return (-1);
- }
-
- for(i=0; i<(remainder+1)/2; i++) {
- tmp.word = iic_inw(adap, ITE_I2CFDR);
- buf[rdcount++] = tmp.byte[1];
- buf[rdcount++] = tmp.byte[0];
- }
-
- /* status FIFO underrun */
- iic_inw(adap, ITE_I2CFSR);
-
- }
-
- iic_stop(adap);
- return rdcount;
-}
-
-
-/* This function implements combined transactions. Combined
- * transactions consist of combinations of reading and writing blocks of data.
- * Each transfer (i.e. a read or a write) is separated by a repeated start
- * condition.
- */
-#if 0
-static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
- int i;
- struct i2c_msg *pmsg;
- int ret;
-
- DEB2(printk("Beginning combined transaction\n"));
-
- for(i=0; i<(num-1); i++) {
- pmsg = &msgs[i];
- if(pmsg->flags & I2C_M_RD) {
- DEB2(printk(" This one is a read\n"));
- ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER);
- }
- else if(!(pmsg->flags & I2C_M_RD)) {
- DEB2(printk("This one is a write\n"));
- ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_COMBINED_XFER);
- }
- }
- /* Last read or write segment needs to be terminated with a stop */
- pmsg = &msgs[i];
-
- if(pmsg->flags & I2C_M_RD) {
- DEB2(printk("Doing the last read\n"));
- ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
- }
- else if(!(pmsg->flags & I2C_M_RD)) {
- DEB2(printk("Doing the last write\n"));
- ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
- }
-
- return ret;
-}
-#endif
-
-
-/* Whenever we initiate a transaction, the first byte clocked
- * onto the bus after the start condition is the address (7 bit) of the
- * device we want to talk to. This function manipulates the address specified
- * so that it makes sense to the hardware when written to the IIC peripheral.
- *
- * Note: 10 bit addresses are not supported in this driver, although they are
- * supported by the hardware. This functionality needs to be implemented.
- */
-static inline int iic_doAddress(struct i2c_algo_iic_data *adap,
- struct i2c_msg *msg, int retries)
-{
- unsigned short flags = msg->flags;
- unsigned int addr;
- int ret;
-
-/* Ten bit addresses not supported right now */
- if ( (flags & I2C_M_TEN) ) {
-#if 0
- addr = 0xf0 | (( msg->addr >> 7) & 0x03);
- DEB2(printk("addr0: %d\n",addr));
- ret = try_address(adap, addr, retries);
- if (ret!=1) {
- printk("iic_doAddress: died at extended address code.\n");
- return -EREMOTEIO;
- }
- iic_outw(adap,msg->addr & 0x7f);
- if (ret != 1) {
- printk("iic_doAddress: died at 2nd address code.\n");
- return -EREMOTEIO;
- }
- if ( flags & I2C_M_RD ) {
- i2c_repstart(adap);
- addr |= 0x01;
- ret = try_address(adap, addr, retries);
- if (ret!=1) {
- printk("iic_doAddress: died at extended address code.\n");
- return -EREMOTEIO;
- }
- }
-#endif
- } else {
-
- addr = ( msg->addr << 1 );
-
-#if 0
- if (flags & I2C_M_RD )
- addr |= 1;
- if (flags & I2C_M_REV_DIR_ADDR )
- addr ^= 1;
-#endif
-
- if (iic_inw(adap, ITE_I2CSAR) != addr) {
- iic_outw(adap, ITE_I2CSAR, addr);
- ret = try_address(adap, addr, retries);
- if (ret!=1) {
- printk("iic_doAddress: died at address code.\n");
- return -EREMOTEIO;
- }
- }
-
- }
-
- return 0;
-}
-
-
-/* Description: Prepares the controller for a transaction (clearing status
- * registers, data buffers, etc), and then calls either iic_readbytes or
- * iic_sendbytes to do the actual transaction.
- *
- * still to be done: Before we issue a transaction, we should
- * 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,
- int num)
-{
- struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
- struct i2c_msg *pmsg;
- int i = 0;
- int ret, timeout;
-
- pmsg = &msgs[i];
-
- if(!pmsg->len) {
- DEB2(printk("iic_xfer: read/write length is 0\n");)
- return -EIO;
- }
- if(!(pmsg->flags & I2C_M_RD) && (!(pmsg->len)%2) ) {
- DEB2(printk("iic_xfer: write buffer length is not odd\n");)
- return -EIO;
- }
-
- /* Wait for any pending transfers to complete */
- timeout = wait_for_bb(adap);
- if (timeout) {
- DEB2(printk("iic_xfer: Timeout waiting for host not busy\n");)
- return -EIO;
- }
-
- /* Flush FIFO */
- iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
-
- /* Load address */
- ret = iic_doAddress(adap, pmsg, i2c_adap->retries);
- if (ret)
- return -EIO;
-
-#if 0
- /* Combined transaction (read and write) */
- if(num > 1) {
- DEB2(printk("iic_xfer: Call combined transaction\n"));
- ret = iic_combined_transaction(i2c_adap, msgs, num);
- }
-#endif
-
- DEB3(printk("iic_xfer: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
- i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
-
- if(pmsg->flags & I2C_M_RD) /* Read */
- ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, 0);
- else { /* Write */
- udelay(1000);
- ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len);
- }
-
- if (ret != pmsg->len)
- DEB3(printk("iic_xfer: error or fail on read/write %d bytes.\n",ret));
- else
- DEB3(printk("iic_xfer: read/write %d bytes.\n",ret));
-
- return ret;
-}
-
-
-/* Implements device specific ioctls. Higher level ioctls can
- * be found in i2c-core.c and are typical of any i2c controller (specifying
- * slave address, timeouts, etc). These ioctls take advantage of any hardware
- * features built into the controller for which this algorithm-adapter set
- * was written. These ioctls allow you to take control of the data and clock
- * lines and set the either high or low,
- * similar to a GPIO pin.
- */
-static int algo_control(struct i2c_adapter *adapter,
- unsigned int cmd, unsigned long arg)
-{
-
- struct i2c_algo_iic_data *adap = adapter->algo_data;
- struct i2c_iic_msg s_msg;
- char *buf;
- int ret;
-
- if (cmd == I2C_SREAD) {
- if(copy_from_user(&s_msg, (struct i2c_iic_msg *)arg,
- sizeof(struct i2c_iic_msg)))
- return -EFAULT;
- buf = kmalloc(s_msg.len, GFP_KERNEL);
- if (buf== NULL)
- return -ENOMEM;
-
- /* Flush FIFO */
- iic_outw(adap, ITE_I2CFCR, ITE_I2CFCR_FLUSH);
-
- /* Load address */
- iic_outw(adap, ITE_I2CSAR,s_msg.addr<<1);
- iic_outw(adap, ITE_I2CSSAR,s_msg.waddr & 0xff);
-
- ret = iic_readbytes(adapter, buf, s_msg.len, 1);
- if (ret>=0) {
- if(copy_to_user( s_msg.buf, buf, s_msg.len) )
- ret = -EFAULT;
- }
- kfree(buf);
- }
- return 0;
-}
-
-
-static u32 iic_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
- I2C_FUNC_PROTOCOL_MANGLING;
-}
-
-/* -----exported algorithm data: ------------------------------------- */
-
-static struct i2c_algorithm iic_algo = {
- .master_xfer = iic_xfer,
- .algo_control = algo_control, /* ioctl */
- .functionality = iic_func,
-};
-
-
-/*
- * registering functions to load algorithms at runtime
- */
-int i2c_iic_add_bus(struct i2c_adapter *adap)
-{
- struct i2c_algo_iic_data *iic_adap = adap->algo_data;
-
- if (iic_test) {
- int ret = test_bus(iic_adap, adap->name);
- if (ret<0)
- return -ENODEV;
- }
-
- DEB2(printk("i2c-algo-ite: hw routines for %s registered.\n",
- adap->name));
-
- /* register new adapter to i2c module... */
- adap->algo = &iic_algo;
-
- adap->timeout = 100; /* default values, should */
- adap->retries = 3; /* be replaced by defines */
- adap->flags = 0;
-
- iic_init(iic_adap);
- return i2c_add_adapter(adap);
-}
-
-
-int i2c_iic_del_bus(struct i2c_adapter *adap)
-{
- int res;
- if ((res = i2c_del_adapter(adap)) < 0)
- return res;
- DEB2(printk("i2c-algo-ite: adapter unregistered: %s\n",adap->name));
-
- return 0;
-}
-
-
-int __init i2c_algo_iic_init (void)
-{
- printk(KERN_INFO "ITE iic (i2c) algorithm module\n");
- return 0;
-}
-
-
-void i2c_algo_iic_exit(void)
-{
- return;
-}
-
-
-EXPORT_SYMBOL(i2c_iic_add_bus);
-EXPORT_SYMBOL(i2c_iic_del_bus);
-
-/* The MODULE_* macros resolve to nothing if MODULES is not defined
- * when this file is compiled.
- */
-MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
-MODULE_DESCRIPTION("ITE iic algorithm");
-MODULE_LICENSE("GPL");
-
-module_param(iic_test, bool, 0);
-module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
-MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
-
-
-/* This function resolves to init_module (the function invoked when a module
- * is loaded via insmod) when this file is compiled with MODULES defined.
- * Otherwise (i.e. if you want this driver statically linked to the kernel),
- * a pointer to this function is stored in a table and called
- * during the initialization of the kernel (in do_basic_setup in /init/main.c)
- *
- * All this functionality is complements of the macros defined in linux/init.h
- */
-module_init(i2c_algo_iic_init);
-
-
-/* If MODULES is defined when this file is compiled, then this function will
- * resolved to cleanup_module.
- */
-module_exit(i2c_algo_iic_exit);
diff --git a/drivers/i2c/algos/i2c-algo-ite.h b/drivers/i2c/algos/i2c-algo-ite.h
deleted file mode 100644
index a8ca3c9b546..00000000000
--- a/drivers/i2c/algos/i2c-algo-ite.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- --------------------------------------------------------------------
- i2c-ite.h: Global defines for the I2C controller on board the
- ITE MIPS processor.
- --------------------------------------------------------------------
- Hai-Pao Fan, MontaVista Software, Inc.
- hpfan@mvista.com or source@mvista.com
-
- Copyright 2001 MontaVista Software Inc.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef I2C_ITE_H
-#define I2C_ITE_H 1
-
-#include <asm/it8172/it8172.h>
-
-/* I2C Registers */
-#define ITE_I2CHCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x30
-#define ITE_I2CHSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x34
-#define ITE_I2CSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x38
-#define ITE_I2CSSAR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x3c
-#define ITE_I2CCKCNT IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x48
-#define ITE_I2CSHDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x4c
-#define ITE_I2CRSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x50
-#define ITE_I2CPSUR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x54
-
-#define ITE_I2CFDR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x70
-#define ITE_I2CFBCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x74
-#define ITE_I2CFCR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x78
-#define ITE_I2CFSR IT8172_PCI_IO_BASE + IT_I2C_BASE + 0x7c
-
-
-/* Host Control Register ITE_I2CHCR */
-#define ITE_I2CHCR_HCE 0x01 /* Enable I2C Host Controller */
-#define ITE_I2CHCR_IE 0x02 /* Enable the interrupt after completing
- the current transaction */
-#define ITE_I2CHCR_CP_W 0x00 /* bit2-4 000 - Write */
-#define ITE_I2CHCR_CP_R 0x08 /* 010 - Current address read */
-#define ITE_I2CHCR_CP_S 0x10 /* 100 - Sequential read */
-#define ITE_I2CHCR_ST 0x20 /* Initiates the I2C host controller to execute
- the command and send the data programmed in
- all required registers to I2C bus */
-#define ITE_CMD ITE_I2CHCR_HCE | ITE_I2CHCR_IE | ITE_I2CHCR_ST
-#define ITE_WRITE ITE_CMD | ITE_I2CHCR_CP_W
-#define ITE_READ ITE_CMD | ITE_I2CHCR_CP_R
-#define ITE_SREAD ITE_CMD | ITE_I2CHCR_CP_S
-
-/* Host Status Register ITE_I2CHSR */
-#define ITE_I2CHSR_DB 0x01 /* Device is busy, receives NACK response except
- in the first and last bytes */
-#define ITE_I2CHSR_DNE 0x02 /* Target address on I2C bus does not exist */
-#define ITE_I2CHSR_TDI 0x04 /* R/W Transaction on I2C bus was completed */
-#define ITE_I2CHSR_HB 0x08 /* Host controller is processing transactions */
-#define ITE_I2CHSR_FER 0x10 /* Error occurs in the FIFO */
-
-/* Slave Address Register ITE_I2CSAR */
-#define ITE_I2CSAR_SA_MASK 0xfe /* Target I2C device address */
-#define ITE_I2CSAR_ASO 0x0100 /* Output 1/0 to I2CAS port when the
- next slave address is addressed */
-
-/* Slave Sub-address Register ITE_I2CSSAR */
-#define ITE_I2CSSAR_SUBA_MASK 0xff /* Target I2C device sub-address */
-
-/* Clock Counter Register ITE_I2CCKCNT */
-#define ITE_I2CCKCNT_STOP 0x00 /* stop I2C clock */
-#define ITE_I2CCKCNT_HPCC_MASK 0x7f /* SCL high period counter */
-#define ITE_I2CCKCNT_LPCC_MASK 0x7f00 /* SCL low period counter */
-
-/* START Hold Time Register ITE_I2CSHDR */
-/* value is counted based on 16 MHz internal clock */
-#define ITE_I2CSHDR_FM 0x0a /* START condition at fast mode */
-#define ITE_I2CSHDR_SM 0x47 /* START contition at standard mode */
-
-/* (Repeated) START Setup Time Register ITE_I2CRSUR */
-/* value is counted based on 16 MHz internal clock */
-#define ITE_I2CRSUR_FM 0x0a /* repeated START condition at fast mode */
-#define ITE_I2CRSUR_SM 0x50 /* repeated START condition at standard mode */
-
-/* STOP setup Time Register ITE_I2CPSUR */
-
-/* FIFO Data Register ITE_I2CFDR */
-#define ITE_I2CFDR_MASK 0xff
-
-/* FIFO Byte Count Register ITE_I2CFBCR */
-#define ITE_I2CFBCR_MASK 0x3f
-
-/* FIFO Control Register ITE_I2CFCR */
-#define ITE_I2CFCR_FLUSH 0x01 /* Flush FIFO and reset the FIFO point
- and I2CFSR */
-/* FIFO Status Register ITE_I2CFSR */
-#define ITE_I2CFSR_FO 0x01 /* FIFO is overrun when write */
-#define ITE_I2CFSR_FU 0x02 /* FIFO is underrun when read */
-#define ITE_I2CFSR_FF 0x04 /* FIFO is full when write */
-#define ITE_I2CFSR_FE 0x08 /* FIFO is empty when read */
-
-#endif /* I2C_ITE_H */
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 9081c9fbcd2..36fdf971f08 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -381,14 +381,7 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
return rval;
}
-
-int i2c_pca_del_bus(struct i2c_adapter *adap)
-{
- return i2c_del_adapter(adap);
-}
-
EXPORT_SYMBOL(i2c_pca_add_bus);
-EXPORT_SYMBOL(i2c_pca_del_bus);
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 3b200339896..ecb2c2d7d54 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -486,15 +486,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
return rval;
}
-
-
-int i2c_pcf_del_bus(struct i2c_adapter *adap)
-{
- return i2c_del_adapter(adap);
-}
-
EXPORT_SYMBOL(i2c_pcf_add_bus);
-EXPORT_SYMBOL(i2c_pcf_del_bus);
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index 490d99997fd..ac2d5053078 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -171,15 +171,7 @@ int i2c_sgi_add_bus(struct i2c_adapter *adap)
return i2c_add_adapter(adap);
}
-
-
-int i2c_sgi_del_bus(struct i2c_adapter *adap)
-{
- return i2c_del_adapter(adap);
-}
-
EXPORT_SYMBOL(i2c_sgi_add_bus);
-EXPORT_SYMBOL(i2c_sgi_del_bus);
MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 90f91d039ee..9367c4cfe93 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -74,6 +74,13 @@ config I2C_AMD8111
This driver can also be built as a module. If so, the module
will be called i2c-amd8111.
+config I2C_AT91
+ tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
+ depends on I2C && ARCH_AT91 && EXPERIMENTAL
+ help
+ This supports the use of the I2C interface on Atmel AT91
+ processors.
+
config I2C_AU1550
tristate "Au1550/Au1200 SMBus interface"
depends on I2C && (SOC_AU1550 || SOC_AU1200)
@@ -209,18 +216,6 @@ config I2C_ISA
tristate
depends on I2C
-config I2C_ITE
- tristate "ITE I2C Adapter"
- depends on I2C && MIPS_ITE8172
- select I2C_ALGOITE
- help
- This supports the ITE8172 I2C peripheral found on some MIPS
- systems. Say Y if you have one of these. You should also say Y for
- the ITE I2C driver algorithm support above.
-
- This support is also available as a module. If so, the module
- will be called i2c-ite.
-
config I2C_IXP4XX
tristate "IXP4xx GPIO-Based I2C Interface"
depends on I2C && ARCH_IXP4XX
@@ -481,6 +476,17 @@ config I2C_STUB
If you don't know what to do here, definitely say N.
+config I2C_VERSATILE
+ tristate "ARM Versatile/Realview I2C bus support"
+ depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
+ select I2C_ALGOBIT
+ help
+ Say yes if you want to support the I2C serial bus on ARMs Versatile
+ range of platforms.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-versatile.
+
config I2C_VIA
tristate "VIA 82C586B"
depends on I2C && PCI && EXPERIMENTAL
@@ -548,4 +554,14 @@ config I2C_MV64XXX
This driver can also be built as a module. If so, the module
will be called i2c-mv64xxx.
+config I2C_PNX
+ tristate "I2C bus support for Philips PNX targets"
+ depends on ARCH_PNX4008 && I2C
+ help
+ This driver supports the Philips IP3204 I2C IP block master and/or
+ slave controller
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-pnx.
+
endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 493c87289b6..37196c1d079 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
+obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
@@ -16,7 +17,6 @@ obj-$(CONFIG_I2C_I810) += i2c-i810.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_ISA) += i2c-isa.o
-obj-$(CONFIG_I2C_ITE) += i2c-ite.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
@@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
+obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
@@ -39,6 +40,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
+obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_VIA) += i2c-via.o
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 33fbb47100a..8e1e3f8e40a 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -2,7 +2,7 @@
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
*
* Copyright (C) 2004 Patrick Mochel
- * 2005 Rudolf Marek <r.marek@sh.cvut.cz>
+ * 2005 Rudolf Marek <r.marek@assembler.cz>
*
* The 1563 southbridge is deceptively similar to the 1533, with a
* few notable exceptions. One of those happens to be the fact they
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
new file mode 100644
index 00000000000..67f91bdda08
--- /dev/null
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -0,0 +1,325 @@
+/*
+ i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
+
+ Copyright (C) 2004 Rick Bronson
+ Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
+
+ Borrowed heavily from original work by:
+ Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+*/
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/at91_twi.h>
+#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+
+#define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */
+
+
+static struct clk *twi_clk;
+static void __iomem *twi_base;
+
+#define at91_twi_read(reg) __raw_readl(twi_base + (reg))
+#define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg))
+
+
+/*
+ * Initialize the TWI hardware registers.
+ */
+static void __devinit at91_twi_hwinit(void)
+{
+ unsigned long cdiv, ckdiv;
+
+ at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */
+ at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */
+ at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); /* Set Master mode */
+
+ /* Calcuate clock dividers */
+ cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
+ cdiv = cdiv + 1; /* round up */
+ ckdiv = 0;
+ while (cdiv > 255) {
+ ckdiv++;
+ cdiv = cdiv >> 1;
+ }
+
+ if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */
+ if (ckdiv > 5) {
+ printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
+ ckdiv = 5;
+ }
+ }
+
+ at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
+}
+
+/*
+ * Poll the i2c status register until the specified bit is set.
+ * Returns 0 if timed out (100 msec).
+ */
+static short at91_poll_status(unsigned long bit)
+{
+ int loop_cntr = 10000;
+
+ do {
+ udelay(10);
+ } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
+
+ return (loop_cntr > 0);
+}
+
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+ /* Send Start */
+ at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
+
+ /* Read data */
+ while (length--) {
+ if (!length) /* need to send Stop before reading last byte */
+ at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
+ if (!at91_poll_status(AT91_TWI_RXRDY)) {
+ dev_dbg(&adap->dev, "RXRDY timeout\n");
+ return -ETIMEDOUT;
+ }
+ *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
+ }
+
+ return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+ /* Load first byte into transmitter */
+ at91_twi_write(AT91_TWI_THR, *buf++);
+
+ /* Send Start */
+ at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
+
+ do {
+ if (!at91_poll_status(AT91_TWI_TXRDY)) {
+ dev_dbg(&adap->dev, "TXRDY timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ length--; /* byte was transmitted */
+
+ if (length > 0) /* more data to send? */
+ at91_twi_write(AT91_TWI_THR, *buf++);
+ } while (length);
+
+ /* Send Stop */
+ at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
+
+ return 0;
+}
+
+/*
+ * Generic i2c master transfer entrypoint.
+ *
+ * Note: We do not use Atmel's feature of storing the "internal device address".
+ * Instead the "internal device address" has to be written using a seperate
+ * i2c message.
+ * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
+ */
+static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
+{
+ int i, ret;
+
+ dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
+
+ for (i = 0; i < num; i++) {
+ dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+ pmsg->flags & I2C_M_RD ? "read" : "writ",
+ pmsg->len, pmsg->len > 1 ? "s" : "",
+ pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
+
+ at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
+ | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
+
+ if (pmsg->len && pmsg->buf) { /* sanity check */
+ if (pmsg->flags & I2C_M_RD)
+ ret = xfer_read(adap, pmsg->buf, pmsg->len);
+ else
+ ret = xfer_write(adap, pmsg->buf, pmsg->len);
+
+ if (ret)
+ return ret;
+
+ /* Wait until transfer is finished */
+ if (!at91_poll_status(AT91_TWI_TXCOMP)) {
+ dev_dbg(&adap->dev, "TXCOMP timeout\n");
+ return -ETIMEDOUT;
+ }
+ }
+ dev_dbg(&adap->dev, "transfer complete\n");
+ pmsg++; /* next message */
+ }
+ return i;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 at91_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm at91_algorithm = {
+ .master_xfer = at91_xfer,
+ .functionality = at91_func,
+};
+
+/*
+ * Main initialization routine.
+ */
+static int __devinit at91_i2c_probe(struct platform_device *pdev)
+{
+ struct i2c_adapter *adapter;
+ struct resource *res;
+ int rc;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!request_mem_region(res->start, res->end - res->start + 1, "at91_i2c"))
+ return -EBUSY;
+
+ twi_base = ioremap(res->start, res->end - res->start + 1);
+ if (!twi_base) {
+ rc = -ENOMEM;
+ goto fail0;
+ }
+
+ twi_clk = clk_get(NULL, "twi_clk");
+ if (IS_ERR(twi_clk)) {
+ dev_err(&pdev->dev, "no clock defined\n");
+ rc = -ENODEV;
+ goto fail1;
+ }
+
+ adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ dev_err(&pdev->dev, "can't allocate inteface!\n");
+ rc = -ENOMEM;
+ goto fail2;
+ }
+ sprintf(adapter->name, "AT91");
+ adapter->algo = &at91_algorithm;
+ adapter->class = I2C_CLASS_HWMON;
+ adapter->dev.parent = &pdev->dev;
+
+ platform_set_drvdata(pdev, adapter);
+
+ clk_enable(twi_clk); /* enable peripheral clock */
+ at91_twi_hwinit(); /* initialize TWI controller */
+
+ rc = i2c_add_adapter(adapter);
+ if (rc) {
+ dev_err(&pdev->dev, "Adapter %s registration failed\n",
+ adapter->name);
+ goto fail3;
+ }
+
+ dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
+ return 0;
+
+fail3:
+ platform_set_drvdata(pdev, NULL);
+ kfree(adapter);
+ clk_disable(twi_clk);
+fail2:
+ clk_put(twi_clk);
+fail1:
+ iounmap(twi_base);
+fail0:
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ return rc;
+}
+
+static int __devexit at91_i2c_remove(struct platform_device *pdev)
+{
+ struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+ struct resource *res;
+ int rc;
+
+ rc = i2c_del_adapter(adapter);
+ platform_set_drvdata(pdev, NULL);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iounmap(twi_base);
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ clk_disable(twi_clk); /* disable peripheral clock */
+ clk_put(twi_clk);
+
+ return rc;
+}
+
+#ifdef CONFIG_PM
+
+/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
+
+static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ clk_disable(twi_clk);
+ return 0;
+}
+
+static int at91_i2c_resume(struct platform_device *pdev)
+{
+ return clk_enable(twi_clk);
+}
+
+#else
+#define at91_i2c_suspend NULL
+#define at91_i2c_resume NULL
+#endif
+
+static struct platform_driver at91_i2c_driver = {
+ .probe = at91_i2c_probe,
+ .remove = __devexit_p(at91_i2c_remove),
+ .suspend = at91_i2c_suspend,
+ .resume = at91_i2c_resume,
+ .driver = {
+ .name = "at91_i2c",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91_i2c_init(void)
+{
+ return platform_driver_register(&at91_i2c_driver);
+}
+
+static void __exit at91_i2c_exit(void)
+{
+ platform_driver_unregister(&at91_i2c_driver);
+}
+
+module_init(at91_i2c_init);
+module_exit(at91_i2c_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index a591fe685f0..83496746481 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -293,7 +293,7 @@ static int __init i2c_pcfisa_init(void)
static void i2c_pcfisa_exit(void)
{
- i2c_pcf_del_bus(&pcf_isa_ops);
+ i2c_del_adapter(&pcf_isa_ops);
if (irq > 0) {
disable_irq(irq);
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 457d48a0ab9..9832f773651 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -146,7 +146,7 @@ static int __devinit hydra_probe(struct pci_dev *dev,
static void __devexit hydra_remove(struct pci_dev *dev)
{
pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */
- i2c_bit_del_bus(&hydra_adap);
+ i2c_del_adapter(&hydra_adap);
iounmap(hydra_bit_data.data);
release_mem_region(pci_resource_start(dev, 0)+
offsetof(struct Hydra, CachePD), 4);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index c7be2fdbd86..ae625b85447 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -470,12 +470,20 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
int err;
I801_dev = dev;
- if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
- (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
+ switch (dev->device) {
+ case PCI_DEVICE_ID_INTEL_82801DB_3:
+ case PCI_DEVICE_ID_INTEL_82801EB_3:
+ case PCI_DEVICE_ID_INTEL_ESB_4:
+ case PCI_DEVICE_ID_INTEL_ICH6_16:
+ case PCI_DEVICE_ID_INTEL_ICH7_17:
+ case PCI_DEVICE_ID_INTEL_ESB2_17:
+ case PCI_DEVICE_ID_INTEL_ICH8_5:
+ case PCI_DEVICE_ID_INTEL_ICH9_6:
isich4 = 1;
- else
+ break;
+ default:
isich4 = 0;
+ }
err = pci_enable_device(dev);
if (err) {
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index b66fb6bb187..10c98bc88aa 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -219,14 +219,14 @@ static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id
return retval;
retval = i2c_bit_add_bus(&i810_ddc_adapter);
if (retval)
- i2c_bit_del_bus(&i810_i2c_adapter);
+ i2c_del_adapter(&i810_i2c_adapter);
return retval;
}
static void __devexit i810_remove(struct pci_dev *dev)
{
- i2c_bit_del_bus(&i810_ddc_adapter);
- i2c_bit_del_bus(&i810_i2c_adapter);
+ i2c_del_adapter(&i810_ddc_adapter);
+ i2c_del_adapter(&i810_i2c_adapter);
iounmap(ioaddr);
}
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 781a99c1647..1898e998702 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -680,6 +680,12 @@ static int __devinit iic_probe(struct ocp_device *ocp){
dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev);
+ if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
+ "ibm_iic")) {
+ ret = -EBUSY;
+ goto fail1;
+ }
+
if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
dev->idx);
@@ -750,6 +756,8 @@ fail:
iounmap(dev->vaddr);
fail2:
+ release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
+fail1:
ocp_set_drvdata(ocp, NULL);
kfree(dev);
return ret;
@@ -777,6 +785,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
+ release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
kfree(dev);
}
}
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
deleted file mode 100644
index f7d71869b3b..00000000000
--- a/drivers/i2c/busses/i2c-ite.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- -------------------------------------------------------------------------
- i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system
- -------------------------------------------------------------------------
- Hai-Pao Fan, MontaVista Software, Inc.
- hpfan@mvista.com or source@mvista.com
-
- Copyright 2001 MontaVista Software Inc.
-
- ----------------------------------------------------------------------------
- This file was highly leveraged from i2c-elektor.c, which was created
- by Simon G. Vogl and Hans Berglund:
-
-
- Copyright (C) 1995-97 Simon G. Vogl
- 1998-99 Hans Berglund
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You 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. */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
- Frodo Looijaard <frodol@dds.nl> */
-
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-ite.h>
-#include <linux/i2c-adap-ite.h>
-#include "../i2c-ite.h"
-
-#define DEFAULT_BASE 0x14014030
-#define ITE_IIC_IO_SIZE 0x40
-#define DEFAULT_IRQ 0
-#define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */
-#define DEFAULT_OWN 0x55
-
-static int base;
-static int irq;
-static int clock;
-static int own;
-
-static struct iic_ite gpi;
-static wait_queue_head_t iic_wait;
-static int iic_pending;
-static spinlock_t lock;
-
-/* ----- local functions ---------------------------------------------- */
-
-static void iic_ite_setiic(void *data, int ctl, short val)
-{
- unsigned long j = jiffies + 10;
-
- pr_debug(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff);
-#ifdef DEBUG
- while (time_before(jiffies, j))
- schedule();
-#endif
- outw(val,ctl);
-}
-
-static short iic_ite_getiic(void *data, int ctl)
-{
- short val;
-
- val = inw(ctl);
- pr_debug("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff);
- return (val);
-}
-
-/* Return our slave address. This is the address
- * put on the I2C bus when another master on the bus wants to address us
- * as a slave
- */
-static int iic_ite_getown(void *data)
-{
- return (gpi.iic_own);
-}
-
-
-static int iic_ite_getclock(void *data)
-{
- return (gpi.iic_clock);
-}
-
-
-/* Put this process to sleep. We will wake up when the
- * IIC controller interrupts.
- */
-static void iic_ite_waitforpin(void) {
- DEFINE_WAIT(wait);
- int timeout = 2;
- unsigned long flags;
-
- /* If interrupts are enabled (which they are), then put the process to
- * sleep. This process will be awakened by two events -- either the
- * the IIC peripheral interrupts or the timeout expires.
- * If interrupts are not enabled then delay for a reasonable amount
- * of time and return.
- */
- if (gpi.iic_irq > 0) {
- spin_lock_irqsave(&lock, flags);
- if (iic_pending == 0) {
- spin_unlock_irqrestore(&lock, flags);
- prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE);
- if (schedule_timeout(timeout*HZ)) {
- spin_lock_irqsave(&lock, flags);
- if (iic_pending == 1) {
- iic_pending = 0;
- }
- spin_unlock_irqrestore(&lock, flags);
- }
- finish_wait(&iic_wait, &wait);
- } else {
- iic_pending = 0;
- spin_unlock_irqrestore(&lock, flags);
- }
- } else {
- udelay(100);
- }
-}
-
-
-static irqreturn_t iic_ite_handler(int this_irq, void *dev_id)
-{
- spin_lock(&lock);
- iic_pending = 1;
- spin_unlock(&lock);
-
- wake_up_interruptible(&iic_wait);
-
- return IRQ_HANDLED;
-}
-
-
-/* Lock the region of memory where I/O registers exist. Request our
- * interrupt line and register its associated handler.
- */
-static int iic_hw_resrc_init(void)
-{
- if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c"))
- return -ENODEV;
-
- if (gpi.iic_irq <= 0)
- return 0;
-
- if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0)
- gpi.iic_irq = 0;
- else
- enable_irq(gpi.iic_irq);
-
- return 0;
-}
-
-
-static void iic_ite_release(void)
-{
- if (gpi.iic_irq > 0) {
- disable_irq(gpi.iic_irq);
- free_irq(gpi.iic_irq, 0);
- }
- release_region(gpi.iic_base , 2);
-}
-
-/* ------------------------------------------------------------------------
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
-static struct i2c_algo_iic_data iic_ite_data = {
- NULL,
- iic_ite_setiic,
- iic_ite_getiic,
- iic_ite_getown,
- iic_ite_getclock,
- iic_ite_waitforpin,
- 80, 80, 100, /* waits, timeout */
-};
-
-static struct i2c_adapter iic_ite_ops = {
- .owner = THIS_MODULE,
- .id = I2C_HW_I_IIC,
- .algo_data = &iic_ite_data,
- .name = "ITE IIC adapter",
-};
-
-/* Called when the module is loaded. This function starts the
- * cascade of calls up through the hierarchy of i2c modules (i.e. up to the
- * algorithm layer and into to the core layer)
- */
-static int __init iic_ite_init(void)
-{
-
- struct iic_ite *piic = &gpi;
-
- printk(KERN_INFO "Initialize ITE IIC adapter module\n");
- if (base == 0)
- piic->iic_base = DEFAULT_BASE;
- else
- piic->iic_base = base;
-
- if (irq == 0)
- piic->iic_irq = DEFAULT_IRQ;
- else
- piic->iic_irq = irq;
-
- if (clock == 0)
- piic->iic_clock = DEFAULT_CLOCK;
- else
- piic->iic_clock = clock;
-
- if (own == 0)
- piic->iic_own = DEFAULT_OWN;
- else
- piic->iic_own = own;
-
- iic_ite_data.data = (void *)piic;
- init_waitqueue_head(&iic_wait);
- spin_lock_init(&lock);
- if (iic_hw_resrc_init() == 0) {
- if (i2c_iic_add_bus(&iic_ite_ops) < 0)
- return -ENODEV;
- } else {
- return -ENODEV;
- }
- printk(KERN_INFO " found device at %#x irq %d.\n",
- piic->iic_base, piic->iic_irq);
- return 0;
-}
-
-
-static void iic_ite_exit(void)
-{
- i2c_iic_del_bus(&iic_ite_ops);
- iic_ite_release();
-}
-
-/* If modules is NOT defined when this file is compiled, then the MODULE_*
- * macros will resolve to nothing
- */
-MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
-MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter");
-MODULE_LICENSE("GPL");
-
-module_param(base, int, 0);
-module_param(irq, int, 0);
-module_param(clock, int, 0);
-module_param(own, int, 0);
-
-
-/* Called when module is loaded or when kernel is initialized.
- * If MODULES is defined when this file is compiled, then this function will
- * resolve to init_module (the function called when insmod is invoked for a
- * module). Otherwise, this function is called early in the boot, when the
- * kernel is intialized. Check out /include/init.h to see how this works.
- */
-module_init(iic_ite_init);
-
-/* Resolves to module_cleanup when MODULES is defined. */
-module_exit(iic_ite_exit);
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index dd3f4cd3aa6..efa3ecc5522 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -90,7 +90,7 @@ static int ixp2000_i2c_remove(struct platform_device *plat_dev)
platform_set_drvdata(plat_dev, NULL);
- i2c_bit_del_bus(&drv_data->adapter);
+ i2c_del_adapter(&drv_data->adapter);
kfree(drv_data);
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index 68fe863f9d5..08e89b83984 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -91,7 +91,7 @@ static int ixp4xx_i2c_remove(struct platform_device *plat_dev)
platform_set_drvdata(plat_dev, NULL);
- i2c_bit_del_bus(&drv_data->adapter);
+ i2c_del_adapter(&drv_data->adapter);
kfree(drv_data);
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index bbc8e3a7ff5..490173611d6 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -529,6 +529,8 @@ mv64xxx_i2c_probe(struct platform_device *pd)
platform_set_drvdata(pd, drv_data);
i2c_set_adapdata(&drv_data->adapter, drv_data);
+ mv64xxx_i2c_hw_init(drv_data);
+
if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0,
MV64XXX_I2C_CTLR_NAME, drv_data)) {
dev_err(&drv_data->adapter.dev,
@@ -542,8 +544,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_free_irq;
}
- mv64xxx_i2c_hw_init(drv_data);
-
return 0;
exit_free_irq:
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index e0292e414ab..ad37c10e7fe 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -35,7 +35,7 @@
nForce4 MCP55 0368
This driver supports the 2 SMBuses that are included in the MCP of the
- nForce2/3/4 chipsets.
+ nForce2/3/4/5xx chipsets.
*/
/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
@@ -52,8 +52,8 @@
#include <asm/io.h>
MODULE_LICENSE("GPL");
-MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>");
-MODULE_DESCRIPTION("nForce2 SMBus driver");
+MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@gmx.net>");
+MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");
struct nforce2_smbus {
@@ -80,9 +80,6 @@ struct nforce2_smbus {
#define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */
#define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */
#define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */
-#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data bytes */
-#define NVIDIA_SMB_ALRM_A (smbus->base + 0x25) /* alarm address */
-#define NVIDIA_SMB_ALRM_D (smbus->base + 0x26) /* 2 bytes alarm data */
#define NVIDIA_SMB_STS_DONE 0x80
#define NVIDIA_SMB_STS_ALRM 0x40
@@ -95,40 +92,17 @@ struct nforce2_smbus {
#define NVIDIA_SMB_PRTCL_BYTE 0x04
#define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06
#define NVIDIA_SMB_PRTCL_WORD_DATA 0x08
-#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a
-#define NVIDIA_SMB_PRTCL_PROC_CALL 0x0c
-#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
-#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define NVIDIA_SMB_PRTCL_PEC 0x80
static struct pci_driver nforce2_driver;
-static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size, union i2c_smbus_data *data);
-static u32 nforce2_func(struct i2c_adapter *adapter);
-
-
-static const struct i2c_algorithm smbus_algorithm = {
- .smbus_xfer = nforce2_access,
- .functionality = nforce2_func,
-};
-
-static struct i2c_adapter nforce2_adapter = {
- .owner = THIS_MODULE,
- .class = I2C_CLASS_HWMON,
- .algo = &smbus_algorithm,
-};
-
-/* Return -1 on error. See smbus.h for more information */
+/* Return -1 on error */
static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data)
{
struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec, temp;
- unsigned char len = 0; /* to keep the compiler quiet */
- int i;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
NVIDIA_SMB_PRTCL_WRITE;
@@ -163,35 +137,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
break;
- case I2C_SMBUS_BLOCK_DATA:
- outb_p(command, NVIDIA_SMB_CMD);
- if (read_write == I2C_SMBUS_WRITE) {
- len = min_t(u8, data->block[0], 32);
- outb_p(len, NVIDIA_SMB_BCNT);
- for (i = 0; i < len; i++)
- outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
- }
- protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
- break;
-
- case I2C_SMBUS_I2C_BLOCK_DATA:
- len = min_t(u8, data->block[0], 32);
- outb_p(command, NVIDIA_SMB_CMD);
- outb_p(len, NVIDIA_SMB_BCNT);
- if (read_write == I2C_SMBUS_WRITE)
- for (i = 0; i < len; i++)
- outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
- protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA;
- break;
-
- case I2C_SMBUS_PROC_CALL:
- dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
- return -1;
-
- case I2C_SMBUS_BLOCK_PROC_CALL:
- dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
- return -1;
-
default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
return -1;
@@ -227,19 +172,8 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
break;
case I2C_SMBUS_WORD_DATA:
- /* case I2C_SMBUS_PROC_CALL: not supported */
data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
break;
-
- case I2C_SMBUS_BLOCK_DATA:
- /* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */
- len = inb_p(NVIDIA_SMB_BCNT);
- len = min_t(u8, len, 32);
- case I2C_SMBUS_I2C_BLOCK_DATA:
- for (i = 0; i < len; i++)
- data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
- data->block[0] = len;
- break;
}
return 0;
@@ -250,10 +184,14 @@ static u32 nforce2_func(struct i2c_adapter *adapter)
{
/* other functionality might be possible, but is not tested */
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* |
- I2C_FUNC_SMBUS_BLOCK_DATA */;
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
}
+static struct i2c_algorithm smbus_algorithm = {
+ .smbus_xfer = nforce2_access,
+ .functionality = nforce2_func,
+};
+
static struct pci_device_id nforce2_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
@@ -267,7 +205,6 @@ static struct pci_device_id nforce2_ids[] = {
{ 0 }
};
-
MODULE_DEVICE_TABLE (pci, nforce2_ids);
@@ -291,7 +228,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
}
smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
- smbus->size = 8;
+ smbus->size = 64;
}
smbus->dev = dev;
@@ -300,7 +237,9 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
smbus->base, smbus->base+smbus->size-1, name);
return -1;
}
- smbus->adapter = nforce2_adapter;
+ smbus->adapter.owner = THIS_MODULE;
+ smbus->adapter.class = I2C_CLASS_HWMON;
+ smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
smbus->adapter.dev.parent = &dev->dev;
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index dec04da0455..bcd8367cede 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -231,8 +231,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
* 13 2 1
* 19.2 2 1
*/
- if (fclk_rate > 16000000)
- psc = (fclk_rate + 8000000) / 12000000;
+ if (fclk_rate > 12000000)
+ psc = fclk_rate / 12000000;
}
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 5eb2bd294fd..4bc42810b9a 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -163,7 +163,7 @@ static void __exit i2c_parport_exit(void)
if (adapter_parm[type].init.val)
line_set(0, &adapter_parm[type].init);
- i2c_bit_del_bus(&parport_adapter);
+ i2c_del_adapter(&parport_adapter);
release_region(base, 3);
}
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 48a829431c7..66696a40c7b 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -218,7 +218,7 @@ static void i2c_parport_detach (struct parport *port)
if (adapter_parm[type].init.val)
line_set(port, 0, &adapter_parm[type].init);
- i2c_bit_del_bus(&adapter->adapter);
+ i2c_del_adapter(&adapter->adapter);
parport_unregister_device(adapter->pdev);
if (prev)
prev->next = adapter->next;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 407840b6a26..cc6536a19ec 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -156,7 +156,7 @@ static int __init pca_isa_init(void)
static void pca_isa_exit(void)
{
- i2c_pca_del_bus(&pca_isa_ops);
+ i2c_del_adapter(&pca_isa_ops);
if (irq > 0) {
disable_irq(irq);
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
new file mode 100644
index 00000000000..17376feb1ac
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -0,0 +1,703 @@
+/*
+ * Provides I2C support for Philips PNX010x/PNX4008 boards.
+ *
+ * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
+ * Vitaly Wool <vwool@ru.mvista.com>
+ *
+ * 2004-2006 (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/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/i2c-pnx.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define I2C_PNX_TIMEOUT 10 /* msec */
+#define I2C_PNX_SPEED_KHZ 100
+#define I2C_PNX_REGION_SIZE 0x100
+#define PNX_DEFAULT_FREQ 13 /* MHz */
+
+static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
+{
+ while (timeout > 0 &&
+ (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
+ mdelay(1);
+ timeout--;
+ }
+ return (timeout <= 0);
+}
+
+static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
+{
+ while (timeout > 0 &&
+ (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
+ mdelay(1);
+ timeout--;
+ }
+ return (timeout <= 0);
+}
+
+static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap)
+{
+ struct i2c_pnx_algo_data *data = adap->algo_data;
+ struct timer_list *timer = &data->mif.timer;
+ int expires = I2C_PNX_TIMEOUT / (1000 / HZ);
+
+ del_timer_sync(timer);
+
+ dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n",
+ jiffies, expires);
+
+ timer->expires = jiffies + expires;
+ timer->data = (unsigned long)adap;
+
+ add_timer(timer);
+}
+
+/**
+ * i2c_pnx_start - start a device
+ * @slave_addr: slave address
+ * @adap: pointer to adapter structure
+ *
+ * Generate a START signal in the desired mode.
+ */
+static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
+{
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+ dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__,
+ slave_addr, alg_data->mif.mode);
+
+ /* Check for 7 bit slave addresses only */
+ if (slave_addr & ~0x7f) {
+ dev_err(&adap->dev, "%s: Invalid slave address %x. "
+ "Only 7-bit addresses are supported\n",
+ adap->name, slave_addr);
+ return -EINVAL;
+ }
+
+ /* First, make sure bus is idle */
+ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
+ /* Somebody else is monopolizing the bus */
+ dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, "
+ "cntrl = %x, stat = %x\n",
+ adap->name, slave_addr,
+ ioread32(I2C_REG_CTL(alg_data)),
+ ioread32(I2C_REG_STS(alg_data)));
+ return -EBUSY;
+ } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
+ /* Sorry, we lost the bus */
+ dev_err(&adap->dev, "%s: Arbitration failure. "
+ "Slave addr = %02x\n", adap->name, slave_addr);
+ return -EIO;
+ }
+
+ /*
+ * OK, I2C is enabled and we have the bus.
+ * Clear the current TDI and AFI status flags.
+ */
+ iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
+ I2C_REG_STS(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__,
+ (slave_addr << 1) | start_bit | alg_data->mif.mode);
+
+ /* Write the slave address, START bit and R/W bit */
+ iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
+ I2C_REG_TX(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
+
+ return 0;
+}
+
+/**
+ * i2c_pnx_stop - stop a device
+ * @adap: pointer to I2C adapter structure
+ *
+ * Generate a STOP signal to terminate the master transaction.
+ */
+static void i2c_pnx_stop(struct i2c_adapter *adap)
+{
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ /* Only 1 msec max timeout due to interrupt context */
+ long timeout = 1000;
+
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+ /* Write a STOP bit to TX FIFO */
+ iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
+
+ /* Wait until the STOP is seen. */
+ while (timeout > 0 &&
+ (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
+ /* may be called from interrupt context */
+ udelay(1);
+ timeout--;
+ }
+
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+}
+
+/**
+ * i2c_pnx_master_xmit - transmit data to slave
+ * @adap: pointer to I2C adapter structure
+ *
+ * Sends one byte of data to the slave
+ */
+static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+{
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ u32 val;
+
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+ if (alg_data->mif.len > 0) {
+ /* We still have something to talk about... */
+ val = *alg_data->mif.buf++;
+
+ if (alg_data->mif.len == 1) {
+ val |= stop_bit;
+ if (!alg_data->last)
+ val |= start_bit;
+ }
+
+ alg_data->mif.len--;
+ iowrite32(val, I2C_REG_TX(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__,
+ val, alg_data->mif.len + 1);
+
+ if (alg_data->mif.len == 0) {
+ if (alg_data->last) {
+ /* Wait until the STOP is seen. */
+ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
+ dev_err(&adap->dev, "The bus is still "
+ "active after timeout\n");
+ }
+ /* Disable master interrupts */
+ iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
+ ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
+ I2C_REG_CTL(alg_data));
+
+ del_timer_sync(&alg_data->mif.timer);
+
+ dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
+ __FUNCTION__);
+
+ complete(&alg_data->mif.complete);
+ }
+ } else if (alg_data->mif.len == 0) {
+ /* zero-sized transfer */
+ i2c_pnx_stop(adap);
+
+ /* Disable master interrupts. */
+ iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
+ ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
+ I2C_REG_CTL(alg_data));
+
+ /* Stop timer. */
+ del_timer_sync(&alg_data->mif.timer);
+ dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
+ "zero-xfer.\n", __FUNCTION__);
+
+ complete(&alg_data->mif.complete);
+ }
+
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+ return 0;
+}
+
+/**
+ * i2c_pnx_master_rcv - receive data from slave
+ * @adap: pointer to I2C adapter structure
+ *
+ * Reads one byte data from the slave
+ */
+static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+{
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ unsigned int val = 0;
+ u32 ctl = 0;
+
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+ /* Check, whether there is already data,
+ * or we didn't 'ask' for it yet.
+ */
+ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
+ dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
+ "Rx-fifo...\n", __FUNCTION__);
+
+ if (alg_data->mif.len == 1) {
+ /* Last byte, do not acknowledge next rcv. */
+ val |= stop_bit;
+ if (!alg_data->last)
+ val |= start_bit;
+
+ /*
+ * Enable interrupt RFDAIE (data in Rx fifo),
+ * and disable DRMIE (need data for Tx)
+ */
+ ctl = ioread32(I2C_REG_CTL(alg_data));
+ ctl |= mcntrl_rffie | mcntrl_daie;
+ ctl &= ~mcntrl_drmie;
+ iowrite32(ctl, I2C_REG_CTL(alg_data));
+ }
+
+ /*
+ * Now we'll 'ask' for data:
+ * For each byte we want to receive, we must
+ * write a (dummy) byte to the Tx-FIFO.
+ */
+ iowrite32(val, I2C_REG_TX(alg_data));
+
+ return 0;
+ }
+
+ /* Handle data. */
+ if (alg_data->mif.len > 0) {
+ val = ioread32(I2C_REG_RX(alg_data));
+ *alg_data->mif.buf++ = (u8) (val & 0xff);
+ dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val,
+ alg_data->mif.len);
+
+ alg_data->mif.len--;
+ if (alg_data->mif.len == 0) {
+ if (alg_data->last)
+ /* Wait until the STOP is seen. */
+ if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
+ dev_err(&adap->dev, "The bus is still "
+ "active after timeout\n");
+
+ /* Disable master interrupts */
+ ctl = ioread32(I2C_REG_CTL(alg_data));
+ ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
+ mcntrl_drmie | mcntrl_daie);
+ iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+ /* Kill timer. */
+ del_timer_sync(&alg_data->mif.timer);
+ complete(&alg_data->mif.complete);
+ }
+ }
+
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+ return 0;
+}
+
+static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+{
+ u32 stat, ctl;
+ struct i2c_adapter *adap = dev_id;
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+ dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
+ __FUNCTION__,
+ ioread32(I2C_REG_STS(alg_data)),
+ ioread32(I2C_REG_CTL(alg_data)),
+ alg_data->mif.mode);
+ stat = ioread32(I2C_REG_STS(alg_data));
+
+ /* let's see what kind of event this is */
+ if (stat & mstatus_afi) {
+ /* We lost arbitration in the midst of a transfer */
+ alg_data->mif.ret = -EIO;
+
+ /* Disable master interrupts. */
+ ctl = ioread32(I2C_REG_CTL(alg_data));
+ ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
+ mcntrl_drmie);
+ iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+ /* Stop timer, to prevent timeout. */
+ del_timer_sync(&alg_data->mif.timer);
+ complete(&alg_data->mif.complete);
+ } else if (stat & mstatus_nai) {
+ /* Slave did not acknowledge, generate a STOP */
+ dev_dbg(&adap->dev, "%s(): "
+ "Slave did not acknowledge, generating a STOP.\n",
+ __FUNCTION__);
+ i2c_pnx_stop(adap);
+
+ /* Disable master interrupts. */
+ ctl = ioread32(I2C_REG_CTL(alg_data));
+ ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
+ mcntrl_drmie);
+ iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+ /* Our return value. */
+ alg_data->mif.ret = -EIO;
+
+ /* Stop timer, to prevent timeout. */
+ del_timer_sync(&alg_data->mif.timer);
+ complete(&alg_data->mif.complete);
+ } else {
+ /*
+ * Two options:
+ * - Master Tx needs data.
+ * - There is data in the Rx-fifo
+ * The latter is only the case if we have requested for data,
+ * via a dummy write. (See 'i2c_pnx_master_rcv'.)
+ * We therefore check, as a sanity check, whether that interrupt
+ * has been enabled.
+ */
+ if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
+ if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
+ i2c_pnx_master_xmit(adap);
+ } else if (alg_data->mif.mode == I2C_SMBUS_READ) {
+ i2c_pnx_master_rcv(adap);
+ }
+ }
+ }
+
+ /* Clear TDI and AFI bits */
+ stat = ioread32(I2C_REG_STS(alg_data));
+ iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)),
+ ioread32(I2C_REG_CTL(alg_data)));
+
+ return IRQ_HANDLED;
+}
+
+static void i2c_pnx_timeout(unsigned long data)
+{
+ struct i2c_adapter *adap = (struct i2c_adapter *)data;
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ u32 ctl;
+
+ dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. "
+ "Resetting master...\n",
+ ioread32(I2C_REG_STS(alg_data)),
+ ioread32(I2C_REG_CTL(alg_data)));
+
+ /* Reset master and disable interrupts */
+ ctl = ioread32(I2C_REG_CTL(alg_data));
+ ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
+ iowrite32(ctl, I2C_REG_CTL(alg_data));
+
+ ctl |= mcntrl_reset;
+ iowrite32(ctl, I2C_REG_CTL(alg_data));
+ wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ alg_data->mif.ret = -EIO;
+ complete(&alg_data->mif.complete);
+}
+
+static inline void bus_reset_if_active(struct i2c_adapter *adap)
+{
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ u32 stat;
+
+ if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
+ dev_err(&adap->dev,
+ "%s: Bus is still active after xfer. Reset it...\n",
+ adap->name);
+ iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
+ I2C_REG_CTL(alg_data));
+ wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
+ /* If there is data in the fifo's after transfer,
+ * flush fifo's by reset.
+ */
+ iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
+ I2C_REG_CTL(alg_data));
+ wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ } else if (stat & mstatus_nai) {
+ iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
+ I2C_REG_CTL(alg_data));
+ wait_reset(I2C_PNX_TIMEOUT, alg_data);
+ }
+}
+
+/**
+ * i2c_pnx_xfer - generic transfer entry point
+ * @adap: pointer to I2C adapter structure
+ * @msgs: array of messages
+ * @num: number of messages
+ *
+ * Initiates the transfer
+ */
+static int
+i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct i2c_msg *pmsg;
+ int rc = 0, completed = 0, i;
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+ u32 stat = ioread32(I2C_REG_STS(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
+ __FUNCTION__, num, ioread32(I2C_REG_STS(alg_data)));
+
+ bus_reset_if_active(adap);
+
+ /* Process transactions in a loop. */
+ for (i = 0; rc >= 0 && i < num; i++) {
+ u8 addr;
+
+ pmsg = &msgs[i];
+ addr = pmsg->addr;
+
+ if (pmsg->flags & I2C_M_TEN) {
+ dev_err(&adap->dev,
+ "%s: 10 bits addr not supported!\n",
+ adap->name);
+ rc = -EINVAL;
+ break;
+ }
+
+ alg_data->mif.buf = pmsg->buf;
+ alg_data->mif.len = pmsg->len;
+ alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
+ I2C_SMBUS_READ : I2C_SMBUS_WRITE;
+ alg_data->mif.ret = 0;
+ alg_data->last = (i == num - 1);
+
+ dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__,
+ alg_data->mif.mode,
+ alg_data->mif.len);
+
+ i2c_pnx_arm_timer(adap);
+
+ /* initialize the completion var */
+ init_completion(&alg_data->mif.complete);
+
+ /* Enable master interrupt */
+ iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
+ mcntrl_naie | mcntrl_drmie,
+ I2C_REG_CTL(alg_data));
+
+ /* Put start-code and slave-address on the bus. */
+ rc = i2c_pnx_start(addr, adap);
+ if (rc < 0)
+ break;
+
+ /* Wait for completion */
+ wait_for_completion(&alg_data->mif.complete);
+
+ if (!(rc = alg_data->mif.ret))
+ completed++;
+ dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
+ __FUNCTION__, rc);
+
+ /* Clear TDI and AFI bits in case they are set. */
+ if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
+ dev_dbg(&adap->dev,
+ "%s: TDI still set... clearing now.\n",
+ adap->name);
+ iowrite32(stat, I2C_REG_STS(alg_data));
+ }
+ if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
+ dev_dbg(&adap->dev,
+ "%s: AFI still set... clearing now.\n",
+ adap->name);
+ iowrite32(stat, I2C_REG_STS(alg_data));
+ }
+ }
+
+ bus_reset_if_active(adap);
+
+ /* Cleanup to be sure... */
+ alg_data->mif.buf = NULL;
+ alg_data->mif.len = 0;
+
+ dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
+ __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
+
+ if (completed != num)
+ return ((rc < 0) ? rc : -EREMOTEIO);
+
+ return num;
+}
+
+static u32 i2c_pnx_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm pnx_algorithm = {
+ .master_xfer = i2c_pnx_xfer,
+ .functionality = i2c_pnx_func,
+};
+
+static int i2c_pnx_controller_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
+ return i2c_pnx->suspend(pdev, state);
+}
+
+static int i2c_pnx_controller_resume(struct platform_device *pdev)
+{
+ struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
+ return i2c_pnx->resume(pdev);
+}
+
+static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+{
+ unsigned long tmp;
+ int ret = 0;
+ struct i2c_pnx_algo_data *alg_data;
+ int freq_mhz;
+ struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
+
+ if (!i2c_pnx || !i2c_pnx->adapter) {
+ dev_err(&pdev->dev, "%s: no platform data supplied\n",
+ __FUNCTION__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ platform_set_drvdata(pdev, i2c_pnx);
+
+ if (i2c_pnx->calculate_input_freq)
+ freq_mhz = i2c_pnx->calculate_input_freq(pdev);
+ else {
+ freq_mhz = PNX_DEFAULT_FREQ;
+ dev_info(&pdev->dev, "Setting bus frequency to default value: "
+ "%d MHz", freq_mhz);
+ }
+
+ i2c_pnx->adapter->algo = &pnx_algorithm;
+
+ alg_data = i2c_pnx->adapter->algo_data;
+ init_timer(&alg_data->mif.timer);
+ alg_data->mif.timer.function = i2c_pnx_timeout;
+ alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter;
+
+ /* Register I/O resource */
+ if (!request_region(alg_data->base, I2C_PNX_REGION_SIZE, pdev->name)) {
+ dev_err(&pdev->dev,
+ "I/O region 0x%08x for I2C already in use.\n",
+ alg_data->base);
+ ret = -ENODEV;
+ goto out_drvdata;
+ }
+
+ if (!(alg_data->ioaddr =
+ (u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) {
+ dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
+ ret = -ENOMEM;
+ goto out_release;
+ }
+
+ i2c_pnx->set_clock_run(pdev);
+
+ /*
+ * Clock Divisor High This value is the number of system clocks
+ * the serial clock (SCL) will be high.
+ * For example, if the system clock period is 50 ns and the maximum
+ * desired serial period is 10000 ns (100 kHz), then CLKHI would be
+ * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
+ * programmed into CLKHI will vary from this slightly due to
+ * variations in the output pad's rise and fall times as well as
+ * the deglitching filter length.
+ */
+
+ tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
+ iowrite32(tmp, I2C_REG_CKH(alg_data));
+ iowrite32(tmp, I2C_REG_CKL(alg_data));
+
+ iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
+ if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
+ ret = -ENODEV;
+ goto out_unmap;
+ }
+ init_completion(&alg_data->mif.complete);
+
+ ret = request_irq(alg_data->irq, i2c_pnx_interrupt,
+ 0, pdev->name, i2c_pnx->adapter);
+ if (ret)
+ goto out_clock;
+
+ /* Register this adapter with the I2C subsystem */
+ i2c_pnx->adapter->dev.parent = &pdev->dev;
+ ret = i2c_add_adapter(i2c_pnx->adapter);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "I2C: Failed to add bus\n");
+ goto out_irq;
+ }
+
+ dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
+ i2c_pnx->adapter->name, alg_data->base, alg_data->irq);
+
+ return 0;
+
+out_irq:
+ free_irq(alg_data->irq, alg_data);
+out_clock:
+ i2c_pnx->set_clock_stop(pdev);
+out_unmap:
+ iounmap((void *)alg_data->ioaddr);
+out_release:
+ release_region(alg_data->base, I2C_PNX_REGION_SIZE);
+out_drvdata:
+ platform_set_drvdata(pdev, NULL);
+out:
+ return ret;
+}
+
+static int __devexit i2c_pnx_remove(struct platform_device *pdev)
+{
+ struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev);
+ struct i2c_adapter *adap = i2c_pnx->adapter;
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+ free_irq(alg_data->irq, alg_data);
+ i2c_del_adapter(adap);
+ i2c_pnx->set_clock_stop(pdev);
+ iounmap((void *)alg_data->ioaddr);
+ release_region(alg_data->base, I2C_PNX_REGION_SIZE);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver i2c_pnx_driver = {
+ .driver = {
+ .name = "pnx-i2c",
+ .owner = THIS_MODULE,
+ },
+ .probe = i2c_pnx_probe,
+ .remove = __devexit_p(i2c_pnx_remove),
+ .suspend = i2c_pnx_controller_suspend,
+ .resume = i2c_pnx_controller_resume,
+};
+
+static int __init i2c_adap_pnx_init(void)
+{
+ return platform_driver_register(&i2c_pnx_driver);
+}
+
+static void __exit i2c_adap_pnx_exit(void)
+{
+ platform_driver_unregister(&i2c_pnx_driver);
+}
+
+MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
+MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
+MODULE_LICENSE("GPL");
+
+/* We need to make sure I2C is initialized before USB */
+subsys_initcall(i2c_adap_pnx_init);
+module_exit(i2c_adap_pnx_exit);
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 7745e21874a..07c1f1e27df 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -212,7 +212,7 @@ static void prosavage_remove(struct pci_dev *dev)
if (chip->i2c_bus[i].adap_ok == 0)
continue;
- ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap);
+ ret = i2c_del_adapter(&chip->i2c_bus[i].adap);
if (ret) {
dev_err(&dev->dev, "%s not removed\n",
chip->i2c_bus[i].adap.name);
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 209f47ea175..844b4ff9089 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -173,7 +173,7 @@ static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_
static void __devexit savage4_remove(struct pci_dev *dev)
{
- i2c_bit_del_bus(&savage4_i2c_adapter);
+ i2c_del_adapter(&savage4_i2c_adapter);
iounmap(ioaddr);
}
diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
new file mode 100644
index 00000000000..081d9578ce1
--- /dev/null
+++ b/drivers/i2c/busses/i2c-versatile.c
@@ -0,0 +1,153 @@
+/*
+ * i2c-versatile.c
+ *
+ * Copyright (C) 2006 ARM Ltd.
+ * written by Russell King, Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#define I2C_CONTROL 0x00
+#define I2C_CONTROLS 0x00
+#define I2C_CONTROLC 0x04
+#define SCL (1 << 0)
+#define SDA (1 << 1)
+
+struct i2c_versatile {
+ struct i2c_adapter adap;
+ struct i2c_algo_bit_data algo;
+ void __iomem *base;
+};
+
+static void i2c_versatile_setsda(void *data, int state)
+{
+ struct i2c_versatile *i2c = data;
+
+ writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
+}
+
+static void i2c_versatile_setscl(void *data, int state)
+{
+ struct i2c_versatile *i2c = data;
+
+ writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
+}
+
+static int i2c_versatile_getsda(void *data)
+{
+ struct i2c_versatile *i2c = data;
+ return !!(readl(i2c->base + I2C_CONTROL) & SDA);
+}
+
+static int i2c_versatile_getscl(void *data)
+{
+ struct i2c_versatile *i2c = data;
+ return !!(readl(i2c->base + I2C_CONTROL) & SCL);
+}
+
+static struct i2c_algo_bit_data i2c_versatile_algo = {
+ .setsda = i2c_versatile_setsda,
+ .setscl = i2c_versatile_setscl,
+ .getsda = i2c_versatile_getsda,
+ .getscl = i2c_versatile_getscl,
+ .udelay = 30,
+ .timeout = HZ,
+};
+
+static int i2c_versatile_probe(struct platform_device *dev)
+{
+ struct i2c_versatile *i2c;
+ struct resource *r;
+ int ret;
+
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!r) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) {
+ ret = -EBUSY;
+ goto err_out;
+ }
+
+ i2c = kzalloc(sizeof(struct i2c_versatile), GFP_KERNEL);
+ if (!i2c) {
+ ret = -ENOMEM;
+ goto err_release;
+ }
+
+ i2c->base = ioremap(r->start, r->end - r->start + 1);
+ if (!i2c->base) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ writel(SCL | SDA, i2c->base + I2C_CONTROLS);
+
+ i2c->adap.owner = THIS_MODULE;
+ strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
+ i2c->adap.algo_data = &i2c->algo;
+ i2c->adap.dev.parent = &dev->dev;
+ i2c->algo = i2c_versatile_algo;
+ i2c->algo.data = i2c;
+
+ ret = i2c_bit_add_bus(&i2c->adap);
+ if (ret >= 0) {
+ platform_set_drvdata(dev, i2c);
+ return 0;
+ }
+
+ iounmap(i2c->base);
+ err_free:
+ kfree(i2c);
+ err_release:
+ release_mem_region(r->start, r->end - r->start + 1);
+ err_out:
+ return ret;
+}
+
+static int i2c_versatile_remove(struct platform_device *dev)
+{
+ struct i2c_versatile *i2c = platform_get_drvdata(dev);
+
+ platform_set_drvdata(dev, NULL);
+
+ i2c_del_adapter(&i2c->adap);
+ return 0;
+}
+
+static struct platform_driver i2c_versatile_driver = {
+ .probe = i2c_versatile_probe,
+ .remove = i2c_versatile_remove,
+ .driver = {
+ .name = "versatile-i2c",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init i2c_versatile_init(void)
+{
+ return platform_driver_register(&i2c_versatile_driver);
+}
+
+static void __exit i2c_versatile_exit(void)
+{
+ platform_driver_unregister(&i2c_versatile_driver);
+}
+
+module_init(i2c_versatile_init);
+module_exit(i2c_versatile_exit);
+
+MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 910e200ad50..15d7e00e47e 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -151,7 +151,7 @@ static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_i
static void __devexit vt586b_remove(struct pci_dev *dev)
{
- i2c_bit_del_bus(&vt586b_adapter);
+ i2c_del_adapter(&vt586b_adapter);
release_region(I2C_DIR, IOSPACE);
pm_io_base = 0;
}
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 6c8d2518338..b0377b81744 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -211,14 +211,14 @@ static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_
return retval;
retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
if (retval)
- i2c_bit_del_bus(&voodoo3_i2c_adapter);
+ i2c_del_adapter(&voodoo3_i2c_adapter);
return retval;
}
static void __devexit voodoo3_remove(struct pci_dev *dev)
{
- i2c_bit_del_bus(&voodoo3_i2c_adapter);
- i2c_bit_del_bus(&voodoo3_ddc_adapter);
+ i2c_del_adapter(&voodoo3_i2c_adapter);
+ i2c_del_adapter(&voodoo3_ddc_adapter);
iounmap(ioaddr);
}
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index 8ddbae4fafe..6cd96e43aa7 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -116,7 +116,7 @@ static int scx200_i2c_init(void)
static void scx200_i2c_cleanup(void)
{
- i2c_bit_del_bus(&scx200_i2c_ops);
+ i2c_del_adapter(&scx200_i2c_ops);
}
module_init(scx200_i2c_init);
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 93d483b8b77..ec17d6b684a 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -347,13 +347,19 @@ static void ds1337_init_client(struct i2c_client *client)
if ((status & 0x80) || (control & 0x80)) {
/* RTC not running */
- u8 buf[16];
+ u8 buf[1+16]; /* First byte is interpreted as address */
struct i2c_msg msg[1];
dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
/* Initialize all, including STATUS and CONTROL to zero */
memset(buf, 0, sizeof(buf));
+
+ /* Write valid values in the date/time registers */
+ buf[1+DS1337_REG_DAY] = 1;
+ buf[1+DS1337_REG_DATE] = 1;
+ buf[1+DS1337_REG_MONTH] = 1;
+
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = sizeof(buf);
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 420377c8642..3fcb646e207 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -209,6 +209,7 @@ m41t00_set(void *arg)
buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f);
buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f);
buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f);
+ buf[m41t00_chip->year] = year;
if (i2c_master_send(save_client, wbuf, 9) < 0)
dev_err(&save_client->dev, "m41t00_set: Write error\n");
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 60bef94cd25..4ee56def61f 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -82,7 +82,7 @@ struct tps65010 {
struct i2c_client client;
struct mutex lock;
int irq;
- struct work_struct work;
+ struct delayed_work work;
struct dentry *file;
unsigned charging:1;
unsigned por:1;
@@ -328,7 +328,7 @@ static void tps65010_interrupt(struct tps65010 *tps)
{
u8 tmp = 0, mask, poll;
- /* IRQs won't trigger irqs for certain events, but we can get
+ /* IRQs won't trigger for certain events, but we can get
* others by polling (normally, with external power applied).
*/
poll = 0;
@@ -411,10 +411,11 @@ static void tps65010_interrupt(struct tps65010 *tps)
}
/* handle IRQs and polling using keventd for now */
-static void tps65010_work(void *_tps)
+static void tps65010_work(struct work_struct *work)
{
- struct tps65010 *tps = _tps;
+ struct tps65010 *tps;
+ tps = container_of(work, struct tps65010, work.work);
mutex_lock(&tps->lock);
tps65010_interrupt(tps);
@@ -452,7 +453,7 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
disable_irq_nosync(irq);
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
- (void) schedule_work(&tps->work);
+ (void) schedule_work(&tps->work.work);
return IRQ_HANDLED;
}
@@ -465,13 +466,15 @@ static int __exit tps65010_detach_client(struct i2c_client *client)
struct tps65010 *tps;
tps = container_of(client, struct tps65010, client);
+ free_irq(tps->irq, tps);
#ifdef CONFIG_ARM
if (machine_is_omap_h2())
omap_free_gpio(58);
if (machine_is_omap_osk())
omap_free_gpio(OMAP_MPUIO(1));
#endif
- free_irq(tps->irq, tps);
+ cancel_delayed_work(&tps->work);
+ flush_scheduled_work();
debugfs_remove(tps->file);
if (i2c_detach_client(client) == 0)
kfree(tps);
@@ -505,7 +508,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
return 0;
mutex_init(&tps->lock);
- INIT_WORK(&tps->work, tps65010_work, tps);
+ INIT_DELAYED_WORK(&tps->work, tps65010_work);
tps->irq = -1;
tps->client.addr = address;
tps->client.adapter = bus;
@@ -620,7 +623,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
(void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f
| i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
- tps65010_work(tps);
+ tps65010_work(&tps->work.work);
tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
tps, DEBUG_FOPS);
@@ -672,7 +675,7 @@ int tps65010_set_vbus_draw(unsigned mA)
&& test_and_set_bit(
FLAG_VBUS_CHANGED, &the_tps->flags)) {
/* gadget drivers call this in_irq() */
- (void) schedule_work(&the_tps->work);
+ (void) schedule_work(&the_tps->work.work);
}
local_irq_restore(flags);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7ca81f42d14..b05378a3d67 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -95,16 +95,32 @@ struct device_driver i2c_adapter_driver = {
.bus = &i2c_bus_type,
};
+/* ------------------------------------------------------------------------- */
+
+/* I2C bus adapters -- one roots each I2C or SMBUS segment */
+
static void i2c_adapter_class_dev_release(struct class_device *dev)
{
struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev);
complete(&adap->class_dev_released);
}
+static ssize_t i2c_adapter_show_name(struct class_device *cdev, char *buf)
+{
+ struct i2c_adapter *adap = class_dev_to_i2c_adapter(cdev);
+ return sprintf(buf, "%s\n", adap->name);
+}
+
+static struct class_device_attribute i2c_adapter_attrs[] = {
+ __ATTR(name, S_IRUGO, i2c_adapter_show_name, NULL),
+ { },
+};
+
struct class i2c_adapter_class = {
- .owner = THIS_MODULE,
- .name = "i2c-adapter",
- .release = &i2c_adapter_class_dev_release,
+ .owner = THIS_MODULE,
+ .name = "i2c-adapter",
+ .class_dev_attrs = i2c_adapter_attrs,
+ .release = &i2c_adapter_class_dev_release,
};
static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -127,20 +143,17 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att
return sprintf(buf, "%s\n", client->name);
}
-/*
- * We can't use the DEVICE_ATTR() macro here as we want the same filename for a
- * different type of a device. So beware if the DEVICE_ATTR() macro ever
- * changes, this definition will also have to change.
+/*
+ * We can't use the DEVICE_ATTR() macro here, as we used the same name for
+ * an i2c adapter attribute (above).
*/
-static struct device_attribute dev_attr_client_name = {
- .attr = {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE },
- .show = &show_client_name,
-};
+static struct device_attribute dev_attr_client_name =
+ __ATTR(name, S_IRUGO, &show_client_name, NULL);
/* ---------------------------------------------------
- * registering functions
- * ---------------------------------------------------
+ * registering functions
+ * ---------------------------------------------------
*/
/* -----
@@ -178,8 +191,12 @@ int i2c_add_adapter(struct i2c_adapter *adap)
* If the parent pointer is not set up,
* we add this adapter to the host bus.
*/
- if (adap->dev.parent == NULL)
+ if (adap->dev.parent == NULL) {
adap->dev.parent = &platform_bus;
+ printk(KERN_WARNING "**WARNING** I2C adapter driver [%s] "
+ "forgot to specify physical device; fix it!\n",
+ adap->name);
+ }
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
adap->dev.driver = &i2c_adapter_driver;
adap->dev.release = &i2c_adapter_dev_release;
@@ -314,7 +331,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
res = driver_register(&driver->driver);
if (res)
return res;
-
+
mutex_lock(&core_lists);
list_add_tail(&driver->list,&drivers);
@@ -338,13 +355,13 @@ int i2c_del_driver(struct i2c_driver *driver)
struct list_head *item1, *item2, *_n;
struct i2c_client *client;
struct i2c_adapter *adap;
-
+
int res = 0;
mutex_lock(&core_lists);
/* Have a look at each adapter, if clients of this driver are still
- * attached. If so, detach them to be able to kill the driver
+ * attached. If so, detach them to be able to kill the driver
* afterwards.
*/
list_for_each(item1,&adapters) {
@@ -419,14 +436,14 @@ int i2c_attach_client(struct i2c_client *client)
goto out_unlock;
}
list_add_tail(&client->list,&adapter->clients);
-
+
client->usage_count = 0;
client->dev.parent = &client->adapter->dev;
client->dev.driver = &client->driver->driver;
client->dev.bus = &i2c_bus_type;
client->dev.release = &i2c_client_release;
-
+
snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
"%d-%04x", i2c_adapter_id(adapter), client->addr);
dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
@@ -467,7 +484,7 @@ int i2c_detach_client(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
int res = 0;
-
+
if (client->usage_count > 0) {
dev_warn(&client->dev, "Client [%s] still busy, "
"can't detach\n", client->name);
@@ -535,10 +552,10 @@ int i2c_release_client(struct i2c_client *client)
__FUNCTION__);
return -EPERM;
}
-
+
client->usage_count--;
i2c_dec_use_client(client);
-
+
return 0;
}
@@ -603,7 +620,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
}
#endif
- mutex_lock(&adap->bus_lock);
+ mutex_lock_nested(&adap->bus_lock, adap->level);
ret = adap->algo->master_xfer(adap,msgs,num);
mutex_unlock(&adap->bus_lock);
@@ -624,7 +641,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
msg.flags = client->flags & I2C_M_TEN;
msg.len = count;
msg.buf = (char *)buf;
-
+
ret = i2c_transfer(adap, &msg, 1);
/* If everything went ok (i.e. 1 msg transmitted), return #bytes
@@ -757,7 +774,7 @@ int i2c_probe(struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
if (address_data->probe[0] == I2C_CLIENT_END
&& address_data->normal_i2c[0] == I2C_CLIENT_END)
- return 0;
+ return 0;
dev_warn(&adapter->dev, "SMBus Quick command not supported, "
"can't probe for chips\n");
@@ -817,7 +834,7 @@ int i2c_probe(struct i2c_adapter *adapter,
struct i2c_adapter* i2c_get_adapter(int id)
{
struct i2c_adapter *adapter;
-
+
mutex_lock(&core_lists);
adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
if (adapter && !try_module_get(adapter->owner))
@@ -834,14 +851,14 @@ void i2c_put_adapter(struct i2c_adapter *adap)
/* The SMBus parts */
-#define POLY (0x1070U << 3)
+#define POLY (0x1070U << 3)
static u8
crc8(u16 data)
{
int i;
-
+
for(i = 0; i < 8; i++) {
- if (data & 0x8000)
+ if (data & 0x8000)
data = data ^ POLY;
data = data << 1;
}
@@ -891,13 +908,13 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
rpec, cpec);
return -1;
}
- return 0;
+ return 0;
}
s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- value,0,I2C_SMBUS_QUICK,NULL);
+ value,0,I2C_SMBUS_QUICK,NULL);
}
s32 i2c_smbus_read_byte(struct i2c_client *client)
@@ -996,11 +1013,11 @@ s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
I2C_SMBUS_I2C_BLOCK_DATA, &data);
}
-/* Simulate a SMBus command using the i2c protocol
+/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
-static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
+static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
unsigned short flags,
- char read_write, u8 command, int size,
+ char read_write, u8 command, int size,
union i2c_smbus_data * data)
{
/* So we need to generate a series of msgs. In the case of writing, we
@@ -1010,7 +1027,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ?2:1;
- struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
+ struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
};
int i;
@@ -1103,14 +1120,14 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
if (i) {
/* Compute PEC if first message is a write */
if (!(msg[0].flags & I2C_M_RD)) {
- if (num == 1) /* Write only */
+ if (num == 1) /* Write only */
i2c_smbus_add_pec(&msg[0]);
else /* Write followed by read */
partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
}
/* Ask for PEC if last message is a read */
if (msg[num-1].flags & I2C_M_RD)
- msg[num-1].len++;
+ msg[num-1].len++;
}
if (i2c_transfer(adapter, msg, num) < 0)
@@ -1130,7 +1147,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
case I2C_SMBUS_BYTE_DATA:
data->byte = msgbuf1[0];
break;
- case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_WORD_DATA:
case I2C_SMBUS_PROC_CALL:
data->word = msgbuf1[0] | (msgbuf1[1] << 8);
break;
@@ -1146,7 +1163,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
- char read_write, u8 command, int size,
+ char read_write, u8 command, int size,
union i2c_smbus_data * data)
{
s32 res;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 94a4e9a3013..ac5bd2a7ca9 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -1,5 +1,5 @@
/*
- i2c-dev.c - i2c-bus driver, char device interface
+ i2c-dev.c - i2c-bus driver, char device interface
Copyright (C) 1995-97 Simon G. Vogl
Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
@@ -90,6 +90,7 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_lock(&i2c_dev_list_lock);
list_del(&i2c_dev->list);
spin_unlock(&i2c_dev_list_lock);
+ kfree(i2c_dev);
}
static ssize_t show_adapter_name(struct device *dev,
@@ -119,7 +120,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
return -ENOMEM;
pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n",
- iminor(file->f_dentry->d_inode), count);
+ iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_recv(client,tmp,count);
if (ret >= 0)
@@ -147,7 +148,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
}
pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n",
- iminor(file->f_dentry->d_inode), count);
+ iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_send(client,tmp,count);
kfree(tmp);
@@ -172,7 +173,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
switch ( cmd ) {
case I2C_SLAVE:
case I2C_SLAVE_FORCE:
- if ((arg > 0x3ff) ||
+ if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
@@ -193,12 +194,11 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
- return (copy_to_user((unsigned long __user *)arg, &funcs,
- sizeof(unsigned long)))?-EFAULT:0;
+ return put_user(funcs, (unsigned long __user *)arg);
case I2C_RDWR:
- if (copy_from_user(&rdwr_arg,
- (struct i2c_rdwr_ioctl_data __user *)arg,
+ if (copy_from_user(&rdwr_arg,
+ (struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
@@ -206,9 +206,9 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
* be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
-
+
rdwr_pa = (struct i2c_msg *)
- kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
+ kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
GFP_KERNEL);
if (rdwr_pa == NULL) return -ENOMEM;
@@ -278,9 +278,9 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
(struct i2c_smbus_ioctl_data __user *) arg,
sizeof(struct i2c_smbus_ioctl_data)))
return -EFAULT;
- if ((data_arg.size != I2C_SMBUS_BYTE) &&
+ if ((data_arg.size != I2C_SMBUS_BYTE) &&
(data_arg.size != I2C_SMBUS_QUICK) &&
- (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
+ (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
(data_arg.size != I2C_SMBUS_WORD_DATA) &&
(data_arg.size != I2C_SMBUS_PROC_CALL) &&
(data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
@@ -291,11 +291,11 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
data_arg.size);
return -EINVAL;
}
- /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
+ /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
so the check is valid if size==I2C_SMBUS_QUICK too. */
- if ((data_arg.read_write != I2C_SMBUS_READ) &&
+ if ((data_arg.read_write != I2C_SMBUS_READ) &&
(data_arg.read_write != I2C_SMBUS_WRITE)) {
- dev_dbg(&client->adapter->dev,
+ dev_dbg(&client->adapter->dev,
"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.read_write);
return -EINVAL;
@@ -304,7 +304,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
/* Note that command values are always valid! */
if ((data_arg.size == I2C_SMBUS_QUICK) ||
- ((data_arg.size == I2C_SMBUS_BYTE) &&
+ ((data_arg.size == I2C_SMBUS_BYTE) &&
(data_arg.read_write == I2C_SMBUS_WRITE)))
/* These are special: we do not use data */
return i2c_smbus_xfer(client->adapter, client->addr,
@@ -322,14 +322,14 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
(data_arg.size == I2C_SMBUS_BYTE))
datasize = sizeof(data_arg.data->byte);
- else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
+ else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
(data_arg.size == I2C_SMBUS_PROC_CALL))
datasize = sizeof(data_arg.data->word);
else /* size == smbus block, i2c block, or block proc. call */
datasize = sizeof(data_arg.data->block);
- if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+ if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+ (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT;
@@ -337,8 +337,8 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
data_arg.read_write,
data_arg.command,data_arg.size,&temp);
- if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+ if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+ (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_READ))) {
if (copy_to_user(data_arg.data, &temp, datasize))
return -EFAULT;
@@ -417,8 +417,8 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
MKDEV(I2C_MAJOR, adap->nr),
"i2c-%d", adap->nr);
- if (!i2c_dev->dev) {
- res = -ENODEV;
+ if (IS_ERR(i2c_dev->dev)) {
+ res = PTR_ERR(i2c_dev->dev);
goto error;
}
res = device_create_file(i2c_dev->dev, &dev_attr_name);
@@ -432,7 +432,6 @@ error_destroy:
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error:
return_i2c_dev(i2c_dev);
- kfree(i2c_dev);
return res;
}
@@ -447,7 +446,6 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
device_remove_file(i2c_dev->dev, &dev_attr_name);
return_i2c_dev(i2c_dev);
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
- kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
return 0;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index e23bc0d6215..3f828052f8d 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -796,7 +796,7 @@ endchoice
config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
int "Maximum transfer size (KB) per request (up to 128)"
default "128"
- depends BLK_DEV_IDE_AU1XXX
+ depends on BLK_DEV_IDE_AU1XXX
config IDE_ARM
def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 88214943d00..5969cec58dc 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -687,8 +687,15 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
struct request *rq = HWGROUP(drive)->rq;
+ ide_hwif_t *hwif = HWIF(drive);
int stat, err, sense_key;
+ /* We may have bogus DMA interrupts in PIO state here */
+ if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) {
+ stat = hwif->INB(hwif->dma_status);
+ /* Should we force the bit as well ? */
+ hwif->OUTB(stat, hwif->dma_status);
+ }
/* Check for errors. */
stat = HWIF(drive)->INB(IDE_STATUS_REG);
if (stat_ret)
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index e3a267622bb..d33717c8afd 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2147,7 +2147,7 @@ static int ide_floppy_probe(ide_drive_t *drive)
printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
- if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+ if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
goto failed;
}
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index df7d1504f84..98410ca044c 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -73,3 +73,8 @@ void __init pnpide_init(void)
{
pnp_register_driver(&idepnp_driver);
}
+
+void __exit pnpide_exit(void)
+{
+ pnp_unregister_driver(&idepnp_driver);
+}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index dad9c47ebb6..5a5c565a32a 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1000,10 +1000,6 @@ static int ide_init_queue(ide_drive_t *drive)
/* needs drive->queue to be set */
ide_toggle_bounce(drive, 1);
- /* enable led activity for disk drives only */
- if (drive->media == ide_disk && hwif->led_act)
- blk_queue_activity_fn(q, hwif->led_act, drive);
-
return 0;
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index e2f4bb54906..b3bcd1d7315 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2573,11 +2573,11 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
int pages = tape->pages_per_stage;
char *b_data = NULL;
- if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
+ if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
return NULL;
stage->next = NULL;
- bh = stage->bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+ bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
if (bh == NULL)
goto abort;
bh->b_reqnext = NULL;
@@ -2607,7 +2607,7 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
continue;
}
prev_bh = bh;
- if ((bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
+ if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
free_page((unsigned long) b_data);
goto abort;
}
@@ -4860,7 +4860,7 @@ static int ide_tape_probe(ide_drive_t *drive)
printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
}
- tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL);
+ tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL);
if (tape == NULL) {
printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
goto failed;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 16890769dca..6c9bd5165bd 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1781,8 +1781,9 @@ done:
return 1;
}
-extern void pnpide_init(void);
-extern void h8300_ide_init(void);
+extern void __init pnpide_init(void);
+extern void __exit pnpide_exit(void);
+extern void __init h8300_ide_init(void);
/*
* probe_for_hwifs() finds/initializes "known" IDE interfaces
@@ -2087,13 +2088,17 @@ int __init init_module (void)
return ide_init();
}
-void cleanup_module (void)
+void __exit cleanup_module (void)
{
int index;
for (index = 0; index < MAX_HWIFS; ++index)
ide_unregister(index);
+#ifdef CONFIG_BLK_DEV_IDEPNP
+ pnpide_exit();
+#endif
+
#ifdef CONFIG_PROC_FS
proc_ide_destroy();
#endif
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index f286079d233..d261bfbad22 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -441,7 +441,7 @@ static struct pci_driver driver = {
.probe = aec62xx_init_one,
};
-static int aec62xx_ide_init(void)
+static int __init aec62xx_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index d419e4bb54f..68df77ec502 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -586,11 +586,11 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
{
unsigned long flags;
u8 tmpbyte;
- struct pci_dev *north = pci_find_slot(0, PCI_DEVFN(0,0));
+ struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
- isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+ isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
if (!ali_proc) {
@@ -613,8 +613,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
* clear bit 7
*/
pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
- local_irq_restore(flags);
- return 0;
+ goto out;
}
/*
@@ -637,10 +636,8 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
* box without a device at 0:0.0. The ALi bridge will be at
* 0:0.0 so if we didn't find one we know what is cooking.
*/
- if (north && north->vendor != PCI_VENDOR_ID_AL) {
- local_irq_restore(flags);
- return 0;
- }
+ if (north && north->vendor != PCI_VENDOR_ID_AL)
+ goto out;
if (m5229_revision < 0xC5 && isa_dev)
{
@@ -661,6 +658,9 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
}
}
+out:
+ pci_dev_put(north);
+ pci_dev_put(isa_dev);
local_irq_restore(flags);
return 0;
}
@@ -907,7 +907,7 @@ static struct pci_driver driver = {
.probe = alim15x3_init_one,
};
-static int ali15x3_ide_init(void)
+static int __init ali15x3_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 753fe0e2145..a4336995a41 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -544,7 +544,7 @@ static struct pci_driver driver = {
.probe = amd74xx_probe,
};
-static int amd74xx_ide_init(void)
+static int __init amd74xx_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index d55b938b1ae..982ac31fa99 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -46,6 +46,8 @@ static atiixp_ide_timing mdma_timing[] = {
static int save_mdma_mode[4];
+static DEFINE_SPINLOCK(atiixp_lock);
+
/**
* atiixp_ratemask - compute rate mask for ATIIXP IDE
* @drive: IDE drive to compute for
@@ -105,7 +107,7 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive)
unsigned long flags;
u16 tmp16;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&atiixp_lock, flags);
pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
if (save_mdma_mode[drive->dn])
@@ -114,7 +116,7 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive)
tmp16 |= (1 << drive->dn);
pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&atiixp_lock, flags);
return __ide_dma_host_on(drive);
}
@@ -125,13 +127,13 @@ static int atiixp_ide_dma_host_off(ide_drive_t *drive)
unsigned long flags;
u16 tmp16;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&atiixp_lock, flags);
pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
tmp16 &= ~(1 << drive->dn);
pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&atiixp_lock, flags);
return __ide_dma_host_off(drive);
}
@@ -152,7 +154,7 @@ static void atiixp_tuneproc(ide_drive_t *drive, u8 pio)
u32 pio_timing_data;
u16 pio_mode_data;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&atiixp_lock, flags);
pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
pio_mode_data &= ~(0x07 << (drive->dn * 4));
@@ -165,7 +167,7 @@ static void atiixp_tuneproc(ide_drive_t *drive, u8 pio)
(pio_timing[pio].command_width << (timing_shift + 4));
pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&atiixp_lock, flags);
}
/**
@@ -189,7 +191,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed)
speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed);
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&atiixp_lock, flags);
save_mdma_mode[drive->dn] = 0;
if (speed >= XFER_UDMA_0) {
@@ -208,7 +210,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed)
}
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&atiixp_lock, flags);
if (speed >= XFER_SW_DMA_0)
pio = atiixp_dma_2_pio(speed);
@@ -289,8 +291,12 @@ fast_ata_pio:
static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
{
+ u8 udma_mode = 0;
+ u8 ch = hwif->channel;
+ struct pci_dev *pdev = hwif->pci_dev;
+
if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
+ hwif->irq = ch ? 15 : 14;
hwif->autodma = 0;
hwif->tuneproc = &atiixp_tuneproc;
@@ -306,8 +312,12 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
- /* FIXME: proper cable detection needed */
- hwif->udma_four = 1;
+ pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+ if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
+ hwif->udma_four = 1;
+ else
+ hwif->udma_four = 0;
+
hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
hwif->ide_dma_check = &atiixp_dma_check;
@@ -318,19 +328,6 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
hwif->drives[0].autodma = hwif->autodma;
}
-static void __devinit init_hwif_sb600_legacy(ide_hwif_t *hwif)
-{
-
- hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-}
static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
{ /* 0 */
@@ -341,12 +338,13 @@ static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
.bootable = ON_BOARD,
},{ /* 1 */
- .name = "ATI SB600 SATA Legacy IDE",
- .init_hwif = init_hwif_sb600_legacy,
- .channels = 2,
+ .name = "SB600_PATA",
+ .init_hwif = init_hwif_atiixp,
+ .channels = 1,
.autodma = AUTODMA,
- .bootable = ON_BOARD,
- }
+ .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
+ .bootable = ON_BOARD,
+ },
};
/**
@@ -367,8 +365,7 @@ static struct pci_device_id atiixp_pci_tbl[] = {
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, PCI_ANY_ID, PCI_ANY_ID, (PCI_CLASS_STORAGE_IDE<<8)|0x8a, 0xffff05, 1},
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
@@ -379,7 +376,7 @@ static struct pci_driver driver = {
.probe = atiixp_init_one,
};
-static int atiixp_ide_init(void)
+static int __init atiixp_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 20c32716bbc..aee947e8fc3 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -793,7 +793,7 @@ static struct pci_driver driver = {
.probe = cmd64x_init_one,
};
-static int cmd64x_ide_init(void)
+static int __init cmd64x_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 079f7c86726..ba6786aabf3 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -260,7 +260,7 @@ static struct pci_driver driver = {
.probe = cs5520_init_one,
};
-static int cs5520_ide_init(void)
+static int __init cs5520_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index ae405fa3223..9bf5fdfc5b1 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -374,7 +374,7 @@ static struct pci_driver driver = {
.probe = cs5530_init_one,
};
-static int cs5530_ide_init(void)
+static int __init cs5530_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 64330c459bd..9eafcbf444f 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -519,7 +519,7 @@ static struct pci_driver driver = {
.probe = cy82c693_init_one,
};
-static int cy82c693_ide_init(void)
+static int __init cy82c693_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 9f306880491..b408c6c517e 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -185,36 +185,6 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.bootable = OFF_BOARD,
- },{ /* 15 */
- .name = "JMB361",
- .init_hwif = init_hwif_generic,
- .channels = 2,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- },{ /* 16 */
- .name = "JMB363",
- .init_hwif = init_hwif_generic,
- .channels = 2,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- },{ /* 17 */
- .name = "JMB365",
- .init_hwif = init_hwif_generic,
- .channels = 2,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- },{ /* 18 */
- .name = "JMB366",
- .init_hwif = init_hwif_generic,
- .channels = 2,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
- },{ /* 19 */
- .name = "JMB368",
- .init_hwif = init_hwif_generic,
- .channels = 2,
- .autodma = AUTODMA,
- .bootable = OFF_BOARD,
}
};
@@ -281,11 +251,6 @@ static struct pci_device_id generic_pci_tbl[] = {
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
{ PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
{ PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
- { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
/* Must come last. If you add entries adjust this table appropriately and the init_one code */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
{ 0, },
@@ -298,7 +263,7 @@ static struct pci_driver driver = {
.probe = generic_init_one,
};
-static int generic_ide_init(void)
+static int __init generic_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index b46cb042290..ce7b08f08a0 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -265,7 +265,7 @@ static struct pci_driver driver = {
.probe = hpt34x_init_one,
};
-static int hpt34x_ide_init(void)
+static int __init hpt34x_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index e993a51f250..b486442dd5d 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -4,6 +4,7 @@
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
+ * Portions Copyright (C) 2005-2006 MontaVista Software, Inc.
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
* Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
@@ -11,9 +12,11 @@
* development and support.
*
*
- * Highpoint have their own driver (source except for the raid part)
- * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz
- * This may be useful to anyone wanting to work on the mainstream hpt IDE.
+ * HighPoint has its own drivers (open source except for the RAID part)
+ * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
+ * This may be useful to anyone wanting to work on this driver, however do not
+ * trust them too much since the code tends to become less and less meaningful
+ * as the time passes... :-/
*
* Note that final HPT370 support was done by force extraction of GPL.
*
@@ -52,6 +55,29 @@
* keeping me sane.
* Alan Cox <alan@redhat.com>
*
+ * - fix the clock turnaround code: it was writing to the wrong ports when
+ * called for the secondary channel, caching the current clock mode per-
+ * channel caused the cached register value to get out of sync with the
+ * actual one, the channels weren't serialized, the turnaround shouldn't
+ * be done on 66 MHz PCI bus
+ * - avoid calibrating PLL twice as the second time results in a wrong PCI
+ * frequency and thus in the wrong timings for the secondary channel
+ * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not
+ * allow for this speed anyway)
+ * - add support for HPT302N and HPT371N clocking (the same as for HPT372N)
+ * - HPT371/N are single channel chips, so avoid touching the primary channel
+ * which exists only virtually (there's no pins for it)
+ * - fix/remove bad/unused timing tables and use one set of tables for the whole
+ * HPT37x chip family; save space by introducing the separate transfer mode
+ * table in which the mode lookup is done
+ * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives
+ * the wrong PCI frequency since DPLL has already been calibrated by BIOS
+ * - fix the hotswap code: it caused RESET- to glitch when tristating the bus,
+ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
+ * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
+ * they tamper with its fields
+ * <source@mvista.com>
+ *
*/
@@ -76,8 +102,8 @@
/* various tuning parameters */
#define HPT_RESET_STATE_ENGINE
-#undef HPT_DELAY_INTERRUPT
-#undef HPT_SERIALIZE_IO
+#undef HPT_DELAY_INTERRUPT
+#define HPT_SERIALIZE_IO 0
static const char *quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
@@ -141,305 +167,175 @@ static const char *bad_ata33[] = {
NULL
};
-struct chipset_bus_clock_list_entry {
- u8 xfer_speed;
- unsigned int chipset_settings;
+static u8 xfer_speeds[] = {
+ XFER_UDMA_6,
+ XFER_UDMA_5,
+ XFER_UDMA_4,
+ XFER_UDMA_3,
+ XFER_UDMA_2,
+ XFER_UDMA_1,
+ XFER_UDMA_0,
+
+ XFER_MW_DMA_2,
+ XFER_MW_DMA_1,
+ XFER_MW_DMA_0,
+
+ XFER_PIO_4,
+ XFER_PIO_3,
+ XFER_PIO_2,
+ XFER_PIO_1,
+ XFER_PIO_0
};
-/* key for bus clock timings
- * bit
- * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
- * DMA. cycles = value + 1
- * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW
- * DMA. cycles = value + 1
- * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file
- * register access.
- * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file
- * register access.
- * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer.
- * during task file register access.
- * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA
- * xfer.
- * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task
- * register access.
- * 28 UDMA enable
- * 29 DMA enable
- * 30 PIO_MST enable. if set, the chip is in bus master mode during
- * PIO.
- * 31 FIFO enable.
+/* Key for bus clock timings
+ * 36x 37x
+ * bits bits
+ * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
+ * cycles = value + 1
+ * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
+ * cycles = value + 1
+ * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
+ * register access.
+ * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
+ * register access.
+ * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
+ * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock.
+ * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
+ * MW DMA xfer.
+ * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
+ * task file register access.
+ * 28 28 UDMA enable.
+ * 29 29 DMA enable.
+ * 30 30 PIO MST enable. If set, the chip is in bus master mode during
+ * PIO xfer.
+ * 31 31 FIFO enable.
*/
-static struct chipset_bus_clock_list_entry forty_base_hpt366[] = {
- { XFER_UDMA_4, 0x900fd943 },
- { XFER_UDMA_3, 0x900ad943 },
- { XFER_UDMA_2, 0x900bd943 },
- { XFER_UDMA_1, 0x9008d943 },
- { XFER_UDMA_0, 0x9008d943 },
-
- { XFER_MW_DMA_2, 0xa008d943 },
- { XFER_MW_DMA_1, 0xa010d955 },
- { XFER_MW_DMA_0, 0xa010d9fc },
-
- { XFER_PIO_4, 0xc008d963 },
- { XFER_PIO_3, 0xc010d974 },
- { XFER_PIO_2, 0xc010d997 },
- { XFER_PIO_1, 0xc010d9c7 },
- { XFER_PIO_0, 0xc018d9d9 },
- { 0, 0x0120d9d9 }
-};
-
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = {
- { XFER_UDMA_4, 0x90c9a731 },
- { XFER_UDMA_3, 0x90cfa731 },
- { XFER_UDMA_2, 0x90caa731 },
- { XFER_UDMA_1, 0x90cba731 },
- { XFER_UDMA_0, 0x90c8a731 },
-
- { XFER_MW_DMA_2, 0xa0c8a731 },
- { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */
- { XFER_MW_DMA_0, 0xa0c8a797 },
-
- { XFER_PIO_4, 0xc0c8a731 },
- { XFER_PIO_3, 0xc0c8a742 },
- { XFER_PIO_2, 0xc0d0a753 },
- { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */
- { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */
- { 0, 0x0120a7a7 }
-};
-
-static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = {
- { XFER_UDMA_4, 0x90c98521 },
- { XFER_UDMA_3, 0x90cf8521 },
- { XFER_UDMA_2, 0x90cf8521 },
- { XFER_UDMA_1, 0x90cb8521 },
- { XFER_UDMA_0, 0x90cb8521 },
-
- { XFER_MW_DMA_2, 0xa0ca8521 },
- { XFER_MW_DMA_1, 0xa0ca8532 },
- { XFER_MW_DMA_0, 0xa0ca8575 },
-
- { XFER_PIO_4, 0xc0ca8521 },
- { XFER_PIO_3, 0xc0ca8532 },
- { XFER_PIO_2, 0xc0ca8542 },
- { XFER_PIO_1, 0xc0d08572 },
- { XFER_PIO_0, 0xc0d08585 },
- { 0, 0x01208585 }
-};
-
-/* from highpoint documentation. these are old values */
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = {
-/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */
- { XFER_UDMA_5, 0x16454e31 },
- { XFER_UDMA_4, 0x16454e31 },
- { XFER_UDMA_3, 0x166d4e31 },
- { XFER_UDMA_2, 0x16494e31 },
- { XFER_UDMA_1, 0x164d4e31 },
- { XFER_UDMA_0, 0x16514e31 },
-
- { XFER_MW_DMA_2, 0x26514e21 },
- { XFER_MW_DMA_1, 0x26514e33 },
- { XFER_MW_DMA_0, 0x26514e97 },
-
- { XFER_PIO_4, 0x06514e21 },
- { XFER_PIO_3, 0x06514e22 },
- { XFER_PIO_2, 0x06514e33 },
- { XFER_PIO_1, 0x06914e43 },
- { XFER_PIO_0, 0x06914e57 },
- { 0, 0x06514e57 }
-};
-
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = {
- { XFER_UDMA_5, 0x14846231 },
- { XFER_UDMA_4, 0x14886231 },
- { XFER_UDMA_3, 0x148c6231 },
- { XFER_UDMA_2, 0x148c6231 },
- { XFER_UDMA_1, 0x14906231 },
- { XFER_UDMA_0, 0x14986231 },
-
- { XFER_MW_DMA_2, 0x26514e21 },
- { XFER_MW_DMA_1, 0x26514e33 },
- { XFER_MW_DMA_0, 0x26514e97 },
-
- { XFER_PIO_4, 0x06514e21 },
- { XFER_PIO_3, 0x06514e22 },
- { XFER_PIO_2, 0x06514e33 },
- { XFER_PIO_1, 0x06914e43 },
- { XFER_PIO_0, 0x06914e57 },
- { 0, 0x06514e57 }
-};
-
-/* these are the current (4 sep 2001) timings from highpoint */
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = {
- { XFER_UDMA_5, 0x12446231 },
- { XFER_UDMA_4, 0x12446231 },
- { XFER_UDMA_3, 0x126c6231 },
- { XFER_UDMA_2, 0x12486231 },
- { XFER_UDMA_1, 0x124c6233 },
- { XFER_UDMA_0, 0x12506297 },
-
- { XFER_MW_DMA_2, 0x22406c31 },
- { XFER_MW_DMA_1, 0x22406c33 },
- { XFER_MW_DMA_0, 0x22406c97 },
-
- { XFER_PIO_4, 0x06414e31 },
- { XFER_PIO_3, 0x06414e42 },
- { XFER_PIO_2, 0x06414e53 },
- { XFER_PIO_1, 0x06814e93 },
- { XFER_PIO_0, 0x06814ea7 },
- { 0, 0x06814ea7 }
-};
-
-/* 2x 33MHz timings */
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = {
- { XFER_UDMA_5, 0x1488e673 },
- { XFER_UDMA_4, 0x1488e673 },
- { XFER_UDMA_3, 0x1498e673 },
- { XFER_UDMA_2, 0x1490e673 },
- { XFER_UDMA_1, 0x1498e677 },
- { XFER_UDMA_0, 0x14a0e73f },
-
- { XFER_MW_DMA_2, 0x2480fa73 },
- { XFER_MW_DMA_1, 0x2480fa77 },
- { XFER_MW_DMA_0, 0x2480fb3f },
-
- { XFER_PIO_4, 0x0c82be73 },
- { XFER_PIO_3, 0x0c82be95 },
- { XFER_PIO_2, 0x0c82beb7 },
- { XFER_PIO_1, 0x0d02bf37 },
- { XFER_PIO_0, 0x0d02bf5f },
- { 0, 0x0d02bf5f }
-};
-static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = {
- { XFER_UDMA_5, 0x12848242 },
- { XFER_UDMA_4, 0x12ac8242 },
- { XFER_UDMA_3, 0x128c8242 },
- { XFER_UDMA_2, 0x120c8242 },
- { XFER_UDMA_1, 0x12148254 },
- { XFER_UDMA_0, 0x121882ea },
-
- { XFER_MW_DMA_2, 0x22808242 },
- { XFER_MW_DMA_1, 0x22808254 },
- { XFER_MW_DMA_0, 0x228082ea },
-
- { XFER_PIO_4, 0x0a81f442 },
- { XFER_PIO_3, 0x0a81f443 },
- { XFER_PIO_2, 0x0a81f454 },
- { XFER_PIO_1, 0x0ac1f465 },
- { XFER_PIO_0, 0x0ac1f48a },
- { 0, 0x0ac1f48a }
+static u32 forty_base_hpt36x[] = {
+ /* XFER_UDMA_6 */ 0x900fd943,
+ /* XFER_UDMA_5 */ 0x900fd943,
+ /* XFER_UDMA_4 */ 0x900fd943,
+ /* XFER_UDMA_3 */ 0x900ad943,
+ /* XFER_UDMA_2 */ 0x900bd943,
+ /* XFER_UDMA_1 */ 0x9008d943,
+ /* XFER_UDMA_0 */ 0x9008d943,
+
+ /* XFER_MW_DMA_2 */ 0xa008d943,
+ /* XFER_MW_DMA_1 */ 0xa010d955,
+ /* XFER_MW_DMA_0 */ 0xa010d9fc,
+
+ /* XFER_PIO_4 */ 0xc008d963,
+ /* XFER_PIO_3 */ 0xc010d974,
+ /* XFER_PIO_2 */ 0xc010d997,
+ /* XFER_PIO_1 */ 0xc010d9c7,
+ /* XFER_PIO_0 */ 0xc018d9d9
};
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = {
- { XFER_UDMA_6, 0x1c81dc62 },
- { XFER_UDMA_5, 0x1c6ddc62 },
- { XFER_UDMA_4, 0x1c8ddc62 },
- { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */
- { XFER_UDMA_2, 0x1c91dc62 },
- { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */
- { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */
-
- { XFER_MW_DMA_2, 0x2c829262 },
- { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */
- { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */
-
- { XFER_PIO_4, 0x0c829c62 },
- { XFER_PIO_3, 0x0c829c84 },
- { XFER_PIO_2, 0x0c829ca6 },
- { XFER_PIO_1, 0x0d029d26 },
- { XFER_PIO_0, 0x0d029d5e },
- { 0, 0x0d029d5e }
+static u32 thirty_three_base_hpt36x[] = {
+ /* XFER_UDMA_6 */ 0x90c9a731,
+ /* XFER_UDMA_5 */ 0x90c9a731,
+ /* XFER_UDMA_4 */ 0x90c9a731,
+ /* XFER_UDMA_3 */ 0x90cfa731,
+ /* XFER_UDMA_2 */ 0x90caa731,
+ /* XFER_UDMA_1 */ 0x90cba731,
+ /* XFER_UDMA_0 */ 0x90c8a731,
+
+ /* XFER_MW_DMA_2 */ 0xa0c8a731,
+ /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */
+ /* XFER_MW_DMA_0 */ 0xa0c8a797,
+
+ /* XFER_PIO_4 */ 0xc0c8a731,
+ /* XFER_PIO_3 */ 0xc0c8a742,
+ /* XFER_PIO_2 */ 0xc0d0a753,
+ /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */
+ /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */
};
-static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = {
- { XFER_UDMA_5, 0x12848242 },
- { XFER_UDMA_4, 0x12ac8242 },
- { XFER_UDMA_3, 0x128c8242 },
- { XFER_UDMA_2, 0x120c8242 },
- { XFER_UDMA_1, 0x12148254 },
- { XFER_UDMA_0, 0x121882ea },
-
- { XFER_MW_DMA_2, 0x22808242 },
- { XFER_MW_DMA_1, 0x22808254 },
- { XFER_MW_DMA_0, 0x228082ea },
-
- { XFER_PIO_4, 0x0a81f442 },
- { XFER_PIO_3, 0x0a81f443 },
- { XFER_PIO_2, 0x0a81f454 },
- { XFER_PIO_1, 0x0ac1f465 },
- { XFER_PIO_0, 0x0ac1f48a },
- { 0, 0x0a81f443 }
+static u32 twenty_five_base_hpt36x[] = {
+ /* XFER_UDMA_6 */ 0x90c98521,
+ /* XFER_UDMA_5 */ 0x90c98521,
+ /* XFER_UDMA_4 */ 0x90c98521,
+ /* XFER_UDMA_3 */ 0x90cf8521,
+ /* XFER_UDMA_2 */ 0x90cf8521,
+ /* XFER_UDMA_1 */ 0x90cb8521,
+ /* XFER_UDMA_0 */ 0x90cb8521,
+
+ /* XFER_MW_DMA_2 */ 0xa0ca8521,
+ /* XFER_MW_DMA_1 */ 0xa0ca8532,
+ /* XFER_MW_DMA_0 */ 0xa0ca8575,
+
+ /* XFER_PIO_4 */ 0xc0ca8521,
+ /* XFER_PIO_3 */ 0xc0ca8532,
+ /* XFER_PIO_2 */ 0xc0ca8542,
+ /* XFER_PIO_1 */ 0xc0d08572,
+ /* XFER_PIO_0 */ 0xc0d08585
};
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = {
- { XFER_UDMA_6, 0x1c869c62 },
- { XFER_UDMA_5, 0x1cae9c62 },
- { XFER_UDMA_4, 0x1c8a9c62 },
- { XFER_UDMA_3, 0x1c8e9c62 },
- { XFER_UDMA_2, 0x1c929c62 },
- { XFER_UDMA_1, 0x1c9a9c62 },
- { XFER_UDMA_0, 0x1c829c62 },
-
- { XFER_MW_DMA_2, 0x2c829c62 },
- { XFER_MW_DMA_1, 0x2c829c66 },
- { XFER_MW_DMA_0, 0x2c829d2e },
-
- { XFER_PIO_4, 0x0c829c62 },
- { XFER_PIO_3, 0x0c829c84 },
- { XFER_PIO_2, 0x0c829ca6 },
- { XFER_PIO_1, 0x0d029d26 },
- { XFER_PIO_0, 0x0d029d5e },
- { 0, 0x0d029d26 }
+static u32 thirty_three_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
+ /* XFER_UDMA_5 */ 0x12446231,
+ /* XFER_UDMA_4 */ 0x12446231,
+ /* XFER_UDMA_3 */ 0x126c6231,
+ /* XFER_UDMA_2 */ 0x12486231,
+ /* XFER_UDMA_1 */ 0x124c6233,
+ /* XFER_UDMA_0 */ 0x12506297,
+
+ /* XFER_MW_DMA_2 */ 0x22406c31,
+ /* XFER_MW_DMA_1 */ 0x22406c33,
+ /* XFER_MW_DMA_0 */ 0x22406c97,
+
+ /* XFER_PIO_4 */ 0x06414e31,
+ /* XFER_PIO_3 */ 0x06414e42,
+ /* XFER_PIO_2 */ 0x06414e53,
+ /* XFER_PIO_1 */ 0x06814e93,
+ /* XFER_PIO_0 */ 0x06814ea7
};
-static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = {
- { XFER_UDMA_6, 0x12808242 },
- { XFER_UDMA_5, 0x12848242 },
- { XFER_UDMA_4, 0x12ac8242 },
- { XFER_UDMA_3, 0x128c8242 },
- { XFER_UDMA_2, 0x120c8242 },
- { XFER_UDMA_1, 0x12148254 },
- { XFER_UDMA_0, 0x121882ea },
-
- { XFER_MW_DMA_2, 0x22808242 },
- { XFER_MW_DMA_1, 0x22808254 },
- { XFER_MW_DMA_0, 0x228082ea },
-
- { XFER_PIO_4, 0x0a81f442 },
- { XFER_PIO_3, 0x0a81f443 },
- { XFER_PIO_2, 0x0a81f454 },
- { XFER_PIO_1, 0x0ac1f465 },
- { XFER_PIO_0, 0x0ac1f48a },
- { 0, 0x06814e93 }
+static u32 fifty_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x12848242,
+ /* XFER_UDMA_5 */ 0x12848242,
+ /* XFER_UDMA_4 */ 0x12ac8242,
+ /* XFER_UDMA_3 */ 0x128c8242,
+ /* XFER_UDMA_2 */ 0x120c8242,
+ /* XFER_UDMA_1 */ 0x12148254,
+ /* XFER_UDMA_0 */ 0x121882ea,
+
+ /* XFER_MW_DMA_2 */ 0x22808242,
+ /* XFER_MW_DMA_1 */ 0x22808254,
+ /* XFER_MW_DMA_0 */ 0x228082ea,
+
+ /* XFER_PIO_4 */ 0x0a81f442,
+ /* XFER_PIO_3 */ 0x0a81f443,
+ /* XFER_PIO_2 */ 0x0a81f454,
+ /* XFER_PIO_1 */ 0x0ac1f465,
+ /* XFER_PIO_0 */ 0x0ac1f48a
};
-/* FIXME: 50MHz timings for HPT374 */
-
-#if 0
-static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
- { XFER_UDMA_6, 0x12406231 }, /* checkme */
- { XFER_UDMA_5, 0x12446231 }, /* 0x14846231 */
- { XFER_UDMA_4, 0x16814ea7 }, /* 0x14886231 */
- { XFER_UDMA_3, 0x16814ea7 }, /* 0x148c6231 */
- { XFER_UDMA_2, 0x16814ea7 }, /* 0x148c6231 */
- { XFER_UDMA_1, 0x16814ea7 }, /* 0x14906231 */
- { XFER_UDMA_0, 0x16814ea7 }, /* 0x14986231 */
- { XFER_MW_DMA_2, 0x16814ea7 }, /* 0x26514e21 */
- { XFER_MW_DMA_1, 0x16814ea7 }, /* 0x26514e97 */
- { XFER_MW_DMA_0, 0x16814ea7 }, /* 0x26514e97 */
- { XFER_PIO_4, 0x06814ea7 }, /* 0x06514e21 */
- { XFER_PIO_3, 0x06814ea7 }, /* 0x06514e22 */
- { XFER_PIO_2, 0x06814ea7 }, /* 0x06514e33 */
- { XFER_PIO_1, 0x06814ea7 }, /* 0x06914e43 */
- { XFER_PIO_0, 0x06814ea7 }, /* 0x06914e57 */
- { 0, 0x06814ea7 }
+static u32 sixty_six_base_hpt37x[] = {
+ /* XFER_UDMA_6 */ 0x1c869c62,
+ /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */
+ /* XFER_UDMA_4 */ 0x1c8a9c62,
+ /* XFER_UDMA_3 */ 0x1c8e9c62,
+ /* XFER_UDMA_2 */ 0x1c929c62,
+ /* XFER_UDMA_1 */ 0x1c9a9c62,
+ /* XFER_UDMA_0 */ 0x1c829c62,
+
+ /* XFER_MW_DMA_2 */ 0x2c829c62,
+ /* XFER_MW_DMA_1 */ 0x2c829c66,
+ /* XFER_MW_DMA_0 */ 0x2c829d2e,
+
+ /* XFER_PIO_4 */ 0x0c829c62,
+ /* XFER_PIO_3 */ 0x0c829c84,
+ /* XFER_PIO_2 */ 0x0c829ca6,
+ /* XFER_PIO_1 */ 0x0d029d26,
+ /* XFER_PIO_0 */ 0x0d029d5e
};
-#endif
#define HPT366_DEBUG_DRIVE_INFO 0
#define HPT374_ALLOW_ATA133_6 0
#define HPT371_ALLOW_ATA133_6 0
#define HPT302_ALLOW_ATA133_6 0
-#define HPT372_ALLOW_ATA133_6 1
+#define HPT372_ALLOW_ATA133_6 0
#define HPT370_ALLOW_ATA100_5 1
#define HPT366_ALLOW_ATA66_4 1
#define HPT366_ALLOW_ATA66_3 1
@@ -461,9 +357,10 @@ struct hpt_info
int revision; /* Chipset revision */
int flags; /* Chipset properties */
#define PLL_MODE 1
-#define IS_372N 2
+#define IS_3xxN 2
+#define PCI_66MHZ 4
/* Speed table */
- struct chipset_bus_clock_list_entry *speed;
+ u32 *speed;
};
/*
@@ -600,12 +497,20 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
return 0;
}
-static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table)
+static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
{
- for ( ; chipset_table->xfer_speed ; chipset_table++)
- if (chipset_table->xfer_speed == speed)
- return chipset_table->chipset_settings;
- return chipset_table->chipset_settings;
+ int i;
+
+ /*
+ * Lookup the transfer mode table to get the index into
+ * the timing table.
+ *
+ * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
+ */
+ for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
+ if (xfer_speeds[i] == speed)
+ break;
+ return chipset_table[i];
}
static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
@@ -956,156 +861,127 @@ static int hpt374_ide_dma_end (ide_drive_t *drive)
}
/**
- * hpt372n_set_clock - perform clock switching dance
- * @drive: Drive to switch
- * @mode: Switching mode (0x21 for write, 0x23 otherwise)
+ * hpt3xxn_set_clock - perform clock switching dance
+ * @hwif: hwif to switch
+ * @mode: clocking mode (0x21 for write, 0x23 otherwise)
*
- * Switch the DPLL clock on the HPT372N devices. This is a
- * right mess.
+ * Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
+ * NOTE: avoid touching the disabled primary channel on HPT371N -- it
+ * doesn't physically exist anyway...
*/
-
-static void hpt372n_set_clock(ide_drive_t *drive, int mode)
+
+static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
{
- ide_hwif_t *hwif = HWIF(drive);
-
- /* FIXME: should we check for DMA active and BUG() */
+ u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b);
+
+ if ((scr2 & 0x7f) == mode)
+ return;
+
+ /* MISC. control register 1 has the channel enable bit... */
+ mcr1 = hwif->INB(hwif->dma_master + 0x70);
+
/* Tristate the bus */
- outb(0x80, hwif->dma_base+0x73);
- outb(0x80, hwif->dma_base+0x77);
-
+ if (mcr1 & 0x04)
+ hwif->OUTB(0x80, hwif->dma_master + 0x73);
+ hwif->OUTB(0x80, hwif->dma_master + 0x77);
+
/* Switch clock and reset channels */
- outb(mode, hwif->dma_base+0x7B);
- outb(0xC0, hwif->dma_base+0x79);
-
+ hwif->OUTB(mode, hwif->dma_master + 0x7b);
+ hwif->OUTB(0xc0, hwif->dma_master + 0x79);
+
/* Reset state machines */
- outb(0x37, hwif->dma_base+0x70);
- outb(0x37, hwif->dma_base+0x74);
-
+ if (mcr1 & 0x04)
+ hwif->OUTB(0x37, hwif->dma_master + 0x70);
+ hwif->OUTB(0x37, hwif->dma_master + 0x74);
+
/* Complete reset */
- outb(0x00, hwif->dma_base+0x79);
-
+ hwif->OUTB(0x00, hwif->dma_master + 0x79);
+
/* Reconnect channels to bus */
- outb(0x00, hwif->dma_base+0x73);
- outb(0x00, hwif->dma_base+0x77);
+ if (mcr1 & 0x04)
+ hwif->OUTB(0x00, hwif->dma_master + 0x73);
+ hwif->OUTB(0x00, hwif->dma_master + 0x77);
}
/**
- * hpt372n_rw_disk - prepare for I/O
+ * hpt3xxn_rw_disk - prepare for I/O
* @drive: drive for command
* @rq: block request structure
*
- * This is called when a disk I/O is issued to the 372N.
+ * This is called when a disk I/O is issued to HPT3xxN.
* We need it because of the clock switching.
*/
-static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq)
-{
- ide_hwif_t *hwif = drive->hwif;
- int wantclock;
-
- wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
-
- if (hwif->config_data != wantclock) {
- hpt372n_set_clock(drive, wantclock);
- hwif->config_data = wantclock;
- }
-}
-
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-
-static void hpt3xx_reset (ide_drive_t *drive)
-{
-}
-
-static int hpt3xx_tristate (ide_drive_t * drive, int state)
+static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40;
- u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
-
- pci_read_config_byte(dev, 0x59, &reg59h);
- pci_read_config_byte(dev, state_reg, &regXXh);
+ u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
- if (state) {
- (void) ide_do_reset(drive);
- pci_write_config_byte(dev, state_reg, regXXh|0x80);
- pci_write_config_byte(dev, 0x59, reg59h|reset);
- } else {
- pci_write_config_byte(dev, 0x59, reg59h & ~(reset));
- pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));
- (void) ide_do_reset(drive);
- }
- return 0;
+ hpt3xxn_set_clock(hwif, wantclock);
}
/*
- * set/get power state for a drive.
- * turning the power off does the following things:
- * 1) soft-reset the drive
- * 2) tri-states the ide bus
+ * Set/get power state for a drive.
*
- * when we turn things back on, we need to re-initialize things.
+ * When we turn the power back on, we need to re-initialize things.
*/
#define TRISTATE_BIT 0x8000
-static int hpt370_busproc(ide_drive_t * drive, int state)
+
+static int hpt3xx_busproc(ide_drive_t *drive, int state)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = hwif->pci_dev;
- u8 tristate = 0, resetmask = 0, bus_reg = 0;
- u16 tri_reg;
+ u8 tristate, resetmask, bus_reg = 0;
+ u16 tri_reg = 0;
hwif->bus_state = state;
if (hwif->channel) {
/* secondary channel */
- tristate = 0x56;
- resetmask = 0x80;
+ tristate = 0x56;
+ resetmask = 0x80;
} else {
/* primary channel */
- tristate = 0x52;
+ tristate = 0x52;
resetmask = 0x40;
}
- /* grab status */
+ /* Grab the status. */
pci_read_config_word(dev, tristate, &tri_reg);
pci_read_config_byte(dev, 0x59, &bus_reg);
- /* set the state. we don't set it if we don't need to do so.
- * make sure that the drive knows that it has failed if it's off */
+ /*
+ * Set the state. We don't set it if we don't need to do so.
+ * Make sure that the drive knows that it has failed if it's off.
+ */
switch (state) {
case BUSSTATE_ON:
- hwif->drives[0].failures = 0;
- hwif->drives[1].failures = 0;
- if ((bus_reg & resetmask) == 0)
+ if (!(bus_reg & resetmask))
return 0;
- tri_reg &= ~TRISTATE_BIT;
- bus_reg &= ~resetmask;
- break;
+ hwif->drives[0].failures = hwif->drives[1].failures = 0;
+
+ pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
+ pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
+ return 0;
case BUSSTATE_OFF:
- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
- if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask))
+ if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
return 0;
tri_reg &= ~TRISTATE_BIT;
- bus_reg |= resetmask;
break;
case BUSSTATE_TRISTATE:
- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
- if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask))
+ if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT))
return 0;
tri_reg |= TRISTATE_BIT;
- bus_reg |= resetmask;
break;
+ default:
+ return -EINVAL;
}
- pci_write_config_byte(dev, 0x59, bus_reg);
- pci_write_config_word(dev, tristate, tri_reg);
+ hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+ hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+
+ pci_write_config_word(dev, tristate, tri_reg);
+ pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
return 0;
}
@@ -1119,14 +995,14 @@ static void __devinit hpt366_clocking(ide_hwif_t *hwif)
/* detect bus speed by looking at control reg timing: */
switch((reg1 >> 8) & 7) {
case 5:
- info->speed = forty_base_hpt366;
+ info->speed = forty_base_hpt36x;
break;
case 9:
- info->speed = twenty_five_base_hpt366;
+ info->speed = twenty_five_base_hpt36x;
break;
case 7:
default:
- info->speed = thirty_three_base_hpt366;
+ info->speed = thirty_three_base_hpt36x;
break;
}
}
@@ -1136,9 +1012,9 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
struct hpt_info *info = ide_get_hwifdata(hwif);
struct pci_dev *dev = hwif->pci_dev;
int adjust, i;
- u16 freq;
- u32 pll;
- u8 reg5bh;
+ u16 freq = 0;
+ u32 pll, temp = 0;
+ u8 reg5bh = 0, mcr1 = 0;
/*
* default to pci clock. make sure MA15/16 are set to output
@@ -1151,27 +1027,40 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
pci_write_config_byte(dev, 0x5b, 0x23);
/*
- * set up the PLL. we need to adjust it so that it's stable.
- * freq = Tpll * 192 / Tpci
+ * We'll have to read f_CNT value in order to determine
+ * the PCI clock frequency according to the following ratio:
+ *
+ * f_CNT = Fpci * 192 / Fdpll
+ *
+ * First try reading the register in which the HighPoint BIOS
+ * saves f_CNT value before reprogramming the DPLL from its
+ * default setting (which differs for the various chips).
+ * NOTE: This register is only accessible via I/O space.
*
- * Todo. For non x86 should probably check the dword is
- * set to 0xABCDExxx indicating the BIOS saved f_CNT
+ * In case the signature check fails, we'll have to resort to
+ * reading the f_CNT register itself in hopes that nobody has
+ * touched the DPLL yet...
*/
- pci_read_config_word(dev, 0x78, &freq);
- freq &= 0x1FF;
-
+ temp = inl(pci_resource_start(dev, 4) + 0x90);
+ if ((temp & 0xFFFFF000) != 0xABCDE000) {
+ printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n");
+
+ /* Calculate the average value of f_CNT */
+ for (temp = i = 0; i < 128; i++) {
+ pci_read_config_word(dev, 0x78, &freq);
+ temp += freq & 0x1ff;
+ mdelay(1);
+ }
+ freq = temp / 128;
+ } else
+ freq = temp & 0x1ff;
+
/*
- * The 372N uses different PCI clock information and has
- * some other complications
- * On PCI33 timing we must clock switch
- * On PCI66 timing we must NOT use the PCI clock
- *
- * Currently we always set up the PLL for the 372N
+ * HPT3xxN chips use different PCI clock information.
+ * Currently we always set up the PLL for them.
*/
-
- if(info->flags & IS_372N)
- {
- printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
+
+ if (info->flags & IS_3xxN) {
if(freq < 0x55)
pll = F_LOW_PCI_33;
else if(freq < 0x70)
@@ -1180,10 +1069,8 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
pll = F_LOW_PCI_50;
else
pll = F_LOW_PCI_66;
-
- printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll);
-
- /* We always use the pll not the PCI clock on 372N */
+
+ printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll);
}
else
{
@@ -1197,41 +1084,22 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
pll = F_LOW_PCI_66;
if (pll == F_LOW_PCI_33) {
- if (info->revision >= 8)
- info->speed = thirty_three_base_hpt374;
- else if (info->revision >= 5)
- info->speed = thirty_three_base_hpt372;
- else if (info->revision >= 4)
- info->speed = thirty_three_base_hpt370a;
- else
- info->speed = thirty_three_base_hpt370;
+ info->speed = thirty_three_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
} else if (pll == F_LOW_PCI_40) {
/* Unsupported */
} else if (pll == F_LOW_PCI_50) {
- if (info->revision >= 8)
- info->speed = fifty_base_hpt370a;
- else if (info->revision >= 5)
- info->speed = fifty_base_hpt372;
- else if (info->revision >= 4)
- info->speed = fifty_base_hpt370a;
- else
- info->speed = fifty_base_hpt370a;
+ info->speed = fifty_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
} else {
- if (info->revision >= 8) {
- printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
- }
- else if (info->revision >= 5)
- info->speed = sixty_six_base_hpt372;
- else if (info->revision >= 4)
- info->speed = sixty_six_base_hpt370a;
- else
- info->speed = sixty_six_base_hpt370;
+ info->speed = sixty_six_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
}
}
-
+
+ if (pll == F_LOW_PCI_66)
+ info->flags |= PCI_66MHZ;
+
/*
* only try the pll if we don't have a table for the clock
* speed that we're running at. NOTE: the internal PLL will
@@ -1248,11 +1116,8 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
info->flags |= PLL_MODE;
/*
- * FIXME: make this work correctly, esp with 372N as per
- * reference driver code.
- *
- * adjust PLL based upon PCI clock, enable it, and wait for
- * stabilization.
+ * Adjust the PLL based upon the PCI clock, enable it, and
+ * wait for stabilization...
*/
adjust = 0;
freq = (pll < F_LOW_PCI_50) ? 2 : 4;
@@ -1275,22 +1140,12 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
pci_write_config_dword(dev, 0x5c,
pll & ~0x100);
pci_write_config_byte(dev, 0x5b, 0x21);
- if (info->revision >= 8)
- info->speed = fifty_base_hpt370a;
- else if (info->revision >= 5)
- info->speed = fifty_base_hpt372;
- else if (info->revision >= 4)
- info->speed = fifty_base_hpt370a;
- else
- info->speed = fifty_base_hpt370a;
+
+ info->speed = fifty_base_hpt37x;
printk("HPT37X: using 50MHz internal PLL\n");
goto init_hpt37X_done;
}
}
- if (!pci_get_drvdata(dev)) {
- printk("No Clock Stabilization!!!\n");
- return;
- }
pll_recal:
if (adjust & 1)
pll -= (adjust >> 1);
@@ -1300,11 +1155,16 @@ pll_recal:
init_hpt37X_done:
if (!info->speed)
- printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n",
- (info->flags & IS_372N)?"N":"", pll, freq);
- /* reset state engine */
- pci_write_config_byte(dev, 0x50, 0x37);
- pci_write_config_byte(dev, 0x54, 0x37);
+ printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
+ (info->flags & IS_3xxN) ? "N" : "", pll, freq);
+ /*
+ * Reset the state engines.
+ * NOTE: avoid accidentally enabling the primary channel on HPT371N.
+ */
+ pci_read_config_byte(dev, 0x50, &mcr1);
+ if (mcr1 & 0x04)
+ pci_write_config_byte(dev, 0x50, 0x37);
+ pci_write_config_byte(dev, 0x54, 0x37);
udelay(100);
}
@@ -1367,6 +1227,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = ide_get_hwifdata(hwif);
u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
+ int serialize = HPT_SERIALIZE_IO;
hwif->tuneproc = &hpt3xx_tune_drive;
hwif->speedproc = &hpt3xx_tune_chipset;
@@ -1374,8 +1235,20 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
- if(info->flags & IS_372N)
- hwif->rw_disk = &hpt372n_rw_disk;
+ /*
+ * HPT3xxN chips have some complications:
+ *
+ * - on 33 MHz PCI we must clock switch
+ * - on 66 MHz PCI we must NOT use the PCI clock
+ */
+ if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) {
+ /*
+ * Clock is shared between the channels,
+ * so we'll have to serialize them... :-(
+ */
+ serialize = 1;
+ hwif->rw_disk = &hpt3xxn_rw_disk;
+ }
/*
* The HPT37x uses the CBLID pins as outputs for MA15/MA16
@@ -1418,29 +1291,15 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
PCI_FUNC(hwif->pci_dev->devfn));
#endif /* DEBUG */
-#ifdef HPT_SERIALIZE_IO
- /* serialize access to this device */
- if (hwif->mate)
+ /* Serialize access to this device */
+ if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
-#endif
- if (info->revision >= 3) {
- u8 reg5ah = 0;
- pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
- /*
- * set up ioctl for power status.
- * note: power affects both
- * drives on each channel
- */
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt370_busproc;
- } else if (info->revision >= 2) {
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt3xx_tristate;
- } else {
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt3xx_tristate;
- }
+ /*
+ * Set up ioctl for power status.
+ * NOTE: power affects both drives on each channel.
+ */
+ hwif->busproc = &hpt3xx_busproc;
if (!hwif->dma_base) {
hwif->drives[0].autotune = 1;
@@ -1490,7 +1349,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
return;
if(info->speed == NULL) {
- printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n");
+ printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
return;
}
@@ -1519,9 +1378,10 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
{
- struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
- unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4);
- u8 did, rid;
+ struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
+ struct pci_dev *dev = hwif->pci_dev;
+ u16 did = dev->device;
+ u8 rid = 0;
if(info == NULL) {
printk(KERN_WARNING "hpt366: out of memory.\n");
@@ -1529,15 +1389,22 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
}
ide_set_hwifdata(hwif, info);
- if(dmabase) {
- did = inb(dmabase + 0x22);
- rid = inb(dmabase + 0x28);
-
- if((did == 4 && rid == 6) || (did == 5 && rid > 1))
- info->flags |= IS_372N;
+ /* Avoid doing the same thing twice. */
+ if (hwif->channel && hwif->mate) {
+ memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
+ return;
}
- info->revision = hpt_revision(hwif->pci_dev);
+ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid);
+
+ if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) ||
+ ((did == PCI_DEVICE_ID_TTI_HPT372 ||
+ did == PCI_DEVICE_ID_TTI_HPT302 ||
+ did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
+ did == PCI_DEVICE_ID_TTI_HPT372N)
+ info->flags |= IS_3xxN;
+
+ info->revision = hpt_revision(dev);
if (info->revision >= 3)
hpt37x_clocking(hwif);
@@ -1574,6 +1441,23 @@ static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
return ide_setup_pci_device(dev, d);
}
+static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
+{
+ u8 mcr1 = 0;
+
+ /*
+ * HPT371 chips physically have only one channel, the secondary one,
+ * but the primary channel registers do exist! Go figure...
+ * So, we manually disable the non-existing channel here
+ * (if the BIOS hasn't done this already).
+ */
+ pci_read_config_byte(dev, 0x50, &mcr1);
+ if (mcr1 & 0x04)
+ pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04));
+
+ return ide_setup_pci_device(dev, d);
+}
+
static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
@@ -1661,13 +1545,14 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.bootable = OFF_BOARD,
},{ /* 3 */
.name = "HPT371",
- .init_setup = init_setup_hpt37x,
+ .init_setup = init_setup_hpt371,
.init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
.channels = 2,
.autodma = AUTODMA,
+ .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD,
},{ /* 4 */
.name = "HPT374",
@@ -1699,13 +1584,16 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
+ *
+ * NOTE: since we'll have to modify some fields of the ide_pci_device_t
+ * structure depending on the chip's revision, we'd better pass a local
+ * copy down the call chain...
*/
-
static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &hpt366_chipsets[id->driver_data];
+ ide_pci_device_t d = hpt366_chipsets[id->driver_data];
- return d->init_setup(dev, d);
+ return d.init_setup(dev, &d);
}
static struct pci_device_id hpt366_pci_tbl[] = {
@@ -1725,7 +1613,7 @@ static struct pci_driver driver = {
.probe = hpt366_init_one,
};
-static int hpt366_ide_init(void)
+static int __init hpt366_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index c1cec236ecf..f07bbbed177 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -86,15 +86,16 @@ static int __devinit ata66_jmicron(ide_hwif_t *hwif)
{
case PORT_PATA0:
if (control & (1 << 3)) /* 40/80 pin primary */
- return 1;
- return 0;
+ return 0;
+ return 1;
case PORT_PATA1:
if (control5 & (1 << 19)) /* 40/80 pin secondary */
return 0;
return 1;
case PORT_SATA:
- return 1;
+ break;
}
+ return 1; /* Avoid bogus "control reaches end of non-void function" */
}
static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -240,11 +241,11 @@ static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_devi
}
static struct pci_device_id jmicron_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 0},
- { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 1},
- { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 2},
- { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 3},
- { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 4},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+ { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
{ 0, },
};
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index d95714bcee4..8aaea4ea554 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -302,7 +302,7 @@ static struct pci_driver driver = {
.probe = ns87415_init_one,
};
-static int ns87415_ide_init(void)
+static int __init ns87415_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 7a7c2ef78ac..22bbf613f94 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -382,7 +382,7 @@ static struct pci_driver driver = {
.probe = opti621_init_one,
};
-static int opti621_ide_init(void)
+static int __init opti621_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 6c097e80b4d..77a9aaa7dab 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -9,6 +9,7 @@
* Split from:
* linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2005-2006 MontaVista Software, Inc.
* Portions Copyright (C) 1999 Promise Technology, Inc.
* Author: Frank Tiernan (frankt@promise.com)
* Released under terms of General Public License
@@ -38,6 +39,14 @@
#define PDC202_DEBUG_CABLE 0
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
static const char *pdc_quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
"QUANTUM FIREBALLP KA6.4",
@@ -50,37 +59,11 @@ static const char *pdc_quirk_drives[] = {
NULL
};
-#define set_2regs(a, b) \
- do { \
- hwif->OUTB((a + adj), indexreg); \
- hwif->OUTB(b, datareg); \
- } while(0)
-
-#define set_ultra(a, b, c) \
- do { \
- set_2regs(0x10,(a)); \
- set_2regs(0x11,(b)); \
- set_2regs(0x12,(c)); \
- } while(0)
-
-#define set_ata2(a, b) \
- do { \
- set_2regs(0x0e,(a)); \
- set_2regs(0x0f,(b)); \
- } while(0)
-
-#define set_pio(a, b, c) \
- do { \
- set_2regs(0x0c,(a)); \
- set_2regs(0x0d,(b)); \
- set_2regs(0x13,(c)); \
- } while(0)
-
-static u8 pdcnew_ratemask (ide_drive_t *drive)
+static u8 max_dma_rate(struct pci_dev *pdev)
{
u8 mode;
- switch(HWIF(drive)->pci_dev->device) {
+ switch(pdev->device) {
case PCI_DEVICE_ID_PROMISE_20277:
case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20275:
@@ -95,12 +78,21 @@ static u8 pdcnew_ratemask (ide_drive_t *drive)
default:
return 0;
}
- if (!eighty_ninty_three(drive))
- mode = min(mode, (u8)1);
+
return mode;
}
-static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+static u8 pdcnew_ratemask(ide_drive_t *drive)
+{
+ u8 mode = max_dma_rate(HWIF(drive)->pci_dev);
+
+ if (!eighty_ninty_three(drive))
+ mode = min_t(u8, mode, 1);
+
+ return mode;
+}
+
+static int check_in_drive_lists(ide_drive_t *drive, const char **list)
{
struct hd_driveid *id = drive->id;
@@ -120,43 +112,141 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
return 0;
}
-static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+/**
+ * get_indexed_reg - Get indexed register
+ * @hwif: for the port address
+ * @index: index of the indexed register
+ */
+static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
+{
+ u8 value;
+
+ hwif->OUTB(index, hwif->dma_vendor1);
+ value = hwif->INB(hwif->dma_vendor3);
+
+ DBG("index[%02X] value[%02X]\n", index, value);
+ return value;
+}
+
+/**
+ * set_indexed_reg - Set indexed register
+ * @hwif: for the port address
+ * @index: index of the indexed register
+ */
+static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
+{
+ hwif->OUTB(index, hwif->dma_vendor1);
+ hwif->OUTB(value, hwif->dma_vendor3);
+ DBG("index[%02X] value[%02X]\n", index, value);
+}
+
+/*
+ * ATA Timing Tables based on 133 MHz PLL output clock.
+ *
+ * If the PLL outputs 100 MHz clock, the ASIC hardware will set
+ * the timing registers automatically when "set features" command is
+ * issued to the device. However, if the PLL output clock is 133 MHz,
+ * the following tables must be used.
+ */
+static struct pio_timing {
+ u8 reg0c, reg0d, reg13;
+} pio_timings [] = {
+ { 0xfb, 0x2b, 0xac }, /* PIO mode 0, IORDY off, Prefetch off */
+ { 0x46, 0x29, 0xa4 }, /* PIO mode 1, IORDY off, Prefetch off */
+ { 0x23, 0x26, 0x64 }, /* PIO mode 2, IORDY off, Prefetch off */
+ { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */
+ { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */
+};
+
+static struct mwdma_timing {
+ u8 reg0e, reg0f;
+} mwdma_timings [] = {
+ { 0xdf, 0x5f }, /* MWDMA mode 0 */
+ { 0x6b, 0x27 }, /* MWDMA mode 1 */
+ { 0x69, 0x25 }, /* MWDMA mode 2 */
+};
+
+static struct udma_timing {
+ u8 reg10, reg11, reg12;
+} udma_timings [] = {
+ { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */
+ { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */
+ { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */
+ { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */
+ { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */
+ { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */
+ { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */
+};
+
+static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned long indexreg = hwif->dma_vendor1;
- unsigned long datareg = hwif->dma_vendor3;
- u8 thold = 0x10;
- u8 adj = (drive->dn%2) ? 0x08 : 0x00;
- u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed);
-
- if (speed == XFER_UDMA_2) {
- hwif->OUTB((thold + adj), indexreg);
- hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg);
- }
+ u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
+ int err;
- switch (speed) {
- case XFER_UDMA_7:
- speed = XFER_UDMA_6;
- case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break;
- case XFER_UDMA_5: set_ultra(0x1a, 0x02, 0xcb); break;
- case XFER_UDMA_4: set_ultra(0x1a, 0x03, 0xcd); break;
- case XFER_UDMA_3: set_ultra(0x1a, 0x05, 0xcd); break;
- case XFER_UDMA_2: set_ultra(0x2a, 0x07, 0xcd); break;
- case XFER_UDMA_1: set_ultra(0x3a, 0x0a, 0xd0); break;
- case XFER_UDMA_0: set_ultra(0x4a, 0x0f, 0xd5); break;
- case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break;
- case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break;
- case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break;
- case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break;
- case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break;
- case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break;
- case XFER_PIO_1: set_pio(0x46, 0x29, 0xa4); break;
- case XFER_PIO_0: set_pio(0xfb, 0x2b, 0xac); break;
- default:
- ;
- }
+ speed = ide_rate_filter(pdcnew_ratemask(drive), speed);
+
+ /*
+ * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will
+ * automatically set the timing registers based on 100 MHz PLL output.
+ */
+ err = ide_config_drive_speed(drive, speed);
+
+ /*
+ * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
+ * chips, we must override the default register settings...
+ */
+ if (max_dma_rate(hwif->pci_dev) == 4) {
+ u8 mode = speed & 0x07;
+
+ switch (speed) {
+ case XFER_UDMA_6:
+ case XFER_UDMA_5:
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ set_indexed_reg(hwif, 0x10 + adj,
+ udma_timings[mode].reg10);
+ set_indexed_reg(hwif, 0x11 + adj,
+ udma_timings[mode].reg11);
+ set_indexed_reg(hwif, 0x12 + adj,
+ udma_timings[mode].reg12);
+ break;
+
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ set_indexed_reg(hwif, 0x0e + adj,
+ mwdma_timings[mode].reg0e);
+ set_indexed_reg(hwif, 0x0f + adj,
+ mwdma_timings[mode].reg0f);
+ break;
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ set_indexed_reg(hwif, 0x0c + adj,
+ pio_timings[mode].reg0c);
+ set_indexed_reg(hwif, 0x0d + adj,
+ pio_timings[mode].reg0d);
+ set_indexed_reg(hwif, 0x13 + adj,
+ pio_timings[mode].reg13);
+ break;
+ default:
+ printk(KERN_ERR "pdc202xx_new: "
+ "Unknown speed %d ignored\n", speed);
+ }
+ } else if (speed == XFER_UDMA_2) {
+ /* Set tHOLD bit to 0 if using UDMA mode 2 */
+ u8 tmp = get_indexed_reg(hwif, 0x10 + adj);
- return (ide_config_drive_speed(drive, speed));
+ set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
+ }
+
+ return err;
}
/* 0 1 2 3 4 5 6 7 8
@@ -168,55 +258,55 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
*/
static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
{
- u8 speed;
-
- if (pio == 5) pio = 4;
- speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
-
- (void)pdcnew_new_tune_chipset(drive, speed);
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+ (void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio);
}
-static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif)
+static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
{
- hwif->OUTB(0x0b, hwif->dma_vendor1);
- return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04)));
+ return get_indexed_reg(hwif, 0x0b) & 0x04;
}
-static int config_chipset_for_dma (ide_drive_t *drive)
+
+static int config_chipset_for_dma(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
- u8 speed = -1;
- u8 cable;
-
- u8 ultra_66 = ((id->dma_ultra & 0x0010) ||
- (id->dma_ultra & 0x0008)) ? 1 : 0;
-
- cable = pdcnew_new_cable_detect(hwif);
+ u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0;
+ u8 cable = pdcnew_cable_detect(hwif);
+ u8 speed;
if (ultra_66 && cable) {
- printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary");
+ printk(KERN_WARNING "Warning: %s channel "
+ "requires an 80-pin cable for operation.\n",
+ hwif->channel ? "Secondary" : "Primary");
printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name);
}
if (drive->media != ide_disk)
return 0;
- if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */
- hwif->OUTB((0x13 + ((drive->dn%2) ? 0x08 : 0x00)), hwif->dma_vendor1);
- hwif->OUTB((hwif->INB(hwif->dma_vendor3)|0x03), hwif->dma_vendor3);
+
+ if (id->capability & 4) {
+ /*
+ * Set IORDY_EN & PREFETCH_EN (this seems to have
+ * NO real effect since this register is reloaded
+ * by hardware when the transfer mode is selected)
+ */
+ u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00;
+
+ tmp = get_indexed_reg(hwif, 0x13 + adj);
+ set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03);
}
speed = ide_dma_speed(drive, pdcnew_ratemask(drive));
- if (!(speed)) {
- hwif->tuneproc(drive, 5);
+ if (!speed)
return 0;
- }
(void) hwif->speedproc(drive, speed);
return ide_dma_enable(drive);
}
-static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive)
+static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id;
@@ -234,16 +324,16 @@ static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive)
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
- hwif->tuneproc(drive, 5);
+ hwif->tuneproc(drive, 255);
return hwif->ide_dma_off_quietly(drive);
}
/* IORDY not supported */
return 0;
}
-static int pdcnew_quirkproc (ide_drive_t *drive)
+static int pdcnew_quirkproc(ide_drive_t *drive)
{
- return ((int) check_in_drive_lists(drive, pdc_quirk_drives));
+ return check_in_drive_lists(drive, pdc_quirk_drives);
}
static int pdcnew_ide_dma_lostirq(ide_drive_t *drive)
@@ -260,21 +350,100 @@ static int pdcnew_ide_dma_timeout(ide_drive_t *drive)
return __ide_dma_timeout(drive);
}
-static void pdcnew_new_reset (ide_drive_t *drive)
+static void pdcnew_reset(ide_drive_t *drive)
{
/*
* Deleted this because it is redundant from the caller.
*/
- printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
+ printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",
HWIF(drive)->channel ? "Secondary" : "Primary");
}
+/**
+ * read_counter - Read the byte count registers
+ * @dma_base: for the port address
+ */
+static long __devinit read_counter(u32 dma_base)
+{
+ u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;
+ u8 cnt0, cnt1, cnt2, cnt3;
+ long count = 0, last;
+ int retry = 3;
+
+ do {
+ last = count;
+
+ /* Read the current count */
+ outb(0x20, pri_dma_base + 0x01);
+ cnt0 = inb(pri_dma_base + 0x03);
+ outb(0x21, pri_dma_base + 0x01);
+ cnt1 = inb(pri_dma_base + 0x03);
+ outb(0x20, sec_dma_base + 0x01);
+ cnt2 = inb(sec_dma_base + 0x03);
+ outb(0x21, sec_dma_base + 0x01);
+ cnt3 = inb(sec_dma_base + 0x03);
+
+ count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0;
+
+ /*
+ * The 30-bit decrementing counter is read in 4 pieces.
+ * Incorrect value may be read when the most significant bytes
+ * are changing...
+ */
+ } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count));
+
+ DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n",
+ cnt0, cnt1, cnt2, cnt3);
+
+ return count;
+}
+
+/**
+ * detect_pll_input_clock - Detect the PLL input clock in Hz.
+ * @dma_base: for the port address
+ * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock.
+ */
+static long __devinit detect_pll_input_clock(unsigned long dma_base)
+{
+ long start_count, end_count;
+ long pll_input;
+ u8 scr1;
+
+ start_count = read_counter(dma_base);
+
+ /* Start the test mode */
+ outb(0x01, dma_base + 0x01);
+ scr1 = inb(dma_base + 0x03);
+ DBG("scr1[%02X]\n", scr1);
+ outb(scr1 | 0x40, dma_base + 0x03);
+
+ /* Let the counter run for 10 ms. */
+ mdelay(10);
+
+ end_count = read_counter(dma_base);
+
+ /* Stop the test mode */
+ outb(0x01, dma_base + 0x01);
+ scr1 = inb(dma_base + 0x03);
+ DBG("scr1[%02X]\n", scr1);
+ outb(scr1 & ~0x40, dma_base + 0x03);
+
+ /*
+ * Calculate the input clock in Hz
+ * (the clock counter is 30 bit wide and counts down)
+ */
+ pll_input = ((start_count - end_count) & 0x3ffffff) * 100;
+
+ DBG("start[%ld] end[%ld]\n", start_count, end_count);
+
+ return pll_input;
+}
+
#ifdef CONFIG_PPC_PMAC
static void __devinit apple_kiwi_init(struct pci_dev *pdev)
{
struct device_node *np = pci_device_to_OF_node(pdev);
unsigned int class_rev = 0;
- void __iomem *mmio;
u8 conf;
if (np == NULL || !device_is_compatible(np, "kiwi-root"))
@@ -285,30 +454,20 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
if (class_rev >= 0x03) {
/* Setup chip magic config stuff (from darwin) */
- pci_read_config_byte(pdev, 0x40, &conf);
- pci_write_config_byte(pdev, 0x40, conf | 0x01);
- }
- mmio = ioremap(pci_resource_start(pdev, 5),
- pci_resource_len(pdev, 5));
-
- /* Setup some PLL stuffs */
- switch (pdev->device) {
- case PCI_DEVICE_ID_PROMISE_20270:
- writew(0x0d2b, mmio + 0x1202);
- mdelay(30);
- break;
- case PCI_DEVICE_ID_PROMISE_20271:
- writew(0x0826, mmio + 0x1202);
- mdelay(30);
- break;
+ pci_read_config_byte (pdev, 0x40, &conf);
+ pci_write_config_byte(pdev, 0x40, (conf | 0x01));
}
-
- iounmap(mmio);
}
#endif /* CONFIG_PPC_PMAC */
static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name)
{
+ unsigned long dma_base = pci_resource_start(dev, 4);
+ unsigned long sec_dma_base = dma_base + 0x08;
+ long pll_input, pll_output, ratio;
+ int f, r;
+ u8 pll_ctl0, pll_ctl1;
+
if (dev->resource[PCI_ROM_RESOURCE].start) {
pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
@@ -320,6 +479,106 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
apple_kiwi_init(dev);
#endif
+ /* Calculate the required PLL output frequency */
+ switch(max_dma_rate(dev)) {
+ case 4: /* it's 133 MHz for Ultra133 chips */
+ pll_output = 133333333;
+ break;
+ case 3: /* and 100 MHz for Ultra100 chips */
+ default:
+ pll_output = 100000000;
+ break;
+ }
+
+ /*
+ * Detect PLL input clock.
+ * On some systems, where PCI bus is running at non-standard clock rate
+ * (e.g. 25 or 40 MHz), we have to adjust the cycle time.
+ * PDC20268 and newer chips employ PLL circuit to help correct timing
+ * registers setting.
+ */
+ pll_input = detect_pll_input_clock(dma_base);
+ printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000);
+
+ /* Sanity check */
+ if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
+ printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n",
+ name, pll_input);
+ goto out;
+ }
+
+#ifdef DEBUG
+ DBG("pll_output is %ld Hz\n", pll_output);
+
+ /* Show the current clock value of PLL control register
+ * (maybe already configured by the BIOS)
+ */
+ outb(0x02, sec_dma_base + 0x01);
+ pll_ctl0 = inb(sec_dma_base + 0x03);
+ outb(0x03, sec_dma_base + 0x01);
+ pll_ctl1 = inb(sec_dma_base + 0x03);
+
+ DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+ /*
+ * Calculate the ratio of F, R and NO
+ * POUT = (F + 2) / (( R + 2) * NO)
+ */
+ ratio = pll_output / (pll_input / 1000);
+ if (ratio < 8600L) { /* 8.6x */
+ /* Using NO = 0x01, R = 0x0d */
+ r = 0x0d;
+ } else if (ratio < 12900L) { /* 12.9x */
+ /* Using NO = 0x01, R = 0x08 */
+ r = 0x08;
+ } else if (ratio < 16100L) { /* 16.1x */
+ /* Using NO = 0x01, R = 0x06 */
+ r = 0x06;
+ } else if (ratio < 64000L) { /* 64x */
+ r = 0x00;
+ } else {
+ /* Invalid ratio */
+ printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio);
+ goto out;
+ }
+
+ f = (ratio * (r + 2)) / 1000 - 2;
+
+ DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio);
+
+ if (unlikely(f < 0 || f > 127)) {
+ /* Invalid F */
+ printk(KERN_ERR "%s: F[%d] invalid!\n", name, f);
+ goto out;
+ }
+
+ pll_ctl0 = (u8) f;
+ pll_ctl1 = (u8) r;
+
+ DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+
+ outb(0x02, sec_dma_base + 0x01);
+ outb(pll_ctl0, sec_dma_base + 0x03);
+ outb(0x03, sec_dma_base + 0x01);
+ outb(pll_ctl1, sec_dma_base + 0x03);
+
+ /* Wait the PLL circuit to be stable */
+ mdelay(30);
+
+#ifdef DEBUG
+ /*
+ * Show the current clock value of PLL control register
+ */
+ outb(0x02, sec_dma_base + 0x01);
+ pll_ctl0 = inb(sec_dma_base + 0x03);
+ outb(0x03, sec_dma_base + 0x01);
+ pll_ctl1 = inb(sec_dma_base + 0x03);
+
+ DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+ out:
return dev->irq;
}
@@ -329,8 +588,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->tuneproc = &pdcnew_tune_drive;
hwif->quirkproc = &pdcnew_quirkproc;
- hwif->speedproc = &pdcnew_new_tune_chipset;
- hwif->resetproc = &pdcnew_new_reset;
+ hwif->speedproc = &pdcnew_tune_chipset;
+ hwif->resetproc = &pdcnew_reset;
hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
@@ -342,11 +601,14 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq;
hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout;
- if (!(hwif->udma_four))
- hwif->udma_four = (pdcnew_new_cable_detect(hwif)) ? 0 : 1;
+
+ if (!hwif->udma_four)
+ hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+
if (!noautodma)
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
+
#if PDC202_DEBUG_CABLE
printk(KERN_DEBUG "%s: %s-pin cable\n",
hwif->name, hwif->udma_four ? "80" : "40");
@@ -362,6 +624,7 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev,
ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
+ int ret;
if ((dev->bus->self &&
dev->bus->self->vendor == PCI_VENDOR_ID_DEC) &&
@@ -369,14 +632,16 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev,
if (PCI_SLOT(dev->devfn) & 2)
return -ENODEV;
d->extra = 0;
- while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
+ while ((findev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
if ((findev->vendor == dev->vendor) &&
(findev->device == dev->device) &&
(PCI_SLOT(findev->devfn) & 2)) {
if (findev->irq != dev->irq) {
findev->irq = dev->irq;
}
- return ide_setup_pci_devices(dev, findev, d);
+ ret = ide_setup_pci_devices(dev, findev, d);
+ pci_dev_put(findev);
+ return ret;
}
}
}
@@ -491,7 +756,7 @@ static struct pci_driver driver = {
.probe = pdc202new_init_one,
};
-static int pdc202new_ide_init(void)
+static int __init pdc202new_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 184cdacddeb..143239c093d 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -719,7 +719,7 @@ static struct pci_driver driver = {
.probe = pdc202xx_init_one,
};
-static int pdc202xx_ide_init(void)
+static int __init pdc202xx_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index cdc3aab9ebc..edb37f3d558 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,13 +1,14 @@
/*
- * linux/drivers/ide/pci/piix.c Version 0.44 March 20, 2003
+ * linux/drivers/ide/pci/piix.c Version 0.45 May 12, 2006
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ * Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com>
*
* May be copied or modified under the terms of the GNU General Public License
*
- * PIO mode setting function for Intel chipsets.
+ * PIO mode setting function for Intel chipsets.
* For use instead of BIOS settings.
*
* 40-41
@@ -25,7 +26,7 @@
* sitre = word42 & 0x4000; secondary
*
* 44 8421|8421 hdd|hdb
- *
+ *
* 48 8421 hdd|hdc|hdb|hda udma enabled
*
* 0001 hda
@@ -353,56 +354,24 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed)
}
/**
- * piix_faulty_dma0 - check for DMA0 errata
- * @hwif: IDE interface to check
- *
- * If an ICH/ICH0/ICH2 interface is is operating in multi-word
- * DMA mode with 600nS cycle time the IDE PIO prefetch buffer will
- * inadvertently provide an extra piece of secondary data to the primary
- * device resulting in data corruption.
- *
- * With such a device this test function returns true. This allows
- * our tuning code to follow Intel recommendations and use PIO on
- * such devices.
- */
-
-static int piix_faulty_dma0(ide_hwif_t *hwif)
-{
- switch(hwif->pci_dev->device)
- {
- case PCI_DEVICE_ID_INTEL_82801AA_1: /* ICH */
- case PCI_DEVICE_ID_INTEL_82801AB_1: /* ICH0 */
- case PCI_DEVICE_ID_INTEL_82801BA_8: /* ICH2 */
- case PCI_DEVICE_ID_INTEL_82801BA_9: /* ICH2 */
- return 1;
- }
- return 0;
-}
-
-/**
* piix_config_drive_for_dma - configure drive for DMA
* @drive: IDE drive to configure
*
* Set up a PIIX interface channel for the best available speed.
- * We prefer UDMA if it is available and then MWDMA. If DMA is
- * not available we switch to PIO and return 0.
+ * We prefer UDMA if it is available and then MWDMA. If DMA is
+ * not available we switch to PIO and return 0.
*/
static int piix_config_drive_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, piix_ratemask(drive));
-
- /* Some ICH devices cannot support DMA mode 0 */
- if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive)))
- speed = 0;
-
- /* If no DMA speed was available or the chipset has DMA bugs
- then disable DMA and use PIO */
-
- if (!speed || no_piix_dma) {
- u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
- speed = piix_dma_2_pio(XFER_PIO_0 + tspeed);
- }
+
+ /*
+ * If no DMA speed was available or the chipset has DMA bugs
+ * then disable DMA and use PIO
+ */
+ if (!speed || no_piix_dma)
+ return 0;
(void) piix_tune_chipset(drive, speed);
return ide_dma_enable(drive);
@@ -425,17 +394,16 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive)
if ((id->capability & 1) && drive->autodma) {
- if (ide_use_dma(drive)) {
- if (piix_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
+ if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
+ return hwif->ide_dma_on(drive);
goto fast_ata_pio;
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
/* Find best PIO mode. */
- hwif->tuneproc(drive, 255);
+ (void) hwif->speedproc(drive, XFER_PIO_0 +
+ ide_get_best_pio_mode(drive, 255, 4, NULL));
return hwif->ide_dma_off_quietly(drive);
}
/* IORDY not supported */
@@ -505,6 +473,10 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
/* This is a painful system best to let it self tune for now */
return;
}
+ /* ESB2 appears to generate spurious DMA interrupts in PIO mode
+ when in native mode */
+ if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
+ hwif->atapi_irq_bogon = 1;
hwif->autodma = 0;
hwif->tuneproc = &piix_tune_drive;
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 5f6950c2d1d..c1855311052 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -77,7 +77,7 @@ static struct pci_driver driver = {
.probe = rz1000_init_one,
};
-static int rz1000_ide_init(void)
+static int __init rz1000_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index ff80937d94d..8d762d323f8 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -507,7 +507,7 @@ static struct pci_driver driver = {
#endif
};
-static int sc1200_ide_init(void)
+static int __init sc1200_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 057548d0720..ea9a28a4585 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -666,7 +666,7 @@ static struct pci_driver driver = {
.probe = svwks_init_one,
};
-static int svwks_ide_init(void)
+static int __init svwks_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index cfad09accf5..b0bf0180927 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -762,8 +762,7 @@ static struct ioc4_submodule ioc4_ide_submodule = {
/* .is_remove = ioc4_ide_remove_one, */
};
-static int __devinit
-ioc4_ide_init(void)
+static int __init ioc4_ide_init(void)
{
return ioc4_register_submodule(&ioc4_ide_submodule);
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 697f566fb90..4ff89c7d990 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1096,7 +1096,7 @@ static struct pci_driver driver = {
.probe = siimage_init_one,
};
-static int siimage_ide_init(void)
+static int __init siimage_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 92edf76bd7a..1afff659ab5 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -800,9 +800,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
if (trueid == 0x5517) { /* SiS 961/961B */
- lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */
+ lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
pci_read_config_byte(dev, 0x49, &prefctl);
+ pci_dev_put(lpc_bridge);
if (sbrev == 0x10 && (prefctl & 0x80)) {
printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
@@ -967,7 +968,7 @@ static struct pci_driver driver = {
.probe = sis5513_init_one,
};
-static int sis5513_ide_init(void)
+static int __init sis5513_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 0b4b6049851..170a2619905 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -299,14 +299,14 @@ static void sl82c105_selectproc(ide_drive_t *drive)
//DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16;
- old = val = *((u32 *)&hwif->hwif_data);
+ old = val = (u32)pci_get_drvdata(dev);
if (drive->using_dma)
val &= ~mask;
else
val |= mask;
if (old != val) {
pci_write_config_dword(dev, 0x40, val);
- *((u32 *)&hwif->hwif_data) = val;
+ pci_set_drvdata(dev, (void *)val);
}
}
@@ -316,14 +316,13 @@ static void sl82c105_selectproc(ide_drive_t *drive)
*/
static void sl82c105_resetproc(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
u32 val;
DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
pci_read_config_dword(dev, 0x40, &val);
- *((u32 *)&hwif->hwif_data) = val;
+ pci_set_drvdata(dev, (void *)val);
}
/*
@@ -394,6 +393,7 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
pci_read_config_dword(dev, 0x40, &val);
val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
pci_write_config_dword(dev, 0x40, val);
+ pci_set_drvdata(dev, (void *)val);
return dev->irq;
}
@@ -404,30 +404,25 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
unsigned int rev;
u8 dma_state;
- u32 val;
-
+
DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
hwif->tuneproc = tune_sl82c105;
hwif->selectproc = sl82c105_selectproc;
hwif->resetproc = sl82c105_resetproc;
-
- /* Default to PIO 0 for fallback unless tuned otherwise,
- * we always autotune PIO, this is done before DMA is
- * checked, so there is no risk of accidentally disabling
- * DMA
- */
+
+ /*
+ * Default to PIO 0 for fallback unless tuned otherwise.
+ * We always autotune PIO, this is done before DMA is checked,
+ * so there's no risk of accidentally disabling DMA
+ */
hwif->drives[0].pio_speed = XFER_PIO_0;
hwif->drives[0].autotune = 1;
- hwif->drives[1].pio_speed = XFER_PIO_1;
+ hwif->drives[1].pio_speed = XFER_PIO_0;
hwif->drives[1].autotune = 1;
- pci_read_config_dword(dev, 0x40, &val);
- *((u32 *)&hwif->hwif_data) = val;
-
hwif->atapi_dma = 0;
hwif->mwdma_mask = 0;
hwif->swdma_mask = 0;
@@ -497,7 +492,7 @@ static struct pci_driver driver = {
.probe = sl82c105_init_one,
};
-static int sl82c105_ide_init(void)
+static int __init sl82c105_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 4a1853af3bb..90e79c0844d 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -1,9 +1,10 @@
/*
- * linux/drivers/ide/pci/slc90e66.c Version 0.11 September 11, 2002
+ * linux/drivers/ide/pci/slc90e66.c Version 0.12 May 12, 2006
*
* Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com>
*
- * This a look-a-like variation of the ICH0 PIIX4 Ultra-66,
+ * This is a look-alike variation of the ICH0 PIIX4 Ultra-66,
* but this keeps the ISA-Bridge and slots alive.
*
*/
@@ -158,10 +159,8 @@ static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive));
- if (!(speed)) {
- u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
- speed = slc90e66_dma_2_pio(XFER_PIO_0 + tspeed);
- }
+ if (!speed)
+ return 0;
(void) slc90e66_tune_chipset(drive, speed);
return ide_dma_enable(drive);
@@ -176,16 +175,15 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->autodma) {
- if (ide_use_dma(drive)) {
- if (slc90e66_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
+ if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
+ return hwif->ide_dma_on(drive);
goto fast_ata_pio;
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
- hwif->tuneproc(drive, 5);
+ (void) hwif->speedproc(drive, XFER_PIO_0 +
+ ide_get_best_pio_mode(drive, 255, 4, NULL));
return hwif->ide_dma_off_quietly(drive);
}
/* IORDY not supported */
@@ -255,7 +253,7 @@ static struct pci_driver driver = {
.probe = slc90e66_init_one,
};
-static int slc90e66_ide_init(void)
+static int __init slc90e66_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index 56d84931d6d..b13cce1fd1a 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -173,7 +173,7 @@ static struct pci_driver driver = {
.probe = triflex_init_one,
};
-static int triflex_ide_init(void)
+static int __init triflex_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 2a282529bfc..174b88c4780 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -355,7 +355,7 @@ static struct pci_driver driver = {
.probe = trm290_init_one,
};
-static int trm290_ide_init(void)
+static int __init trm290_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 61f1a9665a7..6fb6e50b823 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -78,6 +78,8 @@ static struct via_isa_bridge {
u8 rev_max;
u16 flags;
} via_isa_bridges[] = {
+ { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+ { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
@@ -123,7 +125,7 @@ struct via82cxxx_dev
static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
{
struct pci_dev *dev = hwif->pci_dev;
- struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif);
+ struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
u8 t;
if (~vdev->via_config->flags & VIA_BAD_AST) {
@@ -162,7 +164,7 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
static int via_set_drive(ide_drive_t *drive, u8 speed)
{
ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
- struct via82cxxx_dev *vdev = ide_get_hwifdata(drive->hwif);
+ struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev);
struct ide_timing t, p;
unsigned int T, UT;
@@ -225,7 +227,7 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
static int via82cxxx_ide_dma_check (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif);
+ struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
u16 w80 = hwif->udma_four;
u16 speed = ide_find_best_mode(drive,
@@ -262,6 +264,53 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
return via_config;
}
+/*
+ * Check and handle 80-wire cable presence
+ */
+static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
+{
+ int i;
+
+ switch (vdev->via_config->flags & VIA_UDMA) {
+ case VIA_UDMA_66:
+ for (i = 24; i >= 0; i -= 8)
+ if (((u >> (i & 16)) & 8) &&
+ ((u >> i) & 0x20) &&
+ (((u >> i) & 7) < 2)) {
+ /*
+ * 2x PCI clock and
+ * UDMA w/ < 3T/cycle
+ */
+ vdev->via_80w |= (1 << (1 - (i >> 4)));
+ }
+ break;
+
+ case VIA_UDMA_100:
+ for (i = 24; i >= 0; i -= 8)
+ if (((u >> i) & 0x10) ||
+ (((u >> i) & 0x20) &&
+ (((u >> i) & 7) < 4))) {
+ /* BIOS 80-wire bit or
+ * UDMA w/ < 60ns/cycle
+ */
+ vdev->via_80w |= (1 << (1 - (i >> 4)));
+ }
+ break;
+
+ case VIA_UDMA_133:
+ for (i = 24; i >= 0; i -= 8)
+ if (((u >> i) & 0x10) ||
+ (((u >> i) & 0x20) &&
+ (((u >> i) & 7) < 6))) {
+ /* BIOS 80-wire bit or
+ * UDMA w/ < 60ns/cycle
+ */
+ vdev->via_80w |= (1 << (1 - (i >> 4)));
+ }
+ break;
+ }
+}
+
/**
* init_chipset_via82cxxx - initialization handler
* @dev: PCI device
@@ -274,14 +323,22 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
{
struct pci_dev *isa = NULL;
+ struct via82cxxx_dev *vdev;
struct via_isa_bridge *via_config;
u8 t, v;
- unsigned int u;
+ u32 u;
+
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev) {
+ printk(KERN_ERR "VP_IDE: out of memory :(\n");
+ return -ENOMEM;
+ }
+ pci_set_drvdata(dev, vdev);
/*
* Find the ISA bridge to see how good the IDE is.
*/
- via_config = via_config_find(&isa);
+ vdev->via_config = via_config = via_config_find(&isa);
/* We checked this earlier so if it fails here deeep badness
is involved */
@@ -289,16 +346,17 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
BUG_ON(!via_config->id);
/*
- * Setup or disable Clk66 if appropriate
+ * Detect cable and configure Clk66
*/
+ pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+
+ via_cable_detect(vdev, u);
if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
/* Enable Clk66 */
- pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
} else if (via_config->flags & VIA_BAD_CLK66) {
/* Would cause trouble on 596a and 686 */
- pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008);
}
@@ -367,75 +425,11 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
return 0;
}
-/*
- * Check and handle 80-wire cable presence
- */
-static void __devinit via_cable_detect(struct pci_dev *dev, struct via82cxxx_dev *vdev)
-{
- unsigned int u;
- int i;
- pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
-
- switch (vdev->via_config->flags & VIA_UDMA) {
-
- case VIA_UDMA_66:
- for (i = 24; i >= 0; i -= 8)
- if (((u >> (i & 16)) & 8) &&
- ((u >> i) & 0x20) &&
- (((u >> i) & 7) < 2)) {
- /*
- * 2x PCI clock and
- * UDMA w/ < 3T/cycle
- */
- vdev->via_80w |= (1 << (1 - (i >> 4)));
- }
- break;
-
- case VIA_UDMA_100:
- for (i = 24; i >= 0; i -= 8)
- if (((u >> i) & 0x10) ||
- (((u >> i) & 0x20) &&
- (((u >> i) & 7) < 4))) {
- /* BIOS 80-wire bit or
- * UDMA w/ < 60ns/cycle
- */
- vdev->via_80w |= (1 << (1 - (i >> 4)));
- }
- break;
-
- case VIA_UDMA_133:
- for (i = 24; i >= 0; i -= 8)
- if (((u >> i) & 0x10) ||
- (((u >> i) & 0x20) &&
- (((u >> i) & 7) < 6))) {
- /* BIOS 80-wire bit or
- * UDMA w/ < 60ns/cycle
- */
- vdev->via_80w |= (1 << (1 - (i >> 4)));
- }
- break;
-
- }
-}
-
static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
{
- struct via82cxxx_dev *vdev = kmalloc(sizeof(struct via82cxxx_dev),
- GFP_KERNEL);
- struct pci_dev *isa = NULL;
+ struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
int i;
- if (vdev == NULL) {
- printk(KERN_ERR "VP_IDE: out of memory :(\n");
- return;
- }
-
- memset(vdev, 0, sizeof(struct via82cxxx_dev));
- ide_set_hwifdata(hwif, vdev);
-
- vdev->via_config = via_config_find(&isa);
- via_cable_detect(hwif->pci_dev, vdev);
-
hwif->autodma = 0;
hwif->tuneproc = &via82cxxx_tune_drive;
@@ -512,6 +506,7 @@ static struct pci_device_id via_pci_tbl[] = {
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_SATA_EIDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, via_pci_tbl);
@@ -522,7 +517,7 @@ static struct pci_driver driver = {
.probe = via_init_one,
};
-static int via_ide_init(void)
+static int __init via_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 0719b648482..695e23904d3 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -844,11 +844,11 @@ void __init ide_scan_pcibus (int scan_direction)
pre_init = 0;
if (!scan_direction) {
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
ide_scan_pcidev(dev);
}
} else {
- while ((dev = pci_find_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
ide_scan_pcidev(dev);
}
}
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index af4a78a8ef3..536ba3f580f 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -217,7 +217,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
/* return the index (within a minor number block) of a file */
static inline unsigned char ieee1394_file_to_instance(struct file *file)
{
- return file->f_dentry->d_inode->i_cindex;
+ return file->f_path.dentry->d_inode->i_cindex;
}
extern int hpsb_disable_irm;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 13a617917bf..fbb7f14ec50 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1485,7 +1485,7 @@ static int __devinit add_card(struct pci_dev *dev,
}
- i2c_bit_del_bus(i2c_ad);
+ i2c_del_adapter(i2c_ad);
kfree(i2c_ad);
}
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index e68b80b7340..4325aac7733 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -490,11 +490,11 @@ static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
return -ENOMEM;
}
- cmd->command_orb_dma = dma_map_single(&hi->host->device,
+ cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
&cmd->command_orb,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
- cmd->sge_dma = dma_map_single(&hi->host->device,
+ cmd->sge_dma = dma_map_single(hi->host->device.parent,
&cmd->scatter_gather_element,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
@@ -516,10 +516,11 @@ static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
if (!list_empty(&lu->cmd_orb_completed))
list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
cmd = list_entry(lh, struct sbp2_command_info, list);
- dma_unmap_single(&host->device, cmd->command_orb_dma,
+ dma_unmap_single(host->device.parent,
+ cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
- dma_unmap_single(&host->device, cmd->sge_dma,
+ dma_unmap_single(host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
kfree(cmd);
@@ -601,17 +602,17 @@ static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
if (cmd->cmd_dma) {
if (cmd->dma_type == CMD_DMA_SINGLE)
- dma_unmap_single(&host->device, cmd->cmd_dma,
+ dma_unmap_single(host->device.parent, cmd->cmd_dma,
cmd->dma_size, cmd->dma_dir);
else if (cmd->dma_type == CMD_DMA_PAGE)
- dma_unmap_page(&host->device, cmd->cmd_dma,
+ dma_unmap_page(host->device.parent, cmd->cmd_dma,
cmd->dma_size, cmd->dma_dir);
/* XXX: Check for CMD_DMA_NONE bug */
cmd->dma_type = CMD_DMA_NONE;
cmd->cmd_dma = 0;
}
if (cmd->sge_buffer) {
- dma_unmap_sg(&host->device, cmd->sge_buffer,
+ dma_unmap_sg(host->device.parent, cmd->sge_buffer,
cmd->dma_size, cmd->dma_dir);
cmd->sge_buffer = NULL;
}
@@ -836,37 +837,37 @@ static int sbp2_start_device(struct sbp2_lu *lu)
struct sbp2_fwhost_info *hi = lu->hi;
int error;
- lu->login_response = dma_alloc_coherent(&hi->host->device,
+ lu->login_response = dma_alloc_coherent(hi->host->device.parent,
sizeof(struct sbp2_login_response),
&lu->login_response_dma, GFP_KERNEL);
if (!lu->login_response)
goto alloc_fail;
- lu->query_logins_orb = dma_alloc_coherent(&hi->host->device,
+ lu->query_logins_orb = dma_alloc_coherent(hi->host->device.parent,
sizeof(struct sbp2_query_logins_orb),
&lu->query_logins_orb_dma, GFP_KERNEL);
if (!lu->query_logins_orb)
goto alloc_fail;
- lu->query_logins_response = dma_alloc_coherent(&hi->host->device,
+ lu->query_logins_response = dma_alloc_coherent(hi->host->device.parent,
sizeof(struct sbp2_query_logins_response),
&lu->query_logins_response_dma, GFP_KERNEL);
if (!lu->query_logins_response)
goto alloc_fail;
- lu->reconnect_orb = dma_alloc_coherent(&hi->host->device,
+ lu->reconnect_orb = dma_alloc_coherent(hi->host->device.parent,
sizeof(struct sbp2_reconnect_orb),
&lu->reconnect_orb_dma, GFP_KERNEL);
if (!lu->reconnect_orb)
goto alloc_fail;
- lu->logout_orb = dma_alloc_coherent(&hi->host->device,
+ lu->logout_orb = dma_alloc_coherent(hi->host->device.parent,
sizeof(struct sbp2_logout_orb),
&lu->logout_orb_dma, GFP_KERNEL);
if (!lu->logout_orb)
goto alloc_fail;
- lu->login_orb = dma_alloc_coherent(&hi->host->device,
+ lu->login_orb = dma_alloc_coherent(hi->host->device.parent,
sizeof(struct sbp2_login_orb),
&lu->login_orb_dma, GFP_KERNEL);
if (!lu->login_orb)
@@ -929,32 +930,32 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
list_del(&lu->lu_list);
if (lu->login_response)
- dma_free_coherent(&hi->host->device,
+ dma_free_coherent(hi->host->device.parent,
sizeof(struct sbp2_login_response),
lu->login_response,
lu->login_response_dma);
if (lu->login_orb)
- dma_free_coherent(&hi->host->device,
+ dma_free_coherent(hi->host->device.parent,
sizeof(struct sbp2_login_orb),
lu->login_orb,
lu->login_orb_dma);
if (lu->reconnect_orb)
- dma_free_coherent(&hi->host->device,
+ dma_free_coherent(hi->host->device.parent,
sizeof(struct sbp2_reconnect_orb),
lu->reconnect_orb,
lu->reconnect_orb_dma);
if (lu->logout_orb)
- dma_free_coherent(&hi->host->device,
+ dma_free_coherent(hi->host->device.parent,
sizeof(struct sbp2_logout_orb),
lu->logout_orb,
lu->logout_orb_dma);
if (lu->query_logins_orb)
- dma_free_coherent(&hi->host->device,
+ dma_free_coherent(hi->host->device.parent,
sizeof(struct sbp2_query_logins_orb),
lu->query_logins_orb,
lu->query_logins_orb_dma);
if (lu->query_logins_response)
- dma_free_coherent(&hi->host->device,
+ dma_free_coherent(hi->host->device.parent,
sizeof(struct sbp2_query_logins_response),
lu->query_logins_response,
lu->query_logins_response_dma);
@@ -1445,7 +1446,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
cmd->dma_size = sgpnt[0].length;
cmd->dma_type = CMD_DMA_PAGE;
- cmd->cmd_dma = dma_map_page(&hi->host->device,
+ cmd->cmd_dma = dma_map_page(hi->host->device.parent,
sgpnt[0].page, sgpnt[0].offset,
cmd->dma_size, cmd->dma_dir);
@@ -1457,8 +1458,8 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
&cmd->scatter_gather_element[0];
u32 sg_count, sg_len;
dma_addr_t sg_addr;
- int i, count = dma_map_sg(&hi->host->device, sgpnt, scsi_use_sg,
- dma_dir);
+ int i, count = dma_map_sg(hi->host->device.parent, sgpnt,
+ scsi_use_sg, dma_dir);
cmd->dma_size = scsi_use_sg;
cmd->sge_buffer = sgpnt;
@@ -1508,7 +1509,8 @@ static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
cmd->dma_dir = dma_dir;
cmd->dma_size = scsi_request_bufflen;
cmd->dma_type = CMD_DMA_SINGLE;
- cmd->cmd_dma = dma_map_single(&hi->host->device, scsi_request_buffer,
+ cmd->cmd_dma = dma_map_single(hi->host->device.parent,
+ scsi_request_buffer,
cmd->dma_size, cmd->dma_dir);
orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
orb->misc |= ORB_SET_DIRECTION(orb_direction);
@@ -1626,10 +1628,11 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
size_t length;
unsigned long flags;
- dma_sync_single_for_device(&hi->host->device, cmd->command_orb_dma,
+ dma_sync_single_for_device(hi->host->device.parent,
+ cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
- dma_sync_single_for_device(&hi->host->device, cmd->sge_dma,
+ dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
@@ -1655,14 +1658,15 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
* The target's fetch agent may or may not have read this
* previous ORB yet.
*/
- dma_sync_single_for_cpu(&hi->host->device, last_orb_dma,
+ dma_sync_single_for_cpu(hi->host->device.parent, last_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
wmb();
/* Tells hardware that this pointer is valid */
last_orb->next_ORB_hi = 0;
- dma_sync_single_for_device(&hi->host->device, last_orb_dma,
+ dma_sync_single_for_device(hi->host->device.parent,
+ last_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
addr += SBP2_DOORBELL_OFFSET;
@@ -1790,10 +1794,11 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
else
cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
if (cmd) {
- dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma,
+ dma_sync_single_for_cpu(hi->host->device.parent,
+ cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
- dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
+ dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
/* Grab SCSI command pointers and check status. */
@@ -1882,16 +1887,6 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
if (unlikely(SCpnt->device->lun))
goto done;
- /* handle the request sense command here (auto-request sense) */
- if (SCpnt->cmnd[0] == REQUEST_SENSE) {
- memcpy(SCpnt->request_buffer, SCpnt->sense_buffer,
- SCpnt->request_bufflen);
- memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
- sbp2scsi_complete_command(lu, SBP2_SCSI_STATUS_GOOD, SCpnt,
- done);
- return 0;
- }
-
if (unlikely(!hpsb_node_entry_valid(lu->ne))) {
SBP2_ERR("Bus reset in progress - rejecting command");
result = DID_BUS_BUSY << 16;
@@ -1931,10 +1926,11 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
while (!list_empty(&lu->cmd_orb_inuse)) {
lh = lu->cmd_orb_inuse.next;
cmd = list_entry(lh, struct sbp2_command_info, list);
- dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma,
+ dma_sync_single_for_cpu(hi->host->device.parent,
+ cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
- dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
+ dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
sbp2util_mark_command_completed(lu, cmd);
@@ -2024,6 +2020,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
sdev->use_10_for_rw = 1;
+ if (sdev->type == TYPE_ROM)
+ sdev->use_10_for_ms = 1;
if (sdev->type == TYPE_DISK &&
lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
sdev->skip_ms_page_8 = 1;
@@ -2059,11 +2057,12 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
if (cmd) {
- dma_sync_single_for_cpu(&hi->host->device,
+ dma_sync_single_for_cpu(hi->host->device.parent,
cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
- dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma,
+ dma_sync_single_for_cpu(hi->host->device.parent,
+ cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
sbp2util_mark_command_completed(lu, cmd);
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index 163d991eb8c..50fb1cd447b 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -1,9 +1,11 @@
infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS) := ib_addr.o rdma_cm.o
+user_access-$(CONFIG_INFINIBAND_ADDR_TRANS) := rdma_ucm.o
obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \
ib_cm.o iw_cm.o $(infiniband-y)
obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o
-obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o
+obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \
+ $(user_access-y)
ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
device.o fmr_pool.o cache.o
@@ -18,6 +20,8 @@ iw_cm-y := iwcm.o
rdma_cm-y := cma.o
+rdma_ucm-y := ucma.o
+
ib_addr-y := addr.o
ib_umad-y := user_mad.o
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 79c937bf696..d446998b12a 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3289,6 +3289,10 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
spin_lock_irqsave(&cm_id_priv->lock, flags);
switch (cm_id_priv->id.state) {
+ /* Allow transition to RTS before sending REP */
+ case IB_CM_REQ_RCVD:
+ case IB_CM_MRA_REQ_SENT:
+
case IB_CM_REP_RCVD:
case IB_CM_MRA_REP_SENT:
case IB_CM_REP_SENT:
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 985a6b564d8..9e0ab048c87 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -70,6 +70,7 @@ static DEFINE_MUTEX(lock);
static struct workqueue_struct *cma_wq;
static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
+static DEFINE_IDR(udp_ps);
struct cma_device {
struct list_head list;
@@ -133,7 +134,6 @@ struct rdma_id_private {
u32 seq_num;
u32 qp_num;
- enum ib_qp_type qp_type;
u8 srq;
};
@@ -392,7 +392,6 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
id->qp = qp;
id_priv->qp_num = qp->qp_num;
- id_priv->qp_type = qp->qp_type;
id_priv->srq = (qp->srq != NULL);
return 0;
err:
@@ -510,9 +509,17 @@ static inline int cma_any_addr(struct sockaddr *addr)
return cma_zero_addr(addr) || cma_loopback_addr(addr);
}
+static inline __be16 cma_port(struct sockaddr *addr)
+{
+ if (addr->sa_family == AF_INET)
+ return ((struct sockaddr_in *) addr)->sin_port;
+ else
+ return ((struct sockaddr_in6 *) addr)->sin6_port;
+}
+
static inline int cma_any_port(struct sockaddr *addr)
{
- return !((struct sockaddr_in *) addr)->sin_port;
+ return !cma_port(addr);
}
static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
@@ -594,20 +601,6 @@ static inline int cma_user_data_offset(enum rdma_port_space ps)
}
}
-static int cma_notify_user(struct rdma_id_private *id_priv,
- enum rdma_cm_event_type type, int status,
- void *data, u8 data_len)
-{
- struct rdma_cm_event event;
-
- event.event = type;
- event.status = status;
- event.private_data = data;
- event.private_data_len = data_len;
-
- return id_priv->id.event_handler(&id_priv->id, &event);
-}
-
static void cma_cancel_route(struct rdma_id_private *id_priv)
{
switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
@@ -776,63 +769,61 @@ static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
return 0;
}
-static int cma_rtu_recv(struct rdma_id_private *id_priv)
+static void cma_set_rep_event_data(struct rdma_cm_event *event,
+ struct ib_cm_rep_event_param *rep_data,
+ void *private_data)
{
- int ret;
-
- ret = cma_modify_qp_rts(&id_priv->id);
- if (ret)
- goto reject;
-
- return 0;
-reject:
- cma_modify_qp_err(&id_priv->id);
- ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
- NULL, 0, NULL, 0);
- return ret;
+ event->param.conn.private_data = private_data;
+ event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
+ event->param.conn.responder_resources = rep_data->responder_resources;
+ event->param.conn.initiator_depth = rep_data->initiator_depth;
+ event->param.conn.flow_control = rep_data->flow_control;
+ event->param.conn.rnr_retry_count = rep_data->rnr_retry_count;
+ event->param.conn.srq = rep_data->srq;
+ event->param.conn.qp_num = rep_data->remote_qpn;
}
static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{
struct rdma_id_private *id_priv = cm_id->context;
- enum rdma_cm_event_type event;
- u8 private_data_len = 0;
- int ret = 0, status = 0;
+ struct rdma_cm_event event;
+ int ret = 0;
atomic_inc(&id_priv->dev_remove);
if (!cma_comp(id_priv, CMA_CONNECT))
goto out;
+ memset(&event, 0, sizeof event);
switch (ib_event->event) {
case IB_CM_REQ_ERROR:
case IB_CM_REP_ERROR:
- event = RDMA_CM_EVENT_UNREACHABLE;
- status = -ETIMEDOUT;
+ event.event = RDMA_CM_EVENT_UNREACHABLE;
+ event.status = -ETIMEDOUT;
break;
case IB_CM_REP_RECEIVED:
- status = cma_verify_rep(id_priv, ib_event->private_data);
- if (status)
- event = RDMA_CM_EVENT_CONNECT_ERROR;
+ event.status = cma_verify_rep(id_priv, ib_event->private_data);
+ if (event.status)
+ event.event = RDMA_CM_EVENT_CONNECT_ERROR;
else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
- status = cma_rep_recv(id_priv);
- event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
- RDMA_CM_EVENT_ESTABLISHED;
+ event.status = cma_rep_recv(id_priv);
+ event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :
+ RDMA_CM_EVENT_ESTABLISHED;
} else
- event = RDMA_CM_EVENT_CONNECT_RESPONSE;
- private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
+ event.event = RDMA_CM_EVENT_CONNECT_RESPONSE;
+ cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd,
+ ib_event->private_data);
break;
case IB_CM_RTU_RECEIVED:
- status = cma_rtu_recv(id_priv);
- event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
- RDMA_CM_EVENT_ESTABLISHED;
+ case IB_CM_USER_ESTABLISHED:
+ event.event = RDMA_CM_EVENT_ESTABLISHED;
break;
case IB_CM_DREQ_ERROR:
- status = -ETIMEDOUT; /* fall through */
+ event.status = -ETIMEDOUT; /* fall through */
case IB_CM_DREQ_RECEIVED:
case IB_CM_DREP_RECEIVED:
if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
goto out;
- event = RDMA_CM_EVENT_DISCONNECTED;
+ event.event = RDMA_CM_EVENT_DISCONNECTED;
break;
case IB_CM_TIMEWAIT_EXIT:
case IB_CM_MRA_RECEIVED:
@@ -840,9 +831,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
goto out;
case IB_CM_REJ_RECEIVED:
cma_modify_qp_err(&id_priv->id);
- status = ib_event->param.rej_rcvd.reason;
- event = RDMA_CM_EVENT_REJECTED;
- private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
+ event.status = ib_event->param.rej_rcvd.reason;
+ event.event = RDMA_CM_EVENT_REJECTED;
+ event.param.conn.private_data = ib_event->private_data;
+ event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
break;
default:
printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
@@ -850,8 +842,7 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
goto out;
}
- ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
- private_data_len);
+ ret = id_priv->id.event_handler(&id_priv->id, &event);
if (ret) {
/* Destroy the CM ID by returning a non-zero value. */
id_priv->cm_id.ib = NULL;
@@ -865,8 +856,8 @@ out:
return ret;
}
-static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
- struct ib_cm_event *ib_event)
+static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
+ struct ib_cm_event *ib_event)
{
struct rdma_id_private *id_priv;
struct rdma_cm_id *id;
@@ -913,9 +904,61 @@ err:
return NULL;
}
+static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
+ struct ib_cm_event *ib_event)
+{
+ struct rdma_id_private *id_priv;
+ struct rdma_cm_id *id;
+ union cma_ip_addr *src, *dst;
+ __u16 port;
+ u8 ip_ver;
+ int ret;
+
+ id = rdma_create_id(listen_id->event_handler, listen_id->context,
+ listen_id->ps);
+ if (IS_ERR(id))
+ return NULL;
+
+
+ if (cma_get_net_info(ib_event->private_data, listen_id->ps,
+ &ip_ver, &port, &src, &dst))
+ goto err;
+
+ cma_save_net_info(&id->route.addr, &listen_id->route.addr,
+ ip_ver, port, src, dst);
+
+ ret = rdma_translate_ip(&id->route.addr.src_addr,
+ &id->route.addr.dev_addr);
+ if (ret)
+ goto err;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
+ id_priv->state = CMA_CONNECT;
+ return id_priv;
+err:
+ rdma_destroy_id(id);
+ return NULL;
+}
+
+static void cma_set_req_event_data(struct rdma_cm_event *event,
+ struct ib_cm_req_event_param *req_data,
+ void *private_data, int offset)
+{
+ event->param.conn.private_data = private_data + offset;
+ event->param.conn.private_data_len = IB_CM_REQ_PRIVATE_DATA_SIZE - offset;
+ event->param.conn.responder_resources = req_data->responder_resources;
+ event->param.conn.initiator_depth = req_data->initiator_depth;
+ event->param.conn.flow_control = req_data->flow_control;
+ event->param.conn.retry_count = req_data->retry_count;
+ event->param.conn.rnr_retry_count = req_data->rnr_retry_count;
+ event->param.conn.srq = req_data->srq;
+ event->param.conn.qp_num = req_data->remote_qpn;
+}
+
static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{
struct rdma_id_private *listen_id, *conn_id;
+ struct rdma_cm_event event;
int offset, ret;
listen_id = cm_id->context;
@@ -925,7 +968,19 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
goto out;
}
- conn_id = cma_new_id(&listen_id->id, ib_event);
+ memset(&event, 0, sizeof event);
+ offset = cma_user_data_offset(listen_id->id.ps);
+ event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
+ if (listen_id->id.ps == RDMA_PS_UDP) {
+ conn_id = cma_new_udp_id(&listen_id->id, ib_event);
+ event.param.ud.private_data = ib_event->private_data + offset;
+ event.param.ud.private_data_len =
+ IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE - offset;
+ } else {
+ conn_id = cma_new_conn_id(&listen_id->id, ib_event);
+ cma_set_req_event_data(&event, &ib_event->param.req_rcvd,
+ ib_event->private_data, offset);
+ }
if (!conn_id) {
ret = -ENOMEM;
goto out;
@@ -942,10 +997,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
cm_id->context = conn_id;
cm_id->cm_handler = cma_ib_handler;
- offset = cma_user_data_offset(listen_id->id.ps);
- ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
- ib_event->private_data + offset,
- IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
+ ret = conn_id->id.event_handler(&conn_id->id, &event);
if (!ret)
goto out;
@@ -964,8 +1016,7 @@ out:
static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
{
- return cpu_to_be64(((u64)ps << 16) +
- be16_to_cpu(((struct sockaddr_in *) addr)->sin_port));
+ return cpu_to_be64(((u64)ps << 16) + be16_to_cpu(cma_port(addr)));
}
static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
@@ -1021,36 +1072,49 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
{
struct rdma_id_private *id_priv = iw_id->context;
- enum rdma_cm_event_type event = 0;
+ struct rdma_cm_event event;
struct sockaddr_in *sin;
int ret = 0;
+ memset(&event, 0, sizeof event);
atomic_inc(&id_priv->dev_remove);
switch (iw_event->event) {
case IW_CM_EVENT_CLOSE:
- event = RDMA_CM_EVENT_DISCONNECTED;
+ event.event = RDMA_CM_EVENT_DISCONNECTED;
break;
case IW_CM_EVENT_CONNECT_REPLY:
sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
*sin = iw_event->local_addr;
sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr;
*sin = iw_event->remote_addr;
- if (iw_event->status)
- event = RDMA_CM_EVENT_REJECTED;
- else
- event = RDMA_CM_EVENT_ESTABLISHED;
+ switch (iw_event->status) {
+ case 0:
+ event.event = RDMA_CM_EVENT_ESTABLISHED;
+ break;
+ case -ECONNRESET:
+ case -ECONNREFUSED:
+ event.event = RDMA_CM_EVENT_REJECTED;
+ break;
+ case -ETIMEDOUT:
+ event.event = RDMA_CM_EVENT_UNREACHABLE;
+ break;
+ default:
+ event.event = RDMA_CM_EVENT_CONNECT_ERROR;
+ break;
+ }
break;
case IW_CM_EVENT_ESTABLISHED:
- event = RDMA_CM_EVENT_ESTABLISHED;
+ event.event = RDMA_CM_EVENT_ESTABLISHED;
break;
default:
BUG_ON(1);
}
- ret = cma_notify_user(id_priv, event, iw_event->status,
- iw_event->private_data,
- iw_event->private_data_len);
+ event.status = iw_event->status;
+ event.param.conn.private_data = iw_event->private_data;
+ event.param.conn.private_data_len = iw_event->private_data_len;
+ ret = id_priv->id.event_handler(&id_priv->id, &event);
if (ret) {
/* Destroy the CM ID by returning a non-zero value. */
id_priv->cm_id.iw = NULL;
@@ -1071,6 +1135,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
struct rdma_id_private *listen_id, *conn_id;
struct sockaddr_in *sin;
struct net_device *dev = NULL;
+ struct rdma_cm_event event;
int ret;
listen_id = cm_id->context;
@@ -1124,9 +1189,11 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
*sin = iw_event->remote_addr;
- ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
- iw_event->private_data,
- iw_event->private_data_len);
+ memset(&event, 0, sizeof event);
+ event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
+ event.param.conn.private_data = iw_event->private_data;
+ event.param.conn.private_data_len = iw_event->private_data_len;
+ ret = conn_id->id.event_handler(&conn_id->id, &event);
if (ret) {
/* User wants to destroy the CM ID */
conn_id->cm_id.iw = NULL;
@@ -1515,8 +1582,9 @@ static void addr_handler(int status, struct sockaddr *src_addr,
struct rdma_dev_addr *dev_addr, void *context)
{
struct rdma_id_private *id_priv = context;
- enum rdma_cm_event_type event;
+ struct rdma_cm_event event;
+ memset(&event, 0, sizeof event);
atomic_inc(&id_priv->dev_remove);
/*
@@ -1536,14 +1604,15 @@ static void addr_handler(int status, struct sockaddr *src_addr,
if (status) {
if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
goto out;
- event = RDMA_CM_EVENT_ADDR_ERROR;
+ event.event = RDMA_CM_EVENT_ADDR_ERROR;
+ event.status = status;
} else {
memcpy(&id_priv->id.route.addr.src_addr, src_addr,
ip_addr_size(src_addr));
- event = RDMA_CM_EVENT_ADDR_RESOLVED;
+ event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
}
- if (cma_notify_user(id_priv, event, status, NULL, 0)) {
+ if (id_priv->id.event_handler(&id_priv->id, &event)) {
cma_exch(id_priv, CMA_DESTROYING);
cma_release_remove(id_priv);
cma_deref_id(id_priv);
@@ -1733,6 +1802,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
case RDMA_PS_TCP:
ps = &tcp_ps;
break;
+ case RDMA_PS_UDP:
+ ps = &udp_ps;
+ break;
default:
return -EPROTONOSUPPORT;
}
@@ -1821,6 +1893,110 @@ static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
return 0;
}
+static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
+ struct ib_cm_event *ib_event)
+{
+ struct rdma_id_private *id_priv = cm_id->context;
+ struct rdma_cm_event event;
+ struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
+ int ret = 0;
+
+ memset(&event, 0, sizeof event);
+ atomic_inc(&id_priv->dev_remove);
+ if (!cma_comp(id_priv, CMA_CONNECT))
+ goto out;
+
+ switch (ib_event->event) {
+ case IB_CM_SIDR_REQ_ERROR:
+ event.event = RDMA_CM_EVENT_UNREACHABLE;
+ event.status = -ETIMEDOUT;
+ break;
+ case IB_CM_SIDR_REP_RECEIVED:
+ event.param.ud.private_data = ib_event->private_data;
+ event.param.ud.private_data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
+ if (rep->status != IB_SIDR_SUCCESS) {
+ event.event = RDMA_CM_EVENT_UNREACHABLE;
+ event.status = ib_event->param.sidr_rep_rcvd.status;
+ break;
+ }
+ if (rep->qkey != RDMA_UD_QKEY) {
+ event.event = RDMA_CM_EVENT_UNREACHABLE;
+ event.status = -EINVAL;
+ break;
+ }
+ ib_init_ah_from_path(id_priv->id.device, id_priv->id.port_num,
+ id_priv->id.route.path_rec,
+ &event.param.ud.ah_attr);
+ event.param.ud.qp_num = rep->qpn;
+ event.param.ud.qkey = rep->qkey;
+ event.event = RDMA_CM_EVENT_ESTABLISHED;
+ event.status = 0;
+ break;
+ default:
+ printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
+ ib_event->event);
+ goto out;
+ }
+
+ ret = id_priv->id.event_handler(&id_priv->id, &event);
+ if (ret) {
+ /* Destroy the CM ID by returning a non-zero value. */
+ id_priv->cm_id.ib = NULL;
+ cma_exch(id_priv, CMA_DESTROYING);
+ cma_release_remove(id_priv);
+ rdma_destroy_id(&id_priv->id);
+ return ret;
+ }
+out:
+ cma_release_remove(id_priv);
+ return ret;
+}
+
+static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
+ struct rdma_conn_param *conn_param)
+{
+ struct ib_cm_sidr_req_param req;
+ struct rdma_route *route;
+ int ret;
+
+ req.private_data_len = sizeof(struct cma_hdr) +
+ conn_param->private_data_len;
+ req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
+ if (!req.private_data)
+ return -ENOMEM;
+
+ if (conn_param->private_data && conn_param->private_data_len)
+ memcpy((void *) req.private_data + sizeof(struct cma_hdr),
+ conn_param->private_data, conn_param->private_data_len);
+
+ route = &id_priv->id.route;
+ ret = cma_format_hdr((void *) req.private_data, id_priv->id.ps, route);
+ if (ret)
+ goto out;
+
+ id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,
+ cma_sidr_rep_handler, id_priv);
+ if (IS_ERR(id_priv->cm_id.ib)) {
+ ret = PTR_ERR(id_priv->cm_id.ib);
+ goto out;
+ }
+
+ req.path = route->path_rec;
+ req.service_id = cma_get_service_id(id_priv->id.ps,
+ &route->addr.dst_addr);
+ req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8);
+ req.max_cm_retries = CMA_MAX_CM_RETRIES;
+
+ ret = ib_send_cm_sidr_req(id_priv->cm_id.ib, &req);
+ if (ret) {
+ ib_destroy_cm_id(id_priv->cm_id.ib);
+ id_priv->cm_id.ib = NULL;
+ }
+out:
+ kfree(req.private_data);
+ return ret;
+}
+
static int cma_connect_ib(struct rdma_id_private *id_priv,
struct rdma_conn_param *conn_param)
{
@@ -1860,7 +2036,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
req.service_id = cma_get_service_id(id_priv->id.ps,
&route->addr.dst_addr);
req.qp_num = id_priv->qp_num;
- req.qp_type = id_priv->qp_type;
+ req.qp_type = IB_QPT_RC;
req.starting_psn = id_priv->seq_num;
req.responder_resources = conn_param->responder_resources;
req.initiator_depth = conn_param->initiator_depth;
@@ -1937,13 +2113,15 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
if (!id->qp) {
id_priv->qp_num = conn_param->qp_num;
- id_priv->qp_type = conn_param->qp_type;
id_priv->srq = conn_param->srq;
}
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- ret = cma_connect_ib(id_priv, conn_param);
+ if (id->ps == RDMA_PS_UDP)
+ ret = cma_resolve_ib_udp(id_priv, conn_param);
+ else
+ ret = cma_connect_ib(id_priv, conn_param);
break;
case RDMA_TRANSPORT_IWARP:
ret = cma_connect_iw(id_priv, conn_param);
@@ -1966,11 +2144,25 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
struct rdma_conn_param *conn_param)
{
struct ib_cm_rep_param rep;
- int ret;
+ struct ib_qp_attr qp_attr;
+ int qp_attr_mask, ret;
- ret = cma_modify_qp_rtr(&id_priv->id);
- if (ret)
- return ret;
+ if (id_priv->id.qp) {
+ ret = cma_modify_qp_rtr(&id_priv->id);
+ if (ret)
+ goto out;
+
+ qp_attr.qp_state = IB_QPS_RTS;
+ ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
+ &qp_attr_mask);
+ if (ret)
+ goto out;
+
+ qp_attr.max_rd_atomic = conn_param->initiator_depth;
+ ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+ if (ret)
+ goto out;
+ }
memset(&rep, 0, sizeof rep);
rep.qp_num = id_priv->qp_num;
@@ -1985,7 +2177,9 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
rep.rnr_retry_count = conn_param->rnr_retry_count;
rep.srq = id_priv->srq ? 1 : 0;
- return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+ ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+out:
+ return ret;
}
static int cma_accept_iw(struct rdma_id_private *id_priv,
@@ -2010,6 +2204,24 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
return iw_cm_accept(id_priv->cm_id.iw, &iw_param);
}
+static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
+ enum ib_cm_sidr_status status,
+ const void *private_data, int private_data_len)
+{
+ struct ib_cm_sidr_rep_param rep;
+
+ memset(&rep, 0, sizeof rep);
+ rep.status = status;
+ if (status == IB_SIDR_SUCCESS) {
+ rep.qp_num = id_priv->qp_num;
+ rep.qkey = RDMA_UD_QKEY;
+ }
+ rep.private_data = private_data;
+ rep.private_data_len = private_data_len;
+
+ return ib_send_cm_sidr_rep(id_priv->cm_id.ib, &rep);
+}
+
int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
{
struct rdma_id_private *id_priv;
@@ -2021,13 +2233,16 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
if (!id->qp && conn_param) {
id_priv->qp_num = conn_param->qp_num;
- id_priv->qp_type = conn_param->qp_type;
id_priv->srq = conn_param->srq;
}
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (conn_param)
+ if (id->ps == RDMA_PS_UDP)
+ ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+ conn_param->private_data,
+ conn_param->private_data_len);
+ else if (conn_param)
ret = cma_accept_ib(id_priv, conn_param);
else
ret = cma_rep_recv(id_priv);
@@ -2051,6 +2266,27 @@ reject:
}
EXPORT_SYMBOL(rdma_accept);
+int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
+{
+ struct rdma_id_private *id_priv;
+ int ret;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
+ if (!cma_comp(id_priv, CMA_CONNECT))
+ return -EINVAL;
+
+ switch (id->device->node_type) {
+ case RDMA_NODE_IB_CA:
+ ret = ib_cm_notify(id_priv->cm_id.ib, event);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(rdma_notify);
+
int rdma_reject(struct rdma_cm_id *id, const void *private_data,
u8 private_data_len)
{
@@ -2063,9 +2299,13 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- ret = ib_send_cm_rej(id_priv->cm_id.ib,
- IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
- private_data, private_data_len);
+ if (id->ps == RDMA_PS_UDP)
+ ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
+ private_data, private_data_len);
+ else
+ ret = ib_send_cm_rej(id_priv->cm_id.ib,
+ IB_CM_REJ_CONSUMER_DEFINED, NULL,
+ 0, private_data, private_data_len);
break;
case RDMA_TRANSPORT_IWARP:
ret = iw_cm_reject(id_priv->cm_id.iw,
@@ -2136,6 +2376,7 @@ static void cma_add_one(struct ib_device *device)
static int cma_remove_id_dev(struct rdma_id_private *id_priv)
{
+ struct rdma_cm_event event;
enum cma_state state;
/* Record that we want to remove the device */
@@ -2150,8 +2391,9 @@ static int cma_remove_id_dev(struct rdma_id_private *id_priv)
if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
return 0;
- return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
- 0, NULL, 0);
+ memset(&event, 0, sizeof event);
+ event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
+ return id_priv->id.event_handler(&id_priv->id, &event);
}
static void cma_process_remove(struct cma_device *cma_dev)
@@ -2233,6 +2475,7 @@ static void cma_cleanup(void)
destroy_workqueue(cma_wq);
idr_destroy(&sdp_ps);
idr_destroy(&tcp_ps);
+ idr_destroy(&udp_ps);
}
module_init(cma_init);
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 86a3b2d401d..8926a2bd4a8 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -394,20 +394,12 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
*/
int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
{
- int serial;
-
- atomic_inc(&pool->req_ser);
- /*
- * It's OK if someone else bumps req_ser again here -- we'll
- * just wait a little longer.
- */
- serial = atomic_read(&pool->req_ser);
+ int serial = atomic_inc_return(&pool->req_ser);
wake_up_process(pool->thread);
if (wait_event_interruptible(pool->force_wait,
- atomic_read(&pool->flush_ser) -
- atomic_read(&pool->req_ser) >= 0))
+ atomic_read(&pool->flush_ser) - serial >= 0))
return -EINTR;
return 0;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 15f38d94b3a..5ed141ebd1c 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -998,17 +998,17 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
mad_agent = mad_send_wr->send_buf.mad_agent;
sge = mad_send_wr->sg_list;
- sge[0].addr = dma_map_single(mad_agent->device->dma_device,
- mad_send_wr->send_buf.mad,
- sge[0].length,
- DMA_TO_DEVICE);
- pci_unmap_addr_set(mad_send_wr, header_mapping, sge[0].addr);
-
- sge[1].addr = dma_map_single(mad_agent->device->dma_device,
- ib_get_payload(mad_send_wr),
- sge[1].length,
- DMA_TO_DEVICE);
- pci_unmap_addr_set(mad_send_wr, payload_mapping, sge[1].addr);
+ sge[0].addr = ib_dma_map_single(mad_agent->device,
+ mad_send_wr->send_buf.mad,
+ sge[0].length,
+ DMA_TO_DEVICE);
+ mad_send_wr->header_mapping = sge[0].addr;
+
+ sge[1].addr = ib_dma_map_single(mad_agent->device,
+ ib_get_payload(mad_send_wr),
+ sge[1].length,
+ DMA_TO_DEVICE);
+ mad_send_wr->payload_mapping = sge[1].addr;
spin_lock_irqsave(&qp_info->send_queue.lock, flags);
if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
@@ -1026,12 +1026,12 @@ int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
}
spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
if (ret) {
- dma_unmap_single(mad_agent->device->dma_device,
- pci_unmap_addr(mad_send_wr, header_mapping),
- sge[0].length, DMA_TO_DEVICE);
- dma_unmap_single(mad_agent->device->dma_device,
- pci_unmap_addr(mad_send_wr, payload_mapping),
- sge[1].length, DMA_TO_DEVICE);
+ ib_dma_unmap_single(mad_agent->device,
+ mad_send_wr->header_mapping,
+ sge[0].length, DMA_TO_DEVICE);
+ ib_dma_unmap_single(mad_agent->device,
+ mad_send_wr->payload_mapping,
+ sge[1].length, DMA_TO_DEVICE);
}
return ret;
}
@@ -1850,11 +1850,11 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
mad_priv_hdr = container_of(mad_list, struct ib_mad_private_header,
mad_list);
recv = container_of(mad_priv_hdr, struct ib_mad_private, header);
- dma_unmap_single(port_priv->device->dma_device,
- pci_unmap_addr(&recv->header, mapping),
- sizeof(struct ib_mad_private) -
- sizeof(struct ib_mad_private_header),
- DMA_FROM_DEVICE);
+ ib_dma_unmap_single(port_priv->device,
+ recv->header.mapping,
+ sizeof(struct ib_mad_private) -
+ sizeof(struct ib_mad_private_header),
+ DMA_FROM_DEVICE);
/* Setup MAD receive work completion from "normal" work completion */
recv->header.wc = *wc;
@@ -2080,12 +2080,12 @@ static void ib_mad_send_done_handler(struct ib_mad_port_private *port_priv,
qp_info = send_queue->qp_info;
retry:
- dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
- pci_unmap_addr(mad_send_wr, header_mapping),
- mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
- dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
- pci_unmap_addr(mad_send_wr, payload_mapping),
- mad_send_wr->sg_list[1].length, DMA_TO_DEVICE);
+ ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device,
+ mad_send_wr->header_mapping,
+ mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
+ ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device,
+ mad_send_wr->payload_mapping,
+ mad_send_wr->sg_list[1].length, DMA_TO_DEVICE);
queued_send_wr = NULL;
spin_lock_irqsave(&send_queue->lock, flags);
list_del(&mad_list->list);
@@ -2528,13 +2528,12 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
break;
}
}
- sg_list.addr = dma_map_single(qp_info->port_priv->
- device->dma_device,
- &mad_priv->grh,
- sizeof *mad_priv -
- sizeof mad_priv->header,
- DMA_FROM_DEVICE);
- pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr);
+ sg_list.addr = ib_dma_map_single(qp_info->port_priv->device,
+ &mad_priv->grh,
+ sizeof *mad_priv -
+ sizeof mad_priv->header,
+ DMA_FROM_DEVICE);
+ mad_priv->header.mapping = sg_list.addr;
recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list;
mad_priv->header.mad_list.mad_queue = recv_queue;
@@ -2549,12 +2548,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
list_del(&mad_priv->header.mad_list.list);
recv_queue->count--;
spin_unlock_irqrestore(&recv_queue->lock, flags);
- dma_unmap_single(qp_info->port_priv->device->dma_device,
- pci_unmap_addr(&mad_priv->header,
- mapping),
- sizeof *mad_priv -
- sizeof mad_priv->header,
- DMA_FROM_DEVICE);
+ ib_dma_unmap_single(qp_info->port_priv->device,
+ mad_priv->header.mapping,
+ sizeof *mad_priv -
+ sizeof mad_priv->header,
+ DMA_FROM_DEVICE);
kmem_cache_free(ib_mad_cache, mad_priv);
printk(KERN_ERR PFX "ib_post_recv failed: %d\n", ret);
break;
@@ -2586,11 +2584,11 @@ static void cleanup_recv_queue(struct ib_mad_qp_info *qp_info)
/* Remove from posted receive MAD list */
list_del(&mad_list->list);
- dma_unmap_single(qp_info->port_priv->device->dma_device,
- pci_unmap_addr(&recv->header, mapping),
- sizeof(struct ib_mad_private) -
- sizeof(struct ib_mad_private_header),
- DMA_FROM_DEVICE);
+ ib_dma_unmap_single(qp_info->port_priv->device,
+ recv->header.mapping,
+ sizeof(struct ib_mad_private) -
+ sizeof(struct ib_mad_private_header),
+ DMA_FROM_DEVICE);
kmem_cache_free(ib_mad_cache, recv);
}
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index d5548e73e06..de89717f49f 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -73,7 +73,7 @@ struct ib_mad_private_header {
struct ib_mad_list_head mad_list;
struct ib_mad_recv_wc recv_wc;
struct ib_wc wc;
- DECLARE_PCI_UNMAP_ADDR(mapping)
+ u64 mapping;
} __attribute__ ((packed));
struct ib_mad_private {
@@ -126,8 +126,8 @@ struct ib_mad_send_wr_private {
struct list_head agent_list;
struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_buf send_buf;
- DECLARE_PCI_UNMAP_ADDR(header_mapping)
- DECLARE_PCI_UNMAP_ADDR(payload_mapping)
+ u64 header_mapping;
+ u64 payload_mapping;
struct ib_send_wr send_wr;
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
__be64 tid;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
new file mode 100644
index 00000000000..e2e8d329b44
--- /dev/null
+++ b/drivers/infiniband/core/ucma.c
@@ -0,0 +1,885 @@
+/*
+ * Copyright (c) 2005-2006 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/idr.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/miscdevice.h>
+
+#include <rdma/rdma_user_cm.h>
+#include <rdma/ib_marshall.h>
+#include <rdma/rdma_cm.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
+MODULE_LICENSE("Dual BSD/GPL");
+
+enum {
+ UCMA_MAX_BACKLOG = 128
+};
+
+struct ucma_file {
+ struct mutex mut;
+ struct file *filp;
+ struct list_head ctx_list;
+ struct list_head event_list;
+ wait_queue_head_t poll_wait;
+};
+
+struct ucma_context {
+ int id;
+ struct completion comp;
+ atomic_t ref;
+ int events_reported;
+ int backlog;
+
+ struct ucma_file *file;
+ struct rdma_cm_id *cm_id;
+ u64 uid;
+
+ struct list_head list;
+};
+
+struct ucma_event {
+ struct ucma_context *ctx;
+ struct list_head list;
+ struct rdma_cm_id *cm_id;
+ struct rdma_ucm_event_resp resp;
+};
+
+static DEFINE_MUTEX(mut);
+static DEFINE_IDR(ctx_idr);
+
+static inline struct ucma_context *_ucma_find_context(int id,
+ struct ucma_file *file)
+{
+ struct ucma_context *ctx;
+
+ ctx = idr_find(&ctx_idr, id);
+ if (!ctx)
+ ctx = ERR_PTR(-ENOENT);
+ else if (ctx->file != file)
+ ctx = ERR_PTR(-EINVAL);
+ return ctx;
+}
+
+static struct ucma_context *ucma_get_ctx(struct ucma_file *file, int id)
+{
+ struct ucma_context *ctx;
+
+ mutex_lock(&mut);
+ ctx = _ucma_find_context(id, file);
+ if (!IS_ERR(ctx))
+ atomic_inc(&ctx->ref);
+ mutex_unlock(&mut);
+ return ctx;
+}
+
+static void ucma_put_ctx(struct ucma_context *ctx)
+{
+ if (atomic_dec_and_test(&ctx->ref))
+ complete(&ctx->comp);
+}
+
+static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
+{
+ struct ucma_context *ctx;
+ int ret;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ atomic_set(&ctx->ref, 1);
+ init_completion(&ctx->comp);
+ ctx->file = file;
+
+ do {
+ ret = idr_pre_get(&ctx_idr, GFP_KERNEL);
+ if (!ret)
+ goto error;
+
+ mutex_lock(&mut);
+ ret = idr_get_new(&ctx_idr, ctx, &ctx->id);
+ mutex_unlock(&mut);
+ } while (ret == -EAGAIN);
+
+ if (ret)
+ goto error;
+
+ list_add_tail(&ctx->list, &file->ctx_list);
+ return ctx;
+
+error:
+ kfree(ctx);
+ return NULL;
+}
+
+static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
+ struct rdma_conn_param *src)
+{
+ if (src->private_data_len)
+ memcpy(dst->private_data, src->private_data,
+ src->private_data_len);
+ dst->private_data_len = src->private_data_len;
+ dst->responder_resources =src->responder_resources;
+ dst->initiator_depth = src->initiator_depth;
+ dst->flow_control = src->flow_control;
+ dst->retry_count = src->retry_count;
+ dst->rnr_retry_count = src->rnr_retry_count;
+ dst->srq = src->srq;
+ dst->qp_num = src->qp_num;
+}
+
+static void ucma_copy_ud_event(struct rdma_ucm_ud_param *dst,
+ struct rdma_ud_param *src)
+{
+ if (src->private_data_len)
+ memcpy(dst->private_data, src->private_data,
+ src->private_data_len);
+ dst->private_data_len = src->private_data_len;
+ ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
+ dst->qp_num = src->qp_num;
+ dst->qkey = src->qkey;
+}
+
+static void ucma_set_event_context(struct ucma_context *ctx,
+ struct rdma_cm_event *event,
+ struct ucma_event *uevent)
+{
+ uevent->ctx = ctx;
+ uevent->resp.uid = ctx->uid;
+ uevent->resp.id = ctx->id;
+}
+
+static int ucma_event_handler(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event)
+{
+ struct ucma_event *uevent;
+ struct ucma_context *ctx = cm_id->context;
+ int ret = 0;
+
+ uevent = kzalloc(sizeof(*uevent), GFP_KERNEL);
+ if (!uevent)
+ return event->event == RDMA_CM_EVENT_CONNECT_REQUEST;
+
+ uevent->cm_id = cm_id;
+ ucma_set_event_context(ctx, event, uevent);
+ uevent->resp.event = event->event;
+ uevent->resp.status = event->status;
+ if (cm_id->ps == RDMA_PS_UDP)
+ ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
+ else
+ ucma_copy_conn_event(&uevent->resp.param.conn,
+ &event->param.conn);
+
+ mutex_lock(&ctx->file->mut);
+ if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) {
+ if (!ctx->backlog) {
+ ret = -EDQUOT;
+ kfree(uevent);
+ goto out;
+ }
+ ctx->backlog--;
+ } else if (!ctx->uid) {
+ /*
+ * We ignore events for new connections until userspace has set
+ * their context. This can only happen if an error occurs on a
+ * new connection before the user accepts it. This is okay,
+ * since the accept will just fail later.
+ */
+ kfree(uevent);
+ goto out;
+ }
+
+ list_add_tail(&uevent->list, &ctx->file->event_list);
+ wake_up_interruptible(&ctx->file->poll_wait);
+out:
+ mutex_unlock(&ctx->file->mut);
+ return ret;
+}
+
+static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct ucma_context *ctx;
+ struct rdma_ucm_get_event cmd;
+ struct ucma_event *uevent;
+ int ret = 0;
+ DEFINE_WAIT(wait);
+
+ if (out_len < sizeof uevent->resp)
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ mutex_lock(&file->mut);
+ while (list_empty(&file->event_list)) {
+ if (file->filp->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ prepare_to_wait(&file->poll_wait, &wait, TASK_INTERRUPTIBLE);
+ mutex_unlock(&file->mut);
+ schedule();
+ mutex_lock(&file->mut);
+ finish_wait(&file->poll_wait, &wait);
+ }
+
+ if (ret)
+ goto done;
+
+ uevent = list_entry(file->event_list.next, struct ucma_event, list);
+
+ if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST) {
+ ctx = ucma_alloc_ctx(file);
+ if (!ctx) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ uevent->ctx->backlog++;
+ ctx->cm_id = uevent->cm_id;
+ ctx->cm_id->context = ctx;
+ uevent->resp.id = ctx->id;
+ }
+
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &uevent->resp, sizeof uevent->resp)) {
+ ret = -EFAULT;
+ goto done;
+ }
+
+ list_del(&uevent->list);
+ uevent->ctx->events_reported++;
+ kfree(uevent);
+done:
+ mutex_unlock(&file->mut);
+ return ret;
+}
+
+static ssize_t ucma_create_id(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_create_id cmd;
+ struct rdma_ucm_create_id_resp resp;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ mutex_lock(&file->mut);
+ ctx = ucma_alloc_ctx(file);
+ mutex_unlock(&file->mut);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->uid = cmd.uid;
+ ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps);
+ if (IS_ERR(ctx->cm_id)) {
+ ret = PTR_ERR(ctx->cm_id);
+ goto err1;
+ }
+
+ resp.id = ctx->id;
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp))) {
+ ret = -EFAULT;
+ goto err2;
+ }
+ return 0;
+
+err2:
+ rdma_destroy_id(ctx->cm_id);
+err1:
+ mutex_lock(&mut);
+ idr_remove(&ctx_idr, ctx->id);
+ mutex_unlock(&mut);
+ kfree(ctx);
+ return ret;
+}
+
+static void ucma_cleanup_events(struct ucma_context *ctx)
+{
+ struct ucma_event *uevent, *tmp;
+
+ list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
+ if (uevent->ctx != ctx)
+ continue;
+
+ list_del(&uevent->list);
+
+ /* clear incoming connections. */
+ if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST)
+ rdma_destroy_id(uevent->cm_id);
+
+ kfree(uevent);
+ }
+}
+
+static int ucma_free_ctx(struct ucma_context *ctx)
+{
+ int events_reported;
+
+ /* No new events will be generated after destroying the id. */
+ rdma_destroy_id(ctx->cm_id);
+
+ /* Cleanup events not yet reported to the user. */
+ mutex_lock(&ctx->file->mut);
+ ucma_cleanup_events(ctx);
+ list_del(&ctx->list);
+ mutex_unlock(&ctx->file->mut);
+
+ events_reported = ctx->events_reported;
+ kfree(ctx);
+ return events_reported;
+}
+
+static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_destroy_id cmd;
+ struct rdma_ucm_destroy_id_resp resp;
+ struct ucma_context *ctx;
+ int ret = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ mutex_lock(&mut);
+ ctx = _ucma_find_context(cmd.id, file);
+ if (!IS_ERR(ctx))
+ idr_remove(&ctx_idr, ctx->id);
+ mutex_unlock(&mut);
+
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ucma_put_ctx(ctx);
+ wait_for_completion(&ctx->comp);
+ resp.events_reported = ucma_free_ctx(ctx);
+
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ ret = -EFAULT;
+
+ return ret;
+}
+
+static ssize_t ucma_bind_addr(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_bind_addr cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_resolve_addr(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_resolve_addr cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
+ (struct sockaddr *) &cmd.dst_addr,
+ cmd.timeout_ms);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_resolve_route(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_resolve_route cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = rdma_resolve_route(ctx->cm_id, cmd.timeout_ms);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
+ struct rdma_route *route)
+{
+ struct rdma_dev_addr *dev_addr;
+
+ resp->num_paths = route->num_paths;
+ switch (route->num_paths) {
+ case 0:
+ dev_addr = &route->addr.dev_addr;
+ ib_addr_get_dgid(dev_addr,
+ (union ib_gid *) &resp->ib_route[0].dgid);
+ ib_addr_get_sgid(dev_addr,
+ (union ib_gid *) &resp->ib_route[0].sgid);
+ resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
+ break;
+ case 2:
+ ib_copy_path_rec_to_user(&resp->ib_route[1],
+ &route->path_rec[1]);
+ /* fall through */
+ case 1:
+ ib_copy_path_rec_to_user(&resp->ib_route[0],
+ &route->path_rec[0]);
+ break;
+ default:
+ break;
+ }
+}
+
+static ssize_t ucma_query_route(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_query_route cmd;
+ struct rdma_ucm_query_route_resp resp;
+ struct ucma_context *ctx;
+ struct sockaddr *addr;
+ int ret = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ memset(&resp, 0, sizeof resp);
+ addr = &ctx->cm_id->route.addr.src_addr;
+ memcpy(&resp.src_addr, addr, addr->sa_family == AF_INET ?
+ sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+ addr = &ctx->cm_id->route.addr.dst_addr;
+ memcpy(&resp.dst_addr, addr, addr->sa_family == AF_INET ?
+ sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+ if (!ctx->cm_id->device)
+ goto out;
+
+ resp.node_guid = ctx->cm_id->device->node_guid;
+ resp.port_num = ctx->cm_id->port_num;
+ switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
+ case RDMA_TRANSPORT_IB:
+ ucma_copy_ib_route(&resp, &ctx->cm_id->route);
+ break;
+ default:
+ break;
+ }
+
+out:
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ ret = -EFAULT;
+
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static void ucma_copy_conn_param(struct rdma_conn_param *dst,
+ struct rdma_ucm_conn_param *src)
+{
+ dst->private_data = src->private_data;
+ dst->private_data_len = src->private_data_len;
+ dst->responder_resources =src->responder_resources;
+ dst->initiator_depth = src->initiator_depth;
+ dst->flow_control = src->flow_control;
+ dst->retry_count = src->retry_count;
+ dst->rnr_retry_count = src->rnr_retry_count;
+ dst->srq = src->srq;
+ dst->qp_num = src->qp_num;
+}
+
+static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_connect cmd;
+ struct rdma_conn_param conn_param;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ if (!cmd.conn_param.valid)
+ return -EINVAL;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+ ret = rdma_connect(ctx->cm_id, &conn_param);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_listen(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_listen cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ctx->backlog = cmd.backlog > 0 && cmd.backlog < UCMA_MAX_BACKLOG ?
+ cmd.backlog : UCMA_MAX_BACKLOG;
+ ret = rdma_listen(ctx->cm_id, ctx->backlog);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_accept cmd;
+ struct rdma_conn_param conn_param;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ if (cmd.conn_param.valid) {
+ ctx->uid = cmd.uid;
+ ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+ ret = rdma_accept(ctx->cm_id, &conn_param);
+ } else
+ ret = rdma_accept(ctx->cm_id, NULL);
+
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_reject(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_reject cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = rdma_reject(ctx->cm_id, cmd.private_data, cmd.private_data_len);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_disconnect(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_disconnect cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = rdma_disconnect(ctx->cm_id);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_init_qp_attr(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_init_qp_attr cmd;
+ struct ib_uverbs_qp_attr resp;
+ struct ucma_context *ctx;
+ struct ib_qp_attr qp_attr;
+ int ret;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ resp.qp_attr_mask = 0;
+ memset(&qp_attr, 0, sizeof qp_attr);
+ qp_attr.qp_state = cmd.qp_state;
+ ret = rdma_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
+ if (ret)
+ goto out;
+
+ ib_copy_qp_attr_to_user(&resp, &qp_attr);
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ ret = -EFAULT;
+
+out:
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_notify cmd;
+ struct ucma_context *ctx;
+ int ret;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ ret = rdma_notify(ctx->cm_id, (enum ib_event_type) cmd.event);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len) = {
+ [RDMA_USER_CM_CMD_CREATE_ID] = ucma_create_id,
+ [RDMA_USER_CM_CMD_DESTROY_ID] = ucma_destroy_id,
+ [RDMA_USER_CM_CMD_BIND_ADDR] = ucma_bind_addr,
+ [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr,
+ [RDMA_USER_CM_CMD_RESOLVE_ROUTE]= ucma_resolve_route,
+ [RDMA_USER_CM_CMD_QUERY_ROUTE] = ucma_query_route,
+ [RDMA_USER_CM_CMD_CONNECT] = ucma_connect,
+ [RDMA_USER_CM_CMD_LISTEN] = ucma_listen,
+ [RDMA_USER_CM_CMD_ACCEPT] = ucma_accept,
+ [RDMA_USER_CM_CMD_REJECT] = ucma_reject,
+ [RDMA_USER_CM_CMD_DISCONNECT] = ucma_disconnect,
+ [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr,
+ [RDMA_USER_CM_CMD_GET_EVENT] = ucma_get_event,
+ [RDMA_USER_CM_CMD_GET_OPTION] = NULL,
+ [RDMA_USER_CM_CMD_SET_OPTION] = NULL,
+ [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify,
+};
+
+static ssize_t ucma_write(struct file *filp, const char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct ucma_file *file = filp->private_data;
+ struct rdma_ucm_cmd_hdr hdr;
+ ssize_t ret;
+
+ if (len < sizeof(hdr))
+ return -EINVAL;
+
+ if (copy_from_user(&hdr, buf, sizeof(hdr)))
+ return -EFAULT;
+
+ if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
+ return -EINVAL;
+
+ if (hdr.in + sizeof(hdr) > len)
+ return -EINVAL;
+
+ if (!ucma_cmd_table[hdr.cmd])
+ return -ENOSYS;
+
+ ret = ucma_cmd_table[hdr.cmd](file, buf + sizeof(hdr), hdr.in, hdr.out);
+ if (!ret)
+ ret = len;
+
+ return ret;
+}
+
+static unsigned int ucma_poll(struct file *filp, struct poll_table_struct *wait)
+{
+ struct ucma_file *file = filp->private_data;
+ unsigned int mask = 0;
+
+ poll_wait(filp, &file->poll_wait, wait);
+
+ if (!list_empty(&file->event_list))
+ mask = POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+static int ucma_open(struct inode *inode, struct file *filp)
+{
+ struct ucma_file *file;
+
+ file = kmalloc(sizeof *file, GFP_KERNEL);
+ if (!file)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&file->event_list);
+ INIT_LIST_HEAD(&file->ctx_list);
+ init_waitqueue_head(&file->poll_wait);
+ mutex_init(&file->mut);
+
+ filp->private_data = file;
+ file->filp = filp;
+ return 0;
+}
+
+static int ucma_close(struct inode *inode, struct file *filp)
+{
+ struct ucma_file *file = filp->private_data;
+ struct ucma_context *ctx, *tmp;
+
+ mutex_lock(&file->mut);
+ list_for_each_entry_safe(ctx, tmp, &file->ctx_list, list) {
+ mutex_unlock(&file->mut);
+
+ mutex_lock(&mut);
+ idr_remove(&ctx_idr, ctx->id);
+ mutex_unlock(&mut);
+
+ ucma_free_ctx(ctx);
+ mutex_lock(&file->mut);
+ }
+ mutex_unlock(&file->mut);
+ kfree(file);
+ return 0;
+}
+
+static struct file_operations ucma_fops = {
+ .owner = THIS_MODULE,
+ .open = ucma_open,
+ .release = ucma_close,
+ .write = ucma_write,
+ .poll = ucma_poll,
+};
+
+static struct miscdevice ucma_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "rdma_cm",
+ .fops = &ucma_fops,
+};
+
+static ssize_t show_abi_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", RDMA_USER_CM_ABI_VERSION);
+}
+static DEVICE_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+
+static int __init ucma_init(void)
+{
+ int ret;
+
+ ret = misc_register(&ucma_misc);
+ if (ret)
+ return ret;
+
+ ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version);
+ if (ret) {
+ printk(KERN_ERR "rdma_ucm: couldn't create abi_version attr\n");
+ goto err;
+ }
+ return 0;
+err:
+ misc_deregister(&ucma_misc);
+ return ret;
+}
+
+static void __exit ucma_cleanup(void)
+{
+ device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
+ misc_deregister(&ucma_misc);
+ idr_destroy(&ctx_idr);
+}
+
+module_init(ucma_init);
+module_exit(ucma_cleanup);
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 4e16314e8e6..a617ca7b692 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -534,9 +534,9 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
* module reference.
*/
filp->f_op = fops_get(&uverbs_event_fops);
- filp->f_vfsmnt = mntget(uverbs_event_mnt);
- filp->f_dentry = dget(uverbs_event_mnt->mnt_root);
- filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+ filp->f_path.mnt = mntget(uverbs_event_mnt);
+ filp->f_path.dentry = dget(uverbs_event_mnt->mnt_root);
+ filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
filp->f_flags = O_RDONLY;
filp->f_mode = FMODE_READ;
filp->private_data = ev_file;
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
index ce46b13ae02..5440da0e59b 100644
--- a/drivers/infiniband/core/uverbs_marshall.c
+++ b/drivers/infiniband/core/uverbs_marshall.c
@@ -32,8 +32,8 @@
#include <rdma/ib_marshall.h>
-static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
- struct ib_ah_attr *src)
+void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
+ struct ib_ah_attr *src)
{
memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid);
dst->grh.flow_label = src->grh.flow_label;
@@ -47,6 +47,7 @@ static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
dst->is_global = src->ah_flags & IB_AH_GRH ? 1 : 0;
dst->port_num = src->port_num;
}
+EXPORT_SYMBOL(ib_copy_ah_attr_to_user);
void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
struct ib_qp_attr *src)
diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c
index db12cc0841d..c95fe952abd 100644
--- a/drivers/infiniband/core/uverbs_mem.c
+++ b/drivers/infiniband/core/uverbs_mem.c
@@ -52,8 +52,8 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
int i;
list_for_each_entry_safe(chunk, tmp, &umem->chunk_list, list) {
- dma_unmap_sg(dev->dma_device, chunk->page_list,
- chunk->nents, DMA_BIDIRECTIONAL);
+ ib_dma_unmap_sg(dev, chunk->page_list,
+ chunk->nents, DMA_BIDIRECTIONAL);
for (i = 0; i < chunk->nents; ++i) {
if (umem->writable && dirty)
set_page_dirty_lock(chunk->page_list[i].page);
@@ -136,10 +136,10 @@ int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
chunk->page_list[i].length = PAGE_SIZE;
}
- chunk->nmap = dma_map_sg(dev->dma_device,
- &chunk->page_list[0],
- chunk->nents,
- DMA_BIDIRECTIONAL);
+ chunk->nmap = ib_dma_map_sg(dev,
+ &chunk->page_list[0],
+ chunk->nents,
+ DMA_BIDIRECTIONAL);
if (chunk->nmap <= 0) {
for (i = 0; i < chunk->nents; ++i)
put_page(chunk->page_list[i].page);
diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
index 179d005ed4a..420c1380f5c 100644
--- a/drivers/infiniband/hw/amso1100/c2_qp.c
+++ b/drivers/infiniband/hw/amso1100/c2_qp.c
@@ -161,8 +161,10 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
if (attr_mask & IB_QP_STATE) {
/* Ensure the state is valid */
- if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR)
- return -EINVAL;
+ if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) {
+ err = -EINVAL;
+ goto bail0;
+ }
wr.next_qp_state = cpu_to_be32(to_c2_state(attr->qp_state));
@@ -184,9 +186,10 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
if (attr->cur_qp_state != IB_QPS_RTR &&
attr->cur_qp_state != IB_QPS_RTS &&
attr->cur_qp_state != IB_QPS_SQD &&
- attr->cur_qp_state != IB_QPS_SQE)
- return -EINVAL;
- else
+ attr->cur_qp_state != IB_QPS_SQE) {
+ err = -EINVAL;
+ goto bail0;
+ } else
wr.next_qp_state =
cpu_to_be32(to_c2_state(attr->cur_qp_state));
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 93995b658d9..6074c897f51 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -344,8 +344,11 @@ int ehca_destroy_cq(struct ib_cq *cq)
unsigned long flags;
spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- while (my_cq->nr_callbacks)
+ while (my_cq->nr_callbacks) {
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
yield();
+ spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ }
idr_remove(&ehca_cq_idr, my_cq->token);
spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index e1b618c5f68..b7be950ab47 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -50,7 +50,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
ib_device);
struct hipz_query_hca *rblock;
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
@@ -110,7 +110,7 @@ int ehca_query_port(struct ib_device *ibdev,
ib_device);
struct hipz_query_port *rblock;
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
@@ -179,7 +179,7 @@ int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
return -EINVAL;
}
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
@@ -212,7 +212,7 @@ int ehca_query_gid(struct ib_device *ibdev, u8 port,
return -EINVAL;
}
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index c3ea746e904..c069be8cbcb 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -138,7 +138,7 @@ int ehca_error_data(struct ehca_shca *shca, void *data,
u64 *rblock;
unsigned long block_count;
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
if (!rblock) {
ehca_err(&shca->ib_device, "Cannot allocate rblock memory.");
ret = -ENOMEM;
@@ -440,7 +440,8 @@ void ehca_tasklet_eq(unsigned long data)
cq = idr_find(&ehca_cq_idr, token);
if (cq == NULL) {
- spin_unlock(&ehca_cq_idr_lock);
+ spin_unlock_irqrestore(&ehca_cq_idr_lock,
+ flags);
break;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 3720e3032cc..cd7789f0d08 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -180,10 +180,10 @@ int ehca_mmap_register(u64 physical,void **mapped,
int ehca_munmap(unsigned long addr, size_t len);
#ifdef CONFIG_PPC_64K_PAGES
-void *ehca_alloc_fw_ctrlblock(void);
+void *ehca_alloc_fw_ctrlblock(gfp_t flags);
void ehca_free_fw_ctrlblock(void *ptr);
#else
-#define ehca_alloc_fw_ctrlblock() ((void *) get_zeroed_page(GFP_KERNEL))
+#define ehca_alloc_fw_ctrlblock(flags) ((void *) get_zeroed_page(flags))
#define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
#endif
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index cc47e4c13a1..6574fbbaead 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -106,9 +106,9 @@ static struct timer_list poll_eqs_timer;
#ifdef CONFIG_PPC_64K_PAGES
static struct kmem_cache *ctblk_cache = NULL;
-void *ehca_alloc_fw_ctrlblock(void)
+void *ehca_alloc_fw_ctrlblock(gfp_t flags)
{
- void *ret = kmem_cache_zalloc(ctblk_cache, GFP_KERNEL);
+ void *ret = kmem_cache_zalloc(ctblk_cache, flags);
if (!ret)
ehca_gen_err("Out of memory for ctblk");
return ret;
@@ -206,7 +206,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
u64 h_ret;
struct hipz_query_hca *rblock;
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_gen_err("Cannot allocate rblock memory.");
return -ENOMEM;
@@ -258,7 +258,7 @@ static int init_node_guid(struct ehca_shca *shca)
int ret = 0;
struct hipz_query_hca *rblock;
- rblock = ehca_alloc_fw_ctrlblock();
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
@@ -469,7 +469,7 @@ static ssize_t ehca_show_##name(struct device *dev, \
\
shca = dev->driver_data; \
\
- rblock = ehca_alloc_fw_ctrlblock(); \
+ rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); \
if (!rblock) { \
dev_err(dev, "Can't allocate rblock memory."); \
return 0; \
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 0a5e2214cc5..cfb362a1029 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -1013,7 +1013,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
u32 i;
u64 *kpage;
- kpage = ehca_alloc_fw_ctrlblock();
+ kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!kpage) {
ehca_err(&shca->ib_device, "kpage alloc failed");
ret = -ENOMEM;
@@ -1124,7 +1124,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
ehca_mrmw_map_acl(acl, &hipz_acl);
ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl);
- kpage = ehca_alloc_fw_ctrlblock();
+ kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!kpage) {
ehca_err(&shca->ib_device, "kpage alloc failed");
ret = -ENOMEM;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index c6c9cef203e..34b85556d01 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -807,7 +807,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
unsigned long spl_flags = 0;
/* do query_qp to obtain current attr values */
- mqpcb = ehca_alloc_fw_ctrlblock();
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!mqpcb) {
ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
"ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
@@ -1273,7 +1273,7 @@ int ehca_query_qp(struct ib_qp *qp,
return -EINVAL;
}
- qpcb = ehca_alloc_fw_ctrlblock();
+ qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!qpcb) {
ehca_err(qp->device,"Out of memory for qpcb "
"ehca_qp=%p qp_num=%x", my_qp, qp->qp_num);
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
index 7dc10551cf1..ec2e603ea24 100644
--- a/drivers/infiniband/hw/ipath/Makefile
+++ b/drivers/infiniband/hw/ipath/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
ib_ipath-y := \
ipath_cq.o \
ipath_diag.o \
+ ipath_dma.o \
ipath_driver.o \
ipath_eeprom.o \
ipath_file_ops.o \
diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c
new file mode 100644
index 00000000000..6e0f2b8918c
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_dma.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2006 QLogic, Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_verbs.h>
+
+#include "ipath_verbs.h"
+
+#define BAD_DMA_ADDRESS ((u64) 0)
+
+/*
+ * The following functions implement driver specific replacements
+ * for the ib_dma_*() functions.
+ *
+ * These functions return kernel virtual addresses instead of
+ * device bus addresses since the driver uses the CPU to copy
+ * data instead of using hardware DMA.
+ */
+
+static int ipath_mapping_error(struct ib_device *dev, u64 dma_addr)
+{
+ return dma_addr == BAD_DMA_ADDRESS;
+}
+
+static u64 ipath_dma_map_single(struct ib_device *dev,
+ void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+ return (u64) cpu_addr;
+}
+
+static void ipath_dma_unmap_single(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+}
+
+static u64 ipath_dma_map_page(struct ib_device *dev,
+ struct page *page,
+ unsigned long offset,
+ size_t size,
+ enum dma_data_direction direction)
+{
+ u64 addr;
+
+ BUG_ON(!valid_dma_direction(direction));
+
+ if (offset + size > PAGE_SIZE) {
+ addr = BAD_DMA_ADDRESS;
+ goto done;
+ }
+
+ addr = (u64) page_address(page);
+ if (addr)
+ addr += offset;
+ /* TODO: handle highmem pages */
+
+done:
+ return addr;
+}
+
+static void ipath_dma_unmap_page(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+}
+
+int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ u64 addr;
+ int i;
+ int ret = nents;
+
+ BUG_ON(!valid_dma_direction(direction));
+
+ for (i = 0; i < nents; i++) {
+ addr = (u64) page_address(sg[i].page);
+ /* TODO: handle highmem pages */
+ if (!addr) {
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static void ipath_unmap_sg(struct ib_device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ BUG_ON(!valid_dma_direction(direction));
+}
+
+static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg)
+{
+ u64 addr = (u64) page_address(sg->page);
+
+ if (addr)
+ addr += sg->offset;
+ return addr;
+}
+
+static unsigned int ipath_sg_dma_len(struct ib_device *dev,
+ struct scatterlist *sg)
+{
+ return sg->length;
+}
+
+static void ipath_sync_single_for_cpu(struct ib_device *dev,
+ u64 addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+}
+
+static void ipath_sync_single_for_device(struct ib_device *dev,
+ u64 addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+}
+
+static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size,
+ u64 *dma_handle, gfp_t flag)
+{
+ struct page *p;
+ void *addr = NULL;
+
+ p = alloc_pages(flag, get_order(size));
+ if (p)
+ addr = page_address(p);
+ if (dma_handle)
+ *dma_handle = (u64) addr;
+ return addr;
+}
+
+static void ipath_dma_free_coherent(struct ib_device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long) cpu_addr, get_order(size));
+}
+
+struct ib_dma_mapping_ops ipath_dma_mapping_ops = {
+ ipath_mapping_error,
+ ipath_dma_map_single,
+ ipath_dma_unmap_single,
+ ipath_dma_map_page,
+ ipath_dma_unmap_page,
+ ipath_map_sg,
+ ipath_unmap_sg,
+ ipath_sg_dma_address,
+ ipath_sg_dma_len,
+ ipath_sync_single_for_cpu,
+ ipath_sync_single_for_device,
+ ipath_dma_alloc_coherent,
+ ipath_dma_free_coherent
+};
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 1aeddb48e35..ae7f21a0cdc 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1825,8 +1825,6 @@ void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno,
*/
void ipath_shutdown_device(struct ipath_devdata *dd)
{
- u64 val;
-
ipath_dbg("Shutting down the device\n");
dd->ipath_flags |= IPATH_LINKUNK;
@@ -1849,7 +1847,7 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
*/
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
/* flush it */
- val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
/*
* enough for anything that's going to trickle out to have actually
* done so.
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index a9ddc6911f6..b932bcb67a5 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -699,7 +699,6 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
int start_stop)
{
struct ipath_devdata *dd = pd->port_dd;
- u64 tval;
ipath_cdbg(PROC, "%sabling rcv for unit %u port %u:%u\n",
start_stop ? "en" : "dis", dd->ipath_unit,
@@ -729,7 +728,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
dd->ipath_rcvctrl);
/* now be sure chip saw it before we return */
- tval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
if (start_stop) {
/*
* And try to be sure that tail reg update has happened too.
@@ -738,7 +737,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
* in memory copy, since we could overwrite an update by the
* chip if we did.
*/
- tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
}
/* always; new head should be equal to new tail; see above */
bail:
@@ -1745,9 +1744,9 @@ static int ipath_assign_port(struct file *fp,
goto done;
}
- i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE;
+ i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE;
ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
- (long)fp->f_dentry->d_inode->i_rdev, i_minor);
+ (long)fp->f_path.dentry->d_inode->i_rdev, i_minor);
if (i_minor)
ret = find_free_port(i_minor - 1, fp, uinfo);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index d9ff283f725..79a60f020a2 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -118,7 +118,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
u16 i;
struct ipath_devdata *dd;
- dd = file->f_dentry->d_inode->i_private;
+ dd = file->f_path.dentry->d_inode->i_private;
for (i = 0; i < NUM_COUNTERS; i++)
counters[i] = ipath_snap_cntr(dd, i);
@@ -138,7 +138,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
struct ipath_devdata *dd;
u64 guid;
- dd = file->f_dentry->d_inode->i_private;
+ dd = file->f_path.dentry->d_inode->i_private;
guid = be64_to_cpu(dd->ipath_guid);
@@ -177,7 +177,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
u32 tmp, tmp2;
struct ipath_devdata *dd;
- dd = file->f_dentry->d_inode->i_private;
+ dd = file->f_path.dentry->d_inode->i_private;
/* so we only initialize non-zero fields. */
memset(portinfo, 0, sizeof portinfo);
@@ -324,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf,
goto bail;
}
- dd = file->f_dentry->d_inode->i_private;
+ dd = file->f_path.dentry->d_inode->i_private;
if (ipath_eeprom_read(dd, pos, tmp, count)) {
ipath_dev_err(dd, "failed to read from flash\n");
ret = -ENXIO;
@@ -377,7 +377,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
goto bail_tmp;
}
- dd = file->f_dentry->d_inode->i_private;
+ dd = file->f_path.dentry->d_inode->i_private;
if (ipath_eeprom_write(dd, pos, tmp, count)) {
ret = -ENXIO;
ipath_dev_err(dd, "failed to write to flash\n");
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
index e57c7a351cb..7468477ba83 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -1447,7 +1447,7 @@ static void ipath_ht_tidtemplate(struct ipath_devdata *dd)
static int ipath_ht_early_init(struct ipath_devdata *dd)
{
u32 __iomem *piobuf;
- u32 pioincr, val32, egrsize;
+ u32 pioincr, val32;
int i;
/*
@@ -1467,7 +1467,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
* errors interrupts if we ever see one).
*/
dd->ipath_rcvegrbufsize = dd->ipath_piosize2k;
- egrsize = dd->ipath_rcvegrbufsize;
/*
* the min() check here is currently a nop, but it may not
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index 6af89683f71..ae8bf9950c6 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -602,7 +602,7 @@ static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
*/
static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
{
- u64 val, tmp, config1, prev_val;
+ u64 val, config1, prev_val;
int ret = 0;
ipath_dbg("Trying to bringup serdes\n");
@@ -633,7 +633,7 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
| INFINIPATH_SERDC0_L1PWR_DN;
ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
/* be sure chip saw it */
- tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
udelay(5); /* need pll reset set at least for a bit */
/*
* after PLL is reset, set the per-lane Resets and TxIdle and
@@ -647,7 +647,7 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
"and txidle (%llx)\n", (unsigned long long) val);
ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
/* be sure chip saw it */
- tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
/* need PLL reset clear for at least 11 usec before lane
* resets cleared; give it a few more to be sure */
udelay(15);
@@ -851,12 +851,12 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
int pos, ret;
dd->ipath_msi_lo = 0; /* used as a flag during reset processing */
- dd->ipath_irq = pdev->irq;
ret = pci_enable_msi(dd->pcidev);
if (ret)
ipath_dev_err(dd, "pci_enable_msi failed: %d, "
"interrupts may not work\n", ret);
/* continue even if it fails, we may still be OK... */
+ dd->ipath_irq = pdev->irq;
if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
u16 control;
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index d819cca524c..d4f6b5239ef 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -347,10 +347,9 @@ done:
static int init_chip_reset(struct ipath_devdata *dd,
struct ipath_portdata **pdp)
{
- struct ipath_portdata *pd;
u32 rtmp;
- *pdp = pd = dd->ipath_pd[0];
+ *pdp = dd->ipath_pd[0];
/* ensure chip does no sends or receives while we re-initialize */
dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 5652a550d44..72b9e279d19 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -598,10 +598,9 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
* on close
*/
if (errs & INFINIPATH_E_RRCVHDRFULL) {
- int any;
u32 hd, tl;
ipath_stats.sps_hdrqfull++;
- for (any = i = 0; i < dd->ipath_cfgports; i++) {
+ for (i = 0; i < dd->ipath_cfgports; i++) {
struct ipath_portdata *pd = dd->ipath_pd[i];
if (i == 0) {
hd = dd->ipath_port0head;
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
index 9a6cbd05adc..851763d7d2d 100644
--- a/drivers/infiniband/hw/ipath/ipath_keys.c
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -134,7 +134,7 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
*/
if (sge->lkey == 0) {
isge->mr = NULL;
- isge->vaddr = bus_to_virt(sge->addr);
+ isge->vaddr = (void *) sge->addr;
isge->length = sge->length;
isge->sge_length = sge->length;
ret = 1;
@@ -202,12 +202,12 @@ int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss,
int ret;
/*
- * We use RKEY == zero for physical addresses
- * (see ipath_get_dma_mr).
+ * We use RKEY == zero for kernel virtual addresses
+ * (see ipath_get_dma_mr and ipath_dma.c).
*/
if (rkey == 0) {
sge->mr = NULL;
- sge->vaddr = phys_to_virt(vaddr);
+ sge->vaddr = (void *) vaddr;
sge->length = len;
sge->sge_length = len;
ss->sg_list = NULL;
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
index a0673c1eef7..8cc8598d6c6 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -54,6 +54,8 @@ static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr)
* @acc: access flags
*
* Returns the memory region on success, otherwise returns an errno.
+ * Note that all DMA addresses should be created via the
+ * struct ib_dma_mapping_ops functions (see ipath_dma.c).
*/
struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc)
{
@@ -149,8 +151,7 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
m = 0;
n = 0;
for (i = 0; i < num_phys_buf; i++) {
- mr->mr.map[m]->segs[n].vaddr =
- phys_to_virt(buffer_list[i].addr);
+ mr->mr.map[m]->segs[n].vaddr = (void *) buffer_list[i].addr;
mr->mr.map[m]->segs[n].length = buffer_list[i].size;
mr->mr.length += buffer_list[i].size;
n++;
@@ -347,7 +348,7 @@ int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
n = 0;
ps = 1 << fmr->page_shift;
for (i = 0; i < list_len; i++) {
- fmr->mr.map[m]->segs[n].vaddr = phys_to_virt(page_list[i]);
+ fmr->mr.map[m]->segs[n].vaddr = (void *) page_list[i];
fmr->mr.map[m]->segs[n].length = ps;
if (++n == IPATH_SEGSZ) {
m++;
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index 182de34f9f4..ffa6318ad0c 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -215,7 +215,6 @@ static ssize_t store_mlid(struct device *dev,
size_t count)
{
struct ipath_devdata *dd = dev_get_drvdata(dev);
- int unit;
u16 mlid;
int ret;
@@ -223,8 +222,6 @@ static ssize_t store_mlid(struct device *dev,
if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE)
goto invalid;
- unit = dd->ipath_unit;
-
dd->ipath_mlid = mlid;
goto bail;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index acdee33ee1f..2aaacdb7e52 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1599,6 +1599,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
dev->detach_mcast = ipath_multicast_detach;
dev->process_mad = ipath_process_mad;
dev->mmap = ipath_mmap;
+ dev->dma_ops = &ipath_dma_mapping_ops;
snprintf(dev->node_desc, sizeof(dev->node_desc),
IPATH_IDSTR " %s", init_utsname()->nodename);
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index 8039f6e5f0c..c0c8d5b24a7 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -812,4 +812,6 @@ extern unsigned int ib_ipath_max_srq_wrs;
extern const u32 ib_ipath_rnr_table[];
+extern struct ib_dma_mapping_ops ipath_dma_mapping_ops;
+
#endif /* IPATH_VERBS_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 283d50b76c3..1159c8a0f2c 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -54,6 +54,10 @@ enum {
MTHCA_CQ_ENTRY_SIZE = 0x20
};
+enum {
+ MTHCA_ATOMIC_BYTE_LEN = 8
+};
+
/*
* Must be packed because start is 64 bits but only aligned to 32 bits.
*/
@@ -599,11 +603,11 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
break;
case MTHCA_OPCODE_ATOMIC_CS:
entry->opcode = IB_WC_COMP_SWAP;
- entry->byte_len = be32_to_cpu(cqe->byte_cnt);
+ entry->byte_len = MTHCA_ATOMIC_BYTE_LEN;
break;
case MTHCA_OPCODE_ATOMIC_FA:
entry->opcode = IB_WC_FETCH_ADD;
- entry->byte_len = be32_to_cpu(cqe->byte_cnt);
+ entry->byte_len = MTHCA_ATOMIC_BYTE_LEN;
break;
case MTHCA_OPCODE_BIND_MW:
entry->opcode = IB_WC_BIND_MW;
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 0491ec7a7c0..44bc6cc734a 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -80,24 +80,61 @@ static int tune_pci = 0;
module_param(tune_pci, int, 0444);
MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");
-struct mutex mthca_device_mutex;
+DEFINE_MUTEX(mthca_device_mutex);
+
+#define MTHCA_DEFAULT_NUM_QP (1 << 16)
+#define MTHCA_DEFAULT_RDB_PER_QP (1 << 2)
+#define MTHCA_DEFAULT_NUM_CQ (1 << 16)
+#define MTHCA_DEFAULT_NUM_MCG (1 << 13)
+#define MTHCA_DEFAULT_NUM_MPT (1 << 17)
+#define MTHCA_DEFAULT_NUM_MTT (1 << 20)
+#define MTHCA_DEFAULT_NUM_UDAV (1 << 15)
+#define MTHCA_DEFAULT_NUM_RESERVED_MTTS (1 << 18)
+#define MTHCA_DEFAULT_NUM_UARC_SIZE (1 << 18)
+
+static struct mthca_profile hca_profile = {
+ .num_qp = MTHCA_DEFAULT_NUM_QP,
+ .rdb_per_qp = MTHCA_DEFAULT_RDB_PER_QP,
+ .num_cq = MTHCA_DEFAULT_NUM_CQ,
+ .num_mcg = MTHCA_DEFAULT_NUM_MCG,
+ .num_mpt = MTHCA_DEFAULT_NUM_MPT,
+ .num_mtt = MTHCA_DEFAULT_NUM_MTT,
+ .num_udav = MTHCA_DEFAULT_NUM_UDAV, /* Tavor only */
+ .fmr_reserved_mtts = MTHCA_DEFAULT_NUM_RESERVED_MTTS, /* Tavor only */
+ .uarc_size = MTHCA_DEFAULT_NUM_UARC_SIZE, /* Arbel only */
+};
+
+module_param_named(num_qp, hca_profile.num_qp, int, 0444);
+MODULE_PARM_DESC(num_qp, "maximum number of QPs per HCA");
+
+module_param_named(rdb_per_qp, hca_profile.rdb_per_qp, int, 0444);
+MODULE_PARM_DESC(rdb_per_qp, "number of RDB buffers per QP");
+
+module_param_named(num_cq, hca_profile.num_cq, int, 0444);
+MODULE_PARM_DESC(num_cq, "maximum number of CQs per HCA");
+
+module_param_named(num_mcg, hca_profile.num_mcg, int, 0444);
+MODULE_PARM_DESC(num_mcg, "maximum number of multicast groups per HCA");
+
+module_param_named(num_mpt, hca_profile.num_mpt, int, 0444);
+MODULE_PARM_DESC(num_mpt,
+ "maximum number of memory protection table entries per HCA");
+
+module_param_named(num_mtt, hca_profile.num_mtt, int, 0444);
+MODULE_PARM_DESC(num_mtt,
+ "maximum number of memory translation table segments per HCA");
+
+module_param_named(num_udav, hca_profile.num_udav, int, 0444);
+MODULE_PARM_DESC(num_udav, "maximum number of UD address vectors per HCA");
+
+module_param_named(fmr_reserved_mtts, hca_profile.fmr_reserved_mtts, int, 0444);
+MODULE_PARM_DESC(fmr_reserved_mtts,
+ "number of memory translation table segments reserved for FMR");
static const char mthca_version[] __devinitdata =
DRV_NAME ": Mellanox InfiniBand HCA driver v"
DRV_VERSION " (" DRV_RELDATE ")\n";
-static struct mthca_profile default_profile = {
- .num_qp = 1 << 16,
- .rdb_per_qp = 4,
- .num_cq = 1 << 16,
- .num_mcg = 1 << 13,
- .num_mpt = 1 << 17,
- .num_mtt = 1 << 20,
- .num_udav = 1 << 15, /* Tavor only */
- .fmr_reserved_mtts = 1 << 18, /* Tavor only */
- .uarc_size = 1 << 18, /* Arbel only */
-};
-
static int mthca_tune_pci(struct mthca_dev *mdev)
{
int cap;
@@ -303,7 +340,7 @@ static int mthca_init_tavor(struct mthca_dev *mdev)
goto err_disable;
}
- profile = default_profile;
+ profile = hca_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
profile.uarc_size = 0;
if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
@@ -621,7 +658,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
goto err_stop_fw;
}
- profile = default_profile;
+ profile = hca_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
profile.num_udav = 0;
if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
@@ -1278,11 +1315,55 @@ static struct pci_driver mthca_driver = {
.remove = __devexit_p(mthca_remove_one)
};
+static void __init __mthca_check_profile_val(const char *name, int *pval,
+ int pval_default)
+{
+ /* value must be positive and power of 2 */
+ int old_pval = *pval;
+
+ if (old_pval <= 0)
+ *pval = pval_default;
+ else
+ *pval = roundup_pow_of_two(old_pval);
+
+ if (old_pval != *pval) {
+ printk(KERN_WARNING PFX "Invalid value %d for %s in module parameter.\n",
+ old_pval, name);
+ printk(KERN_WARNING PFX "Corrected %s to %d.\n", name, *pval);
+ }
+}
+
+#define mthca_check_profile_val(name, default) \
+ __mthca_check_profile_val(#name, &hca_profile.name, default)
+
+static void __init mthca_validate_profile(void)
+{
+ mthca_check_profile_val(num_qp, MTHCA_DEFAULT_NUM_QP);
+ mthca_check_profile_val(rdb_per_qp, MTHCA_DEFAULT_RDB_PER_QP);
+ mthca_check_profile_val(num_cq, MTHCA_DEFAULT_NUM_CQ);
+ mthca_check_profile_val(num_mcg, MTHCA_DEFAULT_NUM_MCG);
+ mthca_check_profile_val(num_mpt, MTHCA_DEFAULT_NUM_MPT);
+ mthca_check_profile_val(num_mtt, MTHCA_DEFAULT_NUM_MTT);
+ mthca_check_profile_val(num_udav, MTHCA_DEFAULT_NUM_UDAV);
+ mthca_check_profile_val(fmr_reserved_mtts, MTHCA_DEFAULT_NUM_RESERVED_MTTS);
+
+ if (hca_profile.fmr_reserved_mtts >= hca_profile.num_mtt) {
+ printk(KERN_WARNING PFX "Invalid fmr_reserved_mtts module parameter %d.\n",
+ hca_profile.fmr_reserved_mtts);
+ printk(KERN_WARNING PFX "(Must be smaller than num_mtt %d)\n",
+ hca_profile.num_mtt);
+ hca_profile.fmr_reserved_mtts = hca_profile.num_mtt / 2;
+ printk(KERN_WARNING PFX "Corrected fmr_reserved_mtts to %d.\n",
+ hca_profile.fmr_reserved_mtts);
+ }
+}
+
static int __init mthca_init(void)
{
int ret;
- mutex_init(&mthca_device_mutex);
+ mthca_validate_profile();
+
ret = mthca_catas_init();
if (ret)
return ret;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 15cc2f6eb47..6b19645d946 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -232,7 +232,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj)
list_for_each_entry(chunk, &icm->chunk_list, list) {
for (i = 0; i < chunk->npages; ++i) {
- if (chunk->mem[i].length >= offset) {
+ if (chunk->mem[i].length > offset) {
page = chunk->mem[i].page;
goto out;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 21422a3336a..7b96751695e 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -124,7 +124,7 @@ static int mthca_query_device(struct ib_device *ibdev,
props->max_map_per_fmr = 255;
else
props->max_map_per_fmr =
- (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1;
+ (1 << (32 - ilog2(mdev->limits.num_mpts))) - 1;
err = 0;
out:
@@ -816,7 +816,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
lkey = ucmd.lkey;
}
- ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status);
+ ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status);
if (status)
ret = -EINVAL;
@@ -1100,10 +1100,11 @@ static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
struct mthca_fmr *fmr;
int err;
- fmr = kmemdup(fmr_attr, sizeof *fmr, GFP_KERNEL);
+ fmr = kmalloc(sizeof *fmr, GFP_KERNEL);
if (!fmr)
return ERR_PTR(-ENOMEM);
+ memcpy(&fmr->attr, fmr_attr, sizeof *fmr_attr);
err = mthca_fmr_alloc(to_mdev(pd->device), to_mpd(pd)->pd_num,
convert_access(mr_access_flags), fmr);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 33e3ba7937f..5f5214c0337 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -429,13 +429,18 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
- int err;
- struct mthca_mailbox *mailbox;
+ int err = 0;
+ struct mthca_mailbox *mailbox = NULL;
struct mthca_qp_param *qp_param;
struct mthca_qp_context *context;
int mthca_state;
u8 status;
+ if (qp->state == IB_QPS_RESET) {
+ qp_attr->qp_state = IB_QPS_RESET;
+ goto done;
+ }
+
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -454,7 +459,6 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
mthca_state = be32_to_cpu(context->flags) >> 28;
qp_attr->qp_state = to_ib_qp_state(mthca_state);
- qp_attr->cur_qp_state = qp_attr->qp_state;
qp_attr->path_mtu = context->mtu_msgmax >> 5;
qp_attr->path_mig_state =
to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3);
@@ -464,11 +468,6 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
qp_attr->dest_qp_num = be32_to_cpu(context->remote_qpn) & 0xffffff;
qp_attr->qp_access_flags =
to_ib_qp_access_flags(be32_to_cpu(context->params2));
- qp_attr->cap.max_send_wr = qp->sq.max;
- qp_attr->cap.max_recv_wr = qp->rq.max;
- qp_attr->cap.max_send_sge = qp->sq.max_gs;
- qp_attr->cap.max_recv_sge = qp->rq.max_gs;
- qp_attr->cap.max_inline_data = qp->max_inline_data;
if (qp->transport == RC || qp->transport == UC) {
to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
@@ -495,7 +494,16 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
qp_attr->retry_cnt = (be32_to_cpu(context->params1) >> 16) & 0x7;
qp_attr->rnr_retry = context->pri_path.rnr_retry >> 5;
qp_attr->alt_timeout = context->alt_path.ackto >> 3;
- qp_init_attr->cap = qp_attr->cap;
+
+done:
+ qp_attr->cur_qp_state = qp_attr->qp_state;
+ qp_attr->cap.max_send_wr = qp->sq.max;
+ qp_attr->cap.max_recv_wr = qp->rq.max;
+ qp_attr->cap.max_send_sge = qp->sq.max_gs;
+ qp_attr->cap.max_recv_sge = qp->rq.max_gs;
+ qp_attr->cap.max_inline_data = qp->max_inline_data;
+
+ qp_init_attr->cap = qp_attr->cap;
out:
mthca_free_mailbox(dev, mailbox);
@@ -636,11 +644,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
if (mthca_is_memfree(dev)) {
if (qp->rq.max)
- qp_context->rq_size_stride = long_log2(qp->rq.max) << 3;
+ qp_context->rq_size_stride = ilog2(qp->rq.max) << 3;
qp_context->rq_size_stride |= qp->rq.wqe_shift - 4;
if (qp->sq.max)
- qp_context->sq_size_stride = long_log2(qp->sq.max) << 3;
+ qp_context->sq_size_stride = ilog2(qp->sq.max) << 3;
qp_context->sq_size_stride |= qp->sq.wqe_shift - 4;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 34d2c476896..10684da33d5 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -120,7 +120,7 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev,
memset(context, 0, sizeof *context);
- logsize = long_log2(srq->max);
+ logsize = ilog2(srq->max);
context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn);
context->lkey = cpu_to_be32(srq->mr.ibmr.lkey);
context->db_index = cpu_to_be32(srq->db_index);
@@ -213,7 +213,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz))
return -EINVAL;
- srq->wqe_shift = long_log2(ds);
+ srq->wqe_shift = ilog2(ds);
srq->srqn = mthca_alloc(&dev->srq_table.alloc);
if (srq->srqn == -1)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 99547996aba..07deee8f81c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -105,12 +105,12 @@ struct ipoib_mcast;
struct ipoib_rx_buf {
struct sk_buff *skb;
- dma_addr_t mapping;
+ u64 mapping;
};
struct ipoib_tx_buf {
struct sk_buff *skb;
- DECLARE_PCI_UNMAP_ADDR(mapping)
+ u64 mapping;
};
/*
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index f10fba5d326..59d9594ed6d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -109,9 +109,8 @@ static int ipoib_ib_post_receive(struct net_device *dev, int id)
ret = ib_post_recv(priv->qp, &param, &bad_wr);
if (unlikely(ret)) {
ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
- dma_unmap_single(priv->ca->dma_device,
- priv->rx_ring[id].mapping,
- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_single(priv->ca, priv->rx_ring[id].mapping,
+ IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(priv->rx_ring[id].skb);
priv->rx_ring[id].skb = NULL;
}
@@ -123,7 +122,7 @@ static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct sk_buff *skb;
- dma_addr_t addr;
+ u64 addr;
skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
if (!skb)
@@ -136,10 +135,9 @@ static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
*/
skb_reserve(skb, 4);
- addr = dma_map_single(priv->ca->dma_device,
- skb->data, IPOIB_BUF_SIZE,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(addr))) {
+ addr = ib_dma_map_single(priv->ca, skb->data, IPOIB_BUF_SIZE,
+ DMA_FROM_DEVICE);
+ if (unlikely(ib_dma_mapping_error(priv->ca, addr))) {
dev_kfree_skb_any(skb);
return -EIO;
}
@@ -174,7 +172,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
struct ipoib_dev_priv *priv = netdev_priv(dev);
unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV;
struct sk_buff *skb;
- dma_addr_t addr;
+ u64 addr;
ipoib_dbg_data(priv, "recv completion: id %d, op %d, status: %d\n",
wr_id, wc->opcode, wc->status);
@@ -193,8 +191,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
ipoib_warn(priv, "failed recv event "
"(status=%d, wrid=%d vend_err %x)\n",
wc->status, wr_id, wc->vendor_err);
- dma_unmap_single(priv->ca->dma_device, addr,
- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_single(priv->ca, addr,
+ IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
priv->rx_ring[wr_id].skb = NULL;
return;
@@ -212,8 +210,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
wc->byte_len, wc->slid);
- dma_unmap_single(priv->ca->dma_device, addr,
- IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+ ib_dma_unmap_single(priv->ca, addr, IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
skb_put(skb, wc->byte_len);
skb_pull(skb, IB_GRH_BYTES);
@@ -261,10 +258,8 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
tx_req = &priv->tx_ring[wr_id];
- dma_unmap_single(priv->ca->dma_device,
- pci_unmap_addr(tx_req, mapping),
- tx_req->skb->len,
- DMA_TO_DEVICE);
+ ib_dma_unmap_single(priv->ca, tx_req->mapping,
+ tx_req->skb->len, DMA_TO_DEVICE);
++priv->stats.tx_packets;
priv->stats.tx_bytes += tx_req->skb->len;
@@ -311,7 +306,7 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
static inline int post_send(struct ipoib_dev_priv *priv,
unsigned int wr_id,
struct ib_ah *address, u32 qpn,
- dma_addr_t addr, int len)
+ u64 addr, int len)
{
struct ib_send_wr *bad_wr;
@@ -330,7 +325,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_tx_buf *tx_req;
- dma_addr_t addr;
+ u64 addr;
if (unlikely(skb->len > dev->mtu + INFINIBAND_ALEN)) {
ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
@@ -353,21 +348,20 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
*/
tx_req = &priv->tx_ring[priv->tx_head & (ipoib_sendq_size - 1)];
tx_req->skb = skb;
- addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,
- DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(addr))) {
+ addr = ib_dma_map_single(priv->ca, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ if (unlikely(ib_dma_mapping_error(priv->ca, addr))) {
++priv->stats.tx_errors;
dev_kfree_skb_any(skb);
return;
}
- pci_unmap_addr_set(tx_req, mapping, addr);
+ tx_req->mapping = addr;
if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
address->ah, qpn, addr, skb->len))) {
ipoib_warn(priv, "post_send failed\n");
++priv->stats.tx_errors;
- dma_unmap_single(priv->ca->dma_device, addr, skb->len,
- DMA_TO_DEVICE);
+ ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
} else {
dev->trans_start = jiffies;
@@ -538,24 +532,27 @@ int ipoib_ib_dev_stop(struct net_device *dev)
while ((int) priv->tx_tail - (int) priv->tx_head < 0) {
tx_req = &priv->tx_ring[priv->tx_tail &
(ipoib_sendq_size - 1)];
- dma_unmap_single(priv->ca->dma_device,
- pci_unmap_addr(tx_req, mapping),
- tx_req->skb->len,
- DMA_TO_DEVICE);
+ ib_dma_unmap_single(priv->ca,
+ tx_req->mapping,
+ tx_req->skb->len,
+ DMA_TO_DEVICE);
dev_kfree_skb_any(tx_req->skb);
++priv->tx_tail;
}
- for (i = 0; i < ipoib_recvq_size; ++i)
- if (priv->rx_ring[i].skb) {
- dma_unmap_single(priv->ca->dma_device,
- pci_unmap_addr(&priv->rx_ring[i],
- mapping),
- IPOIB_BUF_SIZE,
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(priv->rx_ring[i].skb);
- priv->rx_ring[i].skb = NULL;
- }
+ for (i = 0; i < ipoib_recvq_size; ++i) {
+ struct ipoib_rx_buf *rx_req;
+
+ rx_req = &priv->rx_ring[i];
+ if (!rx_req->skb)
+ continue;
+ ib_dma_unmap_single(priv->ca,
+ rx_req->mapping,
+ IPOIB_BUF_SIZE,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(rx_req->skb);
+ rx_req->skb = NULL;
+ }
goto timeout;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index c0928024372..705eb1d0e55 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -497,8 +497,6 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
return;
}
- skb_queue_head_init(&neigh->queue);
-
/*
* We can only be called from ipoib_start_xmit, so we're
* inside tx_lock -- no need to save/restore flags.
@@ -806,6 +804,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
neigh->neighbour = neighbour;
*to_ipoib_neigh(neighbour) = neigh;
+ skb_queue_head_init(&neigh->queue);
return neigh;
}
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 9b2041e25d5..dd221eda3ea 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -177,7 +177,7 @@ iscsi_iser_mtask_xmit(struct iscsi_conn *conn,
* - if yes, the mtask is recycled at iscsi_complete_pdu
* - if no, the mtask is recycled at iser_snd_completion
*/
- if (error && error != -EAGAIN)
+ if (error && error != -ENOBUFS)
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
return error;
@@ -241,7 +241,7 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask);
iscsi_iser_ctask_xmit_exit:
- if (error && error != -EAGAIN)
+ if (error && error != -ENOBUFS)
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
return error;
}
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 234e5b061a7..cae8c96a55f 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -182,7 +182,7 @@ struct iser_regd_buf {
struct iser_mem_reg reg; /* memory registration info */
void *virt_addr;
struct iser_device *device; /* device->device for dma_unmap */
- dma_addr_t dma_addr; /* if non zero, addr for dma_unmap */
+ u64 dma_addr; /* if non zero, addr for dma_unmap */
enum dma_data_direction direction; /* direction for dma_unmap */
unsigned int data_size;
atomic_t ref_count; /* refcount, freed when dec to 0 */
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 9b3d79c796c..0a7d1ab60e6 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -304,18 +304,14 @@ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
static int
iser_check_xmit(struct iscsi_conn *conn, void *task)
{
- int rc = 0;
struct iscsi_iser_conn *iser_conn = conn->dd_data;
- write_lock_bh(conn->recv_lock);
if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
ISER_QP_MAX_REQ_DTOS) {
- iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task);
- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
- rc = -EAGAIN;
+ iser_dbg("%ld can't xmit task %p\n",jiffies,task);
+ return -ENOBUFS;
}
- write_unlock_bh(conn->recv_lock);
- return rc;
+ return 0;
}
@@ -340,7 +336,7 @@ int iser_send_command(struct iscsi_conn *conn,
return -EPERM;
}
if (iser_check_xmit(conn, ctask))
- return -EAGAIN;
+ return -ENOBUFS;
edtl = ntohl(hdr->data_length);
@@ -426,7 +422,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
}
if (iser_check_xmit(conn, ctask))
- return -EAGAIN;
+ return -ENOBUFS;
itt = ntohl(hdr->itt);
data_seg_len = ntoh24(hdr->dlength);
@@ -487,10 +483,8 @@ int iser_send_control(struct iscsi_conn *conn,
struct iscsi_iser_conn *iser_conn = conn->dd_data;
struct iser_desc *mdesc = mtask->dd_data;
struct iser_dto *send_dto = NULL;
- unsigned int itt;
unsigned long data_seg_len;
int err = 0;
- unsigned char opcode;
struct iser_regd_buf *regd_buf;
struct iser_device *device;
@@ -500,7 +494,7 @@ int iser_send_control(struct iscsi_conn *conn,
}
if (iser_check_xmit(conn,mtask))
- return -EAGAIN;
+ return -ENOBUFS;
/* build the tx desc regd header and add it to the tx desc dto */
mdesc->type = ISCSI_TX_CONTROL;
@@ -512,8 +506,6 @@ int iser_send_control(struct iscsi_conn *conn,
iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
- itt = ntohl(mtask->hdr->itt);
- opcode = mtask->hdr->opcode & ISCSI_OPCODE_MASK;
data_seg_len = ntoh24(mtask->hdr->dlength);
if (data_seg_len > 0) {
@@ -609,6 +601,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
struct iscsi_conn *conn = iser_conn->iscsi_conn;
struct iscsi_mgmt_task *mtask;
+ int resume_tx = 0;
iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
@@ -617,15 +610,16 @@ void iser_snd_completion(struct iser_desc *tx_desc)
if (tx_desc->type == ISCSI_TX_DATAOUT)
kmem_cache_free(ig.desc_cache, tx_desc);
+ if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
+ ISER_QP_MAX_REQ_DTOS)
+ resume_tx = 1;
+
atomic_dec(&ib_conn->post_send_buf_count);
- write_lock(conn->recv_lock);
- if (conn->suspend_tx) {
+ if (resume_tx) {
iser_dbg("%ld resuming tx\n",jiffies);
- clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
scsi_queue_work(conn->session->host, &conn->xmitwork);
}
- write_unlock(conn->recv_lock);
if (tx_desc->type == ISCSI_TX_CONTROL) {
/* this arithmetic is legal by libiscsi dd_data allocation */
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index 5e122501fd8..fc9f1fd0ae5 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -52,7 +52,7 @@
*/
int iser_regd_buff_release(struct iser_regd_buf *regd_buf)
{
- struct device *dma_device;
+ struct ib_device *dev;
if ((atomic_read(&regd_buf->ref_count) == 0) ||
atomic_dec_and_test(&regd_buf->ref_count)) {
@@ -61,8 +61,8 @@ int iser_regd_buff_release(struct iser_regd_buf *regd_buf)
iser_unreg_mem(&regd_buf->reg);
if (regd_buf->dma_addr) {
- dma_device = regd_buf->device->ib_device->dma_device;
- dma_unmap_single(dma_device,
+ dev = regd_buf->device->ib_device;
+ ib_dma_unmap_single(dev,
regd_buf->dma_addr,
regd_buf->data_size,
regd_buf->direction);
@@ -84,12 +84,12 @@ void iser_reg_single(struct iser_device *device,
struct iser_regd_buf *regd_buf,
enum dma_data_direction direction)
{
- dma_addr_t dma_addr;
+ u64 dma_addr;
- dma_addr = dma_map_single(device->ib_device->dma_device,
- regd_buf->virt_addr,
- regd_buf->data_size, direction);
- BUG_ON(dma_mapping_error(dma_addr));
+ dma_addr = ib_dma_map_single(device->ib_device,
+ regd_buf->virt_addr,
+ regd_buf->data_size, direction);
+ BUG_ON(ib_dma_mapping_error(device->ib_device, dma_addr));
regd_buf->reg.lkey = device->mr->lkey;
regd_buf->reg.len = regd_buf->data_size;
@@ -107,14 +107,14 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
enum iser_data_dir cmd_dir)
{
int dma_nents;
- struct device *dma_device;
+ struct ib_device *dev;
char *mem = NULL;
struct iser_data_buf *data = &iser_ctask->data[cmd_dir];
unsigned long cmd_data_len = data->data_len;
if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
mem = (void *)__get_free_pages(GFP_NOIO,
- long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+ ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
else
mem = kmalloc(cmd_data_len, GFP_NOIO);
@@ -147,17 +147,12 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
iser_ctask->data_copy[cmd_dir].copy_buf = mem;
- dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
-
- if (cmd_dir == ISER_DIR_OUT)
- dma_nents = dma_map_sg(dma_device,
- &iser_ctask->data_copy[cmd_dir].sg_single,
- 1, DMA_TO_DEVICE);
- else
- dma_nents = dma_map_sg(dma_device,
- &iser_ctask->data_copy[cmd_dir].sg_single,
- 1, DMA_FROM_DEVICE);
-
+ dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
+ dma_nents = ib_dma_map_sg(dev,
+ &iser_ctask->data_copy[cmd_dir].sg_single,
+ 1,
+ (cmd_dir == ISER_DIR_OUT) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE);
BUG_ON(dma_nents == 0);
iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents;
@@ -170,19 +165,16 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
enum iser_data_dir cmd_dir)
{
- struct device *dma_device;
+ struct ib_device *dev;
struct iser_data_buf *mem_copy;
unsigned long cmd_data_len;
- dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
- mem_copy = &iser_ctask->data_copy[cmd_dir];
+ dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
+ mem_copy = &iser_ctask->data_copy[cmd_dir];
- if (cmd_dir == ISER_DIR_OUT)
- dma_unmap_sg(dma_device, &mem_copy->sg_single, 1,
- DMA_TO_DEVICE);
- else
- dma_unmap_sg(dma_device, &mem_copy->sg_single, 1,
- DMA_FROM_DEVICE);
+ ib_dma_unmap_sg(dev, &mem_copy->sg_single, 1,
+ (cmd_dir == ISER_DIR_OUT) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (cmd_dir == ISER_DIR_IN) {
char *mem;
@@ -211,7 +203,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
free_pages((unsigned long)mem_copy->copy_buf,
- long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+ ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
else
kfree(mem_copy->copy_buf);
@@ -231,11 +223,12 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
* consecutive elements. Also, it handles one entry SG.
*/
static int iser_sg_to_page_vec(struct iser_data_buf *data,
- struct iser_page_vec *page_vec)
+ struct iser_page_vec *page_vec,
+ struct ib_device *ibdev)
{
struct scatterlist *sg = (struct scatterlist *)data->buf;
- dma_addr_t first_addr, last_addr, page;
- int start_aligned, end_aligned;
+ u64 first_addr, last_addr, page;
+ int end_aligned;
unsigned int cur_page = 0;
unsigned long total_sz = 0;
int i;
@@ -244,19 +237,21 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
page_vec->offset = (u64) sg[0].offset & ~MASK_4K;
for (i = 0; i < data->dma_nents; i++) {
- total_sz += sg_dma_len(&sg[i]);
+ unsigned int dma_len = ib_sg_dma_len(ibdev, &sg[i]);
+
+ total_sz += dma_len;
- first_addr = sg_dma_address(&sg[i]);
- last_addr = first_addr + sg_dma_len(&sg[i]);
+ first_addr = ib_sg_dma_address(ibdev, &sg[i]);
+ last_addr = first_addr + dma_len;
- start_aligned = !(first_addr & ~MASK_4K);
end_aligned = !(last_addr & ~MASK_4K);
/* continue to collect page fragments till aligned or SG ends */
while (!end_aligned && (i + 1 < data->dma_nents)) {
i++;
- total_sz += sg_dma_len(&sg[i]);
- last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]);
+ dma_len = ib_sg_dma_len(ibdev, &sg[i]);
+ total_sz += dma_len;
+ last_addr = ib_sg_dma_address(ibdev, &sg[i]) + dma_len;
end_aligned = !(last_addr & ~MASK_4K);
}
@@ -288,10 +283,11 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
* the number of entries which are aligned correctly. Supports the case where
* consecutive SG elements are actually fragments of the same physcial page.
*/
-static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data)
+static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data,
+ struct ib_device *ibdev)
{
struct scatterlist *sg;
- dma_addr_t end_addr, next_addr;
+ u64 end_addr, next_addr;
int i, cnt;
unsigned int ret_len = 0;
@@ -303,12 +299,12 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data)
(unsigned long)page_to_phys(sg[i].page),
(unsigned long)sg[i].offset,
(unsigned long)sg[i].length); */
- end_addr = sg_dma_address(&sg[i]) +
- sg_dma_len(&sg[i]);
+ end_addr = ib_sg_dma_address(ibdev, &sg[i]) +
+ ib_sg_dma_len(ibdev, &sg[i]);
/* iser_dbg("Checking sg iobuf end address "
"0x%08lX\n", end_addr); */
if (i + 1 < data->dma_nents) {
- next_addr = sg_dma_address(&sg[i+1]);
+ next_addr = ib_sg_dma_address(ibdev, &sg[i+1]);
/* are i, i+1 fragments of the same page? */
if (end_addr == next_addr)
continue;
@@ -325,7 +321,8 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data)
return ret_len;
}
-static void iser_data_buf_dump(struct iser_data_buf *data)
+static void iser_data_buf_dump(struct iser_data_buf *data,
+ struct ib_device *ibdev)
{
struct scatterlist *sg = (struct scatterlist *)data->buf;
int i;
@@ -333,9 +330,9 @@ static void iser_data_buf_dump(struct iser_data_buf *data)
for (i = 0; i < data->dma_nents; i++)
iser_err("sg[%d] dma_addr:0x%lX page:0x%p "
"off:0x%x sz:0x%x dma_len:0x%x\n",
- i, (unsigned long)sg_dma_address(&sg[i]),
+ i, (unsigned long)ib_sg_dma_address(ibdev, &sg[i]),
sg[i].page, sg[i].offset,
- sg[i].length,sg_dma_len(&sg[i]));
+ sg[i].length, ib_sg_dma_len(ibdev, &sg[i]));
}
static void iser_dump_page_vec(struct iser_page_vec *page_vec)
@@ -349,7 +346,8 @@ static void iser_dump_page_vec(struct iser_page_vec *page_vec)
}
static void iser_page_vec_build(struct iser_data_buf *data,
- struct iser_page_vec *page_vec)
+ struct iser_page_vec *page_vec,
+ struct ib_device *ibdev)
{
int page_vec_len = 0;
@@ -357,14 +355,14 @@ static void iser_page_vec_build(struct iser_data_buf *data,
page_vec->offset = 0;
iser_dbg("Translating sg sz: %d\n", data->dma_nents);
- page_vec_len = iser_sg_to_page_vec(data,page_vec);
+ page_vec_len = iser_sg_to_page_vec(data, page_vec, ibdev);
iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len);
page_vec->length = page_vec_len;
if (page_vec_len * SIZE_4K < page_vec->data_size) {
iser_err("page_vec too short to hold this SG\n");
- iser_data_buf_dump(data);
+ iser_data_buf_dump(data, ibdev);
iser_dump_page_vec(page_vec);
BUG();
}
@@ -375,13 +373,12 @@ int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
enum iser_data_dir iser_dir,
enum dma_data_direction dma_dir)
{
- struct device *dma_device;
+ struct ib_device *dev;
iser_ctask->dir[iser_dir] = 1;
- dma_device =
- iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+ dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
- data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir);
+ data->dma_nents = ib_dma_map_sg(dev, data->buf, data->size, dma_dir);
if (data->dma_nents == 0) {
iser_err("dma_map_sg failed!!!\n");
return -EINVAL;
@@ -391,20 +388,19 @@ int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
{
- struct device *dma_device;
+ struct ib_device *dev;
struct iser_data_buf *data;
- dma_device =
- iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+ dev = iser_ctask->iser_conn->ib_conn->device->ib_device;
if (iser_ctask->dir[ISER_DIR_IN]) {
data = &iser_ctask->data[ISER_DIR_IN];
- dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE);
+ ib_dma_unmap_sg(dev, data->buf, data->size, DMA_FROM_DEVICE);
}
if (iser_ctask->dir[ISER_DIR_OUT]) {
data = &iser_ctask->data[ISER_DIR_OUT];
- dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE);
+ ib_dma_unmap_sg(dev, data->buf, data->size, DMA_TO_DEVICE);
}
}
@@ -419,6 +415,7 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
{
struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn;
struct iser_device *device = ib_conn->device;
+ struct ib_device *ibdev = device->ib_device;
struct iser_data_buf *mem = &iser_ctask->data[cmd_dir];
struct iser_regd_buf *regd_buf;
int aligned_len;
@@ -428,11 +425,11 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
regd_buf = &iser_ctask->rdma_regd[cmd_dir];
- aligned_len = iser_data_buf_aligned_len(mem);
+ aligned_len = iser_data_buf_aligned_len(mem, ibdev);
if (aligned_len != mem->dma_nents) {
iser_err("rdma alignment violation %d/%d aligned\n",
aligned_len, mem->size);
- iser_data_buf_dump(mem);
+ iser_data_buf_dump(mem, ibdev);
/* unmap the command data before accessing it */
iser_dma_unmap_task_data(iser_ctask);
@@ -450,8 +447,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
regd_buf->reg.lkey = device->mr->lkey;
regd_buf->reg.rkey = device->mr->rkey;
- regd_buf->reg.len = sg_dma_len(&sg[0]);
- regd_buf->reg.va = sg_dma_address(&sg[0]);
+ regd_buf->reg.len = ib_sg_dma_len(ibdev, &sg[0]);
+ regd_buf->reg.va = ib_sg_dma_address(ibdev, &sg[0]);
regd_buf->reg.is_fmr = 0;
iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X "
@@ -461,10 +458,10 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
(unsigned long)regd_buf->reg.va,
(unsigned long)regd_buf->reg.len);
} else { /* use FMR for multiple dma entries */
- iser_page_vec_build(mem, ib_conn->page_vec);
+ iser_page_vec_build(mem, ib_conn->page_vec, ibdev);
err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg);
if (err) {
- iser_data_buf_dump(mem);
+ iser_data_buf_dump(mem, ibdev);
iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", mem->dma_nents,
ntoh24(iser_ctask->desc.iscsi_header.dlength));
iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n",
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index a6289595557..72611fd1510 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -122,9 +122,8 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
if (!iu->buf)
goto out_free_iu;
- iu->dma = dma_map_single(host->dev->dev->dma_device,
- iu->buf, size, direction);
- if (dma_mapping_error(iu->dma))
+ iu->dma = ib_dma_map_single(host->dev->dev, iu->buf, size, direction);
+ if (ib_dma_mapping_error(host->dev->dev, iu->dma))
goto out_free_buf;
iu->size = size;
@@ -145,8 +144,7 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
if (!iu)
return;
- dma_unmap_single(host->dev->dev->dma_device,
- iu->dma, iu->size, iu->direction);
+ ib_dma_unmap_single(host->dev->dev, iu->dma, iu->size, iu->direction);
kfree(iu->buf);
kfree(iu);
}
@@ -482,8 +480,8 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
scat = &req->fake_sg;
}
- dma_unmap_sg(target->srp_host->dev->dev->dma_device, scat, nents,
- scmnd->sc_data_direction);
+ ib_dma_unmap_sg(target->srp_host->dev->dev, scat, nents,
+ scmnd->sc_data_direction);
}
static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
@@ -595,23 +593,26 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
int i, j;
int ret;
struct srp_device *dev = target->srp_host->dev;
+ struct ib_device *ibdev = dev->dev;
if (!dev->fmr_pool)
return -ENODEV;
- if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) &&
+ if ((ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask) &&
mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3))
return -EINVAL;
len = page_cnt = 0;
for (i = 0; i < sg_cnt; ++i) {
- if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
+ unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+
+ if (ib_sg_dma_address(ibdev, &scat[i]) & ~dev->fmr_page_mask) {
if (i > 0)
return -EINVAL;
else
++page_cnt;
}
- if ((sg_dma_address(&scat[i]) + sg_dma_len(&scat[i])) &
+ if ((ib_sg_dma_address(ibdev, &scat[i]) + dma_len) &
~dev->fmr_page_mask) {
if (i < sg_cnt - 1)
return -EINVAL;
@@ -619,7 +620,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
++page_cnt;
}
- len += sg_dma_len(&scat[i]);
+ len += dma_len;
}
page_cnt += len >> dev->fmr_page_shift;
@@ -631,10 +632,14 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
return -ENOMEM;
page_cnt = 0;
- for (i = 0; i < sg_cnt; ++i)
- for (j = 0; j < sg_dma_len(&scat[i]); j += dev->fmr_page_size)
+ for (i = 0; i < sg_cnt; ++i) {
+ unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+
+ for (j = 0; j < dma_len; j += dev->fmr_page_size)
dma_pages[page_cnt++] =
- (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j;
+ (ib_sg_dma_address(ibdev, &scat[i]) &
+ dev->fmr_page_mask) + j;
+ }
req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool,
dma_pages, page_cnt, io_addr);
@@ -644,7 +649,8 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
goto out;
}
- buf->va = cpu_to_be64(sg_dma_address(&scat[0]) & ~dev->fmr_page_mask);
+ buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, &scat[0]) &
+ ~dev->fmr_page_mask);
buf->key = cpu_to_be32(req->fmr->fmr->rkey);
buf->len = cpu_to_be32(len);
@@ -663,6 +669,8 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
struct srp_cmd *cmd = req->cmd->buf;
int len, nents, count;
u8 fmt = SRP_DATA_DESC_DIRECT;
+ struct srp_device *dev;
+ struct ib_device *ibdev;
if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
return sizeof (struct srp_cmd);
@@ -687,8 +695,10 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
}
- count = dma_map_sg(target->srp_host->dev->dev->dma_device,
- scat, nents, scmnd->sc_data_direction);
+ dev = target->srp_host->dev;
+ ibdev = dev->dev;
+
+ count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
fmt = SRP_DATA_DESC_DIRECT;
len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf);
@@ -702,9 +712,9 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
*/
struct srp_direct_buf *buf = (void *) cmd->add_data;
- buf->va = cpu_to_be64(sg_dma_address(scat));
- buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
- buf->len = cpu_to_be32(sg_dma_len(scat));
+ buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, scat));
+ buf->key = cpu_to_be32(dev->mr->rkey);
+ buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
} else if (srp_map_fmr(target, scat, count, req,
(void *) cmd->add_data)) {
/*
@@ -722,13 +732,14 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
count * sizeof (struct srp_direct_buf);
for (i = 0; i < count; ++i) {
+ unsigned int dma_len = ib_sg_dma_len(ibdev, &scat[i]);
+
buf->desc_list[i].va =
- cpu_to_be64(sg_dma_address(&scat[i]));
+ cpu_to_be64(ib_sg_dma_address(ibdev, &scat[i]));
buf->desc_list[i].key =
- cpu_to_be32(target->srp_host->dev->mr->rkey);
- buf->desc_list[i].len =
- cpu_to_be32(sg_dma_len(&scat[i]));
- datalen += sg_dma_len(&scat[i]);
+ cpu_to_be32(dev->mr->rkey);
+ buf->desc_list[i].len = cpu_to_be32(dma_len);
+ datalen += dma_len;
}
if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -808,13 +819,15 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
{
+ struct ib_device *dev;
struct srp_iu *iu;
u8 opcode;
iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
- dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma,
- target->max_ti_iu_len, DMA_FROM_DEVICE);
+ dev = target->srp_host->dev->dev;
+ ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
+ DMA_FROM_DEVICE);
opcode = *(u8 *) iu->buf;
@@ -850,8 +863,8 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
break;
}
- dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma,
- target->max_ti_iu_len, DMA_FROM_DEVICE);
+ ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
+ DMA_FROM_DEVICE);
}
static void srp_completion(struct ib_cq *cq, void *target_ptr)
@@ -969,6 +982,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
struct srp_request *req;
struct srp_iu *iu;
struct srp_cmd *cmd;
+ struct ib_device *dev;
int len;
if (target->state == SRP_TARGET_CONNECTING)
@@ -985,8 +999,9 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
if (!iu)
goto err;
- dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma,
- srp_max_iu_len, DMA_TO_DEVICE);
+ dev = target->srp_host->dev->dev;
+ ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
+ DMA_TO_DEVICE);
req = list_entry(target->free_reqs.next, struct srp_request, list);
@@ -1018,8 +1033,8 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
goto err_unmap;
}
- dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma,
- srp_max_iu_len, DMA_TO_DEVICE);
+ ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
+ DMA_TO_DEVICE);
if (__srp_post_send(target, iu, len)) {
printk(KERN_ERR PFX "Send failed\n");
@@ -1606,18 +1621,30 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
switch (token) {
case SRP_OPT_ID_EXT:
p = match_strdup(args);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
target->id_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
kfree(p);
break;
case SRP_OPT_IOC_GUID:
p = match_strdup(args);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
target->ioc_guid = cpu_to_be64(simple_strtoull(p, NULL, 16));
kfree(p);
break;
case SRP_OPT_DGID:
p = match_strdup(args);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
if (strlen(p) != 32) {
printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
kfree(p);
@@ -1641,6 +1668,10 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
case SRP_OPT_SERVICE_ID:
p = match_strdup(args);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));
kfree(p);
break;
@@ -1678,6 +1709,10 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
case SRP_OPT_INITIATOR_EXT:
p = match_strdup(args);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
target->initiator_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
kfree(p);
break;
@@ -1883,7 +1918,7 @@ static void srp_add_one(struct ib_device *device)
*/
srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1);
srp_dev->fmr_page_size = 1 << srp_dev->fmr_page_shift;
- srp_dev->fmr_page_mask = ~((unsigned long) srp_dev->fmr_page_size - 1);
+ srp_dev->fmr_page_mask = ~((u64) srp_dev->fmr_page_size - 1);
INIT_LIST_HEAD(&srp_dev->dev_list);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index d4e35ef5137..c21772317b8 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -87,7 +87,7 @@ struct srp_device {
struct ib_fmr_pool *fmr_pool;
int fmr_page_shift;
int fmr_page_size;
- unsigned long fmr_page_mask;
+ u64 fmr_page_mask;
};
struct srp_host {
@@ -161,7 +161,7 @@ struct srp_target_port {
};
struct srp_iu {
- dma_addr_t dma;
+ u64 dma;
void *buf;
size_t size;
enum dma_data_direction direction;
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index a005b1df5f1..da575deb3c7 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_INPUT_MOUSE) += mouse/
obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
+
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 35656cadc91..783b3412cea 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -203,7 +203,7 @@ static int erase_effect(struct input_dev *dev, int effect_id,
}
/**
- * input_ff_erase - erase an effect from device
+ * input_ff_erase - erase a force-feedback effect from device
* @dev: input device to erase effect from
* @effect_id: id of the ffect to be erased
* @file: purported owner of the request
@@ -347,7 +347,7 @@ EXPORT_SYMBOL_GPL(input_ff_create);
/**
* input_ff_free() - frees force feedback portion of input device
- * @dev: input device supporintg force feedback
+ * @dev: input device supporting force feedback
*
* This function is only needed in error path as input core will
* automatically free force feedback structures when device is
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index cd8b7297e6d..eba18b6ac5e 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -460,7 +460,7 @@ static void ml_ff_destroy(struct ff_device *ff)
}
/**
- * input_ff_create_memless() - create memoryless FF device
+ * input_ff_create_memless() - create memoryless force-feedback device
* @dev: input device supporting force-feedback
* @data: driver-specific data to be passed into @play_effect
* @play_effect: driver-specific method for playing FF effect
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 79dfb4b25c9..a00fe470a82 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -731,12 +731,6 @@ static int gameport_driver_remove(struct device *dev)
return 0;
}
-static struct bus_type gameport_bus = {
- .name = "gameport",
- .probe = gameport_driver_probe,
- .remove = gameport_driver_remove,
-};
-
static void gameport_add_driver(struct gameport_driver *drv)
{
int error;
@@ -782,6 +776,15 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv)
return !gameport_drv->ignore;
}
+static struct bus_type gameport_bus = {
+ .name = "gameport",
+ .dev_attrs = gameport_device_attrs,
+ .drv_attrs = gameport_driver_attrs,
+ .match = gameport_bus_match,
+ .probe = gameport_driver_probe,
+ .remove = gameport_driver_remove,
+};
+
static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
{
mutex_lock(&gameport->drv_mutex);
@@ -791,7 +794,6 @@ static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *
int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
{
-
if (gameport->open) {
if (gameport->open(gameport, mode)) {
return -1;
@@ -819,9 +821,6 @@ static int __init gameport_init(void)
{
int error;
- gameport_bus.dev_attrs = gameport_device_attrs;
- gameport_bus.drv_attrs = gameport_driver_attrs;
- gameport_bus.match = gameport_bus_match;
error = bus_register(&gameport_bus);
if (error) {
printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
index d65d8108025..6b4d4561d46 100644
--- a/drivers/input/gameport/lightning.c
+++ b/drivers/input/gameport/lightning.c
@@ -309,7 +309,7 @@ static int __init l4_init(void)
int i, cards = 0;
if (!request_region(L4_PORT, 1, "lightning"))
- return -1;
+ return -EBUSY;
for (i = 0; i < 2; i++)
if (l4_add_card(i) == 0)
@@ -319,7 +319,7 @@ static int __init l4_init(void)
if (!cards) {
release_region(L4_PORT, 1);
- return -1;
+ return -ENODEV;
}
return 0;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 1c8c8a5bc4a..7cf2b4f603a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -37,7 +37,7 @@ static struct input_handler *input_table[8];
/**
* input_event() - report new input event
- * @handle: device that generated the event
+ * @dev: device that generated the event
* @type: type of the event
* @code: event code
* @value: value of the event
@@ -900,6 +900,15 @@ struct class input_class = {
};
EXPORT_SYMBOL_GPL(input_class);
+/**
+ * input_allocate_device - allocate memory for new input device
+ *
+ * Returns prepared struct input_dev or NULL.
+ *
+ * NOTE: Use input_free_device() to free devices that have not been
+ * registered; input_unregister_device() should be used for already
+ * registered devices.
+ */
struct input_dev *input_allocate_device(void)
{
struct input_dev *dev;
@@ -919,6 +928,20 @@ struct input_dev *input_allocate_device(void)
}
EXPORT_SYMBOL(input_allocate_device);
+/**
+ * input_free_device - free memory occupied by input_dev structure
+ * @dev: input device to free
+ *
+ * This function should only be used if input_register_device()
+ * was not called yet or if it failed. Once device was registered
+ * use input_unregister_device() and memory will be freed once last
+ * refrence to the device is dropped.
+ *
+ * Device should be allocated by input_allocate_device().
+ *
+ * NOTE: If there are references to the input device then memory
+ * will not be freed until last reference is dropped.
+ */
void input_free_device(struct input_dev *dev)
{
if (dev) {
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index 704bf70f1db..6279ced8a35 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -521,11 +521,19 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0) {
adi_init_center(port->adi + i);
- input_register_device(port->adi[i].dev);
+ err = input_register_device(port->adi[i].dev);
+ if (err)
+ goto fail3;
}
return 0;
+ fail3: while (--i >= 0) {
+ if (port->adi[i].length > 0) {
+ input_unregister_device(port->adi[i].dev);
+ port->adi[i].dev = NULL;
+ }
+ }
fail2: for (i = 0; i < 2; i++)
if (port->adi[i].dev)
input_free_device(port->adi[i].dev);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 650acf3a30b..e608691b5a6 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -147,7 +147,11 @@ static int __init amijoy_init(void)
amijoy_dev[i]->absmax[ABS_X + j] = 1;
}
- input_register_device(amijoy_dev[i]);
+ err = input_register_device(amijoy_dev[i]);
+ if (err) {
+ input_free_device(amijoy_dev[i]);
+ goto fail;
+ }
}
return 0;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index e9a02db36ec..7ef68456d7d 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -434,6 +434,7 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i
{
struct input_dev *input_dev;
int i, j, t, v, w, x, y, z;
+ int error;
analog_name(analog);
snprintf(analog->phys, sizeof(analog->phys),
@@ -505,7 +506,11 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i
analog_decode(analog, port->axes, port->initial, port->buttons);
- input_register_device(analog->dev);
+ error = input_register_device(analog->dev);
+ if (error) {
+ input_free_device(analog->dev);
+ return error;
+ }
return 0;
}
@@ -668,7 +673,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
return 0;
fail3: while (--i >= 0)
- input_unregister_device(port->analog[i].dev);
+ if (port->analog[i].mask)
+ input_unregister_device(port->analog[i].dev);
fail2: gameport_close(gameport);
fail1: gameport_set_drvdata(gameport, NULL);
kfree(port);
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index d5e42eb88a2..034ec39c251 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -223,12 +223,15 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
for (j = 0; cobra_btn[j]; j++)
set_bit(cobra_btn[j], input_dev->keybit);
- input_register_device(cobra->dev[i]);
+ err = input_register_device(cobra->dev[i]);
+ if (err)
+ goto fail4;
}
return 0;
- fail3: for (i = 0; i < 2; i++)
+ fail4: input_free_device(cobra->dev[i]);
+ fail3: while (--i >= 0)
if (cobra->dev[i])
input_unregister_device(cobra->dev[i]);
fail2: gameport_close(gameport);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index e4a699f6ec8..bacbab5d1b6 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -341,7 +341,9 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
}
- input_register_device(gf2k->dev);
+ err = input_register_device(gf2k->dev);
+ if (err)
+ goto fail2;
return 0;
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 62438944a69..8120a9c4077 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -423,7 +423,10 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
if (!port->registered) {
dbg("New Grip pad in multiport slot %d.\n", slot);
- register_slot(slot, grip);
+ if (register_slot(slot, grip)) {
+ port->mode = GRIP_MODE_RESET;
+ port->dirty = 0;
+ }
}
return flags;
}
@@ -585,6 +588,7 @@ static int register_slot(int slot, struct grip_mp *grip)
struct grip_port *port = grip->port[slot];
struct input_dev *input_dev;
int j, t;
+ int err;
port->dev = input_dev = input_allocate_device();
if (!input_dev)
@@ -610,7 +614,12 @@ static int register_slot(int slot, struct grip_mp *grip)
if (t > 0)
set_bit(t, input_dev->keybit);
- input_register_device(port->dev);
+ err = input_register_device(port->dev);
+ if (err) {
+ input_free_device(port->dev);
+ return err;
+ }
+
port->registered = 1;
if (port->dirty) /* report initial state, if any */
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 840ed9b512b..dbc5d92858b 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -250,7 +250,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
set_bit(t, input_dev->keybit);
- input_register_device(guillemot->dev);
+ err = input_register_device(guillemot->dev);
+ if (err)
+ goto fail2;
return 0;
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 24c684bc633..3393a37fec3 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -325,8 +325,8 @@ int iforce_init_device(struct iforce *iforce)
if (i == 20) { /* 5 seconds */
printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
- input_free_device(input_dev);
- return -ENODEV;
+ error = -ENODEV;
+ goto fail;
}
/*
@@ -439,10 +439,8 @@ int iforce_init_device(struct iforce *iforce)
set_bit(iforce->type->ff[i], input_dev->ffbit);
error = input_ff_create(input_dev, ff_effects);
- if (error) {
- input_free_device(input_dev);
- return error;
- }
+ if (error)
+ goto fail;
ff = input_dev->ff;
ff->upload = iforce_upload_effect;
@@ -455,22 +453,35 @@ int iforce_init_device(struct iforce *iforce)
* Register input device.
*/
- input_register_device(iforce->dev);
+ error = input_register_device(iforce->dev);
+ if (error)
+ goto fail;
printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
return 0;
+
+ fail: input_free_device(input_dev);
+ return error;
}
static int __init iforce_init(void)
{
+ int err = 0;
+
#ifdef CONFIG_JOYSTICK_IFORCE_USB
- usb_register(&iforce_usb_driver);
+ err = usb_register(&iforce_usb_driver);
+ if (err)
+ return err;
#endif
#ifdef CONFIG_JOYSTICK_IFORCE_232
- serio_register_driver(&iforce_serio_drv);
+ err = serio_register_driver(&iforce_serio_drv);
+#ifdef CONFIG_JOYSTICK_IFORCE_USB
+ if (err)
+ usb_deregister(&iforce_usb_driver);
#endif
- return 0;
+#endif
+ return err;
}
static void __exit iforce_exit(void)
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index ca08f45c204..ec4be535f48 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -141,21 +141,19 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, iforce);
err = serio_open(serio, drv);
- if (err) {
- serio_set_drvdata(serio, NULL);
- kfree(iforce);
- return err;
- }
+ if (err)
+ goto fail1;
err = iforce_init_device(iforce);
- if (err) {
- serio_close(serio);
- serio_set_drvdata(serio, NULL);
- kfree(iforce);
- return -ENODEV;
- }
+ if (err)
+ goto fail2;
return 0;
+
+ fail2: serio_close(serio);
+ fail1: serio_set_drvdata(serio, NULL);
+ kfree(iforce);
+ return err;
}
static void iforce_serio_disconnect(struct serio *serio)
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index bbfeb9c59b8..fec8b3d0967 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -283,7 +283,9 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
set_bit(t, input_dev->keybit);
- input_register_device(interact->dev);
+ err = input_register_device(interact->dev);
+ if (err)
+ goto fail2;
return 0;
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index e3d19444ba2..4112789f119 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -157,7 +157,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
input_dev = input_allocate_device();
if (!magellan || !input_dev)
- goto fail;
+ goto fail1;
magellan->dev = input_dev;
snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys);
@@ -183,13 +183,17 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(magellan->dev);
+ if (err)
+ goto fail3;
- input_register_device(magellan->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(magellan);
return err;
}
@@ -227,8 +231,7 @@ static struct serio_driver magellan_drv = {
static int __init magellan_init(void)
{
- serio_register_driver(&magellan_drv);
- return 0;
+ return serio_register_driver(&magellan_drv);
}
static void __exit magellan_exit(void)
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 2a9808cf826..08bf113e62e 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -215,7 +215,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
input_dev = input_allocate_device();
if (!spaceball || !input_dev)
- goto fail;
+ goto fail1;
spaceball->dev = input_dev;
snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys);
@@ -252,13 +252,17 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(spaceball->dev);
+ if (err)
+ goto fail3;
- input_register_device(spaceball->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(spaceball);
return err;
}
@@ -296,8 +300,7 @@ static struct serio_driver spaceball_drv = {
static int __init spaceball_init(void)
{
- serio_register_driver(&spaceball_drv);
- return 0;
+ return serio_register_driver(&spaceball_drv);
}
static void __exit spaceball_exit(void)
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index c4db0247c5f..c9c79211af7 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -172,7 +172,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
input_dev = input_allocate_device();
if (!spaceorb || !input_dev)
- goto fail;
+ goto fail1;
spaceorb->dev = input_dev;
snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys);
@@ -198,13 +198,17 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(spaceorb->dev);
+ if (err)
+ goto fail3;
- input_register_device(spaceorb->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(spaceorb);
return err;
}
@@ -242,8 +246,7 @@ static struct serio_driver spaceorb_drv = {
static int __init spaceorb_init(void)
{
- serio_register_driver(&spaceorb_drv);
- return 0;
+ return serio_register_driver(&spaceorb_drv);
}
static void __exit spaceorb_exit(void)
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 1ffb0322331..ecb0916215f 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -143,7 +143,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
input_dev = input_allocate_device();
if (!stinger || !input_dev)
- goto fail;
+ goto fail1;
stinger->dev = input_dev;
snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys);
@@ -168,13 +168,17 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(stinger->dev);
+ if (err)
+ goto fail3;
- input_register_device(stinger->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(stinger);
return err;
}
@@ -212,8 +216,7 @@ static struct serio_driver stinger_drv = {
static int __init stinger_init(void)
{
- serio_register_driver(&stinger_drv);
- return 0;
+ return serio_register_driver(&stinger_drv);
}
static void __exit stinger_exit(void)
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 49085df2d63..9cf17d6ced8 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -194,7 +194,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
input_dev = input_allocate_device();
if (!twidjoy || !input_dev)
- goto fail;
+ goto fail1;
twidjoy->dev = input_dev;
snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys);
@@ -221,13 +221,17 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(twidjoy->dev);
+ if (err)
+ goto fail3;
- input_register_device(twidjoy->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(twidjoy);
return err;
}
@@ -265,8 +269,7 @@ static struct serio_driver twidjoy_drv = {
static int __init twidjoy_init(void)
{
- serio_register_driver(&twidjoy_drv);
- return 0;
+ return serio_register_driver(&twidjoy_drv);
}
static void __exit twidjoy_exit(void)
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 35edea1ab95..29d339acf43 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -149,7 +149,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
input_dev = input_allocate_device();
if (!warrior || !input_dev)
- goto fail;
+ goto fail1;
warrior->dev = input_dev;
snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys);
@@ -176,13 +176,17 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(warrior->dev);
+ if (err)
+ goto fail3;
- input_register_device(warrior->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(warrior);
return err;
}
@@ -220,8 +224,7 @@ static struct serio_driver warrior_drv = {
static int __init warrior_init(void)
{
- serio_register_driver(&warrior_drv);
- return 0;
+ return serio_register_driver(&warrior_drv);
}
static void __exit warrior_exit(void)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 81a333f7301..049f2f544e7 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -203,4 +203,15 @@ config KEYBOARD_OMAP
To compile this driver as a module, choose M here: the
module will be called omap-keypad.
+config KEYBOARD_AAED2000
+ tristate "AAED-2000 keyboard"
+ depends on MACH_AAED2000
+ default y
+ help
+ Say Y here to enable the keyboard on the Agilent AAED-2000
+ development board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aaed2000_kbd.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 4c79e7bc9d0..56879790734 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -17,4 +17,5 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
+obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
new file mode 100644
index 00000000000..65fcb6af63a
--- /dev/null
+++ b/drivers/input/keyboard/aaed2000_kbd.c
@@ -0,0 +1,203 @@
+/*
+ * Keyboard driver for the AAED-2000 dev board
+ *
+ * Copyright (c) 2006 Nicolas Bellido Y Ortega
+ *
+ * Based on corgikbd.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/aaed2000.h>
+
+#define KB_ROWS 12
+#define KB_COLS 8
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(r,c) (((c) * KB_ROWS) + (r))
+#define NR_SCANCODES (KB_COLS * KB_ROWS)
+
+#define SCAN_INTERVAL (50) /* ms */
+#define KB_ACTIVATE_DELAY (20) /* us */
+
+static unsigned char aaedkbd_keycode[NR_SCANCODES] = {
+ KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0,
+ KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0,
+ KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0,
+ KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0,
+ KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK,
+ KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB,
+ KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE,
+ 0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL
+};
+
+struct aaedkbd {
+ unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)];
+ struct input_dev *input;
+ struct work_struct workq;
+ int kbdscan_state[KB_COLS];
+ int kbdscan_count[KB_COLS];
+};
+
+#define KBDSCAN_STABLE_COUNT 2
+
+static void aaedkbd_report_col(struct aaedkbd *aaedkbd,
+ unsigned int col, unsigned int rowd)
+{
+ unsigned int scancode, pressed;
+ unsigned int row;
+
+ for (row = 0; row < KB_ROWS; row++) {
+ scancode = SCANCODE(row, col);
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(aaedkbd->input, aaedkbd->keycode[scancode], pressed);
+ }
+}
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void aaedkbd_work(void *data)
+{
+ struct aaedkbd *aaedkbd = data;
+ unsigned int col, rowd;
+
+ col = 0;
+ do {
+ AAEC_GPIO_KSCAN = col + 8;
+ udelay(KB_ACTIVATE_DELAY);
+ rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN;
+
+ if (rowd != aaedkbd->kbdscan_state[col]) {
+ aaedkbd->kbdscan_count[col] = 0;
+ aaedkbd->kbdscan_state[col] = rowd;
+ } else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) {
+ aaedkbd_report_col(aaedkbd, col, rowd);
+ col++;
+ }
+ } while (col < KB_COLS);
+
+ AAEC_GPIO_KSCAN = 0x07;
+ input_sync(aaedkbd->input);
+
+ schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
+}
+
+static int aaedkbd_open(struct input_dev *indev)
+{
+ struct aaedkbd *aaedkbd = indev->private;
+
+ schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
+
+ return 0;
+}
+
+static void aaedkbd_close(struct input_dev *indev)
+{
+ struct aaedkbd *aaedkbd = indev->private;
+
+ cancel_delayed_work(&aaedkbd->workq);
+ flush_scheduled_work();
+}
+
+static int __devinit aaedkbd_probe(struct platform_device *pdev)
+{
+ struct aaedkbd *aaedkbd;
+ struct input_dev *input_dev;
+ int i;
+ int error;
+
+ aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!aaedkbd || !input_dev) {
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ platform_set_drvdata(pdev, aaedkbd);
+
+ aaedkbd->input = input_dev;
+
+ /* Init keyboard rescan workqueue */
+ INIT_WORK(&aaedkbd->workq, aaedkbd_work, aaedkbd);
+
+ memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode));
+
+ input_dev->name = "AAED-2000 Keyboard";
+ input_dev->phys = "aaedkbd/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &pdev->dev;
+ input_dev->private = aaedkbd;
+
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input_dev->keycode = aaedkbd->keycode;
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode);
+
+ for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++)
+ set_bit(aaedkbd->keycode[i], input_dev->keybit);
+ clear_bit(0, input_dev->keybit);
+
+ input_dev->open = aaedkbd_open;
+ input_dev->close = aaedkbd_close;
+
+ error = input_register_device(aaedkbd->input);
+ if (error)
+ goto fail;
+
+ return 0;
+
+ fail: kfree(aaedkbd);
+ input_free_device(input_dev);
+ return error;
+}
+
+static int __devexit aaedkbd_remove(struct platform_device *pdev)
+{
+ struct aaedkbd *aaedkbd = platform_get_drvdata(pdev);
+
+ input_unregister_device(aaedkbd->input);
+ kfree(aaedkbd);
+
+ return 0;
+}
+
+static struct platform_driver aaedkbd_driver = {
+ .probe = aaedkbd_probe,
+ .remove = __devexit_p(aaedkbd_remove),
+ .driver = {
+ .name = "aaed2000-keyboard",
+ },
+};
+
+static int __init aaedkbd_init(void)
+{
+ return platform_driver_register(&aaedkbd_driver);
+}
+
+static void __exit aaedkbd_exit(void)
+{
+ platform_driver_unregister(&aaedkbd_driver);
+}
+
+module_init(aaedkbd_init);
+module_exit(aaedkbd_exit);
+
+MODULE_AUTHOR("Nicolas Bellido Y Ortega");
+MODULE_DESCRIPTION("AAED-2000 Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 8abdbd0ee8f..c67e84ec2d6 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -187,10 +187,10 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy)
static int __init amikbd_init(void)
{
- int i, j;
+ int i, j, err;
if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
- return -EIO;
+ return -ENODEV;
if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
return -EBUSY;
@@ -198,8 +198,8 @@ static int __init amikbd_init(void)
amikbd_dev = input_allocate_device();
if (!amikbd_dev) {
printk(KERN_ERR "amikbd: not enough memory for input device\n");
- release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto fail1;
}
amikbd_dev->name = "Amiga Keyboard";
@@ -231,10 +231,22 @@ static int __init amikbd_init(void)
memcpy(key_maps[i], temp_map, sizeof(temp_map));
}
ciaa.cra &= ~0x41; /* serial data in, turn off TA */
- request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
+ if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd",
+ amikbd_interrupt)) {
+ err = -EBUSY;
+ goto fail2;
+ }
+
+ err = input_register_device(amikbd_dev);
+ if (err)
+ goto fail3;
- input_register_device(amikbd_dev);
return 0;
+
+ fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
+ fail2: input_free_device(amikbd_dev);
+ fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
+ return err;
}
static void __exit amikbd_exit(void)
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 8451b29a3db..c621a9177a5 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -939,7 +939,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
dev = input_allocate_device();
if (!atkbd || !dev)
- goto fail;
+ goto fail1;
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
@@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
if (atkbd->write) {
if (atkbd_probe(atkbd)) {
- serio_close(serio);
err = -ENODEV;
- goto fail;
+ goto fail3;
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
+ err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
+ if (err)
+ goto fail3;
atkbd_enable(atkbd);
- input_register_device(atkbd->dev);
+ err = input_register_device(atkbd->dev);
+ if (err)
+ goto fail4;
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(dev);
+ fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(dev);
kfree(atkbd);
return err;
}
@@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
{
- struct input_dev *new_dev;
+ struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
+ int err;
+ unsigned char old_extra, old_set;
if (!atkbd->write)
return -EIO;
@@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
if (atkbd->extra != value) {
/*
* Since device's properties will change we need to
- * unregister old device. But allocate new one first
- * to make sure we have it.
+ * unregister old device. But allocate and register
+ * new one first to make sure we have it.
*/
- if (!(new_dev = input_allocate_device()))
+ old_dev = atkbd->dev;
+ old_extra = atkbd->extra;
+ old_set = atkbd->set;
+
+ new_dev = input_allocate_device();
+ if (!new_dev)
return -ENOMEM;
- input_unregister_device(atkbd->dev);
+
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
atkbd_activate(atkbd);
+ atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(atkbd->dev);
+
+ err = input_register_device(atkbd->dev);
+ if (err) {
+ input_free_device(new_dev);
+
+ atkbd->dev = old_dev;
+ atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
+ atkbd_set_keycode_table(atkbd);
+ atkbd_set_device_attrs(atkbd);
+
+ return err;
+ }
+ input_unregister_device(old_dev);
+
}
return count;
}
@@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
{
- struct input_dev *new_dev;
+ struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
+ int err;
+ unsigned char old_scroll;
value = simple_strtoul(buf, &rest, 10);
if (*rest || value > 1)
return -EINVAL;
if (atkbd->scroll != value) {
- if (!(new_dev = input_allocate_device()))
+ old_dev = atkbd->dev;
+ old_scroll = atkbd->scroll;
+
+ new_dev = input_allocate_device();
+ if (!new_dev)
return -ENOMEM;
- input_unregister_device(atkbd->dev);
+
atkbd->dev = new_dev;
atkbd->scroll = value;
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(atkbd->dev);
+
+ err = input_register_device(atkbd->dev);
+ if (err) {
+ input_free_device(new_dev);
+
+ atkbd->scroll = old_scroll;
+ atkbd->dev = old_dev;
+ atkbd_set_keycode_table(atkbd);
+ atkbd_set_device_attrs(atkbd);
+
+ return err;
+ }
+ input_unregister_device(old_dev);
}
return count;
}
@@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{
- struct input_dev *new_dev;
+ struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
+ int err;
+ unsigned char old_set, old_extra;
if (!atkbd->write)
return -EIO;
@@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
return -EINVAL;
if (atkbd->set != value) {
- if (!(new_dev = input_allocate_device()))
+ old_dev = atkbd->dev;
+ old_extra = atkbd->extra;
+ old_set = atkbd->set;
+
+ new_dev = input_allocate_device();
+ if (!new_dev)
return -ENOMEM;
- input_unregister_device(atkbd->dev);
+
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
- input_register_device(atkbd->dev);
+
+ err = input_register_device(atkbd->dev);
+ if (err) {
+ input_free_device(new_dev);
+
+ atkbd->dev = old_dev;
+ atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
+ atkbd_set_keycode_table(atkbd);
+ atkbd_set_device_attrs(atkbd);
+
+ return err;
+ }
+ input_unregister_device(old_dev);
}
return count;
}
@@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
{
- struct input_dev *new_dev;
+ struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
+ int err;
+ unsigned char old_softrepeat, old_softraw;
if (!atkbd->write)
return -EIO;
@@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
return -EINVAL;
if (atkbd->softrepeat != value) {
- if (!(new_dev = input_allocate_device()))
+ old_dev = atkbd->dev;
+ old_softrepeat = atkbd->softrepeat;
+ old_softraw = atkbd->softraw;
+
+ new_dev = input_allocate_device();
+ if (!new_dev)
return -ENOMEM;
- input_unregister_device(atkbd->dev);
+
atkbd->dev = new_dev;
atkbd->softrepeat = value;
if (atkbd->softrepeat)
atkbd->softraw = 1;
atkbd_set_device_attrs(atkbd);
- input_register_device(atkbd->dev);
+
+ err = input_register_device(atkbd->dev);
+ if (err) {
+ input_free_device(new_dev);
+
+ atkbd->dev = old_dev;
+ atkbd->softrepeat = old_softrepeat;
+ atkbd->softraw = old_softraw;
+ atkbd_set_device_attrs(atkbd);
+
+ return err;
+ }
+ input_unregister_device(old_dev);
}
return count;
}
@@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
{
- struct input_dev *new_dev;
+ struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
+ int err;
+ unsigned char old_softraw;
value = simple_strtoul(buf, &rest, 10);
if (*rest || value > 1)
return -EINVAL;
if (atkbd->softraw != value) {
- if (!(new_dev = input_allocate_device()))
+ old_dev = atkbd->dev;
+ old_softraw = atkbd->softraw;
+
+ new_dev = input_allocate_device();
+ if (!new_dev)
return -ENOMEM;
- input_unregister_device(atkbd->dev);
+
atkbd->dev = new_dev;
atkbd->softraw = value;
atkbd_set_device_attrs(atkbd);
- input_register_device(atkbd->dev);
+
+ err = input_register_device(atkbd->dev);
+ if (err) {
+ input_free_device(new_dev);
+
+ atkbd->dev = old_dev;
+ atkbd->softraw = old_softraw;
+ atkbd_set_device_attrs(atkbd);
+
+ return err;
+ }
+ input_unregister_device(old_dev);
}
return count;
}
@@ -1290,8 +1389,7 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
static int __init atkbd_init(void)
{
- serio_register_driver(&atkbd_drv);
- return 0;
+ return serio_register_driver(&atkbd_drv);
}
static void __exit atkbd_exit(void)
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index befdd6006b5..1016c94e65d 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -291,15 +291,12 @@ static int __init corgikbd_probe(struct platform_device *pdev)
{
struct corgikbd *corgikbd;
struct input_dev *input_dev;
- int i;
+ int i, err = -ENOMEM;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
input_dev = input_allocate_device();
- if (!corgikbd || !input_dev) {
- kfree(corgikbd);
- input_free_device(input_dev);
- return -ENOMEM;
- }
+ if (!corgikbd || !input_dev)
+ goto fail;
platform_set_drvdata(pdev, corgikbd);
@@ -341,7 +338,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
- input_register_device(corgikbd->input);
+ err = input_register_device(corgikbd->input);
+ if (err)
+ goto fail;
mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
@@ -362,6 +361,10 @@ static int __init corgikbd_probe(struct platform_device *pdev)
pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(corgikbd);
+ return err;
}
static int corgikbd_remove(struct platform_device *pdev)
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index e774dd31e99..7cc9728b04d 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -381,8 +381,7 @@ struct serio_driver hil_kbd_serio_drv = {
static int __init hil_kbd_init(void)
{
- serio_register_driver(&hil_kbd_serio_drv);
- return 0;
+ return serio_register_driver(&hil_kbd_serio_drv);
}
static void __exit hil_kbd_exit(void)
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index 54bc569db4b..35461eab2fa 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -23,7 +23,12 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/hil.h>
+#include <linux/io.h>
#include <linux/spinlock.h>
+#include <asm/irq.h>
+#ifdef CONFIG_HP300
+#include <asm/hwtest.h>
+#endif
MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index b7f049b45b6..3d4d0a0ede2 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -646,7 +646,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
input_dev = input_allocate_device ();
if (!lk || !input_dev) {
err = -ENOMEM;
- goto fail;
+ goto fail1;
}
lk->serio = serio;
@@ -691,15 +691,19 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
err = serio_open (serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device (lk->dev);
+ if (err)
+ goto fail3;
- input_register_device (lk->dev);
lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
return 0;
- fail: serio_set_drvdata (serio, NULL);
- input_free_device (input_dev);
+ fail3: serio_close (serio);
+ fail2: serio_set_drvdata (serio, NULL);
+ fail1: input_free_device (input_dev);
kfree (lk);
return err;
}
@@ -749,8 +753,7 @@ static struct serio_driver lkkbd_drv = {
static int __init
lkkbd_init (void)
{
- serio_register_driver(&lkkbd_drv);
- return 0;
+ return serio_register_driver(&lkkbd_drv);
}
static void __exit
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 5788dbc317b..2ade5186cc4 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -193,22 +193,22 @@ static int locomokbd_probe(struct locomo_dev *dev)
{
struct locomokbd *locomokbd;
struct input_dev *input_dev;
- int i, ret;
+ int i, err;
locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!locomokbd || !input_dev) {
- ret = -ENOMEM;
- goto free;
+ err = -ENOMEM;
+ goto err_free_mem;
}
/* try and claim memory region */
if (!request_mem_region((unsigned long) dev->mapbase,
dev->length,
LOCOMO_DRIVER_NAME(dev))) {
- ret = -EBUSY;
+ err = -EBUSY;
printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
- goto free;
+ goto err_free_mem;
}
locomokbd->ldev = dev;
@@ -244,24 +244,28 @@ static int locomokbd_probe(struct locomo_dev *dev)
clear_bit(0, input_dev->keybit);
/* attempt to get the interrupt */
- ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
- if (ret) {
+ err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
+ if (err) {
printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
- goto out;
+ goto err_release_region;
}
- input_register_device(locomokbd->input);
+ err = input_register_device(locomokbd->input);
+ if (err)
+ goto err_free_irq;
return 0;
-out:
+ err_free_irq:
+ free_irq(dev->irq[0], locomokbd);
+ err_release_region:
release_mem_region((unsigned long) dev->mapbase, dev->length);
locomo_set_drvdata(dev, NULL);
-free:
+ err_free_mem:
input_free_device(input_dev);
kfree(locomokbd);
- return ret;
+ return err;
}
static int locomokbd_remove(struct locomo_dev *dev)
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
deleted file mode 100644
index cc6aaf9e85b..00000000000
--- a/drivers/input/keyboard/maple_keyb.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $
- * SEGA Dreamcast keyboard driver
- * Based on drivers/usb/usbkbd.c
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/maple.h>
-
-MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
-MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
-MODULE_LICENSE("GPL");
-
-static unsigned char dc_kbd_keycode[256] = {
- 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
- 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
- 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
- 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
- 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
- 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
- 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
- 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
- 150,158,159,128,136,177,178,176,142,152,173,140
-};
-
-
-struct dc_kbd {
- struct input_dev *dev;
- unsigned char new[8];
- unsigned char old[8];
-};
-
-
-static void dc_scan_kbd(struct dc_kbd *kbd)
-{
- int i;
- struct input_dev *dev = kbd->dev;
-
- for (i = 0; i < 8; i++)
- input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
- for (i = 2; i < 8; i++) {
-
- if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) {
- if (dc_kbd_keycode[kbd->old[i]])
- input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0);
- else
- printk("Unknown key (scancode %#x) released.",
- kbd->old[i]);
- }
-
- if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) {
- if(dc_kbd_keycode[kbd->new[i]])
- input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1);
- else
- printk("Unknown key (scancode %#x) pressed.",
- kbd->new[i]);
- }
- }
-
- input_sync(dev);
-
- memcpy(kbd->old, kbd->new, 8);
-}
-
-
-static void dc_kbd_callback(struct mapleq *mq)
-{
- struct maple_device *mapledev = mq->dev;
- struct dc_kbd *kbd = mapledev->private_data;
- unsigned long *buf = mq->recvbuf;
-
- if (buf[1] == mapledev->function) {
- memcpy(kbd->new, buf + 2, 8);
- dc_scan_kbd(kbd);
- }
-}
-
-static int dc_kbd_connect(struct maple_device *dev)
-{
- struct dc_kbd *kbd;
- struct input_dev *input_dev;
- unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
- int i;
-
- dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!kbd || !input_dev) {
- kfree(kbd);
- input_free_device(input_dev);
- return -ENOMEM;
- }
-
- kbd->dev = input_dev;
-
- input_dev->name = dev->product_name;
- input_dev->id.bustype = BUS_MAPLE;
- input_dev->private = kbd;
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- for (i = 0; i < 255; i++)
- set_bit(dc_kbd_keycode[i], input_dev->keybit);
- clear_bit(0, input_dev->keybit);
-
- input_register_device(kbd->dev);
-
- maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
- return 0;
-}
-
-
-static void dc_kbd_disconnect(struct maple_device *dev)
-{
- struct dc_kbd *kbd = dev->private_data;
-
- input_unregister_device(kbd->dev);
- kfree(kbd);
-}
-
-
-static struct maple_driver dc_kbd_driver = {
- .function = MAPLE_FUNC_KEYBOARD,
- .name = "Dreamcast keyboard",
- .connect = dc_kbd_connect,
- .disconnect = dc_kbd_disconnect,
-};
-
-
-static int __init dc_kbd_init(void)
-{
- maple_register_driver(&dc_kbd_driver);
- return 0;
-}
-
-
-static void __exit dc_kbd_exit(void)
-{
- maple_unregister_driver(&dc_kbd_driver);
-}
-
-
-module_init(dc_kbd_init);
-module_exit(dc_kbd_exit);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 9282e4e082b..aa29b50765c 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -91,7 +91,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!nkbd || !input_dev)
- goto fail;
+ goto fail1;
nkbd->serio = serio;
nkbd->dev = input_dev;
@@ -119,13 +119,17 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(nkbd->dev);
+ if (err)
+ goto fail3;
- input_register_device(nkbd->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(nkbd);
return err;
}
@@ -165,8 +169,7 @@ static struct serio_driver nkbd_drv = {
static int __init nkbd_init(void)
{
- serio_register_driver(&nkbd_drv);
- return 0;
+ return serio_register_driver(&nkbd_drv);
}
static void __exit nkbd_exit(void)
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 28b2748e82d..8a2166c77ff 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -346,17 +346,12 @@ static int __init spitzkbd_probe(struct platform_device *dev)
{
struct spitzkbd *spitzkbd;
struct input_dev *input_dev;
- int i;
+ int i, err = -ENOMEM;
spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
- if (!spitzkbd)
- return -ENOMEM;
-
input_dev = input_allocate_device();
- if (!input_dev) {
- kfree(spitzkbd);
- return -ENOMEM;
- }
+ if (!spitzkbd || !input_dev)
+ goto fail;
platform_set_drvdata(dev, spitzkbd);
strcpy(spitzkbd->phys, "spitzkbd/input0");
@@ -400,7 +395,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
- input_register_device(input_dev);
+ err = input_register_device(input_dev);
+ if (err)
+ goto fail;
mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
@@ -434,13 +431,15 @@ static int __init spitzkbd_probe(struct platform_device *dev)
request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"Spitzkbd SWB", spitzkbd);
- request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
+ request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"Spitzkbd HP", spitzkbd);
- printk(KERN_INFO "input: Spitz Keyboard Registered\n");
-
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(spitzkbd);
+ return err;
}
static int spitzkbd_remove(struct platform_device *dev)
@@ -474,6 +473,7 @@ static struct platform_driver spitzkbd_driver = {
.resume = spitzkbd_resume,
.driver = {
.name = "spitz-keyboard",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c
index e60937d17b1..f7b5c5b8145 100644
--- a/drivers/input/keyboard/stowaway.c
+++ b/drivers/input/keyboard/stowaway.c
@@ -173,8 +173,7 @@ static struct serio_driver skbd_drv = {
static int __init skbd_init(void)
{
- serio_register_driver(&skbd_drv);
- return 0;
+ return serio_register_driver(&skbd_drv);
}
static void __exit skbd_exit(void)
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 6cd887c5eb0..cc023836641 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -225,7 +225,7 @@ static void sunkbd_reinit(struct work_struct *work)
static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
{
serio_pause_rx(sunkbd->serio);
- sunkbd->enabled = 1;
+ sunkbd->enabled = enable;
serio_continue_rx(sunkbd->serio);
}
@@ -243,7 +243,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!sunkbd || !input_dev)
- goto fail;
+ goto fail1;
sunkbd->serio = serio;
sunkbd->dev = input_dev;
@@ -255,11 +255,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
if (sunkbd_initialize(sunkbd) < 0) {
- serio_close(serio);
- goto fail;
+ err = -ENODEV;
+ goto fail3;
}
snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type);
@@ -287,11 +287,17 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
clear_bit(0, input_dev->keybit);
sunkbd_enable(sunkbd, 1);
- input_register_device(sunkbd->dev);
+
+ err = input_register_device(sunkbd->dev);
+ if (err)
+ goto fail4;
+
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail4: sunkbd_enable(sunkbd, 0);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(sunkbd);
return err;
}
@@ -346,8 +352,7 @@ static struct serio_driver sunkbd_drv = {
static int __init sunkbd_init(void)
{
- serio_register_driver(&sunkbd_drv);
- return 0;
+ return serio_register_driver(&sunkbd_drv);
}
static void __exit sunkbd_exit(void)
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 8c11dc93545..a8209343213 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -95,7 +95,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!xtkbd || !input_dev)
- goto fail;
+ goto fail1;
xtkbd->serio = serio;
xtkbd->dev = input_dev;
@@ -124,13 +124,17 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(xtkbd->dev);
+ if (err)
+ goto fail3;
- input_register_device(xtkbd->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(xtkbd);
return err;
}
@@ -170,8 +174,7 @@ static struct serio_driver xtkbd_drv = {
static int __init xtkbd_init(void)
{
- serio_register_driver(&xtkbd_drv);
- return 0;
+ return serio_register_driver(&xtkbd_drv);
}
static void __exit xtkbd_exit(void)
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index 599a7b2dc51..239a0e16d91 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -95,10 +95,13 @@ static void amimouse_close(struct input_dev *dev)
static int __init amimouse_init(void)
{
+ int err;
+
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
- if (!(amimouse_dev = input_allocate_device()))
+ amimouse_dev = input_allocate_device();
+ if (!amimouse_dev)
return -ENOMEM;
amimouse_dev->name = "Amiga mouse";
@@ -114,7 +117,11 @@ static int __init amimouse_init(void)
amimouse_dev->open = amimouse_open;
amimouse_dev->close = amimouse_close;
- input_register_device(amimouse_dev);
+ err = input_register_device(amimouse_dev);
+ if (err) {
+ input_free_device(amimouse_dev);
+ return err;
+ }
return 0;
}
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index 4f2b503c1ac..bfb174fe323 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -417,8 +417,7 @@ static struct serio_driver hil_ptr_serio_driver = {
static int __init hil_ptr_init(void)
{
- serio_register_driver(&hil_ptr_serio_driver);
- return 0;
+ return serio_register_driver(&hil_ptr_serio_driver);
}
static void __exit hil_ptr_exit(void)
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index e1252fa9a10..13dd96785e3 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -135,6 +135,7 @@ static void inport_close(struct input_dev *dev)
static int __init inport_init(void)
{
unsigned char a, b, c;
+ int err;
if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@@ -145,15 +146,16 @@ static int __init inport_init(void)
b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT);
if (a == b || a != c) {
- release_region(INPORT_BASE, INPORT_EXTENT);
printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
- return -ENODEV;
+ err = -ENODEV;
+ goto err_release_region;
}
- if (!(inport_dev = input_allocate_device())) {
+ inport_dev = input_allocate_device();
+ if (!inport_dev) {
printk(KERN_ERR "inport.c: Not enough memory for input device\n");
- release_region(INPORT_BASE, INPORT_EXTENT);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_release_region;
}
inport_dev->name = INPORT_NAME;
@@ -174,9 +176,18 @@ static int __init inport_init(void)
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
- input_register_device(inport_dev);
+ err = input_register_device(inport_dev);
+ if (err)
+ goto err_free_dev;
return 0;
+
+ err_free_dev:
+ input_free_device(inport_dev);
+ err_release_region:
+ release_region(INPORT_BASE, INPORT_EXTENT);
+
+ return err;
}
static void __exit inport_exit(void)
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index c57e8853b94..29542f0631c 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -21,47 +21,51 @@
#include "lifebook.h"
static struct dmi_system_id lifebook_dmi_table[] = {
- {
- .ident = "LifeBook B",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
- },
- },
- {
- .ident = "Lifebook B",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
- },
- },
- {
- .ident = "Lifebook B213x/B2150",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
- },
- },
- {
- .ident = "Zephyr",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
- },
- },
- {
- .ident = "CF-18",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
- },
- },
- {
- .ident = "Lifebook B142",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
- },
-
- },
- { }
+ {
+ .ident = "FLORA-ie 55mi",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"),
+ },
+ },
+ {
+ .ident = "LifeBook B",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
+ },
+ },
+ {
+ .ident = "Lifebook B",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
+ },
+ },
+ {
+ .ident = "Lifebook B213x/B2150",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
+ },
+ },
+ {
+ .ident = "Zephyr",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
+ },
+ },
+ {
+ .ident = "CF-18",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
+ },
+ },
+ {
+ .ident = "Lifebook B142",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
+ },
+ },
+ { }
};
-
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
{
unsigned char *packet = psmouse->packet;
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 8e9c2f3d69a..db205995bff 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -124,6 +124,8 @@ static void logibm_close(struct input_dev *dev)
static int __init logibm_init(void)
{
+ int err;
+
if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
return -EBUSY;
@@ -134,18 +136,19 @@ static int __init logibm_init(void)
udelay(100);
if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
- release_region(LOGIBM_BASE, LOGIBM_EXTENT);
printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
- return -ENODEV;
+ err = -ENODEV;
+ goto err_release_region;
}
outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
- if (!(logibm_dev = input_allocate_device())) {
+ logibm_dev = input_allocate_device();
+ if (!logibm_dev) {
printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
- release_region(LOGIBM_BASE, LOGIBM_EXTENT);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_release_region;
}
logibm_dev->name = "Logitech bus mouse";
@@ -162,9 +165,18 @@ static int __init logibm_init(void)
logibm_dev->open = logibm_open;
logibm_dev->close = logibm_close;
- input_register_device(logibm_dev);
+ err = input_register_device(logibm_dev);
+ if (err)
+ goto err_free_dev;
return 0;
+
+ err_free_dev:
+ input_free_device(logibm_dev);
+ err_release_region:
+ release_region(LOGIBM_BASE, LOGIBM_EXTENT);
+
+ return err;
}
static void __exit logibm_exit(void)
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 8a4f862709e..d3ddea26b8c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -328,6 +328,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
unsigned char model, buttons;
const struct ps2pp_info *model_info;
int use_ps2pp = 0;
+ int error;
param[0] = 0;
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
@@ -393,8 +394,14 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
psmouse->set_resolution = ps2pp_set_resolution;
psmouse->disconnect = ps2pp_disconnect;
- device_create_file(&psmouse->ps2dev.serio->dev,
- &psmouse_attr_smartscroll.dattr);
+ error = device_create_file(&psmouse->ps2dev.serio->dev,
+ &psmouse_attr_smartscroll.dattr);
+ if (error) {
+ printk(KERN_ERR
+ "logips2pp.c: failed to create smartscroll "
+ "sysfs attribute, error: %d\n", error);
+ return -1;
+ }
}
}
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 8c075aa7223..f155c1fea04 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -108,6 +108,7 @@ static int pc110pad_open(struct input_dev *dev)
static int __init pc110pad_init(void)
{
struct pci_dev *dev;
+ int err;
dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
@@ -124,16 +125,16 @@ static int __init pc110pad_init(void)
outb(PC110PAD_OFF, pc110pad_io + 2);
if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
- release_region(pc110pad_io, 4);
printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
- return -EBUSY;
+ err = -EBUSY;
+ goto err_release_region;
}
- if (!(pc110pad_dev = input_allocate_device())) {
- free_irq(pc110pad_irq, NULL);
- release_region(pc110pad_io, 4);
+ pc110pad_dev = input_allocate_device();
+ if (!pc110pad_dev) {
printk(KERN_ERR "pc110pad: Not enough memory.\n");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_free_irq;
}
pc110pad_dev->name = "IBM PC110 TouchPad";
@@ -153,9 +154,20 @@ static int __init pc110pad_init(void)
pc110pad_dev->open = pc110pad_open;
pc110pad_dev->close = pc110pad_close;
- input_register_device(pc110pad_dev);
+ err = input_register_device(pc110pad_dev);
+ if (err)
+ goto err_free_dev;
return 0;
+
+ err_free_dev:
+ input_free_device(pc110pad_dev);
+ err_free_irq:
+ free_irq(pc110pad_irq, NULL);
+ err_release_region:
+ release_region(pc110pad_io, 4);
+
+ return err;
}
static void __exit pc110pad_exit(void)
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 52bb2226ce2..a0e4a033e2d 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -1103,7 +1103,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct psmouse *psmouse, *parent = NULL;
struct input_dev *input_dev;
- int retval = -ENOMEM;
+ int retval = 0, error = -ENOMEM;
mutex_lock(&psmouse_mutex);
@@ -1119,7 +1119,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
input_dev = input_allocate_device();
if (!psmouse || !input_dev)
- goto out;
+ goto err_free;
ps2_init(&psmouse->ps2dev, serio);
INIT_WORK(&psmouse->resync_work, psmouse_resync);
@@ -1130,14 +1130,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
serio_set_drvdata(serio, psmouse);
- retval = serio_open(serio, drv);
- if (retval)
- goto out;
+ error = serio_open(serio, drv);
+ if (error)
+ goto err_clear_drvdata;
if (psmouse_probe(psmouse) < 0) {
- serio_close(serio);
- retval = -ENODEV;
- goto out;
+ error = -ENODEV;
+ goto err_close_serio;
}
psmouse->rate = psmouse_rate;
@@ -1151,30 +1150,44 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
psmouse_initialize(psmouse);
- input_register_device(psmouse->dev);
+ error = input_register_device(psmouse->dev);
+ if (error)
+ goto err_protocol_disconnect;
if (parent && parent->pt_activate)
parent->pt_activate(parent);
- sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
+ error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
+ if (error)
+ goto err_pt_deactivate;
psmouse_activate(psmouse);
- retval = 0;
-
-out:
- if (retval) {
- serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
- kfree(psmouse);
- }
-
+ out:
/* If this is a pass-through port the parent needs to be re-activated */
if (parent)
psmouse_activate(parent);
mutex_unlock(&psmouse_mutex);
return retval;
+
+ err_pt_deactivate:
+ if (parent && parent->pt_deactivate)
+ parent->pt_deactivate(parent);
+ err_protocol_disconnect:
+ if (psmouse->disconnect)
+ psmouse->disconnect(psmouse);
+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ err_close_serio:
+ serio_close(serio);
+ err_clear_drvdata:
+ serio_set_drvdata(serio, NULL);
+ err_free:
+ input_free_device(input_dev);
+ kfree(psmouse);
+
+ retval = error;
+ goto out;
}
@@ -1337,14 +1350,14 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
{
- unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+ unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
- return sprintf(buf, "%lu\n", *field);
+ return sprintf(buf, "%u\n", *field);
}
static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
{
- unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+ unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
unsigned long value;
char *rest;
@@ -1352,6 +1365,9 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
if (*rest)
return -EINVAL;
+ if ((unsigned int)value != value)
+ return -EINVAL;
+
*field = value;
return count;
@@ -1366,17 +1382,20 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
{
struct serio *serio = psmouse->ps2dev.serio;
struct psmouse *parent = NULL;
- struct input_dev *new_dev;
- const struct psmouse_protocol *proto;
+ struct input_dev *old_dev, *new_dev;
+ const struct psmouse_protocol *proto, *old_proto;
+ int error;
int retry = 0;
- if (!(proto = psmouse_protocol_by_name(buf, count)))
+ proto = psmouse_protocol_by_name(buf, count);
+ if (!proto)
return -EINVAL;
if (psmouse->type == proto->type)
return count;
- if (!(new_dev = input_allocate_device()))
+ new_dev = input_allocate_device();
+ if (!new_dev)
return -ENOMEM;
while (serio->child) {
@@ -1409,11 +1428,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
parent->pt_deactivate(parent);
}
+ old_dev = psmouse->dev;
+ old_proto = psmouse_protocol_by_type(psmouse->type);
+
if (psmouse->disconnect)
psmouse->disconnect(psmouse);
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_unregister_device(psmouse->dev);
psmouse->dev = new_dev;
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -1427,7 +1448,23 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
psmouse_initialize(psmouse);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- input_register_device(psmouse->dev);
+ error = input_register_device(psmouse->dev);
+ if (error) {
+ if (psmouse->disconnect)
+ psmouse->disconnect(psmouse);
+
+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ input_free_device(new_dev);
+ psmouse->dev = old_dev;
+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+ psmouse_switch_protocol(psmouse, old_proto);
+ psmouse_initialize(psmouse);
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
+ return error;
+ }
+
+ input_unregister_device(old_dev);
if (parent && parent->pt_activate)
parent->pt_activate(parent);
@@ -1488,15 +1525,19 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
static int __init psmouse_init(void)
{
+ int err;
+
kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
if (!kpsmoused_wq) {
printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
return -ENOMEM;
}
- serio_register_driver(&psmouse_drv);
+ err = serio_register_driver(&psmouse_drv);
+ if (err)
+ destroy_workqueue(kpsmoused_wq);
- return 0;
+ return err;
}
static void __exit psmouse_exit(void)
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index ea046856961..fbdcfd8eb4e 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -66,7 +66,10 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id)
static int __init rpcmouse_init(void)
{
- if (!(rpcmouse_dev = input_allocate_device()))
+ int err;
+
+ rpcmouse_dev = input_allocate_device();
+ if (!rpcmouse_dev)
return -ENOMEM;
rpcmouse_dev->name = "Acorn RiscPC Mouse";
@@ -85,13 +88,22 @@ static int __init rpcmouse_init(void)
if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) {
printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
- input_free_device(rpcmouse_dev);
- return -EBUSY;
+ err = -EBUSY;
+ goto err_free_dev;
}
- input_register_device(rpcmouse_dev);
+ err = input_register_device(rpcmouse_dev);
+ if (err)
+ goto err_free_irq;
return 0;
+
+ err_free_irq:
+ free_irq(IRQ_VSYNCPULSE, rpcmouse_dev);
+ err_free_dev:
+ input_free_device(rpcmouse_dev);
+
+ return err;
}
static void __exit rpcmouse_exit(void)
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 2a272c5daf0..a85d74710b4 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -246,7 +246,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
input_dev = input_allocate_device();
if (!sermouse || !input_dev)
- goto fail;
+ goto fail1;
sermouse->dev = input_dev;
snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
@@ -275,14 +275,17 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
- input_register_device(sermouse->dev);
+ err = input_register_device(sermouse->dev);
+ if (err)
+ goto fail3;
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(sermouse);
return err;
}
@@ -348,8 +351,7 @@ static struct serio_driver sermouse_drv = {
static int __init sermouse_init(void)
{
- serio_register_driver(&sermouse_drv);
- return 0;
+ return serio_register_driver(&sermouse_drv);
}
static void __exit sermouse_exit(void)
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index ae5871a0e06..9ab5b5ea809 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -293,6 +293,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char firmware_id;
unsigned char button_info;
+ int error;
if (trackpoint_start_protocol(psmouse, &firmware_id))
return -1;
@@ -305,7 +306,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
button_info = 0;
}
- psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
+ psmouse->private = priv = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
if (!priv)
return -1;
@@ -318,7 +319,14 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
trackpoint_defaults(priv);
trackpoint_sync(psmouse);
- sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+ error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+ if (error) {
+ printk(KERN_ERR
+ "trackpoint.c: failed to create sysfs attributes, error: %d\n",
+ error);
+ kfree(priv);
+ return -1;
+ }
printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index ffdb50eee93..c3d64fcc858 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -497,7 +497,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
input_dev = input_allocate_device ();
if (!mouse || !input_dev)
- goto fail;
+ goto fail1;
mouse->dev = input_dev;
mouse->serio = serio;
@@ -527,7 +527,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
err = serio_open (serio, drv);
if (err)
- goto fail;
+ goto fail2;
/*
* Request selftest. Standard packet format and differential
@@ -535,12 +535,15 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
*/
serio->write (serio, 'T'); /* Test */
- input_register_device (input_dev);
+ err = input_register_device (input_dev);
+ if (err)
+ goto fail3;
return 0;
- fail: serio_set_drvdata (serio, NULL);
- input_free_device (input_dev);
+ fail3: serio_close (serio);
+ fail2: serio_set_drvdata (serio, NULL);
+ fail1: input_free_device (input_dev);
kfree (mouse);
return err;
}
@@ -571,8 +574,7 @@ static struct serio_driver vsxxxaa_drv = {
static int __init
vsxxxaa_init (void)
{
- serio_register_driver(&vsxxxaa_drv);
- return 0;
+ return serio_register_driver(&vsxxxaa_drv);
}
static void __exit
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index a22a74a2a3d..664bcc8116f 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -196,12 +196,12 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
switch (code) {
case BTN_TOUCH:
case BTN_0:
- case BTN_FORWARD:
case BTN_LEFT: index = 0; break;
case BTN_STYLUS:
case BTN_1:
case BTN_RIGHT: index = 1; break;
case BTN_2:
+ case BTN_FORWARD:
case BTN_STYLUS2:
case BTN_MIDDLE: index = 2; break;
case BTN_3:
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index 54adba2d8ed..d9ca55891cd 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -16,6 +16,7 @@ static int i8042_aux_irq = -1;
#define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
static void __iomem *kbd_iobase;
+static struct resource *kbd_res;
#define I8042_COMMAND_REG (kbd_iobase + 0x64UL)
#define I8042_DATA_REG (kbd_iobase + 0x60UL)
@@ -60,6 +61,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev
i8042_kbd_irq = irq;
kbd_iobase = of_ioremap(&kbd->resource[0],
0, 8, "kbd");
+ kbd_res = &kbd->resource[0];
} else if (!strcmp(dp->name, OBP_PS2MS_NAME1) ||
!strcmp(dp->name, OBP_PS2MS_NAME2)) {
struct of_device *ms = of_find_device_by_node(dp);
@@ -77,7 +79,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev
static int __devexit sparc_i8042_remove(struct of_device *op)
{
- of_iounmap(kbd_iobase, 8);
+ of_iounmap(kbd_res, kbd_iobase, 8);
return 0;
}
@@ -119,7 +121,7 @@ static int __init i8042_platform_init(void)
if (i8042_kbd_irq == -1 ||
i8042_aux_irq == -1) {
if (kbd_iobase) {
- of_iounmap(kbd_iobase, 8);
+ of_iounmap(kbd_res, kbd_iobase, 8);
kbd_iobase = (void __iomem *) NULL;
}
return -ENODEV;
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 8738edda661..d36bd5475b6 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -111,6 +111,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ .ident = "Fujitsu Lifebook P7010",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+ },
+ },
+ {
.ident = "Fujitsu Lifebook P5020D",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 7e3141f37e3..debe9445488 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -255,25 +255,10 @@ static int i8042_kbd_write(struct serio *port, unsigned char c)
static int i8042_aux_write(struct serio *serio, unsigned char c)
{
struct i8042_port *port = serio->port_data;
- int retval;
-
-/*
- * Send the byte out.
- */
-
- if (port->mux == -1)
- retval = i8042_command(&c, I8042_CMD_AUX_SEND);
- else
- retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);
-
-/*
- * Make sure the interrupt happens and the character is received even
- * in the case the IRQ isn't wired, so that we can receive further
- * characters later.
- */
- i8042_interrupt(0, NULL);
- return retval;
+ return i8042_command(&c, port->mux == -1 ?
+ I8042_CMD_AUX_SEND :
+ I8042_CMD_MUX_SEND + port->mux);
}
/*
@@ -337,23 +322,27 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
dfl = 0;
if (str & I8042_STR_MUXERR) {
dbg("MUX error, status is %02x, data is %02x", str, data);
- switch (data) {
- default:
/*
* When MUXERR condition is signalled the data register can only contain
* 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
- * it is not always the case. Some KBC just get confused which port the
- * data came from and signal error leaving the data intact. They _do not_
- * revert to legacy mode (actually I've never seen KBC reverting to legacy
- * mode yet, when we see one we'll add proper handling).
- * Anyway, we will assume that the data came from the same serio last byte
+ * it is not always the case. Some KBCs also report 0xfc when there is
+ * nothing connected to the port while others sometimes get confused which
+ * port the data came from and signal error leaving the data intact. They
+ * _do not_ revert to legacy mode (actually I've never seen KBC reverting
+ * to legacy mode yet, when we see one we'll add proper handling).
+ * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the
+ * rest assume that the data came from the same serio last byte
* was transmitted (if transmission happened not too long ago).
*/
+
+ switch (data) {
+ default:
if (time_before(jiffies, last_transmit + HZ/10)) {
str = last_str;
break;
}
/* fall through - report timeout */
+ case 0xfc:
case 0xfd:
case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
case 0xff: dfl = SERIO_PARITY; data = 0xfe; break;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 5f1d4032fd5..f0ce822c102 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -45,8 +45,7 @@ EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_child_port);
-EXPORT_SYMBOL(__serio_unregister_port_delayed);
-EXPORT_SYMBOL(__serio_register_driver);
+EXPORT_SYMBOL(serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
@@ -63,11 +62,10 @@ static LIST_HEAD(serio_list);
static struct bus_type serio_bus;
-static void serio_add_driver(struct serio_driver *drv);
static void serio_add_port(struct serio *serio);
-static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio);
+static void serio_attach_driver(struct serio_driver *drv);
static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
{
@@ -171,11 +169,10 @@ static void serio_find_driver(struct serio *serio)
*/
enum serio_event_type {
- SERIO_RESCAN,
- SERIO_RECONNECT,
+ SERIO_RESCAN_PORT,
+ SERIO_RECONNECT_PORT,
SERIO_REGISTER_PORT,
- SERIO_UNREGISTER_PORT,
- SERIO_REGISTER_DRIVER,
+ SERIO_ATTACH_DRIVER,
};
struct serio_event {
@@ -190,11 +187,12 @@ static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static struct task_struct *serio_task;
-static void serio_queue_event(void *object, struct module *owner,
- enum serio_event_type event_type)
+static int serio_queue_event(void *object, struct module *owner,
+ enum serio_event_type event_type)
{
unsigned long flags;
struct serio_event *event;
+ int retval = 0;
spin_lock_irqsave(&serio_event_lock, flags);
@@ -213,24 +211,34 @@ static void serio_queue_event(void *object, struct module *owner,
}
}
- if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
- if (!try_module_get(owner)) {
- printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
- kfree(event);
- goto out;
- }
-
- event->type = event_type;
- event->object = object;
- event->owner = owner;
+ event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
+ if (!event) {
+ printk(KERN_ERR
+ "serio: Not enough memory to queue event %d\n",
+ event_type);
+ retval = -ENOMEM;
+ goto out;
+ }
- 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);
+ if (!try_module_get(owner)) {
+ printk(KERN_WARNING
+ "serio: Can't get module reference, dropping event %d\n",
+ event_type);
+ kfree(event);
+ retval = -EINVAL;
+ goto out;
}
+
+ event->type = event_type;
+ event->object = object;
+ event->owner = owner;
+
+ list_add_tail(&event->node, &serio_event_list);
+ wake_up(&serio_wait);
+
out:
spin_unlock_irqrestore(&serio_event_lock, flags);
+ return retval;
}
static void serio_free_event(struct serio_event *event)
@@ -308,22 +316,17 @@ static void serio_handle_event(void)
serio_add_port(event->object);
break;
- case SERIO_UNREGISTER_PORT:
- serio_disconnect_port(event->object);
- serio_destroy_port(event->object);
- break;
-
- case SERIO_RECONNECT:
+ case SERIO_RECONNECT_PORT:
serio_reconnect_port(event->object);
break;
- case SERIO_RESCAN:
+ case SERIO_RESCAN_PORT:
serio_disconnect_port(event->object);
serio_find_driver(event->object);
break;
- case SERIO_REGISTER_DRIVER:
- serio_add_driver(event->object);
+ case SERIO_ATTACH_DRIVER:
+ serio_attach_driver(event->object);
break;
default:
@@ -675,12 +678,12 @@ static void serio_disconnect_port(struct serio *serio)
void serio_rescan(struct serio *serio)
{
- serio_queue_event(serio, NULL, SERIO_RESCAN);
+ serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
}
void serio_reconnect(struct serio *serio)
{
- serio_queue_event(serio, NULL, SERIO_RECONNECT);
+ serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
}
/*
@@ -717,16 +720,6 @@ void serio_unregister_child_port(struct serio *serio)
mutex_unlock(&serio_mutex);
}
-/*
- * Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_mutex is
- * taken or not and when delayed execution is feasible.
- */
-void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
-{
- serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT);
-}
-
/*
* Serio driver operations
@@ -785,28 +778,52 @@ static int serio_driver_remove(struct device *dev)
return 0;
}
-static struct bus_type serio_bus = {
- .name = "serio",
- .probe = serio_driver_probe,
- .remove = serio_driver_remove,
-};
-
-static void serio_add_driver(struct serio_driver *drv)
+static void serio_attach_driver(struct serio_driver *drv)
{
int error;
- error = driver_register(&drv->driver);
+ error = driver_attach(&drv->driver);
if (error)
- printk(KERN_ERR
- "serio: driver_register() failed for %s, error: %d\n",
+ printk(KERN_WARNING
+ "serio: driver_attach() failed for %s with error %d\n",
drv->driver.name, error);
}
-void __serio_register_driver(struct serio_driver *drv, struct module *owner)
+int serio_register_driver(struct serio_driver *drv)
{
+ int manual_bind = drv->manual_bind;
+ int error;
+
drv->driver.bus = &serio_bus;
- serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
+ /*
+ * Temporarily disable automatic binding because probing
+ * takes long time and we are better off doing it in kseriod
+ */
+ drv->manual_bind = 1;
+
+ error = driver_register(&drv->driver);
+ if (error) {
+ printk(KERN_ERR
+ "serio: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+ return error;
+ }
+
+ /*
+ * Restore original bind mode and let kseriod bind the
+ * driver to free ports
+ */
+ if (!manual_bind) {
+ drv->manual_bind = 0;
+ error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
+ if (error) {
+ driver_unregister(&drv->driver);
+ return error;
+ }
+ }
+
+ return 0;
}
void serio_unregister_driver(struct serio_driver *drv)
@@ -947,15 +964,21 @@ irqreturn_t serio_interrupt(struct serio *serio,
return ret;
}
+static struct bus_type serio_bus = {
+ .name = "serio",
+ .dev_attrs = serio_device_attrs,
+ .drv_attrs = serio_driver_attrs,
+ .match = serio_bus_match,
+ .uevent = serio_uevent,
+ .probe = serio_driver_probe,
+ .remove = serio_driver_remove,
+ .resume = serio_resume,
+};
+
static int __init serio_init(void)
{
int error;
- serio_bus.dev_attrs = serio_device_attrs;
- serio_bus.drv_attrs = serio_driver_attrs;
- serio_bus.match = serio_bus_match;
- serio_bus.uevent = serio_uevent;
- serio_bus.resume = serio_resume;
error = bus_register(&serio_bus);
if (error) {
printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 7c8d0399ae8..088ebc348ba 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -389,8 +389,7 @@ static struct serio_driver serio_raw_drv = {
static int __init serio_raw_init(void)
{
- serio_register_driver(&serio_raw_drv);
- return 0;
+ return serio_register_driver(&serio_raw_drv);
}
static void __exit serio_raw_exit(void)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 9418bbe4707..6b46c9bf1d2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -144,4 +144,19 @@ config TOUCHSCREEN_TOUCHWIN
To compile this driver as a module, choose M here: the
module will be called touchwin.
+config TOUCHSCREEN_UCB1400
+ tristate "Philips UCB1400 touchscreen"
+ select AC97_BUS
+ help
+ This enables support for the Philips UCB1400 touchscreen interface.
+ The UCB1400 is an AC97 audio codec. The touchscreen interface
+ will be initialized only after the ALSA subsystem has been
+ brought up and the UCB1400 detected. You therefore have to
+ configure ALSA support as well (either built-in or modular,
+ independently of whether this driver is itself built-in or
+ modular) for this driver to work.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ucb1400_ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 1abb8f10d60..30e6e2217a1 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 0517c7387d6..c6164b6f476 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -76,6 +76,7 @@ struct ads7846 {
char phys[32];
struct spi_device *spi;
+ struct attribute_group *attr_group;
u16 model;
u16 vref_delay_usecs;
u16 x_plate_ohms;
@@ -317,6 +318,48 @@ static ssize_t ads7846_disable_store(struct device *dev,
static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
+static struct attribute *ads7846_attributes[] = {
+ &dev_attr_temp0.attr,
+ &dev_attr_temp1.attr,
+ &dev_attr_vbatt.attr,
+ &dev_attr_vaux.attr,
+ &dev_attr_pen_down.attr,
+ &dev_attr_disable.attr,
+ NULL,
+};
+
+static struct attribute_group ads7846_attr_group = {
+ .attrs = ads7846_attributes,
+};
+
+/*
+ * ads7843/7845 don't have temperature sensors, and
+ * use the other sensors a bit differently too
+ */
+
+static struct attribute *ads7843_attributes[] = {
+ &dev_attr_vbatt.attr,
+ &dev_attr_vaux.attr,
+ &dev_attr_pen_down.attr,
+ &dev_attr_disable.attr,
+ NULL,
+};
+
+static struct attribute_group ads7843_attr_group = {
+ .attrs = ads7843_attributes,
+};
+
+static struct attribute *ads7845_attributes[] = {
+ &dev_attr_vaux.attr,
+ &dev_attr_pen_down.attr,
+ &dev_attr_disable.attr,
+ NULL,
+};
+
+static struct attribute_group ads7845_attr_group = {
+ .attrs = ads7845_attributes,
+};
+
/*--------------------------------------------------------------------------*/
/*
@@ -788,38 +831,30 @@ static int __devinit ads7846_probe(struct spi_device *spi)
(void) ads7846_read12_ser(&spi->dev,
READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
- /* ads7843/7845 don't have temperature sensors, and
- * use the other sensors a bit differently too
- */
- if (ts->model == 7846) {
- device_create_file(&spi->dev, &dev_attr_temp0);
- device_create_file(&spi->dev, &dev_attr_temp1);
+ switch (ts->model) {
+ case 7846:
+ ts->attr_group = &ads7846_attr_group;
+ break;
+ case 7845:
+ ts->attr_group = &ads7845_attr_group;
+ break;
+ default:
+ ts->attr_group = &ads7843_attr_group;
+ break;
}
- if (ts->model != 7845)
- device_create_file(&spi->dev, &dev_attr_vbatt);
- device_create_file(&spi->dev, &dev_attr_vaux);
-
- device_create_file(&spi->dev, &dev_attr_pen_down);
-
- device_create_file(&spi->dev, &dev_attr_disable);
+ err = sysfs_create_group(&spi->dev.kobj, ts->attr_group);
+ if (err)
+ goto err_free_irq;
err = input_register_device(input_dev);
if (err)
- goto err_remove_attr;
+ goto err_remove_attr_group;
return 0;
- err_remove_attr:
- device_remove_file(&spi->dev, &dev_attr_disable);
- device_remove_file(&spi->dev, &dev_attr_pen_down);
- if (ts->model == 7846) {
- device_remove_file(&spi->dev, &dev_attr_temp1);
- device_remove_file(&spi->dev, &dev_attr_temp0);
- }
- if (ts->model != 7845)
- device_remove_file(&spi->dev, &dev_attr_vbatt);
- device_remove_file(&spi->dev, &dev_attr_vaux);
-
+ err_remove_attr_group:
+ sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
+ err_free_irq:
free_irq(spi->irq, ts);
err_free_mem:
input_free_device(input_dev);
@@ -835,15 +870,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
ads7846_suspend(spi, PMSG_SUSPEND);
- device_remove_file(&spi->dev, &dev_attr_disable);
- device_remove_file(&spi->dev, &dev_attr_pen_down);
- if (ts->model == 7846) {
- device_remove_file(&spi->dev, &dev_attr_temp1);
- device_remove_file(&spi->dev, &dev_attr_temp0);
- }
- if (ts->model != 7845)
- device_remove_file(&spi->dev, &dev_attr_vbatt);
- device_remove_file(&spi->dev, &dev_attr_vaux);
+ sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
free_irq(ts->spi->irq, ts);
/* suspend left the IRQ disabled */
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 66121f6a89a..e2945582828 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -175,17 +175,19 @@ static int read_xydata(struct corgi_ts *corgi_ts)
static void new_data(struct corgi_ts *corgi_ts)
{
+ struct input_dev *dev = corgi_ts->input;
+
if (corgi_ts->power_mode != PWR_MODE_ACTIVE)
return;
if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
return;
- 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);
+ input_report_abs(dev, ABS_X, corgi_ts->tc.x);
+ input_report_abs(dev, ABS_Y, corgi_ts->tc.y);
+ input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure);
+ input_report_key(dev, BTN_TOUCH, corgi_ts->pendown);
+ input_sync(dev);
}
static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
@@ -219,12 +221,14 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer)
static void corgi_ts_timer(unsigned long data)
{
struct corgi_ts *corgits_data = (struct corgi_ts *) data;
+
ts_interrupt_main(corgits_data, 1);
}
static irqreturn_t ts_interrupt(int irq, void *dev_id)
{
struct corgi_ts *corgits_data = dev_id;
+
ts_interrupt_main(corgits_data, 0);
return IRQ_HANDLED;
}
@@ -272,7 +276,7 @@ static int __init corgits_probe(struct platform_device *pdev)
corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL);
input_dev = input_allocate_device();
if (!corgi_ts || !input_dev)
- goto fail;
+ goto fail1;
platform_set_drvdata(pdev, corgi_ts);
@@ -281,7 +285,7 @@ static int __init corgits_probe(struct platform_device *pdev)
if (corgi_ts->irq_gpio < 0) {
err = -ENODEV;
- goto fail;
+ goto fail1;
}
corgi_ts->input = input_dev;
@@ -319,10 +323,12 @@ static int __init corgits_probe(struct platform_device *pdev)
if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) {
err = -EBUSY;
- goto fail;
+ goto fail1;
}
- input_register_device(corgi_ts->input);
+ err = input_register_device(corgi_ts->input);
+ if (err)
+ goto fail2;
corgi_ts->power_mode = PWR_MODE_ACTIVE;
@@ -331,17 +337,17 @@ static int __init corgits_probe(struct platform_device *pdev)
return 0;
- fail: input_free_device(input_dev);
+ fail2: free_irq(corgi_ts->irq_gpio, corgi_ts);
+ fail1: input_free_device(input_dev);
kfree(corgi_ts);
return err;
-
}
static int corgits_remove(struct platform_device *pdev)
{
struct corgi_ts *corgi_ts = platform_get_drvdata(pdev);
- free_irq(corgi_ts->irq_gpio, NULL);
+ free_irq(corgi_ts->irq_gpio, corgi_ts);
del_timer_sync(&corgi_ts->timer);
corgi_ts->machinfo->put_hsync();
input_unregister_device(corgi_ts->input);
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 913e1b73bb0..9d61cd133d0 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -397,8 +397,7 @@ static struct serio_driver elo_drv = {
static int __init elo_init(void)
{
- serio_register_driver(&elo_drv);
- return 0;
+ return serio_register_driver(&elo_drv);
}
static void __exit elo_exit(void)
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 817c2198933..9157eb148e8 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -123,7 +123,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
input_dev = input_allocate_device();
if (!gunze || !input_dev) {
err = -ENOMEM;
- goto fail;
+ goto fail1;
}
gunze->serio = serio;
@@ -146,13 +146,17 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
+
+ err = input_register_device(gunze->dev);
+ if (err)
+ goto fail3;
- input_register_device(gunze->dev);
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(gunze);
return err;
}
@@ -190,8 +194,7 @@ static struct serio_driver gunze_drv = {
static int __init gunze_init(void)
{
- serio_register_driver(&gunze_drv);
- return 0;
+ return serio_register_driver(&gunze_drv);
}
static void __exit gunze_exit(void)
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index d9e61ee05ea..c4116d4f64e 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -478,8 +478,7 @@ static struct serio_driver h3600ts_drv = {
static int __init h3600ts_init(void)
{
- serio_register_driver(&h3600ts_drv);
- return 0;
+ return serio_register_driver(&h3600ts_drv);
}
static void __exit h3600ts_exit(void)
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index 58fca316786..24908747274 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -76,38 +76,47 @@ static irqreturn_t hp680_ts_interrupt(int irq, void *dev)
static int __init hp680_ts_init(void)
{
+ int err;
+
hp680_ts_dev = input_allocate_device();
if (!hp680_ts_dev)
return -ENOMEM;
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;
+ input_set_abs_params(hp680_ts_dev, ABS_X,
+ HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);
+ input_set_abs_params(hp680_ts_dev, ABS_Y,
+ HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0);
hp680_ts_dev->name = "HP Jornada touchscreen";
hp680_ts_dev->phys = "hp680_ts/input0";
- input_register_device(hp680_ts_dev);
-
if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
IRQF_DISABLED, 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;
+ err = -EBUSY;
+ goto fail1;
}
+ err = input_register_device(hp680_ts_dev);
+ if (err)
+ goto fail2;
+
return 0;
+
+ fail2: free_irq(HP680_TS_IRQ, NULL);
+ cancel_delayed_work(&work);
+ flush_scheduled_work();
+ fail1: input_free_device(hp680_ts_dev);
+ return err;
}
static void __exit hp680_ts_exit(void)
{
- free_irq(HP680_TS_IRQ, 0);
+ free_irq(HP680_TS_IRQ, NULL);
cancel_delayed_work(&work);
flush_scheduled_work();
input_unregister_device(hp680_ts_dev);
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index 4cbcaa6a71e..44140feeffc 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -96,15 +96,13 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id)
goto end;
}
- if (~status & MK712_STATUS_TOUCH)
- {
+ if (~status & MK712_STATUS_TOUCH) {
debounce = 1;
input_report_key(mk712_dev, BTN_TOUCH, 0);
goto end;
}
- if (debounce)
- {
+ if (debounce) {
debounce = 0;
goto end;
}
@@ -113,8 +111,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id)
input_report_abs(mk712_dev, ABS_X, last_x);
input_report_abs(mk712_dev, ABS_Y, last_y);
-end:
-
+ end:
last_x = inw(mk712_io + MK712_X) & 0x0fff;
last_y = inw(mk712_io + MK712_Y) & 0x0fff;
input_sync(mk712_dev);
@@ -169,13 +166,14 @@ static int __init mk712_init(void)
(inw(mk712_io + MK712_STATUS) & 0xf333)) {
printk(KERN_WARNING "mk712: device not present\n");
err = -ENODEV;
- goto fail;
+ goto fail1;
}
- if (!(mk712_dev = input_allocate_device())) {
+ mk712_dev = input_allocate_device();
+ if (!mk712_dev) {
printk(KERN_ERR "mk712: not enough memory\n");
err = -ENOMEM;
- goto fail;
+ goto fail1;
}
mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
@@ -196,13 +194,17 @@ static int __init mk712_init(void)
if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
printk(KERN_WARNING "mk712: unable to get IRQ\n");
err = -EBUSY;
- goto fail;
+ goto fail1;
}
- input_register_device(mk712_dev);
+ err = input_register_device(mk712_dev);
+ if (err)
+ goto fail2;
+
return 0;
- fail: input_free_device(mk712_dev);
+ fail2: free_irq(mk712_irq, mk712_dev);
+ fail1: input_free_device(mk712_dev);
release_region(mk712_io, 8);
return err;
}
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index 3b4c61664b6..c3c2d735d0e 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -137,7 +137,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
input_dev = input_allocate_device();
if (!mtouch || !input_dev) {
err = -ENOMEM;
- goto fail;
+ goto fail1;
}
mtouch->serio = serio;
@@ -160,14 +160,17 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
- goto fail;
+ goto fail2;
- input_register_device(mtouch->dev);
+ err = input_register_device(mtouch->dev);
+ if (err)
+ goto fail3;
return 0;
- fail: serio_set_drvdata(serio, NULL);
- input_free_device(input_dev);
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
kfree(mtouch);
return err;
}
@@ -205,8 +208,7 @@ static struct serio_driver mtouch_drv = {
static int __init mtouch_init(void)
{
- serio_register_driver(&mtouch_drv);
- return 0;
+ return serio_register_driver(&mtouch_drv);
}
static void __exit mtouch_exit(void)
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 6c7d0c2c76c..bd2767991ae 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -171,8 +171,7 @@ static struct serio_driver pm_drv = {
static int __init pm_init(void)
{
- serio_register_driver(&pm_drv);
- return 0;
+ return serio_register_driver(&pm_drv);
}
static void __exit pm_exit(void)
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index c74f74e57af..35ba46c6ad2 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -182,8 +182,7 @@ static struct serio_driver tr_drv = {
static int __init tr_init(void)
{
- serio_register_driver(&tr_drv);
- return 0;
+ return serio_register_driver(&tr_drv);
}
static void __exit tr_exit(void)
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index 9911820fa2f..4dc073dacab 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -189,8 +189,7 @@ static struct serio_driver tw_drv = {
static int __init tw_init(void)
{
- serio_register_driver(&tw_drv);
- return 0;
+ return serio_register_driver(&tw_drv);
}
static void __exit tw_exit(void)
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
new file mode 100644
index 00000000000..4358a0a78ea
--- /dev/null
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -0,0 +1,579 @@
+/*
+ * Philips UCB1400 touchscreen driver
+ *
+ * Author: Nicolas Pitre
+ * Created: September 25, 2006
+ * Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This code is heavily based on ucb1x00-*.c copyrighted by Russell King
+ * covering the UCB1100, UCB1200 and UCB1300.. Support for the UCB1400 has
+ * been made separate from ucb1x00-core/ucb1x00-ts on Russell's request.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/ac97_codec.h>
+
+
+/*
+ * Interesting UCB1400 AC-link registers
+ */
+
+#define UCB_IE_RIS 0x5e
+#define UCB_IE_FAL 0x60
+#define UCB_IE_STATUS 0x62
+#define UCB_IE_CLEAR 0x62
+#define UCB_IE_ADC (1 << 11)
+#define UCB_IE_TSPX (1 << 12)
+
+#define UCB_TS_CR 0x64
+#define UCB_TS_CR_TSMX_POW (1 << 0)
+#define UCB_TS_CR_TSPX_POW (1 << 1)
+#define UCB_TS_CR_TSMY_POW (1 << 2)
+#define UCB_TS_CR_TSPY_POW (1 << 3)
+#define UCB_TS_CR_TSMX_GND (1 << 4)
+#define UCB_TS_CR_TSPX_GND (1 << 5)
+#define UCB_TS_CR_TSMY_GND (1 << 6)
+#define UCB_TS_CR_TSPY_GND (1 << 7)
+#define UCB_TS_CR_MODE_INT (0 << 8)
+#define UCB_TS_CR_MODE_PRES (1 << 8)
+#define UCB_TS_CR_MODE_POS (2 << 8)
+#define UCB_TS_CR_BIAS_ENA (1 << 11)
+#define UCB_TS_CR_TSPX_LOW (1 << 12)
+#define UCB_TS_CR_TSMX_LOW (1 << 13)
+
+#define UCB_ADC_CR 0x66
+#define UCB_ADC_SYNC_ENA (1 << 0)
+#define UCB_ADC_VREFBYP_CON (1 << 1)
+#define UCB_ADC_INP_TSPX (0 << 2)
+#define UCB_ADC_INP_TSMX (1 << 2)
+#define UCB_ADC_INP_TSPY (2 << 2)
+#define UCB_ADC_INP_TSMY (3 << 2)
+#define UCB_ADC_INP_AD0 (4 << 2)
+#define UCB_ADC_INP_AD1 (5 << 2)
+#define UCB_ADC_INP_AD2 (6 << 2)
+#define UCB_ADC_INP_AD3 (7 << 2)
+#define UCB_ADC_EXT_REF (1 << 5)
+#define UCB_ADC_START (1 << 7)
+#define UCB_ADC_ENA (1 << 15)
+
+#define UCB_ADC_DATA 0x68
+#define UCB_ADC_DAT_VALID (1 << 15)
+#define UCB_ADC_DAT_VALUE(x) ((x) & 0x3ff)
+
+#define UCB_ID 0x7e
+#define UCB_ID_1400 0x4304
+
+
+struct ucb1400 {
+ ac97_t *ac97;
+ struct input_dev *ts_idev;
+
+ int irq;
+
+ wait_queue_head_t ts_wait;
+ struct task_struct *ts_task;
+
+ unsigned int irq_pending; /* not bit field shared */
+ unsigned int ts_restart:1;
+ unsigned int adcsync:1;
+};
+
+static int adcsync;
+
+static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
+{
+ return ucb->ac97->bus->ops->read(ucb->ac97, reg);
+}
+
+static inline void ucb1400_reg_write(struct ucb1400 *ucb, u16 reg, u16 val)
+{
+ ucb->ac97->bus->ops->write(ucb->ac97, reg, val);
+}
+
+static inline void ucb1400_adc_enable(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+}
+
+static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel)
+{
+ unsigned int val;
+
+ if (ucb->adcsync)
+ adc_channel |= UCB_ADC_SYNC_ENA;
+
+ ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel);
+ ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel | UCB_ADC_START);
+
+ for (;;) {
+ val = ucb1400_reg_read(ucb, UCB_ADC_DATA);
+ if (val & UCB_ADC_DAT_VALID)
+ break;
+ /* yield to other processes */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ return UCB_ADC_DAT_VALUE(val);
+}
+
+static inline void ucb1400_adc_disable(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_ADC_CR, 0);
+}
+
+/* Switch to interrupt mode. */
+static inline void ucb1400_ts_mode_int(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+ UCB_TS_CR_MODE_INT);
+}
+
+/*
+ * Switch to pressure mode, and read pressure. We don't need to wait
+ * here, since both plates are being driven.
+ */
+static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
+}
+
+/*
+ * Switch to X position mode and measure Y plate. We switch the plate
+ * configuration in pressure mode, then switch to position mode. This
+ * gives a faster response time. Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
+}
+
+/*
+ * Switch to Y position mode and measure X plate. We switch the plate
+ * configuration in pressure mode, then switch to position mode. This
+ * gives a faster response time. Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+ udelay(55);
+
+ return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
+}
+
+/*
+ * Switch to X plate resistance mode. Set MX to ground, PX to
+ * supply. Measure current.
+ */
+static inline unsigned int ucb1400_ts_read_xres(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1400_adc_read(ucb, 0);
+}
+
+/*
+ * Switch to Y plate resistance mode. Set MY to ground, PY to
+ * supply. Measure current.
+ */
+static inline unsigned int ucb1400_ts_read_yres(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_TS_CR,
+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+ return ucb1400_adc_read(ucb, 0);
+}
+
+static inline int ucb1400_ts_pen_down(struct ucb1400 *ucb)
+{
+ unsigned short val = ucb1400_reg_read(ucb, UCB_TS_CR);
+ return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
+}
+
+static inline void ucb1400_ts_irq_enable(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, UCB_IE_TSPX);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+ ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_TSPX);
+}
+
+static inline void ucb1400_ts_irq_disable(struct ucb1400 *ucb)
+{
+ ucb1400_reg_write(ucb, UCB_IE_FAL, 0);
+}
+
+static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y)
+{
+ input_report_abs(idev, ABS_X, x);
+ input_report_abs(idev, ABS_Y, y);
+ input_report_abs(idev, ABS_PRESSURE, pressure);
+ input_sync(idev);
+}
+
+static void ucb1400_ts_event_release(struct input_dev *idev)
+{
+ input_report_abs(idev, ABS_PRESSURE, 0);
+ input_sync(idev);
+}
+
+static void ucb1400_handle_pending_irq(struct ucb1400 *ucb)
+{
+ unsigned int isr;
+
+ isr = ucb1400_reg_read(ucb, UCB_IE_STATUS);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, isr);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ if (isr & UCB_IE_TSPX)
+ ucb1400_ts_irq_disable(ucb);
+ else
+ printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+
+ enable_irq(ucb->irq);
+}
+
+static int ucb1400_ts_thread(void *_ucb)
+{
+ struct ucb1400 *ucb = _ucb;
+ struct task_struct *tsk = current;
+ int valid = 0;
+
+ tsk->policy = SCHED_FIFO;
+ tsk->rt_priority = 1;
+
+ while (!kthread_should_stop()) {
+ unsigned int x, y, p;
+ long timeout;
+
+ ucb->ts_restart = 0;
+
+ if (ucb->irq_pending) {
+ ucb->irq_pending = 0;
+ ucb1400_handle_pending_irq(ucb);
+ }
+
+ ucb1400_adc_enable(ucb);
+ x = ucb1400_ts_read_xpos(ucb);
+ y = ucb1400_ts_read_ypos(ucb);
+ p = ucb1400_ts_read_pressure(ucb);
+ ucb1400_adc_disable(ucb);
+
+ /* Switch back to interrupt mode. */
+ ucb1400_ts_mode_int(ucb);
+
+ msleep(10);
+
+ if (ucb1400_ts_pen_down(ucb)) {
+ ucb1400_ts_irq_enable(ucb);
+
+ /*
+ * If we spat out a valid sample set last time,
+ * spit out a "pen off" sample here.
+ */
+ if (valid) {
+ ucb1400_ts_event_release(ucb->ts_idev);
+ valid = 0;
+ }
+
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ } else {
+ valid = 1;
+ ucb1400_ts_evt_add(ucb->ts_idev, p, x, y);
+ timeout = msecs_to_jiffies(10);
+ }
+
+ wait_event_interruptible_timeout(ucb->ts_wait,
+ ucb->irq_pending || ucb->ts_restart || kthread_should_stop(),
+ timeout);
+ try_to_freeze();
+ }
+
+ /* Send the "pen off" if we are stopping with the pen still active */
+ if (valid)
+ ucb1400_ts_event_release(ucb->ts_idev);
+
+ ucb->ts_task = NULL;
+ return 0;
+}
+
+/*
+ * A restriction with interrupts exists when using the ucb1400, as
+ * the codec read/write routines may sleep while waiting for codec
+ * access completion and uses semaphores for access control to the
+ * AC97 bus. A complete codec read cycle could take anywhere from
+ * 60 to 100uSec so we *definitely* don't want to spin inside the
+ * interrupt handler waiting for codec access. So, we handle the
+ * interrupt by scheduling a RT kernel thread to run in process
+ * context instead of interrupt context.
+ */
+static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
+{
+ struct ucb1400 *ucb = devid;
+
+ if (irqnr == ucb->irq) {
+ disable_irq(ucb->irq);
+ ucb->irq_pending = 1;
+ wake_up(&ucb->ts_wait);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static int ucb1400_ts_open(struct input_dev *idev)
+{
+ struct ucb1400 *ucb = idev->private;
+ int ret = 0;
+
+ BUG_ON(ucb->ts_task);
+
+ ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts");
+ if (IS_ERR(ucb->ts_task)) {
+ ret = PTR_ERR(ucb->ts_task);
+ ucb->ts_task = NULL;
+ }
+
+ return ret;
+}
+
+static void ucb1400_ts_close(struct input_dev *idev)
+{
+ struct ucb1400 *ucb = idev->private;
+
+ if (ucb->ts_task)
+ kthread_stop(ucb->ts_task);
+
+ ucb1400_ts_irq_disable(ucb);
+ ucb1400_reg_write(ucb, UCB_TS_CR, 0);
+}
+
+#ifdef CONFIG_PM
+static int ucb1400_ts_resume(struct device *dev)
+{
+ struct ucb1400 *ucb = dev_get_drvdata(dev);
+
+ if (ucb->ts_task) {
+ /*
+ * Restart the TS thread to ensure the
+ * TS interrupt mode is set up again
+ * after sleep.
+ */
+ ucb->ts_restart = 1;
+ wake_up(&ucb->ts_wait);
+ }
+ return 0;
+}
+#else
+#define ucb1400_ts_resume NULL
+#endif
+
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
+/*
+ * Try to probe our interrupt, rather than relying on lots of
+ * hard-coded machine dependencies.
+ */
+static int ucb1400_detect_irq(struct ucb1400 *ucb)
+{
+ unsigned long mask, timeout;
+
+ mask = probe_irq_on();
+ if (!mask) {
+ probe_irq_off(mask);
+ return -EBUSY;
+ }
+
+ /* Enable the ADC interrupt. */
+ ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+ ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ /* Cause an ADC interrupt. */
+ ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+ ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
+
+ /* Wait for the conversion to complete. */
+ timeout = jiffies + HZ/2;
+ while (!(ucb1400_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VALID)) {
+ cpu_relax();
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "ucb1400: timed out in IRQ probe\n");
+ probe_irq_off(mask);
+ return -ENODEV;
+ }
+ }
+ ucb1400_reg_write(ucb, UCB_ADC_CR, 0);
+
+ /* Disable and clear interrupt. */
+ ucb1400_reg_write(ucb, UCB_IE_RIS, 0);
+ ucb1400_reg_write(ucb, UCB_IE_FAL, 0);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+ ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+ /* Read triggered interrupt. */
+ ucb->irq = probe_irq_off(mask);
+ if (ucb->irq < 0 || ucb->irq == NO_IRQ)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int ucb1400_ts_probe(struct device *dev)
+{
+ struct ucb1400 *ucb;
+ struct input_dev *idev;
+ int error, id, x_res, y_res;
+
+ ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL);
+ idev = input_allocate_device();
+ if (!ucb || !idev) {
+ error = -ENOMEM;
+ goto err_free_devs;
+ }
+
+ ucb->ts_idev = idev;
+ ucb->adcsync = adcsync;
+ ucb->ac97 = to_ac97_t(dev);
+ init_waitqueue_head(&ucb->ts_wait);
+
+ id = ucb1400_reg_read(ucb, UCB_ID);
+ if (id != UCB_ID_1400) {
+ error = -ENODEV;
+ goto err_free_devs;
+ }
+
+ error = ucb1400_detect_irq(ucb);
+ if (error) {
+ printk(KERN_ERR "UCB1400: IRQ probe failed\n");
+ goto err_free_devs;
+ }
+
+ error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING,
+ "UCB1400", ucb);
+ if (error) {
+ printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n",
+ ucb->irq, error);
+ goto err_free_devs;
+ }
+ printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
+
+ idev->private = ucb;
+ idev->cdev.dev = dev;
+ idev->name = "UCB1400 touchscreen interface";
+ idev->id.vendor = ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
+ idev->id.product = id;
+ idev->open = ucb1400_ts_open;
+ idev->close = ucb1400_ts_close;
+ idev->evbit[0] = BIT(EV_ABS);
+
+ ucb1400_adc_enable(ucb);
+ x_res = ucb1400_ts_read_xres(ucb);
+ y_res = ucb1400_ts_read_yres(ucb);
+ ucb1400_adc_disable(ucb);
+ printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res);
+
+ input_set_abs_params(idev, ABS_X, 0, x_res, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, y_res, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0);
+
+ error = input_register_device(idev);
+ if (error)
+ goto err_free_irq;
+
+ dev_set_drvdata(dev, ucb);
+ return 0;
+
+ err_free_irq:
+ free_irq(ucb->irq, ucb);
+ err_free_devs:
+ input_free_device(idev);
+ kfree(ucb);
+ return error;
+}
+
+static int ucb1400_ts_remove(struct device *dev)
+{
+ struct ucb1400 *ucb = dev_get_drvdata(dev);
+
+ free_irq(ucb->irq, ucb);
+ input_unregister_device(ucb->ts_idev);
+ dev_set_drvdata(dev, NULL);
+ kfree(ucb);
+ return 0;
+}
+
+static struct device_driver ucb1400_ts_driver = {
+ .owner = THIS_MODULE,
+ .bus = &ac97_bus_type,
+ .probe = ucb1400_ts_probe,
+ .remove = ucb1400_ts_remove,
+ .resume = ucb1400_ts_resume,
+};
+
+static int __init ucb1400_ts_init(void)
+{
+ return driver_register(&ucb1400_ts_driver);
+}
+
+static void __exit ucb1400_ts_exit(void)
+{
+ driver_unregister(&ucb1400_ts_driver);
+}
+
+module_param(adcsync, int, 0444);
+
+module_init(ucb1400_ts_init);
+module_exit(ucb1400_ts_exit);
+
+MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index 3cac2373934..09ea50dd345 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -408,7 +408,7 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb)
p = cblock.buffer;
if (!access_ok(VERIFY_READ, p, length))
return -EFAULT;
- buf = (u_char *) kmalloc(1024, GFP_KERNEL);
+ buf = kmalloc(1024, GFP_KERNEL);
if (!buf)
return -ENOMEM;
timeout = 0;
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
index 90593e2ef87..e3e5c139907 100644
--- a/drivers/isdn/act2000/module.c
+++ b/drivers/isdn/act2000/module.c
@@ -573,12 +573,11 @@ act2000_alloccard(int bus, int port, int irq, char *id)
{
int i;
act2000_card *card;
- if (!(card = (act2000_card *) kmalloc(sizeof(act2000_card), GFP_KERNEL))) {
+ if (!(card = kzalloc(sizeof(act2000_card), GFP_KERNEL))) {
printk(KERN_WARNING
"act2000: (%s) Could not allocate card-struct.\n", id);
return;
}
- memset((char *) card, 0, sizeof(act2000_card));
spin_lock_init(&card->lock);
spin_lock_init(&card->mnlock);
skb_queue_head_init(&card->sndq);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 11844bbfe93..d22c0224fde 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -215,13 +215,12 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
unsigned int minor = 0;
unsigned long flags;
- mp = kmalloc(sizeof(*mp), GFP_ATOMIC);
+ mp = kzalloc(sizeof(*mp), GFP_ATOMIC);
if (!mp) {
printk(KERN_ERR "capi: can't alloc capiminor\n");
return NULL;
}
- memset(mp, 0, sizeof(struct capiminor));
mp->ap = ap;
mp->ncci = ncci;
mp->msgid = 0;
@@ -304,10 +303,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
struct capiminor *mp = NULL;
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
- np = kmalloc(sizeof(*np), GFP_ATOMIC);
+ np = kzalloc(sizeof(*np), GFP_ATOMIC);
if (!np)
return NULL;
- memset(np, 0, sizeof(struct capincci));
np->ncci = ncci;
np->cdev = cdev;
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -384,10 +382,9 @@ static struct capidev *capidev_alloc(void)
struct capidev *cdev;
unsigned long flags;
- cdev = kmalloc(sizeof(*cdev), GFP_KERNEL);
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return NULL;
- memset(cdev, 0, sizeof(struct capidev));
init_MUTEX(&cdev->ncci_list_sem);
skb_queue_head_init(&cdev->recvqueue);
@@ -1010,7 +1007,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
{
struct capiminor *mp;
- if ((mp = capiminor_find(iminor(file->f_dentry->d_inode))) == 0)
+ if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0)
return -ENXIO;
if (mp->nccip == 0)
return -ENXIO;
@@ -1203,7 +1200,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
return error;
}
-static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
+static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
{
#ifdef _DEBUG_TTYFUNCS
printk(KERN_DEBUG "capinc_tty_set_termios\n");
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index b6f9476c050..c4d438c17da 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -334,12 +334,11 @@ static capidrv_plci *new_plci(capidrv_contr * card, int chan)
{
capidrv_plci *plcip;
- plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC);
+ plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
if (plcip == 0)
return NULL;
- memset(plcip, 0, sizeof(capidrv_plci));
plcip->state = ST_PLCI_NONE;
plcip->plci = 0;
plcip->msgid = 0;
@@ -404,12 +403,11 @@ static inline capidrv_ncci *new_ncci(capidrv_contr * card,
{
capidrv_ncci *nccip;
- nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
+ nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
if (nccip == 0)
return NULL;
- memset(nccip, 0, sizeof(capidrv_ncci));
nccip->ncci = ncci;
nccip->state = ST_NCCI_NONE;
nccip->plcip = plcip;
@@ -2005,18 +2003,17 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
return -1;
}
- if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
+ if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
printk(KERN_WARNING
"capidrv: (%s) Could not allocate contr-struct.\n", id);
return -1;
}
- memset(card, 0, sizeof(capidrv_contr));
card->owner = THIS_MODULE;
init_timer(&card->listentimer);
strcpy(card->name, id);
card->contrnr = contr;
card->nbchan = profp->nbchannel;
- card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
+ card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
if (!card->bchans) {
printk(KERN_WARNING
"capidrv: (%s) Could not allocate bchan-structs.\n", id);
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 399b316111f..06967da7c4a 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -45,7 +45,7 @@ put_info_buffer(char *cp)
return;
if (!*cp)
return;
- if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
+ if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
return; /* no memory */
strcpy(ib->info_start, cp); /* set output string */
ib->next = NULL;
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 03319ea5aa0..7d97d54588d 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -153,7 +153,7 @@ int cf_command(int drvid, int mode,
*ielenp = p - ielenp - 1; /* set total IE length */
/* allocate mem for information struct */
- if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
+ if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
return(-ENOMEM); /* no memory */
init_timer(&cs->timer);
cs->info[0] = '\0';
@@ -276,7 +276,7 @@ int insertrule(int idx, divert_rule *newrule)
{ struct deflect_struc *ds,*ds1=NULL;
unsigned long flags;
- if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc),
+ if (!(ds = kmalloc(sizeof(struct deflect_struc),
GFP_KERNEL)))
return(-ENOMEM); /* no memory */
@@ -451,7 +451,7 @@ static int isdn_divert_icall(isdn_ctrl *ic)
if (dv->rule.action == DEFLECT_PROCEED)
if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
return(0); /* no external deflection needed */
- if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
+ if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
return(0); /* no memory */
init_timer(&cs->timer);
cs->info[0] = '\0';
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
index 5b203fe21dc..708d47a6484 100644
--- a/drivers/isdn/gigaset/Kconfig
+++ b/drivers/isdn/gigaset/Kconfig
@@ -5,6 +5,7 @@ config ISDN_DRV_GIGASET
tristate "Siemens Gigaset support (isdn)"
depends on ISDN_I4L
select CRC_CCITT
+ select BITREVERSE
help
Say m here if you have a Gigaset or Sinus isdn device.
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index ce3cd77094b..88e958f176d 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -15,6 +15,7 @@
#include "gigaset.h"
#include <linux/crc-ccitt.h>
+#include <linux/bitrev.h>
//#define GIG_M10x_STUFF_VOICE_DATA
@@ -302,7 +303,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
inputstate |= INS_skip_frame;
break;
}
- *__skb_put(skb, 1) = gigaset_invtab[c];
+ *__skb_put(skb, 1) = bitrev8(c);
}
if (unlikely(!numbytes))
@@ -543,7 +544,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
cp = skb->data;
len = skb->len;
while (len--) {
- c = gigaset_invtab[*cp++];
+ c = bitrev8(*cp++);
if (c == DLE_FLAG)
*(skb_put(iraw_skb, 1)) = c;
*(skb_put(iraw_skb, 1)) = c;
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 63b629b1cdb..b5e7f9c7d74 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1853,20 +1853,24 @@ static int gigaset_write_cmd(struct cardstate *cs,
{
struct cmdbuf_t *cb;
unsigned long flags;
- int status;
+ int rc;
gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
- if (len <= 0)
- return 0; /* nothing to do */
+ if (len <= 0) {
+ /* nothing to do */
+ rc = 0;
+ goto notqueued;
+ }
if (len > IF_WRITEBUF)
len = IF_WRITEBUF;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto notqueued;
}
memcpy(cb->buf, buf, len);
@@ -1891,11 +1895,21 @@ static int gigaset_write_cmd(struct cardstate *cs,
if (unlikely(!cs->connected)) {
spin_unlock_irqrestore(&cs->lock, flags);
gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+ /* flush command queue */
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ while (cs->cmdbuf != NULL)
+ complete_cb(cs);
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
return -ENODEV;
}
- status = start_cbsend(cs);
+ rc = start_cbsend(cs);
spin_unlock_irqrestore(&cs->lock, flags);
- return status < 0 ? status : len;
+ return rc < 0 ? rc : len;
+
+notqueued: /* request handled without queuing */
+ if (wake_tasklet)
+ tasklet_schedule(wake_tasklet);
+ return rc;
}
/* gigaset_write_room
@@ -1964,20 +1978,15 @@ static int gigaset_freebcshw(struct bc_state *bcs)
/* kill URBs and tasklets before freeing - better safe than sorry */
atomic_set(&ubc->running, 0);
- for (i = 0; i < BAS_OUTURBS; ++i)
- if (ubc->isoouturbs[i].urb) {
- gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d",
- __func__, i);
- usb_kill_urb(ubc->isoouturbs[i].urb);
- usb_free_urb(ubc->isoouturbs[i].urb);
- }
- for (i = 0; i < BAS_INURBS; ++i)
- if (ubc->isoinurbs[i]) {
- gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d",
- __func__, i);
- usb_kill_urb(ubc->isoinurbs[i]);
- usb_free_urb(ubc->isoinurbs[i]);
- }
+ gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
+ for (i = 0; i < BAS_OUTURBS; ++i) {
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ }
+ for (i = 0; i < BAS_INURBS; ++i) {
+ usb_kill_urb(ubc->isoinurbs[i]);
+ usb_free_urb(ubc->isoinurbs[i]);
+ }
tasklet_kill(&ubc->sent_tasklet);
tasklet_kill(&ubc->rcvd_tasklet);
kfree(ubc->isooutbuf);
@@ -2099,55 +2108,32 @@ static void freeurbs(struct cardstate *cs)
struct bas_bc_state *ubc;
int i, j;
+ gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__);
for (j = 0; j < 2; ++j) {
ubc = cs->bcs[j].hw.bas;
- for (i = 0; i < BAS_OUTURBS; ++i)
- if (ubc->isoouturbs[i].urb) {
- usb_kill_urb(ubc->isoouturbs[i].urb);
- gig_dbg(DEBUG_INIT,
- "%s: isoc output URB %d/%d unlinked",
- __func__, j, i);
- usb_free_urb(ubc->isoouturbs[i].urb);
- ubc->isoouturbs[i].urb = NULL;
- }
- for (i = 0; i < BAS_INURBS; ++i)
- if (ubc->isoinurbs[i]) {
- usb_kill_urb(ubc->isoinurbs[i]);
- gig_dbg(DEBUG_INIT,
- "%s: isoc input URB %d/%d unlinked",
- __func__, j, i);
- usb_free_urb(ubc->isoinurbs[i]);
- ubc->isoinurbs[i] = NULL;
- }
- }
- if (ucs->urb_int_in) {
- usb_kill_urb(ucs->urb_int_in);
- gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_int_in);
- ucs->urb_int_in = NULL;
- }
- if (ucs->urb_cmd_out) {
- usb_kill_urb(ucs->urb_cmd_out);
- gig_dbg(DEBUG_INIT, "%s: command output URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_cmd_out);
- ucs->urb_cmd_out = NULL;
- }
- if (ucs->urb_cmd_in) {
- usb_kill_urb(ucs->urb_cmd_in);
- gig_dbg(DEBUG_INIT, "%s: command input URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_cmd_in);
- ucs->urb_cmd_in = NULL;
- }
- if (ucs->urb_ctrl) {
- usb_kill_urb(ucs->urb_ctrl);
- gig_dbg(DEBUG_INIT, "%s: control output URB unlinked",
- __func__);
- usb_free_urb(ucs->urb_ctrl);
- ucs->urb_ctrl = NULL;
+ for (i = 0; i < BAS_OUTURBS; ++i) {
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ ubc->isoouturbs[i].urb = NULL;
+ }
+ for (i = 0; i < BAS_INURBS; ++i) {
+ usb_kill_urb(ubc->isoinurbs[i]);
+ usb_free_urb(ubc->isoinurbs[i]);
+ ubc->isoinurbs[i] = NULL;
+ }
}
+ usb_kill_urb(ucs->urb_int_in);
+ usb_free_urb(ucs->urb_int_in);
+ ucs->urb_int_in = NULL;
+ usb_kill_urb(ucs->urb_cmd_out);
+ usb_free_urb(ucs->urb_cmd_out);
+ ucs->urb_cmd_out = NULL;
+ usb_kill_urb(ucs->urb_cmd_in);
+ usb_free_urb(ucs->urb_cmd_in);
+ ucs->urb_cmd_in = NULL;
+ usb_kill_urb(ucs->urb_ctrl);
+ usb_free_urb(ucs->urb_ctrl);
+ ucs->urb_ctrl = NULL;
}
/* gigaset_probe
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index defd5743dba..4f75cce6fdf 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -33,43 +33,6 @@ MODULE_PARM_DESC(debug, "debug level");
#define VALID_ID 0x02
#define ASSIGNED 0x04
-/* bitwise byte inversion table */
-__u8 gigaset_invtab[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
-};
-EXPORT_SYMBOL_GPL(gigaset_invtab);
-
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
size_t len, const unsigned char *buf)
{
@@ -393,16 +356,17 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv)
{
unsigned long flags;
unsigned i;
- static struct cardstate *ret = NULL;
+ struct cardstate *ret = NULL;
spin_lock_irqsave(&drv->lock, flags);
for (i = 0; i < drv->minors; ++i) {
if (!(drv->flags[i] & VALID_MINOR)) {
- drv->flags[i] = VALID_MINOR;
- ret = drv->cs + i;
- }
- if (ret)
+ if (try_module_get(drv->owner)) {
+ drv->flags[i] = VALID_MINOR;
+ ret = drv->cs + i;
+ }
break;
+ }
}
spin_unlock_irqrestore(&drv->lock, flags);
return ret;
@@ -413,6 +377,8 @@ static void free_cs(struct cardstate *cs)
unsigned long flags;
struct gigaset_driver *drv = cs->driver;
spin_lock_irqsave(&drv->lock, flags);
+ if (drv->flags[cs->minor_index] & VALID_MINOR)
+ module_put(drv->owner);
drv->flags[cs->minor_index] = 0;
spin_unlock_irqrestore(&drv->lock, flags);
}
@@ -616,7 +582,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
skb_reserve(bcs->skb, HW_HDR_LEN);
else {
- warn("could not allocate skb\n");
+ warn("could not allocate skb");
bcs->inputstate |= INS_skip_frame;
}
@@ -669,17 +635,25 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
int i;
gig_dbg(DEBUG_INIT, "allocating cs");
- cs = alloc_cs(drv);
- if (!cs)
- goto error;
+ if (!(cs = alloc_cs(drv))) {
+ err("maximum number of devices exceeded");
+ return NULL;
+ }
+ mutex_init(&cs->mutex);
+ mutex_lock(&cs->mutex);
+
gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
- if (!cs->bcs)
+ if (!cs->bcs) {
+ err("out of memory");
goto error;
+ }
gig_dbg(DEBUG_INIT, "allocating inbuf");
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
- if (!cs->inbuf)
+ if (!cs->inbuf) {
+ err("out of memory");
goto error;
+ }
cs->cs_init = 0;
cs->channels = channels;
@@ -691,8 +665,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
spin_lock_init(&cs->ev_lock);
cs->ev_tail = 0;
cs->ev_head = 0;
- mutex_init(&cs->mutex);
- mutex_lock(&cs->mutex);
tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
(unsigned long) cs);
@@ -721,8 +693,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
for (i = 0; i < channels; ++i) {
gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
- if (!gigaset_initbcs(cs->bcs + i, cs, i))
+ if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
+ err("could not allocate channel %d data", i);
goto error;
+ }
}
++cs->cs_init;
@@ -757,8 +731,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
make_valid(cs, VALID_ID);
++cs->cs_init;
gig_dbg(DEBUG_INIT, "setting up hw");
- if (!cs->ops->initcshw(cs))
+ if (!cs->ops->initcshw(cs)) {
+ err("could not allocate device specific data");
goto error;
+ }
++cs->cs_init;
@@ -780,8 +756,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
mutex_unlock(&cs->mutex);
return cs;
-error: if (cs)
- mutex_unlock(&cs->mutex);
+error:
+ mutex_unlock(&cs->mutex);
gig_dbg(DEBUG_INIT, "failed");
gigaset_freecs(cs);
return NULL;
@@ -1077,7 +1053,6 @@ void gigaset_freedriver(struct gigaset_driver *drv)
spin_unlock_irqrestore(&driver_lock, flags);
gigaset_if_freedriver(drv);
- module_put(drv->owner);
kfree(drv->cs);
kfree(drv->flags);
@@ -1109,10 +1084,6 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
if (!drv)
return NULL;
- if (!try_module_get(owner))
- goto out1;
-
- drv->cs = NULL;
drv->have_tty = 0;
drv->minor = minor;
drv->minors = minors;
@@ -1124,11 +1095,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
if (!drv->cs)
- goto out2;
+ goto error;
drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
if (!drv->flags)
- goto out3;
+ goto error;
for (i = 0; i < minors; ++i) {
drv->flags[i] = 0;
@@ -1145,11 +1116,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
return drv;
-out3:
+error:
kfree(drv->cs);
-out2:
- module_put(owner);
-out1:
kfree(drv);
return NULL;
}
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 06298cc52bf..a0317abaeb1 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -876,10 +876,6 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb,
}
}
-
-/* bitwise byte inversion table */
-extern __u8 gigaset_invtab[]; /* in common.c */
-
/* append received bytes to inbuf */
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
unsigned numbytes);
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 7edea015867..458b6462f93 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -127,7 +127,7 @@ static int if_write_room(struct tty_struct *tty);
static int if_chars_in_buffer(struct tty_struct *tty);
static void if_throttle(struct tty_struct *tty);
static void if_unthrottle(struct tty_struct *tty);
-static void if_set_termios(struct tty_struct *tty, struct termios *old);
+static void if_set_termios(struct tty_struct *tty, struct ktermios *old);
static int if_tiocmget(struct tty_struct *tty, struct file *file);
static int if_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
@@ -490,7 +490,7 @@ static void if_unthrottle(struct tty_struct *tty)
mutex_unlock(&cs->mutex);
}
-static void if_set_termios(struct tty_struct *tty, struct termios *old)
+static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct cardstate *cs;
unsigned int iflag;
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 8667daaa1a8..df988eb0e36 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -14,6 +14,7 @@
#include "gigaset.h"
#include <linux/crc-ccitt.h>
+#include <linux/bitrev.h>
/* access methods for isowbuf_t */
/* ============================ */
@@ -487,7 +488,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
gig_dbg(DEBUG_STREAM, "put %d bytes", count);
write = atomic_read(&iwb->write);
do {
- c = gigaset_invtab[*in++];
+ c = bitrev8(*in++);
iwb->data[write++] = c;
write %= BAS_OUTBUFSIZE;
} while (--count > 0);
@@ -876,7 +877,7 @@ static inline void trans_receive(unsigned char *src, unsigned count,
while (count > 0) {
dst = skb_put(skb, count < dobytes ? count : dobytes);
while (count > 0 && dobytes > 0) {
- *dst++ = gigaset_invtab[*src++];
+ *dst++ = bitrev8(*src++);
count--;
dobytes--;
}
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index fd5d7364a48..eba10466ccc 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -121,10 +121,9 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
p_dev->conf.Present = PRESENT_OPTION;
/* Allocate space for private device-specific data */
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
goto err;
- memset(local, 0, sizeof(local_info_t));
p_dev->priv = local;
return avmcs_config(p_dev);
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index da272924771..7a69a18d07e 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -65,18 +65,15 @@ avmcard *b1_alloc_card(int nr_controllers)
avmctrl_info *cinfo;
int i;
- card = kmalloc(sizeof(*card), GFP_KERNEL);
+ card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card)
return NULL;
- memset(card, 0, sizeof(*card));
-
- cinfo = kmalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
+ cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
if (!cinfo) {
kfree(card);
return NULL;
}
- memset(cinfo, 0, sizeof(*cinfo) * nr_controllers);
card->ctrlinfo = cinfo;
for (i = 0; i < nr_controllers; i++) {
@@ -718,12 +715,11 @@ avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
avmcard_dmainfo *p;
void *buf;
- p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
+ p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
if (!p) {
printk(KERN_WARNING "%s: no memory.\n", name);
goto err;
}
- memset(p, 0, sizeof(avmcard_dmainfo));
p->recvbuf.size = rsize;
buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index e47c60b0a8e..c925020fe9b 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -584,6 +584,7 @@ static void __exit t1isa_exit(void)
{
int i;
+ unregister_capi_driver(&capi_driver_t1isa);
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index 6851c6270ce..d835e74ecf1 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -756,14 +756,14 @@ int diva_get_driver_info (dword id, byte* data, int data_length) {
data_length -= 9;
- if ((to_copy = MIN(strlen(clients[id].drvName), data_length-1))) {
+ if ((to_copy = min(strlen(clients[id].drvName), (size_t)(data_length-1)))) {
memcpy (p, clients[id].drvName, to_copy);
p += to_copy;
data_length -= to_copy;
if ((data_length >= 4) && clients[id].hDbg->drvTag[0]) {
*p++ = '(';
data_length -= 1;
- if ((to_copy = MIN(strlen(clients[id].hDbg->drvTag), data_length-2))) {
+ if ((to_copy = min(strlen(clients[id].hDbg->drvTag), (size_t)(data_length-2)))) {
memcpy (p, clients[id].hDbg->drvTag, to_copy);
p += to_copy;
data_length -= to_copy;
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c
index 0617d7cabf0..e1df8d98c31 100644
--- a/drivers/isdn/hardware/eicon/di.c
+++ b/drivers/isdn/hardware/eicon/di.c
@@ -133,7 +133,7 @@ void pr_out(ADAPTER * a)
i = this->XCurrent;
X = PTR_X(a,this);
while(i<this->XNum && length<270) {
- clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
+ clength = min((word)(270-length),(word)(X[i].PLength-this->XOffset));
a->ram_out_buffer(a,
&ReqOut->XBuffer.P[length],
PTR_P(a,this,&X[i].P[this->XOffset]),
@@ -622,7 +622,7 @@ byte isdn_ind(ADAPTER * a,
sizeof(a->stream_buffer),
&final, NULL, NULL);
}
- IoAdapter->RBuffer.length = MIN(MLength, 270);
+ IoAdapter->RBuffer.length = min(MLength, (word)270);
if (IoAdapter->RBuffer.length != MLength) {
this->complete = 0;
} else {
@@ -676,9 +676,9 @@ byte isdn_ind(ADAPTER * a,
this->RCurrent++;
}
if (cma) {
- clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset);
+ clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset));
} else {
- clength = MIN(a->ram_inw(a, &RBuffer->length)-offset,
+ clength = min(a->ram_inw(a, &RBuffer->length)-offset,
R[this->RCurrent].PLength-this->ROffset);
}
if(R[this->RCurrent].P) {
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index dae2e83dd5e..91fc92c01af 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -185,7 +185,7 @@ void diva_log_info(unsigned char *format, ...)
unsigned char line[160];
va_start(args, format);
- vsprintf(line, format, args);
+ vsnprintf(line, sizeof(line), format, args);
va_end(args);
printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line);
diff --git a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c
index 4a27e230b0a..6fd9b007417 100644
--- a/drivers/isdn/hardware/eicon/io.c
+++ b/drivers/isdn/hardware/eicon/io.c
@@ -262,7 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
memset (&prms, 0x00, sizeof(prms));
- prms.structure_length = MIN(sizeof(prms), pI->structure_length);
+ prms.structure_length = min_t(size_t, sizeof(prms), pI->structure_length);
memset (pI, 0x00, pI->structure_length);
prms.flag_dynamic_l1_down = (IoAdapter->capi_cfg.cfg_1 & \
DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? 1 : 0;
diff --git a/drivers/isdn/hardware/eicon/istream.c b/drivers/isdn/hardware/eicon/istream.c
index 23139668d9b..18f8798442f 100644
--- a/drivers/isdn/hardware/eicon/istream.c
+++ b/drivers/isdn/hardware/eicon/istream.c
@@ -92,7 +92,7 @@ int diva_istream_write (void* context,
return (-1); /* was not able to write */
break; /* only part of message was written */
}
- to_write = MIN(length, DIVA_DFIFO_DATA_SZ);
+ to_write = min(length, DIVA_DFIFO_DATA_SZ);
if (to_write) {
a->ram_out_buffer (a,
#ifdef PLATFORM_GT_32BIT
@@ -176,7 +176,7 @@ int diva_istream_read (void* context,
return (-1); /* was not able to read */
break;
}
- to_read = MIN(max_length, tmp[1]);
+ to_read = min(max_length, (int)tmp[1]);
if (to_read) {
a->ram_in_buffer(a,
#ifdef PLATFORM_GT_32BIT
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
index a66836cf756..2444811e0b3 100644
--- a/drivers/isdn/hardware/eicon/platform.h
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -83,14 +83,6 @@
#define NULL ((void *) 0)
#endif
-#ifndef MIN
-#define MIN(a,b) ((a)>(b) ? (b) : (a))
-#endif
-
-#ifndef MAX
-#define MAX(a,b) ((a)>(b) ? (a) : (b))
-#endif
-
#ifndef far
#define far
#endif
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index cfd2718a490..34ab5f7dcab 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -110,7 +110,7 @@ config HISAX_16_3
config HISAX_TELESPCI
bool "Teles PCI"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the Teles PCI.
See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -238,7 +238,7 @@ config HISAX_MIC
config HISAX_NETJET
bool "NETjet card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the NetJet from Traverse
Technologies.
@@ -249,7 +249,7 @@ config HISAX_NETJET
config HISAX_NETJET_U
bool "NETspider U card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the Netspider U interface ISDN card
from Traverse Technologies.
@@ -317,7 +317,7 @@ config HISAX_GAZEL
config HISAX_HFC_PCI
bool "HFC PCI-Bus cards"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
@@ -344,18 +344,11 @@ config HISAX_HFC_SX
config HISAX_ENTERNOW_PCI
bool "Formula-n enter:now PCI card"
- depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
+ depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
help
This enables HiSax support for the Formula-n enter:now PCI
ISDN card.
-config HISAX_AMD7930
- bool "Am7930 (EXPERIMENTAL)"
- depends on EXPERIMENTAL && SPARC && BROKEN
- help
- This enables HiSax support for the AMD7930 chips on some SPARCs.
- This code is not finished yet.
-
endif
if ISDN_DRV_HISAX
@@ -402,6 +395,7 @@ config HISAX_ST5481
tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
select CRC_CCITT
+ select BITREVERSE
help
This enables the driver for ST5481 based USB ISDN adapters,
e.g. the BeWan Gazel 128 USB
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 876fec6c6be..9e70c206779 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -123,11 +123,10 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)
DEBUG(0, "avma1cs_attach()\n");
/* Allocate space for private device-specific data */
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
return -ENOMEM;
- memset(local, 0, sizeof(local_info_t));
p_dev->priv = local;
/* The io structure describes IO port mapping */
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index cede72cdbb3..17ec0b70ba1 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -227,14 +227,6 @@ const char *CardType[] = {
#define DEFAULT_CFG {5,0x2E0,0,0}
#endif
-
-#ifdef CONFIG_HISAX_AMD7930
-#undef DEFAULT_CARD
-#undef DEFAULT_CFG
-#define DEFAULT_CARD ISDN_CTYPE_AMD7930
-#define DEFAULT_CFG {12,0x3e0,0,0}
-#endif
-
#ifdef CONFIG_HISAX_NICCY
#undef DEFAULT_CARD
#undef DEFAULT_CFG
@@ -545,10 +537,6 @@ extern int setup_hfcpci(struct IsdnCard *card);
extern int setup_hfcsx(struct IsdnCard *card);
#endif
-#if CARD_AMD7930
-extern int setup_amd7930(struct IsdnCard *card);
-#endif
-
#if CARD_NICCY
extern int setup_niccy(struct IsdnCard *card);
#endif
@@ -869,14 +857,13 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
struct IsdnCard *card = cards + cardnr;
struct IsdnCardState *cs;
- cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+ cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
if (!cs) {
printk(KERN_WARNING
"HiSax: No memory for IsdnCardState(card %d)\n",
cardnr + 1);
goto out;
}
- memset(cs, 0, sizeof(struct IsdnCardState));
card->cs = cs;
spin_lock_init(&cs->statlock);
spin_lock_init(&cs->lock);
@@ -1064,11 +1051,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
ret = setup_niccy(card);
break;
#endif
-#if CARD_AMD7930
- case ISDN_CTYPE_AMD7930:
- ret = setup_amd7930(card);
- break;
-#endif
#if CARD_ISURF
case ISDN_CTYPE_ISURF:
ret = setup_isurf(card);
@@ -1437,7 +1419,6 @@ static int __init HiSax_init(void)
break;
case ISDN_CTYPE_ELSA_PCI:
case ISDN_CTYPE_NETJET_S:
- case ISDN_CTYPE_AMD7930:
case ISDN_CTYPE_TELESPCI:
case ISDN_CTYPE_W6692:
case ISDN_CTYPE_NETJET_U:
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 3dacfff93f5..6eebeb441bf 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -1121,7 +1121,11 @@ setup_diva(struct IsdnCard *card)
bytecnt = 32;
}
}
+
+#ifdef __ISAPNP__
ready:
+#endif
+
printk(KERN_INFO
"Diva: %s card configured at %#lx IRQ %d\n",
(cs->subtyp == DIVA_PCI) ? "PCI" :
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 4e180d210fa..79ab9dda7d0 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -146,9 +146,8 @@ static int elsa_cs_probe(struct pcmcia_device *link)
DEBUG(0, "elsa_cs_attach()\n");
/* Allocate space for private device-specific data */
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return -ENOMEM;
- memset(local, 0, sizeof(local_info_t));
local->p_dev = link;
link->priv = local;
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
index 0d44a3f480a..34fade96a58 100644
--- a/drivers/isdn/hisax/fsm.c
+++ b/drivers/isdn/hisax/fsm.c
@@ -26,12 +26,10 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
int i;
fsm->jumpmatrix = (FSMFNPTR *)
- kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
+ kzalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
if (!fsm->jumpmatrix)
return -ENOMEM;
- memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
-
for (i = 0; i < fncount; i++)
if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index de9b1a4d6ba..a2fa4ecb8c8 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1591,11 +1591,10 @@ hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data;
hfc4s8s_hw *hw;
- if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) {
+ if (!(hw = kzalloc(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);
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 5db0a85b827..8a48a3ce0a5 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1211,7 +1211,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
break;
case (HW_TESTLOOP | REQUEST):
spin_lock_irqsave(&cs->lock, flags);
- switch ((int) arg) {
+ switch ((long) arg) {
case (1):
Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */
Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */
@@ -1229,7 +1229,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
default:
spin_unlock_irqrestore(&cs->lock, flags);
if (cs->debug & L1_DEB_WARN)
- debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
+ debugl1(cs, "hfcpci_l1hw loop invalid %4lx", (long) arg);
return;
}
cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */
@@ -1711,9 +1711,9 @@ setup_hfcpci(struct IsdnCard *card)
pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
printk(KERN_INFO
- "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
- (u_int) cs->hw.hfcpci.pci_io,
- (u_int) cs->hw.hfcpci.fifos,
+ "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
+ cs->hw.hfcpci.pci_io,
+ cs->hw.hfcpci.fifos,
(u_int) virt_to_bus(cs->hw.hfcpci.fifos),
cs->irq, HZ);
spin_lock_irqsave(&cs->lock, flags);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 7105b043add..5a6989f23fc 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1481,9 +1481,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
iface = iface_used;
if (!
(context =
- kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
+ kzalloc(sizeof(hfcusb_data), GFP_KERNEL)))
return (-ENOMEM); /* got no mem */
- memset(context, 0, sizeof(hfcusb_data));
ep = iface->endpoint;
vcf = validconf[small_match];
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 159c5896061..3f1137e3467 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1139,12 +1139,6 @@ struct IsdnCardState {
#define CARD_HFC_SX 0
#endif
-#ifdef CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 1
-#else
-#define CARD_AMD7930 0
-#endif
-
#ifdef CONFIG_HISAX_NICCY
#define CARD_NICCY 1
#ifndef ISDN_CHIP_ISAC
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index f6db55a752c..9e088fce8c3 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -841,12 +841,10 @@ new_adapter(void)
struct hisax_b_if *b_if[2];
int i;
- adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
+ adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
if (!adapter)
return NULL;
- memset(adapter, 0, sizeof(struct fritz_adapter));
-
adapter->isac.hisax_d_if.owner = THIS_MODULE;
adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
index 81eac344bb0..d0fefcf999c 100644
--- a/drivers/isdn/hisax/hisax_isac.c
+++ b/drivers/isdn/hisax/hisax_isac.c
@@ -433,7 +433,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
char buf[256];
va_start(args, fmt);
- vsprintf(buf, fmt, args);
+ vsnprintf(buf, sizeof(buf), fmt, args);
DBG(DBG_L1M, "%s", buf);
va_end(args);
}
diff --git a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/hisax/isdnhdlc.c
index cbdf54c5af8..268dced6c34 100644
--- a/drivers/isdn/hisax/isdnhdlc.c
+++ b/drivers/isdn/hisax/isdnhdlc.c
@@ -35,30 +35,6 @@ MODULE_LICENSE("GPL");
/*-------------------------------------------------------------------*/
-/* bit swap table.
- * Very handy for devices with different bit order,
- * and neccessary for each transparent B-channel access for all
- * devices which works with this HDLC decoder without bit reversal.
- */
-const unsigned char isdnhdlc_bit_rev_tab[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
-};
-
enum {
HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
HDLC_GET_DATA,HDLC_FAST_FLAG
@@ -621,7 +597,6 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src,
return len;
}
-EXPORT_SYMBOL(isdnhdlc_bit_rev_tab);
EXPORT_SYMBOL(isdnhdlc_rcv_init);
EXPORT_SYMBOL(isdnhdlc_decode);
EXPORT_SYMBOL(isdnhdlc_out_init);
diff --git a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h
index 5655b5f9c48..45167d2f8fb 100644
--- a/drivers/isdn/hisax/isdnhdlc.h
+++ b/drivers/isdn/hisax/isdnhdlc.h
@@ -57,8 +57,6 @@ struct isdnhdlc_vars {
#define HDLC_CRC_ERROR 2
#define HDLC_LENGTH_ERROR 3
-extern const unsigned char isdnhdlc_bit_rev_tab[256];
-
extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56);
extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 9522141f435..030d1625c5c 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -677,7 +677,11 @@ setup_sedlbauer(struct IsdnCard *card)
return (0);
#endif /* CONFIG_PCI */
}
+
+#ifdef __ISAPNP__
ready:
+#endif
+
/* In case of the sedlbauer pcmcia card, this region is in use,
* reserved for us by the card manager. So we do not check it
* here, it would fail.
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 46ed65334c5..45debde05fb 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -155,9 +155,8 @@ static int sedlbauer_probe(struct pcmcia_device *link)
DEBUG(0, "sedlbauer_attach()\n");
/* Allocate space for private device-specific data */
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return -ENOMEM;
- memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
local->p_dev = link;
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 75d0f248e4e..fa64115cd7c 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -14,6 +14,7 @@
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
+#include <linux/bitrev.h>
#include "st5481.h"
static inline void B_L1L2(struct st5481_bcs *bcs, int pr, void *arg)
@@ -72,7 +73,7 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr)
register unsigned char *dest = urb->transfer_buffer+len;
register unsigned int count;
for (count = 0; count < bytes_sent; count++)
- *dest++ = isdnhdlc_bit_rev_tab[*src++];
+ *dest++ = bitrev8(*src++);
}
len += bytes_sent;
} else {
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 1d8c2618366..b8c4855cc88 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -173,7 +173,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
char buf[256];
va_start(args, fmt);
- vsprintf(buf, fmt, args);
+ vsnprintf(buf, sizeof(buf), fmt, args);
DBG(8, "%s", buf);
va_end(args);
}
@@ -275,7 +275,7 @@ static void dout_debug(struct FsmInst *fi, char *fmt, ...)
char buf[256];
va_start(args, fmt);
- vsprintf(buf, fmt, args);
+ vsnprintf(buf, sizeof(buf), fmt, args);
DBG(0x2, "%s", buf);
va_end(args);
}
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 2716aa5c60f..bb3a28a53ff 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -69,12 +69,10 @@ static int probe_st5481(struct usb_interface *intf,
le16_to_cpu(dev->descriptor.idProduct),
number_of_leds);
- adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL);
+ adapter = kzalloc(sizeof(struct st5481_adapter), GFP_KERNEL);
if (!adapter)
return -ENOMEM;
- memset(adapter, 0, sizeof(struct st5481_adapter));
-
adapter->number_of_leds = number_of_leds;
adapter->usb_dev = dev;
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 6b754f18379..3e3e18239ec 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -137,9 +137,8 @@ static int teles_probe(struct pcmcia_device *link)
DEBUG(0, "teles_attach()\n");
/* Allocate space for private device-specific data */
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return -ENOMEM;
- memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
local->p_dev = link;
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index 6bac43cc91b..b2ae4ec1e49 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -745,12 +745,11 @@ hycapi_capi_create(hysdn_card *card)
return 1;
}
if (!card->hyctrlinfo) {
- cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC);
+ cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC);
if (!cinfo) {
printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n");
return -ENOMEM;
}
- memset(cinfo, 0, sizeof(hycapictrl_info));
card->hyctrlinfo = cinfo;
cinfo->card = card;
spin_lock_init(&cinfo->lock);
diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c
index 6d0eb0f42fc..be787e16bb7 100644
--- a/drivers/isdn/hysdn/hysdn_boot.c
+++ b/drivers/isdn/hysdn/hysdn_boot.c
@@ -278,14 +278,13 @@ pof_write_open(hysdn_card * card, unsigned char **bufp)
return (-ERR_ALREADY_BOOT); /* boot already active */
}
/* error no mem available */
- if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) {
+ if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) {
if (card->debug_flags & LOG_MEM_ERR)
hysdn_addlog(card, "POF open: unable to allocate mem");
return (-EFAULT);
}
card->boot = boot;
card->state = CARD_STATE_BOOTING;
- memset(boot, 0, sizeof(struct boot_data));
card->stopcard(card); /* first stop the card */
if (card->testram(card)) {
diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c
index b702ed27252..9e01748a176 100644
--- a/drivers/isdn/hysdn/hysdn_init.c
+++ b/drivers/isdn/hysdn/hysdn_init.c
@@ -81,11 +81,10 @@ search_cards(void)
if (pci_enable_device(akt_pcidev))
continue;
- if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) {
+ if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) {
printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
return;
}
- memset(card, 0, sizeof(hysdn_card));
card->myid = cardmax; /* set own id */
card->bus = akt_pcidev->bus->number;
card->devfn = akt_pcidev->devfn; /* slot + function */
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index d205249a124..557d96c78a6 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -278,11 +278,10 @@ hysdn_net_create(hysdn_card * card)
return (-ENOMEM);
}
hysdn_net_release(card); /* release an existing net device */
- if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
+ if ((dev = kzalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
return (-ENOMEM);
}
- memset(dev, 0, sizeof(struct net_local)); /* clean the structure */
spin_lock_init(&((struct net_local *) dev)->lock);
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 8e2b03889f3..94a93508911 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -275,7 +275,7 @@ hysdn_conf_open(struct inode *ino, struct file *filep)
} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
/* read access -> output card info data */
- if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
+ if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
unlock_kernel();
return (-EFAULT); /* out of memory */
}
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index fcd49920b22..375d956884d 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -111,7 +111,7 @@ put_log_buffer(hysdn_card * card, char *cp)
if (pd->if_used <= 0)
return; /* no open file for read */
- if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
+ if (!(ib = kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
return; /* no memory */
strcpy(ib->log_start, cp); /* set output string */
ib->next = NULL;
@@ -204,7 +204,7 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off)
{
struct log_data *inf;
int len;
- struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
struct procdata *pd = NULL;
hysdn_card *card;
@@ -354,7 +354,7 @@ static unsigned int
hysdn_log_poll(struct file *file, poll_table * wait)
{
unsigned int mask = 0;
- struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
hysdn_card *card;
struct procdata *pd = NULL;
@@ -405,8 +405,7 @@ hysdn_proclog_init(hysdn_card * card)
/* create a cardlog proc entry */
- if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
- memset(pd, 0, sizeof(struct procdata));
+ if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
pd->log->proc_fops = &log_fops;
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
index 2cc56d6a9fa..fb350c567c6 100644
--- a/drivers/isdn/i4l/isdn_audio.c
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -328,7 +328,7 @@ adpcm_state *
isdn_audio_adpcm_init(adpcm_state * s, int nbits)
{
if (!s)
- s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
+ s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
if (s) {
s->a = 0;
s->d = 5;
@@ -343,7 +343,7 @@ dtmf_state *
isdn_audio_dtmf_init(dtmf_state * s)
{
if (!s)
- s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
+ s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
if (s) {
s->idx = 0;
s->last = ' ';
@@ -621,7 +621,7 @@ silence_state *
isdn_audio_silence_init(silence_state * s)
{
if (!s)
- s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
+ s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
if (s) {
s->idx = 0;
s->state = 0;
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index 0afe442db3b..a20f33b4a22 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -331,12 +331,10 @@ static void *bsd_alloc (struct isdn_ppp_comp_data *data)
* Allocate the main control structure for this instance.
*/
maxmaxcode = MAXCODE(bits);
- db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL);
+ db = kzalloc (sizeof (struct bsd_db),GFP_KERNEL);
if (!db)
return NULL;
- memset (db, 0, sizeof(struct bsd_db));
-
db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
decomp = db->xmit ? 0 : 1;
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 69aee2602aa..6a2ef0a87ed 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1059,7 +1059,7 @@ isdn_info_update(void)
static ssize_t
isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
{
- uint minor = iminor(file->f_dentry->d_inode);
+ uint minor = iminor(file->f_path.dentry->d_inode);
int len = 0;
int drvidx;
int chidx;
@@ -1166,7 +1166,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
static ssize_t
isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
{
- uint minor = iminor(file->f_dentry->d_inode);
+ uint minor = iminor(file->f_path.dentry->d_inode);
int drvidx;
int chidx;
int retval;
@@ -1228,7 +1228,7 @@ static unsigned int
isdn_poll(struct file *file, poll_table * wait)
{
unsigned int mask = 0;
- unsigned int minor = iminor(file->f_dentry->d_inode);
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
lock_kernel();
@@ -2072,21 +2072,19 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
if ((adding) && (d->rcverr))
kfree(d->rcverr);
- if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
+ if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
return -1;
}
- memset((char *) d->rcverr, 0, sizeof(int) * m);
if ((adding) && (d->rcvcount))
kfree(d->rcvcount);
- if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
+ if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
if (!adding)
kfree(d->rcverr);
return -1;
}
- memset((char *) d->rcvcount, 0, sizeof(int) * m);
if ((adding) && (d->rpqueue)) {
for (j = 0; j < d->channels; j++)
@@ -2226,11 +2224,10 @@ register_isdn(isdn_if * i)
printk(KERN_WARNING "register_isdn: No write routine given.\n");
return 0;
}
- if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
+ if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
return 0;
}
- memset((char *) d, 0, sizeof(isdn_driver_t));
d->maxbufsize = i->maxbufsize;
d->pktcount = 0;
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 2e4daebfb7e..838b3734e2b 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -2542,17 +2542,15 @@ isdn_net_new(char *name, struct net_device *master)
printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
return NULL;
}
- if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
+ if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
return NULL;
}
- memset(netdev, 0, sizeof(isdn_net_dev));
- if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
+ if (!(netdev->local = kzalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
kfree(netdev);
return NULL;
}
- memset(netdev->local, 0, sizeof(isdn_net_local));
if (name == NULL)
strcpy(netdev->local->name, " ");
else
@@ -2950,7 +2948,7 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
isdn_net_phone *n;
if (p) {
- if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
+ if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
return -ENOMEM;
strcpy(n->num, phone->phone);
n->next = p->local->phone[phone->outgoing & 1];
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 119412d6bd1..4e3f127e400 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -667,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
if (is->debug & 0x2)
printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
- iminor(file->f_dentry->d_inode));
+ iminor(file->f_path.dentry->d_inode));
/* just registers wait_queue hook. This doesn't really wait. */
poll_wait(file, &is->wq, wait);
@@ -717,7 +717,7 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
printk(KERN_DEBUG "ippp: device not activated.\n");
return 0;
}
- nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
+ nbuf = kmalloc(len + 4, GFP_ATOMIC);
if (!nbuf) {
printk(KERN_WARNING "ippp: Can't alloc buf\n");
return 0;
@@ -876,14 +876,12 @@ isdn_ppp_init(void)
#endif /* CONFIG_ISDN_MPP */
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if (!(ippp_table[i] = (struct ippp_struct *)
- kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
+ if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
for (j = 0; j < i; j++)
kfree(ippp_table[j]);
return -1;
}
- memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
spin_lock_init(&ippp_table[i]->buflock);
ippp_table[i]->state = 0;
ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
@@ -1529,10 +1527,8 @@ static int isdn_ppp_mp_bundle_array_init(void)
{
int i;
int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
- if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz,
- GFP_KERNEL)) == NULL )
+ if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
return -ENOMEM;
- memset(isdn_ppp_bundle_arr, 0, sz);
for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
return 0;
@@ -2246,13 +2242,12 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
{
struct ippp_ccp_reset *r;
- r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+ r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
if(!r) {
printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
" structure - no mem\n");
return NULL;
}
- memset(r, 0, sizeof(struct ippp_ccp_reset));
printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
is->reset = r;
return r;
@@ -2338,13 +2333,13 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
id);
return NULL;
} else {
- rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+ rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
if(!rs)
return NULL;
- memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
rs->state = CCPResetIdle;
rs->is = is;
rs->id = id;
+ init_timer(&rs->timer);
rs->timer.data = (unsigned long)rs;
rs->timer.function = isdn_ppp_ccp_timer_callback;
is->reset->rs[id] = rs;
@@ -2536,6 +2531,11 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
+ if (!skb_out) {
+ kfree_skb(skb);
+ printk(KERN_ERR "ippp: decomp memory allocation failure\n");
+ return NULL;
+ }
len = ipc->decompress(stat, skb, skb_out, &rsparm);
kfree_skb(skb);
if (len <= 0) {
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 2b91bb07fc7..fc80afe555b 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1464,7 +1464,7 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
}
static void
-isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
+isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
modem_info *info = (modem_info *) tty->driver_data;
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c
index 38619e8cd82..5484d3c38a5 100644
--- a/drivers/isdn/i4l/isdn_v110.c
+++ b/drivers/isdn/i4l/isdn_v110.c
@@ -92,9 +92,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
int i;
isdn_v110_stream *v;
- if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
+ if ((v = kzalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
return NULL;
- memset(v, 0, sizeof(isdn_v110_stream));
v->key = key;
v->nbits = 0;
for (i = 0; key & (1 << i); i++)
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 730bbd07ebc..1e699bcaba0 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1519,12 +1519,11 @@ icn_initcard(int port, char *id)
icn_card *card;
int i;
- if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) {
+ if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) {
printk(KERN_WARNING
"icn: (%s) Could not allocate card-struct.\n", id);
return (icn_card *) 0;
}
- memset((char *) card, 0, sizeof(icn_card));
spin_lock_init(&card->lock);
card->port = port;
card->interface.owner = THIS_MODULE;
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index c3ae2edaf6f..e3add27dd0e 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -1430,12 +1430,11 @@ isdnloop_initcard(char *id)
isdnloop_card *card;
int i;
- if (!(card = (isdnloop_card *) kmalloc(sizeof(isdnloop_card), GFP_KERNEL))) {
+ if (!(card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL))) {
printk(KERN_WARNING
"isdnloop: (%s) Could not allocate card-struct.\n", id);
return (isdnloop_card *) 0;
}
- memset((char *) card, 0, sizeof(isdnloop_card));
card->interface.owner = THIS_MODULE;
card->interface.channels = ISDNLOOP_BCH;
card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 1966f3410a1..11c1b0b6e39 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -73,14 +73,13 @@ int pcbit_init_dev(int board, int mem_base, int irq)
struct pcbit_dev *dev;
isdn_if *dev_if;
- if ((dev=kmalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL)
+ if ((dev=kzalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL)
{
printk("pcbit_init: couldn't malloc pcbit_dev struct\n");
return -ENOMEM;
}
dev_pcbit[board] = dev;
- memset(dev, 0, sizeof(struct pcbit_dev));
init_waitqueue_head(&dev->set_running_wq);
spin_lock_init(&dev->lock);
@@ -104,7 +103,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
return -EACCES;
}
- dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
+ dev->b1 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
if (!dev->b1) {
printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
iounmap(dev->sh_mem);
@@ -113,7 +112,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
return -ENOMEM;
}
- dev->b2 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
+ dev->b2 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
if (!dev->b2) {
printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
kfree(dev->b1);
@@ -123,8 +122,6 @@ int pcbit_init_dev(int board, int mem_base, int irq)
return -ENOMEM;
}
- memset(dev->b1, 0, sizeof(struct pcbit_chan));
- memset(dev->b2, 0, sizeof(struct pcbit_chan));
dev->b2->id = 1;
INIT_WORK(&dev->qdelivery, pcbit_deliver);
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index 0c9f6df873f..eafcce5e656 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -100,7 +100,7 @@ pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum,
dev_kfree_skb(skb);
return -1;
}
- if ((frame = (struct frame_buf *) kmalloc(sizeof(struct frame_buf),
+ if ((frame = kmalloc(sizeof(struct frame_buf),
GFP_ATOMIC)) == NULL) {
printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n");
dev_kfree_skb(skb);
@@ -369,13 +369,12 @@ pcbit_receive(struct pcbit_dev *dev)
kfree(dev->read_frame);
dev->read_frame = NULL;
}
- frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC);
+ frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC);
if (frame == NULL) {
printk(KERN_WARNING "kmalloc failed\n");
return;
}
- memset(frame, 0, sizeof(struct frame_buf));
cpu = pcbit_readb(dev);
proc = pcbit_readb(dev);
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 06c9872e8c6..150759a5cdd 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -271,14 +271,13 @@ static int __init sc_init(void)
* Horray! We found a board, Make sure we can register
* it with ISDN4Linux
*/
- interface = kmalloc(sizeof(isdn_if), GFP_KERNEL);
+ interface = kzalloc(sizeof(isdn_if), GFP_KERNEL);
if (interface == NULL) {
/*
* Oops, can't malloc isdn_if
*/
continue;
}
- memset(interface, 0, sizeof(isdn_if));
interface->owner = THIS_MODULE;
interface->hl_hdrlen = 0;
@@ -294,7 +293,7 @@ static int __init sc_init(void)
/*
* Allocate the board structure
*/
- sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL);
+ sc_adapter[cinst] = kzalloc(sizeof(board), GFP_KERNEL);
if (sc_adapter[cinst] == NULL) {
/*
* Oops, can't alloc memory for the board
@@ -302,7 +301,6 @@ static int __init sc_init(void)
kfree(interface);
continue;
}
- memset(sc_adapter[cinst], 0, sizeof(board));
spin_lock_init(&sc_adapter[cinst]->lock);
if(!register_isdn(interface)) {
@@ -326,7 +324,7 @@ static int __init sc_init(void)
/*
* Allocate channels status structures
*/
- sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL);
+ sc_adapter[cinst]->channel = kzalloc(sizeof(bchan) * channels, GFP_KERNEL);
if (sc_adapter[cinst]->channel == NULL) {
/*
* Oops, can't alloc memory for the channels
@@ -336,7 +334,6 @@ static int __init sc_init(void)
kfree(sc_adapter[cinst]);
continue;
}
- memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels);
/*
* Lock down the hardware resources
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
new file mode 100644
index 00000000000..703cc88d1ef
--- /dev/null
+++ b/drivers/kvm/Kconfig
@@ -0,0 +1,37 @@
+#
+# KVM configuration
+#
+menu "Virtualization"
+
+config KVM
+ tristate "Kernel-based Virtual Machine (KVM) support"
+ depends on X86 && EXPERIMENTAL
+ ---help---
+ Support hosting fully virtualized guest machines using hardware
+ virtualization extensions. You will need a fairly recent
+ processor equipped with virtualization extensions. You will also
+ need to select one or more of the processor modules below.
+
+ This module provides access to the hardware capabilities through
+ a character device node named /dev/kvm.
+
+ To compile this as a module, choose M here: the module
+ will be called kvm.
+
+ If unsure, say N.
+
+config KVM_INTEL
+ tristate "KVM for Intel processors support"
+ depends on KVM
+ ---help---
+ Provides support for KVM on Intel processors equipped with the VT
+ extensions.
+
+config KVM_AMD
+ tristate "KVM for AMD processors support"
+ depends on KVM
+ ---help---
+ Provides support for KVM on AMD processors equipped with the AMD-V
+ (SVM) extensions.
+
+endmenu
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
new file mode 100644
index 00000000000..c0a789fa9d6
--- /dev/null
+++ b/drivers/kvm/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for Kernel-based Virtual Machine module
+#
+
+kvm-objs := kvm_main.o mmu.o x86_emulate.o
+obj-$(CONFIG_KVM) += kvm.o
+kvm-intel-objs = vmx.o
+obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
+kvm-amd-objs = svm.o
+obj-$(CONFIG_KVM_AMD) += kvm-amd.o
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
new file mode 100644
index 00000000000..2db1ca4c680
--- /dev/null
+++ b/drivers/kvm/kvm.h
@@ -0,0 +1,630 @@
+#ifndef __KVM_H
+#define __KVM_H
+
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include "vmx.h"
+#include <linux/kvm.h>
+
+#define CR0_PE_MASK (1ULL << 0)
+#define CR0_TS_MASK (1ULL << 3)
+#define CR0_NE_MASK (1ULL << 5)
+#define CR0_WP_MASK (1ULL << 16)
+#define CR0_NW_MASK (1ULL << 29)
+#define CR0_CD_MASK (1ULL << 30)
+#define CR0_PG_MASK (1ULL << 31)
+
+#define CR3_WPT_MASK (1ULL << 3)
+#define CR3_PCD_MASK (1ULL << 4)
+
+#define CR3_RESEVED_BITS 0x07ULL
+#define CR3_L_MODE_RESEVED_BITS (~((1ULL << 40) - 1) | 0x0fe7ULL)
+#define CR3_FLAGS_MASK ((1ULL << 5) - 1)
+
+#define CR4_VME_MASK (1ULL << 0)
+#define CR4_PSE_MASK (1ULL << 4)
+#define CR4_PAE_MASK (1ULL << 5)
+#define CR4_PGE_MASK (1ULL << 7)
+#define CR4_VMXE_MASK (1ULL << 13)
+
+#define KVM_GUEST_CR0_MASK \
+ (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \
+ | CR0_NW_MASK | CR0_CD_MASK)
+#define KVM_VM_CR0_ALWAYS_ON \
+ (CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK)
+#define KVM_GUEST_CR4_MASK \
+ (CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK)
+#define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK)
+#define KVM_RMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK | CR4_VME_MASK)
+
+#define INVALID_PAGE (~(hpa_t)0)
+#define UNMAPPED_GVA (~(gpa_t)0)
+
+#define KVM_MAX_VCPUS 1
+#define KVM_MEMORY_SLOTS 4
+#define KVM_NUM_MMU_PAGES 256
+#define KVM_MIN_FREE_MMU_PAGES 5
+#define KVM_REFILL_PAGES 25
+
+#define FX_IMAGE_SIZE 512
+#define FX_IMAGE_ALIGN 16
+#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN)
+
+#define DE_VECTOR 0
+#define DF_VECTOR 8
+#define TS_VECTOR 10
+#define NP_VECTOR 11
+#define SS_VECTOR 12
+#define GP_VECTOR 13
+#define PF_VECTOR 14
+
+#define SELECTOR_TI_MASK (1 << 2)
+#define SELECTOR_RPL_MASK 0x03
+
+#define IOPL_SHIFT 12
+
+/*
+ * Address types:
+ *
+ * gva - guest virtual address
+ * gpa - guest physical address
+ * gfn - guest frame number
+ * hva - host virtual address
+ * hpa - host physical address
+ * hfn - host frame number
+ */
+
+typedef unsigned long gva_t;
+typedef u64 gpa_t;
+typedef unsigned long gfn_t;
+
+typedef unsigned long hva_t;
+typedef u64 hpa_t;
+typedef unsigned long hfn_t;
+
+#define NR_PTE_CHAIN_ENTRIES 5
+
+struct kvm_pte_chain {
+ u64 *parent_ptes[NR_PTE_CHAIN_ENTRIES];
+ struct hlist_node link;
+};
+
+/*
+ * kvm_mmu_page_role, below, is defined as:
+ *
+ * bits 0:3 - total guest paging levels (2-4, or zero for real mode)
+ * bits 4:7 - page table level for this shadow (1-4)
+ * bits 8:9 - page table quadrant for 2-level guests
+ * bit 16 - "metaphysical" - gfn is not a real page (huge page/real mode)
+ */
+union kvm_mmu_page_role {
+ unsigned word;
+ struct {
+ unsigned glevels : 4;
+ unsigned level : 4;
+ unsigned quadrant : 2;
+ unsigned pad_for_nice_hex_output : 6;
+ unsigned metaphysical : 1;
+ };
+};
+
+struct kvm_mmu_page {
+ struct list_head link;
+ struct hlist_node hash_link;
+
+ /*
+ * The following two entries are used to key the shadow page in the
+ * hash table.
+ */
+ gfn_t gfn;
+ union kvm_mmu_page_role role;
+
+ hpa_t page_hpa;
+ unsigned long slot_bitmap; /* One bit set per slot which has memory
+ * in this shadow page.
+ */
+ int global; /* Set if all ptes in this page are global */
+ int multimapped; /* More than one parent_pte? */
+ int root_count; /* Currently serving as active root */
+ union {
+ u64 *parent_pte; /* !multimapped */
+ struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */
+ };
+};
+
+struct vmcs {
+ u32 revision_id;
+ u32 abort;
+ char data[0];
+};
+
+#define vmx_msr_entry kvm_msr_entry
+
+struct kvm_vcpu;
+
+/*
+ * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
+ * 32-bit). The kvm_mmu structure abstracts the details of the current mmu
+ * mode.
+ */
+struct kvm_mmu {
+ void (*new_cr3)(struct kvm_vcpu *vcpu);
+ int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
+ void (*free)(struct kvm_vcpu *vcpu);
+ gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva);
+ hpa_t root_hpa;
+ int root_level;
+ int shadow_root_level;
+
+ u64 *pae_root;
+};
+
+#define KVM_NR_MEM_OBJS 20
+
+struct kvm_mmu_memory_cache {
+ int nobjs;
+ void *objects[KVM_NR_MEM_OBJS];
+};
+
+/*
+ * We don't want allocation failures within the mmu code, so we preallocate
+ * enough memory for a single page fault in a cache.
+ */
+struct kvm_guest_debug {
+ int enabled;
+ unsigned long bp[4];
+ int singlestep;
+};
+
+enum {
+ VCPU_REGS_RAX = 0,
+ VCPU_REGS_RCX = 1,
+ VCPU_REGS_RDX = 2,
+ VCPU_REGS_RBX = 3,
+ VCPU_REGS_RSP = 4,
+ VCPU_REGS_RBP = 5,
+ VCPU_REGS_RSI = 6,
+ VCPU_REGS_RDI = 7,
+#ifdef CONFIG_X86_64
+ VCPU_REGS_R8 = 8,
+ VCPU_REGS_R9 = 9,
+ VCPU_REGS_R10 = 10,
+ VCPU_REGS_R11 = 11,
+ VCPU_REGS_R12 = 12,
+ VCPU_REGS_R13 = 13,
+ VCPU_REGS_R14 = 14,
+ VCPU_REGS_R15 = 15,
+#endif
+ NR_VCPU_REGS
+};
+
+enum {
+ VCPU_SREG_CS,
+ VCPU_SREG_DS,
+ VCPU_SREG_ES,
+ VCPU_SREG_FS,
+ VCPU_SREG_GS,
+ VCPU_SREG_SS,
+ VCPU_SREG_TR,
+ VCPU_SREG_LDTR,
+};
+
+struct kvm_vcpu {
+ struct kvm *kvm;
+ union {
+ struct vmcs *vmcs;
+ struct vcpu_svm *svm;
+ };
+ struct mutex mutex;
+ int cpu;
+ int launched;
+ int interrupt_window_open;
+ unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
+#define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long)
+ unsigned long irq_pending[NR_IRQ_WORDS];
+ unsigned long regs[NR_VCPU_REGS]; /* for rsp: vcpu_load_rsp_rip() */
+ unsigned long rip; /* needs vcpu_load_rsp_rip() */
+
+ unsigned long cr0;
+ unsigned long cr2;
+ unsigned long cr3;
+ unsigned long cr4;
+ unsigned long cr8;
+ u64 pdptrs[4]; /* pae */
+ u64 shadow_efer;
+ u64 apic_base;
+ u64 ia32_misc_enable_msr;
+ int nmsrs;
+ struct vmx_msr_entry *guest_msrs;
+ struct vmx_msr_entry *host_msrs;
+
+ struct list_head free_pages;
+ struct kvm_mmu_page page_header_buf[KVM_NUM_MMU_PAGES];
+ struct kvm_mmu mmu;
+
+ struct kvm_mmu_memory_cache mmu_pte_chain_cache;
+ struct kvm_mmu_memory_cache mmu_rmap_desc_cache;
+
+ gfn_t last_pt_write_gfn;
+ int last_pt_write_count;
+
+ struct kvm_guest_debug guest_debug;
+
+ char fx_buf[FX_BUF_SIZE];
+ char *host_fx_image;
+ char *guest_fx_image;
+
+ int mmio_needed;
+ int mmio_read_completed;
+ int mmio_is_write;
+ int mmio_size;
+ unsigned char mmio_data[8];
+ gpa_t mmio_phys_addr;
+
+ struct {
+ int active;
+ u8 save_iopl;
+ struct kvm_save_segment {
+ u16 selector;
+ unsigned long base;
+ u32 limit;
+ u32 ar;
+ } tr, es, ds, fs, gs;
+ } rmode;
+};
+
+struct kvm_memory_slot {
+ gfn_t base_gfn;
+ unsigned long npages;
+ unsigned long flags;
+ struct page **phys_mem;
+ unsigned long *dirty_bitmap;
+};
+
+struct kvm {
+ spinlock_t lock; /* protects everything except vcpus */
+ int nmemslots;
+ struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS];
+ /*
+ * Hash table of struct kvm_mmu_page.
+ */
+ struct list_head active_mmu_pages;
+ int n_free_mmu_pages;
+ struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
+ struct kvm_vcpu vcpus[KVM_MAX_VCPUS];
+ int memory_config_version;
+ int busy;
+ unsigned long rmap_overflow;
+};
+
+struct kvm_stat {
+ u32 pf_fixed;
+ u32 pf_guest;
+ u32 tlb_flush;
+ u32 invlpg;
+
+ u32 exits;
+ u32 io_exits;
+ u32 mmio_exits;
+ u32 signal_exits;
+ u32 irq_window_exits;
+ u32 halt_exits;
+ u32 request_irq_exits;
+ u32 irq_exits;
+};
+
+struct descriptor_table {
+ u16 limit;
+ unsigned long base;
+} __attribute__((packed));
+
+struct kvm_arch_ops {
+ int (*cpu_has_kvm_support)(void); /* __init */
+ int (*disabled_by_bios)(void); /* __init */
+ void (*hardware_enable)(void *dummy); /* __init */
+ void (*hardware_disable)(void *dummy);
+ int (*hardware_setup)(void); /* __init */
+ void (*hardware_unsetup)(void); /* __exit */
+
+ int (*vcpu_create)(struct kvm_vcpu *vcpu);
+ void (*vcpu_free)(struct kvm_vcpu *vcpu);
+
+ struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu);
+ void (*vcpu_put)(struct kvm_vcpu *vcpu);
+
+ int (*set_guest_debug)(struct kvm_vcpu *vcpu,
+ struct kvm_debug_guest *dbg);
+ int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
+ int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data);
+ u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
+ void (*get_segment)(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg);
+ void (*set_segment)(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg);
+ void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
+ void (*decache_cr0_cr4_guest_bits)(struct kvm_vcpu *vcpu);
+ void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
+ void (*set_cr0_no_modeswitch)(struct kvm_vcpu *vcpu,
+ unsigned long cr0);
+ void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
+ void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
+ void (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
+ void (*get_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+ void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+ void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+ void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
+ unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr);
+ void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value,
+ int *exception);
+ void (*cache_regs)(struct kvm_vcpu *vcpu);
+ void (*decache_regs)(struct kvm_vcpu *vcpu);
+ unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
+ void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
+
+ void (*invlpg)(struct kvm_vcpu *vcpu, gva_t addr);
+ void (*tlb_flush)(struct kvm_vcpu *vcpu);
+ void (*inject_page_fault)(struct kvm_vcpu *vcpu,
+ unsigned long addr, u32 err_code);
+
+ void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code);
+
+ int (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run);
+ int (*vcpu_setup)(struct kvm_vcpu *vcpu);
+ void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+};
+
+extern struct kvm_stat kvm_stat;
+extern struct kvm_arch_ops *kvm_arch_ops;
+
+#define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt)
+#define vcpu_printf(vcpu, fmt...) kvm_printf(vcpu->kvm, fmt)
+
+int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module);
+void kvm_exit_arch(void);
+
+void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
+int kvm_mmu_create(struct kvm_vcpu *vcpu);
+int kvm_mmu_setup(struct kvm_vcpu *vcpu);
+
+int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
+void kvm_mmu_slot_remove_write_access(struct kvm_vcpu *vcpu, int slot);
+
+hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa);
+#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
+#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
+static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
+hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva);
+
+void kvm_emulator_want_group7_invlpg(void);
+
+extern hpa_t bad_page_address;
+
+static inline struct page *gfn_to_page(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+ return slot->phys_mem[gfn - slot->base_gfn];
+}
+
+struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
+void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
+
+enum emulation_result {
+ EMULATE_DONE, /* no further processing */
+ EMULATE_DO_MMIO, /* kvm_run filled with mmio request */
+ EMULATE_FAIL, /* can't emulate this instruction */
+};
+
+int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
+ unsigned long cr2, u16 error_code);
+void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
+void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
+void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
+ unsigned long *rflags);
+
+unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr);
+void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
+ unsigned long *rflags);
+
+struct x86_emulate_ctxt;
+
+int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
+int emulate_clts(struct kvm_vcpu *vcpu);
+int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
+ unsigned long *dest);
+int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr,
+ unsigned long value);
+
+void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
+void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr0);
+void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr0);
+void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr0);
+void lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
+
+int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
+int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
+
+void fx_init(struct kvm_vcpu *vcpu);
+
+void load_msrs(struct vmx_msr_entry *e, int n);
+void save_msrs(struct vmx_msr_entry *e, int n);
+void kvm_resched(struct kvm_vcpu *vcpu);
+
+int kvm_read_guest(struct kvm_vcpu *vcpu,
+ gva_t addr,
+ unsigned long size,
+ void *dest);
+
+int kvm_write_guest(struct kvm_vcpu *vcpu,
+ gva_t addr,
+ unsigned long size,
+ void *data);
+
+unsigned long segment_base(u16 selector);
+
+void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
+void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
+int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
+void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
+
+static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
+ u32 error_code)
+{
+ if (unlikely(vcpu->kvm->n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
+ kvm_mmu_free_some_pages(vcpu);
+ return vcpu->mmu.page_fault(vcpu, gva, error_code);
+}
+
+static inline struct page *_gfn_to_page(struct kvm *kvm, gfn_t gfn)
+{
+ struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
+ return (slot) ? slot->phys_mem[gfn - slot->base_gfn] : NULL;
+}
+
+static inline int is_long_mode(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_X86_64
+ return vcpu->shadow_efer & EFER_LME;
+#else
+ return 0;
+#endif
+}
+
+static inline int is_pae(struct kvm_vcpu *vcpu)
+{
+ return vcpu->cr4 & CR4_PAE_MASK;
+}
+
+static inline int is_pse(struct kvm_vcpu *vcpu)
+{
+ return vcpu->cr4 & CR4_PSE_MASK;
+}
+
+static inline int is_paging(struct kvm_vcpu *vcpu)
+{
+ return vcpu->cr0 & CR0_PG_MASK;
+}
+
+static inline int memslot_id(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+ return slot - kvm->memslots;
+}
+
+static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
+{
+ struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT);
+
+ return (struct kvm_mmu_page *)page->private;
+}
+
+static inline u16 read_fs(void)
+{
+ u16 seg;
+ asm ("mov %%fs, %0" : "=g"(seg));
+ return seg;
+}
+
+static inline u16 read_gs(void)
+{
+ u16 seg;
+ asm ("mov %%gs, %0" : "=g"(seg));
+ return seg;
+}
+
+static inline u16 read_ldt(void)
+{
+ u16 ldt;
+ asm ("sldt %0" : "=g"(ldt));
+ return ldt;
+}
+
+static inline void load_fs(u16 sel)
+{
+ asm ("mov %0, %%fs" : : "rm"(sel));
+}
+
+static inline void load_gs(u16 sel)
+{
+ asm ("mov %0, %%gs" : : "rm"(sel));
+}
+
+#ifndef load_ldt
+static inline void load_ldt(u16 sel)
+{
+ asm ("lldt %0" : : "g"(sel));
+}
+#endif
+
+static inline void get_idt(struct descriptor_table *table)
+{
+ asm ("sidt %0" : "=m"(*table));
+}
+
+static inline void get_gdt(struct descriptor_table *table)
+{
+ asm ("sgdt %0" : "=m"(*table));
+}
+
+static inline unsigned long read_tr_base(void)
+{
+ u16 tr;
+ asm ("str %0" : "=g"(tr));
+ return segment_base(tr);
+}
+
+#ifdef CONFIG_X86_64
+static inline unsigned long read_msr(unsigned long msr)
+{
+ u64 value;
+
+ rdmsrl(msr, value);
+ return value;
+}
+#endif
+
+static inline void fx_save(void *image)
+{
+ asm ("fxsave (%0)":: "r" (image));
+}
+
+static inline void fx_restore(void *image)
+{
+ asm ("fxrstor (%0)":: "r" (image));
+}
+
+static inline void fpu_init(void)
+{
+ asm ("finit");
+}
+
+static inline u32 get_rdx_init_val(void)
+{
+ return 0x600; /* P6 family */
+}
+
+#define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2"
+#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3"
+#define ASM_VMX_VMPTRLD_RAX ".byte 0x0f, 0xc7, 0x30"
+#define ASM_VMX_VMREAD_RDX_RAX ".byte 0x0f, 0x78, 0xd0"
+#define ASM_VMX_VMWRITE_RAX_RDX ".byte 0x0f, 0x79, 0xd0"
+#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4"
+#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4"
+#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30"
+
+#define MSR_IA32_TIME_STAMP_COUNTER 0x010
+
+#define TSS_IOPB_BASE_OFFSET 0x66
+#define TSS_BASE_SIZE 0x68
+#define TSS_IOPB_SIZE (65536 / 8)
+#define TSS_REDIRECTION_SIZE (256 / 8)
+#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
+
+#endif
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
new file mode 100644
index 00000000000..b10972ed0c9
--- /dev/null
+++ b/drivers/kvm/kvm_main.c
@@ -0,0 +1,2136 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "kvm.h"
+
+#include <linux/kvm.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <linux/percpu.h>
+#include <linux/gfp.h>
+#include <asm/msr.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <linux/reboot.h>
+#include <asm/io.h>
+#include <linux/debugfs.h>
+#include <linux/highmem.h>
+#include <linux/file.h>
+#include <asm/desc.h>
+
+#include "x86_emulate.h"
+#include "segment_descriptor.h"
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+struct kvm_arch_ops *kvm_arch_ops;
+struct kvm_stat kvm_stat;
+EXPORT_SYMBOL_GPL(kvm_stat);
+
+static struct kvm_stats_debugfs_item {
+ const char *name;
+ u32 *data;
+ struct dentry *dentry;
+} debugfs_entries[] = {
+ { "pf_fixed", &kvm_stat.pf_fixed },
+ { "pf_guest", &kvm_stat.pf_guest },
+ { "tlb_flush", &kvm_stat.tlb_flush },
+ { "invlpg", &kvm_stat.invlpg },
+ { "exits", &kvm_stat.exits },
+ { "io_exits", &kvm_stat.io_exits },
+ { "mmio_exits", &kvm_stat.mmio_exits },
+ { "signal_exits", &kvm_stat.signal_exits },
+ { "irq_window", &kvm_stat.irq_window_exits },
+ { "halt_exits", &kvm_stat.halt_exits },
+ { "request_irq", &kvm_stat.request_irq_exits },
+ { "irq_exits", &kvm_stat.irq_exits },
+ { 0, 0 }
+};
+
+static struct dentry *debugfs_dir;
+
+#define MAX_IO_MSRS 256
+
+#define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL
+#define LMSW_GUEST_MASK 0x0eULL
+#define CR4_RESEVED_BITS (~((1ULL << 11) - 1))
+#define CR8_RESEVED_BITS (~0x0fULL)
+#define EFER_RESERVED_BITS 0xfffffffffffff2fe
+
+#ifdef CONFIG_X86_64
+// LDT or TSS descriptor in the GDT. 16 bytes.
+struct segment_descriptor_64 {
+ struct segment_descriptor s;
+ u32 base_higher;
+ u32 pad_zero;
+};
+
+#endif
+
+unsigned long segment_base(u16 selector)
+{
+ struct descriptor_table gdt;
+ struct segment_descriptor *d;
+ unsigned long table_base;
+ typedef unsigned long ul;
+ unsigned long v;
+
+ if (selector == 0)
+ return 0;
+
+ asm ("sgdt %0" : "=m"(gdt));
+ table_base = gdt.base;
+
+ if (selector & 4) { /* from ldt */
+ u16 ldt_selector;
+
+ asm ("sldt %0" : "=g"(ldt_selector));
+ table_base = segment_base(ldt_selector);
+ }
+ d = (struct segment_descriptor *)(table_base + (selector & ~7));
+ v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24);
+#ifdef CONFIG_X86_64
+ if (d->system == 0
+ && (d->type == 2 || d->type == 9 || d->type == 11))
+ v |= ((ul)((struct segment_descriptor_64 *)d)->base_higher) << 32;
+#endif
+ return v;
+}
+EXPORT_SYMBOL_GPL(segment_base);
+
+static inline int valid_vcpu(int n)
+{
+ return likely(n >= 0 && n < KVM_MAX_VCPUS);
+}
+
+int kvm_read_guest(struct kvm_vcpu *vcpu,
+ gva_t addr,
+ unsigned long size,
+ void *dest)
+{
+ unsigned char *host_buf = dest;
+ unsigned long req_size = size;
+
+ while (size) {
+ hpa_t paddr;
+ unsigned now;
+ unsigned offset;
+ hva_t guest_buf;
+
+ paddr = gva_to_hpa(vcpu, addr);
+
+ if (is_error_hpa(paddr))
+ break;
+
+ guest_buf = (hva_t)kmap_atomic(
+ pfn_to_page(paddr >> PAGE_SHIFT),
+ KM_USER0);
+ offset = addr & ~PAGE_MASK;
+ guest_buf |= offset;
+ now = min(size, PAGE_SIZE - offset);
+ memcpy(host_buf, (void*)guest_buf, now);
+ host_buf += now;
+ addr += now;
+ size -= now;
+ kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0);
+ }
+ return req_size - size;
+}
+EXPORT_SYMBOL_GPL(kvm_read_guest);
+
+int kvm_write_guest(struct kvm_vcpu *vcpu,
+ gva_t addr,
+ unsigned long size,
+ void *data)
+{
+ unsigned char *host_buf = data;
+ unsigned long req_size = size;
+
+ while (size) {
+ hpa_t paddr;
+ unsigned now;
+ unsigned offset;
+ hva_t guest_buf;
+
+ paddr = gva_to_hpa(vcpu, addr);
+
+ if (is_error_hpa(paddr))
+ break;
+
+ guest_buf = (hva_t)kmap_atomic(
+ pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0);
+ offset = addr & ~PAGE_MASK;
+ guest_buf |= offset;
+ now = min(size, PAGE_SIZE - offset);
+ memcpy((void*)guest_buf, host_buf, now);
+ host_buf += now;
+ addr += now;
+ size -= now;
+ kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0);
+ }
+ return req_size - size;
+}
+EXPORT_SYMBOL_GPL(kvm_write_guest);
+
+static int vcpu_slot(struct kvm_vcpu *vcpu)
+{
+ return vcpu - vcpu->kvm->vcpus;
+}
+
+/*
+ * Switches to specified vcpu, until a matching vcpu_put()
+ */
+static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot)
+{
+ struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot];
+
+ mutex_lock(&vcpu->mutex);
+ if (unlikely(!vcpu->vmcs)) {
+ mutex_unlock(&vcpu->mutex);
+ return 0;
+ }
+ return kvm_arch_ops->vcpu_load(vcpu);
+}
+
+static void vcpu_put(struct kvm_vcpu *vcpu)
+{
+ kvm_arch_ops->vcpu_put(vcpu);
+ mutex_unlock(&vcpu->mutex);
+}
+
+static int kvm_dev_open(struct inode *inode, struct file *filp)
+{
+ struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
+ int i;
+
+ if (!kvm)
+ return -ENOMEM;
+
+ spin_lock_init(&kvm->lock);
+ INIT_LIST_HEAD(&kvm->active_mmu_pages);
+ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+ struct kvm_vcpu *vcpu = &kvm->vcpus[i];
+
+ mutex_init(&vcpu->mutex);
+ vcpu->kvm = kvm;
+ vcpu->mmu.root_hpa = INVALID_PAGE;
+ INIT_LIST_HEAD(&vcpu->free_pages);
+ }
+ filp->private_data = kvm;
+ return 0;
+}
+
+/*
+ * Free any memory in @free but not in @dont.
+ */
+static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
+ struct kvm_memory_slot *dont)
+{
+ int i;
+
+ if (!dont || free->phys_mem != dont->phys_mem)
+ if (free->phys_mem) {
+ for (i = 0; i < free->npages; ++i)
+ if (free->phys_mem[i])
+ __free_page(free->phys_mem[i]);
+ vfree(free->phys_mem);
+ }
+
+ if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
+ vfree(free->dirty_bitmap);
+
+ free->phys_mem = 0;
+ free->npages = 0;
+ free->dirty_bitmap = 0;
+}
+
+static void kvm_free_physmem(struct kvm *kvm)
+{
+ int i;
+
+ for (i = 0; i < kvm->nmemslots; ++i)
+ kvm_free_physmem_slot(&kvm->memslots[i], 0);
+}
+
+static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
+{
+ vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
+ kvm_mmu_destroy(vcpu);
+ vcpu_put(vcpu);
+ kvm_arch_ops->vcpu_free(vcpu);
+}
+
+static void kvm_free_vcpus(struct kvm *kvm)
+{
+ unsigned int i;
+
+ for (i = 0; i < KVM_MAX_VCPUS; ++i)
+ kvm_free_vcpu(&kvm->vcpus[i]);
+}
+
+static int kvm_dev_release(struct inode *inode, struct file *filp)
+{
+ struct kvm *kvm = filp->private_data;
+
+ kvm_free_vcpus(kvm);
+ kvm_free_physmem(kvm);
+ kfree(kvm);
+ return 0;
+}
+
+static void inject_gp(struct kvm_vcpu *vcpu)
+{
+ kvm_arch_ops->inject_gp(vcpu, 0);
+}
+
+/*
+ * Load the pae pdptrs. Return true is they are all valid.
+ */
+static int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+ gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT;
+ unsigned offset = ((cr3 & (PAGE_SIZE-1)) >> 5) << 2;
+ int i;
+ u64 pdpte;
+ u64 *pdpt;
+ int ret;
+ struct kvm_memory_slot *memslot;
+
+ spin_lock(&vcpu->kvm->lock);
+ memslot = gfn_to_memslot(vcpu->kvm, pdpt_gfn);
+ /* FIXME: !memslot - emulate? 0xff? */
+ pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0);
+
+ ret = 1;
+ for (i = 0; i < 4; ++i) {
+ pdpte = pdpt[offset + i];
+ if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull)) {
+ ret = 0;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < 4; ++i)
+ vcpu->pdptrs[i] = pdpt[offset + i];
+
+out:
+ kunmap_atomic(pdpt, KM_USER0);
+ spin_unlock(&vcpu->kvm->lock);
+
+ return ret;
+}
+
+void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+ if (cr0 & CR0_RESEVED_BITS) {
+ printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
+ cr0, vcpu->cr0);
+ inject_gp(vcpu);
+ return;
+ }
+
+ if ((cr0 & CR0_NW_MASK) && !(cr0 & CR0_CD_MASK)) {
+ printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n");
+ inject_gp(vcpu);
+ return;
+ }
+
+ if ((cr0 & CR0_PG_MASK) && !(cr0 & CR0_PE_MASK)) {
+ printk(KERN_DEBUG "set_cr0: #GP, set PG flag "
+ "and a clear PE flag\n");
+ inject_gp(vcpu);
+ return;
+ }
+
+ if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
+#ifdef CONFIG_X86_64
+ if ((vcpu->shadow_efer & EFER_LME)) {
+ int cs_db, cs_l;
+
+ if (!is_pae(vcpu)) {
+ printk(KERN_DEBUG "set_cr0: #GP, start paging "
+ "in long mode while PAE is disabled\n");
+ inject_gp(vcpu);
+ return;
+ }
+ kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+ if (cs_l) {
+ printk(KERN_DEBUG "set_cr0: #GP, start paging "
+ "in long mode while CS.L == 1\n");
+ inject_gp(vcpu);
+ return;
+
+ }
+ } else
+#endif
+ if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->cr3)) {
+ printk(KERN_DEBUG "set_cr0: #GP, pdptrs "
+ "reserved bits\n");
+ inject_gp(vcpu);
+ return;
+ }
+
+ }
+
+ kvm_arch_ops->set_cr0(vcpu, cr0);
+ vcpu->cr0 = cr0;
+
+ spin_lock(&vcpu->kvm->lock);
+ kvm_mmu_reset_context(vcpu);
+ spin_unlock(&vcpu->kvm->lock);
+ return;
+}
+EXPORT_SYMBOL_GPL(set_cr0);
+
+void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
+{
+ kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+ set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f));
+}
+EXPORT_SYMBOL_GPL(lmsw);
+
+void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+ if (cr4 & CR4_RESEVED_BITS) {
+ printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n");
+ inject_gp(vcpu);
+ return;
+ }
+
+ if (is_long_mode(vcpu)) {
+ if (!(cr4 & CR4_PAE_MASK)) {
+ printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while "
+ "in long mode\n");
+ inject_gp(vcpu);
+ return;
+ }
+ } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK)
+ && !load_pdptrs(vcpu, vcpu->cr3)) {
+ printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n");
+ inject_gp(vcpu);
+ }
+
+ if (cr4 & CR4_VMXE_MASK) {
+ printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n");
+ inject_gp(vcpu);
+ return;
+ }
+ kvm_arch_ops->set_cr4(vcpu, cr4);
+ spin_lock(&vcpu->kvm->lock);
+ kvm_mmu_reset_context(vcpu);
+ spin_unlock(&vcpu->kvm->lock);
+}
+EXPORT_SYMBOL_GPL(set_cr4);
+
+void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+ if (is_long_mode(vcpu)) {
+ if ( cr3 & CR3_L_MODE_RESEVED_BITS) {
+ printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
+ inject_gp(vcpu);
+ return;
+ }
+ } else {
+ if (cr3 & CR3_RESEVED_BITS) {
+ printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
+ inject_gp(vcpu);
+ return;
+ }
+ if (is_paging(vcpu) && is_pae(vcpu) &&
+ !load_pdptrs(vcpu, cr3)) {
+ printk(KERN_DEBUG "set_cr3: #GP, pdptrs "
+ "reserved bits\n");
+ inject_gp(vcpu);
+ return;
+ }
+ }
+
+ vcpu->cr3 = cr3;
+ spin_lock(&vcpu->kvm->lock);
+ /*
+ * Does the new cr3 value map to physical memory? (Note, we
+ * catch an invalid cr3 even in real-mode, because it would
+ * cause trouble later on when we turn on paging anyway.)
+ *
+ * A real CPU would silently accept an invalid cr3 and would
+ * attempt to use it - with largely undefined (and often hard
+ * to debug) behavior on the guest side.
+ */
+ if (unlikely(!gfn_to_memslot(vcpu->kvm, cr3 >> PAGE_SHIFT)))
+ inject_gp(vcpu);
+ else
+ vcpu->mmu.new_cr3(vcpu);
+ spin_unlock(&vcpu->kvm->lock);
+}
+EXPORT_SYMBOL_GPL(set_cr3);
+
+void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+{
+ if ( cr8 & CR8_RESEVED_BITS) {
+ printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8);
+ inject_gp(vcpu);
+ return;
+ }
+ vcpu->cr8 = cr8;
+}
+EXPORT_SYMBOL_GPL(set_cr8);
+
+void fx_init(struct kvm_vcpu *vcpu)
+{
+ struct __attribute__ ((__packed__)) fx_image_s {
+ u16 control; //fcw
+ u16 status; //fsw
+ u16 tag; // ftw
+ u16 opcode; //fop
+ u64 ip; // fpu ip
+ u64 operand;// fpu dp
+ u32 mxcsr;
+ u32 mxcsr_mask;
+
+ } *fx_image;
+
+ fx_save(vcpu->host_fx_image);
+ fpu_init();
+ fx_save(vcpu->guest_fx_image);
+ fx_restore(vcpu->host_fx_image);
+
+ fx_image = (struct fx_image_s *)vcpu->guest_fx_image;
+ fx_image->mxcsr = 0x1f80;
+ memset(vcpu->guest_fx_image + sizeof(struct fx_image_s),
+ 0, FX_IMAGE_SIZE - sizeof(struct fx_image_s));
+}
+EXPORT_SYMBOL_GPL(fx_init);
+
+/*
+ * Creates some virtual cpus. Good luck creating more than one.
+ */
+static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n)
+{
+ int r;
+ struct kvm_vcpu *vcpu;
+
+ r = -EINVAL;
+ if (!valid_vcpu(n))
+ goto out;
+
+ vcpu = &kvm->vcpus[n];
+
+ mutex_lock(&vcpu->mutex);
+
+ if (vcpu->vmcs) {
+ mutex_unlock(&vcpu->mutex);
+ return -EEXIST;
+ }
+
+ vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf,
+ FX_IMAGE_ALIGN);
+ vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
+
+ vcpu->cpu = -1; /* First load will set up TR */
+ r = kvm_arch_ops->vcpu_create(vcpu);
+ if (r < 0)
+ goto out_free_vcpus;
+
+ r = kvm_mmu_create(vcpu);
+ if (r < 0)
+ goto out_free_vcpus;
+
+ kvm_arch_ops->vcpu_load(vcpu);
+ r = kvm_mmu_setup(vcpu);
+ if (r >= 0)
+ r = kvm_arch_ops->vcpu_setup(vcpu);
+ vcpu_put(vcpu);
+
+ if (r < 0)
+ goto out_free_vcpus;
+
+ return 0;
+
+out_free_vcpus:
+ kvm_free_vcpu(vcpu);
+ mutex_unlock(&vcpu->mutex);
+out:
+ return r;
+}
+
+/*
+ * Allocate some memory and give it an address in the guest physical address
+ * space.
+ *
+ * Discontiguous memory is allowed, mostly for framebuffers.
+ */
+static int kvm_dev_ioctl_set_memory_region(struct kvm *kvm,
+ struct kvm_memory_region *mem)
+{
+ int r;
+ gfn_t base_gfn;
+ unsigned long npages;
+ unsigned long i;
+ struct kvm_memory_slot *memslot;
+ struct kvm_memory_slot old, new;
+ int memory_config_version;
+
+ r = -EINVAL;
+ /* General sanity checks */
+ if (mem->memory_size & (PAGE_SIZE - 1))
+ goto out;
+ if (mem->guest_phys_addr & (PAGE_SIZE - 1))
+ goto out;
+ if (mem->slot >= KVM_MEMORY_SLOTS)
+ goto out;
+ if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr)
+ goto out;
+
+ memslot = &kvm->memslots[mem->slot];
+ base_gfn = mem->guest_phys_addr >> PAGE_SHIFT;
+ npages = mem->memory_size >> PAGE_SHIFT;
+
+ if (!npages)
+ mem->flags &= ~KVM_MEM_LOG_DIRTY_PAGES;
+
+raced:
+ spin_lock(&kvm->lock);
+
+ memory_config_version = kvm->memory_config_version;
+ new = old = *memslot;
+
+ new.base_gfn = base_gfn;
+ new.npages = npages;
+ new.flags = mem->flags;
+
+ /* Disallow changing a memory slot's size. */
+ r = -EINVAL;
+ if (npages && old.npages && npages != old.npages)
+ goto out_unlock;
+
+ /* Check for overlaps */
+ r = -EEXIST;
+ for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
+ struct kvm_memory_slot *s = &kvm->memslots[i];
+
+ if (s == memslot)
+ continue;
+ if (!((base_gfn + npages <= s->base_gfn) ||
+ (base_gfn >= s->base_gfn + s->npages)))
+ goto out_unlock;
+ }
+ /*
+ * Do memory allocations outside lock. memory_config_version will
+ * detect any races.
+ */
+ spin_unlock(&kvm->lock);
+
+ /* Deallocate if slot is being removed */
+ if (!npages)
+ new.phys_mem = 0;
+
+ /* Free page dirty bitmap if unneeded */
+ if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES))
+ new.dirty_bitmap = 0;
+
+ r = -ENOMEM;
+
+ /* Allocate if a slot is being created */
+ if (npages && !new.phys_mem) {
+ new.phys_mem = vmalloc(npages * sizeof(struct page *));
+
+ if (!new.phys_mem)
+ goto out_free;
+
+ memset(new.phys_mem, 0, npages * sizeof(struct page *));
+ for (i = 0; i < npages; ++i) {
+ new.phys_mem[i] = alloc_page(GFP_HIGHUSER
+ | __GFP_ZERO);
+ if (!new.phys_mem[i])
+ goto out_free;
+ new.phys_mem[i]->private = 0;
+ }
+ }
+
+ /* Allocate page dirty bitmap if needed */
+ if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
+ unsigned dirty_bytes = ALIGN(npages, BITS_PER_LONG) / 8;
+
+ new.dirty_bitmap = vmalloc(dirty_bytes);
+ if (!new.dirty_bitmap)
+ goto out_free;
+ memset(new.dirty_bitmap, 0, dirty_bytes);
+ }
+
+ spin_lock(&kvm->lock);
+
+ if (memory_config_version != kvm->memory_config_version) {
+ spin_unlock(&kvm->lock);
+ kvm_free_physmem_slot(&new, &old);
+ goto raced;
+ }
+
+ r = -EAGAIN;
+ if (kvm->busy)
+ goto out_unlock;
+
+ if (mem->slot >= kvm->nmemslots)
+ kvm->nmemslots = mem->slot + 1;
+
+ *memslot = new;
+ ++kvm->memory_config_version;
+
+ spin_unlock(&kvm->lock);
+
+ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+ struct kvm_vcpu *vcpu;
+
+ vcpu = vcpu_load(kvm, i);
+ if (!vcpu)
+ continue;
+ kvm_mmu_reset_context(vcpu);
+ vcpu_put(vcpu);
+ }
+
+ kvm_free_physmem_slot(&old, &new);
+ return 0;
+
+out_unlock:
+ spin_unlock(&kvm->lock);
+out_free:
+ kvm_free_physmem_slot(&new, &old);
+out:
+ return r;
+}
+
+static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot)
+{
+ spin_lock(&vcpu->kvm->lock);
+ kvm_mmu_slot_remove_write_access(vcpu, slot);
+ spin_unlock(&vcpu->kvm->lock);
+}
+
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm,
+ struct kvm_dirty_log *log)
+{
+ struct kvm_memory_slot *memslot;
+ int r, i;
+ int n;
+ int cleared;
+ unsigned long any = 0;
+
+ spin_lock(&kvm->lock);
+
+ /*
+ * Prevent changes to guest memory configuration even while the lock
+ * is not taken.
+ */
+ ++kvm->busy;
+ spin_unlock(&kvm->lock);
+ r = -EINVAL;
+ if (log->slot >= KVM_MEMORY_SLOTS)
+ goto out;
+
+ memslot = &kvm->memslots[log->slot];
+ r = -ENOENT;
+ if (!memslot->dirty_bitmap)
+ goto out;
+
+ n = ALIGN(memslot->npages, 8) / 8;
+
+ for (i = 0; !any && i < n; ++i)
+ any = memslot->dirty_bitmap[i];
+
+ r = -EFAULT;
+ if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
+ goto out;
+
+
+ if (any) {
+ cleared = 0;
+ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+ struct kvm_vcpu *vcpu = vcpu_load(kvm, i);
+
+ if (!vcpu)
+ continue;
+ if (!cleared) {
+ do_remove_write_access(vcpu, log->slot);
+ memset(memslot->dirty_bitmap, 0, n);
+ cleared = 1;
+ }
+ kvm_arch_ops->tlb_flush(vcpu);
+ vcpu_put(vcpu);
+ }
+ }
+
+ r = 0;
+
+out:
+ spin_lock(&kvm->lock);
+ --kvm->busy;
+ spin_unlock(&kvm->lock);
+ return r;
+}
+
+struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
+{
+ int i;
+
+ for (i = 0; i < kvm->nmemslots; ++i) {
+ struct kvm_memory_slot *memslot = &kvm->memslots[i];
+
+ if (gfn >= memslot->base_gfn
+ && gfn < memslot->base_gfn + memslot->npages)
+ return memslot;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gfn_to_memslot);
+
+void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
+{
+ int i;
+ struct kvm_memory_slot *memslot = 0;
+ unsigned long rel_gfn;
+
+ for (i = 0; i < kvm->nmemslots; ++i) {
+ memslot = &kvm->memslots[i];
+
+ if (gfn >= memslot->base_gfn
+ && gfn < memslot->base_gfn + memslot->npages) {
+
+ if (!memslot || !memslot->dirty_bitmap)
+ return;
+
+ rel_gfn = gfn - memslot->base_gfn;
+
+ /* avoid RMW */
+ if (!test_bit(rel_gfn, memslot->dirty_bitmap))
+ set_bit(rel_gfn, memslot->dirty_bitmap);
+ return;
+ }
+ }
+}
+
+static int emulator_read_std(unsigned long addr,
+ unsigned long *val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct kvm_vcpu *vcpu = ctxt->vcpu;
+ void *data = val;
+
+ while (bytes) {
+ gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+ unsigned offset = addr & (PAGE_SIZE-1);
+ unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset);
+ unsigned long pfn;
+ struct kvm_memory_slot *memslot;
+ void *page;
+
+ if (gpa == UNMAPPED_GVA)
+ return X86EMUL_PROPAGATE_FAULT;
+ pfn = gpa >> PAGE_SHIFT;
+ memslot = gfn_to_memslot(vcpu->kvm, pfn);
+ if (!memslot)
+ return X86EMUL_UNHANDLEABLE;
+ page = kmap_atomic(gfn_to_page(memslot, pfn), KM_USER0);
+
+ memcpy(data, page + offset, tocopy);
+
+ kunmap_atomic(page, KM_USER0);
+
+ bytes -= tocopy;
+ data += tocopy;
+ addr += tocopy;
+ }
+
+ return X86EMUL_CONTINUE;
+}
+
+static int emulator_write_std(unsigned long addr,
+ unsigned long val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ printk(KERN_ERR "emulator_write_std: addr %lx n %d\n",
+ addr, bytes);
+ return X86EMUL_UNHANDLEABLE;
+}
+
+static int emulator_read_emulated(unsigned long addr,
+ unsigned long *val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct kvm_vcpu *vcpu = ctxt->vcpu;
+
+ if (vcpu->mmio_read_completed) {
+ memcpy(val, vcpu->mmio_data, bytes);
+ vcpu->mmio_read_completed = 0;
+ return X86EMUL_CONTINUE;
+ } else if (emulator_read_std(addr, val, bytes, ctxt)
+ == X86EMUL_CONTINUE)
+ return X86EMUL_CONTINUE;
+ else {
+ gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+ if (gpa == UNMAPPED_GVA)
+ return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGATE_FAULT;
+ vcpu->mmio_needed = 1;
+ vcpu->mmio_phys_addr = gpa;
+ vcpu->mmio_size = bytes;
+ vcpu->mmio_is_write = 0;
+
+ return X86EMUL_UNHANDLEABLE;
+ }
+}
+
+static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+ unsigned long val, int bytes)
+{
+ struct kvm_memory_slot *m;
+ struct page *page;
+ void *virt;
+
+ if (((gpa + bytes - 1) >> PAGE_SHIFT) != (gpa >> PAGE_SHIFT))
+ return 0;
+ m = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
+ if (!m)
+ return 0;
+ page = gfn_to_page(m, gpa >> PAGE_SHIFT);
+ kvm_mmu_pre_write(vcpu, gpa, bytes);
+ virt = kmap_atomic(page, KM_USER0);
+ memcpy(virt + offset_in_page(gpa), &val, bytes);
+ kunmap_atomic(virt, KM_USER0);
+ kvm_mmu_post_write(vcpu, gpa, bytes);
+ return 1;
+}
+
+static int emulator_write_emulated(unsigned long addr,
+ unsigned long val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct kvm_vcpu *vcpu = ctxt->vcpu;
+ gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+
+ if (gpa == UNMAPPED_GVA)
+ return X86EMUL_PROPAGATE_FAULT;
+
+ if (emulator_write_phys(vcpu, gpa, val, bytes))
+ return X86EMUL_CONTINUE;
+
+ vcpu->mmio_needed = 1;
+ vcpu->mmio_phys_addr = gpa;
+ vcpu->mmio_size = bytes;
+ vcpu->mmio_is_write = 1;
+ memcpy(vcpu->mmio_data, &val, bytes);
+
+ return X86EMUL_CONTINUE;
+}
+
+static int emulator_cmpxchg_emulated(unsigned long addr,
+ unsigned long old,
+ unsigned long new,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt)
+{
+ static int reported;
+
+ if (!reported) {
+ reported = 1;
+ printk(KERN_WARNING "kvm: emulating exchange as write\n");
+ }
+ return emulator_write_emulated(addr, new, bytes, ctxt);
+}
+
+#ifdef CONFIG_X86_32
+
+static int emulator_cmpxchg8b_emulated(unsigned long addr,
+ unsigned long old_lo,
+ unsigned long old_hi,
+ unsigned long new_lo,
+ unsigned long new_hi,
+ struct x86_emulate_ctxt *ctxt)
+{
+ static int reported;
+ int r;
+
+ if (!reported) {
+ reported = 1;
+ printk(KERN_WARNING "kvm: emulating exchange8b as write\n");
+ }
+ r = emulator_write_emulated(addr, new_lo, 4, ctxt);
+ if (r != X86EMUL_CONTINUE)
+ return r;
+ return emulator_write_emulated(addr+4, new_hi, 4, ctxt);
+}
+
+#endif
+
+static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+ return kvm_arch_ops->get_segment_base(vcpu, seg);
+}
+
+int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)
+{
+ return X86EMUL_CONTINUE;
+}
+
+int emulate_clts(struct kvm_vcpu *vcpu)
+{
+ unsigned long cr0;
+
+ kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+ cr0 = vcpu->cr0 & ~CR0_TS_MASK;
+ kvm_arch_ops->set_cr0(vcpu, cr0);
+ return X86EMUL_CONTINUE;
+}
+
+int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, unsigned long *dest)
+{
+ struct kvm_vcpu *vcpu = ctxt->vcpu;
+
+ switch (dr) {
+ case 0 ... 3:
+ *dest = kvm_arch_ops->get_dr(vcpu, dr);
+ return X86EMUL_CONTINUE;
+ default:
+ printk(KERN_DEBUG "%s: unexpected dr %u\n",
+ __FUNCTION__, dr);
+ return X86EMUL_UNHANDLEABLE;
+ }
+}
+
+int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
+{
+ unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U;
+ int exception;
+
+ kvm_arch_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception);
+ if (exception) {
+ /* FIXME: better handling */
+ return X86EMUL_UNHANDLEABLE;
+ }
+ return X86EMUL_CONTINUE;
+}
+
+static void report_emulation_failure(struct x86_emulate_ctxt *ctxt)
+{
+ static int reported;
+ u8 opcodes[4];
+ unsigned long rip = ctxt->vcpu->rip;
+ unsigned long rip_linear;
+
+ rip_linear = rip + get_segment_base(ctxt->vcpu, VCPU_SREG_CS);
+
+ if (reported)
+ return;
+
+ emulator_read_std(rip_linear, (void *)opcodes, 4, ctxt);
+
+ printk(KERN_ERR "emulation failed but !mmio_needed?"
+ " rip %lx %02x %02x %02x %02x\n",
+ rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
+ reported = 1;
+}
+
+struct x86_emulate_ops emulate_ops = {
+ .read_std = emulator_read_std,
+ .write_std = emulator_write_std,
+ .read_emulated = emulator_read_emulated,
+ .write_emulated = emulator_write_emulated,
+ .cmpxchg_emulated = emulator_cmpxchg_emulated,
+#ifdef CONFIG_X86_32
+ .cmpxchg8b_emulated = emulator_cmpxchg8b_emulated,
+#endif
+};
+
+int emulate_instruction(struct kvm_vcpu *vcpu,
+ struct kvm_run *run,
+ unsigned long cr2,
+ u16 error_code)
+{
+ struct x86_emulate_ctxt emulate_ctxt;
+ int r;
+ int cs_db, cs_l;
+
+ kvm_arch_ops->cache_regs(vcpu);
+
+ kvm_arch_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+
+ emulate_ctxt.vcpu = vcpu;
+ emulate_ctxt.eflags = kvm_arch_ops->get_rflags(vcpu);
+ emulate_ctxt.cr2 = cr2;
+ emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM)
+ ? X86EMUL_MODE_REAL : cs_l
+ ? X86EMUL_MODE_PROT64 : cs_db
+ ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+
+ if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
+ emulate_ctxt.cs_base = 0;
+ emulate_ctxt.ds_base = 0;
+ emulate_ctxt.es_base = 0;
+ emulate_ctxt.ss_base = 0;
+ } else {
+ emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS);
+ emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS);
+ emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES);
+ emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS);
+ }
+
+ emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS);
+ emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS);
+
+ vcpu->mmio_is_write = 0;
+ r = x86_emulate_memop(&emulate_ctxt, &emulate_ops);
+
+ if ((r || vcpu->mmio_is_write) && run) {
+ run->mmio.phys_addr = vcpu->mmio_phys_addr;
+ memcpy(run->mmio.data, vcpu->mmio_data, 8);
+ run->mmio.len = vcpu->mmio_size;
+ run->mmio.is_write = vcpu->mmio_is_write;
+ }
+
+ if (r) {
+ if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
+ return EMULATE_DONE;
+ if (!vcpu->mmio_needed) {
+ report_emulation_failure(&emulate_ctxt);
+ return EMULATE_FAIL;
+ }
+ return EMULATE_DO_MMIO;
+ }
+
+ kvm_arch_ops->decache_regs(vcpu);
+ kvm_arch_ops->set_rflags(vcpu, emulate_ctxt.eflags);
+
+ if (vcpu->mmio_is_write)
+ return EMULATE_DO_MMIO;
+
+ return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(emulate_instruction);
+
+static u64 mk_cr_64(u64 curr_cr, u32 new_val)
+{
+ return (curr_cr & ~((1ULL << 32) - 1)) | new_val;
+}
+
+void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
+{
+ struct descriptor_table dt = { limit, base };
+
+ kvm_arch_ops->set_gdt(vcpu, &dt);
+}
+
+void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
+{
+ struct descriptor_table dt = { limit, base };
+
+ kvm_arch_ops->set_idt(vcpu, &dt);
+}
+
+void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
+ unsigned long *rflags)
+{
+ lmsw(vcpu, msw);
+ *rflags = kvm_arch_ops->get_rflags(vcpu);
+}
+
+unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
+{
+ kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+ switch (cr) {
+ case 0:
+ return vcpu->cr0;
+ case 2:
+ return vcpu->cr2;
+ case 3:
+ return vcpu->cr3;
+ case 4:
+ return vcpu->cr4;
+ default:
+ vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
+ return 0;
+ }
+}
+
+void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
+ unsigned long *rflags)
+{
+ switch (cr) {
+ case 0:
+ set_cr0(vcpu, mk_cr_64(vcpu->cr0, val));
+ *rflags = kvm_arch_ops->get_rflags(vcpu);
+ break;
+ case 2:
+ vcpu->cr2 = val;
+ break;
+ case 3:
+ set_cr3(vcpu, val);
+ break;
+ case 4:
+ set_cr4(vcpu, mk_cr_64(vcpu->cr4, val));
+ break;
+ default:
+ vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
+ }
+}
+
+int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+ u64 data;
+
+ switch (msr) {
+ case 0xc0010010: /* SYSCFG */
+ case 0xc0010015: /* HWCR */
+ case MSR_IA32_PLATFORM_ID:
+ case MSR_IA32_P5_MC_ADDR:
+ case MSR_IA32_P5_MC_TYPE:
+ case MSR_IA32_MC0_CTL:
+ case MSR_IA32_MCG_STATUS:
+ case MSR_IA32_MCG_CAP:
+ case MSR_IA32_MC0_MISC:
+ case MSR_IA32_MC0_MISC+4:
+ case MSR_IA32_MC0_MISC+8:
+ case MSR_IA32_MC0_MISC+12:
+ case MSR_IA32_MC0_MISC+16:
+ case MSR_IA32_UCODE_REV:
+ case MSR_IA32_PERF_STATUS:
+ /* MTRR registers */
+ case 0xfe:
+ case 0x200 ... 0x2ff:
+ data = 0;
+ break;
+ case 0xcd: /* fsb frequency */
+ data = 3;
+ break;
+ case MSR_IA32_APICBASE:
+ data = vcpu->apic_base;
+ break;
+ case MSR_IA32_MISC_ENABLE:
+ data = vcpu->ia32_misc_enable_msr;
+ break;
+#ifdef CONFIG_X86_64
+ case MSR_EFER:
+ data = vcpu->shadow_efer;
+ break;
+#endif
+ default:
+ printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", msr);
+ return 1;
+ }
+ *pdata = data;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_get_msr_common);
+
+/*
+ * Reads an msr value (of 'msr_index') into 'pdata'.
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+ return kvm_arch_ops->get_msr(vcpu, msr_index, pdata);
+}
+
+#ifdef CONFIG_X86_64
+
+static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+ if (efer & EFER_RESERVED_BITS) {
+ printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
+ efer);
+ inject_gp(vcpu);
+ return;
+ }
+
+ if (is_paging(vcpu)
+ && (vcpu->shadow_efer & EFER_LME) != (efer & EFER_LME)) {
+ printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n");
+ inject_gp(vcpu);
+ return;
+ }
+
+ kvm_arch_ops->set_efer(vcpu, efer);
+
+ efer &= ~EFER_LMA;
+ efer |= vcpu->shadow_efer & EFER_LMA;
+
+ vcpu->shadow_efer = efer;
+}
+
+#endif
+
+int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+ switch (msr) {
+#ifdef CONFIG_X86_64
+ case MSR_EFER:
+ set_efer(vcpu, data);
+ break;
+#endif
+ case MSR_IA32_MC0_STATUS:
+ printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n",
+ __FUNCTION__, data);
+ break;
+ case MSR_IA32_UCODE_REV:
+ case MSR_IA32_UCODE_WRITE:
+ case 0x200 ... 0x2ff: /* MTRRs */
+ break;
+ case MSR_IA32_APICBASE:
+ vcpu->apic_base = data;
+ break;
+ case MSR_IA32_MISC_ENABLE:
+ vcpu->ia32_misc_enable_msr = data;
+ break;
+ default:
+ printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr);
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_set_msr_common);
+
+/*
+ * Writes msr value into into the appropriate "register".
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+ return kvm_arch_ops->set_msr(vcpu, msr_index, data);
+}
+
+void kvm_resched(struct kvm_vcpu *vcpu)
+{
+ vcpu_put(vcpu);
+ cond_resched();
+ /* Cannot fail - no vcpu unplug yet. */
+ vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
+}
+EXPORT_SYMBOL_GPL(kvm_resched);
+
+void load_msrs(struct vmx_msr_entry *e, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ wrmsrl(e[i].index, e[i].data);
+}
+EXPORT_SYMBOL_GPL(load_msrs);
+
+void save_msrs(struct vmx_msr_entry *e, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ rdmsrl(e[i].index, e[i].data);
+}
+EXPORT_SYMBOL_GPL(save_msrs);
+
+static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run)
+{
+ struct kvm_vcpu *vcpu;
+ int r;
+
+ if (!valid_vcpu(kvm_run->vcpu))
+ return -EINVAL;
+
+ vcpu = vcpu_load(kvm, kvm_run->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ if (kvm_run->emulated) {
+ kvm_arch_ops->skip_emulated_instruction(vcpu);
+ kvm_run->emulated = 0;
+ }
+
+ if (kvm_run->mmio_completed) {
+ memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
+ vcpu->mmio_read_completed = 1;
+ }
+
+ vcpu->mmio_needed = 0;
+
+ r = kvm_arch_ops->run(vcpu, kvm_run);
+
+ vcpu_put(vcpu);
+ return r;
+}
+
+static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs)
+{
+ struct kvm_vcpu *vcpu;
+
+ if (!valid_vcpu(regs->vcpu))
+ return -EINVAL;
+
+ vcpu = vcpu_load(kvm, regs->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ kvm_arch_ops->cache_regs(vcpu);
+
+ regs->rax = vcpu->regs[VCPU_REGS_RAX];
+ regs->rbx = vcpu->regs[VCPU_REGS_RBX];
+ regs->rcx = vcpu->regs[VCPU_REGS_RCX];
+ regs->rdx = vcpu->regs[VCPU_REGS_RDX];
+ regs->rsi = vcpu->regs[VCPU_REGS_RSI];
+ regs->rdi = vcpu->regs[VCPU_REGS_RDI];
+ regs->rsp = vcpu->regs[VCPU_REGS_RSP];
+ regs->rbp = vcpu->regs[VCPU_REGS_RBP];
+#ifdef CONFIG_X86_64
+ regs->r8 = vcpu->regs[VCPU_REGS_R8];
+ regs->r9 = vcpu->regs[VCPU_REGS_R9];
+ regs->r10 = vcpu->regs[VCPU_REGS_R10];
+ regs->r11 = vcpu->regs[VCPU_REGS_R11];
+ regs->r12 = vcpu->regs[VCPU_REGS_R12];
+ regs->r13 = vcpu->regs[VCPU_REGS_R13];
+ regs->r14 = vcpu->regs[VCPU_REGS_R14];
+ regs->r15 = vcpu->regs[VCPU_REGS_R15];
+#endif
+
+ regs->rip = vcpu->rip;
+ regs->rflags = kvm_arch_ops->get_rflags(vcpu);
+
+ /*
+ * Don't leak debug flags in case they were set for guest debugging
+ */
+ if (vcpu->guest_debug.enabled && vcpu->guest_debug.singlestep)
+ regs->rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
+
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
+static int kvm_dev_ioctl_set_regs(struct kvm *kvm, struct kvm_regs *regs)
+{
+ struct kvm_vcpu *vcpu;
+
+ if (!valid_vcpu(regs->vcpu))
+ return -EINVAL;
+
+ vcpu = vcpu_load(kvm, regs->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ vcpu->regs[VCPU_REGS_RAX] = regs->rax;
+ vcpu->regs[VCPU_REGS_RBX] = regs->rbx;
+ vcpu->regs[VCPU_REGS_RCX] = regs->rcx;
+ vcpu->regs[VCPU_REGS_RDX] = regs->rdx;
+ vcpu->regs[VCPU_REGS_RSI] = regs->rsi;
+ vcpu->regs[VCPU_REGS_RDI] = regs->rdi;
+ vcpu->regs[VCPU_REGS_RSP] = regs->rsp;
+ vcpu->regs[VCPU_REGS_RBP] = regs->rbp;
+#ifdef CONFIG_X86_64
+ vcpu->regs[VCPU_REGS_R8] = regs->r8;
+ vcpu->regs[VCPU_REGS_R9] = regs->r9;
+ vcpu->regs[VCPU_REGS_R10] = regs->r10;
+ vcpu->regs[VCPU_REGS_R11] = regs->r11;
+ vcpu->regs[VCPU_REGS_R12] = regs->r12;
+ vcpu->regs[VCPU_REGS_R13] = regs->r13;
+ vcpu->regs[VCPU_REGS_R14] = regs->r14;
+ vcpu->regs[VCPU_REGS_R15] = regs->r15;
+#endif
+
+ vcpu->rip = regs->rip;
+ kvm_arch_ops->set_rflags(vcpu, regs->rflags);
+
+ kvm_arch_ops->decache_regs(vcpu);
+
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
+static void get_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ return kvm_arch_ops->get_segment(vcpu, var, seg);
+}
+
+static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
+{
+ struct kvm_vcpu *vcpu;
+ struct descriptor_table dt;
+
+ if (!valid_vcpu(sregs->vcpu))
+ return -EINVAL;
+ vcpu = vcpu_load(kvm, sregs->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ get_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
+ get_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
+ get_segment(vcpu, &sregs->es, VCPU_SREG_ES);
+ get_segment(vcpu, &sregs->fs, VCPU_SREG_FS);
+ get_segment(vcpu, &sregs->gs, VCPU_SREG_GS);
+ get_segment(vcpu, &sregs->ss, VCPU_SREG_SS);
+
+ get_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
+ get_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
+
+ kvm_arch_ops->get_idt(vcpu, &dt);
+ sregs->idt.limit = dt.limit;
+ sregs->idt.base = dt.base;
+ kvm_arch_ops->get_gdt(vcpu, &dt);
+ sregs->gdt.limit = dt.limit;
+ sregs->gdt.base = dt.base;
+
+ kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+ sregs->cr0 = vcpu->cr0;
+ sregs->cr2 = vcpu->cr2;
+ sregs->cr3 = vcpu->cr3;
+ sregs->cr4 = vcpu->cr4;
+ sregs->cr8 = vcpu->cr8;
+ sregs->efer = vcpu->shadow_efer;
+ sregs->apic_base = vcpu->apic_base;
+
+ memcpy(sregs->interrupt_bitmap, vcpu->irq_pending,
+ sizeof sregs->interrupt_bitmap);
+
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
+static void set_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ return kvm_arch_ops->set_segment(vcpu, var, seg);
+}
+
+static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
+{
+ struct kvm_vcpu *vcpu;
+ int mmu_reset_needed = 0;
+ int i;
+ struct descriptor_table dt;
+
+ if (!valid_vcpu(sregs->vcpu))
+ return -EINVAL;
+ vcpu = vcpu_load(kvm, sregs->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
+ set_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
+ set_segment(vcpu, &sregs->es, VCPU_SREG_ES);
+ set_segment(vcpu, &sregs->fs, VCPU_SREG_FS);
+ set_segment(vcpu, &sregs->gs, VCPU_SREG_GS);
+ set_segment(vcpu, &sregs->ss, VCPU_SREG_SS);
+
+ set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
+ set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
+
+ dt.limit = sregs->idt.limit;
+ dt.base = sregs->idt.base;
+ kvm_arch_ops->set_idt(vcpu, &dt);
+ dt.limit = sregs->gdt.limit;
+ dt.base = sregs->gdt.base;
+ kvm_arch_ops->set_gdt(vcpu, &dt);
+
+ vcpu->cr2 = sregs->cr2;
+ mmu_reset_needed |= vcpu->cr3 != sregs->cr3;
+ vcpu->cr3 = sregs->cr3;
+
+ vcpu->cr8 = sregs->cr8;
+
+ mmu_reset_needed |= vcpu->shadow_efer != sregs->efer;
+#ifdef CONFIG_X86_64
+ kvm_arch_ops->set_efer(vcpu, sregs->efer);
+#endif
+ vcpu->apic_base = sregs->apic_base;
+
+ kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+
+ mmu_reset_needed |= vcpu->cr0 != sregs->cr0;
+ kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0);
+
+ mmu_reset_needed |= vcpu->cr4 != sregs->cr4;
+ kvm_arch_ops->set_cr4(vcpu, sregs->cr4);
+ if (!is_long_mode(vcpu) && is_pae(vcpu))
+ load_pdptrs(vcpu, vcpu->cr3);
+
+ if (mmu_reset_needed)
+ kvm_mmu_reset_context(vcpu);
+
+ memcpy(vcpu->irq_pending, sregs->interrupt_bitmap,
+ sizeof vcpu->irq_pending);
+ vcpu->irq_summary = 0;
+ for (i = 0; i < NR_IRQ_WORDS; ++i)
+ if (vcpu->irq_pending[i])
+ __set_bit(i, &vcpu->irq_summary);
+
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
+/*
+ * List of msr numbers which we expose to userspace through KVM_GET_MSRS
+ * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
+ *
+ * This list is modified at module load time to reflect the
+ * capabilities of the host cpu.
+ */
+static u32 msrs_to_save[] = {
+ MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
+ MSR_K6_STAR,
+#ifdef CONFIG_X86_64
+ MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
+#endif
+ MSR_IA32_TIME_STAMP_COUNTER,
+};
+
+static unsigned num_msrs_to_save;
+
+static u32 emulated_msrs[] = {
+ MSR_IA32_MISC_ENABLE,
+};
+
+static __init void kvm_init_msr_list(void)
+{
+ u32 dummy[2];
+ unsigned i, j;
+
+ for (i = j = 0; i < ARRAY_SIZE(msrs_to_save); i++) {
+ if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0)
+ continue;
+ if (j < i)
+ msrs_to_save[j] = msrs_to_save[i];
+ j++;
+ }
+ num_msrs_to_save = j;
+}
+
+/*
+ * Adapt set_msr() to msr_io()'s calling convention
+ */
+static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
+{
+ return set_msr(vcpu, index, *data);
+}
+
+/*
+ * Read or write a bunch of msrs. All parameters are kernel addresses.
+ *
+ * @return number of msrs set successfully.
+ */
+static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs,
+ struct kvm_msr_entry *entries,
+ int (*do_msr)(struct kvm_vcpu *vcpu,
+ unsigned index, u64 *data))
+{
+ struct kvm_vcpu *vcpu;
+ int i;
+
+ if (!valid_vcpu(msrs->vcpu))
+ return -EINVAL;
+
+ vcpu = vcpu_load(kvm, msrs->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ for (i = 0; i < msrs->nmsrs; ++i)
+ if (do_msr(vcpu, entries[i].index, &entries[i].data))
+ break;
+
+ vcpu_put(vcpu);
+
+ return i;
+}
+
+/*
+ * Read or write a bunch of msrs. Parameters are user addresses.
+ *
+ * @return number of msrs set successfully.
+ */
+static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs,
+ int (*do_msr)(struct kvm_vcpu *vcpu,
+ unsigned index, u64 *data),
+ int writeback)
+{
+ struct kvm_msrs msrs;
+ struct kvm_msr_entry *entries;
+ int r, n;
+ unsigned size;
+
+ r = -EFAULT;
+ if (copy_from_user(&msrs, user_msrs, sizeof msrs))
+ goto out;
+
+ r = -E2BIG;
+ if (msrs.nmsrs >= MAX_IO_MSRS)
+ goto out;
+
+ r = -ENOMEM;
+ size = sizeof(struct kvm_msr_entry) * msrs.nmsrs;
+ entries = vmalloc(size);
+ if (!entries)
+ goto out;
+
+ r = -EFAULT;
+ if (copy_from_user(entries, user_msrs->entries, size))
+ goto out_free;
+
+ r = n = __msr_io(kvm, &msrs, entries, do_msr);
+ if (r < 0)
+ goto out_free;
+
+ r = -EFAULT;
+ if (writeback && copy_to_user(user_msrs->entries, entries, size))
+ goto out_free;
+
+ r = n;
+
+out_free:
+ vfree(entries);
+out:
+ return r;
+}
+
+/*
+ * Translate a guest virtual address to a guest physical address.
+ */
+static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr)
+{
+ unsigned long vaddr = tr->linear_address;
+ struct kvm_vcpu *vcpu;
+ gpa_t gpa;
+
+ vcpu = vcpu_load(kvm, tr->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+ spin_lock(&kvm->lock);
+ gpa = vcpu->mmu.gva_to_gpa(vcpu, vaddr);
+ tr->physical_address = gpa;
+ tr->valid = gpa != UNMAPPED_GVA;
+ tr->writeable = 1;
+ tr->usermode = 0;
+ spin_unlock(&kvm->lock);
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
+static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq)
+{
+ struct kvm_vcpu *vcpu;
+
+ if (!valid_vcpu(irq->vcpu))
+ return -EINVAL;
+ if (irq->irq < 0 || irq->irq >= 256)
+ return -EINVAL;
+ vcpu = vcpu_load(kvm, irq->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ set_bit(irq->irq, vcpu->irq_pending);
+ set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary);
+
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
+static int kvm_dev_ioctl_debug_guest(struct kvm *kvm,
+ struct kvm_debug_guest *dbg)
+{
+ struct kvm_vcpu *vcpu;
+ int r;
+
+ if (!valid_vcpu(dbg->vcpu))
+ return -EINVAL;
+ vcpu = vcpu_load(kvm, dbg->vcpu);
+ if (!vcpu)
+ return -ENOENT;
+
+ r = kvm_arch_ops->set_guest_debug(vcpu, dbg);
+
+ vcpu_put(vcpu);
+
+ return r;
+}
+
+static long kvm_dev_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ struct kvm *kvm = filp->private_data;
+ int r = -EINVAL;
+
+ switch (ioctl) {
+ case KVM_GET_API_VERSION:
+ r = KVM_API_VERSION;
+ break;
+ case KVM_CREATE_VCPU: {
+ r = kvm_dev_ioctl_create_vcpu(kvm, arg);
+ if (r)
+ goto out;
+ break;
+ }
+ case KVM_RUN: {
+ struct kvm_run kvm_run;
+
+ r = -EFAULT;
+ if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run))
+ goto out;
+ r = kvm_dev_ioctl_run(kvm, &kvm_run);
+ if (r < 0 && r != -EINTR)
+ goto out;
+ if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run)) {
+ r = -EFAULT;
+ goto out;
+ }
+ break;
+ }
+ case KVM_GET_REGS: {
+ struct kvm_regs kvm_regs;
+
+ r = -EFAULT;
+ if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+ goto out;
+ r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs))
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_SET_REGS: {
+ struct kvm_regs kvm_regs;
+
+ r = -EFAULT;
+ if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+ goto out;
+ r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_GET_SREGS: {
+ struct kvm_sregs kvm_sregs;
+
+ r = -EFAULT;
+ if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+ goto out;
+ r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs))
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_SET_SREGS: {
+ struct kvm_sregs kvm_sregs;
+
+ r = -EFAULT;
+ if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+ goto out;
+ r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_TRANSLATE: {
+ struct kvm_translation tr;
+
+ r = -EFAULT;
+ if (copy_from_user(&tr, (void *)arg, sizeof tr))
+ goto out;
+ r = kvm_dev_ioctl_translate(kvm, &tr);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user((void *)arg, &tr, sizeof tr))
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_INTERRUPT: {
+ struct kvm_interrupt irq;
+
+ r = -EFAULT;
+ if (copy_from_user(&irq, (void *)arg, sizeof irq))
+ goto out;
+ r = kvm_dev_ioctl_interrupt(kvm, &irq);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_DEBUG_GUEST: {
+ struct kvm_debug_guest dbg;
+
+ r = -EFAULT;
+ if (copy_from_user(&dbg, (void *)arg, sizeof dbg))
+ goto out;
+ r = kvm_dev_ioctl_debug_guest(kvm, &dbg);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_SET_MEMORY_REGION: {
+ struct kvm_memory_region kvm_mem;
+
+ r = -EFAULT;
+ if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem))
+ goto out;
+ r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
+ if (r)
+ goto out;
+ break;
+ }
+ case KVM_GET_DIRTY_LOG: {
+ struct kvm_dirty_log log;
+
+ r = -EFAULT;
+ if (copy_from_user(&log, (void *)arg, sizeof log))
+ goto out;
+ r = kvm_dev_ioctl_get_dirty_log(kvm, &log);
+ if (r)
+ goto out;
+ break;
+ }
+ case KVM_GET_MSRS:
+ r = msr_io(kvm, (void __user *)arg, get_msr, 1);
+ break;
+ case KVM_SET_MSRS:
+ r = msr_io(kvm, (void __user *)arg, do_set_msr, 0);
+ break;
+ case KVM_GET_MSR_INDEX_LIST: {
+ struct kvm_msr_list __user *user_msr_list = (void __user *)arg;
+ struct kvm_msr_list msr_list;
+ unsigned n;
+
+ r = -EFAULT;
+ if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
+ goto out;
+ n = msr_list.nmsrs;
+ msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs);
+ if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
+ goto out;
+ r = -E2BIG;
+ if (n < num_msrs_to_save)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(user_msr_list->indices, &msrs_to_save,
+ num_msrs_to_save * sizeof(u32)))
+ goto out;
+ if (copy_to_user(user_msr_list->indices
+ + num_msrs_to_save * sizeof(u32),
+ &emulated_msrs,
+ ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
+ goto out;
+ r = 0;
+ break;
+ }
+ default:
+ ;
+ }
+out:
+ return r;
+}
+
+static struct page *kvm_dev_nopage(struct vm_area_struct *vma,
+ unsigned long address,
+ int *type)
+{
+ struct kvm *kvm = vma->vm_file->private_data;
+ unsigned long pgoff;
+ struct kvm_memory_slot *slot;
+ struct page *page;
+
+ *type = VM_FAULT_MINOR;
+ pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+ slot = gfn_to_memslot(kvm, pgoff);
+ if (!slot)
+ return NOPAGE_SIGBUS;
+ page = gfn_to_page(slot, pgoff);
+ if (!page)
+ return NOPAGE_SIGBUS;
+ get_page(page);
+ return page;
+}
+
+static struct vm_operations_struct kvm_dev_vm_ops = {
+ .nopage = kvm_dev_nopage,
+};
+
+static int kvm_dev_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ vma->vm_ops = &kvm_dev_vm_ops;
+ return 0;
+}
+
+static struct file_operations kvm_chardev_ops = {
+ .open = kvm_dev_open,
+ .release = kvm_dev_release,
+ .unlocked_ioctl = kvm_dev_ioctl,
+ .compat_ioctl = kvm_dev_ioctl,
+ .mmap = kvm_dev_mmap,
+};
+
+static struct miscdevice kvm_dev = {
+ MISC_DYNAMIC_MINOR,
+ "kvm",
+ &kvm_chardev_ops,
+};
+
+static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
+ void *v)
+{
+ if (val == SYS_RESTART) {
+ /*
+ * Some (well, at least mine) BIOSes hang on reboot if
+ * in vmx root mode.
+ */
+ printk(KERN_INFO "kvm: exiting hardware virtualization\n");
+ on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_reboot_notifier = {
+ .notifier_call = kvm_reboot,
+ .priority = 0,
+};
+
+static __init void kvm_init_debug(void)
+{
+ struct kvm_stats_debugfs_item *p;
+
+ debugfs_dir = debugfs_create_dir("kvm", 0);
+ for (p = debugfs_entries; p->name; ++p)
+ p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
+ p->data);
+}
+
+static void kvm_exit_debug(void)
+{
+ struct kvm_stats_debugfs_item *p;
+
+ for (p = debugfs_entries; p->name; ++p)
+ debugfs_remove(p->dentry);
+ debugfs_remove(debugfs_dir);
+}
+
+hpa_t bad_page_address;
+
+int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
+{
+ int r;
+
+ if (kvm_arch_ops) {
+ printk(KERN_ERR "kvm: already loaded the other module\n");
+ return -EEXIST;
+ }
+
+ if (!ops->cpu_has_kvm_support()) {
+ printk(KERN_ERR "kvm: no hardware support\n");
+ return -EOPNOTSUPP;
+ }
+ if (ops->disabled_by_bios()) {
+ printk(KERN_ERR "kvm: disabled by bios\n");
+ return -EOPNOTSUPP;
+ }
+
+ kvm_arch_ops = ops;
+
+ r = kvm_arch_ops->hardware_setup();
+ if (r < 0)
+ return r;
+
+ on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+ register_reboot_notifier(&kvm_reboot_notifier);
+
+ kvm_chardev_ops.owner = module;
+
+ r = misc_register(&kvm_dev);
+ if (r) {
+ printk (KERN_ERR "kvm: misc device register failed\n");
+ goto out_free;
+ }
+
+ return r;
+
+out_free:
+ unregister_reboot_notifier(&kvm_reboot_notifier);
+ on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+ kvm_arch_ops->hardware_unsetup();
+ return r;
+}
+
+void kvm_exit_arch(void)
+{
+ misc_deregister(&kvm_dev);
+
+ unregister_reboot_notifier(&kvm_reboot_notifier);
+ on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+ kvm_arch_ops->hardware_unsetup();
+ kvm_arch_ops = NULL;
+}
+
+static __init int kvm_init(void)
+{
+ static struct page *bad_page;
+ int r = 0;
+
+ kvm_init_debug();
+
+ kvm_init_msr_list();
+
+ if ((bad_page = alloc_page(GFP_KERNEL)) == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ bad_page_address = page_to_pfn(bad_page) << PAGE_SHIFT;
+ memset(__va(bad_page_address), 0, PAGE_SIZE);
+
+ return r;
+
+out:
+ kvm_exit_debug();
+ return r;
+}
+
+static __exit void kvm_exit(void)
+{
+ kvm_exit_debug();
+ __free_page(pfn_to_page(bad_page_address >> PAGE_SHIFT));
+}
+
+module_init(kvm_init)
+module_exit(kvm_exit)
+
+EXPORT_SYMBOL_GPL(kvm_init_arch);
+EXPORT_SYMBOL_GPL(kvm_exit_arch);
diff --git a/drivers/kvm/kvm_svm.h b/drivers/kvm/kvm_svm.h
new file mode 100644
index 00000000000..74cc862f493
--- /dev/null
+++ b/drivers/kvm/kvm_svm.h
@@ -0,0 +1,44 @@
+#ifndef __KVM_SVM_H
+#define __KVM_SVM_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <asm/msr.h>
+
+#include "svm.h"
+#include "kvm.h"
+
+static const u32 host_save_msrs[] = {
+#ifdef CONFIG_X86_64
+ MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
+ MSR_FS_BASE, MSR_GS_BASE,
+#endif
+ MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
+ MSR_IA32_DEBUGCTLMSR, /*MSR_IA32_LASTBRANCHFROMIP,
+ MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/
+};
+
+#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs))
+#define NUM_DB_REGS 4
+
+struct vcpu_svm {
+ struct vmcb *vmcb;
+ unsigned long vmcb_pa;
+ struct svm_cpu_data *svm_data;
+ uint64_t asid_generation;
+
+ unsigned long cr0;
+ unsigned long cr4;
+ unsigned long db_regs[NUM_DB_REGS];
+
+ u64 next_rip;
+
+ u64 host_msrs[NR_HOST_SAVE_MSRS];
+ unsigned long host_cr2;
+ unsigned long host_db_regs[NUM_DB_REGS];
+ unsigned long host_dr6;
+ unsigned long host_dr7;
+};
+
+#endif
+
diff --git a/drivers/kvm/kvm_vmx.h b/drivers/kvm/kvm_vmx.h
new file mode 100644
index 00000000000..d139f73fb6e
--- /dev/null
+++ b/drivers/kvm/kvm_vmx.h
@@ -0,0 +1,14 @@
+#ifndef __KVM_VMX_H
+#define __KVM_VMX_H
+
+#ifdef CONFIG_X86_64
+/*
+ * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
+ * mechanism (cpu bug AA24)
+ */
+#define NR_BAD_MSRS 2
+#else
+#define NR_BAD_MSRS 0
+#endif
+
+#endif
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
new file mode 100644
index 00000000000..22c426cd8cb
--- /dev/null
+++ b/drivers/kvm/mmu.c
@@ -0,0 +1,1454 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * MMU support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Yaniv Kamay <yaniv@qumranet.com>
+ * Avi Kivity <avi@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+#include "vmx.h"
+#include "kvm.h"
+
+#undef MMU_DEBUG
+
+#undef AUDIT
+
+#ifdef AUDIT
+static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg);
+#else
+static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg) {}
+#endif
+
+#ifdef MMU_DEBUG
+
+#define pgprintk(x...) do { if (dbg) printk(x); } while (0)
+#define rmap_printk(x...) do { if (dbg) printk(x); } while (0)
+
+#else
+
+#define pgprintk(x...) do { } while (0)
+#define rmap_printk(x...) do { } while (0)
+
+#endif
+
+#if defined(MMU_DEBUG) || defined(AUDIT)
+static int dbg = 1;
+#endif
+
+#define ASSERT(x) \
+ if (!(x)) { \
+ printk(KERN_WARNING "assertion failed %s:%d: %s\n", \
+ __FILE__, __LINE__, #x); \
+ }
+
+#define PT64_PT_BITS 9
+#define PT64_ENT_PER_PAGE (1 << PT64_PT_BITS)
+#define PT32_PT_BITS 10
+#define PT32_ENT_PER_PAGE (1 << PT32_PT_BITS)
+
+#define PT_WRITABLE_SHIFT 1
+
+#define PT_PRESENT_MASK (1ULL << 0)
+#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT)
+#define PT_USER_MASK (1ULL << 2)
+#define PT_PWT_MASK (1ULL << 3)
+#define PT_PCD_MASK (1ULL << 4)
+#define PT_ACCESSED_MASK (1ULL << 5)
+#define PT_DIRTY_MASK (1ULL << 6)
+#define PT_PAGE_SIZE_MASK (1ULL << 7)
+#define PT_PAT_MASK (1ULL << 7)
+#define PT_GLOBAL_MASK (1ULL << 8)
+#define PT64_NX_MASK (1ULL << 63)
+
+#define PT_PAT_SHIFT 7
+#define PT_DIR_PAT_SHIFT 12
+#define PT_DIR_PAT_MASK (1ULL << PT_DIR_PAT_SHIFT)
+
+#define PT32_DIR_PSE36_SIZE 4
+#define PT32_DIR_PSE36_SHIFT 13
+#define PT32_DIR_PSE36_MASK (((1ULL << PT32_DIR_PSE36_SIZE) - 1) << PT32_DIR_PSE36_SHIFT)
+
+
+#define PT32_PTE_COPY_MASK \
+ (PT_PRESENT_MASK | PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_GLOBAL_MASK)
+
+#define PT64_PTE_COPY_MASK (PT64_NX_MASK | PT32_PTE_COPY_MASK)
+
+#define PT_FIRST_AVAIL_BITS_SHIFT 9
+#define PT64_SECOND_AVAIL_BITS_SHIFT 52
+
+#define PT_SHADOW_PS_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
+#define PT_SHADOW_IO_MARK (1ULL << PT_FIRST_AVAIL_BITS_SHIFT)
+
+#define PT_SHADOW_WRITABLE_SHIFT (PT_FIRST_AVAIL_BITS_SHIFT + 1)
+#define PT_SHADOW_WRITABLE_MASK (1ULL << PT_SHADOW_WRITABLE_SHIFT)
+
+#define PT_SHADOW_USER_SHIFT (PT_SHADOW_WRITABLE_SHIFT + 1)
+#define PT_SHADOW_USER_MASK (1ULL << (PT_SHADOW_USER_SHIFT))
+
+#define PT_SHADOW_BITS_OFFSET (PT_SHADOW_WRITABLE_SHIFT - PT_WRITABLE_SHIFT)
+
+#define VALID_PAGE(x) ((x) != INVALID_PAGE)
+
+#define PT64_LEVEL_BITS 9
+
+#define PT64_LEVEL_SHIFT(level) \
+ ( PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS )
+
+#define PT64_LEVEL_MASK(level) \
+ (((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level))
+
+#define PT64_INDEX(address, level)\
+ (((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
+
+
+#define PT32_LEVEL_BITS 10
+
+#define PT32_LEVEL_SHIFT(level) \
+ ( PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS )
+
+#define PT32_LEVEL_MASK(level) \
+ (((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level))
+
+#define PT32_INDEX(address, level)\
+ (((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1))
+
+
+#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK)
+#define PT64_DIR_BASE_ADDR_MASK \
+ (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1))
+
+#define PT32_BASE_ADDR_MASK PAGE_MASK
+#define PT32_DIR_BASE_ADDR_MASK \
+ (PAGE_MASK & ~((1ULL << (PAGE_SHIFT + PT32_LEVEL_BITS)) - 1))
+
+
+#define PFERR_PRESENT_MASK (1U << 0)
+#define PFERR_WRITE_MASK (1U << 1)
+#define PFERR_USER_MASK (1U << 2)
+#define PFERR_FETCH_MASK (1U << 4)
+
+#define PT64_ROOT_LEVEL 4
+#define PT32_ROOT_LEVEL 2
+#define PT32E_ROOT_LEVEL 3
+
+#define PT_DIRECTORY_LEVEL 2
+#define PT_PAGE_TABLE_LEVEL 1
+
+#define RMAP_EXT 4
+
+struct kvm_rmap_desc {
+ u64 *shadow_ptes[RMAP_EXT];
+ struct kvm_rmap_desc *more;
+};
+
+static int is_write_protection(struct kvm_vcpu *vcpu)
+{
+ return vcpu->cr0 & CR0_WP_MASK;
+}
+
+static int is_cpuid_PSE36(void)
+{
+ return 1;
+}
+
+static int is_nx(struct kvm_vcpu *vcpu)
+{
+ return vcpu->shadow_efer & EFER_NX;
+}
+
+static int is_present_pte(unsigned long pte)
+{
+ return pte & PT_PRESENT_MASK;
+}
+
+static int is_writeble_pte(unsigned long pte)
+{
+ return pte & PT_WRITABLE_MASK;
+}
+
+static int is_io_pte(unsigned long pte)
+{
+ return pte & PT_SHADOW_IO_MARK;
+}
+
+static int is_rmap_pte(u64 pte)
+{
+ return (pte & (PT_WRITABLE_MASK | PT_PRESENT_MASK))
+ == (PT_WRITABLE_MASK | PT_PRESENT_MASK);
+}
+
+static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
+ size_t objsize, int min)
+{
+ void *obj;
+
+ if (cache->nobjs >= min)
+ return 0;
+ while (cache->nobjs < ARRAY_SIZE(cache->objects)) {
+ obj = kzalloc(objsize, GFP_NOWAIT);
+ if (!obj)
+ return -ENOMEM;
+ cache->objects[cache->nobjs++] = obj;
+ }
+ return 0;
+}
+
+static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc)
+{
+ while (mc->nobjs)
+ kfree(mc->objects[--mc->nobjs]);
+}
+
+static int mmu_topup_memory_caches(struct kvm_vcpu *vcpu)
+{
+ int r;
+
+ r = mmu_topup_memory_cache(&vcpu->mmu_pte_chain_cache,
+ sizeof(struct kvm_pte_chain), 4);
+ if (r)
+ goto out;
+ r = mmu_topup_memory_cache(&vcpu->mmu_rmap_desc_cache,
+ sizeof(struct kvm_rmap_desc), 1);
+out:
+ return r;
+}
+
+static void mmu_free_memory_caches(struct kvm_vcpu *vcpu)
+{
+ mmu_free_memory_cache(&vcpu->mmu_pte_chain_cache);
+ mmu_free_memory_cache(&vcpu->mmu_rmap_desc_cache);
+}
+
+static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc,
+ size_t size)
+{
+ void *p;
+
+ BUG_ON(!mc->nobjs);
+ p = mc->objects[--mc->nobjs];
+ memset(p, 0, size);
+ return p;
+}
+
+static void mmu_memory_cache_free(struct kvm_mmu_memory_cache *mc, void *obj)
+{
+ if (mc->nobjs < KVM_NR_MEM_OBJS)
+ mc->objects[mc->nobjs++] = obj;
+ else
+ kfree(obj);
+}
+
+static struct kvm_pte_chain *mmu_alloc_pte_chain(struct kvm_vcpu *vcpu)
+{
+ return mmu_memory_cache_alloc(&vcpu->mmu_pte_chain_cache,
+ sizeof(struct kvm_pte_chain));
+}
+
+static void mmu_free_pte_chain(struct kvm_vcpu *vcpu,
+ struct kvm_pte_chain *pc)
+{
+ mmu_memory_cache_free(&vcpu->mmu_pte_chain_cache, pc);
+}
+
+static struct kvm_rmap_desc *mmu_alloc_rmap_desc(struct kvm_vcpu *vcpu)
+{
+ return mmu_memory_cache_alloc(&vcpu->mmu_rmap_desc_cache,
+ sizeof(struct kvm_rmap_desc));
+}
+
+static void mmu_free_rmap_desc(struct kvm_vcpu *vcpu,
+ struct kvm_rmap_desc *rd)
+{
+ mmu_memory_cache_free(&vcpu->mmu_rmap_desc_cache, rd);
+}
+
+/*
+ * Reverse mapping data structures:
+ *
+ * If page->private bit zero is zero, then page->private points to the
+ * shadow page table entry that points to page_address(page).
+ *
+ * If page->private bit zero is one, (then page->private & ~1) points
+ * to a struct kvm_rmap_desc containing more mappings.
+ */
+static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte)
+{
+ struct page *page;
+ struct kvm_rmap_desc *desc;
+ int i;
+
+ if (!is_rmap_pte(*spte))
+ return;
+ page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
+ if (!page->private) {
+ rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
+ page->private = (unsigned long)spte;
+ } else if (!(page->private & 1)) {
+ rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte);
+ desc = mmu_alloc_rmap_desc(vcpu);
+ desc->shadow_ptes[0] = (u64 *)page->private;
+ desc->shadow_ptes[1] = spte;
+ page->private = (unsigned long)desc | 1;
+ } else {
+ rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
+ desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+ while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
+ desc = desc->more;
+ if (desc->shadow_ptes[RMAP_EXT-1]) {
+ desc->more = mmu_alloc_rmap_desc(vcpu);
+ desc = desc->more;
+ }
+ for (i = 0; desc->shadow_ptes[i]; ++i)
+ ;
+ desc->shadow_ptes[i] = spte;
+ }
+}
+
+static void rmap_desc_remove_entry(struct kvm_vcpu *vcpu,
+ struct page *page,
+ struct kvm_rmap_desc *desc,
+ int i,
+ struct kvm_rmap_desc *prev_desc)
+{
+ int j;
+
+ for (j = RMAP_EXT - 1; !desc->shadow_ptes[j] && j > i; --j)
+ ;
+ desc->shadow_ptes[i] = desc->shadow_ptes[j];
+ desc->shadow_ptes[j] = 0;
+ if (j != 0)
+ return;
+ if (!prev_desc && !desc->more)
+ page->private = (unsigned long)desc->shadow_ptes[0];
+ else
+ if (prev_desc)
+ prev_desc->more = desc->more;
+ else
+ page->private = (unsigned long)desc->more | 1;
+ mmu_free_rmap_desc(vcpu, desc);
+}
+
+static void rmap_remove(struct kvm_vcpu *vcpu, u64 *spte)
+{
+ struct page *page;
+ struct kvm_rmap_desc *desc;
+ struct kvm_rmap_desc *prev_desc;
+ int i;
+
+ if (!is_rmap_pte(*spte))
+ return;
+ page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
+ if (!page->private) {
+ printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
+ BUG();
+ } else if (!(page->private & 1)) {
+ rmap_printk("rmap_remove: %p %llx 1->0\n", spte, *spte);
+ if ((u64 *)page->private != spte) {
+ printk(KERN_ERR "rmap_remove: %p %llx 1->BUG\n",
+ spte, *spte);
+ BUG();
+ }
+ page->private = 0;
+ } else {
+ rmap_printk("rmap_remove: %p %llx many->many\n", spte, *spte);
+ desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+ prev_desc = NULL;
+ while (desc) {
+ for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i)
+ if (desc->shadow_ptes[i] == spte) {
+ rmap_desc_remove_entry(vcpu, page,
+ desc, i,
+ prev_desc);
+ return;
+ }
+ prev_desc = desc;
+ desc = desc->more;
+ }
+ BUG();
+ }
+}
+
+static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct page *page;
+ struct kvm_memory_slot *slot;
+ struct kvm_rmap_desc *desc;
+ u64 *spte;
+
+ slot = gfn_to_memslot(kvm, gfn);
+ BUG_ON(!slot);
+ page = gfn_to_page(slot, gfn);
+
+ while (page->private) {
+ if (!(page->private & 1))
+ spte = (u64 *)page->private;
+ else {
+ desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+ spte = desc->shadow_ptes[0];
+ }
+ BUG_ON(!spte);
+ BUG_ON((*spte & PT64_BASE_ADDR_MASK) !=
+ page_to_pfn(page) << PAGE_SHIFT);
+ BUG_ON(!(*spte & PT_PRESENT_MASK));
+ BUG_ON(!(*spte & PT_WRITABLE_MASK));
+ rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
+ rmap_remove(vcpu, spte);
+ kvm_arch_ops->tlb_flush(vcpu);
+ *spte &= ~(u64)PT_WRITABLE_MASK;
+ }
+}
+
+static int is_empty_shadow_page(hpa_t page_hpa)
+{
+ u64 *pos;
+ u64 *end;
+
+ for (pos = __va(page_hpa), end = pos + PAGE_SIZE / sizeof(u64);
+ pos != end; pos++)
+ if (*pos != 0) {
+ printk(KERN_ERR "%s: %p %llx\n", __FUNCTION__,
+ pos, *pos);
+ return 0;
+ }
+ return 1;
+}
+
+static void kvm_mmu_free_page(struct kvm_vcpu *vcpu, hpa_t page_hpa)
+{
+ struct kvm_mmu_page *page_head = page_header(page_hpa);
+
+ ASSERT(is_empty_shadow_page(page_hpa));
+ list_del(&page_head->link);
+ page_head->page_hpa = page_hpa;
+ list_add(&page_head->link, &vcpu->free_pages);
+ ++vcpu->kvm->n_free_mmu_pages;
+}
+
+static unsigned kvm_page_table_hashfn(gfn_t gfn)
+{
+ return gfn;
+}
+
+static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
+ u64 *parent_pte)
+{
+ struct kvm_mmu_page *page;
+
+ if (list_empty(&vcpu->free_pages))
+ return NULL;
+
+ page = list_entry(vcpu->free_pages.next, struct kvm_mmu_page, link);
+ list_del(&page->link);
+ list_add(&page->link, &vcpu->kvm->active_mmu_pages);
+ ASSERT(is_empty_shadow_page(page->page_hpa));
+ page->slot_bitmap = 0;
+ page->global = 1;
+ page->multimapped = 0;
+ page->parent_pte = parent_pte;
+ --vcpu->kvm->n_free_mmu_pages;
+ return page;
+}
+
+static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *page, u64 *parent_pte)
+{
+ struct kvm_pte_chain *pte_chain;
+ struct hlist_node *node;
+ int i;
+
+ if (!parent_pte)
+ return;
+ if (!page->multimapped) {
+ u64 *old = page->parent_pte;
+
+ if (!old) {
+ page->parent_pte = parent_pte;
+ return;
+ }
+ page->multimapped = 1;
+ pte_chain = mmu_alloc_pte_chain(vcpu);
+ INIT_HLIST_HEAD(&page->parent_ptes);
+ hlist_add_head(&pte_chain->link, &page->parent_ptes);
+ pte_chain->parent_ptes[0] = old;
+ }
+ hlist_for_each_entry(pte_chain, node, &page->parent_ptes, link) {
+ if (pte_chain->parent_ptes[NR_PTE_CHAIN_ENTRIES-1])
+ continue;
+ for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i)
+ if (!pte_chain->parent_ptes[i]) {
+ pte_chain->parent_ptes[i] = parent_pte;
+ return;
+ }
+ }
+ pte_chain = mmu_alloc_pte_chain(vcpu);
+ BUG_ON(!pte_chain);
+ hlist_add_head(&pte_chain->link, &page->parent_ptes);
+ pte_chain->parent_ptes[0] = parent_pte;
+}
+
+static void mmu_page_remove_parent_pte(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *page,
+ u64 *parent_pte)
+{
+ struct kvm_pte_chain *pte_chain;
+ struct hlist_node *node;
+ int i;
+
+ if (!page->multimapped) {
+ BUG_ON(page->parent_pte != parent_pte);
+ page->parent_pte = NULL;
+ return;
+ }
+ hlist_for_each_entry(pte_chain, node, &page->parent_ptes, link)
+ for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
+ if (!pte_chain->parent_ptes[i])
+ break;
+ if (pte_chain->parent_ptes[i] != parent_pte)
+ continue;
+ while (i + 1 < NR_PTE_CHAIN_ENTRIES
+ && pte_chain->parent_ptes[i + 1]) {
+ pte_chain->parent_ptes[i]
+ = pte_chain->parent_ptes[i + 1];
+ ++i;
+ }
+ pte_chain->parent_ptes[i] = NULL;
+ if (i == 0) {
+ hlist_del(&pte_chain->link);
+ mmu_free_pte_chain(vcpu, pte_chain);
+ if (hlist_empty(&page->parent_ptes)) {
+ page->multimapped = 0;
+ page->parent_pte = NULL;
+ }
+ }
+ return;
+ }
+ BUG();
+}
+
+static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm_vcpu *vcpu,
+ gfn_t gfn)
+{
+ unsigned index;
+ struct hlist_head *bucket;
+ struct kvm_mmu_page *page;
+ struct hlist_node *node;
+
+ pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
+ index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+ bucket = &vcpu->kvm->mmu_page_hash[index];
+ hlist_for_each_entry(page, node, bucket, hash_link)
+ if (page->gfn == gfn && !page->role.metaphysical) {
+ pgprintk("%s: found role %x\n",
+ __FUNCTION__, page->role.word);
+ return page;
+ }
+ return NULL;
+}
+
+static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+ gfn_t gfn,
+ gva_t gaddr,
+ unsigned level,
+ int metaphysical,
+ u64 *parent_pte)
+{
+ union kvm_mmu_page_role role;
+ unsigned index;
+ unsigned quadrant;
+ struct hlist_head *bucket;
+ struct kvm_mmu_page *page;
+ struct hlist_node *node;
+
+ role.word = 0;
+ role.glevels = vcpu->mmu.root_level;
+ role.level = level;
+ role.metaphysical = metaphysical;
+ if (vcpu->mmu.root_level <= PT32_ROOT_LEVEL) {
+ quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level));
+ quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
+ role.quadrant = quadrant;
+ }
+ pgprintk("%s: looking gfn %lx role %x\n", __FUNCTION__,
+ gfn, role.word);
+ index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+ bucket = &vcpu->kvm->mmu_page_hash[index];
+ hlist_for_each_entry(page, node, bucket, hash_link)
+ if (page->gfn == gfn && page->role.word == role.word) {
+ mmu_page_add_parent_pte(vcpu, page, parent_pte);
+ pgprintk("%s: found\n", __FUNCTION__);
+ return page;
+ }
+ page = kvm_mmu_alloc_page(vcpu, parent_pte);
+ if (!page)
+ return page;
+ pgprintk("%s: adding gfn %lx role %x\n", __FUNCTION__, gfn, role.word);
+ page->gfn = gfn;
+ page->role = role;
+ hlist_add_head(&page->hash_link, bucket);
+ if (!metaphysical)
+ rmap_write_protect(vcpu, gfn);
+ return page;
+}
+
+static void kvm_mmu_page_unlink_children(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *page)
+{
+ unsigned i;
+ u64 *pt;
+ u64 ent;
+
+ pt = __va(page->page_hpa);
+
+ if (page->role.level == PT_PAGE_TABLE_LEVEL) {
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+ if (pt[i] & PT_PRESENT_MASK)
+ rmap_remove(vcpu, &pt[i]);
+ pt[i] = 0;
+ }
+ kvm_arch_ops->tlb_flush(vcpu);
+ return;
+ }
+
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+ ent = pt[i];
+
+ pt[i] = 0;
+ if (!(ent & PT_PRESENT_MASK))
+ continue;
+ ent &= PT64_BASE_ADDR_MASK;
+ mmu_page_remove_parent_pte(vcpu, page_header(ent), &pt[i]);
+ }
+}
+
+static void kvm_mmu_put_page(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *page,
+ u64 *parent_pte)
+{
+ mmu_page_remove_parent_pte(vcpu, page, parent_pte);
+}
+
+static void kvm_mmu_zap_page(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *page)
+{
+ u64 *parent_pte;
+
+ while (page->multimapped || page->parent_pte) {
+ if (!page->multimapped)
+ parent_pte = page->parent_pte;
+ else {
+ struct kvm_pte_chain *chain;
+
+ chain = container_of(page->parent_ptes.first,
+ struct kvm_pte_chain, link);
+ parent_pte = chain->parent_ptes[0];
+ }
+ BUG_ON(!parent_pte);
+ kvm_mmu_put_page(vcpu, page, parent_pte);
+ *parent_pte = 0;
+ }
+ kvm_mmu_page_unlink_children(vcpu, page);
+ if (!page->root_count) {
+ hlist_del(&page->hash_link);
+ kvm_mmu_free_page(vcpu, page->page_hpa);
+ } else {
+ list_del(&page->link);
+ list_add(&page->link, &vcpu->kvm->active_mmu_pages);
+ }
+}
+
+static int kvm_mmu_unprotect_page(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+ unsigned index;
+ struct hlist_head *bucket;
+ struct kvm_mmu_page *page;
+ struct hlist_node *node, *n;
+ int r;
+
+ pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
+ r = 0;
+ index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+ bucket = &vcpu->kvm->mmu_page_hash[index];
+ hlist_for_each_entry_safe(page, node, n, bucket, hash_link)
+ if (page->gfn == gfn && !page->role.metaphysical) {
+ pgprintk("%s: gfn %lx role %x\n", __FUNCTION__, gfn,
+ page->role.word);
+ kvm_mmu_zap_page(vcpu, page);
+ r = 1;
+ }
+ return r;
+}
+
+static void page_header_update_slot(struct kvm *kvm, void *pte, gpa_t gpa)
+{
+ int slot = memslot_id(kvm, gfn_to_memslot(kvm, gpa >> PAGE_SHIFT));
+ struct kvm_mmu_page *page_head = page_header(__pa(pte));
+
+ __set_bit(slot, &page_head->slot_bitmap);
+}
+
+hpa_t safe_gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+ hpa_t hpa = gpa_to_hpa(vcpu, gpa);
+
+ return is_error_hpa(hpa) ? bad_page_address | (gpa & ~PAGE_MASK): hpa;
+}
+
+hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+ struct kvm_memory_slot *slot;
+ struct page *page;
+
+ ASSERT((gpa & HPA_ERR_MASK) == 0);
+ slot = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
+ if (!slot)
+ return gpa | HPA_ERR_MASK;
+ page = gfn_to_page(slot, gpa >> PAGE_SHIFT);
+ return ((hpa_t)page_to_pfn(page) << PAGE_SHIFT)
+ | (gpa & (PAGE_SIZE-1));
+}
+
+hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva)
+{
+ gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
+
+ if (gpa == UNMAPPED_GVA)
+ return UNMAPPED_GVA;
+ return gpa_to_hpa(vcpu, gpa);
+}
+
+static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
+{
+}
+
+static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, hpa_t p)
+{
+ int level = PT32E_ROOT_LEVEL;
+ hpa_t table_addr = vcpu->mmu.root_hpa;
+
+ for (; ; level--) {
+ u32 index = PT64_INDEX(v, level);
+ u64 *table;
+ u64 pte;
+
+ ASSERT(VALID_PAGE(table_addr));
+ table = __va(table_addr);
+
+ if (level == 1) {
+ pte = table[index];
+ if (is_present_pte(pte) && is_writeble_pte(pte))
+ return 0;
+ mark_page_dirty(vcpu->kvm, v >> PAGE_SHIFT);
+ page_header_update_slot(vcpu->kvm, table, v);
+ table[index] = p | PT_PRESENT_MASK | PT_WRITABLE_MASK |
+ PT_USER_MASK;
+ rmap_add(vcpu, &table[index]);
+ return 0;
+ }
+
+ if (table[index] == 0) {
+ struct kvm_mmu_page *new_table;
+ gfn_t pseudo_gfn;
+
+ pseudo_gfn = (v & PT64_DIR_BASE_ADDR_MASK)
+ >> PAGE_SHIFT;
+ new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
+ v, level - 1,
+ 1, &table[index]);
+ if (!new_table) {
+ pgprintk("nonpaging_map: ENOMEM\n");
+ return -ENOMEM;
+ }
+
+ table[index] = new_table->page_hpa | PT_PRESENT_MASK
+ | PT_WRITABLE_MASK | PT_USER_MASK;
+ }
+ table_addr = table[index] & PT64_BASE_ADDR_MASK;
+ }
+}
+
+static void mmu_free_roots(struct kvm_vcpu *vcpu)
+{
+ int i;
+ struct kvm_mmu_page *page;
+
+#ifdef CONFIG_X86_64
+ if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) {
+ hpa_t root = vcpu->mmu.root_hpa;
+
+ ASSERT(VALID_PAGE(root));
+ page = page_header(root);
+ --page->root_count;
+ vcpu->mmu.root_hpa = INVALID_PAGE;
+ return;
+ }
+#endif
+ for (i = 0; i < 4; ++i) {
+ hpa_t root = vcpu->mmu.pae_root[i];
+
+ ASSERT(VALID_PAGE(root));
+ root &= PT64_BASE_ADDR_MASK;
+ page = page_header(root);
+ --page->root_count;
+ vcpu->mmu.pae_root[i] = INVALID_PAGE;
+ }
+ vcpu->mmu.root_hpa = INVALID_PAGE;
+}
+
+static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
+{
+ int i;
+ gfn_t root_gfn;
+ struct kvm_mmu_page *page;
+
+ root_gfn = vcpu->cr3 >> PAGE_SHIFT;
+
+#ifdef CONFIG_X86_64
+ if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) {
+ hpa_t root = vcpu->mmu.root_hpa;
+
+ ASSERT(!VALID_PAGE(root));
+ page = kvm_mmu_get_page(vcpu, root_gfn, 0,
+ PT64_ROOT_LEVEL, 0, NULL);
+ root = page->page_hpa;
+ ++page->root_count;
+ vcpu->mmu.root_hpa = root;
+ return;
+ }
+#endif
+ for (i = 0; i < 4; ++i) {
+ hpa_t root = vcpu->mmu.pae_root[i];
+
+ ASSERT(!VALID_PAGE(root));
+ if (vcpu->mmu.root_level == PT32E_ROOT_LEVEL)
+ root_gfn = vcpu->pdptrs[i] >> PAGE_SHIFT;
+ else if (vcpu->mmu.root_level == 0)
+ root_gfn = 0;
+ page = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
+ PT32_ROOT_LEVEL, !is_paging(vcpu),
+ NULL);
+ root = page->page_hpa;
+ ++page->root_count;
+ vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
+ }
+ vcpu->mmu.root_hpa = __pa(vcpu->mmu.pae_root);
+}
+
+static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
+{
+ return vaddr;
+}
+
+static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
+ u32 error_code)
+{
+ gpa_t addr = gva;
+ hpa_t paddr;
+ int r;
+
+ r = mmu_topup_memory_caches(vcpu);
+ if (r)
+ return r;
+
+ ASSERT(vcpu);
+ ASSERT(VALID_PAGE(vcpu->mmu.root_hpa));
+
+
+ paddr = gpa_to_hpa(vcpu , addr & PT64_BASE_ADDR_MASK);
+
+ if (is_error_hpa(paddr))
+ return 1;
+
+ return nonpaging_map(vcpu, addr & PAGE_MASK, paddr);
+}
+
+static void nonpaging_free(struct kvm_vcpu *vcpu)
+{
+ mmu_free_roots(vcpu);
+}
+
+static int nonpaging_init_context(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mmu *context = &vcpu->mmu;
+
+ context->new_cr3 = nonpaging_new_cr3;
+ context->page_fault = nonpaging_page_fault;
+ context->gva_to_gpa = nonpaging_gva_to_gpa;
+ context->free = nonpaging_free;
+ context->root_level = 0;
+ context->shadow_root_level = PT32E_ROOT_LEVEL;
+ mmu_alloc_roots(vcpu);
+ ASSERT(VALID_PAGE(context->root_hpa));
+ kvm_arch_ops->set_cr3(vcpu, context->root_hpa);
+ return 0;
+}
+
+static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu)
+{
+ ++kvm_stat.tlb_flush;
+ kvm_arch_ops->tlb_flush(vcpu);
+}
+
+static void paging_new_cr3(struct kvm_vcpu *vcpu)
+{
+ pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->cr3);
+ mmu_free_roots(vcpu);
+ if (unlikely(vcpu->kvm->n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
+ kvm_mmu_free_some_pages(vcpu);
+ mmu_alloc_roots(vcpu);
+ kvm_mmu_flush_tlb(vcpu);
+ kvm_arch_ops->set_cr3(vcpu, vcpu->mmu.root_hpa);
+}
+
+static void mark_pagetable_nonglobal(void *shadow_pte)
+{
+ page_header(__pa(shadow_pte))->global = 0;
+}
+
+static inline void set_pte_common(struct kvm_vcpu *vcpu,
+ u64 *shadow_pte,
+ gpa_t gaddr,
+ int dirty,
+ u64 access_bits,
+ gfn_t gfn)
+{
+ hpa_t paddr;
+
+ *shadow_pte |= access_bits << PT_SHADOW_BITS_OFFSET;
+ if (!dirty)
+ access_bits &= ~PT_WRITABLE_MASK;
+
+ paddr = gpa_to_hpa(vcpu, gaddr & PT64_BASE_ADDR_MASK);
+
+ *shadow_pte |= access_bits;
+
+ if (!(*shadow_pte & PT_GLOBAL_MASK))
+ mark_pagetable_nonglobal(shadow_pte);
+
+ if (is_error_hpa(paddr)) {
+ *shadow_pte |= gaddr;
+ *shadow_pte |= PT_SHADOW_IO_MARK;
+ *shadow_pte &= ~PT_PRESENT_MASK;
+ return;
+ }
+
+ *shadow_pte |= paddr;
+
+ if (access_bits & PT_WRITABLE_MASK) {
+ struct kvm_mmu_page *shadow;
+
+ shadow = kvm_mmu_lookup_page(vcpu, gfn);
+ if (shadow) {
+ pgprintk("%s: found shadow page for %lx, marking ro\n",
+ __FUNCTION__, gfn);
+ access_bits &= ~PT_WRITABLE_MASK;
+ if (is_writeble_pte(*shadow_pte)) {
+ *shadow_pte &= ~PT_WRITABLE_MASK;
+ kvm_arch_ops->tlb_flush(vcpu);
+ }
+ }
+ }
+
+ if (access_bits & PT_WRITABLE_MASK)
+ mark_page_dirty(vcpu->kvm, gaddr >> PAGE_SHIFT);
+
+ page_header_update_slot(vcpu->kvm, shadow_pte, gaddr);
+ rmap_add(vcpu, shadow_pte);
+}
+
+static void inject_page_fault(struct kvm_vcpu *vcpu,
+ u64 addr,
+ u32 err_code)
+{
+ kvm_arch_ops->inject_page_fault(vcpu, addr, err_code);
+}
+
+static inline int fix_read_pf(u64 *shadow_ent)
+{
+ if ((*shadow_ent & PT_SHADOW_USER_MASK) &&
+ !(*shadow_ent & PT_USER_MASK)) {
+ /*
+ * If supervisor write protect is disabled, we shadow kernel
+ * pages as user pages so we can trap the write access.
+ */
+ *shadow_ent |= PT_USER_MASK;
+ *shadow_ent &= ~PT_WRITABLE_MASK;
+
+ return 1;
+
+ }
+ return 0;
+}
+
+static void paging_free(struct kvm_vcpu *vcpu)
+{
+ nonpaging_free(vcpu);
+}
+
+#define PTTYPE 64
+#include "paging_tmpl.h"
+#undef PTTYPE
+
+#define PTTYPE 32
+#include "paging_tmpl.h"
+#undef PTTYPE
+
+static int paging64_init_context_common(struct kvm_vcpu *vcpu, int level)
+{
+ struct kvm_mmu *context = &vcpu->mmu;
+
+ ASSERT(is_pae(vcpu));
+ context->new_cr3 = paging_new_cr3;
+ context->page_fault = paging64_page_fault;
+ context->gva_to_gpa = paging64_gva_to_gpa;
+ context->free = paging_free;
+ context->root_level = level;
+ context->shadow_root_level = level;
+ mmu_alloc_roots(vcpu);
+ ASSERT(VALID_PAGE(context->root_hpa));
+ kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
+ (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
+ return 0;
+}
+
+static int paging64_init_context(struct kvm_vcpu *vcpu)
+{
+ return paging64_init_context_common(vcpu, PT64_ROOT_LEVEL);
+}
+
+static int paging32_init_context(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mmu *context = &vcpu->mmu;
+
+ context->new_cr3 = paging_new_cr3;
+ context->page_fault = paging32_page_fault;
+ context->gva_to_gpa = paging32_gva_to_gpa;
+ context->free = paging_free;
+ context->root_level = PT32_ROOT_LEVEL;
+ context->shadow_root_level = PT32E_ROOT_LEVEL;
+ mmu_alloc_roots(vcpu);
+ ASSERT(VALID_PAGE(context->root_hpa));
+ kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
+ (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
+ return 0;
+}
+
+static int paging32E_init_context(struct kvm_vcpu *vcpu)
+{
+ return paging64_init_context_common(vcpu, PT32E_ROOT_LEVEL);
+}
+
+static int init_kvm_mmu(struct kvm_vcpu *vcpu)
+{
+ ASSERT(vcpu);
+ ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
+
+ if (!is_paging(vcpu))
+ return nonpaging_init_context(vcpu);
+ else if (is_long_mode(vcpu))
+ return paging64_init_context(vcpu);
+ else if (is_pae(vcpu))
+ return paging32E_init_context(vcpu);
+ else
+ return paging32_init_context(vcpu);
+}
+
+static void destroy_kvm_mmu(struct kvm_vcpu *vcpu)
+{
+ ASSERT(vcpu);
+ if (VALID_PAGE(vcpu->mmu.root_hpa)) {
+ vcpu->mmu.free(vcpu);
+ vcpu->mmu.root_hpa = INVALID_PAGE;
+ }
+}
+
+int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
+{
+ int r;
+
+ destroy_kvm_mmu(vcpu);
+ r = init_kvm_mmu(vcpu);
+ if (r < 0)
+ goto out;
+ r = mmu_topup_memory_caches(vcpu);
+out:
+ return r;
+}
+
+void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
+{
+ gfn_t gfn = gpa >> PAGE_SHIFT;
+ struct kvm_mmu_page *page;
+ struct kvm_mmu_page *child;
+ struct hlist_node *node, *n;
+ struct hlist_head *bucket;
+ unsigned index;
+ u64 *spte;
+ u64 pte;
+ unsigned offset = offset_in_page(gpa);
+ unsigned pte_size;
+ unsigned page_offset;
+ unsigned misaligned;
+ int level;
+ int flooded = 0;
+
+ pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
+ if (gfn == vcpu->last_pt_write_gfn) {
+ ++vcpu->last_pt_write_count;
+ if (vcpu->last_pt_write_count >= 3)
+ flooded = 1;
+ } else {
+ vcpu->last_pt_write_gfn = gfn;
+ vcpu->last_pt_write_count = 1;
+ }
+ index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
+ bucket = &vcpu->kvm->mmu_page_hash[index];
+ hlist_for_each_entry_safe(page, node, n, bucket, hash_link) {
+ if (page->gfn != gfn || page->role.metaphysical)
+ continue;
+ pte_size = page->role.glevels == PT32_ROOT_LEVEL ? 4 : 8;
+ misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1);
+ if (misaligned || flooded) {
+ /*
+ * Misaligned accesses are too much trouble to fix
+ * up; also, they usually indicate a page is not used
+ * as a page table.
+ *
+ * If we're seeing too many writes to a page,
+ * it may no longer be a page table, or we may be
+ * forking, in which case it is better to unmap the
+ * page.
+ */
+ pgprintk("misaligned: gpa %llx bytes %d role %x\n",
+ gpa, bytes, page->role.word);
+ kvm_mmu_zap_page(vcpu, page);
+ continue;
+ }
+ page_offset = offset;
+ level = page->role.level;
+ if (page->role.glevels == PT32_ROOT_LEVEL) {
+ page_offset <<= 1; /* 32->64 */
+ page_offset &= ~PAGE_MASK;
+ }
+ spte = __va(page->page_hpa);
+ spte += page_offset / sizeof(*spte);
+ pte = *spte;
+ if (is_present_pte(pte)) {
+ if (level == PT_PAGE_TABLE_LEVEL)
+ rmap_remove(vcpu, spte);
+ else {
+ child = page_header(pte & PT64_BASE_ADDR_MASK);
+ mmu_page_remove_parent_pte(vcpu, child, spte);
+ }
+ }
+ *spte = 0;
+ }
+}
+
+void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
+{
+}
+
+int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
+{
+ gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
+
+ return kvm_mmu_unprotect_page(vcpu, gpa >> PAGE_SHIFT);
+}
+
+void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
+{
+ while (vcpu->kvm->n_free_mmu_pages < KVM_REFILL_PAGES) {
+ struct kvm_mmu_page *page;
+
+ page = container_of(vcpu->kvm->active_mmu_pages.prev,
+ struct kvm_mmu_page, link);
+ kvm_mmu_zap_page(vcpu, page);
+ }
+}
+EXPORT_SYMBOL_GPL(kvm_mmu_free_some_pages);
+
+static void free_mmu_pages(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mmu_page *page;
+
+ while (!list_empty(&vcpu->kvm->active_mmu_pages)) {
+ page = container_of(vcpu->kvm->active_mmu_pages.next,
+ struct kvm_mmu_page, link);
+ kvm_mmu_zap_page(vcpu, page);
+ }
+ while (!list_empty(&vcpu->free_pages)) {
+ page = list_entry(vcpu->free_pages.next,
+ struct kvm_mmu_page, link);
+ list_del(&page->link);
+ __free_page(pfn_to_page(page->page_hpa >> PAGE_SHIFT));
+ page->page_hpa = INVALID_PAGE;
+ }
+ free_page((unsigned long)vcpu->mmu.pae_root);
+}
+
+static int alloc_mmu_pages(struct kvm_vcpu *vcpu)
+{
+ struct page *page;
+ int i;
+
+ ASSERT(vcpu);
+
+ for (i = 0; i < KVM_NUM_MMU_PAGES; i++) {
+ struct kvm_mmu_page *page_header = &vcpu->page_header_buf[i];
+
+ INIT_LIST_HEAD(&page_header->link);
+ if ((page = alloc_page(GFP_KERNEL)) == NULL)
+ goto error_1;
+ page->private = (unsigned long)page_header;
+ page_header->page_hpa = (hpa_t)page_to_pfn(page) << PAGE_SHIFT;
+ memset(__va(page_header->page_hpa), 0, PAGE_SIZE);
+ list_add(&page_header->link, &vcpu->free_pages);
+ ++vcpu->kvm->n_free_mmu_pages;
+ }
+
+ /*
+ * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.
+ * Therefore we need to allocate shadow page tables in the first
+ * 4GB of memory, which happens to fit the DMA32 zone.
+ */
+ page = alloc_page(GFP_KERNEL | __GFP_DMA32);
+ if (!page)
+ goto error_1;
+ vcpu->mmu.pae_root = page_address(page);
+ for (i = 0; i < 4; ++i)
+ vcpu->mmu.pae_root[i] = INVALID_PAGE;
+
+ return 0;
+
+error_1:
+ free_mmu_pages(vcpu);
+ return -ENOMEM;
+}
+
+int kvm_mmu_create(struct kvm_vcpu *vcpu)
+{
+ ASSERT(vcpu);
+ ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
+ ASSERT(list_empty(&vcpu->free_pages));
+
+ return alloc_mmu_pages(vcpu);
+}
+
+int kvm_mmu_setup(struct kvm_vcpu *vcpu)
+{
+ ASSERT(vcpu);
+ ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
+ ASSERT(!list_empty(&vcpu->free_pages));
+
+ return init_kvm_mmu(vcpu);
+}
+
+void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
+{
+ ASSERT(vcpu);
+
+ destroy_kvm_mmu(vcpu);
+ free_mmu_pages(vcpu);
+ mmu_free_memory_caches(vcpu);
+}
+
+void kvm_mmu_slot_remove_write_access(struct kvm_vcpu *vcpu, int slot)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_mmu_page *page;
+
+ list_for_each_entry(page, &kvm->active_mmu_pages, link) {
+ int i;
+ u64 *pt;
+
+ if (!test_bit(slot, &page->slot_bitmap))
+ continue;
+
+ pt = __va(page->page_hpa);
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+ /* avoid RMW */
+ if (pt[i] & PT_WRITABLE_MASK) {
+ rmap_remove(vcpu, &pt[i]);
+ pt[i] &= ~PT_WRITABLE_MASK;
+ }
+ }
+}
+
+#ifdef AUDIT
+
+static const char *audit_msg;
+
+static gva_t canonicalize(gva_t gva)
+{
+#ifdef CONFIG_X86_64
+ gva = (long long)(gva << 16) >> 16;
+#endif
+ return gva;
+}
+
+static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
+ gva_t va, int level)
+{
+ u64 *pt = __va(page_pte & PT64_BASE_ADDR_MASK);
+ int i;
+ gva_t va_delta = 1ul << (PAGE_SHIFT + 9 * (level - 1));
+
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i, va += va_delta) {
+ u64 ent = pt[i];
+
+ if (!ent & PT_PRESENT_MASK)
+ continue;
+
+ va = canonicalize(va);
+ if (level > 1)
+ audit_mappings_page(vcpu, ent, va, level - 1);
+ else {
+ gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, va);
+ hpa_t hpa = gpa_to_hpa(vcpu, gpa);
+
+ if ((ent & PT_PRESENT_MASK)
+ && (ent & PT64_BASE_ADDR_MASK) != hpa)
+ printk(KERN_ERR "audit error: (%s) levels %d"
+ " gva %lx gpa %llx hpa %llx ent %llx\n",
+ audit_msg, vcpu->mmu.root_level,
+ va, gpa, hpa, ent);
+ }
+ }
+}
+
+static void audit_mappings(struct kvm_vcpu *vcpu)
+{
+ int i;
+
+ if (vcpu->mmu.root_level == 4)
+ audit_mappings_page(vcpu, vcpu->mmu.root_hpa, 0, 4);
+ else
+ for (i = 0; i < 4; ++i)
+ if (vcpu->mmu.pae_root[i] & PT_PRESENT_MASK)
+ audit_mappings_page(vcpu,
+ vcpu->mmu.pae_root[i],
+ i << 30,
+ 2);
+}
+
+static int count_rmaps(struct kvm_vcpu *vcpu)
+{
+ int nmaps = 0;
+ int i, j, k;
+
+ for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
+ struct kvm_memory_slot *m = &vcpu->kvm->memslots[i];
+ struct kvm_rmap_desc *d;
+
+ for (j = 0; j < m->npages; ++j) {
+ struct page *page = m->phys_mem[j];
+
+ if (!page->private)
+ continue;
+ if (!(page->private & 1)) {
+ ++nmaps;
+ continue;
+ }
+ d = (struct kvm_rmap_desc *)(page->private & ~1ul);
+ while (d) {
+ for (k = 0; k < RMAP_EXT; ++k)
+ if (d->shadow_ptes[k])
+ ++nmaps;
+ else
+ break;
+ d = d->more;
+ }
+ }
+ }
+ return nmaps;
+}
+
+static int count_writable_mappings(struct kvm_vcpu *vcpu)
+{
+ int nmaps = 0;
+ struct kvm_mmu_page *page;
+ int i;
+
+ list_for_each_entry(page, &vcpu->kvm->active_mmu_pages, link) {
+ u64 *pt = __va(page->page_hpa);
+
+ if (page->role.level != PT_PAGE_TABLE_LEVEL)
+ continue;
+
+ for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+ u64 ent = pt[i];
+
+ if (!(ent & PT_PRESENT_MASK))
+ continue;
+ if (!(ent & PT_WRITABLE_MASK))
+ continue;
+ ++nmaps;
+ }
+ }
+ return nmaps;
+}
+
+static void audit_rmap(struct kvm_vcpu *vcpu)
+{
+ int n_rmap = count_rmaps(vcpu);
+ int n_actual = count_writable_mappings(vcpu);
+
+ if (n_rmap != n_actual)
+ printk(KERN_ERR "%s: (%s) rmap %d actual %d\n",
+ __FUNCTION__, audit_msg, n_rmap, n_actual);
+}
+
+static void audit_write_protection(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mmu_page *page;
+
+ list_for_each_entry(page, &vcpu->kvm->active_mmu_pages, link) {
+ hfn_t hfn;
+ struct page *pg;
+
+ if (page->role.metaphysical)
+ continue;
+
+ hfn = gpa_to_hpa(vcpu, (gpa_t)page->gfn << PAGE_SHIFT)
+ >> PAGE_SHIFT;
+ pg = pfn_to_page(hfn);
+ if (pg->private)
+ printk(KERN_ERR "%s: (%s) shadow page has writable"
+ " mappings: gfn %lx role %x\n",
+ __FUNCTION__, audit_msg, page->gfn,
+ page->role.word);
+ }
+}
+
+static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg)
+{
+ int olddbg = dbg;
+
+ dbg = 0;
+ audit_msg = msg;
+ audit_rmap(vcpu);
+ audit_write_protection(vcpu);
+ audit_mappings(vcpu);
+ dbg = olddbg;
+}
+
+#endif
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
new file mode 100644
index 00000000000..149fa45fd9a
--- /dev/null
+++ b/drivers/kvm/paging_tmpl.h
@@ -0,0 +1,484 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * MMU support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Yaniv Kamay <yaniv@qumranet.com>
+ * Avi Kivity <avi@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+/*
+ * We need the mmu code to access both 32-bit and 64-bit guest ptes,
+ * so the code in this file is compiled twice, once per pte size.
+ */
+
+#if PTTYPE == 64
+ #define pt_element_t u64
+ #define guest_walker guest_walker64
+ #define FNAME(name) paging##64_##name
+ #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK
+ #define PT_DIR_BASE_ADDR_MASK PT64_DIR_BASE_ADDR_MASK
+ #define PT_INDEX(addr, level) PT64_INDEX(addr, level)
+ #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
+ #define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
+ #define PT_PTE_COPY_MASK PT64_PTE_COPY_MASK
+ #ifdef CONFIG_X86_64
+ #define PT_MAX_FULL_LEVELS 4
+ #else
+ #define PT_MAX_FULL_LEVELS 2
+ #endif
+#elif PTTYPE == 32
+ #define pt_element_t u32
+ #define guest_walker guest_walker32
+ #define FNAME(name) paging##32_##name
+ #define PT_BASE_ADDR_MASK PT32_BASE_ADDR_MASK
+ #define PT_DIR_BASE_ADDR_MASK PT32_DIR_BASE_ADDR_MASK
+ #define PT_INDEX(addr, level) PT32_INDEX(addr, level)
+ #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
+ #define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
+ #define PT_PTE_COPY_MASK PT32_PTE_COPY_MASK
+ #define PT_MAX_FULL_LEVELS 2
+#else
+ #error Invalid PTTYPE value
+#endif
+
+/*
+ * The guest_walker structure emulates the behavior of the hardware page
+ * table walker.
+ */
+struct guest_walker {
+ int level;
+ gfn_t table_gfn[PT_MAX_FULL_LEVELS];
+ pt_element_t *table;
+ pt_element_t *ptep;
+ pt_element_t inherited_ar;
+ gfn_t gfn;
+ u32 error_code;
+};
+
+/*
+ * Fetch a guest pte for a guest virtual address
+ */
+static int FNAME(walk_addr)(struct guest_walker *walker,
+ struct kvm_vcpu *vcpu, gva_t addr,
+ int write_fault, int user_fault, int fetch_fault)
+{
+ hpa_t hpa;
+ struct kvm_memory_slot *slot;
+ pt_element_t *ptep;
+ pt_element_t root;
+ gfn_t table_gfn;
+
+ pgprintk("%s: addr %lx\n", __FUNCTION__, addr);
+ walker->level = vcpu->mmu.root_level;
+ walker->table = NULL;
+ root = vcpu->cr3;
+#if PTTYPE == 64
+ if (!is_long_mode(vcpu)) {
+ walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3];
+ root = *walker->ptep;
+ if (!(root & PT_PRESENT_MASK))
+ goto not_present;
+ --walker->level;
+ }
+#endif
+ table_gfn = (root & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
+ walker->table_gfn[walker->level - 1] = table_gfn;
+ pgprintk("%s: table_gfn[%d] %lx\n", __FUNCTION__,
+ walker->level - 1, table_gfn);
+ slot = gfn_to_memslot(vcpu->kvm, table_gfn);
+ hpa = safe_gpa_to_hpa(vcpu, root & PT64_BASE_ADDR_MASK);
+ walker->table = kmap_atomic(pfn_to_page(hpa >> PAGE_SHIFT), KM_USER0);
+
+ ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) ||
+ (vcpu->cr3 & ~(PAGE_MASK | CR3_FLAGS_MASK)) == 0);
+
+ walker->inherited_ar = PT_USER_MASK | PT_WRITABLE_MASK;
+
+ for (;;) {
+ int index = PT_INDEX(addr, walker->level);
+ hpa_t paddr;
+
+ ptep = &walker->table[index];
+ ASSERT(((unsigned long)walker->table & PAGE_MASK) ==
+ ((unsigned long)ptep & PAGE_MASK));
+
+ if (!is_present_pte(*ptep))
+ goto not_present;
+
+ if (write_fault && !is_writeble_pte(*ptep))
+ if (user_fault || is_write_protection(vcpu))
+ goto access_error;
+
+ if (user_fault && !(*ptep & PT_USER_MASK))
+ goto access_error;
+
+#if PTTYPE == 64
+ if (fetch_fault && is_nx(vcpu) && (*ptep & PT64_NX_MASK))
+ goto access_error;
+#endif
+
+ if (!(*ptep & PT_ACCESSED_MASK))
+ *ptep |= PT_ACCESSED_MASK; /* avoid rmw */
+
+ if (walker->level == PT_PAGE_TABLE_LEVEL) {
+ walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
+ >> PAGE_SHIFT;
+ break;
+ }
+
+ if (walker->level == PT_DIRECTORY_LEVEL
+ && (*ptep & PT_PAGE_SIZE_MASK)
+ && (PTTYPE == 64 || is_pse(vcpu))) {
+ walker->gfn = (*ptep & PT_DIR_BASE_ADDR_MASK)
+ >> PAGE_SHIFT;
+ walker->gfn += PT_INDEX(addr, PT_PAGE_TABLE_LEVEL);
+ break;
+ }
+
+ if (walker->level != 3 || is_long_mode(vcpu))
+ walker->inherited_ar &= walker->table[index];
+ table_gfn = (*ptep & PT_BASE_ADDR_MASK) >> PAGE_SHIFT;
+ paddr = safe_gpa_to_hpa(vcpu, *ptep & PT_BASE_ADDR_MASK);
+ kunmap_atomic(walker->table, KM_USER0);
+ walker->table = kmap_atomic(pfn_to_page(paddr >> PAGE_SHIFT),
+ KM_USER0);
+ --walker->level;
+ walker->table_gfn[walker->level - 1 ] = table_gfn;
+ pgprintk("%s: table_gfn[%d] %lx\n", __FUNCTION__,
+ walker->level - 1, table_gfn);
+ }
+ walker->ptep = ptep;
+ pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep);
+ return 1;
+
+not_present:
+ walker->error_code = 0;
+ goto err;
+
+access_error:
+ walker->error_code = PFERR_PRESENT_MASK;
+
+err:
+ if (write_fault)
+ walker->error_code |= PFERR_WRITE_MASK;
+ if (user_fault)
+ walker->error_code |= PFERR_USER_MASK;
+ if (fetch_fault)
+ walker->error_code |= PFERR_FETCH_MASK;
+ return 0;
+}
+
+static void FNAME(release_walker)(struct guest_walker *walker)
+{
+ if (walker->table)
+ kunmap_atomic(walker->table, KM_USER0);
+}
+
+static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte,
+ u64 *shadow_pte, u64 access_bits, gfn_t gfn)
+{
+ ASSERT(*shadow_pte == 0);
+ access_bits &= guest_pte;
+ *shadow_pte = (guest_pte & PT_PTE_COPY_MASK);
+ set_pte_common(vcpu, shadow_pte, guest_pte & PT_BASE_ADDR_MASK,
+ guest_pte & PT_DIRTY_MASK, access_bits, gfn);
+}
+
+static void FNAME(set_pde)(struct kvm_vcpu *vcpu, u64 guest_pde,
+ u64 *shadow_pte, u64 access_bits, gfn_t gfn)
+{
+ gpa_t gaddr;
+
+ ASSERT(*shadow_pte == 0);
+ access_bits &= guest_pde;
+ gaddr = (gpa_t)gfn << PAGE_SHIFT;
+ if (PTTYPE == 32 && is_cpuid_PSE36())
+ gaddr |= (guest_pde & PT32_DIR_PSE36_MASK) <<
+ (32 - PT32_DIR_PSE36_SHIFT);
+ *shadow_pte = guest_pde & PT_PTE_COPY_MASK;
+ set_pte_common(vcpu, shadow_pte, gaddr,
+ guest_pde & PT_DIRTY_MASK, access_bits, gfn);
+}
+
+/*
+ * Fetch a shadow pte for a specific level in the paging hierarchy.
+ */
+static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+ struct guest_walker *walker)
+{
+ hpa_t shadow_addr;
+ int level;
+ u64 *prev_shadow_ent = NULL;
+ pt_element_t *guest_ent = walker->ptep;
+
+ if (!is_present_pte(*guest_ent))
+ return NULL;
+
+ shadow_addr = vcpu->mmu.root_hpa;
+ level = vcpu->mmu.shadow_root_level;
+ if (level == PT32E_ROOT_LEVEL) {
+ shadow_addr = vcpu->mmu.pae_root[(addr >> 30) & 3];
+ shadow_addr &= PT64_BASE_ADDR_MASK;
+ --level;
+ }
+
+ for (; ; level--) {
+ u32 index = SHADOW_PT_INDEX(addr, level);
+ u64 *shadow_ent = ((u64 *)__va(shadow_addr)) + index;
+ struct kvm_mmu_page *shadow_page;
+ u64 shadow_pte;
+ int metaphysical;
+ gfn_t table_gfn;
+
+ if (is_present_pte(*shadow_ent) || is_io_pte(*shadow_ent)) {
+ if (level == PT_PAGE_TABLE_LEVEL)
+ return shadow_ent;
+ shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
+ prev_shadow_ent = shadow_ent;
+ continue;
+ }
+
+ if (level == PT_PAGE_TABLE_LEVEL) {
+
+ if (walker->level == PT_DIRECTORY_LEVEL) {
+ if (prev_shadow_ent)
+ *prev_shadow_ent |= PT_SHADOW_PS_MARK;
+ FNAME(set_pde)(vcpu, *guest_ent, shadow_ent,
+ walker->inherited_ar,
+ walker->gfn);
+ } else {
+ ASSERT(walker->level == PT_PAGE_TABLE_LEVEL);
+ FNAME(set_pte)(vcpu, *guest_ent, shadow_ent,
+ walker->inherited_ar,
+ walker->gfn);
+ }
+ return shadow_ent;
+ }
+
+ if (level - 1 == PT_PAGE_TABLE_LEVEL
+ && walker->level == PT_DIRECTORY_LEVEL) {
+ metaphysical = 1;
+ table_gfn = (*guest_ent & PT_BASE_ADDR_MASK)
+ >> PAGE_SHIFT;
+ } else {
+ metaphysical = 0;
+ table_gfn = walker->table_gfn[level - 2];
+ }
+ shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
+ metaphysical, shadow_ent);
+ shadow_addr = shadow_page->page_hpa;
+ shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
+ | PT_WRITABLE_MASK | PT_USER_MASK;
+ *shadow_ent = shadow_pte;
+ prev_shadow_ent = shadow_ent;
+ }
+}
+
+/*
+ * The guest faulted for write. We need to
+ *
+ * - check write permissions
+ * - update the guest pte dirty bit
+ * - update our own dirty page tracking structures
+ */
+static int FNAME(fix_write_pf)(struct kvm_vcpu *vcpu,
+ u64 *shadow_ent,
+ struct guest_walker *walker,
+ gva_t addr,
+ int user,
+ int *write_pt)
+{
+ pt_element_t *guest_ent;
+ int writable_shadow;
+ gfn_t gfn;
+ struct kvm_mmu_page *page;
+
+ if (is_writeble_pte(*shadow_ent))
+ return !user || (*shadow_ent & PT_USER_MASK);
+
+ writable_shadow = *shadow_ent & PT_SHADOW_WRITABLE_MASK;
+ if (user) {
+ /*
+ * User mode access. Fail if it's a kernel page or a read-only
+ * page.
+ */
+ if (!(*shadow_ent & PT_SHADOW_USER_MASK) || !writable_shadow)
+ return 0;
+ ASSERT(*shadow_ent & PT_USER_MASK);
+ } else
+ /*
+ * Kernel mode access. Fail if it's a read-only page and
+ * supervisor write protection is enabled.
+ */
+ if (!writable_shadow) {
+ if (is_write_protection(vcpu))
+ return 0;
+ *shadow_ent &= ~PT_USER_MASK;
+ }
+
+ guest_ent = walker->ptep;
+
+ if (!is_present_pte(*guest_ent)) {
+ *shadow_ent = 0;
+ return 0;
+ }
+
+ gfn = walker->gfn;
+
+ if (user) {
+ /*
+ * Usermode page faults won't be for page table updates.
+ */
+ while ((page = kvm_mmu_lookup_page(vcpu, gfn)) != NULL) {
+ pgprintk("%s: zap %lx %x\n",
+ __FUNCTION__, gfn, page->role.word);
+ kvm_mmu_zap_page(vcpu, page);
+ }
+ } else if (kvm_mmu_lookup_page(vcpu, gfn)) {
+ pgprintk("%s: found shadow page for %lx, marking ro\n",
+ __FUNCTION__, gfn);
+ *guest_ent |= PT_DIRTY_MASK;
+ *write_pt = 1;
+ return 0;
+ }
+ mark_page_dirty(vcpu->kvm, gfn);
+ *shadow_ent |= PT_WRITABLE_MASK;
+ *guest_ent |= PT_DIRTY_MASK;
+ rmap_add(vcpu, shadow_ent);
+
+ return 1;
+}
+
+/*
+ * Page fault handler. There are several causes for a page fault:
+ * - there is no shadow pte for the guest pte
+ * - write access through a shadow pte marked read only so that we can set
+ * the dirty bit
+ * - write access to a shadow pte marked read only so we can update the page
+ * dirty bitmap, when userspace requests it
+ * - mmio access; in this case we will never install a present shadow pte
+ * - normal guest page fault due to the guest pte marked not present, not
+ * writable, or not executable
+ *
+ * Returns: 1 if we need to emulate the instruction, 0 otherwise, or
+ * a negative value on error.
+ */
+static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
+ u32 error_code)
+{
+ int write_fault = error_code & PFERR_WRITE_MASK;
+ int user_fault = error_code & PFERR_USER_MASK;
+ int fetch_fault = error_code & PFERR_FETCH_MASK;
+ struct guest_walker walker;
+ u64 *shadow_pte;
+ int fixed;
+ int write_pt = 0;
+ int r;
+
+ pgprintk("%s: addr %lx err %x\n", __FUNCTION__, addr, error_code);
+ kvm_mmu_audit(vcpu, "pre page fault");
+
+ r = mmu_topup_memory_caches(vcpu);
+ if (r)
+ return r;
+
+ /*
+ * Look up the shadow pte for the faulting address.
+ */
+ r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault,
+ fetch_fault);
+
+ /*
+ * The page is not mapped by the guest. Let the guest handle it.
+ */
+ if (!r) {
+ pgprintk("%s: guest page fault\n", __FUNCTION__);
+ inject_page_fault(vcpu, addr, walker.error_code);
+ FNAME(release_walker)(&walker);
+ return 0;
+ }
+
+ shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
+ pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__,
+ shadow_pte, *shadow_pte);
+
+ /*
+ * Update the shadow pte.
+ */
+ if (write_fault)
+ fixed = FNAME(fix_write_pf)(vcpu, shadow_pte, &walker, addr,
+ user_fault, &write_pt);
+ else
+ fixed = fix_read_pf(shadow_pte);
+
+ pgprintk("%s: updated shadow pte %p %llx\n", __FUNCTION__,
+ shadow_pte, *shadow_pte);
+
+ FNAME(release_walker)(&walker);
+
+ /*
+ * mmio: emulate if accessible, otherwise its a guest fault.
+ */
+ if (is_io_pte(*shadow_pte)) {
+ return 1;
+ }
+
+ ++kvm_stat.pf_fixed;
+ kvm_mmu_audit(vcpu, "post page fault (fixed)");
+
+ return write_pt;
+}
+
+static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
+{
+ struct guest_walker walker;
+ pt_element_t guest_pte;
+ gpa_t gpa;
+
+ FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
+ guest_pte = *walker.ptep;
+ FNAME(release_walker)(&walker);
+
+ if (!is_present_pte(guest_pte))
+ return UNMAPPED_GVA;
+
+ if (walker.level == PT_DIRECTORY_LEVEL) {
+ ASSERT((guest_pte & PT_PAGE_SIZE_MASK));
+ ASSERT(PTTYPE == 64 || is_pse(vcpu));
+
+ gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr &
+ (PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK));
+
+ if (PTTYPE == 32 && is_cpuid_PSE36())
+ gpa |= (guest_pte & PT32_DIR_PSE36_MASK) <<
+ (32 - PT32_DIR_PSE36_SHIFT);
+ } else {
+ gpa = (guest_pte & PT_BASE_ADDR_MASK);
+ gpa |= (vaddr & ~PAGE_MASK);
+ }
+
+ return gpa;
+}
+
+#undef pt_element_t
+#undef guest_walker
+#undef FNAME
+#undef PT_BASE_ADDR_MASK
+#undef PT_INDEX
+#undef SHADOW_PT_INDEX
+#undef PT_LEVEL_MASK
+#undef PT_PTE_COPY_MASK
+#undef PT_NON_PTE_COPY_MASK
+#undef PT_DIR_BASE_ADDR_MASK
+#undef PT_MAX_FULL_LEVELS
diff --git a/drivers/kvm/segment_descriptor.h b/drivers/kvm/segment_descriptor.h
new file mode 100644
index 00000000000..71fdf458619
--- /dev/null
+++ b/drivers/kvm/segment_descriptor.h
@@ -0,0 +1,17 @@
+struct segment_descriptor {
+ u16 limit_low;
+ u16 base_low;
+ u8 base_mid;
+ u8 type : 4;
+ u8 system : 1;
+ u8 dpl : 2;
+ u8 present : 1;
+ u8 limit_high : 4;
+ u8 avl : 1;
+ u8 long_mode : 1;
+ u8 default_op : 1;
+ u8 granularity : 1;
+ u8 base_high;
+} __attribute__((packed));
+
+
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
new file mode 100644
index 00000000000..c79df79307e
--- /dev/null
+++ b/drivers/kvm/svm.c
@@ -0,0 +1,1721 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * AMD SVM support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Yaniv Kamay <yaniv@qumranet.com>
+ * Avi Kivity <avi@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+#include <linux/profile.h>
+#include <asm/desc.h>
+
+#include "kvm_svm.h"
+#include "x86_emulate.h"
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+#define IOPM_ALLOC_ORDER 2
+#define MSRPM_ALLOC_ORDER 1
+
+#define DB_VECTOR 1
+#define UD_VECTOR 6
+#define GP_VECTOR 13
+
+#define DR7_GD_MASK (1 << 13)
+#define DR6_BD_MASK (1 << 13)
+#define CR4_DE_MASK (1UL << 3)
+
+#define SEG_TYPE_LDT 2
+#define SEG_TYPE_BUSY_TSS16 3
+
+#define KVM_EFER_LMA (1 << 10)
+#define KVM_EFER_LME (1 << 8)
+
+unsigned long iopm_base;
+unsigned long msrpm_base;
+
+struct kvm_ldttss_desc {
+ u16 limit0;
+ u16 base0;
+ unsigned base1 : 8, type : 5, dpl : 2, p : 1;
+ unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
+ u32 base3;
+ u32 zero1;
+} __attribute__((packed));
+
+struct svm_cpu_data {
+ int cpu;
+
+ uint64_t asid_generation;
+ uint32_t max_asid;
+ uint32_t next_asid;
+ struct kvm_ldttss_desc *tss_desc;
+
+ struct page *save_area;
+};
+
+static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
+
+struct svm_init_data {
+ int cpu;
+ int r;
+};
+
+static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
+
+#define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges))
+#define MSRS_RANGE_SIZE 2048
+#define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
+
+#define MAX_INST_SIZE 15
+
+static unsigned get_addr_size(struct kvm_vcpu *vcpu)
+{
+ struct vmcb_save_area *sa = &vcpu->svm->vmcb->save;
+ u16 cs_attrib;
+
+ if (!(sa->cr0 & CR0_PE_MASK) || (sa->rflags & X86_EFLAGS_VM))
+ return 2;
+
+ cs_attrib = sa->cs.attrib;
+
+ return (cs_attrib & SVM_SELECTOR_L_MASK) ? 8 :
+ (cs_attrib & SVM_SELECTOR_DB_MASK) ? 4 : 2;
+}
+
+static inline u8 pop_irq(struct kvm_vcpu *vcpu)
+{
+ int word_index = __ffs(vcpu->irq_summary);
+ int bit_index = __ffs(vcpu->irq_pending[word_index]);
+ int irq = word_index * BITS_PER_LONG + bit_index;
+
+ clear_bit(bit_index, &vcpu->irq_pending[word_index]);
+ if (!vcpu->irq_pending[word_index])
+ clear_bit(word_index, &vcpu->irq_summary);
+ return irq;
+}
+
+static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq)
+{
+ set_bit(irq, vcpu->irq_pending);
+ set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
+}
+
+static inline void clgi(void)
+{
+ asm volatile (SVM_CLGI);
+}
+
+static inline void stgi(void)
+{
+ asm volatile (SVM_STGI);
+}
+
+static inline void invlpga(unsigned long addr, u32 asid)
+{
+ asm volatile (SVM_INVLPGA :: "a"(addr), "c"(asid));
+}
+
+static inline unsigned long kvm_read_cr2(void)
+{
+ unsigned long cr2;
+
+ asm volatile ("mov %%cr2, %0" : "=r" (cr2));
+ return cr2;
+}
+
+static inline void kvm_write_cr2(unsigned long val)
+{
+ asm volatile ("mov %0, %%cr2" :: "r" (val));
+}
+
+static inline unsigned long read_dr6(void)
+{
+ unsigned long dr6;
+
+ asm volatile ("mov %%dr6, %0" : "=r" (dr6));
+ return dr6;
+}
+
+static inline void write_dr6(unsigned long val)
+{
+ asm volatile ("mov %0, %%dr6" :: "r" (val));
+}
+
+static inline unsigned long read_dr7(void)
+{
+ unsigned long dr7;
+
+ asm volatile ("mov %%dr7, %0" : "=r" (dr7));
+ return dr7;
+}
+
+static inline void write_dr7(unsigned long val)
+{
+ asm volatile ("mov %0, %%dr7" :: "r" (val));
+}
+
+static inline void force_new_asid(struct kvm_vcpu *vcpu)
+{
+ vcpu->svm->asid_generation--;
+}
+
+static inline void flush_guest_tlb(struct kvm_vcpu *vcpu)
+{
+ force_new_asid(vcpu);
+}
+
+static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+ if (!(efer & KVM_EFER_LMA))
+ efer &= ~KVM_EFER_LME;
+
+ vcpu->svm->vmcb->save.efer = efer | MSR_EFER_SVME_MASK;
+ vcpu->shadow_efer = efer;
+}
+
+static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
+{
+ vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
+ SVM_EVTINJ_VALID_ERR |
+ SVM_EVTINJ_TYPE_EXEPT |
+ GP_VECTOR;
+ vcpu->svm->vmcb->control.event_inj_err = error_code;
+}
+
+static void inject_ud(struct kvm_vcpu *vcpu)
+{
+ vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
+ SVM_EVTINJ_TYPE_EXEPT |
+ UD_VECTOR;
+}
+
+static void inject_db(struct kvm_vcpu *vcpu)
+{
+ vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
+ SVM_EVTINJ_TYPE_EXEPT |
+ DB_VECTOR;
+}
+
+static int is_page_fault(uint32_t info)
+{
+ info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
+ return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT);
+}
+
+static int is_external_interrupt(u32 info)
+{
+ info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
+ return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
+}
+
+static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+ if (!vcpu->svm->next_rip) {
+ printk(KERN_DEBUG "%s: NOP\n", __FUNCTION__);
+ return;
+ }
+ if (vcpu->svm->next_rip - vcpu->svm->vmcb->save.rip > 15) {
+ printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n",
+ __FUNCTION__,
+ vcpu->svm->vmcb->save.rip,
+ vcpu->svm->next_rip);
+ }
+
+ vcpu->rip = vcpu->svm->vmcb->save.rip = vcpu->svm->next_rip;
+ vcpu->svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+
+ vcpu->interrupt_window_open = 1;
+}
+
+static int has_svm(void)
+{
+ uint32_t eax, ebx, ecx, edx;
+
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
+ printk(KERN_INFO "has_svm: not amd\n");
+ return 0;
+ }
+
+ cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
+ if (eax < SVM_CPUID_FUNC) {
+ printk(KERN_INFO "has_svm: can't execute cpuid_8000000a\n");
+ return 0;
+ }
+
+ cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
+ if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) {
+ printk(KERN_DEBUG "has_svm: svm not available\n");
+ return 0;
+ }
+ return 1;
+}
+
+static void svm_hardware_disable(void *garbage)
+{
+ struct svm_cpu_data *svm_data
+ = per_cpu(svm_data, raw_smp_processor_id());
+
+ if (svm_data) {
+ uint64_t efer;
+
+ wrmsrl(MSR_VM_HSAVE_PA, 0);
+ rdmsrl(MSR_EFER, efer);
+ wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
+ per_cpu(svm_data, raw_smp_processor_id()) = 0;
+ __free_page(svm_data->save_area);
+ kfree(svm_data);
+ }
+}
+
+static void svm_hardware_enable(void *garbage)
+{
+
+ struct svm_cpu_data *svm_data;
+ uint64_t efer;
+#ifdef CONFIG_X86_64
+ struct desc_ptr gdt_descr;
+#else
+ struct Xgt_desc_struct gdt_descr;
+#endif
+ struct desc_struct *gdt;
+ int me = raw_smp_processor_id();
+
+ if (!has_svm()) {
+ printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me);
+ return;
+ }
+ svm_data = per_cpu(svm_data, me);
+
+ if (!svm_data) {
+ printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n",
+ me);
+ return;
+ }
+
+ svm_data->asid_generation = 1;
+ svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
+ svm_data->next_asid = svm_data->max_asid + 1;
+
+ asm volatile ( "sgdt %0" : "=m"(gdt_descr) );
+ gdt = (struct desc_struct *)gdt_descr.address;
+ svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
+
+ rdmsrl(MSR_EFER, efer);
+ wrmsrl(MSR_EFER, efer | MSR_EFER_SVME_MASK);
+
+ wrmsrl(MSR_VM_HSAVE_PA,
+ page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
+}
+
+static int svm_cpu_init(int cpu)
+{
+ struct svm_cpu_data *svm_data;
+ int r;
+
+ svm_data = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
+ if (!svm_data)
+ return -ENOMEM;
+ svm_data->cpu = cpu;
+ svm_data->save_area = alloc_page(GFP_KERNEL);
+ r = -ENOMEM;
+ if (!svm_data->save_area)
+ goto err_1;
+
+ per_cpu(svm_data, cpu) = svm_data;
+
+ return 0;
+
+err_1:
+ kfree(svm_data);
+ return r;
+
+}
+
+static int set_msr_interception(u32 *msrpm, unsigned msr,
+ int read, int write)
+{
+ int i;
+
+ for (i = 0; i < NUM_MSR_MAPS; i++) {
+ if (msr >= msrpm_ranges[i] &&
+ msr < msrpm_ranges[i] + MSRS_IN_RANGE) {
+ u32 msr_offset = (i * MSRS_IN_RANGE + msr -
+ msrpm_ranges[i]) * 2;
+
+ u32 *base = msrpm + (msr_offset / 32);
+ u32 msr_shift = msr_offset % 32;
+ u32 mask = ((write) ? 0 : 2) | ((read) ? 0 : 1);
+ *base = (*base & ~(0x3 << msr_shift)) |
+ (mask << msr_shift);
+ return 1;
+ }
+ }
+ printk(KERN_DEBUG "%s: not found 0x%x\n", __FUNCTION__, msr);
+ return 0;
+}
+
+static __init int svm_hardware_setup(void)
+{
+ int cpu;
+ struct page *iopm_pages;
+ struct page *msrpm_pages;
+ void *msrpm_va;
+ int r;
+
+ kvm_emulator_want_group7_invlpg();
+
+ iopm_pages = alloc_pages(GFP_KERNEL, IOPM_ALLOC_ORDER);
+
+ if (!iopm_pages)
+ return -ENOMEM;
+ memset(page_address(iopm_pages), 0xff,
+ PAGE_SIZE * (1 << IOPM_ALLOC_ORDER));
+ iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
+
+
+ msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
+
+ r = -ENOMEM;
+ if (!msrpm_pages)
+ goto err_1;
+
+ msrpm_va = page_address(msrpm_pages);
+ memset(msrpm_va, 0xff, PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER));
+ msrpm_base = page_to_pfn(msrpm_pages) << PAGE_SHIFT;
+
+#ifdef CONFIG_X86_64
+ set_msr_interception(msrpm_va, MSR_GS_BASE, 1, 1);
+ set_msr_interception(msrpm_va, MSR_FS_BASE, 1, 1);
+ set_msr_interception(msrpm_va, MSR_KERNEL_GS_BASE, 1, 1);
+ set_msr_interception(msrpm_va, MSR_LSTAR, 1, 1);
+ set_msr_interception(msrpm_va, MSR_CSTAR, 1, 1);
+ set_msr_interception(msrpm_va, MSR_SYSCALL_MASK, 1, 1);
+#endif
+ set_msr_interception(msrpm_va, MSR_K6_STAR, 1, 1);
+ set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_CS, 1, 1);
+ set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_ESP, 1, 1);
+ set_msr_interception(msrpm_va, MSR_IA32_SYSENTER_EIP, 1, 1);
+
+ for_each_online_cpu(cpu) {
+ r = svm_cpu_init(cpu);
+ if (r)
+ goto err_2;
+ }
+ return 0;
+
+err_2:
+ __free_pages(msrpm_pages, MSRPM_ALLOC_ORDER);
+ msrpm_base = 0;
+err_1:
+ __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
+ iopm_base = 0;
+ return r;
+}
+
+static __exit void svm_hardware_unsetup(void)
+{
+ __free_pages(pfn_to_page(msrpm_base >> PAGE_SHIFT), MSRPM_ALLOC_ORDER);
+ __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
+ iopm_base = msrpm_base = 0;
+}
+
+static void init_seg(struct vmcb_seg *seg)
+{
+ seg->selector = 0;
+ seg->attrib = SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK |
+ SVM_SELECTOR_WRITE_MASK; /* Read/Write Data Segment */
+ seg->limit = 0xffff;
+ seg->base = 0;
+}
+
+static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
+{
+ seg->selector = 0;
+ seg->attrib = SVM_SELECTOR_P_MASK | type;
+ seg->limit = 0xffff;
+ seg->base = 0;
+}
+
+static int svm_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
+static void init_vmcb(struct vmcb *vmcb)
+{
+ struct vmcb_control_area *control = &vmcb->control;
+ struct vmcb_save_area *save = &vmcb->save;
+ u64 tsc;
+
+ control->intercept_cr_read = INTERCEPT_CR0_MASK |
+ INTERCEPT_CR3_MASK |
+ INTERCEPT_CR4_MASK;
+
+ control->intercept_cr_write = INTERCEPT_CR0_MASK |
+ INTERCEPT_CR3_MASK |
+ INTERCEPT_CR4_MASK;
+
+ control->intercept_dr_read = INTERCEPT_DR0_MASK |
+ INTERCEPT_DR1_MASK |
+ INTERCEPT_DR2_MASK |
+ INTERCEPT_DR3_MASK;
+
+ control->intercept_dr_write = INTERCEPT_DR0_MASK |
+ INTERCEPT_DR1_MASK |
+ INTERCEPT_DR2_MASK |
+ INTERCEPT_DR3_MASK |
+ INTERCEPT_DR5_MASK |
+ INTERCEPT_DR7_MASK;
+
+ control->intercept_exceptions = 1 << PF_VECTOR;
+
+
+ control->intercept = (1ULL << INTERCEPT_INTR) |
+ (1ULL << INTERCEPT_NMI) |
+ /*
+ * selective cr0 intercept bug?
+ * 0: 0f 22 d8 mov %eax,%cr3
+ * 3: 0f 20 c0 mov %cr0,%eax
+ * 6: 0d 00 00 00 80 or $0x80000000,%eax
+ * b: 0f 22 c0 mov %eax,%cr0
+ * set cr3 ->interception
+ * get cr0 ->interception
+ * set cr0 -> no interception
+ */
+ /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */
+ (1ULL << INTERCEPT_CPUID) |
+ (1ULL << INTERCEPT_HLT) |
+ (1ULL << INTERCEPT_INVLPGA) |
+ (1ULL << INTERCEPT_IOIO_PROT) |
+ (1ULL << INTERCEPT_MSR_PROT) |
+ (1ULL << INTERCEPT_TASK_SWITCH) |
+ (1ULL << INTERCEPT_SHUTDOWN) |
+ (1ULL << INTERCEPT_VMRUN) |
+ (1ULL << INTERCEPT_VMMCALL) |
+ (1ULL << INTERCEPT_VMLOAD) |
+ (1ULL << INTERCEPT_VMSAVE) |
+ (1ULL << INTERCEPT_STGI) |
+ (1ULL << INTERCEPT_CLGI) |
+ (1ULL << INTERCEPT_SKINIT);
+
+ control->iopm_base_pa = iopm_base;
+ control->msrpm_base_pa = msrpm_base;
+ rdtscll(tsc);
+ control->tsc_offset = -tsc;
+ control->int_ctl = V_INTR_MASKING_MASK;
+
+ init_seg(&save->es);
+ init_seg(&save->ss);
+ init_seg(&save->ds);
+ init_seg(&save->fs);
+ init_seg(&save->gs);
+
+ save->cs.selector = 0xf000;
+ /* Executable/Readable Code Segment */
+ save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
+ SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
+ save->cs.limit = 0xffff;
+ save->cs.base = 0xffff0000;
+
+ save->gdtr.limit = 0xffff;
+ save->idtr.limit = 0xffff;
+
+ init_sys_seg(&save->ldtr, SEG_TYPE_LDT);
+ init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
+
+ save->efer = MSR_EFER_SVME_MASK;
+
+ save->dr6 = 0xffff0ff0;
+ save->dr7 = 0x400;
+ save->rflags = 2;
+ save->rip = 0x0000fff0;
+
+ /*
+ * cr0 val on cpu init should be 0x60000010, we enable cpu
+ * cache by default. the orderly way is to enable cache in bios.
+ */
+ save->cr0 = 0x00000010 | CR0_PG_MASK;
+ save->cr4 = CR4_PAE_MASK;
+ /* rdx = ?? */
+}
+
+static int svm_create_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct page *page;
+ int r;
+
+ r = -ENOMEM;
+ vcpu->svm = kzalloc(sizeof *vcpu->svm, GFP_KERNEL);
+ if (!vcpu->svm)
+ goto out1;
+ page = alloc_page(GFP_KERNEL);
+ if (!page)
+ goto out2;
+
+ vcpu->svm->vmcb = page_address(page);
+ memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+ vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
+ vcpu->svm->cr0 = 0x00000010;
+ vcpu->svm->asid_generation = 0;
+ memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs));
+ init_vmcb(vcpu->svm->vmcb);
+
+ fx_init(vcpu);
+
+ return 0;
+
+out2:
+ kfree(vcpu->svm);
+out1:
+ return r;
+}
+
+static void svm_free_vcpu(struct kvm_vcpu *vcpu)
+{
+ if (!vcpu->svm)
+ return;
+ if (vcpu->svm->vmcb)
+ __free_page(pfn_to_page(vcpu->svm->vmcb_pa >> PAGE_SHIFT));
+ kfree(vcpu->svm);
+}
+
+static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu)
+{
+ get_cpu();
+ return vcpu;
+}
+
+static void svm_vcpu_put(struct kvm_vcpu *vcpu)
+{
+ put_cpu();
+}
+
+static void svm_cache_regs(struct kvm_vcpu *vcpu)
+{
+ vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax;
+ vcpu->regs[VCPU_REGS_RSP] = vcpu->svm->vmcb->save.rsp;
+ vcpu->rip = vcpu->svm->vmcb->save.rip;
+}
+
+static void svm_decache_regs(struct kvm_vcpu *vcpu)
+{
+ vcpu->svm->vmcb->save.rax = vcpu->regs[VCPU_REGS_RAX];
+ vcpu->svm->vmcb->save.rsp = vcpu->regs[VCPU_REGS_RSP];
+ vcpu->svm->vmcb->save.rip = vcpu->rip;
+}
+
+static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
+{
+ return vcpu->svm->vmcb->save.rflags;
+}
+
+static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+ vcpu->svm->vmcb->save.rflags = rflags;
+}
+
+static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
+{
+ struct vmcb_save_area *save = &vcpu->svm->vmcb->save;
+
+ switch (seg) {
+ case VCPU_SREG_CS: return &save->cs;
+ case VCPU_SREG_DS: return &save->ds;
+ case VCPU_SREG_ES: return &save->es;
+ case VCPU_SREG_FS: return &save->fs;
+ case VCPU_SREG_GS: return &save->gs;
+ case VCPU_SREG_SS: return &save->ss;
+ case VCPU_SREG_TR: return &save->tr;
+ case VCPU_SREG_LDTR: return &save->ldtr;
+ }
+ BUG();
+ return 0;
+}
+
+static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+ struct vmcb_seg *s = svm_seg(vcpu, seg);
+
+ return s->base;
+}
+
+static void svm_get_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ struct vmcb_seg *s = svm_seg(vcpu, seg);
+
+ var->base = s->base;
+ var->limit = s->limit;
+ var->selector = s->selector;
+ var->type = s->attrib & SVM_SELECTOR_TYPE_MASK;
+ var->s = (s->attrib >> SVM_SELECTOR_S_SHIFT) & 1;
+ var->dpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
+ var->present = (s->attrib >> SVM_SELECTOR_P_SHIFT) & 1;
+ var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1;
+ var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
+ var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
+ var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
+ var->unusable = !var->present;
+}
+
+static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
+{
+ struct vmcb_seg *s = svm_seg(vcpu, VCPU_SREG_CS);
+
+ *db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
+ *l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
+}
+
+static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ dt->limit = vcpu->svm->vmcb->save.idtr.limit;
+ dt->base = vcpu->svm->vmcb->save.idtr.base;
+}
+
+static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ vcpu->svm->vmcb->save.idtr.limit = dt->limit;
+ vcpu->svm->vmcb->save.idtr.base = dt->base ;
+}
+
+static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ dt->limit = vcpu->svm->vmcb->save.gdtr.limit;
+ dt->base = vcpu->svm->vmcb->save.gdtr.base;
+}
+
+static void svm_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ vcpu->svm->vmcb->save.gdtr.limit = dt->limit;
+ vcpu->svm->vmcb->save.gdtr.base = dt->base ;
+}
+
+static void svm_decache_cr0_cr4_guest_bits(struct kvm_vcpu *vcpu)
+{
+}
+
+static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+#ifdef CONFIG_X86_64
+ if (vcpu->shadow_efer & KVM_EFER_LME) {
+ if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK)) {
+ vcpu->shadow_efer |= KVM_EFER_LMA;
+ vcpu->svm->vmcb->save.efer |= KVM_EFER_LMA | KVM_EFER_LME;
+ }
+
+ if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK) ) {
+ vcpu->shadow_efer &= ~KVM_EFER_LMA;
+ vcpu->svm->vmcb->save.efer &= ~(KVM_EFER_LMA | KVM_EFER_LME);
+ }
+ }
+#endif
+ vcpu->svm->cr0 = cr0;
+ vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK;
+ vcpu->cr0 = cr0;
+}
+
+static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+ vcpu->cr4 = cr4;
+ vcpu->svm->vmcb->save.cr4 = cr4 | CR4_PAE_MASK;
+}
+
+static void svm_set_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ struct vmcb_seg *s = svm_seg(vcpu, seg);
+
+ s->base = var->base;
+ s->limit = var->limit;
+ s->selector = var->selector;
+ if (var->unusable)
+ s->attrib = 0;
+ else {
+ s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
+ s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
+ s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
+ s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT;
+ s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
+ s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
+ s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
+ s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
+ }
+ if (seg == VCPU_SREG_CS)
+ vcpu->svm->vmcb->save.cpl
+ = (vcpu->svm->vmcb->save.cs.attrib
+ >> SVM_SELECTOR_DPL_SHIFT) & 3;
+
+}
+
+/* FIXME:
+
+ vcpu->svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
+ vcpu->svm->vmcb->control.int_ctl |= (sregs->cr8 & V_TPR_MASK);
+
+*/
+
+static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
+{
+ return -EOPNOTSUPP;
+}
+
+static void load_host_msrs(struct kvm_vcpu *vcpu)
+{
+ int i;
+
+ for ( i = 0; i < NR_HOST_SAVE_MSRS; i++)
+ wrmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]);
+}
+
+static void save_host_msrs(struct kvm_vcpu *vcpu)
+{
+ int i;
+
+ for ( i = 0; i < NR_HOST_SAVE_MSRS; i++)
+ rdmsrl(host_save_msrs[i], vcpu->svm->host_msrs[i]);
+}
+
+static void new_asid(struct kvm_vcpu *vcpu, struct svm_cpu_data *svm_data)
+{
+ if (svm_data->next_asid > svm_data->max_asid) {
+ ++svm_data->asid_generation;
+ svm_data->next_asid = 1;
+ vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
+ }
+
+ vcpu->cpu = svm_data->cpu;
+ vcpu->svm->asid_generation = svm_data->asid_generation;
+ vcpu->svm->vmcb->control.asid = svm_data->next_asid++;
+}
+
+static void svm_invlpg(struct kvm_vcpu *vcpu, gva_t address)
+{
+ invlpga(address, vcpu->svm->vmcb->control.asid); // is needed?
+}
+
+static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr)
+{
+ return vcpu->svm->db_regs[dr];
+}
+
+static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
+ int *exception)
+{
+ *exception = 0;
+
+ if (vcpu->svm->vmcb->save.dr7 & DR7_GD_MASK) {
+ vcpu->svm->vmcb->save.dr7 &= ~DR7_GD_MASK;
+ vcpu->svm->vmcb->save.dr6 |= DR6_BD_MASK;
+ *exception = DB_VECTOR;
+ return;
+ }
+
+ switch (dr) {
+ case 0 ... 3:
+ vcpu->svm->db_regs[dr] = value;
+ return;
+ case 4 ... 5:
+ if (vcpu->cr4 & CR4_DE_MASK) {
+ *exception = UD_VECTOR;
+ return;
+ }
+ case 7: {
+ if (value & ~((1ULL << 32) - 1)) {
+ *exception = GP_VECTOR;
+ return;
+ }
+ vcpu->svm->vmcb->save.dr7 = value;
+ return;
+ }
+ default:
+ printk(KERN_DEBUG "%s: unexpected dr %u\n",
+ __FUNCTION__, dr);
+ *exception = UD_VECTOR;
+ return;
+ }
+}
+
+static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 exit_int_info = vcpu->svm->vmcb->control.exit_int_info;
+ u64 fault_address;
+ u32 error_code;
+ enum emulation_result er;
+ int r;
+
+ if (is_external_interrupt(exit_int_info))
+ push_irq(vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
+
+ spin_lock(&vcpu->kvm->lock);
+
+ fault_address = vcpu->svm->vmcb->control.exit_info_2;
+ error_code = vcpu->svm->vmcb->control.exit_info_1;
+ r = kvm_mmu_page_fault(vcpu, fault_address, error_code);
+ if (r < 0) {
+ spin_unlock(&vcpu->kvm->lock);
+ return r;
+ }
+ if (!r) {
+ spin_unlock(&vcpu->kvm->lock);
+ return 1;
+ }
+ er = emulate_instruction(vcpu, kvm_run, fault_address, error_code);
+ spin_unlock(&vcpu->kvm->lock);
+
+ switch (er) {
+ case EMULATE_DONE:
+ return 1;
+ case EMULATE_DO_MMIO:
+ ++kvm_stat.mmio_exits;
+ kvm_run->exit_reason = KVM_EXIT_MMIO;
+ return 0;
+ case EMULATE_FAIL:
+ vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__);
+ break;
+ default:
+ BUG();
+ }
+
+ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+ return 0;
+}
+
+static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ /*
+ * VMCB is undefined after a SHUTDOWN intercept
+ * so reinitialize it.
+ */
+ memset(vcpu->svm->vmcb, 0, PAGE_SIZE);
+ init_vmcb(vcpu->svm->vmcb);
+
+ kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+ return 0;
+}
+
+static int io_get_override(struct kvm_vcpu *vcpu,
+ struct vmcb_seg **seg,
+ int *addr_override)
+{
+ u8 inst[MAX_INST_SIZE];
+ unsigned ins_length;
+ gva_t rip;
+ int i;
+
+ rip = vcpu->svm->vmcb->save.rip;
+ ins_length = vcpu->svm->next_rip - rip;
+ rip += vcpu->svm->vmcb->save.cs.base;
+
+ if (ins_length > MAX_INST_SIZE)
+ printk(KERN_DEBUG
+ "%s: inst length err, cs base 0x%llx rip 0x%llx "
+ "next rip 0x%llx ins_length %u\n",
+ __FUNCTION__,
+ vcpu->svm->vmcb->save.cs.base,
+ vcpu->svm->vmcb->save.rip,
+ vcpu->svm->vmcb->control.exit_info_2,
+ ins_length);
+
+ if (kvm_read_guest(vcpu, rip, ins_length, inst) != ins_length)
+ /* #PF */
+ return 0;
+
+ *addr_override = 0;
+ *seg = 0;
+ for (i = 0; i < ins_length; i++)
+ switch (inst[i]) {
+ case 0xf0:
+ case 0xf2:
+ case 0xf3:
+ case 0x66:
+ continue;
+ case 0x67:
+ *addr_override = 1;
+ continue;
+ case 0x2e:
+ *seg = &vcpu->svm->vmcb->save.cs;
+ continue;
+ case 0x36:
+ *seg = &vcpu->svm->vmcb->save.ss;
+ continue;
+ case 0x3e:
+ *seg = &vcpu->svm->vmcb->save.ds;
+ continue;
+ case 0x26:
+ *seg = &vcpu->svm->vmcb->save.es;
+ continue;
+ case 0x64:
+ *seg = &vcpu->svm->vmcb->save.fs;
+ continue;
+ case 0x65:
+ *seg = &vcpu->svm->vmcb->save.gs;
+ continue;
+ default:
+ return 1;
+ }
+ printk(KERN_DEBUG "%s: unexpected\n", __FUNCTION__);
+ return 0;
+}
+
+static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address)
+{
+ unsigned long addr_mask;
+ unsigned long *reg;
+ struct vmcb_seg *seg;
+ int addr_override;
+ struct vmcb_save_area *save_area = &vcpu->svm->vmcb->save;
+ u16 cs_attrib = save_area->cs.attrib;
+ unsigned addr_size = get_addr_size(vcpu);
+
+ if (!io_get_override(vcpu, &seg, &addr_override))
+ return 0;
+
+ if (addr_override)
+ addr_size = (addr_size == 2) ? 4: (addr_size >> 1);
+
+ if (ins) {
+ reg = &vcpu->regs[VCPU_REGS_RDI];
+ seg = &vcpu->svm->vmcb->save.es;
+ } else {
+ reg = &vcpu->regs[VCPU_REGS_RSI];
+ seg = (seg) ? seg : &vcpu->svm->vmcb->save.ds;
+ }
+
+ addr_mask = ~0ULL >> (64 - (addr_size * 8));
+
+ if ((cs_attrib & SVM_SELECTOR_L_MASK) &&
+ !(vcpu->svm->vmcb->save.rflags & X86_EFLAGS_VM)) {
+ *address = (*reg & addr_mask);
+ return addr_mask;
+ }
+
+ if (!(seg->attrib & SVM_SELECTOR_P_SHIFT)) {
+ svm_inject_gp(vcpu, 0);
+ return 0;
+ }
+
+ *address = (*reg & addr_mask) + seg->base;
+ return addr_mask;
+}
+
+static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug?
+ int _in = io_info & SVM_IOIO_TYPE_MASK;
+
+ ++kvm_stat.io_exits;
+
+ vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2;
+
+ kvm_run->exit_reason = KVM_EXIT_IO;
+ kvm_run->io.port = io_info >> 16;
+ kvm_run->io.direction = (_in) ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
+ kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT);
+ kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0;
+ kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0;
+
+ if (kvm_run->io.string) {
+ unsigned addr_mask;
+
+ addr_mask = io_adress(vcpu, _in, &kvm_run->io.address);
+ if (!addr_mask) {
+ printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__);
+ return 1;
+ }
+
+ if (kvm_run->io.rep) {
+ kvm_run->io.count = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
+ kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags
+ & X86_EFLAGS_DF) != 0;
+ }
+ } else {
+ kvm_run->io.value = vcpu->svm->vmcb->save.rax;
+ }
+ return 0;
+}
+
+
+static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ return 1;
+}
+
+static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1;
+ skip_emulated_instruction(vcpu);
+ if (vcpu->irq_summary)
+ return 1;
+
+ kvm_run->exit_reason = KVM_EXIT_HLT;
+ ++kvm_stat.halt_exits;
+ return 0;
+}
+
+static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ inject_ud(vcpu);
+ return 1;
+}
+
+static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ printk(KERN_DEBUG "%s: task swiche is unsupported\n", __FUNCTION__);
+ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+ return 0;
+}
+
+static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
+ kvm_run->exit_reason = KVM_EXIT_CPUID;
+ return 0;
+}
+
+static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE)
+ printk(KERN_ERR "%s: failed\n", __FUNCTION__);
+ return 1;
+}
+
+static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
+{
+ switch (ecx) {
+ case MSR_IA32_TIME_STAMP_COUNTER: {
+ u64 tsc;
+
+ rdtscll(tsc);
+ *data = vcpu->svm->vmcb->control.tsc_offset + tsc;
+ break;
+ }
+ case MSR_K6_STAR:
+ *data = vcpu->svm->vmcb->save.star;
+ break;
+#ifdef CONFIG_X86_64
+ case MSR_LSTAR:
+ *data = vcpu->svm->vmcb->save.lstar;
+ break;
+ case MSR_CSTAR:
+ *data = vcpu->svm->vmcb->save.cstar;
+ break;
+ case MSR_KERNEL_GS_BASE:
+ *data = vcpu->svm->vmcb->save.kernel_gs_base;
+ break;
+ case MSR_SYSCALL_MASK:
+ *data = vcpu->svm->vmcb->save.sfmask;
+ break;
+#endif
+ case MSR_IA32_SYSENTER_CS:
+ *data = vcpu->svm->vmcb->save.sysenter_cs;
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ *data = vcpu->svm->vmcb->save.sysenter_eip;
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ *data = vcpu->svm->vmcb->save.sysenter_esp;
+ break;
+ default:
+ return kvm_get_msr_common(vcpu, ecx, data);
+ }
+ return 0;
+}
+
+static int rdmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+ u64 data;
+
+ if (svm_get_msr(vcpu, ecx, &data))
+ svm_inject_gp(vcpu, 0);
+ else {
+ vcpu->svm->vmcb->save.rax = data & 0xffffffff;
+ vcpu->regs[VCPU_REGS_RDX] = data >> 32;
+ vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
+ skip_emulated_instruction(vcpu);
+ }
+ return 1;
+}
+
+static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
+{
+ switch (ecx) {
+ case MSR_IA32_TIME_STAMP_COUNTER: {
+ u64 tsc;
+
+ rdtscll(tsc);
+ vcpu->svm->vmcb->control.tsc_offset = data - tsc;
+ break;
+ }
+ case MSR_K6_STAR:
+ vcpu->svm->vmcb->save.star = data;
+ break;
+#ifdef CONFIG_X86_64
+ case MSR_LSTAR:
+ vcpu->svm->vmcb->save.lstar = data;
+ break;
+ case MSR_CSTAR:
+ vcpu->svm->vmcb->save.cstar = data;
+ break;
+ case MSR_KERNEL_GS_BASE:
+ vcpu->svm->vmcb->save.kernel_gs_base = data;
+ break;
+ case MSR_SYSCALL_MASK:
+ vcpu->svm->vmcb->save.sfmask = data;
+ break;
+#endif
+ case MSR_IA32_SYSENTER_CS:
+ vcpu->svm->vmcb->save.sysenter_cs = data;
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ vcpu->svm->vmcb->save.sysenter_eip = data;
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ vcpu->svm->vmcb->save.sysenter_esp = data;
+ break;
+ default:
+ return kvm_set_msr_common(vcpu, ecx, data);
+ }
+ return 0;
+}
+
+static int wrmsr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+ u64 data = (vcpu->svm->vmcb->save.rax & -1u)
+ | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32);
+ vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
+ if (svm_set_msr(vcpu, ecx, data))
+ svm_inject_gp(vcpu, 0);
+ else
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+static int msr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ if (vcpu->svm->vmcb->control.exit_info_1)
+ return wrmsr_interception(vcpu, kvm_run);
+ else
+ return rdmsr_interception(vcpu, kvm_run);
+}
+
+static int interrupt_window_interception(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ /*
+ * If the user space waits to inject interrupts, exit as soon as
+ * possible
+ */
+ if (kvm_run->request_interrupt_window &&
+ !vcpu->irq_summary) {
+ ++kvm_stat.irq_window_exits;
+ kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run) = {
+ [SVM_EXIT_READ_CR0] = emulate_on_interception,
+ [SVM_EXIT_READ_CR3] = emulate_on_interception,
+ [SVM_EXIT_READ_CR4] = emulate_on_interception,
+ /* for now: */
+ [SVM_EXIT_WRITE_CR0] = emulate_on_interception,
+ [SVM_EXIT_WRITE_CR3] = emulate_on_interception,
+ [SVM_EXIT_WRITE_CR4] = emulate_on_interception,
+ [SVM_EXIT_READ_DR0] = emulate_on_interception,
+ [SVM_EXIT_READ_DR1] = emulate_on_interception,
+ [SVM_EXIT_READ_DR2] = emulate_on_interception,
+ [SVM_EXIT_READ_DR3] = emulate_on_interception,
+ [SVM_EXIT_WRITE_DR0] = emulate_on_interception,
+ [SVM_EXIT_WRITE_DR1] = emulate_on_interception,
+ [SVM_EXIT_WRITE_DR2] = emulate_on_interception,
+ [SVM_EXIT_WRITE_DR3] = emulate_on_interception,
+ [SVM_EXIT_WRITE_DR5] = emulate_on_interception,
+ [SVM_EXIT_WRITE_DR7] = emulate_on_interception,
+ [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
+ [SVM_EXIT_INTR] = nop_on_interception,
+ [SVM_EXIT_NMI] = nop_on_interception,
+ [SVM_EXIT_SMI] = nop_on_interception,
+ [SVM_EXIT_INIT] = nop_on_interception,
+ [SVM_EXIT_VINTR] = interrupt_window_interception,
+ /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */
+ [SVM_EXIT_CPUID] = cpuid_interception,
+ [SVM_EXIT_HLT] = halt_interception,
+ [SVM_EXIT_INVLPG] = emulate_on_interception,
+ [SVM_EXIT_INVLPGA] = invalid_op_interception,
+ [SVM_EXIT_IOIO] = io_interception,
+ [SVM_EXIT_MSR] = msr_interception,
+ [SVM_EXIT_TASK_SWITCH] = task_switch_interception,
+ [SVM_EXIT_SHUTDOWN] = shutdown_interception,
+ [SVM_EXIT_VMRUN] = invalid_op_interception,
+ [SVM_EXIT_VMMCALL] = invalid_op_interception,
+ [SVM_EXIT_VMLOAD] = invalid_op_interception,
+ [SVM_EXIT_VMSAVE] = invalid_op_interception,
+ [SVM_EXIT_STGI] = invalid_op_interception,
+ [SVM_EXIT_CLGI] = invalid_op_interception,
+ [SVM_EXIT_SKINIT] = invalid_op_interception,
+};
+
+
+static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 exit_code = vcpu->svm->vmcb->control.exit_code;
+
+ kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
+
+ if (is_external_interrupt(vcpu->svm->vmcb->control.exit_int_info) &&
+ exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR)
+ printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
+ "exit_code 0x%x\n",
+ __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info,
+ exit_code);
+
+ if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers)
+ || svm_exit_handlers[exit_code] == 0) {
+ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+ printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n",
+ __FUNCTION__,
+ exit_code,
+ vcpu->svm->vmcb->save.rip,
+ vcpu->cr0,
+ vcpu->svm->vmcb->save.rflags);
+ return 0;
+ }
+
+ return svm_exit_handlers[exit_code](vcpu, kvm_run);
+}
+
+static void reload_tss(struct kvm_vcpu *vcpu)
+{
+ int cpu = raw_smp_processor_id();
+
+ struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
+ svm_data->tss_desc->type = 9; //available 32/64-bit TSS
+ load_TR_desc();
+}
+
+static void pre_svm_run(struct kvm_vcpu *vcpu)
+{
+ int cpu = raw_smp_processor_id();
+
+ struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
+
+ vcpu->svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
+ if (vcpu->cpu != cpu ||
+ vcpu->svm->asid_generation != svm_data->asid_generation)
+ new_asid(vcpu, svm_data);
+}
+
+
+static inline void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
+{
+ struct vmcb_control_area *control;
+
+ control = &vcpu->svm->vmcb->control;
+ control->int_vector = pop_irq(vcpu);
+ control->int_ctl &= ~V_INTR_PRIO_MASK;
+ control->int_ctl |= V_IRQ_MASK |
+ ((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
+}
+
+static void kvm_reput_irq(struct kvm_vcpu *vcpu)
+{
+ struct vmcb_control_area *control = &vcpu->svm->vmcb->control;
+
+ if (control->int_ctl & V_IRQ_MASK) {
+ control->int_ctl &= ~V_IRQ_MASK;
+ push_irq(vcpu, control->int_vector);
+ }
+
+ vcpu->interrupt_window_open =
+ !(control->int_state & SVM_INTERRUPT_SHADOW_MASK);
+}
+
+static void do_interrupt_requests(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ struct vmcb_control_area *control = &vcpu->svm->vmcb->control;
+
+ vcpu->interrupt_window_open =
+ (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
+ (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF));
+
+ if (vcpu->interrupt_window_open && vcpu->irq_summary)
+ /*
+ * If interrupts enabled, and not blocked by sti or mov ss. Good.
+ */
+ kvm_do_inject_irq(vcpu);
+
+ /*
+ * Interrupts blocked. Wait for unblock.
+ */
+ if (!vcpu->interrupt_window_open &&
+ (vcpu->irq_summary || kvm_run->request_interrupt_window)) {
+ control->intercept |= 1ULL << INTERCEPT_VINTR;
+ } else
+ control->intercept &= ~(1ULL << INTERCEPT_VINTR);
+}
+
+static void post_kvm_run_save(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ kvm_run->ready_for_interrupt_injection = (vcpu->interrupt_window_open &&
+ vcpu->irq_summary == 0);
+ kvm_run->if_flag = (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF) != 0;
+ kvm_run->cr8 = vcpu->cr8;
+ kvm_run->apic_base = vcpu->apic_base;
+}
+
+/*
+ * Check if userspace requested an interrupt window, and that the
+ * interrupt window is open.
+ *
+ * No need to exit to userspace if we already have an interrupt queued.
+ */
+static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ return (!vcpu->irq_summary &&
+ kvm_run->request_interrupt_window &&
+ vcpu->interrupt_window_open &&
+ (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF));
+}
+
+static void save_db_regs(unsigned long *db_regs)
+{
+ asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0]));
+ asm volatile ("mov %%dr1, %0" : "=r"(db_regs[1]));
+ asm volatile ("mov %%dr2, %0" : "=r"(db_regs[2]));
+ asm volatile ("mov %%dr3, %0" : "=r"(db_regs[3]));
+}
+
+static void load_db_regs(unsigned long *db_regs)
+{
+ asm volatile ("mov %0, %%dr0" : : "r"(db_regs[0]));
+ asm volatile ("mov %0, %%dr1" : : "r"(db_regs[1]));
+ asm volatile ("mov %0, %%dr2" : : "r"(db_regs[2]));
+ asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3]));
+}
+
+static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u16 fs_selector;
+ u16 gs_selector;
+ u16 ldt_selector;
+ int r;
+
+again:
+ if (!vcpu->mmio_read_completed)
+ do_interrupt_requests(vcpu, kvm_run);
+
+ clgi();
+
+ pre_svm_run(vcpu);
+
+ save_host_msrs(vcpu);
+ fs_selector = read_fs();
+ gs_selector = read_gs();
+ ldt_selector = read_ldt();
+ vcpu->svm->host_cr2 = kvm_read_cr2();
+ vcpu->svm->host_dr6 = read_dr6();
+ vcpu->svm->host_dr7 = read_dr7();
+ vcpu->svm->vmcb->save.cr2 = vcpu->cr2;
+
+ if (vcpu->svm->vmcb->save.dr7 & 0xff) {
+ write_dr7(0);
+ save_db_regs(vcpu->svm->host_db_regs);
+ load_db_regs(vcpu->svm->db_regs);
+ }
+
+ fx_save(vcpu->host_fx_image);
+ fx_restore(vcpu->guest_fx_image);
+
+ asm volatile (
+#ifdef CONFIG_X86_64
+ "push %%rbx; push %%rcx; push %%rdx;"
+ "push %%rsi; push %%rdi; push %%rbp;"
+ "push %%r8; push %%r9; push %%r10; push %%r11;"
+ "push %%r12; push %%r13; push %%r14; push %%r15;"
+#else
+ "push %%ebx; push %%ecx; push %%edx;"
+ "push %%esi; push %%edi; push %%ebp;"
+#endif
+
+#ifdef CONFIG_X86_64
+ "mov %c[rbx](%[vcpu]), %%rbx \n\t"
+ "mov %c[rcx](%[vcpu]), %%rcx \n\t"
+ "mov %c[rdx](%[vcpu]), %%rdx \n\t"
+ "mov %c[rsi](%[vcpu]), %%rsi \n\t"
+ "mov %c[rdi](%[vcpu]), %%rdi \n\t"
+ "mov %c[rbp](%[vcpu]), %%rbp \n\t"
+ "mov %c[r8](%[vcpu]), %%r8 \n\t"
+ "mov %c[r9](%[vcpu]), %%r9 \n\t"
+ "mov %c[r10](%[vcpu]), %%r10 \n\t"
+ "mov %c[r11](%[vcpu]), %%r11 \n\t"
+ "mov %c[r12](%[vcpu]), %%r12 \n\t"
+ "mov %c[r13](%[vcpu]), %%r13 \n\t"
+ "mov %c[r14](%[vcpu]), %%r14 \n\t"
+ "mov %c[r15](%[vcpu]), %%r15 \n\t"
+#else
+ "mov %c[rbx](%[vcpu]), %%ebx \n\t"
+ "mov %c[rcx](%[vcpu]), %%ecx \n\t"
+ "mov %c[rdx](%[vcpu]), %%edx \n\t"
+ "mov %c[rsi](%[vcpu]), %%esi \n\t"
+ "mov %c[rdi](%[vcpu]), %%edi \n\t"
+ "mov %c[rbp](%[vcpu]), %%ebp \n\t"
+#endif
+
+#ifdef CONFIG_X86_64
+ /* Enter guest mode */
+ "push %%rax \n\t"
+ "mov %c[svm](%[vcpu]), %%rax \n\t"
+ "mov %c[vmcb](%%rax), %%rax \n\t"
+ SVM_VMLOAD "\n\t"
+ SVM_VMRUN "\n\t"
+ SVM_VMSAVE "\n\t"
+ "pop %%rax \n\t"
+#else
+ /* Enter guest mode */
+ "push %%eax \n\t"
+ "mov %c[svm](%[vcpu]), %%eax \n\t"
+ "mov %c[vmcb](%%eax), %%eax \n\t"
+ SVM_VMLOAD "\n\t"
+ SVM_VMRUN "\n\t"
+ SVM_VMSAVE "\n\t"
+ "pop %%eax \n\t"
+#endif
+
+ /* Save guest registers, load host registers */
+#ifdef CONFIG_X86_64
+ "mov %%rbx, %c[rbx](%[vcpu]) \n\t"
+ "mov %%rcx, %c[rcx](%[vcpu]) \n\t"
+ "mov %%rdx, %c[rdx](%[vcpu]) \n\t"
+ "mov %%rsi, %c[rsi](%[vcpu]) \n\t"
+ "mov %%rdi, %c[rdi](%[vcpu]) \n\t"
+ "mov %%rbp, %c[rbp](%[vcpu]) \n\t"
+ "mov %%r8, %c[r8](%[vcpu]) \n\t"
+ "mov %%r9, %c[r9](%[vcpu]) \n\t"
+ "mov %%r10, %c[r10](%[vcpu]) \n\t"
+ "mov %%r11, %c[r11](%[vcpu]) \n\t"
+ "mov %%r12, %c[r12](%[vcpu]) \n\t"
+ "mov %%r13, %c[r13](%[vcpu]) \n\t"
+ "mov %%r14, %c[r14](%[vcpu]) \n\t"
+ "mov %%r15, %c[r15](%[vcpu]) \n\t"
+
+ "pop %%r15; pop %%r14; pop %%r13; pop %%r12;"
+ "pop %%r11; pop %%r10; pop %%r9; pop %%r8;"
+ "pop %%rbp; pop %%rdi; pop %%rsi;"
+ "pop %%rdx; pop %%rcx; pop %%rbx; \n\t"
+#else
+ "mov %%ebx, %c[rbx](%[vcpu]) \n\t"
+ "mov %%ecx, %c[rcx](%[vcpu]) \n\t"
+ "mov %%edx, %c[rdx](%[vcpu]) \n\t"
+ "mov %%esi, %c[rsi](%[vcpu]) \n\t"
+ "mov %%edi, %c[rdi](%[vcpu]) \n\t"
+ "mov %%ebp, %c[rbp](%[vcpu]) \n\t"
+
+ "pop %%ebp; pop %%edi; pop %%esi;"
+ "pop %%edx; pop %%ecx; pop %%ebx; \n\t"
+#endif
+ :
+ : [vcpu]"a"(vcpu),
+ [svm]"i"(offsetof(struct kvm_vcpu, svm)),
+ [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)),
+ [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])),
+ [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])),
+ [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])),
+ [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
+ [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
+ [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP]))
+#ifdef CONFIG_X86_64
+ ,[r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
+ [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
+ [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
+ [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])),
+ [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])),
+ [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])),
+ [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])),
+ [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15]))
+#endif
+ : "cc", "memory" );
+
+ fx_save(vcpu->guest_fx_image);
+ fx_restore(vcpu->host_fx_image);
+
+ if ((vcpu->svm->vmcb->save.dr7 & 0xff))
+ load_db_regs(vcpu->svm->host_db_regs);
+
+ vcpu->cr2 = vcpu->svm->vmcb->save.cr2;
+
+ write_dr6(vcpu->svm->host_dr6);
+ write_dr7(vcpu->svm->host_dr7);
+ kvm_write_cr2(vcpu->svm->host_cr2);
+
+ load_fs(fs_selector);
+ load_gs(gs_selector);
+ load_ldt(ldt_selector);
+ load_host_msrs(vcpu);
+
+ reload_tss(vcpu);
+
+ /*
+ * Profile KVM exit RIPs:
+ */
+ if (unlikely(prof_on == KVM_PROFILING))
+ profile_hit(KVM_PROFILING,
+ (void *)(unsigned long)vcpu->svm->vmcb->save.rip);
+
+ stgi();
+
+ kvm_reput_irq(vcpu);
+
+ vcpu->svm->next_rip = 0;
+
+ if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
+ kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
+ kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code;
+ post_kvm_run_save(vcpu, kvm_run);
+ return 0;
+ }
+
+ r = handle_exit(vcpu, kvm_run);
+ if (r > 0) {
+ if (signal_pending(current)) {
+ ++kvm_stat.signal_exits;
+ post_kvm_run_save(vcpu, kvm_run);
+ return -EINTR;
+ }
+
+ if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+ ++kvm_stat.request_irq_exits;
+ post_kvm_run_save(vcpu, kvm_run);
+ return -EINTR;
+ }
+ kvm_resched(vcpu);
+ goto again;
+ }
+ post_kvm_run_save(vcpu, kvm_run);
+ return r;
+}
+
+static void svm_flush_tlb(struct kvm_vcpu *vcpu)
+{
+ force_new_asid(vcpu);
+}
+
+static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
+{
+ vcpu->svm->vmcb->save.cr3 = root;
+ force_new_asid(vcpu);
+}
+
+static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
+ unsigned long addr,
+ uint32_t err_code)
+{
+ uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info;
+
+ ++kvm_stat.pf_guest;
+
+ if (is_page_fault(exit_int_info)) {
+
+ vcpu->svm->vmcb->control.event_inj_err = 0;
+ vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
+ SVM_EVTINJ_VALID_ERR |
+ SVM_EVTINJ_TYPE_EXEPT |
+ DF_VECTOR;
+ return;
+ }
+ vcpu->cr2 = addr;
+ vcpu->svm->vmcb->save.cr2 = addr;
+ vcpu->svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
+ SVM_EVTINJ_VALID_ERR |
+ SVM_EVTINJ_TYPE_EXEPT |
+ PF_VECTOR;
+ vcpu->svm->vmcb->control.event_inj_err = err_code;
+}
+
+
+static int is_disabled(void)
+{
+ return 0;
+}
+
+static struct kvm_arch_ops svm_arch_ops = {
+ .cpu_has_kvm_support = has_svm,
+ .disabled_by_bios = is_disabled,
+ .hardware_setup = svm_hardware_setup,
+ .hardware_unsetup = svm_hardware_unsetup,
+ .hardware_enable = svm_hardware_enable,
+ .hardware_disable = svm_hardware_disable,
+
+ .vcpu_create = svm_create_vcpu,
+ .vcpu_free = svm_free_vcpu,
+
+ .vcpu_load = svm_vcpu_load,
+ .vcpu_put = svm_vcpu_put,
+
+ .set_guest_debug = svm_guest_debug,
+ .get_msr = svm_get_msr,
+ .set_msr = svm_set_msr,
+ .get_segment_base = svm_get_segment_base,
+ .get_segment = svm_get_segment,
+ .set_segment = svm_set_segment,
+ .get_cs_db_l_bits = svm_get_cs_db_l_bits,
+ .decache_cr0_cr4_guest_bits = svm_decache_cr0_cr4_guest_bits,
+ .set_cr0 = svm_set_cr0,
+ .set_cr0_no_modeswitch = svm_set_cr0,
+ .set_cr3 = svm_set_cr3,
+ .set_cr4 = svm_set_cr4,
+ .set_efer = svm_set_efer,
+ .get_idt = svm_get_idt,
+ .set_idt = svm_set_idt,
+ .get_gdt = svm_get_gdt,
+ .set_gdt = svm_set_gdt,
+ .get_dr = svm_get_dr,
+ .set_dr = svm_set_dr,
+ .cache_regs = svm_cache_regs,
+ .decache_regs = svm_decache_regs,
+ .get_rflags = svm_get_rflags,
+ .set_rflags = svm_set_rflags,
+
+ .invlpg = svm_invlpg,
+ .tlb_flush = svm_flush_tlb,
+ .inject_page_fault = svm_inject_page_fault,
+
+ .inject_gp = svm_inject_gp,
+
+ .run = svm_vcpu_run,
+ .skip_emulated_instruction = skip_emulated_instruction,
+ .vcpu_setup = svm_vcpu_setup,
+};
+
+static int __init svm_init(void)
+{
+ return kvm_init_arch(&svm_arch_ops, THIS_MODULE);
+}
+
+static void __exit svm_exit(void)
+{
+ kvm_exit_arch();
+}
+
+module_init(svm_init)
+module_exit(svm_exit)
diff --git a/drivers/kvm/svm.h b/drivers/kvm/svm.h
new file mode 100644
index 00000000000..df731c3fb58
--- /dev/null
+++ b/drivers/kvm/svm.h
@@ -0,0 +1,315 @@
+#ifndef __SVM_H
+#define __SVM_H
+
+enum {
+ INTERCEPT_INTR,
+ INTERCEPT_NMI,
+ INTERCEPT_SMI,
+ INTERCEPT_INIT,
+ INTERCEPT_VINTR,
+ INTERCEPT_SELECTIVE_CR0,
+ INTERCEPT_STORE_IDTR,
+ INTERCEPT_STORE_GDTR,
+ INTERCEPT_STORE_LDTR,
+ INTERCEPT_STORE_TR,
+ INTERCEPT_LOAD_IDTR,
+ INTERCEPT_LOAD_GDTR,
+ INTERCEPT_LOAD_LDTR,
+ INTERCEPT_LOAD_TR,
+ INTERCEPT_RDTSC,
+ INTERCEPT_RDPMC,
+ INTERCEPT_PUSHF,
+ INTERCEPT_POPF,
+ INTERCEPT_CPUID,
+ INTERCEPT_RSM,
+ INTERCEPT_IRET,
+ INTERCEPT_INTn,
+ INTERCEPT_INVD,
+ INTERCEPT_PAUSE,
+ INTERCEPT_HLT,
+ INTERCEPT_INVLPG,
+ INTERCEPT_INVLPGA,
+ INTERCEPT_IOIO_PROT,
+ INTERCEPT_MSR_PROT,
+ INTERCEPT_TASK_SWITCH,
+ INTERCEPT_FERR_FREEZE,
+ INTERCEPT_SHUTDOWN,
+ INTERCEPT_VMRUN,
+ INTERCEPT_VMMCALL,
+ INTERCEPT_VMLOAD,
+ INTERCEPT_VMSAVE,
+ INTERCEPT_STGI,
+ INTERCEPT_CLGI,
+ INTERCEPT_SKINIT,
+ INTERCEPT_RDTSCP,
+ INTERCEPT_ICEBP,
+ INTERCEPT_WBINVD,
+};
+
+
+struct __attribute__ ((__packed__)) vmcb_control_area {
+ u16 intercept_cr_read;
+ u16 intercept_cr_write;
+ u16 intercept_dr_read;
+ u16 intercept_dr_write;
+ u32 intercept_exceptions;
+ u64 intercept;
+ u8 reserved_1[44];
+ u64 iopm_base_pa;
+ u64 msrpm_base_pa;
+ u64 tsc_offset;
+ u32 asid;
+ u8 tlb_ctl;
+ u8 reserved_2[3];
+ u32 int_ctl;
+ u32 int_vector;
+ u32 int_state;
+ u8 reserved_3[4];
+ u32 exit_code;
+ u32 exit_code_hi;
+ u64 exit_info_1;
+ u64 exit_info_2;
+ u32 exit_int_info;
+ u32 exit_int_info_err;
+ u64 nested_ctl;
+ u8 reserved_4[16];
+ u32 event_inj;
+ u32 event_inj_err;
+ u64 nested_cr3;
+ u64 lbr_ctl;
+ u8 reserved_5[832];
+};
+
+
+#define TLB_CONTROL_DO_NOTHING 0
+#define TLB_CONTROL_FLUSH_ALL_ASID 1
+
+#define V_TPR_MASK 0x0f
+
+#define V_IRQ_SHIFT 8
+#define V_IRQ_MASK (1 << V_IRQ_SHIFT)
+
+#define V_INTR_PRIO_SHIFT 16
+#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
+
+#define V_IGN_TPR_SHIFT 20
+#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
+
+#define V_INTR_MASKING_SHIFT 24
+#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
+
+#define SVM_INTERRUPT_SHADOW_MASK 1
+
+#define SVM_IOIO_STR_SHIFT 2
+#define SVM_IOIO_REP_SHIFT 3
+#define SVM_IOIO_SIZE_SHIFT 4
+#define SVM_IOIO_ASIZE_SHIFT 7
+
+#define SVM_IOIO_TYPE_MASK 1
+#define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT)
+#define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT)
+#define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT)
+#define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT)
+
+struct __attribute__ ((__packed__)) vmcb_seg {
+ u16 selector;
+ u16 attrib;
+ u32 limit;
+ u64 base;
+};
+
+struct __attribute__ ((__packed__)) vmcb_save_area {
+ struct vmcb_seg es;
+ struct vmcb_seg cs;
+ struct vmcb_seg ss;
+ struct vmcb_seg ds;
+ struct vmcb_seg fs;
+ struct vmcb_seg gs;
+ struct vmcb_seg gdtr;
+ struct vmcb_seg ldtr;
+ struct vmcb_seg idtr;
+ struct vmcb_seg tr;
+ u8 reserved_1[43];
+ u8 cpl;
+ u8 reserved_2[4];
+ u64 efer;
+ u8 reserved_3[112];
+ u64 cr4;
+ u64 cr3;
+ u64 cr0;
+ u64 dr7;
+ u64 dr6;
+ u64 rflags;
+ u64 rip;
+ u8 reserved_4[88];
+ u64 rsp;
+ u8 reserved_5[24];
+ u64 rax;
+ u64 star;
+ u64 lstar;
+ u64 cstar;
+ u64 sfmask;
+ u64 kernel_gs_base;
+ u64 sysenter_cs;
+ u64 sysenter_esp;
+ u64 sysenter_eip;
+ u64 cr2;
+ u8 reserved_6[32];
+ u64 g_pat;
+ u64 dbgctl;
+ u64 br_from;
+ u64 br_to;
+ u64 last_excp_from;
+ u64 last_excp_to;
+};
+
+struct __attribute__ ((__packed__)) vmcb {
+ struct vmcb_control_area control;
+ struct vmcb_save_area save;
+};
+
+#define SVM_CPUID_FEATURE_SHIFT 2
+#define SVM_CPUID_FUNC 0x8000000a
+
+#define MSR_EFER_SVME_MASK (1ULL << 12)
+#define MSR_VM_HSAVE_PA 0xc0010117ULL
+
+#define SVM_SELECTOR_S_SHIFT 4
+#define SVM_SELECTOR_DPL_SHIFT 5
+#define SVM_SELECTOR_P_SHIFT 7
+#define SVM_SELECTOR_AVL_SHIFT 8
+#define SVM_SELECTOR_L_SHIFT 9
+#define SVM_SELECTOR_DB_SHIFT 10
+#define SVM_SELECTOR_G_SHIFT 11
+
+#define SVM_SELECTOR_TYPE_MASK (0xf)
+#define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT)
+#define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT)
+#define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT)
+#define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT)
+#define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT)
+#define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT)
+#define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT)
+
+#define SVM_SELECTOR_WRITE_MASK (1 << 1)
+#define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK
+#define SVM_SELECTOR_CODE_MASK (1 << 3)
+
+#define INTERCEPT_CR0_MASK 1
+#define INTERCEPT_CR3_MASK (1 << 3)
+#define INTERCEPT_CR4_MASK (1 << 4)
+
+#define INTERCEPT_DR0_MASK 1
+#define INTERCEPT_DR1_MASK (1 << 1)
+#define INTERCEPT_DR2_MASK (1 << 2)
+#define INTERCEPT_DR3_MASK (1 << 3)
+#define INTERCEPT_DR4_MASK (1 << 4)
+#define INTERCEPT_DR5_MASK (1 << 5)
+#define INTERCEPT_DR6_MASK (1 << 6)
+#define INTERCEPT_DR7_MASK (1 << 7)
+
+#define SVM_EVTINJ_VEC_MASK 0xff
+
+#define SVM_EVTINJ_TYPE_SHIFT 8
+#define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT)
+
+#define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT)
+
+#define SVM_EVTINJ_VALID (1 << 31)
+#define SVM_EVTINJ_VALID_ERR (1 << 11)
+
+#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
+
+#define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
+#define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
+#define SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT
+#define SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT
+
+#define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
+#define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
+
+#define SVM_EXIT_READ_CR0 0x000
+#define SVM_EXIT_READ_CR3 0x003
+#define SVM_EXIT_READ_CR4 0x004
+#define SVM_EXIT_READ_CR8 0x008
+#define SVM_EXIT_WRITE_CR0 0x010
+#define SVM_EXIT_WRITE_CR3 0x013
+#define SVM_EXIT_WRITE_CR4 0x014
+#define SVM_EXIT_WRITE_CR8 0x018
+#define SVM_EXIT_READ_DR0 0x020
+#define SVM_EXIT_READ_DR1 0x021
+#define SVM_EXIT_READ_DR2 0x022
+#define SVM_EXIT_READ_DR3 0x023
+#define SVM_EXIT_READ_DR4 0x024
+#define SVM_EXIT_READ_DR5 0x025
+#define SVM_EXIT_READ_DR6 0x026
+#define SVM_EXIT_READ_DR7 0x027
+#define SVM_EXIT_WRITE_DR0 0x030
+#define SVM_EXIT_WRITE_DR1 0x031
+#define SVM_EXIT_WRITE_DR2 0x032
+#define SVM_EXIT_WRITE_DR3 0x033
+#define SVM_EXIT_WRITE_DR4 0x034
+#define SVM_EXIT_WRITE_DR5 0x035
+#define SVM_EXIT_WRITE_DR6 0x036
+#define SVM_EXIT_WRITE_DR7 0x037
+#define SVM_EXIT_EXCP_BASE 0x040
+#define SVM_EXIT_INTR 0x060
+#define SVM_EXIT_NMI 0x061
+#define SVM_EXIT_SMI 0x062
+#define SVM_EXIT_INIT 0x063
+#define SVM_EXIT_VINTR 0x064
+#define SVM_EXIT_CR0_SEL_WRITE 0x065
+#define SVM_EXIT_IDTR_READ 0x066
+#define SVM_EXIT_GDTR_READ 0x067
+#define SVM_EXIT_LDTR_READ 0x068
+#define SVM_EXIT_TR_READ 0x069
+#define SVM_EXIT_IDTR_WRITE 0x06a
+#define SVM_EXIT_GDTR_WRITE 0x06b
+#define SVM_EXIT_LDTR_WRITE 0x06c
+#define SVM_EXIT_TR_WRITE 0x06d
+#define SVM_EXIT_RDTSC 0x06e
+#define SVM_EXIT_RDPMC 0x06f
+#define SVM_EXIT_PUSHF 0x070
+#define SVM_EXIT_POPF 0x071
+#define SVM_EXIT_CPUID 0x072
+#define SVM_EXIT_RSM 0x073
+#define SVM_EXIT_IRET 0x074
+#define SVM_EXIT_SWINT 0x075
+#define SVM_EXIT_INVD 0x076
+#define SVM_EXIT_PAUSE 0x077
+#define SVM_EXIT_HLT 0x078
+#define SVM_EXIT_INVLPG 0x079
+#define SVM_EXIT_INVLPGA 0x07a
+#define SVM_EXIT_IOIO 0x07b
+#define SVM_EXIT_MSR 0x07c
+#define SVM_EXIT_TASK_SWITCH 0x07d
+#define SVM_EXIT_FERR_FREEZE 0x07e
+#define SVM_EXIT_SHUTDOWN 0x07f
+#define SVM_EXIT_VMRUN 0x080
+#define SVM_EXIT_VMMCALL 0x081
+#define SVM_EXIT_VMLOAD 0x082
+#define SVM_EXIT_VMSAVE 0x083
+#define SVM_EXIT_STGI 0x084
+#define SVM_EXIT_CLGI 0x085
+#define SVM_EXIT_SKINIT 0x086
+#define SVM_EXIT_RDTSCP 0x087
+#define SVM_EXIT_ICEBP 0x088
+#define SVM_EXIT_WBINVD 0x089
+#define SVM_EXIT_NPF 0x400
+
+#define SVM_EXIT_ERR -1
+
+#define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) // TS and MP
+
+#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
+#define SVM_VMRUN ".byte 0x0f, 0x01, 0xd8"
+#define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb"
+#define SVM_CLGI ".byte 0x0f, 0x01, 0xdd"
+#define SVM_STGI ".byte 0x0f, 0x01, 0xdc"
+#define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf"
+
+#endif
+
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
new file mode 100644
index 00000000000..54c35c0b318
--- /dev/null
+++ b/drivers/kvm/vmx.c
@@ -0,0 +1,2061 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "kvm.h"
+#include "vmx.h"
+#include "kvm_vmx.h"
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/profile.h>
+#include <asm/io.h>
+#include <asm/desc.h>
+
+#include "segment_descriptor.h"
+
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+static DEFINE_PER_CPU(struct vmcs *, vmxarea);
+static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
+
+#ifdef CONFIG_X86_64
+#define HOST_IS_64 1
+#else
+#define HOST_IS_64 0
+#endif
+
+static struct vmcs_descriptor {
+ int size;
+ int order;
+ u32 revision_id;
+} vmcs_descriptor;
+
+#define VMX_SEGMENT_FIELD(seg) \
+ [VCPU_SREG_##seg] = { \
+ .selector = GUEST_##seg##_SELECTOR, \
+ .base = GUEST_##seg##_BASE, \
+ .limit = GUEST_##seg##_LIMIT, \
+ .ar_bytes = GUEST_##seg##_AR_BYTES, \
+ }
+
+static struct kvm_vmx_segment_field {
+ unsigned selector;
+ unsigned base;
+ unsigned limit;
+ unsigned ar_bytes;
+} kvm_vmx_segment_fields[] = {
+ VMX_SEGMENT_FIELD(CS),
+ VMX_SEGMENT_FIELD(DS),
+ VMX_SEGMENT_FIELD(ES),
+ VMX_SEGMENT_FIELD(FS),
+ VMX_SEGMENT_FIELD(GS),
+ VMX_SEGMENT_FIELD(SS),
+ VMX_SEGMENT_FIELD(TR),
+ VMX_SEGMENT_FIELD(LDTR),
+};
+
+static const u32 vmx_msr_index[] = {
+#ifdef CONFIG_X86_64
+ MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE,
+#endif
+ MSR_EFER, MSR_K6_STAR,
+};
+#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index))
+
+static inline int is_page_fault(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
+ INTR_INFO_VALID_MASK)) ==
+ (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
+}
+
+static inline int is_external_interrupt(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+ == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
+}
+
+static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
+{
+ int i;
+
+ for (i = 0; i < vcpu->nmsrs; ++i)
+ if (vcpu->guest_msrs[i].index == msr)
+ return &vcpu->guest_msrs[i];
+ return 0;
+}
+
+static void vmcs_clear(struct vmcs *vmcs)
+{
+ u64 phys_addr = __pa(vmcs);
+ u8 error;
+
+ asm volatile (ASM_VMX_VMCLEAR_RAX "; setna %0"
+ : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
+ : "cc", "memory");
+ if (error)
+ printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n",
+ vmcs, phys_addr);
+}
+
+static void __vcpu_clear(void *arg)
+{
+ struct kvm_vcpu *vcpu = arg;
+ int cpu = raw_smp_processor_id();
+
+ if (vcpu->cpu == cpu)
+ vmcs_clear(vcpu->vmcs);
+ if (per_cpu(current_vmcs, cpu) == vcpu->vmcs)
+ per_cpu(current_vmcs, cpu) = NULL;
+}
+
+static unsigned long vmcs_readl(unsigned long field)
+{
+ unsigned long value;
+
+ asm volatile (ASM_VMX_VMREAD_RDX_RAX
+ : "=a"(value) : "d"(field) : "cc");
+ return value;
+}
+
+static u16 vmcs_read16(unsigned long field)
+{
+ return vmcs_readl(field);
+}
+
+static u32 vmcs_read32(unsigned long field)
+{
+ return vmcs_readl(field);
+}
+
+static u64 vmcs_read64(unsigned long field)
+{
+#ifdef CONFIG_X86_64
+ return vmcs_readl(field);
+#else
+ return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32);
+#endif
+}
+
+static noinline void vmwrite_error(unsigned long field, unsigned long value)
+{
+ printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n",
+ field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
+ dump_stack();
+}
+
+static void vmcs_writel(unsigned long field, unsigned long value)
+{
+ u8 error;
+
+ asm volatile (ASM_VMX_VMWRITE_RAX_RDX "; setna %0"
+ : "=q"(error) : "a"(value), "d"(field) : "cc" );
+ if (unlikely(error))
+ vmwrite_error(field, value);
+}
+
+static void vmcs_write16(unsigned long field, u16 value)
+{
+ vmcs_writel(field, value);
+}
+
+static void vmcs_write32(unsigned long field, u32 value)
+{
+ vmcs_writel(field, value);
+}
+
+static void vmcs_write64(unsigned long field, u64 value)
+{
+#ifdef CONFIG_X86_64
+ vmcs_writel(field, value);
+#else
+ vmcs_writel(field, value);
+ asm volatile ("");
+ vmcs_writel(field+1, value >> 32);
+#endif
+}
+
+/*
+ * Switches to specified vcpu, until a matching vcpu_put(), but assumes
+ * vcpu mutex is already taken.
+ */
+static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu)
+{
+ u64 phys_addr = __pa(vcpu->vmcs);
+ int cpu;
+
+ cpu = get_cpu();
+
+ if (vcpu->cpu != cpu) {
+ smp_call_function(__vcpu_clear, vcpu, 0, 1);
+ vcpu->launched = 0;
+ }
+
+ if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) {
+ u8 error;
+
+ per_cpu(current_vmcs, cpu) = vcpu->vmcs;
+ asm volatile (ASM_VMX_VMPTRLD_RAX "; setna %0"
+ : "=g"(error) : "a"(&phys_addr), "m"(phys_addr)
+ : "cc");
+ if (error)
+ printk(KERN_ERR "kvm: vmptrld %p/%llx fail\n",
+ vcpu->vmcs, phys_addr);
+ }
+
+ if (vcpu->cpu != cpu) {
+ struct descriptor_table dt;
+ unsigned long sysenter_esp;
+
+ vcpu->cpu = cpu;
+ /*
+ * Linux uses per-cpu TSS and GDT, so set these when switching
+ * processors.
+ */
+ vmcs_writel(HOST_TR_BASE, read_tr_base()); /* 22.2.4 */
+ get_gdt(&dt);
+ vmcs_writel(HOST_GDTR_BASE, dt.base); /* 22.2.4 */
+
+ rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
+ vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+ }
+ return vcpu;
+}
+
+static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
+{
+ put_cpu();
+}
+
+static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
+{
+ return vmcs_readl(GUEST_RFLAGS);
+}
+
+static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+ vmcs_writel(GUEST_RFLAGS, rflags);
+}
+
+static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+ unsigned long rip;
+ u32 interruptibility;
+
+ rip = vmcs_readl(GUEST_RIP);
+ rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ vmcs_writel(GUEST_RIP, rip);
+
+ /*
+ * We emulated an instruction, so temporary interrupt blocking
+ * should be removed, if set.
+ */
+ interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ if (interruptibility & 3)
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
+ interruptibility & ~3);
+ vcpu->interrupt_window_open = 1;
+}
+
+static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
+{
+ printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n",
+ vmcs_readl(GUEST_RIP));
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ GP_VECTOR |
+ INTR_TYPE_EXCEPTION |
+ INTR_INFO_DELIEVER_CODE_MASK |
+ INTR_INFO_VALID_MASK);
+}
+
+/*
+ * reads and returns guest's timestamp counter "register"
+ * guest_tsc = host_tsc + tsc_offset -- 21.3
+ */
+static u64 guest_read_tsc(void)
+{
+ u64 host_tsc, tsc_offset;
+
+ rdtscll(host_tsc);
+ tsc_offset = vmcs_read64(TSC_OFFSET);
+ return host_tsc + tsc_offset;
+}
+
+/*
+ * writes 'guest_tsc' into guest's timestamp counter "register"
+ * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc
+ */
+static void guest_write_tsc(u64 guest_tsc)
+{
+ u64 host_tsc;
+
+ rdtscll(host_tsc);
+ vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc);
+}
+
+static void reload_tss(void)
+{
+#ifndef CONFIG_X86_64
+
+ /*
+ * VT restores TR but not its size. Useless.
+ */
+ struct descriptor_table gdt;
+ struct segment_descriptor *descs;
+
+ get_gdt(&gdt);
+ descs = (void *)gdt.base;
+ descs[GDT_ENTRY_TSS].type = 9; /* available TSS */
+ load_TR_desc();
+#endif
+}
+
+/*
+ * Reads an msr value (of 'msr_index') into 'pdata'.
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+ u64 data;
+ struct vmx_msr_entry *msr;
+
+ if (!pdata) {
+ printk(KERN_ERR "BUG: get_msr called with NULL pdata\n");
+ return -EINVAL;
+ }
+
+ switch (msr_index) {
+#ifdef CONFIG_X86_64
+ case MSR_FS_BASE:
+ data = vmcs_readl(GUEST_FS_BASE);
+ break;
+ case MSR_GS_BASE:
+ data = vmcs_readl(GUEST_GS_BASE);
+ break;
+ case MSR_EFER:
+ return kvm_get_msr_common(vcpu, msr_index, pdata);
+#endif
+ case MSR_IA32_TIME_STAMP_COUNTER:
+ data = guest_read_tsc();
+ break;
+ case MSR_IA32_SYSENTER_CS:
+ data = vmcs_read32(GUEST_SYSENTER_CS);
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ data = vmcs_read32(GUEST_SYSENTER_EIP);
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ data = vmcs_read32(GUEST_SYSENTER_ESP);
+ break;
+ default:
+ msr = find_msr_entry(vcpu, msr_index);
+ if (msr) {
+ data = msr->data;
+ break;
+ }
+ return kvm_get_msr_common(vcpu, msr_index, pdata);
+ }
+
+ *pdata = data;
+ return 0;
+}
+
+/*
+ * Writes msr value into into the appropriate "register".
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+ struct vmx_msr_entry *msr;
+ switch (msr_index) {
+#ifdef CONFIG_X86_64
+ case MSR_EFER:
+ return kvm_set_msr_common(vcpu, msr_index, data);
+ case MSR_FS_BASE:
+ vmcs_writel(GUEST_FS_BASE, data);
+ break;
+ case MSR_GS_BASE:
+ vmcs_writel(GUEST_GS_BASE, data);
+ break;
+#endif
+ case MSR_IA32_SYSENTER_CS:
+ vmcs_write32(GUEST_SYSENTER_CS, data);
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ vmcs_write32(GUEST_SYSENTER_EIP, data);
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ vmcs_write32(GUEST_SYSENTER_ESP, data);
+ break;
+ case MSR_IA32_TIME_STAMP_COUNTER: {
+ guest_write_tsc(data);
+ break;
+ }
+ default:
+ msr = find_msr_entry(vcpu, msr_index);
+ if (msr) {
+ msr->data = data;
+ break;
+ }
+ return kvm_set_msr_common(vcpu, msr_index, data);
+ msr->data = data;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Sync the rsp and rip registers into the vcpu structure. This allows
+ * registers to be accessed by indexing vcpu->regs.
+ */
+static void vcpu_load_rsp_rip(struct kvm_vcpu *vcpu)
+{
+ vcpu->regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
+ vcpu->rip = vmcs_readl(GUEST_RIP);
+}
+
+/*
+ * Syncs rsp and rip back into the vmcs. Should be called after possible
+ * modification.
+ */
+static void vcpu_put_rsp_rip(struct kvm_vcpu *vcpu)
+{
+ vmcs_writel(GUEST_RSP, vcpu->regs[VCPU_REGS_RSP]);
+ vmcs_writel(GUEST_RIP, vcpu->rip);
+}
+
+static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
+{
+ unsigned long dr7 = 0x400;
+ u32 exception_bitmap;
+ int old_singlestep;
+
+ exception_bitmap = vmcs_read32(EXCEPTION_BITMAP);
+ old_singlestep = vcpu->guest_debug.singlestep;
+
+ vcpu->guest_debug.enabled = dbg->enabled;
+ if (vcpu->guest_debug.enabled) {
+ int i;
+
+ dr7 |= 0x200; /* exact */
+ for (i = 0; i < 4; ++i) {
+ if (!dbg->breakpoints[i].enabled)
+ continue;
+ vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address;
+ dr7 |= 2 << (i*2); /* global enable */
+ dr7 |= 0 << (i*4+16); /* execution breakpoint */
+ }
+
+ exception_bitmap |= (1u << 1); /* Trap debug exceptions */
+
+ vcpu->guest_debug.singlestep = dbg->singlestep;
+ } else {
+ exception_bitmap &= ~(1u << 1); /* Ignore debug exceptions */
+ vcpu->guest_debug.singlestep = 0;
+ }
+
+ if (old_singlestep && !vcpu->guest_debug.singlestep) {
+ unsigned long flags;
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
+ vmcs_writel(GUEST_RFLAGS, flags);
+ }
+
+ vmcs_write32(EXCEPTION_BITMAP, exception_bitmap);
+ vmcs_writel(GUEST_DR7, dr7);
+
+ return 0;
+}
+
+static __init int cpu_has_kvm_support(void)
+{
+ unsigned long ecx = cpuid_ecx(1);
+ return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
+}
+
+static __init int vmx_disabled_by_bios(void)
+{
+ u64 msr;
+
+ rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
+ return (msr & 5) == 1; /* locked but not enabled */
+}
+
+static __init void hardware_enable(void *garbage)
+{
+ int cpu = raw_smp_processor_id();
+ u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
+ u64 old;
+
+ rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
+ if ((old & 5) != 5)
+ /* enable and lock */
+ wrmsrl(MSR_IA32_FEATURE_CONTROL, old | 5);
+ write_cr4(read_cr4() | CR4_VMXE); /* FIXME: not cpu hotplug safe */
+ asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr), "m"(phys_addr)
+ : "memory", "cc");
+}
+
+static void hardware_disable(void *garbage)
+{
+ asm volatile (ASM_VMX_VMXOFF : : : "cc");
+}
+
+static __init void setup_vmcs_descriptor(void)
+{
+ u32 vmx_msr_low, vmx_msr_high;
+
+ rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);
+ vmcs_descriptor.size = vmx_msr_high & 0x1fff;
+ vmcs_descriptor.order = get_order(vmcs_descriptor.size);
+ vmcs_descriptor.revision_id = vmx_msr_low;
+}
+
+static struct vmcs *alloc_vmcs_cpu(int cpu)
+{
+ int node = cpu_to_node(cpu);
+ struct page *pages;
+ struct vmcs *vmcs;
+
+ pages = alloc_pages_node(node, GFP_KERNEL, vmcs_descriptor.order);
+ if (!pages)
+ return NULL;
+ vmcs = page_address(pages);
+ memset(vmcs, 0, vmcs_descriptor.size);
+ vmcs->revision_id = vmcs_descriptor.revision_id; /* vmcs revision id */
+ return vmcs;
+}
+
+static struct vmcs *alloc_vmcs(void)
+{
+ return alloc_vmcs_cpu(raw_smp_processor_id());
+}
+
+static void free_vmcs(struct vmcs *vmcs)
+{
+ free_pages((unsigned long)vmcs, vmcs_descriptor.order);
+}
+
+static __exit void free_kvm_area(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ free_vmcs(per_cpu(vmxarea, cpu));
+}
+
+extern struct vmcs *alloc_vmcs_cpu(int cpu);
+
+static __init int alloc_kvm_area(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ struct vmcs *vmcs;
+
+ vmcs = alloc_vmcs_cpu(cpu);
+ if (!vmcs) {
+ free_kvm_area();
+ return -ENOMEM;
+ }
+
+ per_cpu(vmxarea, cpu) = vmcs;
+ }
+ return 0;
+}
+
+static __init int hardware_setup(void)
+{
+ setup_vmcs_descriptor();
+ return alloc_kvm_area();
+}
+
+static __exit void hardware_unsetup(void)
+{
+ free_kvm_area();
+}
+
+static void update_exception_bitmap(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->rmode.active)
+ vmcs_write32(EXCEPTION_BITMAP, ~0);
+ else
+ vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
+}
+
+static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
+{
+ struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+ if (vmcs_readl(sf->base) == save->base) {
+ vmcs_write16(sf->selector, save->selector);
+ vmcs_writel(sf->base, save->base);
+ vmcs_write32(sf->limit, save->limit);
+ vmcs_write32(sf->ar_bytes, save->ar);
+ } else {
+ u32 dpl = (vmcs_read16(sf->selector) & SELECTOR_RPL_MASK)
+ << AR_DPL_SHIFT;
+ vmcs_write32(sf->ar_bytes, 0x93 | dpl);
+ }
+}
+
+static void enter_pmode(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags;
+
+ vcpu->rmode.active = 0;
+
+ vmcs_writel(GUEST_TR_BASE, vcpu->rmode.tr.base);
+ vmcs_write32(GUEST_TR_LIMIT, vcpu->rmode.tr.limit);
+ vmcs_write32(GUEST_TR_AR_BYTES, vcpu->rmode.tr.ar);
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ flags &= ~(IOPL_MASK | X86_EFLAGS_VM);
+ flags |= (vcpu->rmode.save_iopl << IOPL_SHIFT);
+ vmcs_writel(GUEST_RFLAGS, flags);
+
+ vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~CR4_VME_MASK) |
+ (vmcs_readl(CR4_READ_SHADOW) & CR4_VME_MASK));
+
+ update_exception_bitmap(vcpu);
+
+ fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->rmode.es);
+ fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->rmode.ds);
+ fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->rmode.gs);
+ fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->rmode.fs);
+
+ vmcs_write16(GUEST_SS_SELECTOR, 0);
+ vmcs_write32(GUEST_SS_AR_BYTES, 0x93);
+
+ vmcs_write16(GUEST_CS_SELECTOR,
+ vmcs_read16(GUEST_CS_SELECTOR) & ~SELECTOR_RPL_MASK);
+ vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
+}
+
+static int rmode_tss_base(struct kvm* kvm)
+{
+ gfn_t base_gfn = kvm->memslots[0].base_gfn + kvm->memslots[0].npages - 3;
+ return base_gfn << PAGE_SHIFT;
+}
+
+static void fix_rmode_seg(int seg, struct kvm_save_segment *save)
+{
+ struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+ save->selector = vmcs_read16(sf->selector);
+ save->base = vmcs_readl(sf->base);
+ save->limit = vmcs_read32(sf->limit);
+ save->ar = vmcs_read32(sf->ar_bytes);
+ vmcs_write16(sf->selector, vmcs_readl(sf->base) >> 4);
+ vmcs_write32(sf->limit, 0xffff);
+ vmcs_write32(sf->ar_bytes, 0xf3);
+}
+
+static void enter_rmode(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags;
+
+ vcpu->rmode.active = 1;
+
+ vcpu->rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
+ vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
+
+ vcpu->rmode.tr.limit = vmcs_read32(GUEST_TR_LIMIT);
+ vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1);
+
+ vcpu->rmode.tr.ar = vmcs_read32(GUEST_TR_AR_BYTES);
+ vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ vcpu->rmode.save_iopl = (flags & IOPL_MASK) >> IOPL_SHIFT;
+
+ flags |= IOPL_MASK | X86_EFLAGS_VM;
+
+ vmcs_writel(GUEST_RFLAGS, flags);
+ vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | CR4_VME_MASK);
+ update_exception_bitmap(vcpu);
+
+ vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4);
+ vmcs_write32(GUEST_SS_LIMIT, 0xffff);
+ vmcs_write32(GUEST_SS_AR_BYTES, 0xf3);
+
+ vmcs_write32(GUEST_CS_AR_BYTES, 0xf3);
+ vmcs_write32(GUEST_CS_LIMIT, 0xffff);
+ vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4);
+
+ fix_rmode_seg(VCPU_SREG_ES, &vcpu->rmode.es);
+ fix_rmode_seg(VCPU_SREG_DS, &vcpu->rmode.ds);
+ fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
+ fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
+}
+
+#ifdef CONFIG_X86_64
+
+static void enter_lmode(struct kvm_vcpu *vcpu)
+{
+ u32 guest_tr_ar;
+
+ guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
+ if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
+ printk(KERN_DEBUG "%s: tss fixup for long mode. \n",
+ __FUNCTION__);
+ vmcs_write32(GUEST_TR_AR_BYTES,
+ (guest_tr_ar & ~AR_TYPE_MASK)
+ | AR_TYPE_BUSY_64_TSS);
+ }
+
+ vcpu->shadow_efer |= EFER_LMA;
+
+ find_msr_entry(vcpu, MSR_EFER)->data |= EFER_LMA | EFER_LME;
+ vmcs_write32(VM_ENTRY_CONTROLS,
+ vmcs_read32(VM_ENTRY_CONTROLS)
+ | VM_ENTRY_CONTROLS_IA32E_MASK);
+}
+
+static void exit_lmode(struct kvm_vcpu *vcpu)
+{
+ vcpu->shadow_efer &= ~EFER_LMA;
+
+ vmcs_write32(VM_ENTRY_CONTROLS,
+ vmcs_read32(VM_ENTRY_CONTROLS)
+ & ~VM_ENTRY_CONTROLS_IA32E_MASK);
+}
+
+#endif
+
+static void vmx_decache_cr0_cr4_guest_bits(struct kvm_vcpu *vcpu)
+{
+ vcpu->cr0 &= KVM_GUEST_CR0_MASK;
+ vcpu->cr0 |= vmcs_readl(GUEST_CR0) & ~KVM_GUEST_CR0_MASK;
+
+ vcpu->cr4 &= KVM_GUEST_CR4_MASK;
+ vcpu->cr4 |= vmcs_readl(GUEST_CR4) & ~KVM_GUEST_CR4_MASK;
+}
+
+static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+ if (vcpu->rmode.active && (cr0 & CR0_PE_MASK))
+ enter_pmode(vcpu);
+
+ if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
+ enter_rmode(vcpu);
+
+#ifdef CONFIG_X86_64
+ if (vcpu->shadow_efer & EFER_LME) {
+ if (!is_paging(vcpu) && (cr0 & CR0_PG_MASK))
+ enter_lmode(vcpu);
+ if (is_paging(vcpu) && !(cr0 & CR0_PG_MASK))
+ exit_lmode(vcpu);
+ }
+#endif
+
+ vmcs_writel(CR0_READ_SHADOW, cr0);
+ vmcs_writel(GUEST_CR0,
+ (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
+ vcpu->cr0 = cr0;
+}
+
+/*
+ * Used when restoring the VM to avoid corrupting segment registers
+ */
+static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+ vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0);
+ update_exception_bitmap(vcpu);
+ vmcs_writel(CR0_READ_SHADOW, cr0);
+ vmcs_writel(GUEST_CR0,
+ (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON);
+ vcpu->cr0 = cr0;
+}
+
+static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+ vmcs_writel(GUEST_CR3, cr3);
+}
+
+static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+ vmcs_writel(CR4_READ_SHADOW, cr4);
+ vmcs_writel(GUEST_CR4, cr4 | (vcpu->rmode.active ?
+ KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON));
+ vcpu->cr4 = cr4;
+}
+
+#ifdef CONFIG_X86_64
+
+static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+ struct vmx_msr_entry *msr = find_msr_entry(vcpu, MSR_EFER);
+
+ vcpu->shadow_efer = efer;
+ if (efer & EFER_LMA) {
+ vmcs_write32(VM_ENTRY_CONTROLS,
+ vmcs_read32(VM_ENTRY_CONTROLS) |
+ VM_ENTRY_CONTROLS_IA32E_MASK);
+ msr->data = efer;
+
+ } else {
+ vmcs_write32(VM_ENTRY_CONTROLS,
+ vmcs_read32(VM_ENTRY_CONTROLS) &
+ ~VM_ENTRY_CONTROLS_IA32E_MASK);
+
+ msr->data = efer & ~EFER_LME;
+ }
+}
+
+#endif
+
+static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+ struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+ return vmcs_readl(sf->base);
+}
+
+static void vmx_get_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+ u32 ar;
+
+ var->base = vmcs_readl(sf->base);
+ var->limit = vmcs_read32(sf->limit);
+ var->selector = vmcs_read16(sf->selector);
+ ar = vmcs_read32(sf->ar_bytes);
+ if (ar & AR_UNUSABLE_MASK)
+ ar = 0;
+ var->type = ar & 15;
+ var->s = (ar >> 4) & 1;
+ var->dpl = (ar >> 5) & 3;
+ var->present = (ar >> 7) & 1;
+ var->avl = (ar >> 12) & 1;
+ var->l = (ar >> 13) & 1;
+ var->db = (ar >> 14) & 1;
+ var->g = (ar >> 15) & 1;
+ var->unusable = (ar >> 16) & 1;
+}
+
+static void vmx_set_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+ u32 ar;
+
+ vmcs_writel(sf->base, var->base);
+ vmcs_write32(sf->limit, var->limit);
+ vmcs_write16(sf->selector, var->selector);
+ if (var->unusable)
+ ar = 1 << 16;
+ else {
+ ar = var->type & 15;
+ ar |= (var->s & 1) << 4;
+ ar |= (var->dpl & 3) << 5;
+ ar |= (var->present & 1) << 7;
+ ar |= (var->avl & 1) << 12;
+ ar |= (var->l & 1) << 13;
+ ar |= (var->db & 1) << 14;
+ ar |= (var->g & 1) << 15;
+ }
+ if (ar == 0) /* a 0 value means unusable */
+ ar = AR_UNUSABLE_MASK;
+ vmcs_write32(sf->ar_bytes, ar);
+}
+
+static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
+{
+ u32 ar = vmcs_read32(GUEST_CS_AR_BYTES);
+
+ *db = (ar >> 14) & 1;
+ *l = (ar >> 13) & 1;
+}
+
+static void vmx_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ dt->limit = vmcs_read32(GUEST_IDTR_LIMIT);
+ dt->base = vmcs_readl(GUEST_IDTR_BASE);
+}
+
+static void vmx_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ vmcs_write32(GUEST_IDTR_LIMIT, dt->limit);
+ vmcs_writel(GUEST_IDTR_BASE, dt->base);
+}
+
+static void vmx_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ dt->limit = vmcs_read32(GUEST_GDTR_LIMIT);
+ dt->base = vmcs_readl(GUEST_GDTR_BASE);
+}
+
+static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
+{
+ vmcs_write32(GUEST_GDTR_LIMIT, dt->limit);
+ vmcs_writel(GUEST_GDTR_BASE, dt->base);
+}
+
+static int init_rmode_tss(struct kvm* kvm)
+{
+ struct page *p1, *p2, *p3;
+ gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
+ char *page;
+
+ p1 = _gfn_to_page(kvm, fn++);
+ p2 = _gfn_to_page(kvm, fn++);
+ p3 = _gfn_to_page(kvm, fn);
+
+ if (!p1 || !p2 || !p3) {
+ kvm_printf(kvm,"%s: gfn_to_page failed\n", __FUNCTION__);
+ return 0;
+ }
+
+ page = kmap_atomic(p1, KM_USER0);
+ memset(page, 0, PAGE_SIZE);
+ *(u16*)(page + 0x66) = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
+ kunmap_atomic(page, KM_USER0);
+
+ page = kmap_atomic(p2, KM_USER0);
+ memset(page, 0, PAGE_SIZE);
+ kunmap_atomic(page, KM_USER0);
+
+ page = kmap_atomic(p3, KM_USER0);
+ memset(page, 0, PAGE_SIZE);
+ *(page + RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1) = ~0;
+ kunmap_atomic(page, KM_USER0);
+
+ return 1;
+}
+
+static void vmcs_write32_fixedbits(u32 msr, u32 vmcs_field, u32 val)
+{
+ u32 msr_high, msr_low;
+
+ rdmsr(msr, msr_low, msr_high);
+
+ val &= msr_high;
+ val |= msr_low;
+ vmcs_write32(vmcs_field, val);
+}
+
+static void seg_setup(int seg)
+{
+ struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+ vmcs_write16(sf->selector, 0);
+ vmcs_writel(sf->base, 0);
+ vmcs_write32(sf->limit, 0xffff);
+ vmcs_write32(sf->ar_bytes, 0x93);
+}
+
+/*
+ * Sets up the vmcs for emulated real mode.
+ */
+static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+ u32 host_sysenter_cs;
+ u32 junk;
+ unsigned long a;
+ struct descriptor_table dt;
+ int i;
+ int ret = 0;
+ int nr_good_msrs;
+ extern asmlinkage void kvm_vmx_return(void);
+
+ if (!init_rmode_tss(vcpu->kvm)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memset(vcpu->regs, 0, sizeof(vcpu->regs));
+ vcpu->regs[VCPU_REGS_RDX] = get_rdx_init_val();
+ vcpu->cr8 = 0;
+ vcpu->apic_base = 0xfee00000 |
+ /*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
+ MSR_IA32_APICBASE_ENABLE;
+
+ fx_init(vcpu);
+
+ /*
+ * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
+ * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4. Sigh.
+ */
+ vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
+ vmcs_writel(GUEST_CS_BASE, 0x000f0000);
+ vmcs_write32(GUEST_CS_LIMIT, 0xffff);
+ vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
+
+ seg_setup(VCPU_SREG_DS);
+ seg_setup(VCPU_SREG_ES);
+ seg_setup(VCPU_SREG_FS);
+ seg_setup(VCPU_SREG_GS);
+ seg_setup(VCPU_SREG_SS);
+
+ vmcs_write16(GUEST_TR_SELECTOR, 0);
+ vmcs_writel(GUEST_TR_BASE, 0);
+ vmcs_write32(GUEST_TR_LIMIT, 0xffff);
+ vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
+
+ vmcs_write16(GUEST_LDTR_SELECTOR, 0);
+ vmcs_writel(GUEST_LDTR_BASE, 0);
+ vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
+ vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
+
+ vmcs_write32(GUEST_SYSENTER_CS, 0);
+ vmcs_writel(GUEST_SYSENTER_ESP, 0);
+ vmcs_writel(GUEST_SYSENTER_EIP, 0);
+
+ vmcs_writel(GUEST_RFLAGS, 0x02);
+ vmcs_writel(GUEST_RIP, 0xfff0);
+ vmcs_writel(GUEST_RSP, 0);
+
+ //todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0
+ vmcs_writel(GUEST_DR7, 0x400);
+
+ vmcs_writel(GUEST_GDTR_BASE, 0);
+ vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
+
+ vmcs_writel(GUEST_IDTR_BASE, 0);
+ vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
+
+ vmcs_write32(GUEST_ACTIVITY_STATE, 0);
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
+ vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
+
+ /* I/O */
+ vmcs_write64(IO_BITMAP_A, 0);
+ vmcs_write64(IO_BITMAP_B, 0);
+
+ guest_write_tsc(0);
+
+ vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
+
+ /* Special registers */
+ vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
+
+ /* Control */
+ vmcs_write32_fixedbits(MSR_IA32_VMX_PINBASED_CTLS,
+ PIN_BASED_VM_EXEC_CONTROL,
+ PIN_BASED_EXT_INTR_MASK /* 20.6.1 */
+ | PIN_BASED_NMI_EXITING /* 20.6.1 */
+ );
+ vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS,
+ CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_HLT_EXITING /* 20.6.2 */
+ | CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */
+ | CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */
+ | CPU_BASED_UNCOND_IO_EXITING /* 20.6.2 */
+ | CPU_BASED_MOV_DR_EXITING
+ | CPU_BASED_USE_TSC_OFFSETING /* 21.3 */
+ );
+
+ vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
+ vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */
+
+ vmcs_writel(HOST_CR0, read_cr0()); /* 22.2.3 */
+ vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
+ vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
+
+ vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
+ vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_FS_SELECTOR, read_fs()); /* 22.2.4 */
+ vmcs_write16(HOST_GS_SELECTOR, read_gs()); /* 22.2.4 */
+ vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+#ifdef CONFIG_X86_64
+ rdmsrl(MSR_FS_BASE, a);
+ vmcs_writel(HOST_FS_BASE, a); /* 22.2.4 */
+ rdmsrl(MSR_GS_BASE, a);
+ vmcs_writel(HOST_GS_BASE, a); /* 22.2.4 */
+#else
+ vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */
+ vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
+#endif
+
+ vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
+
+ get_idt(&dt);
+ vmcs_writel(HOST_IDTR_BASE, dt.base); /* 22.2.4 */
+
+
+ vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return); /* 22.2.5 */
+
+ rdmsr(MSR_IA32_SYSENTER_CS, host_sysenter_cs, junk);
+ vmcs_write32(HOST_IA32_SYSENTER_CS, host_sysenter_cs);
+ rdmsrl(MSR_IA32_SYSENTER_ESP, a);
+ vmcs_writel(HOST_IA32_SYSENTER_ESP, a); /* 22.2.3 */
+ rdmsrl(MSR_IA32_SYSENTER_EIP, a);
+ vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */
+
+ for (i = 0; i < NR_VMX_MSR; ++i) {
+ u32 index = vmx_msr_index[i];
+ u32 data_low, data_high;
+ u64 data;
+ int j = vcpu->nmsrs;
+
+ if (rdmsr_safe(index, &data_low, &data_high) < 0)
+ continue;
+ if (wrmsr_safe(index, data_low, data_high) < 0)
+ continue;
+ data = data_low | ((u64)data_high << 32);
+ vcpu->host_msrs[j].index = index;
+ vcpu->host_msrs[j].reserved = 0;
+ vcpu->host_msrs[j].data = data;
+ vcpu->guest_msrs[j] = vcpu->host_msrs[j];
+ ++vcpu->nmsrs;
+ }
+ printk(KERN_DEBUG "kvm: msrs: %d\n", vcpu->nmsrs);
+
+ nr_good_msrs = vcpu->nmsrs - NR_BAD_MSRS;
+ vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
+ virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
+ vmcs_writel(VM_EXIT_MSR_STORE_ADDR,
+ virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
+ vmcs_writel(VM_EXIT_MSR_LOAD_ADDR,
+ virt_to_phys(vcpu->host_msrs + NR_BAD_MSRS));
+ vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS, VM_EXIT_CONTROLS,
+ (HOST_IS_64 << 9)); /* 22.2,1, 20.7.1 */
+ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
+
+
+ /* 22.2.1, 20.8.1 */
+ vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS,
+ VM_ENTRY_CONTROLS, 0);
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
+
+#ifdef CONFIG_X86_64
+ vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0);
+ vmcs_writel(TPR_THRESHOLD, 0);
+#endif
+
+ vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK);
+ vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
+
+ vcpu->cr0 = 0x60000010;
+ vmx_set_cr0(vcpu, vcpu->cr0); // enter rmode
+ vmx_set_cr4(vcpu, 0);
+#ifdef CONFIG_X86_64
+ vmx_set_efer(vcpu, 0);
+#endif
+
+ return 0;
+
+out:
+ return ret;
+}
+
+static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq)
+{
+ u16 ent[2];
+ u16 cs;
+ u16 ip;
+ unsigned long flags;
+ unsigned long ss_base = vmcs_readl(GUEST_SS_BASE);
+ u16 sp = vmcs_readl(GUEST_RSP);
+ u32 ss_limit = vmcs_read32(GUEST_SS_LIMIT);
+
+ if (sp > ss_limit || sp - 6 > sp) {
+ vcpu_printf(vcpu, "%s: #SS, rsp 0x%lx ss 0x%lx limit 0x%x\n",
+ __FUNCTION__,
+ vmcs_readl(GUEST_RSP),
+ vmcs_readl(GUEST_SS_BASE),
+ vmcs_read32(GUEST_SS_LIMIT));
+ return;
+ }
+
+ if (kvm_read_guest(vcpu, irq * sizeof(ent), sizeof(ent), &ent) !=
+ sizeof(ent)) {
+ vcpu_printf(vcpu, "%s: read guest err\n", __FUNCTION__);
+ return;
+ }
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ cs = vmcs_readl(GUEST_CS_BASE) >> 4;
+ ip = vmcs_readl(GUEST_RIP);
+
+
+ if (kvm_write_guest(vcpu, ss_base + sp - 2, 2, &flags) != 2 ||
+ kvm_write_guest(vcpu, ss_base + sp - 4, 2, &cs) != 2 ||
+ kvm_write_guest(vcpu, ss_base + sp - 6, 2, &ip) != 2) {
+ vcpu_printf(vcpu, "%s: write guest err\n", __FUNCTION__);
+ return;
+ }
+
+ vmcs_writel(GUEST_RFLAGS, flags &
+ ~( X86_EFLAGS_IF | X86_EFLAGS_AC | X86_EFLAGS_TF));
+ vmcs_write16(GUEST_CS_SELECTOR, ent[1]) ;
+ vmcs_writel(GUEST_CS_BASE, ent[1] << 4);
+ vmcs_writel(GUEST_RIP, ent[0]);
+ vmcs_writel(GUEST_RSP, (vmcs_readl(GUEST_RSP) & ~0xffff) | (sp - 6));
+}
+
+static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
+{
+ int word_index = __ffs(vcpu->irq_summary);
+ int bit_index = __ffs(vcpu->irq_pending[word_index]);
+ int irq = word_index * BITS_PER_LONG + bit_index;
+
+ clear_bit(bit_index, &vcpu->irq_pending[word_index]);
+ if (!vcpu->irq_pending[word_index])
+ clear_bit(word_index, &vcpu->irq_summary);
+
+ if (vcpu->rmode.active) {
+ inject_rmode_irq(vcpu, irq);
+ return;
+ }
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
+}
+
+
+static void do_interrupt_requests(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ u32 cpu_based_vm_exec_control;
+
+ vcpu->interrupt_window_open =
+ ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+ (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
+
+ if (vcpu->interrupt_window_open &&
+ vcpu->irq_summary &&
+ !(vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) & INTR_INFO_VALID_MASK))
+ /*
+ * If interrupts enabled, and not blocked by sti or mov ss. Good.
+ */
+ kvm_do_inject_irq(vcpu);
+
+ cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ if (!vcpu->interrupt_window_open &&
+ (vcpu->irq_summary || kvm_run->request_interrupt_window))
+ /*
+ * Interrupts blocked. Wait for unblock.
+ */
+ cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
+ else
+ cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+}
+
+static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu)
+{
+ struct kvm_guest_debug *dbg = &vcpu->guest_debug;
+
+ set_debugreg(dbg->bp[0], 0);
+ set_debugreg(dbg->bp[1], 1);
+ set_debugreg(dbg->bp[2], 2);
+ set_debugreg(dbg->bp[3], 3);
+
+ if (dbg->singlestep) {
+ unsigned long flags;
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
+ vmcs_writel(GUEST_RFLAGS, flags);
+ }
+}
+
+static int handle_rmode_exception(struct kvm_vcpu *vcpu,
+ int vec, u32 err_code)
+{
+ if (!vcpu->rmode.active)
+ return 0;
+
+ if (vec == GP_VECTOR && err_code == 0)
+ if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE)
+ return 1;
+ return 0;
+}
+
+static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 intr_info, error_code;
+ unsigned long cr2, rip;
+ u32 vect_info;
+ enum emulation_result er;
+ int r;
+
+ vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+ intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+ !is_page_fault(intr_info)) {
+ printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
+ "intr info 0x%x\n", __FUNCTION__, vect_info, intr_info);
+ }
+
+ if (is_external_interrupt(vect_info)) {
+ int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
+ set_bit(irq, vcpu->irq_pending);
+ set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
+ }
+
+ if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */
+ asm ("int $2");
+ return 1;
+ }
+ error_code = 0;
+ rip = vmcs_readl(GUEST_RIP);
+ if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
+ error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+ if (is_page_fault(intr_info)) {
+ cr2 = vmcs_readl(EXIT_QUALIFICATION);
+
+ spin_lock(&vcpu->kvm->lock);
+ r = kvm_mmu_page_fault(vcpu, cr2, error_code);
+ if (r < 0) {
+ spin_unlock(&vcpu->kvm->lock);
+ return r;
+ }
+ if (!r) {
+ spin_unlock(&vcpu->kvm->lock);
+ return 1;
+ }
+
+ er = emulate_instruction(vcpu, kvm_run, cr2, error_code);
+ spin_unlock(&vcpu->kvm->lock);
+
+ switch (er) {
+ case EMULATE_DONE:
+ return 1;
+ case EMULATE_DO_MMIO:
+ ++kvm_stat.mmio_exits;
+ kvm_run->exit_reason = KVM_EXIT_MMIO;
+ return 0;
+ case EMULATE_FAIL:
+ vcpu_printf(vcpu, "%s: emulate fail\n", __FUNCTION__);
+ break;
+ default:
+ BUG();
+ }
+ }
+
+ if (vcpu->rmode.active &&
+ handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
+ error_code))
+ return 1;
+
+ if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == (INTR_TYPE_EXCEPTION | 1)) {
+ kvm_run->exit_reason = KVM_EXIT_DEBUG;
+ return 0;
+ }
+ kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
+ kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK;
+ kvm_run->ex.error_code = error_code;
+ return 0;
+}
+
+static int handle_external_interrupt(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ ++kvm_stat.irq_exits;
+ return 1;
+}
+
+
+static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
+{
+ u64 inst;
+ gva_t rip;
+ int countr_size;
+ int i, n;
+
+ if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) {
+ countr_size = 2;
+ } else {
+ u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
+
+ countr_size = (cs_ar & AR_L_MASK) ? 8:
+ (cs_ar & AR_DB_MASK) ? 4: 2;
+ }
+
+ rip = vmcs_readl(GUEST_RIP);
+ if (countr_size != 8)
+ rip += vmcs_readl(GUEST_CS_BASE);
+
+ n = kvm_read_guest(vcpu, rip, sizeof(inst), &inst);
+
+ for (i = 0; i < n; i++) {
+ switch (((u8*)&inst)[i]) {
+ case 0xf0:
+ case 0xf2:
+ case 0xf3:
+ case 0x2e:
+ case 0x36:
+ case 0x3e:
+ case 0x26:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ break;
+ case 0x67:
+ countr_size = (countr_size == 2) ? 4: (countr_size >> 1);
+ default:
+ goto done;
+ }
+ }
+ return 0;
+done:
+ countr_size *= 8;
+ *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
+ return 1;
+}
+
+static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u64 exit_qualification;
+
+ ++kvm_stat.io_exits;
+ exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ kvm_run->exit_reason = KVM_EXIT_IO;
+ if (exit_qualification & 8)
+ kvm_run->io.direction = KVM_EXIT_IO_IN;
+ else
+ kvm_run->io.direction = KVM_EXIT_IO_OUT;
+ kvm_run->io.size = (exit_qualification & 7) + 1;
+ kvm_run->io.string = (exit_qualification & 16) != 0;
+ kvm_run->io.string_down
+ = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
+ kvm_run->io.rep = (exit_qualification & 32) != 0;
+ kvm_run->io.port = exit_qualification >> 16;
+ if (kvm_run->io.string) {
+ if (!get_io_count(vcpu, &kvm_run->io.count))
+ return 1;
+ kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS);
+ } else
+ kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */
+ return 0;
+}
+
+static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u64 exit_qualification;
+ int cr;
+ int reg;
+
+ exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ cr = exit_qualification & 15;
+ reg = (exit_qualification >> 8) & 15;
+ switch ((exit_qualification >> 4) & 3) {
+ case 0: /* mov to cr */
+ switch (cr) {
+ case 0:
+ vcpu_load_rsp_rip(vcpu);
+ set_cr0(vcpu, vcpu->regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 3:
+ vcpu_load_rsp_rip(vcpu);
+ set_cr3(vcpu, vcpu->regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 4:
+ vcpu_load_rsp_rip(vcpu);
+ set_cr4(vcpu, vcpu->regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 8:
+ vcpu_load_rsp_rip(vcpu);
+ set_cr8(vcpu, vcpu->regs[reg]);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ };
+ break;
+ case 1: /*mov from cr*/
+ switch (cr) {
+ case 3:
+ vcpu_load_rsp_rip(vcpu);
+ vcpu->regs[reg] = vcpu->cr3;
+ vcpu_put_rsp_rip(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ case 8:
+ printk(KERN_DEBUG "handle_cr: read CR8 "
+ "cpu erratum AA15\n");
+ vcpu_load_rsp_rip(vcpu);
+ vcpu->regs[reg] = vcpu->cr8;
+ vcpu_put_rsp_rip(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ break;
+ case 3: /* lmsw */
+ lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
+
+ skip_emulated_instruction(vcpu);
+ return 1;
+ default:
+ break;
+ }
+ kvm_run->exit_reason = 0;
+ printk(KERN_ERR "kvm: unhandled control register: op %d cr %d\n",
+ (int)(exit_qualification >> 4) & 3, cr);
+ return 0;
+}
+
+static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u64 exit_qualification;
+ unsigned long val;
+ int dr, reg;
+
+ /*
+ * FIXME: this code assumes the host is debugging the guest.
+ * need to deal with guest debugging itself too.
+ */
+ exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+ dr = exit_qualification & 7;
+ reg = (exit_qualification >> 8) & 15;
+ vcpu_load_rsp_rip(vcpu);
+ if (exit_qualification & 16) {
+ /* mov from dr */
+ switch (dr) {
+ case 6:
+ val = 0xffff0ff0;
+ break;
+ case 7:
+ val = 0x400;
+ break;
+ default:
+ val = 0;
+ }
+ vcpu->regs[reg] = val;
+ } else {
+ /* mov to dr */
+ }
+ vcpu_put_rsp_rip(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ kvm_run->exit_reason = KVM_EXIT_CPUID;
+ return 0;
+}
+
+static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+ u64 data;
+
+ if (vmx_get_msr(vcpu, ecx, &data)) {
+ vmx_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ /* FIXME: handling of bits 32:63 of rax, rdx */
+ vcpu->regs[VCPU_REGS_RAX] = data & -1u;
+ vcpu->regs[VCPU_REGS_RDX] = (data >> 32) & -1u;
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u32 ecx = vcpu->regs[VCPU_REGS_RCX];
+ u64 data = (vcpu->regs[VCPU_REGS_RAX] & -1u)
+ | ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32);
+
+ if (vmx_set_msr(vcpu, ecx, data) != 0) {
+ vmx_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+static void post_kvm_run_save(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ kvm_run->if_flag = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) != 0;
+ kvm_run->cr8 = vcpu->cr8;
+ kvm_run->apic_base = vcpu->apic_base;
+ kvm_run->ready_for_interrupt_injection = (vcpu->interrupt_window_open &&
+ vcpu->irq_summary == 0);
+}
+
+static int handle_interrupt_window(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ /*
+ * If the user space waits to inject interrupts, exit as soon as
+ * possible
+ */
+ if (kvm_run->request_interrupt_window &&
+ !vcpu->irq_summary) {
+ kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
+ ++kvm_stat.irq_window_exits;
+ return 0;
+ }
+ return 1;
+}
+
+static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ skip_emulated_instruction(vcpu);
+ if (vcpu->irq_summary)
+ return 1;
+
+ kvm_run->exit_reason = KVM_EXIT_HLT;
+ ++kvm_stat.halt_exits;
+ return 0;
+}
+
+/*
+ * The exit handlers return 1 if the exit was handled fully and guest execution
+ * may resume. Otherwise they set the kvm_run parameter to indicate what needs
+ * to be done to userspace and return 0.
+ */
+static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run) = {
+ [EXIT_REASON_EXCEPTION_NMI] = handle_exception,
+ [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt,
+ [EXIT_REASON_IO_INSTRUCTION] = handle_io,
+ [EXIT_REASON_CR_ACCESS] = handle_cr,
+ [EXIT_REASON_DR_ACCESS] = handle_dr,
+ [EXIT_REASON_CPUID] = handle_cpuid,
+ [EXIT_REASON_MSR_READ] = handle_rdmsr,
+ [EXIT_REASON_MSR_WRITE] = handle_wrmsr,
+ [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window,
+ [EXIT_REASON_HLT] = handle_halt,
+};
+
+static const int kvm_vmx_max_exit_handlers =
+ sizeof(kvm_vmx_exit_handlers) / sizeof(*kvm_vmx_exit_handlers);
+
+/*
+ * The guest has exited. See if we can fix it or if we need userspace
+ * assistance.
+ */
+static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+ u32 vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+ u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
+
+ if ( (vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ exit_reason != EXIT_REASON_EXCEPTION_NMI )
+ printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
+ "exit reason is 0x%x\n", __FUNCTION__, exit_reason);
+ kvm_run->instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ if (exit_reason < kvm_vmx_max_exit_handlers
+ && kvm_vmx_exit_handlers[exit_reason])
+ return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
+ else {
+ kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+ kvm_run->hw.hardware_exit_reason = exit_reason;
+ }
+ return 0;
+}
+
+/*
+ * Check if userspace requested an interrupt window, and that the
+ * interrupt window is open.
+ *
+ * No need to exit to userspace if we already have an interrupt queued.
+ */
+static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ return (!vcpu->irq_summary &&
+ kvm_run->request_interrupt_window &&
+ vcpu->interrupt_window_open &&
+ (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF));
+}
+
+static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ u8 fail;
+ u16 fs_sel, gs_sel, ldt_sel;
+ int fs_gs_ldt_reload_needed;
+ int r;
+
+again:
+ /*
+ * Set host fs and gs selectors. Unfortunately, 22.2.3 does not
+ * allow segment selectors with cpl > 0 or ti == 1.
+ */
+ fs_sel = read_fs();
+ gs_sel = read_gs();
+ ldt_sel = read_ldt();
+ fs_gs_ldt_reload_needed = (fs_sel & 7) | (gs_sel & 7) | ldt_sel;
+ if (!fs_gs_ldt_reload_needed) {
+ vmcs_write16(HOST_FS_SELECTOR, fs_sel);
+ vmcs_write16(HOST_GS_SELECTOR, gs_sel);
+ } else {
+ vmcs_write16(HOST_FS_SELECTOR, 0);
+ vmcs_write16(HOST_GS_SELECTOR, 0);
+ }
+
+#ifdef CONFIG_X86_64
+ vmcs_writel(HOST_FS_BASE, read_msr(MSR_FS_BASE));
+ vmcs_writel(HOST_GS_BASE, read_msr(MSR_GS_BASE));
+#else
+ vmcs_writel(HOST_FS_BASE, segment_base(fs_sel));
+ vmcs_writel(HOST_GS_BASE, segment_base(gs_sel));
+#endif
+
+ if (!vcpu->mmio_read_completed)
+ do_interrupt_requests(vcpu, kvm_run);
+
+ if (vcpu->guest_debug.enabled)
+ kvm_guest_debug_pre(vcpu);
+
+ fx_save(vcpu->host_fx_image);
+ fx_restore(vcpu->guest_fx_image);
+
+ save_msrs(vcpu->host_msrs, vcpu->nmsrs);
+ load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+
+ asm (
+ /* Store host registers */
+ "pushf \n\t"
+#ifdef CONFIG_X86_64
+ "push %%rax; push %%rbx; push %%rdx;"
+ "push %%rsi; push %%rdi; push %%rbp;"
+ "push %%r8; push %%r9; push %%r10; push %%r11;"
+ "push %%r12; push %%r13; push %%r14; push %%r15;"
+ "push %%rcx \n\t"
+ ASM_VMX_VMWRITE_RSP_RDX "\n\t"
+#else
+ "pusha; push %%ecx \n\t"
+ ASM_VMX_VMWRITE_RSP_RDX "\n\t"
+#endif
+ /* Check if vmlaunch of vmresume is needed */
+ "cmp $0, %1 \n\t"
+ /* Load guest registers. Don't clobber flags. */
+#ifdef CONFIG_X86_64
+ "mov %c[cr2](%3), %%rax \n\t"
+ "mov %%rax, %%cr2 \n\t"
+ "mov %c[rax](%3), %%rax \n\t"
+ "mov %c[rbx](%3), %%rbx \n\t"
+ "mov %c[rdx](%3), %%rdx \n\t"
+ "mov %c[rsi](%3), %%rsi \n\t"
+ "mov %c[rdi](%3), %%rdi \n\t"
+ "mov %c[rbp](%3), %%rbp \n\t"
+ "mov %c[r8](%3), %%r8 \n\t"
+ "mov %c[r9](%3), %%r9 \n\t"
+ "mov %c[r10](%3), %%r10 \n\t"
+ "mov %c[r11](%3), %%r11 \n\t"
+ "mov %c[r12](%3), %%r12 \n\t"
+ "mov %c[r13](%3), %%r13 \n\t"
+ "mov %c[r14](%3), %%r14 \n\t"
+ "mov %c[r15](%3), %%r15 \n\t"
+ "mov %c[rcx](%3), %%rcx \n\t" /* kills %3 (rcx) */
+#else
+ "mov %c[cr2](%3), %%eax \n\t"
+ "mov %%eax, %%cr2 \n\t"
+ "mov %c[rax](%3), %%eax \n\t"
+ "mov %c[rbx](%3), %%ebx \n\t"
+ "mov %c[rdx](%3), %%edx \n\t"
+ "mov %c[rsi](%3), %%esi \n\t"
+ "mov %c[rdi](%3), %%edi \n\t"
+ "mov %c[rbp](%3), %%ebp \n\t"
+ "mov %c[rcx](%3), %%ecx \n\t" /* kills %3 (ecx) */
+#endif
+ /* Enter guest mode */
+ "jne launched \n\t"
+ ASM_VMX_VMLAUNCH "\n\t"
+ "jmp kvm_vmx_return \n\t"
+ "launched: " ASM_VMX_VMRESUME "\n\t"
+ ".globl kvm_vmx_return \n\t"
+ "kvm_vmx_return: "
+ /* Save guest registers, load host registers, keep flags */
+#ifdef CONFIG_X86_64
+ "xchg %3, 0(%%rsp) \n\t"
+ "mov %%rax, %c[rax](%3) \n\t"
+ "mov %%rbx, %c[rbx](%3) \n\t"
+ "pushq 0(%%rsp); popq %c[rcx](%3) \n\t"
+ "mov %%rdx, %c[rdx](%3) \n\t"
+ "mov %%rsi, %c[rsi](%3) \n\t"
+ "mov %%rdi, %c[rdi](%3) \n\t"
+ "mov %%rbp, %c[rbp](%3) \n\t"
+ "mov %%r8, %c[r8](%3) \n\t"
+ "mov %%r9, %c[r9](%3) \n\t"
+ "mov %%r10, %c[r10](%3) \n\t"
+ "mov %%r11, %c[r11](%3) \n\t"
+ "mov %%r12, %c[r12](%3) \n\t"
+ "mov %%r13, %c[r13](%3) \n\t"
+ "mov %%r14, %c[r14](%3) \n\t"
+ "mov %%r15, %c[r15](%3) \n\t"
+ "mov %%cr2, %%rax \n\t"
+ "mov %%rax, %c[cr2](%3) \n\t"
+ "mov 0(%%rsp), %3 \n\t"
+
+ "pop %%rcx; pop %%r15; pop %%r14; pop %%r13; pop %%r12;"
+ "pop %%r11; pop %%r10; pop %%r9; pop %%r8;"
+ "pop %%rbp; pop %%rdi; pop %%rsi;"
+ "pop %%rdx; pop %%rbx; pop %%rax \n\t"
+#else
+ "xchg %3, 0(%%esp) \n\t"
+ "mov %%eax, %c[rax](%3) \n\t"
+ "mov %%ebx, %c[rbx](%3) \n\t"
+ "pushl 0(%%esp); popl %c[rcx](%3) \n\t"
+ "mov %%edx, %c[rdx](%3) \n\t"
+ "mov %%esi, %c[rsi](%3) \n\t"
+ "mov %%edi, %c[rdi](%3) \n\t"
+ "mov %%ebp, %c[rbp](%3) \n\t"
+ "mov %%cr2, %%eax \n\t"
+ "mov %%eax, %c[cr2](%3) \n\t"
+ "mov 0(%%esp), %3 \n\t"
+
+ "pop %%ecx; popa \n\t"
+#endif
+ "setbe %0 \n\t"
+ "popf \n\t"
+ : "=q" (fail)
+ : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP),
+ "c"(vcpu),
+ [rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])),
+ [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])),
+ [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])),
+ [rdx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDX])),
+ [rsi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RSI])),
+ [rdi]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RDI])),
+ [rbp]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBP])),
+#ifdef CONFIG_X86_64
+ [r8 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R8 ])),
+ [r9 ]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R9 ])),
+ [r10]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R10])),
+ [r11]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R11])),
+ [r12]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R12])),
+ [r13]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R13])),
+ [r14]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R14])),
+ [r15]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_R15])),
+#endif
+ [cr2]"i"(offsetof(struct kvm_vcpu, cr2))
+ : "cc", "memory" );
+
+ ++kvm_stat.exits;
+
+ save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
+ load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
+
+ fx_save(vcpu->guest_fx_image);
+ fx_restore(vcpu->host_fx_image);
+ vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
+
+#ifndef CONFIG_X86_64
+ asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
+#endif
+
+ /*
+ * Profile KVM exit RIPs:
+ */
+ if (unlikely(prof_on == KVM_PROFILING))
+ profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
+
+ kvm_run->exit_type = 0;
+ if (fail) {
+ kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
+ kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR);
+ r = 0;
+ } else {
+ if (fs_gs_ldt_reload_needed) {
+ load_ldt(ldt_sel);
+ load_fs(fs_sel);
+ /*
+ * If we have to reload gs, we must take care to
+ * preserve our gs base.
+ */
+ local_irq_disable();
+ load_gs(gs_sel);
+#ifdef CONFIG_X86_64
+ wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+#endif
+ local_irq_enable();
+
+ reload_tss();
+ }
+ vcpu->launched = 1;
+ kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
+ r = kvm_handle_exit(kvm_run, vcpu);
+ if (r > 0) {
+ /* Give scheduler a change to reschedule. */
+ if (signal_pending(current)) {
+ ++kvm_stat.signal_exits;
+ post_kvm_run_save(vcpu, kvm_run);
+ return -EINTR;
+ }
+
+ if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+ ++kvm_stat.request_irq_exits;
+ post_kvm_run_save(vcpu, kvm_run);
+ return -EINTR;
+ }
+
+ kvm_resched(vcpu);
+ goto again;
+ }
+ }
+
+ post_kvm_run_save(vcpu, kvm_run);
+ return r;
+}
+
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+{
+ vmcs_writel(GUEST_CR3, vmcs_readl(GUEST_CR3));
+}
+
+static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
+ unsigned long addr,
+ u32 err_code)
+{
+ u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+
+ ++kvm_stat.pf_guest;
+
+ if (is_page_fault(vect_info)) {
+ printk(KERN_DEBUG "inject_page_fault: "
+ "double fault 0x%lx @ 0x%lx\n",
+ addr, vmcs_readl(GUEST_RIP));
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0);
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ DF_VECTOR |
+ INTR_TYPE_EXCEPTION |
+ INTR_INFO_DELIEVER_CODE_MASK |
+ INTR_INFO_VALID_MASK);
+ return;
+ }
+ vcpu->cr2 = addr;
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code);
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ PF_VECTOR |
+ INTR_TYPE_EXCEPTION |
+ INTR_INFO_DELIEVER_CODE_MASK |
+ INTR_INFO_VALID_MASK);
+
+}
+
+static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->vmcs) {
+ on_each_cpu(__vcpu_clear, vcpu, 0, 1);
+ free_vmcs(vcpu->vmcs);
+ vcpu->vmcs = NULL;
+ }
+}
+
+static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
+{
+ vmx_free_vmcs(vcpu);
+}
+
+static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct vmcs *vmcs;
+
+ vcpu->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!vcpu->guest_msrs)
+ return -ENOMEM;
+
+ vcpu->host_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!vcpu->host_msrs)
+ goto out_free_guest_msrs;
+
+ vmcs = alloc_vmcs();
+ if (!vmcs)
+ goto out_free_msrs;
+
+ vmcs_clear(vmcs);
+ vcpu->vmcs = vmcs;
+ vcpu->launched = 0;
+
+ return 0;
+
+out_free_msrs:
+ kfree(vcpu->host_msrs);
+ vcpu->host_msrs = NULL;
+
+out_free_guest_msrs:
+ kfree(vcpu->guest_msrs);
+ vcpu->guest_msrs = NULL;
+
+ return -ENOMEM;
+}
+
+static struct kvm_arch_ops vmx_arch_ops = {
+ .cpu_has_kvm_support = cpu_has_kvm_support,
+ .disabled_by_bios = vmx_disabled_by_bios,
+ .hardware_setup = hardware_setup,
+ .hardware_unsetup = hardware_unsetup,
+ .hardware_enable = hardware_enable,
+ .hardware_disable = hardware_disable,
+
+ .vcpu_create = vmx_create_vcpu,
+ .vcpu_free = vmx_free_vcpu,
+
+ .vcpu_load = vmx_vcpu_load,
+ .vcpu_put = vmx_vcpu_put,
+
+ .set_guest_debug = set_guest_debug,
+ .get_msr = vmx_get_msr,
+ .set_msr = vmx_set_msr,
+ .get_segment_base = vmx_get_segment_base,
+ .get_segment = vmx_get_segment,
+ .set_segment = vmx_set_segment,
+ .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+ .decache_cr0_cr4_guest_bits = vmx_decache_cr0_cr4_guest_bits,
+ .set_cr0 = vmx_set_cr0,
+ .set_cr0_no_modeswitch = vmx_set_cr0_no_modeswitch,
+ .set_cr3 = vmx_set_cr3,
+ .set_cr4 = vmx_set_cr4,
+#ifdef CONFIG_X86_64
+ .set_efer = vmx_set_efer,
+#endif
+ .get_idt = vmx_get_idt,
+ .set_idt = vmx_set_idt,
+ .get_gdt = vmx_get_gdt,
+ .set_gdt = vmx_set_gdt,
+ .cache_regs = vcpu_load_rsp_rip,
+ .decache_regs = vcpu_put_rsp_rip,
+ .get_rflags = vmx_get_rflags,
+ .set_rflags = vmx_set_rflags,
+
+ .tlb_flush = vmx_flush_tlb,
+ .inject_page_fault = vmx_inject_page_fault,
+
+ .inject_gp = vmx_inject_gp,
+
+ .run = vmx_vcpu_run,
+ .skip_emulated_instruction = skip_emulated_instruction,
+ .vcpu_setup = vmx_vcpu_setup,
+};
+
+static int __init vmx_init(void)
+{
+ return kvm_init_arch(&vmx_arch_ops, THIS_MODULE);
+}
+
+static void __exit vmx_exit(void)
+{
+ kvm_exit_arch();
+}
+
+module_init(vmx_init)
+module_exit(vmx_exit)
diff --git a/drivers/kvm/vmx.h b/drivers/kvm/vmx.h
new file mode 100644
index 00000000000..4c0ab151836
--- /dev/null
+++ b/drivers/kvm/vmx.h
@@ -0,0 +1,296 @@
+#ifndef VMX_H
+#define VMX_H
+
+/*
+ * vmx.h: VMX Architecture related definitions
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * A few random additions are:
+ * Copyright (C) 2006 Qumranet
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ *
+ */
+
+#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004
+#define CPU_BASED_USE_TSC_OFFSETING 0x00000008
+#define CPU_BASED_HLT_EXITING 0x00000080
+#define CPU_BASED_INVDPG_EXITING 0x00000200
+#define CPU_BASED_MWAIT_EXITING 0x00000400
+#define CPU_BASED_RDPMC_EXITING 0x00000800
+#define CPU_BASED_RDTSC_EXITING 0x00001000
+#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
+#define CPU_BASED_CR8_STORE_EXITING 0x00100000
+#define CPU_BASED_TPR_SHADOW 0x00200000
+#define CPU_BASED_MOV_DR_EXITING 0x00800000
+#define CPU_BASED_UNCOND_IO_EXITING 0x01000000
+#define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000
+#define CPU_BASED_MSR_BITMAPS 0x10000000
+#define CPU_BASED_MONITOR_EXITING 0x20000000
+#define CPU_BASED_PAUSE_EXITING 0x40000000
+
+#define PIN_BASED_EXT_INTR_MASK 0x1
+#define PIN_BASED_NMI_EXITING 0x8
+
+#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
+#define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200
+
+
+/* VMCS Encodings */
+enum vmcs_field {
+ GUEST_ES_SELECTOR = 0x00000800,
+ GUEST_CS_SELECTOR = 0x00000802,
+ GUEST_SS_SELECTOR = 0x00000804,
+ GUEST_DS_SELECTOR = 0x00000806,
+ GUEST_FS_SELECTOR = 0x00000808,
+ GUEST_GS_SELECTOR = 0x0000080a,
+ GUEST_LDTR_SELECTOR = 0x0000080c,
+ GUEST_TR_SELECTOR = 0x0000080e,
+ HOST_ES_SELECTOR = 0x00000c00,
+ HOST_CS_SELECTOR = 0x00000c02,
+ HOST_SS_SELECTOR = 0x00000c04,
+ HOST_DS_SELECTOR = 0x00000c06,
+ HOST_FS_SELECTOR = 0x00000c08,
+ HOST_GS_SELECTOR = 0x00000c0a,
+ HOST_TR_SELECTOR = 0x00000c0c,
+ IO_BITMAP_A = 0x00002000,
+ IO_BITMAP_A_HIGH = 0x00002001,
+ IO_BITMAP_B = 0x00002002,
+ IO_BITMAP_B_HIGH = 0x00002003,
+ MSR_BITMAP = 0x00002004,
+ MSR_BITMAP_HIGH = 0x00002005,
+ VM_EXIT_MSR_STORE_ADDR = 0x00002006,
+ VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
+ VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
+ VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
+ VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
+ VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
+ TSC_OFFSET = 0x00002010,
+ TSC_OFFSET_HIGH = 0x00002011,
+ VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
+ VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
+ VMCS_LINK_POINTER = 0x00002800,
+ VMCS_LINK_POINTER_HIGH = 0x00002801,
+ GUEST_IA32_DEBUGCTL = 0x00002802,
+ GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
+ PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
+ CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
+ EXCEPTION_BITMAP = 0x00004004,
+ PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
+ PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
+ CR3_TARGET_COUNT = 0x0000400a,
+ VM_EXIT_CONTROLS = 0x0000400c,
+ VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
+ VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
+ VM_ENTRY_CONTROLS = 0x00004012,
+ VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
+ VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
+ VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
+ VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
+ TPR_THRESHOLD = 0x0000401c,
+ SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
+ VM_INSTRUCTION_ERROR = 0x00004400,
+ VM_EXIT_REASON = 0x00004402,
+ VM_EXIT_INTR_INFO = 0x00004404,
+ VM_EXIT_INTR_ERROR_CODE = 0x00004406,
+ IDT_VECTORING_INFO_FIELD = 0x00004408,
+ IDT_VECTORING_ERROR_CODE = 0x0000440a,
+ VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
+ VMX_INSTRUCTION_INFO = 0x0000440e,
+ GUEST_ES_LIMIT = 0x00004800,
+ GUEST_CS_LIMIT = 0x00004802,
+ GUEST_SS_LIMIT = 0x00004804,
+ GUEST_DS_LIMIT = 0x00004806,
+ GUEST_FS_LIMIT = 0x00004808,
+ GUEST_GS_LIMIT = 0x0000480a,
+ GUEST_LDTR_LIMIT = 0x0000480c,
+ GUEST_TR_LIMIT = 0x0000480e,
+ GUEST_GDTR_LIMIT = 0x00004810,
+ GUEST_IDTR_LIMIT = 0x00004812,
+ GUEST_ES_AR_BYTES = 0x00004814,
+ GUEST_CS_AR_BYTES = 0x00004816,
+ GUEST_SS_AR_BYTES = 0x00004818,
+ GUEST_DS_AR_BYTES = 0x0000481a,
+ GUEST_FS_AR_BYTES = 0x0000481c,
+ GUEST_GS_AR_BYTES = 0x0000481e,
+ GUEST_LDTR_AR_BYTES = 0x00004820,
+ GUEST_TR_AR_BYTES = 0x00004822,
+ GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
+ GUEST_ACTIVITY_STATE = 0X00004826,
+ GUEST_SYSENTER_CS = 0x0000482A,
+ HOST_IA32_SYSENTER_CS = 0x00004c00,
+ CR0_GUEST_HOST_MASK = 0x00006000,
+ CR4_GUEST_HOST_MASK = 0x00006002,
+ CR0_READ_SHADOW = 0x00006004,
+ CR4_READ_SHADOW = 0x00006006,
+ CR3_TARGET_VALUE0 = 0x00006008,
+ CR3_TARGET_VALUE1 = 0x0000600a,
+ CR3_TARGET_VALUE2 = 0x0000600c,
+ CR3_TARGET_VALUE3 = 0x0000600e,
+ EXIT_QUALIFICATION = 0x00006400,
+ GUEST_LINEAR_ADDRESS = 0x0000640a,
+ GUEST_CR0 = 0x00006800,
+ GUEST_CR3 = 0x00006802,
+ GUEST_CR4 = 0x00006804,
+ GUEST_ES_BASE = 0x00006806,
+ GUEST_CS_BASE = 0x00006808,
+ GUEST_SS_BASE = 0x0000680a,
+ GUEST_DS_BASE = 0x0000680c,
+ GUEST_FS_BASE = 0x0000680e,
+ GUEST_GS_BASE = 0x00006810,
+ GUEST_LDTR_BASE = 0x00006812,
+ GUEST_TR_BASE = 0x00006814,
+ GUEST_GDTR_BASE = 0x00006816,
+ GUEST_IDTR_BASE = 0x00006818,
+ GUEST_DR7 = 0x0000681a,
+ GUEST_RSP = 0x0000681c,
+ GUEST_RIP = 0x0000681e,
+ GUEST_RFLAGS = 0x00006820,
+ GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
+ GUEST_SYSENTER_ESP = 0x00006824,
+ GUEST_SYSENTER_EIP = 0x00006826,
+ HOST_CR0 = 0x00006c00,
+ HOST_CR3 = 0x00006c02,
+ HOST_CR4 = 0x00006c04,
+ HOST_FS_BASE = 0x00006c06,
+ HOST_GS_BASE = 0x00006c08,
+ HOST_TR_BASE = 0x00006c0a,
+ HOST_GDTR_BASE = 0x00006c0c,
+ HOST_IDTR_BASE = 0x00006c0e,
+ HOST_IA32_SYSENTER_ESP = 0x00006c10,
+ HOST_IA32_SYSENTER_EIP = 0x00006c12,
+ HOST_RSP = 0x00006c14,
+ HOST_RIP = 0x00006c16,
+};
+
+#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
+
+#define EXIT_REASON_EXCEPTION_NMI 0
+#define EXIT_REASON_EXTERNAL_INTERRUPT 1
+
+#define EXIT_REASON_PENDING_INTERRUPT 7
+
+#define EXIT_REASON_TASK_SWITCH 9
+#define EXIT_REASON_CPUID 10
+#define EXIT_REASON_HLT 12
+#define EXIT_REASON_INVLPG 14
+#define EXIT_REASON_RDPMC 15
+#define EXIT_REASON_RDTSC 16
+#define EXIT_REASON_VMCALL 18
+#define EXIT_REASON_VMCLEAR 19
+#define EXIT_REASON_VMLAUNCH 20
+#define EXIT_REASON_VMPTRLD 21
+#define EXIT_REASON_VMPTRST 22
+#define EXIT_REASON_VMREAD 23
+#define EXIT_REASON_VMRESUME 24
+#define EXIT_REASON_VMWRITE 25
+#define EXIT_REASON_VMOFF 26
+#define EXIT_REASON_VMON 27
+#define EXIT_REASON_CR_ACCESS 28
+#define EXIT_REASON_DR_ACCESS 29
+#define EXIT_REASON_IO_INSTRUCTION 30
+#define EXIT_REASON_MSR_READ 31
+#define EXIT_REASON_MSR_WRITE 32
+#define EXIT_REASON_MWAIT_INSTRUCTION 36
+
+/*
+ * Interruption-information format
+ */
+#define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */
+#define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */
+#define INTR_INFO_DELIEVER_CODE_MASK 0x800 /* 11 */
+#define INTR_INFO_VALID_MASK 0x80000000 /* 31 */
+
+#define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK
+#define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK
+#define VECTORING_INFO_DELIEVER_CODE_MASK INTR_INFO_DELIEVER_CODE_MASK
+#define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK
+
+#define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */
+#define INTR_TYPE_EXCEPTION (3 << 8) /* processor exception */
+
+/*
+ * Exit Qualifications for MOV for Control Register Access
+ */
+#define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control register */
+#define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */
+#define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */
+#define LMSW_SOURCE_DATA_SHIFT 16
+#define LMSW_SOURCE_DATA (0xFFFF << LMSW_SOURCE_DATA_SHIFT) /* 16:31 lmsw source */
+#define REG_EAX (0 << 8)
+#define REG_ECX (1 << 8)
+#define REG_EDX (2 << 8)
+#define REG_EBX (3 << 8)
+#define REG_ESP (4 << 8)
+#define REG_EBP (5 << 8)
+#define REG_ESI (6 << 8)
+#define REG_EDI (7 << 8)
+#define REG_R8 (8 << 8)
+#define REG_R9 (9 << 8)
+#define REG_R10 (10 << 8)
+#define REG_R11 (11 << 8)
+#define REG_R12 (12 << 8)
+#define REG_R13 (13 << 8)
+#define REG_R14 (14 << 8)
+#define REG_R15 (15 << 8)
+
+/*
+ * Exit Qualifications for MOV for Debug Register Access
+ */
+#define DEBUG_REG_ACCESS_NUM 0x7 /* 2:0, number of debug register */
+#define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access */
+#define TYPE_MOV_TO_DR (0 << 4)
+#define TYPE_MOV_FROM_DR (1 << 4)
+#define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose register */
+
+
+/* segment AR */
+#define SEGMENT_AR_L_MASK (1 << 13)
+
+/* entry controls */
+#define VM_ENTRY_CONTROLS_IA32E_MASK (1 << 9)
+
+#define AR_TYPE_ACCESSES_MASK 1
+#define AR_TYPE_READABLE_MASK (1 << 1)
+#define AR_TYPE_WRITEABLE_MASK (1 << 2)
+#define AR_TYPE_CODE_MASK (1 << 3)
+#define AR_TYPE_MASK 0x0f
+#define AR_TYPE_BUSY_64_TSS 11
+#define AR_TYPE_BUSY_32_TSS 11
+#define AR_TYPE_BUSY_16_TSS 3
+#define AR_TYPE_LDT 2
+
+#define AR_UNUSABLE_MASK (1 << 16)
+#define AR_S_MASK (1 << 4)
+#define AR_P_MASK (1 << 7)
+#define AR_L_MASK (1 << 13)
+#define AR_DB_MASK (1 << 14)
+#define AR_G_MASK (1 << 15)
+#define AR_DPL_SHIFT 5
+#define AR_DPL(ar) (((ar) >> AR_DPL_SHIFT) & 3)
+
+#define AR_RESERVD_MASK 0xfffe0f00
+
+#define CR4_VMXE 0x2000
+
+#define MSR_IA32_VMX_BASIC 0x480
+#define MSR_IA32_FEATURE_CONTROL 0x03a
+#define MSR_IA32_VMX_PINBASED_CTLS 0x481
+#define MSR_IA32_VMX_PROCBASED_CTLS 0x482
+#define MSR_IA32_VMX_EXIT_CTLS 0x483
+#define MSR_IA32_VMX_ENTRY_CTLS 0x484
+
+#endif
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
new file mode 100644
index 00000000000..7513cddb929
--- /dev/null
+++ b/drivers/kvm/x86_emulate.c
@@ -0,0 +1,1415 @@
+/******************************************************************************
+ * x86_emulate.c
+ *
+ * Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
+ *
+ * Copyright (c) 2005 Keir Fraser
+ *
+ * Linux coding style, mod r/m decoder, segment base fixes, real-mode
+ * privieged instructions:
+ *
+ * Copyright (C) 2006 Qumranet
+ *
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4
+ */
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <stdint.h>
+#include <public/xen.h>
+#define DPRINTF(_f, _a ...) printf( _f , ## _a )
+#else
+#include "kvm.h"
+#define DPRINTF(x...) do {} while (0)
+#endif
+#include "x86_emulate.h"
+#include <linux/module.h>
+
+/*
+ * Opcode effective-address decode tables.
+ * Note that we only emulate instructions that have at least one memory
+ * operand (excluding implicit stack references). We assume that stack
+ * references and instruction fetches will never occur in special memory
+ * areas that require emulation. So, for example, 'mov <imm>,<reg>' need
+ * not be handled.
+ */
+
+/* Operand sizes: 8-bit operands or specified/overridden size. */
+#define ByteOp (1<<0) /* 8-bit operands. */
+/* Destination operand type. */
+#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */
+#define DstReg (2<<1) /* Register operand. */
+#define DstMem (3<<1) /* Memory operand. */
+#define DstMask (3<<1)
+/* Source operand type. */
+#define SrcNone (0<<3) /* No source operand. */
+#define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */
+#define SrcReg (1<<3) /* Register operand. */
+#define SrcMem (2<<3) /* Memory operand. */
+#define SrcMem16 (3<<3) /* Memory operand (16-bit). */
+#define SrcMem32 (4<<3) /* Memory operand (32-bit). */
+#define SrcImm (5<<3) /* Immediate operand. */
+#define SrcImmByte (6<<3) /* 8-bit sign-extended immediate operand. */
+#define SrcMask (7<<3)
+/* Generic ModRM decode. */
+#define ModRM (1<<6)
+/* Destination is only written; never read. */
+#define Mov (1<<7)
+#define BitOp (1<<8)
+
+static u8 opcode_table[256] = {
+ /* 0x00 - 0x07 */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x08 - 0x0F */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x10 - 0x17 */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x18 - 0x1F */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x20 - 0x27 */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x28 - 0x2F */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x30 - 0x37 */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x38 - 0x3F */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
+ 0, 0, 0, 0,
+ /* 0x40 - 0x4F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x50 - 0x5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x60 - 0x6F */
+ 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x70 - 0x7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x80 - 0x87 */
+ ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+ ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+ /* 0x88 - 0x8F */
+ ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
+ ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ 0, 0, 0, DstMem | SrcNone | ModRM | Mov,
+ /* 0x90 - 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xA0 - 0xA7 */
+ ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov,
+ ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov,
+ ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
+ ByteOp | ImplicitOps, ImplicitOps,
+ /* 0xA8 - 0xAF */
+ 0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
+ ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
+ ByteOp | ImplicitOps, ImplicitOps,
+ /* 0xB0 - 0xBF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xC0 - 0xC7 */
+ ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0,
+ 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov,
+ DstMem | SrcImm | ModRM | Mov,
+ /* 0xC8 - 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xD0 - 0xD7 */
+ ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
+ ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
+ 0, 0, 0, 0,
+ /* 0xD8 - 0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xE0 - 0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xF0 - 0xF7 */
+ 0, 0, 0, 0,
+ 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
+ /* 0xF8 - 0xFF */
+ 0, 0, 0, 0,
+ 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
+};
+
+static u16 twobyte_table[256] = {
+ /* 0x00 - 0x0F */
+ 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
+ 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+ /* 0x10 - 0x1F */
+ 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x20 - 0x2F */
+ ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x30 - 0x3F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x40 - 0x47 */
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ /* 0x48 - 0x4F */
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+ /* 0x50 - 0x5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x60 - 0x6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x70 - 0x7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x80 - 0x8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x90 - 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xA0 - 0xA7 */
+ 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
+ /* 0xA8 - 0xAF */
+ 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
+ /* 0xB0 - 0xB7 */
+ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,
+ DstMem | SrcReg | ModRM | BitOp,
+ 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem16 | ModRM | Mov,
+ /* 0xB8 - 0xBF */
+ 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp,
+ 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
+ DstReg | SrcMem16 | ModRM | Mov,
+ /* 0xC0 - 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xD0 - 0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xE0 - 0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xF0 - 0xFF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * Tell the emulator that of the Group 7 instructions (sgdt, lidt, etc.) we
+ * are interested only in invlpg and not in any of the rest.
+ *
+ * invlpg is a special instruction in that the data it references may not
+ * be mapped.
+ */
+void kvm_emulator_want_group7_invlpg(void)
+{
+ twobyte_table[1] &= ~SrcMem;
+}
+EXPORT_SYMBOL_GPL(kvm_emulator_want_group7_invlpg);
+
+/* Type, address-of, and value of an instruction's operand. */
+struct operand {
+ enum { OP_REG, OP_MEM, OP_IMM } type;
+ unsigned int bytes;
+ unsigned long val, orig_val, *ptr;
+};
+
+/* EFLAGS bit definitions. */
+#define EFLG_OF (1<<11)
+#define EFLG_DF (1<<10)
+#define EFLG_SF (1<<7)
+#define EFLG_ZF (1<<6)
+#define EFLG_AF (1<<4)
+#define EFLG_PF (1<<2)
+#define EFLG_CF (1<<0)
+
+/*
+ * Instruction emulation:
+ * Most instructions are emulated directly via a fragment of inline assembly
+ * code. This allows us to save/restore EFLAGS and thus very easily pick up
+ * any modified flags.
+ */
+
+#if defined(CONFIG_X86_64)
+#define _LO32 "k" /* force 32-bit operand */
+#define _STK "%%rsp" /* stack pointer */
+#elif defined(__i386__)
+#define _LO32 "" /* force 32-bit operand */
+#define _STK "%%esp" /* stack pointer */
+#endif
+
+/*
+ * These EFLAGS bits are restored from saved value during emulation, and
+ * any changes are written back to the saved value after emulation.
+ */
+#define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF)
+
+/* Before executing instruction: restore necessary bits in EFLAGS. */
+#define _PRE_EFLAGS(_sav, _msk, _tmp) \
+ /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */ \
+ "push %"_sav"; " \
+ "movl %"_msk",%"_LO32 _tmp"; " \
+ "andl %"_LO32 _tmp",("_STK"); " \
+ "pushf; " \
+ "notl %"_LO32 _tmp"; " \
+ "andl %"_LO32 _tmp",("_STK"); " \
+ "pop %"_tmp"; " \
+ "orl %"_LO32 _tmp",("_STK"); " \
+ "popf; " \
+ /* _sav &= ~msk; */ \
+ "movl %"_msk",%"_LO32 _tmp"; " \
+ "notl %"_LO32 _tmp"; " \
+ "andl %"_LO32 _tmp",%"_sav"; "
+
+/* After executing instruction: write-back necessary bits in EFLAGS. */
+#define _POST_EFLAGS(_sav, _msk, _tmp) \
+ /* _sav |= EFLAGS & _msk; */ \
+ "pushf; " \
+ "pop %"_tmp"; " \
+ "andl %"_msk",%"_LO32 _tmp"; " \
+ "orl %"_LO32 _tmp",%"_sav"; "
+
+/* Raw emulation: instruction has two explicit operands. */
+#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
+ do { \
+ unsigned long _tmp; \
+ \
+ switch ((_dst).bytes) { \
+ case 2: \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","4","2") \
+ _op"w %"_wx"3,%1; " \
+ _POST_EFLAGS("0","4","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : _wy ((_src).val), "i" (EFLAGS_MASK) ); \
+ break; \
+ case 4: \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","4","2") \
+ _op"l %"_lx"3,%1; " \
+ _POST_EFLAGS("0","4","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : _ly ((_src).val), "i" (EFLAGS_MASK) ); \
+ break; \
+ case 8: \
+ __emulate_2op_8byte(_op, _src, _dst, \
+ _eflags, _qx, _qy); \
+ break; \
+ } \
+ } while (0)
+
+#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
+ do { \
+ unsigned long _tmp; \
+ switch ( (_dst).bytes ) \
+ { \
+ case 1: \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","4","2") \
+ _op"b %"_bx"3,%1; " \
+ _POST_EFLAGS("0","4","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : _by ((_src).val), "i" (EFLAGS_MASK) ); \
+ break; \
+ default: \
+ __emulate_2op_nobyte(_op, _src, _dst, _eflags, \
+ _wx, _wy, _lx, _ly, _qx, _qy); \
+ break; \
+ } \
+ } while (0)
+
+/* Source operand is byte-sized and may be restricted to just %cl. */
+#define emulate_2op_SrcB(_op, _src, _dst, _eflags) \
+ __emulate_2op(_op, _src, _dst, _eflags, \
+ "b", "c", "b", "c", "b", "c", "b", "c")
+
+/* Source operand is byte, word, long or quad sized. */
+#define emulate_2op_SrcV(_op, _src, _dst, _eflags) \
+ __emulate_2op(_op, _src, _dst, _eflags, \
+ "b", "q", "w", "r", _LO32, "r", "", "r")
+
+/* Source operand is word, long or quad sized. */
+#define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags) \
+ __emulate_2op_nobyte(_op, _src, _dst, _eflags, \
+ "w", "r", _LO32, "r", "", "r")
+
+/* Instruction has only one explicit operand (no source operand). */
+#define emulate_1op(_op, _dst, _eflags) \
+ do { \
+ unsigned long _tmp; \
+ \
+ switch ( (_dst).bytes ) \
+ { \
+ case 1: \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","3","2") \
+ _op"b %1; " \
+ _POST_EFLAGS("0","3","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : "i" (EFLAGS_MASK) ); \
+ break; \
+ case 2: \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","3","2") \
+ _op"w %1; " \
+ _POST_EFLAGS("0","3","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : "i" (EFLAGS_MASK) ); \
+ break; \
+ case 4: \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","3","2") \
+ _op"l %1; " \
+ _POST_EFLAGS("0","3","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : "i" (EFLAGS_MASK) ); \
+ break; \
+ case 8: \
+ __emulate_1op_8byte(_op, _dst, _eflags); \
+ break; \
+ } \
+ } while (0)
+
+/* Emulate an instruction with quadword operands (x86/64 only). */
+#if defined(CONFIG_X86_64)
+#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) \
+ do { \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","4","2") \
+ _op"q %"_qx"3,%1; " \
+ _POST_EFLAGS("0","4","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
+ : _qy ((_src).val), "i" (EFLAGS_MASK) ); \
+ } while (0)
+
+#define __emulate_1op_8byte(_op, _dst, _eflags) \
+ do { \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0","3","2") \
+ _op"q %1; " \
+ _POST_EFLAGS("0","3","2") \
+ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
+ : "i" (EFLAGS_MASK) ); \
+ } while (0)
+
+#elif defined(__i386__)
+#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)
+#define __emulate_1op_8byte(_op, _dst, _eflags)
+#endif /* __i386__ */
+
+/* Fetch next part of the instruction being emulated. */
+#define insn_fetch(_type, _size, _eip) \
+({ unsigned long _x; \
+ rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x, \
+ (_size), ctxt); \
+ if ( rc != 0 ) \
+ goto done; \
+ (_eip) += (_size); \
+ (_type)_x; \
+})
+
+/* Access/update address held in a register, based on addressing mode. */
+#define register_address(base, reg) \
+ ((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) : \
+ ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
+
+#define register_address_increment(reg, inc) \
+ do { \
+ /* signed type ensures sign extension to long */ \
+ int _inc = (inc); \
+ if ( ad_bytes == sizeof(unsigned long) ) \
+ (reg) += _inc; \
+ else \
+ (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \
+ (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \
+ } while (0)
+
+void *decode_register(u8 modrm_reg, unsigned long *regs,
+ int highbyte_regs)
+{
+ void *p;
+
+ p = &regs[modrm_reg];
+ if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8)
+ p = (unsigned char *)&regs[modrm_reg & 3] + 1;
+ return p;
+}
+
+static int read_descriptor(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops,
+ void *ptr,
+ u16 *size, unsigned long *address, int op_bytes)
+{
+ int rc;
+
+ if (op_bytes == 2)
+ op_bytes = 3;
+ *address = 0;
+ rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, ctxt);
+ if (rc)
+ return rc;
+ rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, ctxt);
+ return rc;
+}
+
+int
+x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+{
+ unsigned d;
+ u8 b, sib, twobyte = 0, rex_prefix = 0;
+ u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
+ unsigned long *override_base = NULL;
+ unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
+ int rc = 0;
+ struct operand src, dst;
+ unsigned long cr2 = ctxt->cr2;
+ int mode = ctxt->mode;
+ unsigned long modrm_ea;
+ int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
+
+ /* Shadow copy of register state. Committed on successful emulation. */
+ unsigned long _regs[NR_VCPU_REGS];
+ unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags;
+ unsigned long modrm_val = 0;
+
+ memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);
+
+ switch (mode) {
+ case X86EMUL_MODE_REAL:
+ case X86EMUL_MODE_PROT16:
+ op_bytes = ad_bytes = 2;
+ break;
+ case X86EMUL_MODE_PROT32:
+ op_bytes = ad_bytes = 4;
+ break;
+#ifdef CONFIG_X86_64
+ case X86EMUL_MODE_PROT64:
+ op_bytes = 4;
+ ad_bytes = 8;
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ /* Legacy prefixes. */
+ for (i = 0; i < 8; i++) {
+ switch (b = insn_fetch(u8, 1, _eip)) {
+ case 0x66: /* operand-size override */
+ op_bytes ^= 6; /* switch between 2/4 bytes */
+ break;
+ case 0x67: /* address-size override */
+ if (mode == X86EMUL_MODE_PROT64)
+ ad_bytes ^= 12; /* switch between 4/8 bytes */
+ else
+ ad_bytes ^= 6; /* switch between 2/4 bytes */
+ break;
+ case 0x2e: /* CS override */
+ override_base = &ctxt->cs_base;
+ break;
+ case 0x3e: /* DS override */
+ override_base = &ctxt->ds_base;
+ break;
+ case 0x26: /* ES override */
+ override_base = &ctxt->es_base;
+ break;
+ case 0x64: /* FS override */
+ override_base = &ctxt->fs_base;
+ break;
+ case 0x65: /* GS override */
+ override_base = &ctxt->gs_base;
+ break;
+ case 0x36: /* SS override */
+ override_base = &ctxt->ss_base;
+ break;
+ case 0xf0: /* LOCK */
+ lock_prefix = 1;
+ break;
+ case 0xf3: /* REP/REPE/REPZ */
+ rep_prefix = 1;
+ break;
+ case 0xf2: /* REPNE/REPNZ */
+ break;
+ default:
+ goto done_prefixes;
+ }
+ }
+
+done_prefixes:
+
+ /* REX prefix. */
+ if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) {
+ rex_prefix = b;
+ if (b & 8)
+ op_bytes = 8; /* REX.W */
+ modrm_reg = (b & 4) << 1; /* REX.R */
+ index_reg = (b & 2) << 2; /* REX.X */
+ modrm_rm = base_reg = (b & 1) << 3; /* REG.B */
+ b = insn_fetch(u8, 1, _eip);
+ }
+
+ /* Opcode byte(s). */
+ d = opcode_table[b];
+ if (d == 0) {
+ /* Two-byte opcode? */
+ if (b == 0x0f) {
+ twobyte = 1;
+ b = insn_fetch(u8, 1, _eip);
+ d = twobyte_table[b];
+ }
+
+ /* Unrecognised? */
+ if (d == 0)
+ goto cannot_emulate;
+ }
+
+ /* ModRM and SIB bytes. */
+ if (d & ModRM) {
+ modrm = insn_fetch(u8, 1, _eip);
+ modrm_mod |= (modrm & 0xc0) >> 6;
+ modrm_reg |= (modrm & 0x38) >> 3;
+ modrm_rm |= (modrm & 0x07);
+ modrm_ea = 0;
+ use_modrm_ea = 1;
+
+ if (modrm_mod == 3) {
+ modrm_val = *(unsigned long *)
+ decode_register(modrm_rm, _regs, d & ByteOp);
+ goto modrm_done;
+ }
+
+ if (ad_bytes == 2) {
+ unsigned bx = _regs[VCPU_REGS_RBX];
+ unsigned bp = _regs[VCPU_REGS_RBP];
+ unsigned si = _regs[VCPU_REGS_RSI];
+ unsigned di = _regs[VCPU_REGS_RDI];
+
+ /* 16-bit ModR/M decode. */
+ switch (modrm_mod) {
+ case 0:
+ if (modrm_rm == 6)
+ modrm_ea += insn_fetch(u16, 2, _eip);
+ break;
+ case 1:
+ modrm_ea += insn_fetch(s8, 1, _eip);
+ break;
+ case 2:
+ modrm_ea += insn_fetch(u16, 2, _eip);
+ break;
+ }
+ switch (modrm_rm) {
+ case 0:
+ modrm_ea += bx + si;
+ break;
+ case 1:
+ modrm_ea += bx + di;
+ break;
+ case 2:
+ modrm_ea += bp + si;
+ break;
+ case 3:
+ modrm_ea += bp + di;
+ break;
+ case 4:
+ modrm_ea += si;
+ break;
+ case 5:
+ modrm_ea += di;
+ break;
+ case 6:
+ if (modrm_mod != 0)
+ modrm_ea += bp;
+ break;
+ case 7:
+ modrm_ea += bx;
+ break;
+ }
+ if (modrm_rm == 2 || modrm_rm == 3 ||
+ (modrm_rm == 6 && modrm_mod != 0))
+ if (!override_base)
+ override_base = &ctxt->ss_base;
+ modrm_ea = (u16)modrm_ea;
+ } else {
+ /* 32/64-bit ModR/M decode. */
+ switch (modrm_rm) {
+ case 4:
+ case 12:
+ sib = insn_fetch(u8, 1, _eip);
+ index_reg |= (sib >> 3) & 7;
+ base_reg |= sib & 7;
+ scale = sib >> 6;
+
+ switch (base_reg) {
+ case 5:
+ if (modrm_mod != 0)
+ modrm_ea += _regs[base_reg];
+ else
+ modrm_ea += insn_fetch(s32, 4, _eip);
+ break;
+ default:
+ modrm_ea += _regs[base_reg];
+ }
+ switch (index_reg) {
+ case 4:
+ break;
+ default:
+ modrm_ea += _regs[index_reg] << scale;
+
+ }
+ break;
+ case 5:
+ if (modrm_mod != 0)
+ modrm_ea += _regs[modrm_rm];
+ else if (mode == X86EMUL_MODE_PROT64)
+ rip_relative = 1;
+ break;
+ default:
+ modrm_ea += _regs[modrm_rm];
+ break;
+ }
+ switch (modrm_mod) {
+ case 0:
+ if (modrm_rm == 5)
+ modrm_ea += insn_fetch(s32, 4, _eip);
+ break;
+ case 1:
+ modrm_ea += insn_fetch(s8, 1, _eip);
+ break;
+ case 2:
+ modrm_ea += insn_fetch(s32, 4, _eip);
+ break;
+ }
+ }
+ if (!override_base)
+ override_base = &ctxt->ds_base;
+ if (mode == X86EMUL_MODE_PROT64 &&
+ override_base != &ctxt->fs_base &&
+ override_base != &ctxt->gs_base)
+ override_base = NULL;
+
+ if (override_base)
+ modrm_ea += *override_base;
+
+ if (rip_relative) {
+ modrm_ea += _eip;
+ switch (d & SrcMask) {
+ case SrcImmByte:
+ modrm_ea += 1;
+ break;
+ case SrcImm:
+ if (d & ByteOp)
+ modrm_ea += 1;
+ else
+ if (op_bytes == 8)
+ modrm_ea += 4;
+ else
+ modrm_ea += op_bytes;
+ }
+ }
+ if (ad_bytes != 8)
+ modrm_ea = (u32)modrm_ea;
+ cr2 = modrm_ea;
+ modrm_done:
+ ;
+ }
+
+ /*
+ * Decode and fetch the source operand: register, memory
+ * or immediate.
+ */
+ switch (d & SrcMask) {
+ case SrcNone:
+ break;
+ case SrcReg:
+ src.type = OP_REG;
+ if (d & ByteOp) {
+ src.ptr = decode_register(modrm_reg, _regs,
+ (rex_prefix == 0));
+ src.val = src.orig_val = *(u8 *) src.ptr;
+ src.bytes = 1;
+ } else {
+ src.ptr = decode_register(modrm_reg, _regs, 0);
+ switch ((src.bytes = op_bytes)) {
+ case 2:
+ src.val = src.orig_val = *(u16 *) src.ptr;
+ break;
+ case 4:
+ src.val = src.orig_val = *(u32 *) src.ptr;
+ break;
+ case 8:
+ src.val = src.orig_val = *(u64 *) src.ptr;
+ break;
+ }
+ }
+ break;
+ case SrcMem16:
+ src.bytes = 2;
+ goto srcmem_common;
+ case SrcMem32:
+ src.bytes = 4;
+ goto srcmem_common;
+ case SrcMem:
+ src.bytes = (d & ByteOp) ? 1 : op_bytes;
+ srcmem_common:
+ src.type = OP_MEM;
+ src.ptr = (unsigned long *)cr2;
+ if ((rc = ops->read_emulated((unsigned long)src.ptr,
+ &src.val, src.bytes, ctxt)) != 0)
+ goto done;
+ src.orig_val = src.val;
+ break;
+ case SrcImm:
+ src.type = OP_IMM;
+ src.ptr = (unsigned long *)_eip;
+ src.bytes = (d & ByteOp) ? 1 : op_bytes;
+ if (src.bytes == 8)
+ src.bytes = 4;
+ /* NB. Immediates are sign-extended as necessary. */
+ switch (src.bytes) {
+ case 1:
+ src.val = insn_fetch(s8, 1, _eip);
+ break;
+ case 2:
+ src.val = insn_fetch(s16, 2, _eip);
+ break;
+ case 4:
+ src.val = insn_fetch(s32, 4, _eip);
+ break;
+ }
+ break;
+ case SrcImmByte:
+ src.type = OP_IMM;
+ src.ptr = (unsigned long *)_eip;
+ src.bytes = 1;
+ src.val = insn_fetch(s8, 1, _eip);
+ break;
+ }
+
+ /* Decode and fetch the destination operand: register or memory. */
+ switch (d & DstMask) {
+ case ImplicitOps:
+ /* Special instructions do their own operand decoding. */
+ goto special_insn;
+ case DstReg:
+ dst.type = OP_REG;
+ if ((d & ByteOp)
+ && !(twobyte_table && (b == 0xb6 || b == 0xb7))) {
+ dst.ptr = decode_register(modrm_reg, _regs,
+ (rex_prefix == 0));
+ dst.val = *(u8 *) dst.ptr;
+ dst.bytes = 1;
+ } else {
+ dst.ptr = decode_register(modrm_reg, _regs, 0);
+ switch ((dst.bytes = op_bytes)) {
+ case 2:
+ dst.val = *(u16 *)dst.ptr;
+ break;
+ case 4:
+ dst.val = *(u32 *)dst.ptr;
+ break;
+ case 8:
+ dst.val = *(u64 *)dst.ptr;
+ break;
+ }
+ }
+ break;
+ case DstMem:
+ dst.type = OP_MEM;
+ dst.ptr = (unsigned long *)cr2;
+ dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+ if (d & BitOp) {
+ dst.ptr += src.val / BITS_PER_LONG;
+ dst.bytes = sizeof(long);
+ }
+ if (!(d & Mov) && /* optimisation - avoid slow emulated read */
+ ((rc = ops->read_emulated((unsigned long)dst.ptr,
+ &dst.val, dst.bytes, ctxt)) != 0))
+ goto done;
+ break;
+ }
+ dst.orig_val = dst.val;
+
+ if (twobyte)
+ goto twobyte_insn;
+
+ switch (b) {
+ case 0x00 ... 0x05:
+ add: /* add */
+ emulate_2op_SrcV("add", src, dst, _eflags);
+ break;
+ case 0x08 ... 0x0d:
+ or: /* or */
+ emulate_2op_SrcV("or", src, dst, _eflags);
+ break;
+ case 0x10 ... 0x15:
+ adc: /* adc */
+ emulate_2op_SrcV("adc", src, dst, _eflags);
+ break;
+ case 0x18 ... 0x1d:
+ sbb: /* sbb */
+ emulate_2op_SrcV("sbb", src, dst, _eflags);
+ break;
+ case 0x20 ... 0x25:
+ and: /* and */
+ emulate_2op_SrcV("and", src, dst, _eflags);
+ break;
+ case 0x28 ... 0x2d:
+ sub: /* sub */
+ emulate_2op_SrcV("sub", src, dst, _eflags);
+ break;
+ case 0x30 ... 0x35:
+ xor: /* xor */
+ emulate_2op_SrcV("xor", src, dst, _eflags);
+ break;
+ case 0x38 ... 0x3d:
+ cmp: /* cmp */
+ emulate_2op_SrcV("cmp", src, dst, _eflags);
+ break;
+ case 0x63: /* movsxd */
+ if (mode != X86EMUL_MODE_PROT64)
+ goto cannot_emulate;
+ dst.val = (s32) src.val;
+ break;
+ case 0x80 ... 0x83: /* Grp1 */
+ switch (modrm_reg) {
+ case 0:
+ goto add;
+ case 1:
+ goto or;
+ case 2:
+ goto adc;
+ case 3:
+ goto sbb;
+ case 4:
+ goto and;
+ case 5:
+ goto sub;
+ case 6:
+ goto xor;
+ case 7:
+ goto cmp;
+ }
+ break;
+ case 0x84 ... 0x85:
+ test: /* test */
+ emulate_2op_SrcV("test", src, dst, _eflags);
+ break;
+ case 0x86 ... 0x87: /* xchg */
+ /* Write back the register source. */
+ switch (dst.bytes) {
+ case 1:
+ *(u8 *) src.ptr = (u8) dst.val;
+ break;
+ case 2:
+ *(u16 *) src.ptr = (u16) dst.val;
+ break;
+ case 4:
+ *src.ptr = (u32) dst.val;
+ break; /* 64b reg: zero-extend */
+ case 8:
+ *src.ptr = dst.val;
+ break;
+ }
+ /*
+ * Write back the memory destination with implicit LOCK
+ * prefix.
+ */
+ dst.val = src.val;
+ lock_prefix = 1;
+ break;
+ case 0xa0 ... 0xa1: /* mov */
+ dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+ dst.val = src.val;
+ _eip += ad_bytes; /* skip src displacement */
+ break;
+ case 0xa2 ... 0xa3: /* mov */
+ dst.val = (unsigned long)_regs[VCPU_REGS_RAX];
+ _eip += ad_bytes; /* skip dst displacement */
+ break;
+ case 0x88 ... 0x8b: /* mov */
+ case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
+ dst.val = src.val;
+ break;
+ case 0x8f: /* pop (sole member of Grp1a) */
+ /* 64-bit mode: POP always pops a 64-bit operand. */
+ if (mode == X86EMUL_MODE_PROT64)
+ dst.bytes = 8;
+ if ((rc = ops->read_std(register_address(ctxt->ss_base,
+ _regs[VCPU_REGS_RSP]),
+ &dst.val, dst.bytes, ctxt)) != 0)
+ goto done;
+ register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
+ break;
+ case 0xc0 ... 0xc1:
+ grp2: /* Grp2 */
+ switch (modrm_reg) {
+ case 0: /* rol */
+ emulate_2op_SrcB("rol", src, dst, _eflags);
+ break;
+ case 1: /* ror */
+ emulate_2op_SrcB("ror", src, dst, _eflags);
+ break;
+ case 2: /* rcl */
+ emulate_2op_SrcB("rcl", src, dst, _eflags);
+ break;
+ case 3: /* rcr */
+ emulate_2op_SrcB("rcr", src, dst, _eflags);
+ break;
+ case 4: /* sal/shl */
+ case 6: /* sal/shl */
+ emulate_2op_SrcB("sal", src, dst, _eflags);
+ break;
+ case 5: /* shr */
+ emulate_2op_SrcB("shr", src, dst, _eflags);
+ break;
+ case 7: /* sar */
+ emulate_2op_SrcB("sar", src, dst, _eflags);
+ break;
+ }
+ break;
+ case 0xd0 ... 0xd1: /* Grp2 */
+ src.val = 1;
+ goto grp2;
+ case 0xd2 ... 0xd3: /* Grp2 */
+ src.val = _regs[VCPU_REGS_RCX];
+ goto grp2;
+ case 0xf6 ... 0xf7: /* Grp3 */
+ switch (modrm_reg) {
+ case 0 ... 1: /* test */
+ /*
+ * Special case in Grp3: test has an immediate
+ * source operand.
+ */
+ src.type = OP_IMM;
+ src.ptr = (unsigned long *)_eip;
+ src.bytes = (d & ByteOp) ? 1 : op_bytes;
+ if (src.bytes == 8)
+ src.bytes = 4;
+ switch (src.bytes) {
+ case 1:
+ src.val = insn_fetch(s8, 1, _eip);
+ break;
+ case 2:
+ src.val = insn_fetch(s16, 2, _eip);
+ break;
+ case 4:
+ src.val = insn_fetch(s32, 4, _eip);
+ break;
+ }
+ goto test;
+ case 2: /* not */
+ dst.val = ~dst.val;
+ break;
+ case 3: /* neg */
+ emulate_1op("neg", dst, _eflags);
+ break;
+ default:
+ goto cannot_emulate;
+ }
+ break;
+ case 0xfe ... 0xff: /* Grp4/Grp5 */
+ switch (modrm_reg) {
+ case 0: /* inc */
+ emulate_1op("inc", dst, _eflags);
+ break;
+ case 1: /* dec */
+ emulate_1op("dec", dst, _eflags);
+ break;
+ case 6: /* push */
+ /* 64-bit mode: PUSH always pushes a 64-bit operand. */
+ if (mode == X86EMUL_MODE_PROT64) {
+ dst.bytes = 8;
+ if ((rc = ops->read_std((unsigned long)dst.ptr,
+ &dst.val, 8,
+ ctxt)) != 0)
+ goto done;
+ }
+ register_address_increment(_regs[VCPU_REGS_RSP],
+ -dst.bytes);
+ if ((rc = ops->write_std(
+ register_address(ctxt->ss_base,
+ _regs[VCPU_REGS_RSP]),
+ dst.val, dst.bytes, ctxt)) != 0)
+ goto done;
+ dst.val = dst.orig_val; /* skanky: disable writeback */
+ break;
+ default:
+ goto cannot_emulate;
+ }
+ break;
+ }
+
+writeback:
+ if ((d & Mov) || (dst.orig_val != dst.val)) {
+ switch (dst.type) {
+ case OP_REG:
+ /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
+ switch (dst.bytes) {
+ case 1:
+ *(u8 *)dst.ptr = (u8)dst.val;
+ break;
+ case 2:
+ *(u16 *)dst.ptr = (u16)dst.val;
+ break;
+ case 4:
+ *dst.ptr = (u32)dst.val;
+ break; /* 64b: zero-ext */
+ case 8:
+ *dst.ptr = dst.val;
+ break;
+ }
+ break;
+ case OP_MEM:
+ if (lock_prefix)
+ rc = ops->cmpxchg_emulated((unsigned long)dst.
+ ptr, dst.orig_val,
+ dst.val, dst.bytes,
+ ctxt);
+ else
+ rc = ops->write_emulated((unsigned long)dst.ptr,
+ dst.val, dst.bytes,
+ ctxt);
+ if (rc != 0)
+ goto done;
+ default:
+ break;
+ }
+ }
+
+ /* Commit shadow register state. */
+ memcpy(ctxt->vcpu->regs, _regs, sizeof _regs);
+ ctxt->eflags = _eflags;
+ ctxt->vcpu->rip = _eip;
+
+done:
+ return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
+
+special_insn:
+ if (twobyte)
+ goto twobyte_special_insn;
+ if (rep_prefix) {
+ if (_regs[VCPU_REGS_RCX] == 0) {
+ ctxt->vcpu->rip = _eip;
+ goto done;
+ }
+ _regs[VCPU_REGS_RCX]--;
+ _eip = ctxt->vcpu->rip;
+ }
+ switch (b) {
+ case 0xa4 ... 0xa5: /* movs */
+ dst.type = OP_MEM;
+ dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+ dst.ptr = (unsigned long *)register_address(ctxt->es_base,
+ _regs[VCPU_REGS_RDI]);
+ if ((rc = ops->read_emulated(register_address(
+ override_base ? *override_base : ctxt->ds_base,
+ _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt)) != 0)
+ goto done;
+ register_address_increment(_regs[VCPU_REGS_RSI],
+ (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+ register_address_increment(_regs[VCPU_REGS_RDI],
+ (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+ break;
+ case 0xa6 ... 0xa7: /* cmps */
+ DPRINTF("Urk! I don't handle CMPS.\n");
+ goto cannot_emulate;
+ case 0xaa ... 0xab: /* stos */
+ dst.type = OP_MEM;
+ dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+ dst.ptr = (unsigned long *)cr2;
+ dst.val = _regs[VCPU_REGS_RAX];
+ register_address_increment(_regs[VCPU_REGS_RDI],
+ (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+ break;
+ case 0xac ... 0xad: /* lods */
+ dst.type = OP_REG;
+ dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+ dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+ if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0)
+ goto done;
+ register_address_increment(_regs[VCPU_REGS_RSI],
+ (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
+ break;
+ case 0xae ... 0xaf: /* scas */
+ DPRINTF("Urk! I don't handle SCAS.\n");
+ goto cannot_emulate;
+ }
+ goto writeback;
+
+twobyte_insn:
+ switch (b) {
+ case 0x01: /* lgdt, lidt, lmsw */
+ switch (modrm_reg) {
+ u16 size;
+ unsigned long address;
+
+ case 2: /* lgdt */
+ rc = read_descriptor(ctxt, ops, src.ptr,
+ &size, &address, op_bytes);
+ if (rc)
+ goto done;
+ realmode_lgdt(ctxt->vcpu, size, address);
+ break;
+ case 3: /* lidt */
+ rc = read_descriptor(ctxt, ops, src.ptr,
+ &size, &address, op_bytes);
+ if (rc)
+ goto done;
+ realmode_lidt(ctxt->vcpu, size, address);
+ break;
+ case 4: /* smsw */
+ if (modrm_mod != 3)
+ goto cannot_emulate;
+ *(u16 *)&_regs[modrm_rm]
+ = realmode_get_cr(ctxt->vcpu, 0);
+ break;
+ case 6: /* lmsw */
+ if (modrm_mod != 3)
+ goto cannot_emulate;
+ realmode_lmsw(ctxt->vcpu, (u16)modrm_val, &_eflags);
+ break;
+ case 7: /* invlpg*/
+ emulate_invlpg(ctxt->vcpu, cr2);
+ break;
+ default:
+ goto cannot_emulate;
+ }
+ break;
+ case 0x21: /* mov from dr to reg */
+ if (modrm_mod != 3)
+ goto cannot_emulate;
+ rc = emulator_get_dr(ctxt, modrm_reg, &_regs[modrm_rm]);
+ break;
+ case 0x23: /* mov from reg to dr */
+ if (modrm_mod != 3)
+ goto cannot_emulate;
+ rc = emulator_set_dr(ctxt, modrm_reg, _regs[modrm_rm]);
+ break;
+ case 0x40 ... 0x4f: /* cmov */
+ dst.val = dst.orig_val = src.val;
+ d &= ~Mov; /* default to no move */
+ /*
+ * First, assume we're decoding an even cmov opcode
+ * (lsb == 0).
+ */
+ switch ((b & 15) >> 1) {
+ case 0: /* cmovo */
+ d |= (_eflags & EFLG_OF) ? Mov : 0;
+ break;
+ case 1: /* cmovb/cmovc/cmovnae */
+ d |= (_eflags & EFLG_CF) ? Mov : 0;
+ break;
+ case 2: /* cmovz/cmove */
+ d |= (_eflags & EFLG_ZF) ? Mov : 0;
+ break;
+ case 3: /* cmovbe/cmovna */
+ d |= (_eflags & (EFLG_CF | EFLG_ZF)) ? Mov : 0;
+ break;
+ case 4: /* cmovs */
+ d |= (_eflags & EFLG_SF) ? Mov : 0;
+ break;
+ case 5: /* cmovp/cmovpe */
+ d |= (_eflags & EFLG_PF) ? Mov : 0;
+ break;
+ case 7: /* cmovle/cmovng */
+ d |= (_eflags & EFLG_ZF) ? Mov : 0;
+ /* fall through */
+ case 6: /* cmovl/cmovnge */
+ d |= (!(_eflags & EFLG_SF) !=
+ !(_eflags & EFLG_OF)) ? Mov : 0;
+ break;
+ }
+ /* Odd cmov opcodes (lsb == 1) have inverted sense. */
+ d ^= (b & 1) ? Mov : 0;
+ break;
+ case 0xb0 ... 0xb1: /* cmpxchg */
+ /*
+ * Save real source value, then compare EAX against
+ * destination.
+ */
+ src.orig_val = src.val;
+ src.val = _regs[VCPU_REGS_RAX];
+ emulate_2op_SrcV("cmp", src, dst, _eflags);
+ /* Always write back. The question is: where to? */
+ d |= Mov;
+ if (_eflags & EFLG_ZF) {
+ /* Success: write back to memory. */
+ dst.val = src.orig_val;
+ } else {
+ /* Failure: write the value we saw to EAX. */
+ dst.type = OP_REG;
+ dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
+ }
+ break;
+ case 0xa3:
+ bt: /* bt */
+ src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+ emulate_2op_SrcV_nobyte("bt", src, dst, _eflags);
+ break;
+ case 0xb3:
+ btr: /* btr */
+ src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+ emulate_2op_SrcV_nobyte("btr", src, dst, _eflags);
+ break;
+ case 0xab:
+ bts: /* bts */
+ src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+ emulate_2op_SrcV_nobyte("bts", src, dst, _eflags);
+ break;
+ case 0xb6 ... 0xb7: /* movzx */
+ dst.bytes = op_bytes;
+ dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val;
+ break;
+ case 0xbb:
+ btc: /* btc */
+ src.val &= (dst.bytes << 3) - 1; /* only subword offset */
+ emulate_2op_SrcV_nobyte("btc", src, dst, _eflags);
+ break;
+ case 0xba: /* Grp8 */
+ switch (modrm_reg & 3) {
+ case 0:
+ goto bt;
+ case 1:
+ goto bts;
+ case 2:
+ goto btr;
+ case 3:
+ goto btc;
+ }
+ break;
+ case 0xbe ... 0xbf: /* movsx */
+ dst.bytes = op_bytes;
+ dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
+ break;
+ }
+ goto writeback;
+
+twobyte_special_insn:
+ /* Disable writeback. */
+ dst.orig_val = dst.val;
+ switch (b) {
+ case 0x0d: /* GrpP (prefetch) */
+ case 0x18: /* Grp16 (prefetch/nop) */
+ break;
+ case 0x06:
+ emulate_clts(ctxt->vcpu);
+ break;
+ case 0x20: /* mov cr, reg */
+ if (modrm_mod != 3)
+ goto cannot_emulate;
+ _regs[modrm_rm] = realmode_get_cr(ctxt->vcpu, modrm_reg);
+ break;
+ case 0x22: /* mov reg, cr */
+ if (modrm_mod != 3)
+ goto cannot_emulate;
+ realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
+ break;
+ case 0xc7: /* Grp9 (cmpxchg8b) */
+#if defined(__i386__)
+ {
+ unsigned long old_lo, old_hi;
+ if (((rc = ops->read_emulated(cr2 + 0, &old_lo, 4,
+ ctxt)) != 0)
+ || ((rc = ops->read_emulated(cr2 + 4, &old_hi, 4,
+ ctxt)) != 0))
+ goto done;
+ if ((old_lo != _regs[VCPU_REGS_RAX])
+ || (old_hi != _regs[VCPU_REGS_RDX])) {
+ _regs[VCPU_REGS_RAX] = old_lo;
+ _regs[VCPU_REGS_RDX] = old_hi;
+ _eflags &= ~EFLG_ZF;
+ } else if (ops->cmpxchg8b_emulated == NULL) {
+ rc = X86EMUL_UNHANDLEABLE;
+ goto done;
+ } else {
+ if ((rc = ops->cmpxchg8b_emulated(cr2, old_lo,
+ old_hi,
+ _regs[VCPU_REGS_RBX],
+ _regs[VCPU_REGS_RCX],
+ ctxt)) != 0)
+ goto done;
+ _eflags |= EFLG_ZF;
+ }
+ break;
+ }
+#elif defined(CONFIG_X86_64)
+ {
+ unsigned long old, new;
+ if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0)
+ goto done;
+ if (((u32) (old >> 0) != (u32) _regs[VCPU_REGS_RAX]) ||
+ ((u32) (old >> 32) != (u32) _regs[VCPU_REGS_RDX])) {
+ _regs[VCPU_REGS_RAX] = (u32) (old >> 0);
+ _regs[VCPU_REGS_RDX] = (u32) (old >> 32);
+ _eflags &= ~EFLG_ZF;
+ } else {
+ new = (_regs[VCPU_REGS_RCX] << 32) | (u32) _regs[VCPU_REGS_RBX];
+ if ((rc = ops->cmpxchg_emulated(cr2, old,
+ new, 8, ctxt)) != 0)
+ goto done;
+ _eflags |= EFLG_ZF;
+ }
+ break;
+ }
+#endif
+ }
+ goto writeback;
+
+cannot_emulate:
+ DPRINTF("Cannot emulate %02x\n", b);
+ return -1;
+}
+
+#ifdef __XEN__
+
+#include <asm/mm.h>
+#include <asm/uaccess.h>
+
+int
+x86_emulate_read_std(unsigned long addr,
+ unsigned long *val,
+ unsigned int bytes, struct x86_emulate_ctxt *ctxt)
+{
+ unsigned int rc;
+
+ *val = 0;
+
+ if ((rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0) {
+ propagate_page_fault(addr + bytes - rc, 0); /* read fault */
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ return X86EMUL_CONTINUE;
+}
+
+int
+x86_emulate_write_std(unsigned long addr,
+ unsigned long val,
+ unsigned int bytes, struct x86_emulate_ctxt *ctxt)
+{
+ unsigned int rc;
+
+ if ((rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0) {
+ propagate_page_fault(addr + bytes - rc, PGERR_write_access);
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+
+ return X86EMUL_CONTINUE;
+}
+
+#endif
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h
new file mode 100644
index 00000000000..5d41bd55125
--- /dev/null
+++ b/drivers/kvm/x86_emulate.h
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * x86_emulate.h
+ *
+ * Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
+ *
+ * Copyright (c) 2005 Keir Fraser
+ *
+ * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4
+ */
+
+#ifndef __X86_EMULATE_H__
+#define __X86_EMULATE_H__
+
+struct x86_emulate_ctxt;
+
+/*
+ * x86_emulate_ops:
+ *
+ * These operations represent the instruction emulator's interface to memory.
+ * There are two categories of operation: those that act on ordinary memory
+ * regions (*_std), and those that act on memory regions known to require
+ * special treatment or emulation (*_emulated).
+ *
+ * The emulator assumes that an instruction accesses only one 'emulated memory'
+ * location, that this location is the given linear faulting address (cr2), and
+ * that this is one of the instruction's data operands. Instruction fetches and
+ * stack operations are assumed never to access emulated memory. The emulator
+ * automatically deduces which operand of a string-move operation is accessing
+ * emulated memory, and assumes that the other operand accesses normal memory.
+ *
+ * NOTES:
+ * 1. The emulator isn't very smart about emulated vs. standard memory.
+ * 'Emulated memory' access addresses should be checked for sanity.
+ * 'Normal memory' accesses may fault, and the caller must arrange to
+ * detect and handle reentrancy into the emulator via recursive faults.
+ * Accesses may be unaligned and may cross page boundaries.
+ * 2. If the access fails (cannot emulate, or a standard access faults) then
+ * it is up to the memop to propagate the fault to the guest VM via
+ * some out-of-band mechanism, unknown to the emulator. The memop signals
+ * failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will
+ * then immediately bail.
+ * 3. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
+ * cmpxchg8b_emulated need support 8-byte accesses.
+ * 4. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
+ */
+/* Access completed successfully: continue emulation as normal. */
+#define X86EMUL_CONTINUE 0
+/* Access is unhandleable: bail from emulation and return error to caller. */
+#define X86EMUL_UNHANDLEABLE 1
+/* Terminate emulation but return success to the caller. */
+#define X86EMUL_PROPAGATE_FAULT 2 /* propagate a generated fault to guest */
+#define X86EMUL_RETRY_INSTR 2 /* retry the instruction for some reason */
+#define X86EMUL_CMPXCHG_FAILED 2 /* cmpxchg did not see expected value */
+struct x86_emulate_ops {
+ /*
+ * read_std: Read bytes of standard (non-emulated/special) memory.
+ * Used for instruction fetch, stack operations, and others.
+ * @addr: [IN ] Linear address from which to read.
+ * @val: [OUT] Value read from memory, zero-extended to 'u_long'.
+ * @bytes: [IN ] Number of bytes to read from memory.
+ */
+ int (*read_std)(unsigned long addr,
+ unsigned long *val,
+ unsigned int bytes, struct x86_emulate_ctxt * ctxt);
+
+ /*
+ * write_std: Write bytes of standard (non-emulated/special) memory.
+ * Used for stack operations, and others.
+ * @addr: [IN ] Linear address to which to write.
+ * @val: [IN ] Value to write to memory (low-order bytes used as
+ * required).
+ * @bytes: [IN ] Number of bytes to write to memory.
+ */
+ int (*write_std)(unsigned long addr,
+ unsigned long val,
+ unsigned int bytes, struct x86_emulate_ctxt * ctxt);
+
+ /*
+ * read_emulated: Read bytes from emulated/special memory area.
+ * @addr: [IN ] Linear address from which to read.
+ * @val: [OUT] Value read from memory, zero-extended to 'u_long'.
+ * @bytes: [IN ] Number of bytes to read from memory.
+ */
+ int (*read_emulated) (unsigned long addr,
+ unsigned long *val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt * ctxt);
+
+ /*
+ * write_emulated: Read bytes from emulated/special memory area.
+ * @addr: [IN ] Linear address to which to write.
+ * @val: [IN ] Value to write to memory (low-order bytes used as
+ * required).
+ * @bytes: [IN ] Number of bytes to write to memory.
+ */
+ int (*write_emulated) (unsigned long addr,
+ unsigned long val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt * ctxt);
+
+ /*
+ * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an
+ * emulated/special memory area.
+ * @addr: [IN ] Linear address to access.
+ * @old: [IN ] Value expected to be current at @addr.
+ * @new: [IN ] Value to write to @addr.
+ * @bytes: [IN ] Number of bytes to access using CMPXCHG.
+ */
+ int (*cmpxchg_emulated) (unsigned long addr,
+ unsigned long old,
+ unsigned long new,
+ unsigned int bytes,
+ struct x86_emulate_ctxt * ctxt);
+
+ /*
+ * cmpxchg8b_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an
+ * emulated/special memory area.
+ * @addr: [IN ] Linear address to access.
+ * @old: [IN ] Value expected to be current at @addr.
+ * @new: [IN ] Value to write to @addr.
+ * NOTES:
+ * 1. This function is only ever called when emulating a real CMPXCHG8B.
+ * 2. This function is *never* called on x86/64 systems.
+ * 2. Not defining this function (i.e., specifying NULL) is equivalent
+ * to defining a function that always returns X86EMUL_UNHANDLEABLE.
+ */
+ int (*cmpxchg8b_emulated) (unsigned long addr,
+ unsigned long old_lo,
+ unsigned long old_hi,
+ unsigned long new_lo,
+ unsigned long new_hi,
+ struct x86_emulate_ctxt * ctxt);
+};
+
+struct cpu_user_regs;
+
+struct x86_emulate_ctxt {
+ /* Register state before/after emulation. */
+ struct kvm_vcpu *vcpu;
+
+ /* Linear faulting address (if emulating a page-faulting instruction). */
+ unsigned long eflags;
+ unsigned long cr2;
+
+ /* Emulated execution mode, represented by an X86EMUL_MODE value. */
+ int mode;
+
+ unsigned long cs_base;
+ unsigned long ds_base;
+ unsigned long es_base;
+ unsigned long ss_base;
+ unsigned long gs_base;
+ unsigned long fs_base;
+};
+
+/* Execution mode, passed to the emulator. */
+#define X86EMUL_MODE_REAL 0 /* Real mode. */
+#define X86EMUL_MODE_PROT16 2 /* 16-bit protected mode. */
+#define X86EMUL_MODE_PROT32 4 /* 32-bit protected mode. */
+#define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */
+
+/* Host execution mode. */
+#if defined(__i386__)
+#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
+#elif defined(CONFIG_X86_64)
+#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
+#endif
+
+/*
+ * x86_emulate_memop: Emulate an instruction that faulted attempting to
+ * read/write a 'special' memory area.
+ * Returns -1 on failure, 0 on success.
+ */
+int x86_emulate_memop(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops);
+
+/*
+ * Given the 'reg' portion of a ModRM byte, and a register block, return a
+ * pointer into the block that addresses the relevant register.
+ * @highbyte_regs specifies whether to decode AH,CH,DH,BH.
+ */
+void *decode_register(u8 modrm_reg, unsigned long *regs,
+ int highbyte_regs);
+
+#endif /* __X86_EMULATE_H__ */
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 176142c6149..7399ba79111 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -12,7 +12,7 @@ config NEW_LEDS
config LEDS_CLASS
tristate "LED Class Support"
- depends NEW_LEDS
+ depends on NEW_LEDS
help
This option enables the led sysfs class in /sys/class/leds. You'll
need this to do anything useful with LEDs. If unsure, say N.
@@ -21,28 +21,28 @@ comment "LED drivers"
config LEDS_CORGI
tristate "LED Support for the Sharp SL-C7x0 series"
- depends LEDS_CLASS && PXA_SHARP_C7xx
+ depends on LEDS_CLASS && PXA_SHARP_C7xx
help
This option enables support for the LEDs on Sharp Zaurus
SL-C7x0 series (C700, C750, C760, C860).
config LEDS_LOCOMO
tristate "LED Support for Locomo device"
- depends LEDS_CLASS && SHARP_LOCOMO
+ depends on LEDS_CLASS && SHARP_LOCOMO
help
This option enables support for the LEDs on Sharp Locomo.
Zaurus models SL-5500 and SL-5600.
config LEDS_SPITZ
tristate "LED Support for the Sharp SL-Cxx00 series"
- depends LEDS_CLASS && PXA_SHARP_Cxx00
+ depends on LEDS_CLASS && PXA_SHARP_Cxx00
help
This option enables support for the LEDs on Sharp Zaurus
SL-Cxx00 series (C1000, C3000, C3100).
config LEDS_IXP4XX
tristate "LED Support for GPIO connected LEDs on IXP4XX processors"
- depends LEDS_CLASS && ARCH_IXP4XX
+ depends on LEDS_CLASS && ARCH_IXP4XX
help
This option enables support for the LEDs connected to GPIO
outputs of the Intel IXP4XX processors. To be useful the
@@ -51,7 +51,7 @@ config LEDS_IXP4XX
config LEDS_TOSA
tristate "LED Support for the Sharp SL-6000 series"
- depends LEDS_CLASS && PXA_SHARPSL
+ depends on LEDS_CLASS && PXA_SHARPSL
help
This option enables support for the LEDs on Sharp Zaurus
SL-6000 series.
@@ -65,7 +65,7 @@ config LEDS_S3C24XX
config LEDS_AMS_DELTA
tristate "LED Support for the Amstrad Delta (E3)"
- depends LEDS_CLASS && MACH_AMS_DELTA
+ depends on LEDS_CLASS && MACH_AMS_DELTA
help
This option enables support for the LEDs on Amstrad Delta (E3).
@@ -86,7 +86,7 @@ comment "LED Triggers"
config LEDS_TRIGGERS
bool "LED Trigger support"
- depends NEW_LEDS
+ depends on NEW_LEDS
help
This option enables trigger support for the leds class.
These triggers allow kernel events to drive the LEDs and can
@@ -94,21 +94,21 @@ config LEDS_TRIGGERS
config LEDS_TRIGGER_TIMER
tristate "LED Timer Trigger"
- depends LEDS_TRIGGERS
+ depends on LEDS_TRIGGERS
help
This allows LEDs to be controlled by a programmable timer
via sysfs. If unsure, say Y.
config LEDS_TRIGGER_IDE_DISK
bool "LED IDE Disk Trigger"
- depends LEDS_TRIGGERS && BLK_DEV_IDEDISK
+ depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK
help
This allows LEDs to be controlled by IDE disk activity.
If unsure, say Y.
config LEDS_TRIGGER_HEARTBEAT
tristate "LED Heartbeat Trigger"
- depends LEDS_TRIGGERS
+ depends on LEDS_TRIGGERS
help
This allows LEDs to be controlled by a CPU load average.
The flash frequency is a hyperbolic function of the 1-minute
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index fb1edc1c9ed..50914439d86 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/leds.h>
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/leds-gpio.h>
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 92ccee85e2a..a9e747c3979 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -162,7 +162,6 @@ config INPUT_ADBHID
config MAC_EMUMOUSEBTN
bool "Support for mouse button 2+3 emulation"
- depends on INPUT_ADBHID
help
This provides generic support for emulating the 2nd and 3rd mouse
button with keypresses. If you say Y here, the emulation is still
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index d43ea81d6df..7cec6de5e2b 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -828,7 +828,7 @@ static ssize_t adb_write(struct file *file, const char __user *buf,
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
- req = (struct adb_request *) kmalloc(sizeof(struct adb_request),
+ req = kmalloc(sizeof(struct adb_request),
GFP_KERNEL);
if (req == NULL)
return -ENOMEM;
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 5066e7a8ea9..1c7d6f221b5 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -689,7 +689,6 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
if (!hid || !input_dev) {
err = -ENOMEM;
goto fail;
-
}
sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
@@ -807,7 +806,9 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
input_dev->keycode = hid->keycode;
- input_register_device(input_dev);
+ err = input_register_device(input_dev);
+ if (err)
+ goto fail;
if (default_id == ADB_KEYBOARD) {
/* HACK WARNING!! This should go away as soon there is an utility
@@ -820,7 +821,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
return 0;
fail: input_free_device(input_dev);
- kfree(hid);
+ if (hid) {
+ kfree(hid->keycode);
+ kfree(hid);
+ }
adbhid[id] = NULL;
return err;
}
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
index 8862a83b8d8..4300c628f8a 100644
--- a/drivers/macintosh/apm_emu.c
+++ b/drivers/macintosh/apm_emu.c
@@ -321,7 +321,7 @@ static int do_open(struct inode * inode, struct file * filp)
{
struct apm_user * as;
- as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
sizeof(*as));
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 6b129eef798..ee6b4ca6913 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -106,6 +106,8 @@ EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
static int emumousebtn_input_register(void)
{
+ int ret;
+
emumousebtn = input_allocate_device();
if (!emumousebtn)
return -ENOMEM;
@@ -120,9 +122,11 @@ static int emumousebtn_input_register(void)
emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
- input_register_device(emumousebtn);
+ ret = input_register_device(emumousebtn);
+ if (ret)
+ input_free_device(emumousebtn);
- return 0;
+ return ret;
}
int __init mac_hid_init(void)
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 6dde27ab79a..6f30459b938 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -945,7 +945,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id)
*/
tlen = sizeof(struct property) + len + 18;
- prop = kcalloc(tlen, 1, GFP_KERNEL);
+ prop = kzalloc(tlen, GFP_KERNEL);
if (prop == NULL)
return NULL;
hdr = (struct smu_sdbp_header *)(prop + 1);
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index 6c29fe727c0..801a974342f 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -147,7 +147,7 @@ void __init pmu_backlight_init()
snprintf(name, sizeof(name), "pmubl");
- bd = backlight_device_register(name, NULL, &pmu_backlight_data);
+ bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data);
if (IS_ERR(bd)) {
printk("pmubl: Backlight registration failed\n");
goto error;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index c8558d4ed50..8ca75e52f63 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -44,6 +44,7 @@
#include <linux/sysdev.h>
#include <linux/freezer.h>
#include <linux/syscalls.h>
+#include <linux/suspend.h>
#include <linux/cpu.h>
#include <asm/prom.h>
#include <asm/machdep.h>
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index d9986f3a3fb..93e6ef9233f 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -847,7 +847,7 @@ pbook_pci_save(void)
n_pbook_pci_saves = npci;
if (npci == 0)
return;
- ps = (struct pci_save *) kmalloc(npci * sizeof(*ps), GFP_KERNEL);
+ ps = kmalloc(npci * sizeof(*ps), GFP_KERNEL);
pbook_pci_saves = ps;
if (ps == NULL)
return;
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index c92c1521546..4540ade6b6b 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -215,6 +215,7 @@ config DM_CRYPT
tristate "Crypt target support"
depends on BLK_DEV_DM && EXPERIMENTAL
select CRYPTO
+ select CRYPTO_CBC
---help---
This device-mapper target allows you to create a device that
transparently encrypts the data on it. You'll need to activate
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index d6f614738bb..11108165e26 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -212,8 +212,8 @@ char *file_path(struct file *file, char *buf, int count)
if (!buf)
return NULL;
- d = file->f_dentry;
- v = file->f_vfsmnt;
+ d = file->f_path.dentry;
+ v = file->f_path.mnt;
buf = d_path(d, v, buf, count);
@@ -349,7 +349,7 @@ static struct page *read_page(struct file *file, unsigned long index,
unsigned long count)
{
struct page *page = NULL;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct buffer_head *bh;
sector_t block;
@@ -479,9 +479,12 @@ static int bitmap_read_sb(struct bitmap *bitmap)
int err = -EINVAL;
/* page 0 is the superblock, read it... */
- if (bitmap->file)
- bitmap->sb_page = read_page(bitmap->file, 0, bitmap, PAGE_SIZE);
- else {
+ if (bitmap->file) {
+ loff_t isize = i_size_read(bitmap->file->f_mapping->host);
+ int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize;
+
+ bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes);
+ } else {
bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
}
if (IS_ERR(bitmap->sb_page)) {
@@ -662,7 +665,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
bitmap_file_unmap(bitmap);
if (file) {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
invalidate_inode_pages(inode->i_mapping);
fput(file);
}
@@ -877,7 +880,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
int count;
/* unmap the old page, we're done with it */
if (index == num_pages-1)
- count = bytes - index * PAGE_SIZE;
+ count = bytes + sizeof(bitmap_super_t)
+ - index * PAGE_SIZE;
else
count = PAGE_SIZE;
if (index == 0) {
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h
index bbf4615f0e3..da4349649f7 100644
--- a/drivers/md/dm-bio-list.h
+++ b/drivers/md/dm-bio-list.h
@@ -44,6 +44,20 @@ static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2)
bl->tail = bl2->tail;
}
+static inline void bio_list_merge_head(struct bio_list *bl,
+ struct bio_list *bl2)
+{
+ if (!bl2->head)
+ return;
+
+ if (bl->head)
+ bl2->tail->bi_next = bl->head;
+ else
+ bl->tail = bl2->tail;
+
+ bl->head = bl2->head;
+}
+
static inline struct bio *bio_list_pop(struct bio_list *bl)
{
struct bio *bio = bl->head;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a1086ee8ccc..4c2471ee054 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -220,7 +220,7 @@ static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
const char *opts)
{
unsigned int bs = crypto_blkcipher_blocksize(cc->tfm);
- int log = long_log2(bs);
+ int log = ilog2(bs);
/* we need to calculate how far we must shift the sector count
* to get the cipher block count, we use this shift in _gen */
@@ -962,7 +962,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
atomic_set(&io->pending, 0);
kcryptd_queue_io(io);
- return 0;
+ return DM_MAPIO_SUBMITTED;
}
static int crypt_status(struct dm_target *ti, status_type_t type,
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
index 2b2d45d7baa..265c467854d 100644
--- a/drivers/md/dm-emc.c
+++ b/drivers/md/dm-emc.c
@@ -40,7 +40,7 @@ static inline void free_bio(struct bio *bio)
static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
{
- struct path *path = bio->bi_private;
+ struct dm_path *path = bio->bi_private;
if (bio->bi_size)
return 1;
@@ -61,7 +61,7 @@ static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
return 0;
}
-static struct bio *get_failover_bio(struct path *path, unsigned data_size)
+static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size)
{
struct bio *bio;
struct page *page;
@@ -96,7 +96,7 @@ static struct bio *get_failover_bio(struct path *path, unsigned data_size)
}
static struct request *get_failover_req(struct emc_handler *h,
- struct bio *bio, struct path *path)
+ struct bio *bio, struct dm_path *path)
{
struct request *rq;
struct block_device *bdev = bio->bi_bdev;
@@ -133,7 +133,7 @@ static struct request *get_failover_req(struct emc_handler *h,
}
static struct request *emc_trespass_get(struct emc_handler *h,
- struct path *path)
+ struct dm_path *path)
{
struct bio *bio;
struct request *rq;
@@ -191,7 +191,7 @@ static struct request *emc_trespass_get(struct emc_handler *h,
}
static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed,
- struct path *path)
+ struct dm_path *path)
{
struct request *rq;
struct request_queue *q = bdev_get_queue(path->dev->bdev);
diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h
index 15f5629e231..32eff28e4ad 100644
--- a/drivers/md/dm-hw-handler.h
+++ b/drivers/md/dm-hw-handler.h
@@ -32,7 +32,7 @@ struct hw_handler_type {
void (*destroy) (struct hw_handler *hwh);
void (*pg_init) (struct hw_handler *hwh, unsigned bypassed,
- struct path *path);
+ struct dm_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);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index da663d2ff55..4eb73d39521 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages)
*---------------------------------------------------------------*/
static inline void bio_set_region(struct bio *bio, unsigned region)
{
- bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region;
+ bio->bi_io_vec[bio->bi_max_vecs].bv_len = region;
}
static inline unsigned bio_get_region(struct bio *bio)
{
- return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len;
+ return bio->bi_io_vec[bio->bi_max_vecs].bv_len;
}
/*-----------------------------------------------------------------
@@ -136,6 +136,7 @@ static int endio(struct bio *bio, unsigned int done, int error)
zero_fill_bio(bio);
dec_count(io, bio_get_region(bio), error);
+ bio->bi_max_vecs++;
bio_put(bio);
return 0;
@@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
while (remaining) {
/*
- * Allocate a suitably sized bio, we add an extra
- * bvec for bio_get/set_region().
+ * Allocate a suitably sized-bio: we add an extra
+ * bvec for bio_get/set_region() and decrement bi_max_vecs
+ * to hide it from bio_add_page().
*/
- num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2;
+ num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2;
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 = dm_bio_destructor;
+ bio->bi_max_vecs--;
bio_set_region(bio, region);
/*
@@ -302,7 +305,7 @@ static void dispatch_io(int rw, unsigned int num_regions,
}
/*
- * Drop the extra refence that we were holding to avoid
+ * Drop the extra reference that we were holding to avoid
* the io being completed too early.
*/
dec_count(io, 0, 0);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 4510ad8f971..cd6a184536a 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -765,7 +765,7 @@ out:
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
- int do_lockfs = 1;
+ unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
struct mapped_device *md;
md = find_device(param);
@@ -773,10 +773,12 @@ static int do_suspend(struct dm_ioctl *param)
return -ENXIO;
if (param->flags & DM_SKIP_LOCKFS_FLAG)
- do_lockfs = 0;
+ suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
+ if (param->flags & DM_NOFLUSH_FLAG)
+ suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
if (!dm_suspended(md))
- r = dm_suspend(md, do_lockfs);
+ r = dm_suspend(md, suspend_flags);
if (!r)
r = __dev_status(md, param);
@@ -788,7 +790,7 @@ static int do_suspend(struct dm_ioctl *param)
static int do_resume(struct dm_ioctl *param)
{
int r = 0;
- int do_lockfs = 1;
+ unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
struct hash_cell *hc;
struct mapped_device *md;
struct dm_table *new_map;
@@ -814,9 +816,11 @@ static int do_resume(struct dm_ioctl *param)
if (new_map) {
/* Suspend if it isn't already suspended */
if (param->flags & DM_SKIP_LOCKFS_FLAG)
- do_lockfs = 0;
+ suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
+ if (param->flags & DM_NOFLUSH_FLAG)
+ suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
if (!dm_suspended(md))
- dm_suspend(md, do_lockfs);
+ dm_suspend(md, suspend_flags);
r = dm_swap_table(md, new_map);
if (r) {
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 00234909b3d..17753d80ad2 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -77,7 +77,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio,
bio->bi_bdev = lc->dev->bdev;
bio->bi_sector = lc->start + (bio->bi_sector - ti->begin);
- return 1;
+ return DM_MAPIO_REMAPPED;
}
static int linear_status(struct dm_target *ti, status_type_t type,
@@ -108,7 +108,7 @@ static int linear_ioctl(struct dm_target *ti, struct inode *inode,
struct dentry fake_dentry = {};
fake_file.f_mode = lc->dev->mode;
- fake_file.f_dentry = &fake_dentry;
+ fake_file.f_path.dentry = &fake_dentry;
fake_dentry.d_inode = bdev->bd_inode;
return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg);
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 64b764bd02c..6a926135184 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -466,6 +466,7 @@ static int disk_resume(struct dirty_log *log)
/* copy clean across to sync */
memcpy(lc->sync_bits, lc->clean_bits, size);
lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count);
+ lc->sync_search = 0;
/* set the correct number of regions in the header */
lc->header.nr_regions = lc->region_count;
@@ -480,6 +481,13 @@ static uint32_t core_get_region_size(struct dirty_log *log)
return lc->region_size;
}
+static int core_resume(struct dirty_log *log)
+{
+ struct log_c *lc = (struct log_c *) log->context;
+ lc->sync_search = 0;
+ return 0;
+}
+
static int core_is_clean(struct dirty_log *log, region_t region)
{
struct log_c *lc = (struct log_c *) log->context;
@@ -549,16 +557,19 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
return 1;
}
-static void core_complete_resync_work(struct dirty_log *log, region_t region,
- int success)
+static void core_set_region_sync(struct dirty_log *log, region_t region,
+ int in_sync)
{
struct log_c *lc = (struct log_c *) log->context;
log_clear_bit(lc, lc->recovering_bits, region);
- if (success) {
+ if (in_sync) {
log_set_bit(lc, lc->sync_bits, region);
lc->sync_count++;
- }
+ } else if (log_test_bit(lc->sync_bits, region)) {
+ lc->sync_count--;
+ log_clear_bit(lc, lc->sync_bits, region);
+ }
}
static region_t core_get_sync_count(struct dirty_log *log)
@@ -618,6 +629,7 @@ static struct dirty_log_type _core_type = {
.module = THIS_MODULE,
.ctr = core_ctr,
.dtr = core_dtr,
+ .resume = core_resume,
.get_region_size = core_get_region_size,
.is_clean = core_is_clean,
.in_sync = core_in_sync,
@@ -625,7 +637,7 @@ static struct dirty_log_type _core_type = {
.mark_region = core_mark_region,
.clear_region = core_clear_region,
.get_resync_work = core_get_resync_work,
- .complete_resync_work = core_complete_resync_work,
+ .set_region_sync = core_set_region_sync,
.get_sync_count = core_get_sync_count,
.status = core_status,
};
@@ -644,7 +656,7 @@ static struct dirty_log_type _disk_type = {
.mark_region = core_mark_region,
.clear_region = core_clear_region,
.get_resync_work = core_get_resync_work,
- .complete_resync_work = core_complete_resync_work,
+ .set_region_sync = core_set_region_sync,
.get_sync_count = core_get_sync_count,
.status = disk_status,
};
diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
index 5ae5309ebf2..86a301c8daf 100644
--- a/drivers/md/dm-log.h
+++ b/drivers/md/dm-log.h
@@ -90,12 +90,12 @@ struct dirty_log_type {
int (*get_resync_work)(struct dirty_log *log, region_t *region);
/*
- * This notifies the log that the resync of an area has
- * been completed. The log should then mark this region
- * as CLEAN.
+ * This notifies the log that the resync status of a region
+ * has changed. It also clears the region from the recovering
+ * list (if present).
*/
- void (*complete_resync_work)(struct dirty_log *log,
- region_t region, int success);
+ void (*set_region_sync)(struct dirty_log *log,
+ region_t region, int in_sync);
/*
* Returns the number of regions that are in sync.
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index cf8bf052138..3aa01350696 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -31,7 +31,7 @@ struct pgpath {
struct priority_group *pg; /* Owning PG */
unsigned fail_count; /* Cumulative failure count */
- struct path path;
+ struct dm_path path;
};
#define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -229,7 +229,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
{
- struct path *path;
+ struct dm_path *path;
path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
if (!path)
@@ -282,10 +282,27 @@ failed:
m->current_pg = NULL;
}
+/*
+ * Check whether bios must be queued in the device-mapper core rather
+ * than here in the target.
+ *
+ * m->lock must be held on entry.
+ *
+ * If m->queue_if_no_path and m->saved_queue_if_no_path hold the
+ * same value then we are not between multipath_presuspend()
+ * and multipath_resume() calls and we have no need to check
+ * for the DMF_NOFLUSH_SUSPENDING flag.
+ */
+static int __must_push_back(struct multipath *m)
+{
+ return (m->queue_if_no_path != m->saved_queue_if_no_path &&
+ dm_noflush_suspending(m->ti));
+}
+
static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
unsigned was_queued)
{
- int r = 1;
+ int r = DM_MAPIO_REMAPPED;
unsigned long flags;
struct pgpath *pgpath;
@@ -310,11 +327,13 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
!m->queue_io)
queue_work(kmultipathd, &m->process_queued_ios);
pgpath = NULL;
- r = 0;
- } else if (!pgpath)
- r = -EIO; /* Failed */
- else
+ r = DM_MAPIO_SUBMITTED;
+ } else if (pgpath)
bio->bi_bdev = pgpath->path.dev->bdev;
+ else if (__must_push_back(m))
+ r = DM_MAPIO_REQUEUE;
+ else
+ r = -EIO; /* Failed */
mpio->pgpath = pgpath;
@@ -372,8 +391,10 @@ static void dispatch_queued_ios(struct multipath *m)
r = map_io(m, bio, mpio, 1);
if (r < 0)
bio_endio(bio, bio->bi_size, r);
- else if (r == 1)
+ else if (r == DM_MAPIO_REMAPPED)
generic_make_request(bio);
+ else if (r == DM_MAPIO_REQUEUE)
+ bio_endio(bio, bio->bi_size, -EIO);
bio = next;
}
@@ -783,7 +804,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
map_context->ptr = mpio;
bio->bi_rw |= (1 << BIO_RW_FAILFAST);
r = map_io(m, bio, mpio, 0);
- if (r < 0)
+ if (r < 0 || r == DM_MAPIO_REQUEUE)
mempool_free(mpio, m->mpio_pool);
return r;
@@ -957,7 +978,7 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
/*
* pg_init must call this when it has completed its initialisation
*/
-void dm_pg_init_complete(struct path *path, unsigned err_flags)
+void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
{
struct pgpath *pgpath = path_to_pgpath(path);
struct priority_group *pg = pgpath->pg;
@@ -1007,7 +1028,10 @@ static int do_end_io(struct multipath *m, struct bio *bio,
spin_lock_irqsave(&m->lock, flags);
if (!m->nr_valid_paths) {
- if (!m->queue_if_no_path) {
+ if (__must_push_back(m)) {
+ spin_unlock_irqrestore(&m->lock, flags);
+ return DM_ENDIO_REQUEUE;
+ } else if (!m->queue_if_no_path) {
spin_unlock_irqrestore(&m->lock, flags);
return -EIO;
} else {
@@ -1042,7 +1066,7 @@ static int do_end_io(struct multipath *m, struct bio *bio,
queue_work(kmultipathd, &m->process_queued_ios);
spin_unlock_irqrestore(&m->lock, flags);
- return 1; /* io not complete */
+ return DM_ENDIO_INCOMPLETE; /* io not complete */
}
static int multipath_end_io(struct dm_target *ti, struct bio *bio,
@@ -1060,7 +1084,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio,
if (ps->type->end_io)
ps->type->end_io(ps, &pgpath->path);
}
- if (r <= 0)
+ if (r != DM_ENDIO_INCOMPLETE)
mempool_free(mpio, m->mpio_pool);
return r;
@@ -1272,7 +1296,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode,
struct dentry fake_dentry = {};
int r = 0;
- fake_file.f_dentry = &fake_dentry;
+ fake_file.f_path.dentry = &fake_dentry;
spin_lock_irqsave(&m->lock, flags);
diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
index 8a4bf2b6d52..b9cdcbb3ed5 100644
--- a/drivers/md/dm-mpath.h
+++ b/drivers/md/dm-mpath.h
@@ -11,7 +11,7 @@
struct dm_dev;
-struct path {
+struct dm_path {
struct dm_dev *dev; /* Read-only */
unsigned is_active; /* Read-only */
@@ -20,6 +20,6 @@ struct path {
};
/* Callback for hwh_pg_init_fn to use when complete */
-void dm_pg_init_complete(struct path *path, unsigned err_flags);
+void dm_pg_init_complete(struct dm_path *path, unsigned err_flags);
#endif
diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h
index 732d06a84f8..27357b85d73 100644
--- a/drivers/md/dm-path-selector.h
+++ b/drivers/md/dm-path-selector.h
@@ -44,7 +44,7 @@ struct path_selector_type {
* 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 (*add_path) (struct path_selector *ps, struct dm_path *path,
int argc, char **argv, char **error);
/*
@@ -55,27 +55,27 @@ struct path_selector_type {
* calling the function again. 0 means don't call it again unless
* the path fails.
*/
- struct path *(*select_path) (struct path_selector *ps,
+ struct dm_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);
+ void (*fail_path) (struct path_selector *ps, struct dm_path *p);
/*
* Ask selector to reinstate a path.
*/
- int (*reinstate_path) (struct path_selector *ps, struct path *p);
+ int (*reinstate_path) (struct path_selector *ps, struct dm_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,
+ int (*status) (struct path_selector *ps, struct dm_path *path,
status_type_t type, char *result, unsigned int maxlen);
- int (*end_io) (struct path_selector *ps, struct path *path);
+ int (*end_io) (struct path_selector *ps, struct dm_path *path);
};
/* Register a path selector */
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index fc8cbb168e3..23a642619be 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -344,6 +344,17 @@ static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list)
}
}
+static void complete_resync_work(struct region *reg, int success)
+{
+ struct region_hash *rh = reg->rh;
+
+ rh->log->type->set_region_sync(rh->log, reg->key, success);
+ dispatch_bios(rh->ms, &reg->delayed_bios);
+ if (atomic_dec_and_test(&rh->recovery_in_flight))
+ wake_up_all(&_kmirrord_recovery_stopped);
+ up(&rh->recovery_count);
+}
+
static void rh_update_states(struct region_hash *rh)
{
struct region *reg, *next;
@@ -383,11 +394,7 @@ static void rh_update_states(struct region_hash *rh)
*/
list_for_each_entry_safe (reg, next, &recovered, list) {
rh->log->type->clear_region(rh->log, reg->key);
- rh->log->type->complete_resync_work(rh->log, reg->key, 1);
- dispatch_bios(rh->ms, &reg->delayed_bios);
- if (atomic_dec_and_test(&rh->recovery_in_flight))
- wake_up_all(&_kmirrord_recovery_stopped);
- up(&rh->recovery_count);
+ complete_resync_work(reg, 1);
mempool_free(reg, rh->region_pool);
}
@@ -1137,7 +1144,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
if (rw == WRITE) {
queue_bio(ms, bio, rw);
- return 0;
+ return DM_MAPIO_SUBMITTED;
}
r = ms->rh.log->type->in_sync(ms->rh.log,
@@ -1146,7 +1153,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
return r;
if (r == -EWOULDBLOCK) /* FIXME: ugly */
- r = 0;
+ r = DM_MAPIO_SUBMITTED;
/*
* We don't want to fast track a recovery just for a read
@@ -1159,7 +1166,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
if (!r) {
/* Pass this io over to the daemon */
queue_bio(ms, bio, rw);
- return 0;
+ return DM_MAPIO_SUBMITTED;
}
m = choose_mirror(ms, bio->bi_sector);
@@ -1167,7 +1174,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio,
return -EIO;
map_bio(ms, m, bio);
- return 1;
+ return DM_MAPIO_REMAPPED;
}
static int mirror_end_io(struct dm_target *ti, struct bio *bio,
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
index 6f9fcd4db9b..a348a97b65a 100644
--- a/drivers/md/dm-round-robin.c
+++ b/drivers/md/dm-round-robin.c
@@ -21,7 +21,7 @@
*---------------------------------------------------------------*/
struct path_info {
struct list_head list;
- struct path *path;
+ struct dm_path *path;
unsigned repeat_count;
};
@@ -80,7 +80,7 @@ static void rr_destroy(struct path_selector *ps)
ps->context = NULL;
}
-static int rr_status(struct path_selector *ps, struct path *path,
+static int rr_status(struct path_selector *ps, struct dm_path *path,
status_type_t type, char *result, unsigned int maxlen)
{
struct path_info *pi;
@@ -106,7 +106,7 @@ static int rr_status(struct path_selector *ps, struct path *path,
* Called during initialisation to register each path with an
* optional repeat_count.
*/
-static int rr_add_path(struct path_selector *ps, struct path *path,
+static int rr_add_path(struct path_selector *ps, struct dm_path *path,
int argc, char **argv, char **error)
{
struct selector *s = (struct selector *) ps->context;
@@ -141,7 +141,7 @@ static int rr_add_path(struct path_selector *ps, struct path *path,
return 0;
}
-static void rr_fail_path(struct path_selector *ps, struct path *p)
+static void rr_fail_path(struct path_selector *ps, struct dm_path *p)
{
struct selector *s = (struct selector *) ps->context;
struct path_info *pi = p->pscontext;
@@ -149,7 +149,7 @@ static void rr_fail_path(struct path_selector *ps, struct path *p)
list_move(&pi->list, &s->invalid_paths);
}
-static int rr_reinstate_path(struct path_selector *ps, struct path *p)
+static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p)
{
struct selector *s = (struct selector *) ps->context;
struct path_info *pi = p->pscontext;
@@ -159,7 +159,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct path *p)
return 0;
}
-static struct path *rr_select_path(struct path_selector *ps,
+static struct dm_path *rr_select_path(struct path_selector *ps,
unsigned *repeat_count)
{
struct selector *s = (struct selector *) ps->context;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index b0ce2ce8227..0821a2b68a7 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -39,7 +39,7 @@
*/
#define SNAPSHOT_PAGES 256
-struct workqueue_struct *ksnapd;
+static struct workqueue_struct *ksnapd;
static void flush_queued_bios(struct work_struct *work);
struct pending_exception {
@@ -564,6 +564,17 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return r;
}
+static void __free_exceptions(struct dm_snapshot *s)
+{
+ kcopyd_client_destroy(s->kcopyd_client);
+ s->kcopyd_client = NULL;
+
+ exit_exception_table(&s->pending, pending_cache);
+ exit_exception_table(&s->complete, exception_cache);
+
+ s->store.destroy(&s->store);
+}
+
static void snapshot_dtr(struct dm_target *ti)
{
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
@@ -574,13 +585,7 @@ static void snapshot_dtr(struct dm_target *ti)
/* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s);
- kcopyd_client_destroy(s->kcopyd_client);
-
- exit_exception_table(&s->pending, pending_cache);
- exit_exception_table(&s->complete, exception_cache);
-
- /* Deallocate memory used */
- s->store.destroy(&s->store);
+ __free_exceptions(s);
dm_put_device(ti, s->origin);
dm_put_device(ti, s->cow);
@@ -868,7 +873,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
{
struct exception *e;
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
- int r = 1;
+ int r = DM_MAPIO_REMAPPED;
chunk_t chunk;
struct pending_exception *pe = NULL;
@@ -914,7 +919,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
remap_exception(s, &pe->e, bio);
bio_list_add(&pe->snapshot_bios, bio);
- r = 0;
+ r = DM_MAPIO_SUBMITTED;
if (!pe->started) {
/* this is protected by snap->lock */
@@ -992,7 +997,7 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
*---------------------------------------------------------------*/
static int __origin_write(struct list_head *snapshots, struct bio *bio)
{
- int r = 1, first = 0;
+ int r = DM_MAPIO_REMAPPED, first = 0;
struct dm_snapshot *snap;
struct exception *e;
struct pending_exception *pe, *next_pe, *primary_pe = NULL;
@@ -1050,7 +1055,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
bio_list_add(&primary_pe->origin_bios, bio);
- r = 0;
+ r = DM_MAPIO_SUBMITTED;
}
if (!pe->primary_pe) {
@@ -1099,7 +1104,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
static int do_origin(struct dm_dev *origin, struct bio *bio)
{
struct origin *o;
- int r = 1;
+ int r = DM_MAPIO_REMAPPED;
down_read(&_origins_lock);
o = __lookup_origin(origin->bdev);
@@ -1156,7 +1161,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
return -EOPNOTSUPP;
/* Only tell snapshots if this is a write */
- return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1;
+ return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
}
#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 6c29fcecd89..51f5e076001 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -186,7 +186,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
bio->bi_bdev = sc->stripe[stripe].dev->bdev;
bio->bi_sector = sc->stripe[stripe].physical_start +
(chunk << sc->chunk_shift) + (offset & sc->chunk_mask);
- return 1;
+ return DM_MAPIO_REMAPPED;
}
static int stripe_status(struct dm_target *ti,
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index ea569f7348d..f314d7dc9c2 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -46,7 +46,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio,
bio_endio(bio, bio->bi_size, 0);
/* accepted bio, don't make new request */
- return 0;
+ return DM_MAPIO_SUBMITTED;
}
static struct target_type zero_target = {
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 7ec1b112a6d..3668b170ea6 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -68,10 +68,12 @@ union map_info *dm_get_mapinfo(struct bio *bio)
#define DMF_FROZEN 2
#define DMF_FREEING 3
#define DMF_DELETING 4
+#define DMF_NOFLUSH_SUSPENDING 5
struct mapped_device {
struct rw_semaphore io_lock;
struct semaphore suspend_lock;
+ spinlock_t pushback_lock;
rwlock_t map_lock;
atomic_t holders;
atomic_t open_count;
@@ -89,7 +91,8 @@ struct mapped_device {
*/
atomic_t pending;
wait_queue_head_t wait;
- struct bio_list deferred;
+ struct bio_list deferred;
+ struct bio_list pushback;
/*
* The current mapping.
@@ -444,23 +447,50 @@ int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo)
* you this clearly demarcated crap.
*---------------------------------------------------------------*/
+static int __noflush_suspending(struct mapped_device *md)
+{
+ return test_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+}
+
/*
* Decrements the number of outstanding ios that a bio has been
* cloned into, completing the original io if necc.
*/
static void dec_pending(struct dm_io *io, int error)
{
- if (error)
+ unsigned long flags;
+
+ /* Push-back supersedes any I/O errors */
+ if (error && !(io->error > 0 && __noflush_suspending(io->md)))
io->error = error;
if (atomic_dec_and_test(&io->io_count)) {
+ if (io->error == DM_ENDIO_REQUEUE) {
+ /*
+ * Target requested pushing back the I/O.
+ * This must be handled before the sleeper on
+ * suspend queue merges the pushback list.
+ */
+ spin_lock_irqsave(&io->md->pushback_lock, flags);
+ if (__noflush_suspending(io->md))
+ bio_list_add(&io->md->pushback, io->bio);
+ else
+ /* noflush suspend was interrupted. */
+ io->error = -EIO;
+ spin_unlock_irqrestore(&io->md->pushback_lock, flags);
+ }
+
if (end_io_acct(io))
/* nudge anyone waiting on suspend queue */
wake_up(&io->md->wait);
- blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE);
+ if (io->error != DM_ENDIO_REQUEUE) {
+ blk_add_trace_bio(io->md->queue, io->bio,
+ BLK_TA_COMPLETE);
+
+ bio_endio(io->bio, io->bio->bi_size, io->error);
+ }
- bio_endio(io->bio, io->bio->bi_size, io->error);
free_io(io->md, io);
}
}
@@ -480,12 +510,19 @@ static int clone_endio(struct bio *bio, unsigned int done, int error)
if (endio) {
r = endio(tio->ti, bio, error, &tio->info);
- if (r < 0)
+ if (r < 0 || r == DM_ENDIO_REQUEUE)
+ /*
+ * error and requeue request are handled
+ * in dec_pending().
+ */
error = r;
-
- else if (r > 0)
- /* the target wants another shot at the io */
+ else if (r == DM_ENDIO_INCOMPLETE)
+ /* The target will handle the io */
return 1;
+ else if (r) {
+ DMWARN("unimplemented target endio return value: %d", r);
+ BUG();
+ }
}
dec_pending(tio->io, error);
@@ -543,7 +580,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
atomic_inc(&tio->io->io_count);
sector = clone->bi_sector;
r = ti->type->map(ti, clone, &tio->info);
- if (r > 0) {
+ if (r == DM_MAPIO_REMAPPED) {
/* the bio has been remapped so dispatch it */
blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone,
@@ -551,10 +588,8 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
clone->bi_sector);
generic_make_request(clone);
- }
-
- else if (r < 0) {
- /* error the io and bail out */
+ } else if (r < 0 || r == DM_MAPIO_REQUEUE) {
+ /* error the io and bail out, or requeue it if needed */
md = tio->io->md;
dec_pending(tio->io, r);
/*
@@ -563,6 +598,9 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
clone->bi_private = md->bs;
bio_put(clone);
free_tio(md, tio);
+ } else if (r) {
+ DMWARN("unimplemented target map return value: %d", r);
+ BUG();
}
}
@@ -948,6 +986,7 @@ static struct mapped_device *alloc_dev(int minor)
memset(md, 0, sizeof(*md));
init_rwsem(&md->io_lock);
init_MUTEX(&md->suspend_lock);
+ spin_lock_init(&md->pushback_lock);
rwlock_init(&md->map_lock);
atomic_set(&md->holders, 1);
atomic_set(&md->open_count, 0);
@@ -966,8 +1005,8 @@ static struct mapped_device *alloc_dev(int minor)
md->queue->issue_flush_fn = dm_flush_all;
md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
- if (!md->io_pool)
- goto bad2;
+ if (!md->io_pool)
+ goto bad2;
md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache);
if (!md->tio_pool)
@@ -1077,7 +1116,8 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
if (size != get_capacity(md->disk))
memset(&md->geometry, 0, sizeof(md->geometry));
- __set_size(md, size);
+ if (md->suspended_bdev)
+ __set_size(md, size);
if (size == 0)
return 0;
@@ -1225,6 +1265,11 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table)
if (!dm_suspended(md))
goto out;
+ /* without bdev, the device size cannot be changed */
+ if (!md->suspended_bdev)
+ if (get_capacity(md->disk) != dm_table_get_size(table))
+ goto out;
+
__unbind(md);
r = __bind(md, table);
@@ -1275,12 +1320,15 @@ static void unlock_fs(struct mapped_device *md)
* dm_bind_table, dm_suspend must be called to flush any in
* flight bios and ensure that any further io gets deferred.
*/
-int dm_suspend(struct mapped_device *md, int do_lockfs)
+int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
{
struct dm_table *map = NULL;
+ unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
struct bio *def;
int r = -EINVAL;
+ int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0;
+ int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0;
down(&md->suspend_lock);
@@ -1289,18 +1337,31 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
map = dm_get_table(md);
+ /*
+ * DMF_NOFLUSH_SUSPENDING must be set before presuspend.
+ * This flag is cleared before dm_suspend returns.
+ */
+ if (noflush)
+ set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+
/* This does not get reverted if there's an error later. */
dm_table_presuspend_targets(map);
- md->suspended_bdev = bdget_disk(md->disk, 0);
- if (!md->suspended_bdev) {
- DMWARN("bdget failed in dm_suspend");
- r = -ENOMEM;
- goto out;
+ /* bdget() can stall if the pending I/Os are not flushed */
+ if (!noflush) {
+ md->suspended_bdev = bdget_disk(md->disk, 0);
+ if (!md->suspended_bdev) {
+ DMWARN("bdget failed in dm_suspend");
+ r = -ENOMEM;
+ goto flush_and_out;
+ }
}
- /* Flush I/O to the device. */
- if (do_lockfs) {
+ /*
+ * Flush I/O to the device.
+ * noflush supersedes do_lockfs, because lock_fs() needs to flush I/Os.
+ */
+ if (do_lockfs && !noflush) {
r = lock_fs(md);
if (r)
goto out;
@@ -1336,6 +1397,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
down_write(&md->io_lock);
remove_wait_queue(&md->wait, &wait);
+ if (noflush) {
+ spin_lock_irqsave(&md->pushback_lock, flags);
+ clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+ bio_list_merge_head(&md->deferred, &md->pushback);
+ bio_list_init(&md->pushback);
+ spin_unlock_irqrestore(&md->pushback_lock, flags);
+ }
+
/* were we interrupted ? */
r = -EINTR;
if (atomic_read(&md->pending)) {
@@ -1344,7 +1413,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
__flush_deferred_io(md, def);
up_write(&md->io_lock);
unlock_fs(md);
- goto out;
+ goto out; /* pushback list is already flushed, so skip flush */
}
up_write(&md->io_lock);
@@ -1354,6 +1423,25 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
r = 0;
+flush_and_out:
+ if (r && noflush) {
+ /*
+ * Because there may be already I/Os in the pushback list,
+ * flush them before return.
+ */
+ down_write(&md->io_lock);
+
+ spin_lock_irqsave(&md->pushback_lock, flags);
+ clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
+ bio_list_merge_head(&md->deferred, &md->pushback);
+ bio_list_init(&md->pushback);
+ spin_unlock_irqrestore(&md->pushback_lock, flags);
+
+ def = bio_list_get(&md->deferred);
+ __flush_deferred_io(md, def);
+ up_write(&md->io_lock);
+ }
+
out:
if (r && md->suspended_bdev) {
bdput(md->suspended_bdev);
@@ -1394,8 +1482,10 @@ int dm_resume(struct mapped_device *md)
unlock_fs(md);
- bdput(md->suspended_bdev);
- md->suspended_bdev = NULL;
+ if (md->suspended_bdev) {
+ bdput(md->suspended_bdev);
+ md->suspended_bdev = NULL;
+ }
clear_bit(DMF_SUSPENDED, &md->flags);
@@ -1440,6 +1530,17 @@ int dm_suspended(struct mapped_device *md)
return test_bit(DMF_SUSPENDED, &md->flags);
}
+int dm_noflush_suspending(struct dm_target *ti)
+{
+ struct mapped_device *md = dm_table_get_md(ti->table);
+ int r = __noflush_suspending(md);
+
+ dm_put(md);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(dm_noflush_suspending);
+
static struct block_device_operations dm_blk_dops = {
.open = dm_blk_open,
.release = dm_blk_close,
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index a48ec5e3c1f..2f796b1436b 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -33,6 +33,25 @@
#define SECTOR_SHIFT 9
/*
+ * Definitions of return values from target end_io function.
+ */
+#define DM_ENDIO_INCOMPLETE 1
+#define DM_ENDIO_REQUEUE 2
+
+/*
+ * Definitions of return values from target map function.
+ */
+#define DM_MAPIO_SUBMITTED 0
+#define DM_MAPIO_REMAPPED 1
+#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
+
+/*
+ * Suspend feature flags
+ */
+#define DM_SUSPEND_LOCKFS_FLAG (1 << 0)
+#define DM_SUSPEND_NOFLUSH_FLAG (1 << 1)
+
+/*
* List of devices that a metadevice uses and should open/close.
*/
struct dm_dev {
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index a7a5ab55433..4ebd0f2a75e 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -173,7 +173,7 @@ static int make_request(request_queue_t *q, struct bio *bio)
conf_t *conf = (conf_t*)mddev->private;
int failit = 0;
- if (bio->bi_rw & 1) {
+ if (bio_data_dir(bio) == WRITE) {
/* write request */
if (atomic_read(&conf->counters[WriteAll])) {
/* special case - don't decrement, don't generic_make_request,
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6c4345bde07..e8807ea5377 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1413,7 +1413,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
struct block_device *bdev;
char b[BDEVNAME_SIZE];
- bdev = open_partition_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+ bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
if (IS_ERR(bdev)) {
printk(KERN_ERR "md: could not open %s.\n",
__bdevname(dev, b));
@@ -1423,7 +1423,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
if (err) {
printk(KERN_ERR "md: could not bd_claim %s.\n",
bdevname(bdev, b));
- blkdev_put_partition(bdev);
+ blkdev_put(bdev);
return err;
}
rdev->bdev = bdev;
@@ -1437,7 +1437,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
if (!bdev)
MD_BUG();
bd_release(bdev);
- blkdev_put_partition(bdev);
+ blkdev_put(bdev);
}
void md_autodetect_dev(dev_t dev);
@@ -1633,7 +1633,8 @@ repeat:
* and 'events' is odd, we can roll back to the previous clean state */
if (nospares
&& (mddev->in_sync && mddev->recovery_cp == MaxSector)
- && (mddev->events & 1))
+ && (mddev->events & 1)
+ && mddev->events != 1)
mddev->events--;
else {
/* otherwise we have to go forward and ... */
@@ -1792,7 +1793,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
else {
mddev_t *mddev = rdev->mddev;
kick_rdev_from_array(rdev);
- md_update_sb(mddev, 1);
+ if (mddev->pers)
+ md_update_sb(mddev, 1);
md_new_event(mddev);
err = 0;
}
@@ -2004,6 +2006,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
rdev->desc_nr = -1;
rdev->saved_raid_disk = -1;
+ rdev->raid_disk = -1;
rdev->flags = 0;
rdev->data_offset = 0;
rdev->sb_events = 0;
@@ -2233,7 +2236,6 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks);
static ssize_t
raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
{
- /* can only set raid_disks if array is not yet active */
char *e;
int rv = 0;
unsigned long n = simple_strtoul(buf, &e, 10);
@@ -2631,7 +2633,7 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
return -EINVAL;
buf = e+1;
minor = simple_strtoul(buf, &e, 10);
- if (e==buf || *e != '\n')
+ if (e==buf || (*e && *e != '\n') )
return -EINVAL;
if (major >= sizeof(super_types)/sizeof(super_types[0]) ||
super_types[major].name == NULL)
@@ -3314,6 +3316,10 @@ static int do_md_stop(mddev_t * mddev, int mode)
module_put(mddev->pers->owner);
mddev->pers = NULL;
+
+ set_capacity(disk, 0);
+ mddev->changed = 1;
+
if (mddev->ro)
mddev->ro = 0;
}
@@ -3333,7 +3339,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
if (mode == 0) {
mdk_rdev_t *rdev;
struct list_head *tmp;
- struct gendisk *disk;
+
printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
bitmap_destroy(mddev);
@@ -3358,10 +3364,6 @@ static int do_md_stop(mddev_t * mddev, int mode)
mddev->raid_disks = 0;
mddev->recovery_cp = 0;
- disk = mddev->gendisk;
- if (disk)
- set_capacity(disk, 0);
- mddev->changed = 1;
} else if (mddev->pers)
printk(KERN_INFO "md: %s switched to read-only mode.\n",
mdname(mddev));
@@ -3371,6 +3373,7 @@ out:
return err;
}
+#ifndef MODULE
static void autorun_array(mddev_t *mddev)
{
mdk_rdev_t *rdev;
@@ -3485,6 +3488,7 @@ static void autorun_devices(int part)
}
printk(KERN_INFO "md: ... autorun DONE.\n");
}
+#endif /* !MODULE */
static int get_version(void __user * arg)
{
@@ -3560,6 +3564,8 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg)
char *ptr, *buf = NULL;
int err = -ENOMEM;
+ md_allow_write(mddev);
+
file = kmalloc(sizeof(*file), GFP_KERNEL);
if (!file)
goto out;
@@ -3722,6 +3728,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
if (err)
export_rdev(rdev);
+ md_update_sb(mddev, 1);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
return err;
@@ -3977,6 +3984,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->major_version = info->major_version;
mddev->minor_version = info->minor_version;
mddev->patch_version = info->patch_version;
+ mddev->persistent = !info->not_persistent;
return 0;
}
mddev->major_version = MD_MAJOR_VERSION;
@@ -4301,9 +4309,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
* Commands querying/configuring an existing array:
*/
/* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
- * RUN_ARRAY, and SET_BITMAP_FILE are allowed */
+ * RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */
if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
- && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE) {
+ && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE
+ && cmd != GET_BITMAP_FILE) {
err = -ENODEV;
goto abort_unlock;
}
@@ -4423,7 +4432,7 @@ static int md_open(struct inode *inode, struct file *file)
mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
int err;
- if ((err = mddev_lock(mddev)))
+ if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
goto out;
err = 0;
@@ -4846,8 +4855,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
chunk_kb ? "KB" : "B");
if (bitmap->file) {
seq_printf(seq, ", file: ");
- seq_path(seq, bitmap->file->f_vfsmnt,
- bitmap->file->f_dentry," \t\n");
+ seq_path(seq, bitmap->file->f_path.mnt,
+ bitmap->file->f_path.dentry," \t\n");
}
seq_printf(seq, "\n");
@@ -5025,6 +5034,33 @@ void md_write_end(mddev_t *mddev)
}
}
+/* md_allow_write(mddev)
+ * Calling this ensures that the array is marked 'active' so that writes
+ * may proceed without blocking. It is important to call this before
+ * attempting a GFP_KERNEL allocation while holding the mddev lock.
+ * Must be called with mddev_lock held.
+ */
+void md_allow_write(mddev_t *mddev)
+{
+ if (!mddev->pers)
+ return;
+ if (mddev->ro)
+ return;
+
+ spin_lock_irq(&mddev->write_lock);
+ if (mddev->in_sync) {
+ mddev->in_sync = 0;
+ set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+ if (mddev->safemode_delay &&
+ mddev->safemode == 0)
+ mddev->safemode = 1;
+ spin_unlock_irq(&mddev->write_lock);
+ md_update_sb(mddev, 0);
+ } else
+ spin_unlock_irq(&mddev->write_lock);
+}
+EXPORT_SYMBOL_GPL(md_allow_write);
+
static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
#define SYNC_MARKS 10
@@ -5273,7 +5309,6 @@ void md_do_sync(mddev_t *mddev)
mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
- test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
mddev->curr_resync > 2) {
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
@@ -5297,6 +5332,7 @@ void md_do_sync(mddev_t *mddev)
rdev->recovery_offset = mddev->curr_resync;
}
}
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
skip:
mddev->curr_resync = 0;
@@ -5593,7 +5629,7 @@ static void autostart_arrays(int part)
autorun_devices(part);
}
-#endif
+#endif /* !MODULE */
static __exit void md_exit(void)
{
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 656fae912fe..97ee870b265 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -775,6 +775,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
struct bio_list bl;
struct page **behind_pages = NULL;
const int rw = bio_data_dir(bio);
+ const int do_sync = bio_sync(bio);
int do_barriers;
/*
@@ -835,7 +836,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
read_bio->bi_bdev = mirror->rdev->bdev;
read_bio->bi_end_io = raid1_end_read_request;
- read_bio->bi_rw = READ;
+ read_bio->bi_rw = READ | do_sync;
read_bio->bi_private = r1_bio;
generic_make_request(read_bio);
@@ -906,7 +907,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset;
mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
mbio->bi_end_io = raid1_end_write_request;
- mbio->bi_rw = WRITE | do_barriers;
+ mbio->bi_rw = WRITE | do_barriers | do_sync;
mbio->bi_private = r1_bio;
if (behind_pages) {
@@ -941,6 +942,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
blk_plug_device(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags);
+ if (do_sync)
+ md_wakeup_thread(mddev->thread);
#if 0
while ((bio = bio_list_pop(&bl)) != NULL)
generic_make_request(bio);
@@ -1263,6 +1266,11 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
sbio->bi_sector = r1_bio->sector +
conf->mirrors[i].rdev->data_offset;
sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ for (j = 0; j < vcnt ; j++)
+ memcpy(page_address(sbio->bi_io_vec[j].bv_page),
+ page_address(pbio->bi_io_vec[j].bv_page),
+ PAGE_SIZE);
+
}
}
}
@@ -1541,6 +1549,7 @@ static void raid1d(mddev_t *mddev)
* We already have a nr_pending reference on these rdevs.
*/
int i;
+ const int do_sync = bio_sync(r1_bio->master_bio);
clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
clear_bit(R1BIO_Barrier, &r1_bio->state);
for (i=0; i < conf->raid_disks; i++)
@@ -1561,7 +1570,7 @@ static void raid1d(mddev_t *mddev)
conf->mirrors[i].rdev->data_offset;
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
bio->bi_end_io = raid1_end_write_request;
- bio->bi_rw = WRITE;
+ bio->bi_rw = WRITE | do_sync;
bio->bi_private = r1_bio;
r1_bio->bios[i] = bio;
generic_make_request(bio);
@@ -1593,6 +1602,7 @@ static void raid1d(mddev_t *mddev)
(unsigned long long)r1_bio->sector);
raid_end_bio_io(r1_bio);
} else {
+ const int do_sync = bio_sync(r1_bio->master_bio);
r1_bio->bios[r1_bio->read_disk] =
mddev->ro ? IO_BLOCKED : NULL;
r1_bio->read_disk = disk;
@@ -1608,7 +1618,7 @@ static void raid1d(mddev_t *mddev)
bio->bi_sector = r1_bio->sector + rdev->data_offset;
bio->bi_bdev = rdev->bdev;
bio->bi_end_io = raid1_end_read_request;
- bio->bi_rw = READ;
+ bio->bi_rw = READ | do_sync;
bio->bi_private = r1_bio;
unplug = 1;
generic_make_request(bio);
@@ -1736,7 +1746,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
/* take from bio_init */
bio->bi_next = NULL;
bio->bi_flags |= 1 << BIO_UPTODATE;
- bio->bi_rw = 0;
+ bio->bi_rw = READ;
bio->bi_vcnt = 0;
bio->bi_idx = 0;
bio->bi_phys_segments = 0;
@@ -1951,6 +1961,7 @@ static int run(mddev_t *mddev)
!test_bit(In_sync, &disk->rdev->flags)) {
disk->head_position = 0;
mddev->degraded++;
+ conf->fullsync = 1;
}
}
if (mddev->degraded == conf->raid_disks) {
@@ -2093,6 +2104,8 @@ static int raid1_reshape(mddev_t *mddev)
return -EINVAL;
}
+ md_allow_write(mddev);
+
raid_disks = mddev->raid_disks + mddev->delta_disks;
if (raid_disks < conf->raid_disks) {
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 7492d6033ac..a9401c017e3 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -782,6 +782,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
int i;
int chunk_sects = conf->chunk_mask + 1;
const int rw = bio_data_dir(bio);
+ const int do_sync = bio_sync(bio);
struct bio_list bl;
unsigned long flags;
@@ -863,7 +864,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
mirror->rdev->data_offset;
read_bio->bi_bdev = mirror->rdev->bdev;
read_bio->bi_end_io = raid10_end_read_request;
- read_bio->bi_rw = READ;
+ read_bio->bi_rw = READ | do_sync;
read_bio->bi_private = r10_bio;
generic_make_request(read_bio);
@@ -909,7 +910,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
conf->mirrors[d].rdev->data_offset;
mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
mbio->bi_end_io = raid10_end_write_request;
- mbio->bi_rw = WRITE;
+ mbio->bi_rw = WRITE | do_sync;
mbio->bi_private = r10_bio;
atomic_inc(&r10_bio->remaining);
@@ -922,6 +923,9 @@ static int make_request(request_queue_t *q, struct bio * bio)
blk_plug_device(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags);
+ if (do_sync)
+ md_wakeup_thread(mddev->thread);
+
return 0;
}
@@ -1563,6 +1567,7 @@ static void raid10d(mddev_t *mddev)
(unsigned long long)r10_bio->sector);
raid_end_bio_io(r10_bio);
} else {
+ const int do_sync = bio_sync(r10_bio->master_bio);
rdev = conf->mirrors[mirror].rdev;
if (printk_ratelimit())
printk(KERN_ERR "raid10: %s: redirecting sector %llu to"
@@ -1574,7 +1579,7 @@ static void raid10d(mddev_t *mddev)
bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
+ rdev->data_offset;
bio->bi_bdev = rdev->bdev;
- bio->bi_rw = READ;
+ bio->bi_rw = READ | do_sync;
bio->bi_private = r10_bio;
bio->bi_end_io = raid10_end_read_request;
unplug = 1;
@@ -1785,7 +1790,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_read;
- bio->bi_rw = 0;
+ bio->bi_rw = READ;
bio->bi_sector = r10_bio->devs[j].addr +
conf->mirrors[d].rdev->data_offset;
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
@@ -1801,7 +1806,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_write;
- bio->bi_rw = 1;
+ bio->bi_rw = WRITE;
bio->bi_sector = r10_bio->devs[k].addr +
conf->mirrors[i].rdev->data_offset;
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
@@ -1870,7 +1875,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_read;
- bio->bi_rw = 0;
+ bio->bi_rw = READ;
bio->bi_sector = r10_bio->devs[i].addr +
conf->mirrors[d].rdev->data_offset;
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 52914d5cec7..467c16982d0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -134,6 +134,8 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
list_add_tail(&sh->lru, &conf->inactive_list);
wake_up(&conf->wait_for_stripe);
+ if (conf->retry_read_aligned)
+ md_wakeup_thread(conf->mddev->thread);
}
}
}
@@ -403,6 +405,8 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
if (newsize <= conf->pool_size)
return 0; /* never bother to shrink */
+ md_allow_write(conf->mddev);
+
/* Step 1 */
sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
@@ -542,35 +546,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
}
if (uptodate) {
-#if 0
- struct bio *bio;
- unsigned long flags;
- spin_lock_irqsave(&conf->device_lock, flags);
- /* we can return a buffer if we bypassed the cache or
- * if the top buffer is not in highmem. If there are
- * multiple buffers, leave the extra work to
- * handle_stripe
- */
- buffer = sh->bh_read[i];
- if (buffer &&
- (!PageHighMem(buffer->b_page)
- || buffer->b_page == bh->b_page )
- ) {
- sh->bh_read[i] = buffer->b_reqnext;
- buffer->b_reqnext = NULL;
- } else
- buffer = NULL;
- spin_unlock_irqrestore(&conf->device_lock, flags);
- if (sh->bh_page[i]==bh->b_page)
- set_buffer_uptodate(bh);
- if (buffer) {
- if (buffer->b_page != bh->b_page)
- memcpy(buffer->b_data, bh->b_data, bh->b_size);
- buffer->b_end_io(buffer, 1);
- }
-#else
set_bit(R5_UPTODATE, &sh->dev[i].flags);
-#endif
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
rdev = conf->disks[i].rdev;
printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n",
@@ -616,14 +592,6 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
}
}
rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
-#if 0
- /* must restore b_page before unlocking buffer... */
- if (sh->bh_page[i] != bh->b_page) {
- bh->b_page = sh->bh_page[i];
- bh->b_data = page_address(bh->b_page);
- clear_buffer_uptodate(bh);
- }
-#endif
clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state);
release_stripe(sh);
@@ -821,7 +789,8 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
static sector_t compute_blocknr(struct stripe_head *sh, int i)
{
raid5_conf_t *conf = sh->raid_conf;
- int raid_disks = sh->disks, data_disks = raid_disks - 1;
+ int raid_disks = sh->disks;
+ int data_disks = raid_disks - conf->max_degraded;
sector_t new_sector = sh->sector, check;
int sectors_per_chunk = conf->chunk_size >> 9;
sector_t stripe;
@@ -857,7 +826,6 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
}
break;
case 6:
- data_disks = raid_disks - 2;
if (i == raid6_next_disk(sh->pd_idx, raid_disks))
return 0; /* It is the Q disk */
switch (conf->algorithm) {
@@ -1353,8 +1321,10 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
int pd_idx, dd_idx;
int chunk_offset = sector_div(stripe, sectors_per_chunk);
- raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk
- + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf);
+ raid5_compute_sector(stripe * (disks - conf->max_degraded)
+ *sectors_per_chunk + chunk_offset,
+ disks, disks - conf->max_degraded,
+ &dd_idx, &pd_idx, conf);
return pd_idx;
}
@@ -1615,15 +1585,6 @@ static void handle_stripe5(struct stripe_head *sh)
} else if (test_bit(R5_Insync, &dev->flags)) {
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantread, &dev->flags);
-#if 0
- /* if I am just reading this block and we don't have
- a failed drive, or any pending writes then sidestep the cache */
- if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
- ! syncing && !failed && !to_write) {
- sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page;
- sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data;
- }
-#endif
locked++;
PRINTK("Reading block %d (sync=%d)\n",
i, syncing);
@@ -1641,9 +1602,6 @@ static void handle_stripe5(struct stripe_head *sh)
dev = &sh->dev[i];
if ((dev->towrite || i == sh->pd_idx) &&
(!test_bit(R5_LOCKED, &dev->flags)
-#if 0
-|| sh->bh_page[i]!=bh->b_page
-#endif
) &&
!test_bit(R5_UPTODATE, &dev->flags)) {
if (test_bit(R5_Insync, &dev->flags)
@@ -1655,9 +1613,6 @@ static void handle_stripe5(struct stripe_head *sh)
/* Would I have to read this buffer for reconstruct_write */
if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
(!test_bit(R5_LOCKED, &dev->flags)
-#if 0
-|| sh->bh_page[i] != bh->b_page
-#endif
) &&
!test_bit(R5_UPTODATE, &dev->flags)) {
if (test_bit(R5_Insync, &dev->flags)) rcw++;
@@ -1865,23 +1820,25 @@ static void handle_stripe5(struct stripe_head *sh)
return_bi = bi->bi_next;
bi->bi_next = NULL;
bi->bi_size = 0;
- bi->bi_end_io(bi, bytes, 0);
+ bi->bi_end_io(bi, bytes,
+ test_bit(BIO_UPTODATE, &bi->bi_flags)
+ ? 0 : -EIO);
}
for (i=disks; i-- ;) {
int rw;
struct bio *bi;
mdk_rdev_t *rdev;
if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = 1;
+ rw = WRITE;
else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
- rw = 0;
+ rw = READ;
else
continue;
bi = &sh->dev[i].req;
bi->bi_rw = rw;
- if (rw)
+ if (rw == WRITE)
bi->bi_end_io = raid5_end_write_request;
else
bi->bi_end_io = raid5_end_read_request;
@@ -1917,7 +1874,7 @@ static void handle_stripe5(struct stripe_head *sh)
atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
- if (rw == 1)
+ if (rw == WRITE)
set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
@@ -2193,15 +2150,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
} else if (test_bit(R5_Insync, &dev->flags)) {
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantread, &dev->flags);
-#if 0
- /* if I am just reading this block and we don't have
- a failed drive, or any pending writes then sidestep the cache */
- if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
- ! syncing && !failed && !to_write) {
- sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page;
- sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data;
- }
-#endif
locked++;
PRINTK("Reading block %d (sync=%d)\n",
i, syncing);
@@ -2220,9 +2168,6 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
if (!test_bit(R5_OVERWRITE, &dev->flags)
&& i != pd_idx && i != qd_idx
&& (!test_bit(R5_LOCKED, &dev->flags)
-#if 0
- || sh->bh_page[i] != bh->b_page
-#endif
) &&
!test_bit(R5_UPTODATE, &dev->flags)) {
if (test_bit(R5_Insync, &dev->flags)) rcw++;
@@ -2418,23 +2363,25 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
return_bi = bi->bi_next;
bi->bi_next = NULL;
bi->bi_size = 0;
- bi->bi_end_io(bi, bytes, 0);
+ bi->bi_end_io(bi, bytes,
+ test_bit(BIO_UPTODATE, &bi->bi_flags)
+ ? 0 : -EIO);
}
for (i=disks; i-- ;) {
int rw;
struct bio *bi;
mdk_rdev_t *rdev;
if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = 1;
+ rw = WRITE;
else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
- rw = 0;
+ rw = READ;
else
continue;
bi = &sh->dev[i].req;
bi->bi_rw = rw;
- if (rw)
+ if (rw == WRITE)
bi->bi_end_io = raid5_end_write_request;
else
bi->bi_end_io = raid5_end_read_request;
@@ -2470,7 +2417,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
- if (rw == 1)
+ if (rw == WRITE)
set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
@@ -2611,6 +2558,180 @@ static int raid5_congested(void *data, int bits)
return 0;
}
+/* We want read requests to align with chunks where possible,
+ * but write requests don't need to.
+ */
+static int raid5_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec)
+{
+ mddev_t *mddev = q->queuedata;
+ sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+ int max;
+ unsigned int chunk_sectors = mddev->chunk_size >> 9;
+ unsigned int bio_sectors = bio->bi_size >> 9;
+
+ if (bio_data_dir(bio) == WRITE)
+ return biovec->bv_len; /* always allow writes to be mergeable */
+
+ max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
+ if (max < 0) max = 0;
+ if (max <= biovec->bv_len && bio_sectors == 0)
+ return biovec->bv_len;
+ else
+ return max;
+}
+
+
+static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
+{
+ sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+ unsigned int chunk_sectors = mddev->chunk_size >> 9;
+ unsigned int bio_sectors = bio->bi_size >> 9;
+
+ return chunk_sectors >=
+ ((sector & (chunk_sectors - 1)) + bio_sectors);
+}
+
+/*
+ * add bio to the retry LIFO ( in O(1) ... we are in interrupt )
+ * later sampled by raid5d.
+ */
+static void add_bio_to_retry(struct bio *bi,raid5_conf_t *conf)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&conf->device_lock, flags);
+
+ bi->bi_next = conf->retry_read_aligned_list;
+ conf->retry_read_aligned_list = bi;
+
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ md_wakeup_thread(conf->mddev->thread);
+}
+
+
+static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
+{
+ struct bio *bi;
+
+ bi = conf->retry_read_aligned;
+ if (bi) {
+ conf->retry_read_aligned = NULL;
+ return bi;
+ }
+ bi = conf->retry_read_aligned_list;
+ if(bi) {
+ conf->retry_read_aligned = bi->bi_next;
+ bi->bi_next = NULL;
+ bi->bi_phys_segments = 1; /* biased count of active stripes */
+ bi->bi_hw_segments = 0; /* count of processed stripes */
+ }
+
+ return bi;
+}
+
+
+/*
+ * The "raid5_align_endio" should check if the read succeeded and if it
+ * did, call bio_endio on the original bio (having bio_put the new bio
+ * first).
+ * If the read failed..
+ */
+static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error)
+{
+ struct bio* raid_bi = bi->bi_private;
+ mddev_t *mddev;
+ raid5_conf_t *conf;
+ int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
+ mdk_rdev_t *rdev;
+
+ if (bi->bi_size)
+ return 1;
+ bio_put(bi);
+
+ mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata;
+ conf = mddev_to_conf(mddev);
+ rdev = (void*)raid_bi->bi_next;
+ raid_bi->bi_next = NULL;
+
+ rdev_dec_pending(rdev, conf->mddev);
+
+ if (!error && uptodate) {
+ bio_endio(raid_bi, bytes, 0);
+ if (atomic_dec_and_test(&conf->active_aligned_reads))
+ wake_up(&conf->wait_for_stripe);
+ return 0;
+ }
+
+
+ PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
+
+ add_bio_to_retry(raid_bi, conf);
+ return 0;
+}
+
+static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio)
+{
+ mddev_t *mddev = q->queuedata;
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+ const unsigned int raid_disks = conf->raid_disks;
+ const unsigned int data_disks = raid_disks - conf->max_degraded;
+ unsigned int dd_idx, pd_idx;
+ struct bio* align_bi;
+ mdk_rdev_t *rdev;
+
+ if (!in_chunk_boundary(mddev, raid_bio)) {
+ PRINTK("chunk_aligned_read : non aligned\n");
+ return 0;
+ }
+ /*
+ * use bio_clone to make a copy of the bio
+ */
+ align_bi = bio_clone(raid_bio, GFP_NOIO);
+ if (!align_bi)
+ return 0;
+ /*
+ * set bi_end_io to a new function, and set bi_private to the
+ * original bio.
+ */
+ align_bi->bi_end_io = raid5_align_endio;
+ align_bi->bi_private = raid_bio;
+ /*
+ * compute position
+ */
+ align_bi->bi_sector = raid5_compute_sector(raid_bio->bi_sector,
+ raid_disks,
+ data_disks,
+ &dd_idx,
+ &pd_idx,
+ conf);
+
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[dd_idx].rdev);
+ if (rdev && test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ raid_bio->bi_next = (void*)rdev;
+ align_bi->bi_bdev = rdev->bdev;
+ align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
+ align_bi->bi_sector += rdev->data_offset;
+
+ spin_lock_irq(&conf->device_lock);
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
+ atomic_inc(&conf->active_aligned_reads);
+ spin_unlock_irq(&conf->device_lock);
+
+ generic_make_request(align_bi);
+ return 1;
+ } else {
+ rcu_read_unlock();
+ bio_put(align_bi);
+ return 0;
+ }
+}
+
+
static int make_request(request_queue_t *q, struct bio * bi)
{
mddev_t *mddev = q->queuedata;
@@ -2632,6 +2753,11 @@ static int make_request(request_queue_t *q, struct bio * bi)
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
+ if (rw == READ &&
+ mddev->reshape_position == MaxSector &&
+ chunk_aligned_read(q,bi))
+ return 0;
+
logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
last_sector = bi->bi_sector + (bi->bi_size>>9);
bi->bi_next = NULL;
@@ -2739,7 +2865,9 @@ static int make_request(request_queue_t *q, struct bio * bi)
if ( rw == WRITE )
md_write_end(mddev);
bi->bi_size = 0;
- bi->bi_end_io(bi, bytes, 0);
+ bi->bi_end_io(bi, bytes,
+ test_bit(BIO_UPTODATE, &bi->bi_flags)
+ ? 0 : -EIO);
}
return 0;
}
@@ -2950,6 +3078,74 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
return STRIPE_SECTORS;
}
+static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
+{
+ /* We may not be able to submit a whole bio at once as there
+ * may not be enough stripe_heads available.
+ * We cannot pre-allocate enough stripe_heads as we may need
+ * more than exist in the cache (if we allow ever large chunks).
+ * So we do one stripe head at a time and record in
+ * ->bi_hw_segments how many have been done.
+ *
+ * We *know* that this entire raid_bio is in one chunk, so
+ * it will be only one 'dd_idx' and only need one call to raid5_compute_sector.
+ */
+ struct stripe_head *sh;
+ int dd_idx, pd_idx;
+ sector_t sector, logical_sector, last_sector;
+ int scnt = 0;
+ int remaining;
+ int handled = 0;
+
+ logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+ sector = raid5_compute_sector( logical_sector,
+ conf->raid_disks,
+ conf->raid_disks - conf->max_degraded,
+ &dd_idx,
+ &pd_idx,
+ conf);
+ last_sector = raid_bio->bi_sector + (raid_bio->bi_size>>9);
+
+ for (; logical_sector < last_sector;
+ logical_sector += STRIPE_SECTORS, scnt++) {
+
+ if (scnt < raid_bio->bi_hw_segments)
+ /* already done this stripe */
+ continue;
+
+ sh = get_active_stripe(conf, sector, conf->raid_disks, pd_idx, 1);
+
+ if (!sh) {
+ /* failed to get a stripe - must wait */
+ raid_bio->bi_hw_segments = scnt;
+ conf->retry_read_aligned = raid_bio;
+ return handled;
+ }
+
+ set_bit(R5_ReadError, &sh->dev[dd_idx].flags);
+ add_stripe_bio(sh, raid_bio, dd_idx, 0);
+ handle_stripe(sh, NULL);
+ release_stripe(sh);
+ handled++;
+ }
+ spin_lock_irq(&conf->device_lock);
+ remaining = --raid_bio->bi_phys_segments;
+ spin_unlock_irq(&conf->device_lock);
+ if (remaining == 0) {
+ int bytes = raid_bio->bi_size;
+
+ raid_bio->bi_size = 0;
+ raid_bio->bi_end_io(raid_bio, bytes,
+ test_bit(BIO_UPTODATE, &raid_bio->bi_flags)
+ ? 0 : -EIO);
+ }
+ if (atomic_dec_and_test(&conf->active_aligned_reads))
+ wake_up(&conf->wait_for_stripe);
+ return handled;
+}
+
+
+
/*
* This is our raid5 kernel thread.
*
@@ -2971,6 +3167,7 @@ static void raid5d (mddev_t *mddev)
spin_lock_irq(&conf->device_lock);
while (1) {
struct list_head *first;
+ struct bio *bio;
if (conf->seq_flush != conf->seq_write) {
int seq = conf->seq_flush;
@@ -2987,6 +3184,16 @@ static void raid5d (mddev_t *mddev)
!list_empty(&conf->delayed_list))
raid5_activate_delayed(conf);
+ while ((bio = remove_bio_from_retry(conf))) {
+ int ok;
+ spin_unlock_irq(&conf->device_lock);
+ ok = retry_aligned_read(conf, bio);
+ spin_lock_irq(&conf->device_lock);
+ if (!ok)
+ break;
+ handled++;
+ }
+
if (list_empty(&conf->handle_list))
break;
@@ -3045,6 +3252,7 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
else
break;
}
+ md_allow_write(mddev);
while (new > conf->max_nr_stripes) {
if (grow_one_stripe(conf))
conf->max_nr_stripes++;
@@ -3174,6 +3382,7 @@ static int run(mddev_t *mddev)
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
+ atomic_set(&conf->active_aligned_reads, 0);
PRINTK("raid5: run(%s) called.\n", mdname(mddev));
@@ -3320,6 +3529,8 @@ static int run(mddev_t *mddev)
mddev->array_size = mddev->size * (conf->previous_raid_disks -
conf->max_degraded);
+ blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
+
return 0;
abort:
if (conf) {
@@ -3694,7 +3905,8 @@ static void raid5_quiesce(mddev_t *mddev, int state)
spin_lock_irq(&conf->device_lock);
conf->quiesce = 1;
wait_event_lock_irq(conf->wait_for_stripe,
- atomic_read(&conf->active_stripes) == 0,
+ atomic_read(&conf->active_stripes) == 0 &&
+ atomic_read(&conf->active_aligned_reads) == 0,
conf->device_lock, /* nothing */);
spin_unlock_irq(&conf->device_lock);
break;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 9f7e1fe8c97..87410dbd3df 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -67,6 +67,7 @@ source "drivers/media/common/Kconfig"
config VIDEO_TUNER
tristate
+ depends on I2C
config VIDEO_BUF
tristate
@@ -82,6 +83,7 @@ config VIDEO_IR
config VIDEO_TVEEPROM
tristate
+ depends on I2C
config USB_DABUSB
tristate "DABUSB driver"
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index 8eaa88fd8b9..9a8dd8764c9 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <media/ir-common.h>
/* -------------------------------------------------------------------------- */
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index db753443587..f51e02fe365 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -1552,3 +1552,58 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_norwood);
+
+/* From reading the following remotes:
+ * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
+ * Hauppauge (from NOVA-CI-s box product)
+ * This is a "middle of the road" approach, differences are noted
+ */
+IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_0,
+ [ 0x01 ] = KEY_1,
+ [ 0x02 ] = KEY_2,
+ [ 0x03 ] = KEY_3,
+ [ 0x04 ] = KEY_4,
+ [ 0x05 ] = KEY_5,
+ [ 0x06 ] = KEY_6,
+ [ 0x07 ] = KEY_7,
+ [ 0x08 ] = KEY_8,
+ [ 0x09 ] = KEY_9,
+ [ 0x0a ] = KEY_ENTER,
+ [ 0x0b ] = KEY_RED,
+ [ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */
+ [ 0x0d ] = KEY_MUTE,
+ [ 0x0f ] = KEY_A, /* TV on Hauppauge */
+ [ 0x10 ] = KEY_VOLUMEUP,
+ [ 0x11 ] = KEY_VOLUMEDOWN,
+ [ 0x14 ] = KEY_B,
+ [ 0x1c ] = KEY_UP,
+ [ 0x1d ] = KEY_DOWN,
+ [ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */
+ [ 0x1f ] = KEY_BREAK,
+ [ 0x20 ] = KEY_CHANNELUP,
+ [ 0x21 ] = KEY_CHANNELDOWN,
+ [ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
+ [ 0x24 ] = KEY_RESTART,
+ [ 0x25 ] = KEY_OK,
+ [ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
+ [ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */
+ [ 0x29 ] = KEY_PAUSE,
+ [ 0x2b ] = KEY_RIGHT,
+ [ 0x2c ] = KEY_LEFT,
+ [ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */
+ [ 0x30 ] = KEY_SLOW,
+ [ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */
+ [ 0x32 ] = KEY_REWIND,
+ [ 0x34 ] = KEY_FASTFORWARD,
+ [ 0x35 ] = KEY_PLAY,
+ [ 0x36 ] = KEY_STOP,
+ [ 0x37 ] = KEY_RECORD,
+ [ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */
+ [ 0x3a ] = KEY_C,
+ [ 0x3c ] = KEY_EXIT,
+ [ 0x3d ] = KEY_POWER2,
+ [ 0x3e ] = KEY_TUNER,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 5297a365c92..8c85efc2652 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
saa7146_write(dev, I2C_TRANSFER, *dword);
dev->i2c_op = 1;
+ SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
saa7146_write(dev, MC2, (MASK_00 | MASK_16));
- wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
- if (signal_pending (current)) {
- /* a signal arrived */
- return -ERESTARTSYS;
+ timeout = HZ/100 + 1; /* 10ms */
+ timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+ if (timeout == -ERESTARTSYS || dev->i2c_op) {
+ SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+ SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+ if (timeout == -ERESTARTSYS)
+ /* a signal arrived */
+ return -ERESTARTSYS;
+
+ printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
+ return -EIO;
}
status = saa7146_read(dev, I2C_STATUS);
} else {
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index a0dcd59da76..79875958930 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_BCM3510 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
help
Support for the digital TV receiver chip made by B2C2 Inc. included in
Technisats PCI cards and USB boxes.
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index b8ba8786345..c2b35e36624 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -14,7 +14,7 @@
#include "stv0297.h"
#include "mt312.h"
#include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
#include "dvb-pll.h"
/* lnb control */
@@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
return request_firmware(fw, name, fc->dev);
}
-static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
-{
- struct flexcop_device *fc = fe->dvb->priv;
- return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
-}
-
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.demod_address = 0x59,
.demod_chip = LGDT3303,
@@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the air atsc 3nd generation (lgdt3303) */
if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC3;
- fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+ dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap);
info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
} else
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index ae2ff5dc238..dd66b60fbc9 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -1,13 +1,13 @@
config DVB_BT8XX
tristate "BT8xx based PCI cards"
depends on DVB_CORE && PCI && I2C && VIDEO_BT848
- select DVB_PLL
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_SP887X if !DVB_FE_CUSTOMISE
select DVB_NXT6000 if !DVB_FE_CUSTOMISE
select DVB_CX24110 if !DVB_FE_CUSTOMISE
select DVB_OR51211 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select FW_LOADER
help
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 240ad084fa7..50bc32a8bd5 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -480,7 +480,7 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
struct ca_msg *hw_buffer;
int result = 0;
- if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+ if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
return -ENOMEM;
}
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 14e69a736ed..3e35931af35 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -34,7 +34,6 @@
#include "dvb_frontend.h"
#include "dvb-bt8xx.h"
#include "bt878.h"
-#include "dvb-pll.h"
static int debug;
@@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = {
.demod_init = digitv_alps_tded4_demod_init,
};
-static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
- struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
- return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
-}
-
static struct lgdt330x_config tdvs_tua6034_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
@@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
lgdt330x_reset(card);
card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL) {
- card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
+ dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter);
dprintk ("dvb_bt8xx: lgdt330x detected\n");
}
break;
@@ -664,7 +657,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
case BTTV_BOARD_TWINHAN_DST:
/* DST is not a frontend driver !!! */
- state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+ state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
if (!state) {
printk("dvb_bt8xx: No memory\n");
break;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 4745a9017a1..e75f4173c05 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -37,7 +37,7 @@
#include "cx24110.h"
#include "or51211.h"
#include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
#include "zl10353.h"
struct dvb_bt8xx_card {
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 9123147e376..d64b96cb0c4 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 0);
+ input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
}
cinergyt2->rc_last_code = ~0;
@@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 1);
+ input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_last_code = rc_events[n].value;
}
}
@@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
{
struct input_dev *input_dev;
int i;
+ int err;
- cinergyt2->rc_input_dev = input_dev = input_allocate_device();
+ input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
@@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->keycodesize = 0;
input_dev->keycodemax = 0;
- input_register_device(cinergyt2->rc_input_dev);
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+
+ cinergyt2->rc_input_dev = input_dev;
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index ebf4dc5190f..76e9c36597e 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -605,7 +605,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
{ &utype, sizeof utype },
{ priv->ule_skb->data, priv->ule_skb->len - 4 }
};
- unsigned long ule_crc = ~0L, expected_crc;
+ u32 ule_crc = ~0L, expected_crc;
if (priv->ule_dbit) {
/* Set D-bit for CRC32 verification,
* if it was set originally. */
@@ -618,7 +618,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
*((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",
+ printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, 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);
#ifdef ULE_DEBUG
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index a263b3f3c21..ad52143602c 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -69,6 +69,8 @@ config DVB_USB_DIBUSB_MC
config DVB_USB_DIB0700
tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
depends on DVB_USB
+ select DVB_DIB7000P
+ select DVB_DIB7000M
select DVB_DIB3000MC
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
@@ -96,6 +98,7 @@ config DVB_USB_CXUSB
depends on DVB_USB
select DVB_CX22702 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
help
@@ -157,6 +160,17 @@ config DVB_USB_NOVA_T_USB2
help
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
+config DVB_USB_TTUSB2
+ tristate "Pinnacle 400e DVB-S USB2.0 support"
+ depends on DVB_USB
+ select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+ select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+ select DVB_TDA826X if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
+ firmware protocol used by this module is similar to the one used by the
+ old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
+
config DVB_USB_DTT200U
tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
depends on DVB_USB
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index e239107998e..154d593bbb0 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
dvb-usb-cxusb-objs = cxusb.o
obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
+dvb-usb-ttusb2-objs = ttusb2.o
+obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
+
dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index 2ed3eb62d78..a6c5f19f680 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
- .streaming_ctrl = dibusb2_0_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
-
- .frontend_attach = dibusb_dib3000mc_frontend_attach,
- .tuner_attach = dibusb_dib3000mc_tuner_attach,
-
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 7,
- .endpoint = 0x06,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+
+ .frontend_attach = dibusb_dib3000mc_frontend_attach,
+ .tuner_attach = dibusb_dib3000mc_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
},
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 43f39069ef3..15d12fce34d 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -14,12 +14,12 @@
* TODO: Use the cx25840-driver for the analogue part
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
- * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
+ * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
* Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation, version 2.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 2.
*
* see Documentation/dvb/README.dvb-usb for more information
*/
@@ -27,29 +27,29 @@
#include "cx22702.h"
#include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
#include "mt352.h"
#include "mt352_priv.h"
#include "zl10353.h"
/* debug */
int dvb_usb_cxusb_debug;
-module_param_named(debug,dvb_usb_cxusb_debug, int, 0644);
+module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
- u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+ u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
int wo = (rbuf == NULL || rlen == 0); /* write-only */
u8 sndbuf[1+wlen];
- memset(sndbuf,0,1+wlen);
+ memset(sndbuf, 0, 1+wlen);
sndbuf[0] = cmd;
- memcpy(&sndbuf[1],wbuf,wlen);
+ memcpy(&sndbuf[1], wbuf, wlen);
if (wo)
- dvb_usb_generic_write(d,sndbuf,1+wlen);
+ dvb_usb_generic_write(d, sndbuf, 1+wlen);
else
- dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0);
+ dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
return 0;
}
@@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
{
struct cxusb_state *st = d->priv;
- u8 o[2],i;
+ u8 o[2], i;
if (st->gpio_write_state[GPIO_TUNER] == onoff)
return;
o[0] = GPIO_TUNER;
o[1] = onoff;
- cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
+ cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
if (i != 0x01)
deb_info("gpio_write failed.\n");
@@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
}
/* I2C */
-static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i;
@@ -89,12 +90,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
if (d->udev->descriptor.idVendor == USB_VID_MEDION)
switch (msg[i].addr) {
- case 0x63:
- cxusb_gpio_tuner(d,0);
- break;
- default:
- cxusb_gpio_tuner(d,1);
- break;
+ case 0x63:
+ cxusb_gpio_tuner(d, 0);
+ break;
+ default:
+ cxusb_gpio_tuner(d, 1);
+ break;
}
/* read request */
@@ -103,26 +104,27 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
obuf[0] = msg[i].len;
obuf[1] = msg[i+1].len;
obuf[2] = msg[i].addr;
- memcpy(&obuf[3],msg[i].buf,msg[i].len);
+ memcpy(&obuf[3], msg[i].buf, msg[i].len);
if (cxusb_ctrl_msg(d, CMD_I2C_READ,
- obuf, 3+msg[i].len,
- ibuf, 1+msg[i+1].len) < 0)
+ obuf, 3+msg[i].len,
+ ibuf, 1+msg[i+1].len) < 0)
break;
if (ibuf[0] != 0x08)
deb_i2c("i2c read may have failed\n");
- memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
+ memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
i++;
} else { /* write */
u8 obuf[2+msg[i].len], ibuf;
obuf[0] = msg[i].addr;
obuf[1] = msg[i].len;
- memcpy(&obuf[2],msg[i].buf,msg[i].len);
+ memcpy(&obuf[2], msg[i].buf, msg[i].len);
- if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
+ if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf,
+ 2+msg[i].len, &ibuf,1) < 0)
break;
if (ibuf != 0x08)
deb_i2c("i2c write may have failed\n");
@@ -324,16 +326,8 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
-{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep);
-}
-
static struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
-
.output_mode = CX22702_PARALLEL_OUTPUT,
};
@@ -374,31 +368,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
{
- adap->pll_addr = 0x61;
- adap->pll_desc = &dvb_pll_thomson_dtt7579;
- adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+ NULL, &dvb_pll_thomson_dtt7579);
return 0;
}
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
{
- adap->pll_addr = 0x61;
- adap->pll_desc = &dvb_pll_lg_z201;
- adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201);
return 0;
}
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
{
- adap->pll_addr = 0x60;
- adap->pll_desc = &dvb_pll_thomson_dtt7579;
- adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ NULL, &dvb_pll_thomson_dtt7579);
return 0;
}
-static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap)
+static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
{
- adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
+ dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap);
return 0;
}
@@ -410,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
- if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL)
+ if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
+ &adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
@@ -423,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL)
+ if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
+ &adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
@@ -437,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL)
+ if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
+ &adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
@@ -450,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
- if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) ||
- ((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL))
+ if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
+ &adap->dev->i2c_adap)) != NULL) ||
+ ((adap->fe = dvb_attach(zl10353_attach,
+ &cxusb_zl10353_dee1601_config,
+ &adap->dev->i2c_adap)) != NULL))
return 0;
return -EIO;
@@ -463,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
*/
#define BLUEBIRD_01_ID_OFFSET 6638
-static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
+static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
+ const struct firmware *fw)
{
if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
return -EINVAL;
@@ -471,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
- fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
- fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
+ udev->descriptor.idProduct + 1;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
+ udev->descriptor.idProduct >> 8;
- return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
+ return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
}
return -EINVAL;
@@ -488,7 +487,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
static int cxusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+ const struct usb_device_id *id)
{
if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
@@ -502,20 +501,20 @@ static int cxusb_probe(struct usb_interface *intf,
}
static struct usb_device_id cxusb_table [] = {
- { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
- { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
- {} /* Terminating entry */
+ { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
+ {} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -529,20 +528,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_cx22702_frontend_attach,
- .tuner_attach = cxusb_fmd1216me_tuner_attach,
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 5,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_cx22702_frontend_attach,
+ .tuner_attach = cxusb_fmd1216me_tuner_attach,
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
},
},
@@ -575,21 +574,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_lgdt3303_frontend_attach,
- .tuner_attach = cxusb_lgdt3303_tuner_attach,
-
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 5,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_lgdt3303_frontend_attach,
+ .tuner_attach = cxusb_lgh064f_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
},
},
@@ -627,20 +626,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_dee1601_frontend_attach,
- .tuner_attach = cxusb_dee1601_tuner_attach,
- /* parameter for the MPEG2-data transfer */
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_dee1601_frontend_attach,
+ .tuner_attach = cxusb_dee1601_tuner_attach,
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 5,
- .endpoint = 0x04,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
},
},
@@ -686,21 +685,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
.num_adapters = 2,
.adapter = {
{
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_mt352_frontend_attach,
- .tuner_attach = cxusb_lgz201_tuner_attach,
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_mt352_frontend_attach,
+ .tuner_attach = cxusb_lgz201_tuner_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 5,
- .endpoint = 0x04,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
},
},
.power_ctrl = cxusb_bluebird_power_ctrl,
@@ -736,21 +735,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_mt352_frontend_attach,
- .tuner_attach = cxusb_dtt7579_tuner_attach,
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_mt352_frontend_attach,
+ .tuner_attach = cxusb_dtt7579_tuner_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 5,
- .endpoint = 0x04,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
},
},
.power_ctrl = cxusb_bluebird_power_ctrl,
@@ -776,7 +775,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
- .disconnect = dvb_usb_device_exit,
+ .disconnect = dvb_usb_device_exit,
.id_table = cxusb_table,
};
@@ -802,7 +801,7 @@ module_init (cxusb_module_init);
module_exit (cxusb_module_exit);
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
MODULE_VERSION("1.0-alpha");
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index ac84347f9d4..cda3adea24f 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug;
#define REQUEST_I2C_WRITE 0x3
#define REQUEST_POLL_RC 0x4
#define REQUEST_JUMPRAM 0x8
+#define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC
#define REQUEST_ENABLE_VIDEO 0xF
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
+#define REQUEST_GET_VERSION 0x15
struct dib0700_state {
u8 channel_state;
u16 mt2060_if1[2];
+
+ u8 is_dib7000pc;
};
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
+extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
extern struct i2c_algorithm dib0700_i2c_algo;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index dca6c698566..6a4d150784a 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = {
int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
struct dvb_usb_device_description **desc, int *cold)
{
- u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C
- *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3;
+ u8 b[16];
+ s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
+ REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
+
+ deb_info("FW GET_VERSION length: %d\n",ret);
+
+ *cold = ret <= 0;
deb_info("cold: %d\n", *cold);
return 0;
}
+static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
+ u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
+ u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
+{
+ u8 b[10];
+ b[0] = REQUEST_SET_CLOCK;
+ b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
+ b[2] = (pll_prediv >> 8) & 0xff; // MSB
+ b[3] = pll_prediv & 0xff; // LSB
+ b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
+ b[5] = pll_loopdiv & 0xff; // LSB
+ b[6] = (free_div >> 8) & 0xff; // MSB
+ b[7] = free_div & 0xff; // LSB
+ b[8] = (dsuScaler >> 8) & 0xff; // MSB
+ b[9] = dsuScaler & 0xff; // LSB
+
+ return dib0700_ctrl_wr(d, b, 10);
+}
+
+int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
+{
+ switch (clk_MHz) {
+ case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break;
+ default: return -EINVAL;
+ }
+ return 0;
+}
+
static int dib0700_jumpram(struct usb_device *udev, u32 address)
{
int ret, actlen;
@@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
/* start the firmware */
if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
info("firmware started successfully.");
- msleep(100);
+ msleep(500);
}
} else
ret = -EIO;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index e473bfed226..2208757d901 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -9,6 +9,8 @@
#include "dib0700.h"
#include "dib3000mc.h"
+#include "dib7000m.h"
+#include "dib7000p.h"
#include "mt2060.h"
static int force_lna_activation;
@@ -95,37 +97,189 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
}
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
-/*
-static struct mt2060_config stk7000p_mt2060_config = {
- 0x60
+static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
+ BAND_UHF | BAND_VHF, // band_caps
+
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+ * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+ (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+ 712, // inv_gain
+ 41, // time_stabiliz
+
+ 0, // alpha_level
+ 118, // thlock
+
+ 0, // wbd_inv
+ 4095, // wbd_ref
+ 0, // wbd_sel
+ 0, // wbd_alpha
+
+ 42598, // agc1_max
+ 17694, // agc1_min
+ 45875, // agc2_max
+ 2621, // agc2_min
+ 0, // agc1_pt1
+ 76, // agc1_pt2
+ 139, // agc1_pt3
+ 52, // agc1_slope1
+ 59, // agc1_slope2
+ 107, // agc2_pt1
+ 172, // agc2_pt2
+ 57, // agc2_slope1
+ 70, // agc2_slope2
+
+ 21, // alpha_mant
+ 25, // alpha_exp
+ 28, // beta_mant
+ 48, // beta_exp
+
+ 1, // perform_agc_softsplit
+ { 0, // split_min
+ 107, // split_max
+ 51800, // global_split_min
+ 24700 // global_split_max
+ },
+};
+
+static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
+ BAND_UHF | BAND_VHF,
+
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+ * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
+ (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+
+ 712, // inv_gain
+ 41, // time_stabiliz
+
+ 0, // alpha_level
+ 118, // thlock
+
+ 0, // wbd_inv
+ 4095, // wbd_ref
+ 0, // wbd_sel
+ 0, // wbd_alpha
+
+ 42598, // agc1_max
+ 16384, // agc1_min
+ 42598, // agc2_max
+ 0, // agc2_min
+
+ 0, // agc1_pt1
+ 137, // agc1_pt2
+ 255, // agc1_pt3
+
+ 0, // agc1_slope1
+ 255, // agc1_slope2
+
+ 0, // agc2_pt1
+ 0, // agc2_pt2
+
+ 0, // agc2_slope1
+ 41, // agc2_slope2
+
+ 15, // alpha_mant
+ 25, // alpha_exp
+
+ 28, // beta_mant
+ 48, // beta_exp
+
+ 0, // perform_agc_softsplit
+};
+
+static struct dibx000_bandwidth_config stk7700p_pll_config = {
+ 60000, 30000, // internal, sampling
+ 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
+ 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
+ (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
+ 60258167, // ifreq
+ 20452225, // timf
+};
+
+static struct dib7000m_config stk7700p_dib7000m_config = {
+ .dvbt_mode = 1,
+ .output_mpeg2_in_188_bytes = 1,
+ .quartz_direct = 1,
+
+ .agc_config_count = 1,
+ .agc = &stk7700p_7000m_mt2060_agc_config,
+ .bw = &stk7700p_pll_config,
+
+ .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
+};
+
+static struct dib7000p_config stk7700p_dib7000p_config = {
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc = &stk7700p_7000p_mt2060_agc_config,
+ .bw = &stk7700p_pll_config,
+
+ .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
};
-*/
static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_state *st = adap->dev->priv;
/* unless there is no real power management in DVB - we leave the device on GPIO6 */
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
- dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
+
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50);
+
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
+
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ st->mt2060_if1[0] = 1220;
+
+ if (dib7000pc_detection(&adap->dev->i2c_adap)) {
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+ st->is_dib7000pc = 1;
+ } else
+ adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
-// adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18);
- return 0;
+ return adap->fe == NULL ? -ENODEV : 0;
}
+static struct mt2060_config stk7700p_mt2060_config = {
+ 0x60
+};
+
static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
{
-// tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1);
-// return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1);
- return 0;
+ struct dib0700_state *st = adap->dev->priv;
+ struct i2c_adapter *tun_i2c;
+
+ if (st->is_dib7000pc)
+ tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ else
+ tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+
+ return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
+ st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
}
struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
+ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
+
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
+ { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
+ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -167,20 +321,32 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 3,
+ .num_device_descs = 6,
.devices = {
{ "DiBcom STK7700P reference design",
- { &dib0700_usb_id_table[0], NULL },
+ { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
{ NULL },
},
{ "Hauppauge Nova-T Stick",
- { &dib0700_usb_id_table[3], NULL },
+ { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL },
{ NULL },
},
{ "AVerMedia AVerTV DVB-T Volar",
- { &dib0700_usb_id_table[4], NULL },
+ { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] },
{ NULL },
},
+ { "Compro Videomate U500",
+ { &dib0700_usb_id_table[6], NULL },
+ { NULL },
+ },
+ { "Uniwill STK7700P based (Hama and others)",
+ { &dib0700_usb_id_table[7], NULL },
+ { NULL },
+ },
+ { "Leadtek Winfast DTV Dongle (STK7700P based)",
+ { &dib0700_usb_id_table[8], NULL },
+ { NULL },
+ }
}
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -202,7 +368,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.num_device_descs = 1,
.devices = {
{ "Hauppauge Nova-T 500 Dual DVB-T",
- { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL },
+ { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
{ NULL },
},
}
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 4fe363e4835..7a6ae8f482e 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
- .streaming_ctrl = dibusb_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
- .frontend_attach = dibusb_dib3000mb_frontend_attach,
- .tuner_attach = dibusb_tuner_probe_and_attach,
+ .streaming_ctrl = dibusb_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_tuner_probe_and_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
}
},
@@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
.pid_filter_count = 16,
- .streaming_ctrl = dibusb_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
- .frontend_attach = dibusb_dib3000mb_frontend_attach,
- .tuner_attach = dibusb_tuner_probe_and_attach,
+ .streaming_ctrl = dibusb_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_tuner_probe_and_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
},
},
@@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
- .streaming_ctrl = dibusb2_0_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
- .frontend_attach = dibusb_dib3000mb_frontend_attach,
- .tuner_attach = dibusb_thomson_tuner_attach,
- /* parameter for the MPEG2-data transfer */
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_thomson_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x06,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
}
},
@@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 16,
- .streaming_ctrl = dibusb2_0_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
- .frontend_attach = dibusb_dib3000mb_frontend_attach,
- .tuner_attach = dibusb_tuner_probe_and_attach,
- /* parameter for the MPEG2-data transfer */
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_tuner_probe_and_attach,
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x06,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index a0fd37efc04..e7ea3e753d6 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
- .streaming_ctrl = dibusb2_0_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
- .frontend_attach = dibusb_dib3000mc_frontend_attach,
- .tuner_attach = dibusb_dib3000mc_tuner_attach,
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .frontend_attach = dibusb_dib3000mc_frontend_attach,
+ .tuner_attach = dibusb_dib3000mc_tuner_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x06,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
}
},
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 8fb34375c1f..4a198d4755b 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = {
.num_adapters = 1,
.adapter = {
{
- .frontend_attach = digitv_frontend_attach,
- .tuner_attach = digitv_tuner_attach,
+ .frontend_attach = digitv_frontend_attach,
+ .tuner_attach = digitv_tuner_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
}
},
.identify_state = digitv_identify_state,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index fa43a41d753..7dbe1432101 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
.pid_filter_count = 15,
- .streaming_ctrl = dtt200u_streaming_ctrl,
- .pid_filter = dtt200u_pid_filter,
- .frontend_attach = dtt200u_frontend_attach,
- /* parameter for the MPEG2-data transfer */
+ .streaming_ctrl = dtt200u_streaming_ctrl,
+ .pid_filter = dtt200u_pid_filter,
+ .frontend_attach = dtt200u_frontend_attach,
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
}
},
.power_ctrl = dtt200u_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 4d6b069536c..299382dcb81 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -33,6 +33,7 @@
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
+#define USB_VID_UNIWILL 0x1584
#define USB_VID_WIDEVIEW 0x14aa
/* Product IDs */
@@ -46,6 +47,7 @@
#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
+#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
@@ -53,7 +55,9 @@
#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
#define USB_PID_DIBCOM_STK7700P 0x1e14
+#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
+#define USB_PID_UNIWILL_STK7700P 0x6003
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
@@ -97,7 +101,9 @@
#define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
-#define USB_PID_AVERMEDIA_VOLAR 0x1234
+#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
+#define USB_PID_AVERMEDIA_VOLAR 0xa807
+#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
#define USB_PID_NEBULA_DIGITV 0x0201
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
@@ -110,8 +116,8 @@
#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
-#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
-#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
@@ -125,7 +131,9 @@
#define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
+#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
#define USB_PID_GENPIX_8PSK_COLD 0x0200
#define USB_PID_GENPIX_8PSK_WARM 0x0201
+
#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 794e4471561..19ff5978bc9 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -90,7 +90,9 @@ schedule:
int dvb_usb_remote_init(struct dvb_usb_device *d)
{
+ struct input_dev *input_dev;
int i;
+ int err;
if (d->props.rc_key_map == NULL ||
d->props.rc_query == NULL ||
@@ -100,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
- d->rc_input_dev = input_allocate_device();
- if (!d->rc_input_dev)
+ input_dev = input_allocate_device();
+ if (!input_dev)
return -ENOMEM;
- d->rc_input_dev->evbit[0] = BIT(EV_KEY);
- d->rc_input_dev->keycodesize = sizeof(unsigned char);
- d->rc_input_dev->keycodemax = KEY_MAX;
- d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
- d->rc_input_dev->phys = d->rc_phys;
- usb_to_input_id(d->udev, &d->rc_input_dev->id);
- d->rc_input_dev->cdev.dev = &d->udev->dev;
+ input_dev->evbit[0] = BIT(EV_KEY);
+ input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodemax = KEY_MAX;
+ input_dev->name = "IR-receiver inside an USB DVB receiver";
+ input_dev->phys = d->rc_phys;
+ usb_to_input_id(d->udev, &input_dev->id);
+ input_dev->cdev.dev = &d->udev->dev;
/* set the bits for the keys */
deb_rc("key map size: %d\n", d->props.rc_key_map_size);
for (i = 0; i < d->props.rc_key_map_size; i++) {
- deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
- set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
+ deb_rc("setting bit for event %d item %d\n",
+ d->props.rc_key_map[i].event, i);
+ set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
}
/* Start the remote-control polling. */
@@ -124,10 +127,16 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
d->props.rc_interval = 100; /* default */
/* setting these two values to non-zero, we have to manage key repeats */
- d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
- d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
+ input_dev->rep[REP_PERIOD] = d->props.rc_interval;
+ input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
- input_register_device(d->rc_input_dev);
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+
+ d->rc_input_dev = input_dev;
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 7375eb20166..518d67fca5e 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = gp8psk_streaming_ctrl,
- .frontend_attach = gp8psk_frontend_attach,
- /* parameter for the MPEG2-data transfer */
+ .streaming_ctrl = gp8psk_streaming_ctrl,
+ .frontend_attach = gp8psk_frontend_attach,
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x82,
- .u = {
- .bulk = {
- .buffersize = 8192,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
}
},
.power_ctrl = gp8psk_power_ctrl,
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index a58874c790b..badc468170e 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -90,9 +90,11 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) {
- deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom);
if (haupp_rc_keys[i].data == data &&
haupp_rc_keys[i].custom == custom) {
+
+ deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom);
+
*event = haupp_rc_keys[i].event;
*state = REMOTE_KEY_PRESSED;
if (st->old_toggle == toggle) {
@@ -163,23 +165,23 @@ static struct dvb_usb_device_properties nova_t_properties = {
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
- .streaming_ctrl = dibusb2_0_streaming_ctrl,
- .pid_filter = dibusb_pid_filter,
- .pid_filter_ctrl = dibusb_pid_filter_ctrl,
- .frontend_attach = dibusb_dib3000mc_frontend_attach,
- .tuner_attach = dibusb_dib3000mc_tuner_attach,
-
- /* parameter for the MPEG2-data transfer */
- .stream = {
- .type = USB_BULK,
- .count = 7,
- .endpoint = 0x06,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .frontend_attach = dibusb_dib3000mc_frontend_attach,
+ .tuner_attach = dibusb_dib3000mc_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
}
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
new file mode 100644
index 00000000000..95d29976ed7
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -0,0 +1,270 @@
+/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
+ * (e.g. Pinnacle 400e DVB-S USB2.0).
+ *
+ * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
+ *
+ * TDA8263 + TDA10086
+ *
+ * I2C addresses:
+ * 0x08 - LNBP21PD - LNB power supply
+ * 0x0e - TDA10086 - Demodulator
+ * 0x50 - FX2 eeprom
+ * 0x60 - TDA8263 - Tuner
+ * 0x78 ???
+ *
+ * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
+ * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
+ * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#define DVB_USB_LOG_PREFIX "ttusb2"
+#include "dvb-usb.h"
+
+#include "ttusb2.h"
+
+#include "tda826x.h"
+#include "tda10086.h"
+#include "lnbp21.h"
+
+/* debug */
+static int dvb_usb_ttusb2_debug;
+#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
+module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+
+struct ttusb2_state {
+ u8 id;
+};
+
+static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
+ u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+ struct ttusb2_state *st = d->priv;
+ u8 s[wlen+4],r[64] = { 0 };
+ int ret = 0;
+
+ memset(s,0,wlen+4);
+
+ s[0] = 0xaa;
+ s[1] = ++st->id;
+ s[2] = cmd;
+ s[3] = wlen;
+ memcpy(&s[4],wbuf,wlen);
+
+ ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0);
+
+ if (ret != 0 ||
+ r[0] != 0x55 ||
+ r[1] != s[1] ||
+ r[2] != cmd ||
+ (rlen > 0 && r[3] != rlen)) {
+ warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
+ return -EIO;
+ }
+
+ if (rlen > 0)
+ memcpy(rbuf, &r[4], rlen);
+
+ return 0;
+}
+
+static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ static u8 obuf[60], ibuf[60];
+ int i,read;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 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++) {
+ read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
+
+ obuf[0] = (msg[i].addr << 1) | read;
+ obuf[1] = msg[i].len;
+
+ /* read request */
+ if (read)
+ obuf[2] = msg[i+1].len;
+ else
+ obuf[2] = 0;
+
+ memcpy(&obuf[3],msg[i].buf,msg[i].len);
+
+ if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
+ err("i2c transfer failed.");
+ break;
+ }
+
+ if (read) {
+ memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
+ i++;
+ }
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return i;
+}
+
+static u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm ttusb2_i2c_algo = {
+ .master_xfer = ttusb2_i2c_xfer,
+ .functionality = ttusb2_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int ttusb2_identify_state (struct usb_device *udev, struct
+ dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+ return 0;
+}
+
+static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 b = onoff;
+ ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
+ return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
+}
+
+
+static struct tda10086_config tda10086_config = {
+ .demod_address = 0x0e,
+ .invert = 0,
+};
+
+static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ if (usb_set_interface(adap->dev->udev,0,3) < 0)
+ err("set interface to alts=3 failed");
+
+ if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
+ deb_info("TDA10086 attach failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
+ deb_info("TDA8263 attach failed\n");
+ return -ENODEV;
+ }
+
+ if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
+ deb_info("LNBP21 attach failed\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties ttusb2_properties;
+
+static int ttusb2_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id ttusb2_table [] = {
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, ttusb2_table);
+
+static struct dvb_usb_device_properties ttusb2_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-pctv-400e-01.fw",
+
+ .size_of_priv = sizeof(struct ttusb2_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
+
+ .frontend_attach = ttusb2_frontend_attach,
+ .tuner_attach = ttusb2_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_ISOC,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .isoc = {
+ .framesperurb = 4,
+ .framesize = 940,
+ .interval = 1,
+ }
+ }
+ }
+ }
+ },
+
+ .power_ctrl = ttusb2_power_ctrl,
+ .identify_state = ttusb2_identify_state,
+
+ .i2c_algo = &ttusb2_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Pinnacle 400e DVB-S USB2.0",
+ { &ttusb2_table[0], NULL },
+ { NULL },
+ },
+ }
+};
+
+static struct usb_driver ttusb2_driver = {
+ .name = "dvb_usb_ttusb2",
+ .probe = ttusb2_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = ttusb2_table,
+};
+
+/* module stuff */
+static int __init ttusb2_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&ttusb2_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit ttusb2_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&ttusb2_driver);
+}
+
+module_init (ttusb2_module_init);
+module_exit (ttusb2_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h
new file mode 100644
index 00000000000..52a63af4089
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/ttusb2.h
@@ -0,0 +1,70 @@
+/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
+ * (e.g. Pinnacle 400e DVB-S USB2.0).
+ *
+ * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
+ * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
+ * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_TTUSB2_H_
+#define _DVB_USB_TTUSB2_H_
+
+/* TTUSB protocol
+ *
+ * always to messages (out/in)
+ * out message:
+ * 0xaa <id> <cmdbyte> <datalen> <data...>
+ *
+ * in message (complete block is always 0x40 bytes long)
+ * 0x55 <id> <cmdbyte> <datalen> <data...>
+ *
+ * id is incremented for each transaction
+ */
+
+#define CMD_DSP_DOWNLOAD 0x13
+/* out data: <byte>[28]
+ * last block must be empty */
+
+#define CMD_DSP_BOOT 0x14
+/* out data: nothing */
+
+#define CMD_POWER 0x15
+/* out data: <on=1/off=0> */
+
+#define CMD_LNB 0x16
+/* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */
+
+#define CMD_GET_VERSION 0x17
+/* in data: <version_byte>[5] */
+
+#define CMD_DISEQC 0x18
+/* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */
+
+#define CMD_PID_ENABLE 0x22
+/* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */
+
+#define CMD_PID_DISABLE 0x23
+/* out data: <index> */
+
+#define CMD_FILTER_ENABLE 0x24
+/* out data: <index> <pid_idx> <filter>[12] <mask>[12] */
+
+#define CMD_FILTER_DISABLE 0x25
+/* out data: <index> */
+
+#define CMD_GET_DSP_VERSION 0x26
+/* in data: <version_byte>[28] */
+
+#define CMD_I2C_XFER 0x31
+/* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen]
+ * in data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */
+
+#define CMD_I2C_BITRATE 0x32
+/* out data: <default=0> */
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index f9941ea88b3..f77b48f7658 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = {
.num_adapters = 1,
.adapter = {
{
- .streaming_ctrl = dibusb2_0_streaming_ctrl,
- .frontend_attach = umt_mt352_frontend_attach,
- .tuner_attach = umt_tuner_attach,
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .frontend_attach = umt_mt352_frontend_attach,
+ .tuner_attach = umt_tuner_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 20,
- .endpoint = 0x06,
- .u = {
- .bulk = {
- .buffersize = 512,
- }
- }
- },
+ .count = 20,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 512,
+ }
+ }
+ },
.size_of_priv = sizeof(struct dibusb_state),
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index 02bd61aaac6..16533b31a82 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = {
.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
.streaming_ctrl = vp702x_streaming_ctrl,
- .frontend_attach = vp702x_frontend_attach,
+ .frontend_attach = vp702x_frontend_attach,
- /* parameter for the MPEG2-data transfer */
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
.count = 10,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
.size_of_priv = sizeof(struct vp702x_state),
}
- },
+ },
.read_mac_address = vp702x_read_mac_addr,
.rc_key_map = vp702x_rc_keys,
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index b4cf002703a..69a46b3607a 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -125,7 +125,25 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = {
{ 0x00, 0x00, KEY_TAB }, /* Tab */
{ 0x00, 0x48, KEY_INFO }, /* Preview */
{ 0x00, 0x04, KEY_LIST }, /* RecordList */
- { 0x00, 0x0f, KEY_TEXT } /* Teletext */
+ { 0x00, 0x0f, KEY_TEXT }, /* Teletext */
+ { 0x00, 0x41, KEY_PREVIOUSSONG },
+ { 0x00, 0x42, KEY_NEXTSONG },
+ { 0x00, 0x4b, KEY_UP },
+ { 0x00, 0x51, KEY_DOWN },
+ { 0x00, 0x4e, KEY_LEFT },
+ { 0x00, 0x52, KEY_RIGHT },
+ { 0x00, 0x4f, KEY_ENTER },
+ { 0x00, 0x13, KEY_CANCEL },
+ { 0x00, 0x4a, KEY_CLEAR },
+ { 0x00, 0x54, KEY_PRINT }, /* Capture */
+ { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */
+ { 0x00, 0x08, KEY_VIDEO }, /* A/V */
+ { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */
+ { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */
+ { 0x00, 0x18, KEY_RED},
+ { 0x00, 0x53, KEY_GREEN},
+ { 0x00, 0x5e, KEY_YELLOW},
+ { 0x00, 0x5f, KEY_BLUE}
};
static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@@ -217,18 +235,18 @@ static struct dvb_usb_device_properties vp7045_properties = {
.num_adapters = 1,
.adapter = {
{
- .frontend_attach = vp7045_frontend_attach,
- /* parameter for the MPEG2-data transfer */
+ .frontend_attach = vp7045_frontend_attach,
+ /* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 7,
- .endpoint = 0x02,
- .u = {
- .bulk = {
- .buffersize = 4096,
- }
- }
- },
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
}
},
.power_ctrl = vp7045_power_ctrl,
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index aebb8d6f26f..af314bb1dca 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -172,6 +172,22 @@ config DVB_DIB3000MC
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
+config DVB_DIB7000M
+ tristate "DiBcom 7000MA/MB/PA/PB/MC"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+ to support this frontend.
+
+config DVB_DIB7000P
+ tristate "DiBcom 7000PC"
+ depends on DVB_CORE && I2C
+ default m if DVB_FE_CUSTOMISE
+ help
+ A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+ to support this frontend.
+
comment "DVB-C (cable) frontends"
depends on DVB_CORE
@@ -281,6 +297,14 @@ config DVB_TUNER_MT2060
help
A driver for the silicon IF tuner MT2060 from Microtune.
+config DVB_TUNER_LGH06XF
+ tristate "LG TDVS-H06xF ATSC tuner"
+ depends on DVB_CORE && I2C
+ select DVB_PLL
+ default m if DVB_FE_CUSTOMISE
+ help
+ A driver for the LG TDVS-H06xF ATSC tuner family.
+
comment "Miscellaneous devices"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index dce9cf0c75c..3fa6e5d32a9 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
obj-$(CONFIG_DVB_MT312) += mt312.o
obj-$(CONFIG_DVB_VES1820) += ves1820.o
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
@@ -37,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 3561a777568..23aa75a27c1 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000
/* a channel for autosearch */
- reg = 0;
- if (chan->nfft == -1 && chan->guard == -1) reg = 7;
- if (chan->nfft == -1 && chan->guard != -1) reg = 2;
- if (chan->nfft != -1 && chan->guard == -1) reg = 3;
-
fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
- dib3000mc_set_channel_cfg(state, &fchan, reg);
+ dib3000mc_set_channel_cfg(state, &fchan, 11);
reg = dib3000mc_read_word(state, 0);
dib3000mc_write_word(state, 0, reg | (1 << 8));
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
new file mode 100644
index 00000000000..f5d40aa3d27
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -0,0 +1,1191 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB7000M and
+ * first generation DiB7000P-demodulator-family.
+ *
+ * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib7000m.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0)
+
+struct dib7000m_state {
+ struct dvb_frontend demod;
+ struct dib7000m_config cfg;
+
+ u8 i2c_addr;
+ struct i2c_adapter *i2c_adap;
+
+ struct dibx000_i2c_master i2c_master;
+
+/* offset is 1 in case of the 7000MC */
+ u8 reg_offs;
+
+ u16 wbd_ref;
+
+ u8 current_band;
+ fe_bandwidth_t current_bandwidth;
+ struct dibx000_agc_config *current_agc;
+ u32 timf;
+
+ u16 revision;
+};
+
+enum dib7000m_power_mode {
+ DIB7000M_POWER_ALL = 0,
+
+ DIB7000M_POWER_NO,
+ DIB7000M_POWER_INTERF_ANALOG_AGC,
+ DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
+ DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
+ DIB7000M_POWER_INTERFACE_ONLY,
+};
+
+static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+{
+ u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+ u8 rb[2];
+ struct i2c_msg msg[2] = {
+ { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
+ { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+ };
+
+ if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+ dprintk("i2c read error on %d\n",reg);
+
+ return (rb[0] << 8) | rb[1];
+}
+
+static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+{
+ u8 b[4] = {
+ (reg >> 8) & 0xff, reg & 0xff,
+ (val >> 8) & 0xff, val & 0xff,
+ };
+ struct i2c_msg msg = {
+ .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+ };
+ return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
+{
+ int ret = 0;
+ u16 outreg, fifo_threshold, smo_mode,
+ sram = 0x0005; /* by default SRAM output is disabled */
+
+ outreg = 0;
+ fifo_threshold = 1792;
+ smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
+
+ dprintk("-I- Setting output mode for demod %p to %d\n",
+ &state->demod, mode);
+
+ switch (mode) {
+ case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
+ outreg = (1 << 10); /* 0x0400 */
+ break;
+ case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
+ outreg = (1 << 10) | (1 << 6); /* 0x0440 */
+ break;
+ case OUTMODE_MPEG2_SERIAL: // STBs with serial input
+ outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
+ break;
+ case OUTMODE_DIVERSITY:
+ if (state->cfg.hostbus_diversity)
+ outreg = (1 << 10) | (4 << 6); /* 0x0500 */
+ else
+ sram |= 0x0c00;
+ break;
+ case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
+ smo_mode |= (3 << 1);
+ fifo_threshold = 512;
+ outreg = (1 << 10) | (5 << 6);
+ break;
+ case OUTMODE_HIGH_Z: // disable
+ outreg = 0;
+ break;
+ default:
+ dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+ break;
+ }
+
+ if (state->cfg.output_mpeg2_in_188_bytes)
+ smo_mode |= (1 << 5) ;
+
+ ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode);
+ ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */
+ ret |= dib7000m_write_word(state, 1795, outreg);
+ ret |= dib7000m_write_word(state, 1805, sram);
+
+ return ret;
+}
+
+static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
+{
+ /* by default everything is going to be powered off */
+ u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
+
+ /* now, depending on the requested mode, we power on */
+ switch (mode) {
+ /* power up everything in the demod */
+ case DIB7000M_POWER_ALL:
+ reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
+ break;
+
+ /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
+ case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
+ reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
+ break;
+
+ case DIB7000M_POWER_INTERF_ANALOG_AGC:
+ reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
+ reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
+ reg_906 &= ~((1 << 0));
+ break;
+
+ case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
+ reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
+ break;
+
+ case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
+ reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
+ break;
+ case DIB7000M_POWER_NO:
+ break;
+ }
+
+ /* always power down unused parts */
+ if (!state->cfg.mobile_mode)
+ reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
+
+ /* P_sdio_select_clk = 0 on MC */
+ if (state->revision != 0x4000)
+ reg_906 <<= 1;
+
+ dib7000m_write_word(state, 903, reg_903);
+ dib7000m_write_word(state, 904, reg_904);
+ dib7000m_write_word(state, 905, reg_905);
+ dib7000m_write_word(state, 906, reg_906);
+
+ return 0;
+}
+
+static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
+{
+ int ret = 0;
+ u16 reg_913 = dib7000m_read_word(state, 913),
+ reg_914 = dib7000m_read_word(state, 914);
+
+ switch (no) {
+ case DIBX000_SLOW_ADC_ON:
+ reg_914 |= (1 << 1) | (1 << 0);
+ ret |= dib7000m_write_word(state, 914, reg_914);
+ reg_914 &= ~(1 << 1);
+ break;
+
+ case DIBX000_SLOW_ADC_OFF:
+ reg_914 |= (1 << 1) | (1 << 0);
+ break;
+
+ case DIBX000_ADC_ON:
+ if (state->revision == 0x4000) { // workaround for PA/MA
+ // power-up ADC
+ dib7000m_write_word(state, 913, 0);
+ dib7000m_write_word(state, 914, reg_914 & 0x3);
+ // power-down bandgag
+ dib7000m_write_word(state, 913, (1 << 15));
+ dib7000m_write_word(state, 914, reg_914 & 0x3);
+ }
+
+ reg_913 &= 0x0fff;
+ reg_914 &= 0x0003;
+ break;
+
+ case DIBX000_ADC_OFF: // leave the VBG voltage on
+ reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
+ reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+ break;
+
+ case DIBX000_VBG_ENABLE:
+ reg_913 &= ~(1 << 15);
+ break;
+
+ case DIBX000_VBG_DISABLE:
+ reg_913 |= (1 << 15);
+ break;
+
+ default:
+ break;
+ }
+
+// dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914);
+
+ ret |= dib7000m_write_word(state, 913, reg_913);
+ ret |= dib7000m_write_word(state, 914, reg_914);
+
+ return ret;
+}
+
+static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+ u32 timf;
+
+ // store the current bandwidth for later use
+ state->current_bandwidth = bw_idx;
+
+ if (state->timf == 0) {
+ dprintk("-D- Using default timf\n");
+ timf = state->cfg.bw->timf;
+ } else {
+ dprintk("-D- Using updated timf\n");
+ timf = state->timf;
+ }
+
+ timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80;
+
+ dib7000m_write_word(state, 23, (timf >> 16) & 0xffff);
+ dib7000m_write_word(state, 24, (timf ) & 0xffff);
+
+ return 0;
+}
+
+static int dib7000m_sad_calib(struct dib7000m_state *state)
+{
+
+/* internal */
+// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+ dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
+ dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
+
+ /* do the calibration */
+ dib7000m_write_word(state, 929, (1 << 0));
+ dib7000m_write_word(state, 929, (0 << 0));
+
+ msleep(1);
+
+ return 0;
+}
+
+static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
+{
+ dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff);
+ dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff);
+ dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff);
+ dib7000m_write_word(state, 22, bw->ifreq & 0xffff);
+
+ dib7000m_write_word(state, 928, bw->sad_cfg);
+}
+
+static void dib7000m_reset_pll(struct dib7000m_state *state)
+{
+ const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+ u16 reg_907,reg_910;
+
+ /* default */
+ reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
+ (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
+ (bw->enable_refdiv << 1) | (0 << 0);
+ reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
+
+ // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
+ // this is only working only for 30 MHz crystals
+ if (!state->cfg.quartz_direct) {
+ reg_910 |= (1 << 5); // forcing the predivider to 1
+
+ // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
+ if(state->cfg.input_clk_is_div_2)
+ reg_907 |= (16 << 9);
+ else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
+ reg_907 |= (8 << 9);
+ } else {
+ reg_907 |= (bw->pll_ratio & 0x3f) << 9;
+ reg_910 |= (bw->pll_prediv << 5);
+ }
+
+ dib7000m_write_word(state, 910, reg_910); // pll cfg
+ dib7000m_write_word(state, 907, reg_907); // clk cfg0
+ dib7000m_write_word(state, 908, 0x0006); // clk_cfg1
+
+ dib7000m_reset_pll_common(state, bw);
+}
+
+static void dib7000mc_reset_pll(struct dib7000m_state *state)
+{
+ const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+
+ // clk_cfg0
+ dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
+
+ // clk_cfg1
+ //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
+ dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) |
+ (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
+ (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0));
+
+ // smpl_cfg
+ dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
+
+ dib7000m_reset_pll_common(state, bw);
+}
+
+static int dib7000m_reset_gpio(struct dib7000m_state *st)
+{
+ /* reset the GPIOs */
+ dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",
+ st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos);
+
+ dib7000m_write_word(st, 773, st->cfg.gpio_dir);
+ dib7000m_write_word(st, 774, st->cfg.gpio_val);
+
+ /* TODO 782 is P_gpio_od */
+
+ dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
+
+ dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
+ return 0;
+}
+
+static int dib7000m_demod_reset(struct dib7000m_state *state)
+{
+ dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
+
+ /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
+ dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+ /* restart all parts */
+ dib7000m_write_word(state, 898, 0xffff);
+ dib7000m_write_word(state, 899, 0xffff);
+ dib7000m_write_word(state, 900, 0xff0f);
+ dib7000m_write_word(state, 901, 0xfffc);
+
+ dib7000m_write_word(state, 898, 0);
+ dib7000m_write_word(state, 899, 0);
+ dib7000m_write_word(state, 900, 0);
+ dib7000m_write_word(state, 901, 0);
+
+ if (state->revision == 0x4000)
+ dib7000m_reset_pll(state);
+ else
+ dib7000mc_reset_pll(state);
+
+ if (dib7000m_reset_gpio(state) != 0)
+ dprintk("-E- GPIO reset was not successful.\n");
+
+ if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+ dprintk("-E- OUTPUT_MODE could not be resetted.\n");
+
+ /* unforce divstr regardless whether i2c enumeration was done or not */
+ dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
+
+ dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+
+ dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+ dib7000m_sad_calib(state);
+ dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+
+ dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
+
+ return 0;
+}
+
+static void dib7000m_restart_agc(struct dib7000m_state *state)
+{
+ // P_restart_iqc & P_restart_agc
+ dib7000m_write_word(state, 898, 0x0c00);
+ dib7000m_write_word(state, 898, 0x0000);
+}
+
+static int dib7000m_agc_soft_split(struct dib7000m_state *state)
+{
+ u16 agc,split_offset;
+
+ if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
+ return 0;
+
+ // n_agc_global
+ agc = dib7000m_read_word(state, 390);
+
+ if (agc > state->current_agc->split.min_thres)
+ split_offset = state->current_agc->split.min;
+ else if (agc < state->current_agc->split.max_thres)
+ split_offset = state->current_agc->split.max;
+ else
+ split_offset = state->current_agc->split.max *
+ (agc - state->current_agc->split.min_thres) /
+ (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
+
+ dprintk("AGC split_offset: %d\n",split_offset);
+
+ // P_agc_force_split and P_agc_split_offset
+ return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
+}
+
+static int dib7000m_update_lna(struct dib7000m_state *state)
+{
+ int i;
+ u16 dyn_gain;
+
+ // when there is no LNA to program return immediatly
+ if (state->cfg.update_lna == NULL)
+ return 0;
+
+ msleep(60);
+ for (i = 0; i < 20; i++) {
+ // read dyn_gain here (because it is demod-dependent and not tuner)
+ dyn_gain = dib7000m_read_word(state, 390);
+
+ dprintk("agc global: %d\n", dyn_gain);
+
+ if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
+ dib7000m_restart_agc(state);
+ msleep(60);
+ } else
+ break;
+ }
+ return 0;
+}
+
+static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
+{
+ struct dibx000_agc_config *agc = NULL;
+ int i;
+ if (state->current_band == band)
+ return;
+ state->current_band = band;
+
+ for (i = 0; i < state->cfg.agc_config_count; i++)
+ if (state->cfg.agc[i].band_caps & band) {
+ agc = &state->cfg.agc[i];
+ break;
+ }
+
+ if (agc == NULL) {
+ dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band);
+ return;
+ }
+
+ state->current_agc = agc;
+
+ /* AGC */
+ dib7000m_write_word(state, 72 , agc->setup);
+ dib7000m_write_word(state, 73 , agc->inv_gain);
+ dib7000m_write_word(state, 74 , agc->time_stabiliz);
+ dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
+
+ // Demod AGC loop configuration
+ dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
+ dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
+
+ dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
+ state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+ /* AGC continued */
+ if (state->wbd_ref != 0)
+ dib7000m_write_word(state, 102, state->wbd_ref);
+ else // use default
+ dib7000m_write_word(state, 102, agc->wbd_ref);
+
+ dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
+ dib7000m_write_word(state, 104, agc->agc1_max);
+ dib7000m_write_word(state, 105, agc->agc1_min);
+ dib7000m_write_word(state, 106, agc->agc2_max);
+ dib7000m_write_word(state, 107, agc->agc2_min);
+ dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
+ dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+ dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+ dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+ if (state->revision > 0x4000) { // settings for the MC
+ dib7000m_write_word(state, 71, agc->agc1_pt3);
+// dprintk("-D- 929: %x %d %d\n",
+// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
+ dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
+ } else {
+ // wrong default values
+ u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
+ for (i = 0; i < 9; i++)
+ dib7000m_write_word(state, 88 + i, b[i]);
+ }
+}
+
+static void dib7000m_update_timf_freq(struct dib7000m_state *state)
+{
+ u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
+ state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100);
+ dib7000m_write_word(state, 23, (u16) (timf >> 16));
+ dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
+ dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf);
+}
+
+static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq)
+{
+ u16 value, est[4];
+
+ dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz));
+
+ /* nfft, guard, qam, alpha */
+ dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha));
+ dib7000m_write_word(state, 5, (seq << 4));
+
+ /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */
+ value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1);
+ if (ch->vit_hrch == 0 || ch->vit_select_hp == 1)
+ value |= (ch->vit_code_rate_hp << 1);
+ else
+ value |= (ch->vit_code_rate_lp << 1);
+ dib7000m_write_word(state, 267 + state->reg_offs, value);
+
+ /* offset loop parameters */
+
+ /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
+ dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
+
+ /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+ dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+ /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
+ dib7000m_write_word(state, 32, (0 << 4) | 0x3);
+
+ /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
+ dib7000m_write_word(state, 33, (0 << 4) | 0x5);
+
+ /* P_dvsy_sync_wait */
+ switch (ch->nfft) {
+ case 1: value = 256; break;
+ case 2: value = 128; break;
+ case 0:
+ default: value = 64; break;
+ }
+ value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin
+ value <<= 4;
+
+ /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
+ /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+ if (ch->intlv_native || state->revision > 0x4000)
+ value |= (1 << 2) | (2 << 0);
+ else
+ value |= 0;
+ dib7000m_write_word(state, 266 + state->reg_offs, value);
+
+ /* channel estimation fine configuration */
+ switch (ch->nqam) {
+ case 2:
+ est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
+ est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
+ est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
+ est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
+ break;
+ case 1:
+ est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
+ est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
+ est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
+ est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
+ break;
+ default:
+ est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
+ est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
+ est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
+ est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
+ break;
+ }
+ for (value = 0; value < 4; value++)
+ dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
+
+ // set power-up level: interf+analog+AGC
+ dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
+ dib7000m_set_adc_state(state, DIBX000_ADC_ON);
+
+ msleep(7);
+
+ //AGC initialization
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 1);
+
+ dib7000m_restart_agc(state);
+
+ // wait AGC rough lock time
+ msleep(5);
+
+ dib7000m_update_lna(state);
+ dib7000m_agc_soft_split(state);
+
+ // wait AGC accurate lock time
+ msleep(7);
+
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 0);
+
+ // set power-up level: autosearch
+ dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
+}
+
+static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+ struct dibx000_ofdm_channel auto_ch;
+ int ret = 0;
+ u32 value;
+
+ INIT_OFDM_CHANNEL(&auto_ch);
+ auto_ch.RF_kHz = ch->RF_kHz;
+ auto_ch.Bw = ch->Bw;
+ auto_ch.nqam = 2;
+ auto_ch.guard = 0;
+ auto_ch.nfft = 1;
+ auto_ch.vit_alpha = 1;
+ auto_ch.vit_select_hp = 1;
+ auto_ch.vit_code_rate_hp = 2;
+ auto_ch.vit_code_rate_lp = 3;
+ auto_ch.vit_hrch = 0;
+ auto_ch.intlv_native = 1;
+
+ dib7000m_set_channel(state, &auto_ch, 7);
+
+ // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
+ value = 30 * state->cfg.bw->internal;
+ ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
+ ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
+ value = 100 * state->cfg.bw->internal;
+ ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
+ ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
+ value = 500 * state->cfg.bw->internal;
+ ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
+ ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
+
+ // start search
+ value = dib7000m_read_word(state, 0);
+ ret |= dib7000m_write_word(state, 0, value | (1 << 9));
+
+ /* clear n_irq_pending */
+ if (state->revision == 0x4000)
+ dib7000m_write_word(state, 1793, 0);
+ else
+ dib7000m_read_word(state, 537);
+
+ ret |= dib7000m_write_word(state, 0, (u16) value);
+
+ return ret;
+}
+
+static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
+{
+ u16 irq_pending = dib7000m_read_word(state, reg);
+
+ if (irq_pending & 0x1) { // failed
+ dprintk("#\n");
+ return 1;
+ }
+
+ if (irq_pending & 0x2) { // succeeded
+ dprintk("!\n");
+ return 2;
+ }
+ return 0; // still pending
+}
+
+static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+ if (state->revision == 0x4000)
+ return dib7000m_autosearch_irq(state, 1793);
+ else
+ return dib7000m_autosearch_irq(state, 537);
+}
+
+static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+ int ret = 0;
+ u16 value;
+
+ // we are already tuned - just resuming from suspend
+ if (ch != NULL)
+ dib7000m_set_channel(state, ch, 0);
+ else
+ return -EINVAL;
+
+ // restart demod
+ ret |= dib7000m_write_word(state, 898, 0x4000);
+ ret |= dib7000m_write_word(state, 898, 0x0000);
+ msleep(45);
+
+ ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
+ /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+ ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+ // never achieved a lock with that bandwidth so far - wait for timfreq to update
+ if (state->timf == 0)
+ msleep(200);
+
+ //dump_reg(state);
+ /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
+ value = (6 << 8) | 0x80;
+ switch (ch->nfft) {
+ case 0: value |= (7 << 12); break;
+ case 1: value |= (9 << 12); break;
+ case 2: value |= (8 << 12); break;
+ }
+ ret |= dib7000m_write_word(state, 26, value);
+
+ /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
+ value = (0 << 4);
+ switch (ch->nfft) {
+ case 0: value |= 0x6; break;
+ case 1: value |= 0x8; break;
+ case 2: value |= 0x7; break;
+ }
+ ret |= dib7000m_write_word(state, 32, value);
+
+ /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
+ value = (0 << 4);
+ switch (ch->nfft) {
+ case 0: value |= 0x6; break;
+ case 1: value |= 0x8; break;
+ case 2: value |= 0x7; break;
+ }
+ ret |= dib7000m_write_word(state, 33, value);
+
+ // we achieved a lock - it's time to update the osc freq
+ if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
+ dib7000m_update_timf_freq(state);
+
+ return ret;
+}
+
+static int dib7000m_init(struct dvb_frontend *demod)
+{
+ struct dib7000m_state *state = demod->demodulator_priv;
+ int ret = 0;
+ u8 o = state->reg_offs;
+
+ dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
+
+ if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
+ dprintk("-E- could not start Slow ADC\n");
+
+ if (state->cfg.dvbt_mode)
+ dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
+
+ if (state->cfg.mobile_mode)
+ ret |= dib7000m_write_word(state, 261 + o, 2);
+ else
+ ret |= dib7000m_write_word(state, 224 + o, 1);
+
+ ret |= dib7000m_write_word(state, 173 + o, 0);
+ ret |= dib7000m_write_word(state, 174 + o, 0);
+ ret |= dib7000m_write_word(state, 175 + o, 0);
+ ret |= dib7000m_write_word(state, 176 + o, 0);
+ ret |= dib7000m_write_word(state, 177 + o, 0);
+ ret |= dib7000m_write_word(state, 178 + o, 0);
+ ret |= dib7000m_write_word(state, 179 + o, 0);
+ ret |= dib7000m_write_word(state, 180 + o, 0);
+
+ // P_corm_thres Lock algorithms configuration
+ ret |= dib7000m_write_word(state, 26, 0x6680);
+
+ // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
+ ret |= dib7000m_write_word(state, 170 + o, 0x0410);
+ // P_fft_nb_to_cut
+ ret |= dib7000m_write_word(state, 182 + o, 8192);
+ // P_pha3_thres
+ ret |= dib7000m_write_word(state, 195 + o, 0x0ccd);
+ // P_cti_use_cpe, P_cti_use_prog
+ ret |= dib7000m_write_word(state, 196 + o, 0);
+ // P_cspu_regul, P_cspu_win_cut
+ ret |= dib7000m_write_word(state, 205 + o, 0x200f);
+ // P_adp_regul_cnt
+ ret |= dib7000m_write_word(state, 214 + o, 0x023d);
+ // P_adp_noise_cnt
+ ret |= dib7000m_write_word(state, 215 + o, 0x00a4);
+ // P_adp_regul_ext
+ ret |= dib7000m_write_word(state, 216 + o, 0x00a4);
+ // P_adp_noise_ext
+ ret |= dib7000m_write_word(state, 217 + o, 0x7ff0);
+ // P_adp_fil
+ ret |= dib7000m_write_word(state, 218 + o, 0x3ccc);
+
+ // P_2d_byp_ti_num
+ ret |= dib7000m_write_word(state, 226 + o, 0);
+
+ // P_fec_*
+ ret |= dib7000m_write_word(state, 281 + o, 0x0010);
+ // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+ ret |= dib7000m_write_word(state, 294 + o,0x0062);
+
+ // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
+ if(state->cfg.tuner_is_baseband)
+ ret |= dib7000m_write_word(state, 36, 0x0755);
+ else
+ ret |= dib7000m_write_word(state, 36, 0x1f55);
+
+ // auto search configuration
+ ret |= dib7000m_write_word(state, 2, 0x0004);
+ ret |= dib7000m_write_word(state, 3, 0x1000);
+ ret |= dib7000m_write_word(state, 4, 0x0814);
+ ret |= dib7000m_write_word(state, 6, 0x001b);
+ ret |= dib7000m_write_word(state, 7, 0x7740);
+ ret |= dib7000m_write_word(state, 8, 0x005b);
+ ret |= dib7000m_write_word(state, 9, 0x8d80);
+ ret |= dib7000m_write_word(state, 10, 0x01c9);
+ ret |= dib7000m_write_word(state, 11, 0xc380);
+ ret |= dib7000m_write_word(state, 12, 0x0000);
+ ret |= dib7000m_write_word(state, 13, 0x0080);
+ ret |= dib7000m_write_word(state, 14, 0x0000);
+ ret |= dib7000m_write_word(state, 15, 0x0090);
+ ret |= dib7000m_write_word(state, 16, 0x0001);
+ ret |= dib7000m_write_word(state, 17, 0xd4c0);
+ ret |= dib7000m_write_word(state, 263 + o,0x0001);
+
+ // P_divclksel=3 P_divbitsel=1
+ if (state->revision == 0x4000)
+ dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
+ else
+ dib7000m_write_word(state, 909, (3 << 4) | 1);
+
+ // Tuner IO bank: max drive (14mA)
+ ret |= dib7000m_write_word(state, 912 ,0x2c8a);
+
+ ret |= dib7000m_write_word(state, 1817, 1);
+
+ return ret;
+}
+
+static int dib7000m_sleep(struct dvb_frontend *demod)
+{
+ struct dib7000m_state *st = demod->demodulator_priv;
+ dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
+ return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) |
+ dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
+ dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
+}
+
+static int dib7000m_identify(struct dib7000m_state *state)
+{
+ u16 value;
+ if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
+ dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value);
+ return -EREMOTEIO;
+ }
+
+ state->revision = dib7000m_read_word(state, 897);
+ if (state->revision != 0x4000 &&
+ state->revision != 0x4001 &&
+ state->revision != 0x4002) {
+ dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value);
+ return -EREMOTEIO;
+ }
+
+ /* protect this driver to be used with 7000PC */
+ if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
+ dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n");
+ return -EREMOTEIO;
+ }
+
+ switch (state->revision) {
+ case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break;
+ case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break;
+ case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break;
+ }
+
+ return 0;
+}
+
+
+static int dib7000m_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dib7000m_state *state = fe->demodulator_priv;
+ u16 tps = dib7000m_read_word(state,480);
+
+ fep->inversion = INVERSION_AUTO;
+
+ fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+ switch ((tps >> 8) & 0x3) {
+ case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+ case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+ /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+ }
+
+ switch (tps & 0x3) {
+ case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+ case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+ case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+ case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+ }
+
+ switch ((tps >> 14) & 0x3) {
+ case 0: fep->u.ofdm.constellation = QPSK; break;
+ case 1: fep->u.ofdm.constellation = QAM_16; break;
+ case 2:
+ default: fep->u.ofdm.constellation = QAM_64; break;
+ }
+
+ /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+ /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
+
+ fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ switch ((tps >> 5) & 0x7) {
+ case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+ case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+ case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+ case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+ case 7:
+ default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+ }
+
+ switch ((tps >> 2) & 0x7) {
+ case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+ case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+ case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+ case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+ case 7:
+ default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+ }
+
+ /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
+
+ return 0;
+}
+
+static int dib7000m_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dib7000m_state *state = fe->demodulator_priv;
+ struct dibx000_ofdm_channel ch;
+
+ INIT_OFDM_CHANNEL(&ch);
+ FEP2DIB(fep,&ch);
+
+ state->current_bandwidth = fep->u.ofdm.bandwidth;
+ dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe, fep);
+
+ if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
+ fep->u.ofdm.constellation == QAM_AUTO ||
+ fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ int i = 800, found;
+
+ dib7000m_autosearch_start(fe, &ch);
+ do {
+ msleep(1);
+ found = dib7000m_autosearch_is_irq(fe);
+ } while (found == 0 && i--);
+
+ dprintk("autosearch returns: %d\n",found);
+ if (found == 0 || found == 1)
+ return 0; // no channel found
+
+ dib7000m_get_frontend(fe, fep);
+ FEP2DIB(fep, &ch);
+ }
+
+ /* make this a config parameter */
+ dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+ return dib7000m_tune(fe, &ch);
+}
+
+static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+ struct dib7000m_state *state = fe->demodulator_priv;
+ u16 lock = dib7000m_read_word(state, 535);
+
+ *stat = 0;
+
+ if (lock & 0x8000)
+ *stat |= FE_HAS_SIGNAL;
+ if (lock & 0x3000)
+ *stat |= FE_HAS_CARRIER;
+ if (lock & 0x0100)
+ *stat |= FE_HAS_VITERBI;
+ if (lock & 0x0010)
+ *stat |= FE_HAS_SYNC;
+ if (lock & 0x0008)
+ *stat |= FE_HAS_LOCK;
+
+ return 0;
+}
+
+static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct dib7000m_state *state = fe->demodulator_priv;
+ *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
+ return 0;
+}
+
+static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+ struct dib7000m_state *state = fe->demodulator_priv;
+ *unc = dib7000m_read_word(state, 534);
+ return 0;
+}
+
+static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct dib7000m_state *state = fe->demodulator_priv;
+ u16 val = dib7000m_read_word(state, 390);
+ *strength = 65535 - val;
+ return 0;
+}
+
+static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ *snr = 0x0000;
+ return 0;
+}
+
+static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void dib7000m_release(struct dvb_frontend *demod)
+{
+ struct dib7000m_state *st = demod->demodulator_priv;
+ dibx000_exit_i2c_master(&st->i2c_master);
+ kfree(st);
+}
+
+struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+{
+ struct dib7000m_state *st = demod->demodulator_priv;
+ return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib7000m_get_i2c_master);
+
+int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[])
+{
+ struct dib7000m_state st = { .i2c_adap = i2c };
+ int k = 0;
+ u8 new_addr = 0;
+
+ for (k = no_of_demods-1; k >= 0; k--) {
+ st.cfg = cfg[k];
+
+ /* designated i2c address */
+ new_addr = (0x40 + k) << 1;
+ st.i2c_addr = new_addr;
+ if (dib7000m_identify(&st) != 0) {
+ st.i2c_addr = default_addr;
+ if (dib7000m_identify(&st) != 0) {
+ dprintk("DiB7000M #%d: not identified\n", k);
+ return -EIO;
+ }
+ }
+
+ /* start diversity to pull_down div_str - just for i2c-enumeration */
+ dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
+
+ dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
+
+ /* set new i2c address and force divstart */
+ dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
+
+ dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
+ }
+
+ for (k = 0; k < no_of_demods; k++) {
+ st.cfg = cfg[k];
+ st.i2c_addr = (0x40 + k) << 1;
+
+ // unforce divstr
+ dib7000m_write_word(&st,1794, st.i2c_addr << 2);
+
+ /* deactivate div - it was just for i2c-enumeration */
+ dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(dib7000m_i2c_enumeration);
+
+static struct dvb_frontend_ops dib7000m_ops;
+struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
+{
+ struct dvb_frontend *demod;
+ struct dib7000m_state *st;
+ st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
+ if (st == NULL)
+ return NULL;
+
+ memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
+ st->i2c_adap = i2c_adap;
+ st->i2c_addr = i2c_addr;
+
+ demod = &st->demod;
+ demod->demodulator_priv = st;
+ memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+
+ if (dib7000m_identify(st) != 0)
+ goto error;
+
+ if (st->revision == 0x4000)
+ dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
+ else
+ dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
+
+ dib7000m_demod_reset(st);
+
+ return demod;
+
+error:
+ kfree(st);
+ return NULL;
+}
+EXPORT_SYMBOL(dib7000m_attach);
+
+static struct dvb_frontend_ops dib7000m_ops = {
+ .info = {
+ .name = "DiBcom 7000MA/MB/PA/PB/MC",
+ .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 |
+ 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 = dib7000m_release,
+
+ .init = dib7000m_init,
+ .sleep = dib7000m_sleep,
+
+ .set_frontend = dib7000m_set_frontend,
+ .get_tune_settings = dib7000m_fe_get_tune_settings,
+ .get_frontend = dib7000m_get_frontend,
+
+ .read_status = dib7000m_read_status,
+ .read_ber = dib7000m_read_ber,
+ .read_signal_strength = dib7000m_read_signal_strength,
+ .read_snr = dib7000m_read_snr,
+ .read_ucblocks = dib7000m_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h
new file mode 100644
index 00000000000..597e9cc2da6
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000m.h
@@ -0,0 +1,51 @@
+#ifndef DIB7000M_H
+#define DIB7000M_H
+
+#include "dibx000_common.h"
+
+struct dib7000m_config {
+ u8 dvbt_mode;
+ u8 output_mpeg2_in_188_bytes;
+ u8 hostbus_diversity;
+ u8 tuner_is_baseband;
+ u8 mobile_mode;
+ int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+ u8 agc_config_count;
+ struct dibx000_agc_config *agc;
+
+ struct dibx000_bandwidth_config *bw;
+
+#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff
+ u16 gpio_dir;
+#define DIB7000M_GPIO_DEFAULT_VALUES 0x0000
+ u16 gpio_val;
+#define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
+#define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
+#define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
+#define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf)
+#define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff
+ u16 gpio_pwm_pos;
+
+ u16 pwm_freq_div;
+
+ u8 quartz_direct;
+
+ u8 input_clk_is_div_2;
+
+ int (*agc_control) (struct dvb_frontend *, u8 before);
+};
+
+#define DEFAULT_DIB7000M_I2C_ADDRESS 18
+
+extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg);
+extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+
+/* TODO
+extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
+extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod);
+extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
+extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod);
+*/
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
new file mode 100644
index 00000000000..0349a4b5da3
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -0,0 +1,1019 @@
+/*
+ * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
+ *
+ * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib7000p.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0)
+
+struct dib7000p_state {
+ struct dvb_frontend demod;
+ struct dib7000p_config cfg;
+
+ u8 i2c_addr;
+ struct i2c_adapter *i2c_adap;
+
+ struct dibx000_i2c_master i2c_master;
+
+ u16 wbd_ref;
+
+ u8 current_band;
+ fe_bandwidth_t current_bandwidth;
+ struct dibx000_agc_config *current_agc;
+ u32 timf;
+
+ u16 gpio_dir;
+ u16 gpio_val;
+};
+
+enum dib7000p_power_mode {
+ DIB7000P_POWER_ALL = 0,
+ DIB7000P_POWER_INTERFACE_ONLY,
+};
+
+static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+{
+ u8 wb[2] = { reg >> 8, reg & 0xff };
+ u8 rb[2];
+ struct i2c_msg msg[2] = {
+ { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
+ { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+ };
+
+ if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+ dprintk("i2c read error on %d\n",reg);
+
+ return (rb[0] << 8) | rb[1];
+}
+
+static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+{
+ u8 b[4] = {
+ (reg >> 8) & 0xff, reg & 0xff,
+ (val >> 8) & 0xff, val & 0xff,
+ };
+ struct i2c_msg msg = {
+ .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+ };
+ return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
+{
+ int ret = 0;
+ u16 outreg, fifo_threshold, smo_mode;
+
+ outreg = 0;
+ fifo_threshold = 1792;
+ smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1);
+
+ dprintk("-I- Setting output mode for demod %p to %d\n",
+ &state->demod, mode);
+
+ switch (mode) {
+ case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
+ outreg = (1 << 10); /* 0x0400 */
+ break;
+ case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
+ outreg = (1 << 10) | (1 << 6); /* 0x0440 */
+ break;
+ case OUTMODE_MPEG2_SERIAL: // STBs with serial input
+ outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
+ break;
+ case OUTMODE_DIVERSITY:
+ if (state->cfg.hostbus_diversity)
+ outreg = (1 << 10) | (4 << 6); /* 0x0500 */
+ else
+ outreg = (1 << 11);
+ break;
+ case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
+ smo_mode |= (3 << 1);
+ fifo_threshold = 512;
+ outreg = (1 << 10) | (5 << 6);
+ break;
+ case OUTMODE_HIGH_Z: // disable
+ outreg = 0;
+ break;
+ default:
+ dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+ break;
+ }
+
+ if (state->cfg.output_mpeg2_in_188_bytes)
+ smo_mode |= (1 << 5) ;
+
+ ret |= dib7000p_write_word(state, 235, smo_mode);
+ ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
+ ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
+
+ return ret;
+}
+
+static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
+{
+ /* by default everything is powered off */
+ u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003,
+ reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
+
+ /* now, depending on the requested mode, we power on */
+ switch (mode) {
+ /* power up everything in the demod */
+ case DIB7000P_POWER_ALL:
+ reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
+ break;
+ /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
+ case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
+ reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
+ break;
+/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
+ }
+
+ dib7000p_write_word(state, 774, reg_774);
+ dib7000p_write_word(state, 775, reg_775);
+ dib7000p_write_word(state, 776, reg_776);
+ dib7000p_write_word(state, 899, reg_899);
+ dib7000p_write_word(state, 1280, reg_1280);
+
+ return 0;
+}
+
+static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
+{
+ u16 reg_908 = dib7000p_read_word(state, 908),
+ reg_909 = dib7000p_read_word(state, 909);
+
+ switch (no) {
+ case DIBX000_SLOW_ADC_ON:
+ reg_909 |= (1 << 1) | (1 << 0);
+ dib7000p_write_word(state, 909, reg_909);
+ reg_909 &= ~(1 << 1);
+ break;
+
+ case DIBX000_SLOW_ADC_OFF:
+ reg_909 |= (1 << 1) | (1 << 0);
+ break;
+
+ case DIBX000_ADC_ON:
+ reg_908 &= 0x0fff;
+ reg_909 &= 0x0003;
+ break;
+
+ case DIBX000_ADC_OFF: // leave the VBG voltage on
+ reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
+ reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+ break;
+
+ case DIBX000_VBG_ENABLE:
+ reg_908 &= ~(1 << 15);
+ break;
+
+ case DIBX000_VBG_DISABLE:
+ reg_908 |= (1 << 15);
+ break;
+
+ default:
+ break;
+ }
+
+// dprintk("908: %x, 909: %x\n", reg_908, reg_909);
+
+ dib7000p_write_word(state, 908, reg_908);
+ dib7000p_write_word(state, 909, reg_909);
+}
+
+static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ u32 timf;
+
+ // store the current bandwidth for later use
+ state->current_bandwidth = BW_Idx;
+
+ if (state->timf == 0) {
+ dprintk("-D- Using default timf\n");
+ timf = state->cfg.bw->timf;
+ } else {
+ dprintk("-D- Using updated timf\n");
+ timf = state->timf;
+ }
+
+ timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80;
+
+ dprintk("timf: %d\n",timf);
+
+ dib7000p_write_word(state, 23, (timf >> 16) & 0xffff);
+ dib7000p_write_word(state, 24, (timf ) & 0xffff);
+
+ return 0;
+}
+
+static int dib7000p_sad_calib(struct dib7000p_state *state)
+{
+/* internal */
+// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+ dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
+ dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
+
+ /* do the calibration */
+ dib7000p_write_word(state, 73, (1 << 0));
+ dib7000p_write_word(state, 73, (0 << 0));
+
+ msleep(1);
+
+ return 0;
+}
+
+static void dib7000p_reset_pll(struct dib7000p_state *state)
+{
+ struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
+
+ dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
+ dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) |
+ (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0));
+
+ dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff);
+ dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff);
+ dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff);
+ dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff);
+
+ dib7000p_write_word(state, 72, bw->sad_cfg);
+}
+
+static int dib7000p_reset_gpio(struct dib7000p_state *st)
+{
+ /* reset the GPIOs */
+ dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
+
+ dib7000p_write_word(st, 1029, st->gpio_dir);
+ dib7000p_write_word(st, 1030, st->gpio_val);
+
+ /* TODO 1031 is P_gpio_od */
+
+ dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
+
+ dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
+ return 0;
+}
+
+static int dib7000p_demod_reset(struct dib7000p_state *state)
+{
+ dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+
+ dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+ /* restart all parts */
+ dib7000p_write_word(state, 770, 0xffff);
+ dib7000p_write_word(state, 771, 0xffff);
+ dib7000p_write_word(state, 772, 0x001f);
+ dib7000p_write_word(state, 898, 0x0003);
+ /* except i2c, sdio, gpio - control interfaces */
+ dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) );
+
+ dib7000p_write_word(state, 770, 0);
+ dib7000p_write_word(state, 771, 0);
+ dib7000p_write_word(state, 772, 0);
+ dib7000p_write_word(state, 898, 0);
+ dib7000p_write_word(state, 1280, 0);
+
+ /* default */
+ dib7000p_reset_pll(state);
+
+ if (dib7000p_reset_gpio(state) != 0)
+ dprintk("-E- GPIO reset was not successful.\n");
+
+ if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+ dprintk("-E- OUTPUT_MODE could not be resetted.\n");
+
+ /* unforce divstr regardless whether i2c enumeration was done or not */
+ dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
+
+ dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+
+ return 0;
+}
+
+static void dib7000p_restart_agc(struct dib7000p_state *state)
+{
+ // P_restart_iqc & P_restart_agc
+ dib7000p_write_word(state, 770, 0x0c00);
+ dib7000p_write_word(state, 770, 0x0000);
+}
+
+static void dib7000p_update_lna(struct dib7000p_state *state)
+{
+ int i;
+ u16 dyn_gain;
+
+ // when there is no LNA to program return immediatly
+ if (state->cfg.update_lna == NULL)
+ return;
+
+ for (i = 0; i < 5; i++) {
+ // read dyn_gain here (because it is demod-dependent and not tuner)
+ dyn_gain = dib7000p_read_word(state, 394);
+
+ if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
+ dib7000p_restart_agc(state);
+ msleep(5);
+ } else
+ break;
+ }
+}
+
+static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
+{
+ u16 tmp = 0;
+ tmp = dib7000p_read_word(state, 903);
+ dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll
+ tmp = dib7000p_read_word(state, 900);
+ dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock
+}
+
+static void dib7000p_update_timf_freq(struct dib7000p_state *state)
+{
+ u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
+ state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100);
+ dib7000p_write_word(state, 23, (u16) (timf >> 16));
+ dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
+ dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf);
+}
+
+static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq)
+{
+ u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208;
+
+ /* nfft, guard, qam, alpha */
+ dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha));
+ dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
+
+ /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */
+ tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1);
+ if (ch->vit_hrch == 0 || ch->vit_select_hp == 1)
+ tmp |= (ch->vit_code_rate_hp << 1);
+ else
+ tmp |= (ch->vit_code_rate_lp << 1);
+ dib7000p_write_word(state, 208, tmp);
+
+ /* P_dvsy_sync_wait */
+ switch (ch->nfft) {
+ case 1: tmp = 256; break;
+ case 2: tmp = 128; break;
+ case 0:
+ default: tmp = 64; break;
+ }
+ tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin
+ tmp <<= 4;
+
+ /* deactive the possibility of diversity reception if extended interleave */
+ /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+ if (ch->intlv_native || ch->nfft == 1)
+ tmp |= (1 << 2) | (2 << 0);
+ dib7000p_write_word(state, 207, tmp);
+
+ dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
+ dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073
+ dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
+ dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
+
+ /* channel estimation fine configuration */
+ switch (ch->nqam) {
+ case 2:
+ est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
+ est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
+ est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
+ est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
+ break;
+ case 1:
+ est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
+ est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
+ est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
+ est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
+ break;
+ default:
+ est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
+ est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
+ est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
+ est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
+ break;
+ }
+ for (tmp = 0; tmp < 4; tmp++)
+ dib7000p_write_word(state, 187 + tmp, est[tmp]);
+
+ // set power-up level: interf+analog+AGC
+ dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+ dib7000p_set_adc_state(state, DIBX000_ADC_ON);
+ dib7000p_pll_clk_cfg(state);
+ msleep(7);
+
+ // AGC initialization
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 1);
+
+ dib7000p_restart_agc(state);
+
+ // wait AGC rough lock time
+ msleep(5);
+
+ dib7000p_update_lna(state);
+
+ // wait AGC accurate lock time
+ msleep(7);
+ if (state->cfg.agc_control)
+ state->cfg.agc_control(&state->demod, 0);
+}
+
+static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ struct dibx000_ofdm_channel auto_ch;
+ u32 value;
+
+ INIT_OFDM_CHANNEL(&auto_ch);
+ auto_ch.RF_kHz = ch->RF_kHz;
+ auto_ch.Bw = ch->Bw;
+ auto_ch.nqam = 2;
+ auto_ch.guard = 0;
+ auto_ch.nfft = 1;
+ auto_ch.vit_alpha = 1;
+ auto_ch.vit_select_hp = 1;
+ auto_ch.vit_code_rate_hp = 2;
+ auto_ch.vit_code_rate_lp = 3;
+ auto_ch.vit_hrch = 0;
+ auto_ch.intlv_native = 1;
+
+ dib7000p_set_channel(state, &auto_ch, 7);
+
+ // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
+ value = 30 * state->cfg.bw->internal;
+ dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
+ dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
+ value = 100 * state->cfg.bw->internal;
+ dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
+ dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
+ value = 500 * state->cfg.bw->internal;
+ dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
+ dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
+
+ value = dib7000p_read_word(state, 0);
+ dib7000p_write_word(state, 0, (1 << 9) | value);
+ dib7000p_read_word(state, 1284);
+ dib7000p_write_word(state, 0, (u16) value);
+
+ return 0;
+}
+
+static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ u16 irq_pending = dib7000p_read_word(state, 1284);
+
+ if (irq_pending & 0x1) // failed
+ return 1;
+
+ if (irq_pending & 0x2) // succeeded
+ return 2;
+
+ return 0; // still pending
+}
+
+static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ u16 tmp = 0;
+
+ if (ch != NULL)
+ dib7000p_set_channel(state, ch, 0);
+ else
+ return -EINVAL;
+
+ // restart demod
+ dib7000p_write_word(state, 770, 0x4000);
+ dib7000p_write_word(state, 770, 0x0000);
+ msleep(45);
+
+ /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+ dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+ // never achieved a lock with that bandwidth so far - wait for osc-freq to update
+ if (state->timf == 0)
+ msleep(200);
+
+ /* offset loop parameters */
+
+ /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
+ tmp = (6 << 8) | 0x80;
+ switch (ch->nfft) {
+ case 0: tmp |= (7 << 12); break;
+ case 1: tmp |= (9 << 12); break;
+ case 2: tmp |= (8 << 12); break;
+ }
+ dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
+
+ /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
+ tmp = (0 << 4);
+ switch (ch->nfft) {
+ case 0: tmp |= 0x6; break;
+ case 1: tmp |= 0x8; break;
+ case 2: tmp |= 0x7; break;
+ }
+ dib7000p_write_word(state, 32, tmp);
+
+ /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
+ tmp = (0 << 4);
+ switch (ch->nfft) {
+ case 0: tmp |= 0x6; break;
+ case 1: tmp |= 0x8; break;
+ case 2: tmp |= 0x7; break;
+ }
+ dib7000p_write_word(state, 33, tmp);
+
+ tmp = dib7000p_read_word(state,509);
+ if (!((tmp >> 6) & 0x1)) {
+ /* restart the fec */
+ tmp = dib7000p_read_word(state,771);
+ dib7000p_write_word(state, 771, tmp | (1 << 1));
+ dib7000p_write_word(state, 771, tmp);
+ msleep(10);
+ tmp = dib7000p_read_word(state,509);
+ }
+
+ // we achieved a lock - it's time to update the osc freq
+ if ((tmp >> 6) & 0x1)
+ dib7000p_update_timf_freq(state);
+
+ return 0;
+}
+
+static int dib7000p_init(struct dvb_frontend *demod)
+{
+ struct dibx000_agc_config *agc;
+ struct dib7000p_state *state = demod->demodulator_priv;
+ int ret = 0;
+
+ // Demodulator default configuration
+ agc = state->cfg.agc;
+
+ dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+ dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+
+ /* AGC */
+ ret |= dib7000p_write_word(state, 75 , agc->setup );
+ ret |= dib7000p_write_word(state, 76 , agc->inv_gain );
+ ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz );
+ ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
+
+ // Demod AGC loop configuration
+ ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
+ ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
+
+ /* AGC continued */
+ dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
+ state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+ if (state->wbd_ref != 0)
+ ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
+ else
+ ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
+
+ ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
+
+ ret |= dib7000p_write_word(state, 107, agc->agc1_max);
+ ret |= dib7000p_write_word(state, 108, agc->agc1_min);
+ ret |= dib7000p_write_word(state, 109, agc->agc2_max);
+ ret |= dib7000p_write_word(state, 110, agc->agc2_min);
+ ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
+ ret |= dib7000p_write_word(state, 112, agc->agc1_pt3);
+ ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+ ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+ ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+ /* disable power smoothing */
+ ret |= dib7000p_write_word(state, 145, 0);
+ ret |= dib7000p_write_word(state, 146, 0);
+ ret |= dib7000p_write_word(state, 147, 0);
+ ret |= dib7000p_write_word(state, 148, 0);
+ ret |= dib7000p_write_word(state, 149, 0);
+ ret |= dib7000p_write_word(state, 150, 0);
+ ret |= dib7000p_write_word(state, 151, 0);
+ ret |= dib7000p_write_word(state, 152, 0);
+
+ // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
+ ret |= dib7000p_write_word(state, 26 ,0x6680);
+
+ // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
+ ret |= dib7000p_write_word(state, 142,0x0410);
+ // P_fft_freq_dir=1, P_fft_nb_to_cut=0
+ ret |= dib7000p_write_word(state, 154,1 << 13);
+ // P_pha3_thres, default 0x3000
+ ret |= dib7000p_write_word(state, 168,0x0ccd);
+ // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
+ //ret |= dib7000p_write_word(state, 169,0x0010);
+ // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
+ ret |= dib7000p_write_word(state, 183,0x200f);
+ // P_adp_regul_cnt=573, default: 410
+ ret |= dib7000p_write_word(state, 187,0x023d);
+ // P_adp_noise_cnt=
+ ret |= dib7000p_write_word(state, 188,0x00a4);
+ // P_adp_regul_ext
+ ret |= dib7000p_write_word(state, 189,0x00a4);
+ // P_adp_noise_ext
+ ret |= dib7000p_write_word(state, 190,0x7ff0);
+ // P_adp_fil
+ ret |= dib7000p_write_word(state, 191,0x3ccc);
+
+ ret |= dib7000p_write_word(state, 222,0x0010);
+ // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+ ret |= dib7000p_write_word(state, 235,0x0062);
+
+ // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
+ if(state->cfg.tuner_is_baseband)
+ ret |= dib7000p_write_word(state, 36,0x0755);
+ else
+ ret |= dib7000p_write_word(state, 36,0x1f55);
+
+ // auto search configuration
+ ret |= dib7000p_write_word(state, 2 ,0x0004);
+ ret |= dib7000p_write_word(state, 3 ,0x1000);
+
+ /* Equal Lock */
+ ret |= dib7000p_write_word(state, 4 ,0x0814);
+
+ ret |= dib7000p_write_word(state, 6 ,0x001b);
+ ret |= dib7000p_write_word(state, 7 ,0x7740);
+ ret |= dib7000p_write_word(state, 8 ,0x005b);
+ ret |= dib7000p_write_word(state, 9 ,0x8d80);
+ ret |= dib7000p_write_word(state, 10 ,0x01c9);
+ ret |= dib7000p_write_word(state, 11 ,0xc380);
+ ret |= dib7000p_write_word(state, 12 ,0x0000);
+ ret |= dib7000p_write_word(state, 13 ,0x0080);
+ ret |= dib7000p_write_word(state, 14 ,0x0000);
+ ret |= dib7000p_write_word(state, 15 ,0x0090);
+ ret |= dib7000p_write_word(state, 16 ,0x0001);
+ ret |= dib7000p_write_word(state, 17 ,0xd4c0);
+
+ // P_clk_cfg1
+ ret |= dib7000p_write_word(state, 901, 0x0006);
+
+ // P_divclksel=3 P_divbitsel=1
+ ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
+
+ // Tuner IO bank: max drive (14mA) + divout pads max drive
+ ret |= dib7000p_write_word(state, 905, 0x2c8e);
+
+ ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+ dib7000p_sad_calib(state);
+
+ return ret;
+}
+
+static int dib7000p_sleep(struct dvb_frontend *demod)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+}
+
+static int dib7000p_identify(struct dib7000p_state *st)
+{
+ u16 value;
+ dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n",
+ st->i2c_addr, st->i2c_addr);
+
+ if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
+ dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value);
+ return -EREMOTEIO;
+ }
+
+ if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
+ dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+
+static int dib7000p_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ u16 tps = dib7000p_read_word(state,463);
+
+ fep->inversion = INVERSION_AUTO;
+
+ fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+ switch ((tps >> 8) & 0x3) {
+ case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+ case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+ /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+ }
+
+ switch (tps & 0x3) {
+ case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+ case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+ case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+ case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+ }
+
+ switch ((tps >> 14) & 0x3) {
+ case 0: fep->u.ofdm.constellation = QPSK; break;
+ case 1: fep->u.ofdm.constellation = QAM_16; break;
+ case 2:
+ default: fep->u.ofdm.constellation = QAM_64; break;
+ }
+
+ /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+ /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
+
+ fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ switch ((tps >> 5) & 0x7) {
+ case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+ case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+ case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+ case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+ case 7:
+ default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+ }
+
+ switch ((tps >> 2) & 0x7) {
+ case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+ case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+ case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+ case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+ case 7:
+ default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+ }
+
+ /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
+
+ return 0;
+}
+
+static int dib7000p_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ struct dibx000_ofdm_channel ch;
+
+ INIT_OFDM_CHANNEL(&ch);
+ FEP2DIB(fep,&ch);
+
+ state->current_bandwidth = fep->u.ofdm.bandwidth;
+ dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe, fep);
+
+ if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
+ fep->u.ofdm.constellation == QAM_AUTO ||
+ fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ int i = 800, found;
+
+ dib7000p_autosearch_start(fe, &ch);
+ do {
+ msleep(1);
+ found = dib7000p_autosearch_is_irq(fe);
+ } while (found == 0 && i--);
+
+ dprintk("autosearch returns: %d\n",found);
+ if (found == 0 || found == 1)
+ return 0; // no channel found
+
+ dib7000p_get_frontend(fe, fep);
+ FEP2DIB(fep, &ch);
+ }
+
+ /* make this a config parameter */
+ dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+ return dib7000p_tune(fe, &ch);
+}
+
+static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ u16 lock = dib7000p_read_word(state, 509);
+
+ *stat = 0;
+
+ if (lock & 0x8000)
+ *stat |= FE_HAS_SIGNAL;
+ if (lock & 0x3000)
+ *stat |= FE_HAS_CARRIER;
+ if (lock & 0x0100)
+ *stat |= FE_HAS_VITERBI;
+ if (lock & 0x0010)
+ *stat |= FE_HAS_SYNC;
+ if (lock & 0x0008)
+ *stat |= FE_HAS_LOCK;
+
+ return 0;
+}
+
+static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
+ return 0;
+}
+
+static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ *unc = dib7000p_read_word(state, 506);
+ return 0;
+}
+
+static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ u16 val = dib7000p_read_word(state, 394);
+ *strength = 65535 - val;
+ return 0;
+}
+
+static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ *snr = 0x0000;
+ return 0;
+}
+
+static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void dib7000p_release(struct dvb_frontend *demod)
+{
+ struct dib7000p_state *st = demod->demodulator_priv;
+ dibx000_exit_i2c_master(&st->i2c_master);
+ kfree(st);
+}
+
+int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+{
+ u8 tx[2], rx[2];
+ struct i2c_msg msg[2] = {
+ { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 },
+ { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },
+ };
+
+ tx[0] = 0x03;
+ tx[1] = 0x00;
+
+ if (i2c_transfer(i2c_adap, msg, 2) == 2)
+ if (rx[0] == 0x01 && rx[1] == 0xb3) {
+ dprintk("-D- DiB7000PC detected\n");
+ return 1;
+ }
+
+ msg[0].addr = msg[1].addr = 0x40;
+
+ if (i2c_transfer(i2c_adap, msg, 2) == 2)
+ if (rx[0] == 0x01 && rx[1] == 0xb3) {
+ dprintk("-D- DiB7000PC detected\n");
+ return 1;
+ }
+
+ dprintk("-D- DiB7000PC not detected\n");
+ return 0;
+}
+EXPORT_SYMBOL(dib7000pc_detection);
+
+struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+{
+ struct dib7000p_state *st = demod->demodulator_priv;
+ return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib7000p_get_i2c_master);
+
+int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
+{
+ struct dib7000p_state st = { .i2c_adap = i2c };
+ int k = 0;
+ u8 new_addr = 0;
+
+ for (k = no_of_demods-1; k >= 0; k--) {
+ st.cfg = cfg[k];
+
+ /* designated i2c address */
+ new_addr = (0x40 + k) << 1;
+ st.i2c_addr = new_addr;
+ if (dib7000p_identify(&st) != 0) {
+ st.i2c_addr = default_addr;
+ if (dib7000p_identify(&st) != 0) {
+ dprintk("DiB7000P #%d: not identified\n", k);
+ return -EIO;
+ }
+ }
+
+ /* start diversity to pull_down div_str - just for i2c-enumeration */
+ dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY);
+
+ /* set new i2c address and force divstart */
+ dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2);
+
+ dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
+ }
+
+ for (k = 0; k < no_of_demods; k++) {
+ st.cfg = cfg[k];
+ st.i2c_addr = (0x40 + k) << 1;
+
+ // unforce divstr
+ dib7000p_write_word(&st, 1285, st.i2c_addr << 2);
+
+ /* deactivate div - it was just for i2c-enumeration */
+ dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(dib7000p_i2c_enumeration);
+
+static struct dvb_frontend_ops dib7000p_ops;
+struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+{
+ struct dvb_frontend *demod;
+ struct dib7000p_state *st;
+ st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
+ if (st == NULL)
+ return NULL;
+
+ memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
+ st->i2c_adap = i2c_adap;
+ st->i2c_addr = i2c_addr;
+ st->gpio_val = cfg->gpio_val;
+ st->gpio_dir = cfg->gpio_dir;
+
+ demod = &st->demod;
+ demod->demodulator_priv = st;
+ memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+
+ if (dib7000p_identify(st) != 0)
+ goto error;
+
+ dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
+
+ dib7000p_demod_reset(st);
+
+ return demod;
+
+error:
+ kfree(st);
+ return NULL;
+}
+EXPORT_SYMBOL(dib7000p_attach);
+
+static struct dvb_frontend_ops dib7000p_ops = {
+ .info = {
+ .name = "DiBcom 7000PC",
+ .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 |
+ 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 = dib7000p_release,
+
+ .init = dib7000p_init,
+ .sleep = dib7000p_sleep,
+
+ .set_frontend = dib7000p_set_frontend,
+ .get_tune_settings = dib7000p_fe_get_tune_settings,
+ .get_frontend = dib7000p_get_frontend,
+
+ .read_status = dib7000p_read_status,
+ .read_ber = dib7000p_read_ber,
+ .read_signal_strength = dib7000p_read_signal_strength,
+ .read_snr = dib7000p_read_snr,
+ .read_ucblocks = dib7000p_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
new file mode 100644
index 00000000000..79465cf1ace
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -0,0 +1,46 @@
+#ifndef DIB7000P_H
+#define DIB7000P_H
+
+#include "dibx000_common.h"
+
+struct dib7000p_config {
+ u8 output_mpeg2_in_188_bytes;
+ u8 hostbus_diversity;
+ u8 tuner_is_baseband;
+ int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+ struct dibx000_agc_config *agc;
+ struct dibx000_bandwidth_config *bw;
+
+#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
+ u16 gpio_dir;
+#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000
+ u16 gpio_val;
+#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
+#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
+#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
+#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf)
+#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff
+ u16 gpio_pwm_pos;
+
+ u16 pwm_freq_div;
+
+ u8 quartz_direct;
+
+ int (*agc_control) (struct dvb_frontend *, u8 before);
+};
+
+#define DEFAULT_DIB7000P_I2C_ADDRESS 18
+
+extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
+
+/* TODO
+extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
+extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
+extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
+extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
+*/
+
+#endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
index bb0c65f8aee..a1df604366c 100644
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ b/drivers/media/dvb/frontends/dibx000_common.h
@@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
#define BAND_LBAND 0x01
#define BAND_UHF 0x02
#define BAND_VHF 0x04
+#define BAND_SBAND 0x08
+#define BAND_FM 0x10
+
+#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
+ (freq_kHz) <= 250000 ? BAND_VHF : \
+ (freq_kHz) <= 863000 ? BAND_UHF : \
+ (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
struct dibx000_agc_config {
/* defines the capabilities of this AGC-setting - using the BAND_-defines*/
@@ -129,6 +136,7 @@ enum dibx000_adc_states {
/* I hope I can get rid of the following kludge in the near future */
struct dibx000_ofdm_channel {
+ u32 RF_kHz;
u8 Bw;
s16 nfft;
s16 guard;
@@ -138,9 +146,11 @@ struct dibx000_ofdm_channel {
s16 vit_alpha;
s16 vit_code_rate_hp;
s16 vit_code_rate_lp;
+ u8 intlv_native;
};
#define FEP2DIB(fep,ch) \
+ (ch)->RF_kHz = (fep)->frequency / 1000; \
(ch)->Bw = (fep)->u.ofdm.bandwidth; \
(ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
(ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
@@ -149,7 +159,8 @@ struct dibx000_ofdm_channel {
(ch)->vit_select_hp = 1; \
(ch)->vit_alpha = 1; \
(ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
- (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP;
+ (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \
+ (ch)->intlv_native = 1;
#define INIT_OFDM_CHANNEL(ch) do {\
(ch)->Bw = 0; \
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index b7e7108ee5b..62de760c844 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -472,14 +472,14 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
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;
+ // calculate the frequency we set it to
+ return (div * desc->entries[i].stepsize) - desc->entries[i].offset;
}
EXPORT_SYMBOL(dvb_pll_configure);
static int dvb_pll_release(struct dvb_frontend *fe)
{
- if (fe->tuner_priv)
- kfree(fe->tuner_priv);
+ kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;
}
@@ -489,7 +489,8 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
struct dvb_pll_priv *priv = fe->tuner_priv;
u8 buf[4];
struct i2c_msg msg =
- { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ { .addr = priv->pll_i2c_address, .flags = 0,
+ .buf = buf, .len = sizeof(buf) };
int i;
int result;
@@ -517,16 +518,16 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
return 0;
}
-static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvb_pll_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
{
struct dvb_pll_priv *priv = fe->tuner_priv;
u8 buf[4];
struct i2c_msg msg =
- { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ { .addr = priv->pll_i2c_address, .flags = 0,
+ .buf = buf, .len = sizeof(buf) };
int result;
- u32 div;
- int i;
- u32 bandwidth = 0;
+ u32 bandwidth = 0, frequency = 0;
if (priv->i2c == NULL)
return -EINVAL;
@@ -536,8 +537,11 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
bandwidth = params->u.ofdm.bandwidth;
}
- if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
+ if ((result = dvb_pll_configure(priv->pll_desc, buf,
+ params->frequency, bandwidth)) < 0)
return result;
+ else
+ frequency = result;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -545,26 +549,19 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
return result;
}
- // calculate the frequency we set it to
- for (i = 0; i < priv->pll_desc->count; i++) {
- if (params->frequency > priv->pll_desc->entries[i].limit)
- continue;
- break;
- }
- div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
- priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+ priv->frequency = frequency;
priv->bandwidth = bandwidth;
return 0;
}
-static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+static int dvb_pll_calc_regs(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params,
+ u8 *buf, int buf_len)
{
struct dvb_pll_priv *priv = fe->tuner_priv;
int result;
- u32 div;
- int i;
- u32 bandwidth = 0;
+ u32 bandwidth = 0, frequency = 0;
if (buf_len < 5)
return -EINVAL;
@@ -574,18 +571,15 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame
bandwidth = params->u.ofdm.bandwidth;
}
- if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
+ if ((result = dvb_pll_configure(priv->pll_desc, buf+1,
+ params->frequency, bandwidth)) < 0)
return result;
+ else
+ frequency = result;
+
buf[0] = priv->pll_i2c_address;
- // calculate the frequency we set it to
- for (i = 0; i < priv->pll_desc->count; i++) {
- if (params->frequency > priv->pll_desc->entries[i].limit)
- continue;
- break;
- }
- div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
- priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+ priv->frequency = frequency;
priv->bandwidth = bandwidth;
return 5;
@@ -614,10 +608,13 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
.get_bandwidth = dvb_pll_get_bandwidth,
};
-struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
+ struct i2c_adapter *i2c,
+ struct dvb_pll_desc *desc)
{
u8 b1 [] = { 0 };
- struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
+ struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD,
+ .buf = b1, .len = 1 };
struct dvb_pll_priv *priv = NULL;
int ret;
@@ -640,7 +637,9 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struc
priv->i2c = i2c;
priv->pll_desc = desc;
- memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
+ memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
fe->ops.tuner_ops.info.frequency_min = desc->min;
fe->ops.tuner_ops.info.frequency_min = desc->max;
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index ed5ac5a361a..681186a5e5e 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
- u32 freq, int bandwidth);
+ u32 freq, int bandwidth);
/**
* Attach a dvb-pll to the supplied frontend structure.
@@ -59,6 +59,9 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
* @param desc dvb_pll_desc to use.
* @return Frontend pointer on success, NULL on failure
*/
-extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
+ int pll_addr,
+ struct i2c_adapter *i2c,
+ struct dvb_pll_desc *desc);
#endif
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h
deleted file mode 100644
index 754d51d1112..00000000000
--- a/drivers/media/dvb/frontends/lg_h06xf.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You 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 _LG_H06XF_H_
-#define _LG_H06XF_H_
-#include "dvb-pll.h"
-
-static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
- struct dvb_frontend_parameters* params)
-{
- u8 buf[4];
- struct i2c_msg msg = { .addr = 0x61, .flags = 0,
- .buf = buf, .len = sizeof(buf) };
- int err;
-
- dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
- printk(KERN_WARNING "lg_h06xf: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- /* Set the Auxiliary Byte. */
- buf[0] = buf[2];
- buf[0] &= ~0x20;
- buf[0] |= 0x18;
- buf[1] = 0x50;
- msg.len = 2;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
- printk(KERN_WARNING "lg_h06xf: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- return 0;
-}
-#endif
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 9a354708bd2..68aad0f6519 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -31,9 +31,6 @@
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
* pcHDTV HD5500
*
- * TODO:
- * signal strength always returns 0.
- *
*/
#include <linux/kernel.h>
@@ -46,9 +43,13 @@
#include <asm/byteorder.h>
#include "dvb_frontend.h"
+#include "dvb_math.h"
#include "lgdt330x_priv.h"
#include "lgdt330x.h"
+/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
+/* #define USE_EQMSE */
+
static int debug = 0;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
@@ -68,6 +69,7 @@ struct lgdt330x_state
/* Demodulator private data */
fe_modulation_t current_modulation;
+ u32 snr; /* Result of last SNR calculation */
/* Tuner private data */
u32 current_frequency;
@@ -302,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
static u8 lgdt3303_8vsb_44_data[] = {
0x04, 0x00,
0x0d, 0x40,
- 0x0e, 0x87,
- 0x0f, 0x8e,
- 0x10, 0x01,
- 0x47, 0x8b };
+ 0x0e, 0x87,
+ 0x0f, 0x8e,
+ 0x10, 0x01,
+ 0x47, 0x8b };
/*
* Array of byte pairs <address, value>
@@ -435,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* Test signal does not exist flag */
/* as well as the AGC lock flag. */
*status |= FE_HAS_SIGNAL;
- } else {
- /* Without a signal all other status bits are meaningless */
- return 0;
}
/*
@@ -500,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
/* Test input signal does not exist flag */
/* as well as the AGC lock flag. */
*status |= FE_HAS_SIGNAL;
- } else {
- /* Without a signal all other status bits are meaningless */
- return 0;
}
/* Carrier Recovery Lock Status Register */
@@ -543,151 +539,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
-static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+/* Calculate SNR estimation (scaled by 2^24)
+
+ 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
+ equations from LGDT3303 datasheet. VSB is the same between the '02
+ and '03, so maybe QAM is too? Perhaps someone with a newer datasheet
+ that has QAM information could verify?
+
+ For 8-VSB: (two ways, take your pick)
+ LGDT3302:
+ SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
+ LGDT3303:
+ SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
+ LGDT3302 & LGDT3303:
+ SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one)
+ For 64-QAM:
+ SNR = 10 * log10( 688128 / MSEQAM)
+ For 256-QAM:
+ SNR = 10 * log10( 696320 / MSEQAM)
+
+ We re-write the snr equation as:
+ SNR * 2^24 = 10*(c - intlog10(MSE))
+ Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
+
+static u32 calculate_snr(u32 mse, u32 c)
{
- /* not directly available. */
- *strength = 0;
- return 0;
+ if (mse == 0) /* No signal */
+ return 0;
+
+ mse = intlog10(mse);
+ if (mse > c) {
+ /* Negative SNR, which is possible, but realisticly the
+ demod will lose lock before the signal gets this bad. The
+ API only allows for unsigned values, so just return 0 */
+ return 0;
+ }
+ return 10*(c - mse);
}
static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
{
-#ifdef SNR_IN_DB
- /*
- * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
- * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
- * respectively. The following tables are built on these formulas.
- * The usual definition is SNR = 20 log10(signal/noise)
- * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
- *
- * This table is a an ordered list of noise values computed by the
- * formula from the spec sheet such that the index into the table
- * starting at 43 or 45 is the SNR value in db. There are duplicate noise
- * value entries at the beginning because the SNR varies more than
- * 1 db for a change of 1 digit in noise at very small values of noise.
- *
- * Examples from SNR_EQ table:
- * noise SNR
- * 0 43
- * 1 42
- * 2 39
- * 3 37
- * 4 36
- * 5 35
- * 6 34
- * 7 33
- * 8 33
- * 9 32
- * 10 32
- * 11 31
- * 12 31
- * 13 30
- */
-
- static const u32 SNR_EQ[] =
- { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
- 9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
- 81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
- 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
- 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
- 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
- };
-
- static const u32 SNR_PH[] =
- { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
- 10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
- 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
- 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
- 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
- 90833, 114351, 143960, 181235, 228161, 0x080000
- };
-
- static u8 buf[5];/* read data buffer */
- static u32 noise; /* noise value */
- static u32 snr_db; /* index into SNR_EQ[] */
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ u8 buf[5]; /* read data buffer */
+ u32 noise; /* noise value */
+ u32 c; /* per-modulation SNR calculation constant */
- /* read both equalizer and phase tracker noise data */
- i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
-
- if (state->current_modulation == VSB_8) {
- /* Equalizer Mean-Square Error Register for VSB */
+ switch(state->current_modulation) {
+ case VSB_8:
+ i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
+#ifdef USE_EQMSE
+ /* Use Equalizer Mean-Square Error Register */
+ /* SNR for ranges from -15.61 to +41.58 */
noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
-
- /*
- * Look up noise value in table.
- * A better search algorithm could be used...
- * watch out there are duplicate entries.
- */
- for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
- if (noise < SNR_EQ[snr_db]) {
- *snr = 43 - snr_db;
- break;
- }
- }
- } else {
- /* Phase Tracker Mean-Square Error Register for QAM */
- noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
-
- /* Look up noise value in table. */
- for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
- if (noise < SNR_PH[snr_db]) {
- *snr = 45 - snr_db;
- break;
- }
- }
- }
+ c = 69765745; /* log10(25*24^2)*2^24 */
#else
- /* Return the raw noise value */
- static u8 buf[5];/* read data buffer */
- static u32 noise; /* noise value */
- struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
-
- /* read both equalizer and pase tracker noise data */
- i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
-
- if (state->current_modulation == VSB_8) {
- /* Phase Tracker Mean-Square Error Register for VSB */
+ /* Use Phase Tracker Mean-Square Error Register */
+ /* SNR for ranges from -13.11 to +44.08 */
noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
- } else {
-
- /* Carrier Recovery Mean-Square Error for QAM */
- i2c_read_demod_bytes(state, 0x1a, buf, 2);
+ c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+ break;
+ case QAM_64:
+ case QAM_256:
+ i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
noise = ((buf[0] & 3) << 8) | buf[1];
+ c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
+ /* log10(688128)*2^24 and log10(696320)*2^24 */
+ break;
+ default:
+ printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+ __FUNCTION__);
+ return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
}
- /* Small values for noise mean signal is better so invert noise */
- *snr = ~noise;
-#endif
+ state->snr = calculate_snr(noise, c);
+ *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
- dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+ state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
return 0;
}
static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
{
- /* Return the raw noise value */
- static u8 buf[5];/* read data buffer */
- static u32 noise; /* noise value */
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ u8 buf[5]; /* read data buffer */
+ u32 noise; /* noise value */
+ u32 c; /* per-modulation SNR calculation constant */
- if (state->current_modulation == VSB_8) {
-
- i2c_read_demod_bytes(state, 0x6e, buf, 5);
- /* Phase Tracker Mean-Square Error Register for VSB */
+ switch(state->current_modulation) {
+ case VSB_8:
+ i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
+#ifdef USE_EQMSE
+ /* Use Equalizer Mean-Square Error Register */
+ /* SNR for ranges from -16.12 to +44.08 */
+ noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
+ c = 73957994; /* log10(25*32^2)*2^24 */
+#else
+ /* Use Phase Tracker Mean-Square Error Register */
+ /* SNR for ranges from -13.11 to +44.08 */
noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
- } else {
-
- /* Carrier Recovery Mean-Square Error for QAM */
- i2c_read_demod_bytes(state, 0x1a, buf, 2);
+ c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+ break;
+ case QAM_64:
+ case QAM_256:
+ i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
noise = (buf[0] << 8) | buf[1];
+ c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
+ /* log10(688128)*2^24 and log10(696320)*2^24 */
+ break;
+ default:
+ printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+ __FUNCTION__);
+ return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
}
- /* Small values for noise mean signal is better so invert noise */
- *snr = ~noise;
+ state->snr = calculate_snr(noise, c);
+ *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+ state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
+
+ return 0;
+}
+
+static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+ /* Calculate Strength from SNR up to 35dB */
+ /* Even though the SNR can go higher than 35dB, there is some comfort */
+ /* factor in having a range of strong signals that can show at 100% */
+ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+ u16 snr;
+ int ret;
- dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+ ret = fe->ops.read_snr(fe, &snr);
+ if (ret != 0)
+ return ret;
+ /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+ /* scale the range 0 - 35*2^24 into 0 - 65535 */
+ if (state->snr >= 8960 * 0x10000)
+ *strength = 0xffff;
+ else
+ *strength = state->snr / 8960;
return 0;
}
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h
index 59b7c5b9012..38c76695abf 100644
--- a/drivers/media/dvb/frontends/lgdt330x_priv.h
+++ b/drivers/media/dvb/frontends/lgdt330x_priv.h
@@ -51,14 +51,19 @@ enum I2C_REG {
AGC_RFIF_ACC2= 0x3b,
AGC_STATUS= 0x3f,
SYNC_STATUS_VSB= 0x43,
- EQPH_ERR0= 0x47,
- EQ_ERR1= 0x48,
- EQ_ERR2= 0x49,
- PH_ERR1= 0x4a,
- PH_ERR2= 0x4b,
DEMUX_CONTROL= 0x66,
+ LGDT3302_EQPH_ERR0= 0x47,
+ LGDT3302_EQ_ERR1= 0x48,
+ LGDT3302_EQ_ERR2= 0x49,
+ LGDT3302_PH_ERR1= 0x4a,
+ LGDT3302_PH_ERR2= 0x4b,
LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
+ LGDT3303_EQPH_ERR0= 0x6e,
+ LGDT3303_EQ_ERR1= 0x6f,
+ LGDT3303_EQ_ERR2= 0x70,
+ LGDT3303_PH_ERR1= 0x71,
+ LGDT3303_PH_ERR2= 0x72,
LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
};
diff --git a/drivers/media/dvb/frontends/lgh06xf.c b/drivers/media/dvb/frontends/lgh06xf.c
new file mode 100644
index 00000000000..2202d0cc878
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgh06xf.c
@@ -0,0 +1,134 @@
+/*
+ * lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 "dvb-pll.h"
+#include "lgh06xf.h"
+
+#define LG_H06XF_PLL_I2C_ADDR 0x61
+
+struct lgh06xf_priv {
+ struct i2c_adapter *i2c;
+ u32 frequency;
+};
+
+static int lgh06xf_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static int lgh06xf_set_params(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params)
+{
+ struct lgh06xf_priv *priv = fe->tuner_priv;
+ u8 buf[4];
+ struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0,
+ .buf = buf, .len = sizeof(buf) };
+ u32 frequency;
+ int result;
+
+ if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf,
+ params->frequency, 0)) < 0)
+ return result;
+ else
+ frequency = result;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+ printk(KERN_WARNING "lgh06xf: %s error "
+ "(addr %02x <- %02x, result = %i)\n",
+ __FUNCTION__, buf[0], buf[1], result);
+ if (result < 0)
+ return result;
+ else
+ return -EREMOTEIO;
+ }
+
+ /* Set the Auxiliary Byte. */
+ buf[0] = buf[2];
+ buf[0] &= ~0x20;
+ buf[0] |= 0x18;
+ buf[1] = 0x50;
+ msg.len = 2;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+ printk(KERN_WARNING "lgh06xf: %s error "
+ "(addr %02x <- %02x, result = %i)\n",
+ __FUNCTION__, buf[0], buf[1], result);
+ if (result < 0)
+ return result;
+ else
+ return -EREMOTEIO;
+ }
+
+ priv->frequency = frequency;
+
+ return 0;
+}
+
+static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct lgh06xf_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static struct dvb_tuner_ops lgh06xf_tuner_ops = {
+ .release = lgh06xf_release,
+ .set_params = lgh06xf_set_params,
+ .get_frequency = lgh06xf_get_frequency,
+};
+
+struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c)
+{
+ struct lgh06xf_priv *priv = NULL;
+
+ priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+
+ priv->i2c = i2c;
+
+ memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+ strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name,
+ sizeof(fe->ops.tuner_ops.info.name));
+
+ fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min;
+ fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max;
+
+ fe->tuner_priv = priv;
+ return fe;
+}
+
+EXPORT_SYMBOL(lgh06xf_attach);
+
+MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support");
+MODULE_AUTHOR("Michael Krufky");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/lgh06xf.h b/drivers/media/dvb/frontends/lgh06xf.h
new file mode 100644
index 00000000000..510b4bedfb2
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgh06xf.h
@@ -0,0 +1,35 @@
+/*
+ * lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 _LGH06XF_H_
+#define _LGH06XF_H_
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE))
+extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_TUNER_LGH06XF */
+
+#endif /* _LGH06XF_H_ */
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index d20ab30c1e8..5a3a6e53cda 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <asm/byteorder.h>
+#include "dvb_math.h"
#include "dvb_frontend.h"
#include "dvb-pll.h"
#include "or51132.h"
@@ -62,6 +63,7 @@ struct or51132_state
/* Demodulator private data */
fe_modulation_t current_modulation;
+ u32 snr; /* Result of last SNR calculation */
/* Tuner private data */
u32 current_frequency;
@@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
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,
-};
+/* Calculate SNR estimation (scaled by 2^24)
-static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
+ 8-VSB SNR and QAM equations from Oren datasheets
-static unsigned int i20Log10(unsigned short val)
-{
- unsigned int rntval = 100;
- unsigned int tmp = val;
- unsigned int exp = 1;
+ For 8-VSB:
+ SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
+
+ Where K = 0 if NTSC rejection filter is OFF; and
+ K = 3 if NTSC rejection filter is ON
+
+ For QAM64:
+ SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
- while(tmp > 100) {tmp /= 100; exp++;}
+ For QAM256:
+ SNR[dB] = 10 * log10(907832426.314266 / MSE^2 )
- val = (2 * val)/denom[exp];
- if (exp > 1) rntval = 2000*exp;
+ We re-write the snr equation as:
+ SNR * 2^24 = 10*(c - 2*intlog10(MSE))
+ Where for QAM256, c = log10(907832426.314266) * 2^24
+ and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
- rntval += i100x20log10[val];
- return rntval;
+static u32 calculate_snr(u32 mse, u32 c)
+{
+ if (mse == 0) /* No signal */
+ return 0;
+
+ mse = 2*intlog10(mse);
+ if (mse > c) {
+ /* Negative SNR, which is possible, but realisticly the
+ demod will lose lock before the signal gets this bad. The
+ API only allows for unsigned values, so just return 0 */
+ return 0;
+ }
+ return 10*(c - mse);
}
-static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
{
struct or51132_state* state = fe->demodulator_priv;
- unsigned char rec_buf[2];
- unsigned char snd_buf[2];
- u8 rcvr_stat;
- u16 snr_equ;
- u32 signal_strength;
- int usK;
+ u8 rec_buf[2];
+ u8 snd_buf[2];
+ u32 noise;
+ u32 c;
+ u32 usK;
+ /* Register is same for VSB or QAM firmware */
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;
+ printk(KERN_WARNING "or51132: snr write error\n");
+ return -EREMOTEIO;
}
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;
+ printk(KERN_WARNING "or51132: snr read error\n");
+ return -EREMOTEIO;
}
- 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);
+ noise = rec_buf[0] | (rec_buf[1] << 8);
+ dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise);
- /* Receiver Status */
+ /* Read status, contains modulation type for QAM_AUTO and
+ NTSC filter for VSB */
snd_buf[0]=0x04;
- snd_buf[1]=0x00;
+ snd_buf[1]=0x00; /* Status register */
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;
+ printk(KERN_WARNING "or51132: status write error\n");
+ return -EREMOTEIO;
}
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;
+ printk(KERN_WARNING "or51132: status read error\n");
+ return -EREMOTEIO;
}
- 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% */
- signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
- if (signal_strength > 0xffff)
- *strength = 0xffff;
- else
- *strength = signal_strength;
- dprintk("read_signal_strength %i\n",*strength);
+ usK = 0;
+ switch (rec_buf[0]) {
+ case 0x06:
+ usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0;
+ /* Fall through to QAM64 case */
+ case 0x43:
+ c = 150204167;
+ break;
+ case 0x45:
+ c = 150290396;
+ break;
+ default:
+ printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]);
+ return -EREMOTEIO;
+ }
+ dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
+ rec_buf[0], rec_buf[1]&0x10?"n":"ff");
+
+ /* Calculate SNR using noise, c, and NTSC rejection correction */
+ state->snr = calculate_snr(noise, c) - usK;
+ *snr = (state->snr) >> 16;
+
+ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
+ state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
return 0;
}
-static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
+static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct or51132_state* 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);
+ /* Calculate Strength from SNR up to 35dB */
+ /* Even though the SNR can go higher than 35dB, there is some comfort */
+ /* factor in having a range of strong signals that can show at 100% */
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ u16 snr;
+ int ret;
- *snr = 0xFFFF - snr_equ;
- dprintk("read_snr %i\n",*snr);
+ ret = fe->ops.read_snr(fe, &snr);
+ if (ret != 0)
+ return ret;
+ /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+ /* scale the range 0 - 35*2^24 into 0 - 65535 */
+ if (state->snr >= 8960 * 0x10000)
+ *strength = 0xffff;
+ else
+ *strength = state->snr / 8960;
return 0;
}
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 2bf124b5368..048d7cfe12d 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -39,6 +39,7 @@
#include <linux/slab.h>
#include <asm/byteorder.h>
+#include "dvb_math.h"
#include "dvb_frontend.h"
#include "or51211.h"
@@ -63,6 +64,7 @@ struct or51211_state {
/* Demodulator private data */
u8 initialized:1;
+ u32 snr; /* Result of last SNR claculation */
/* Tuner private data */
u32 current_frequency;
@@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
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};
+/* Calculate SNR estimation (scaled by 2^24)
-static unsigned int i20Log10(unsigned short val)
-{
- unsigned int rntval = 100;
- unsigned int tmp = val;
- unsigned int exp = 1;
+ 8-VSB SNR equation from Oren datasheets
- while(tmp > 100) {tmp /= 100; exp++;}
+ For 8-VSB:
+ SNR[dB] = 10 * log10(219037.9454 / MSE^2 )
- val = (2 * val)/denom[exp];
- if (exp > 1) rntval = 2000*exp;
+ We re-write the snr equation as:
+ SNR * 2^24 = 10*(c - 2*intlog10(MSE))
+ Where for 8-VSB, c = log10(219037.9454) * 2^24 */
- rntval += i100x20log10[val];
- return rntval;
+static u32 calculate_snr(u32 mse, u32 c)
+{
+ if (mse == 0) /* No signal */
+ return 0;
+
+ mse = 2*intlog10(mse);
+ if (mse > c) {
+ /* Negative SNR, which is possible, but realisticly the
+ demod will lose lock before the signal gets this bad. The
+ API only allows for unsigned values, so just return 0 */
+ return 0;
+ }
+ return 10*(c - mse);
}
-static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+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];
- u8 snr_equ;
- u32 signal_strength;
+ u8 snd_buf[3];
/* 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");
+ printk(KERN_WARNING "%s: error writing snr reg\n",
+ __FUNCTION__);
return -1;
}
- msleep(3);
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
- printk(KERN_WARNING "or51211: read_status read error\n");
+ printk(KERN_WARNING "%s: read_status read error\n",
+ __FUNCTION__);
return -1;
}
- snr_equ = rec_buf[0] & 0xff;
- /* The value reported back from the frontend will be FFFF=100% 0000=0% */
- signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000;
- if (signal_strength > 0xffff)
- *strength = 0xffff;
- else
- *strength = signal_strength;
- dprintk("read_signal_strength %i\n",*strength);
+ state->snr = calculate_snr(rec_buf[0], 89599047);
+ *snr = (state->snr) >> 16;
+
+ dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
+ state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
return 0;
}
-static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
+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];
-
- /* 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);
+ /* Calculate Strength from SNR up to 35dB */
+ /* Even though the SNR can go higher than 35dB, there is some comfort */
+ /* factor in having a range of strong signals that can show at 100% */
+ struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
+ u16 snr;
+ int ret;
+
+ ret = fe->ops.read_snr(fe, &snr);
+ if (ret != 0)
+ return ret;
+ /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+ /* scale the range 0 - 35*2^24 into 0 - 65535 */
+ if (state->snr >= 8960 * 0x10000)
+ *strength = 0xffff;
+ else
+ *strength = state->snr / 8960;
return 0;
}
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 11e0dca9a2d..00e4bcd9f1a 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe)
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities
break;
- case TDA10046_AGC_TDA827X:
+ case TDA10046_AGC_TDA827X_GP11:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
break;
- case TDA10046_AGC_TDA827X_GPL:
+ case TDA10046_AGC_TDA827X_GP00:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
break;
+ case TDA10046_AGC_TDA827X_GP01:
+ tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
+ tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
+ tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
+ tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities
+ break;
}
tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
index 605ad2dfc09..ec502d71b83 100644
--- a/drivers/media/dvb/frontends/tda1004x.h
+++ b/drivers/media/dvb/frontends/tda1004x.h
@@ -35,8 +35,9 @@ enum tda10046_agc {
TDA10046_AGC_DEFAULT, /* original configuration */
TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */
TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */
- TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */
- TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */
+ TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */
+ TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */
+ TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/
};
enum tda10046_if {
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 3aa45ebbac3..67415c9db6f 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
if (sync & 0x10)
*status |= FE_HAS_SYNC;
+ if (sync & 0x20) /* frontend can not lock */
+ *status |= FE_TIMEDOUT;
+
if ((sync & 0x1f) == 0x1f)
*status |= FE_HAS_LOCK;
return 0;
}
+static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct tda8083_state* state = fe->demodulator_priv;
+ int ret;
+ u8 buf[3];
+
+ if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
+ return ret;
+
+ *ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
+
+ return 0;
+}
+
static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct tda8083_state* state = fe->demodulator_priv;
@@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
return 0;
}
+static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ struct tda8083_state* state = fe->demodulator_priv;
+
+ *ucblocks = tda8083_readreg(state, 0x0f);
+ if (*ucblocks == 0xff)
+ *ucblocks = 0xffffffff;
+
+ return 0;
+}
+
static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct tda8083_state* state = fe->demodulator_priv;
@@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = {
.read_status = tda8083_read_status,
.read_signal_strength = tda8083_read_signal_strength,
.read_snr = tda8083_read_snr,
+ .read_ber = tda8083_read_ber,
+ .read_ucblocks = tda8083_read_ucblocks,
.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
.diseqc_send_burst = tda8083_diseqc_send_burst,
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
index 34815b0b97e..79f971dc52b 100644
--- a/drivers/media/dvb/frontends/tda826x.c
+++ b/drivers/media/dvb/frontends/tda826x.c
@@ -42,8 +42,7 @@ struct tda826x_priv {
static int tda826x_release(struct dvb_frontend *fe)
{
- if (fe->tuner_priv)
- kfree(fe->tuner_priv);
+ kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;
}
@@ -133,18 +132,21 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
{
struct tda826x_priv *priv = NULL;
u8 b1 [] = { 0, 0 };
- struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 };
+ struct i2c_msg msg[2] = {
+ { .addr = addr, .flags = 0, .buf = NULL, .len = 0 },
+ { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }
+ };
int ret;
dprintk("%s:\n", __FUNCTION__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- ret = i2c_transfer (i2c, &msg, 1);
+ ret = i2c_transfer (i2c, msg, 2);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- if (ret != 1)
+ if (ret != 2)
return NULL;
if (!(b1[1] & 0x80))
return NULL;
diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c
index 88554393a9b..6ba0029dcf2 100644
--- a/drivers/media/dvb/frontends/tua6100.c
+++ b/drivers/media/dvb/frontends/tua6100.c
@@ -43,8 +43,7 @@ struct tua6100_priv {
static int tua6100_release(struct dvb_frontend *fe)
{
- if (fe->tuner_priv)
- kfree(fe->tuner_priv);
+ kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;
}
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 8e4ce101eb2..ffda71dfdd6 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -650,7 +650,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
/* dvb */
ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
if (ret < 0)
- goto err_i2c_bit_del_bus;
+ goto err_i2c_del_adapter;
dvb_adapter = &pluto->dvb_adapter;
@@ -712,8 +712,8 @@ err_dvb_dmx_release:
dvb_dmx_release(dvbdemux);
err_dvb_unregister_adapter:
dvb_unregister_adapter(dvb_adapter);
-err_i2c_bit_del_bus:
- i2c_bit_del_bus(&pluto->i2c_adap);
+err_i2c_del_adapter:
+ i2c_del_adapter(&pluto->i2c_adap);
err_pluto_hw_exit:
pluto_hw_exit(pluto);
err_free_irq:
@@ -748,7 +748,7 @@ static void __devexit pluto2_remove(struct pci_dev *pdev)
dvb_dmxdev_release(&pluto->dmxdev);
dvb_dmx_release(dvbdemux);
dvb_unregister_adapter(dvb_adapter);
- i2c_bit_del_bus(&pluto->i2c_adap);
+ i2c_del_adapter(&pluto->i2c_adap);
pluto_hw_exit(pluto);
free_irq(pdev->irq, pluto);
pci_iounmap(pdev, pluto->io_mem);
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 95531a62499..eec7ccf41f8 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -92,6 +92,7 @@ config DVB_BUDGET_CI
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+ select VIDEO_IR
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index bba23bcd1b1..366c1371ee9 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension av7110_extension = {
.name = "dvb",
- .flags = SAA7146_I2C_SHORT_DELAY,
+ .flags = SAA7146_USE_I2C_IRQ,
.module = THIS_MODULE,
.pci_tbl = &pci_tbl[0],
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index d54bbcdde2c..e4544ea2b89 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data)
if (!data || !test_bit(data, input_dev->key))
return;
- input_event(input_dev, EV_KEY, data, !!0);
+ input_report_key(input_dev, data, 0);
+ input_sync(input_dev);
}
@@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm)
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
delay_timer_finished = 0;
- input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
- input_event(input_dev, EV_KEY, keycode, !0);
- } else
- if (delay_timer_finished)
- input_event(input_dev, EV_KEY, keycode, 2);
+ input_event(input_dev, EV_KEY, keyup_timer.data, 0);
+ input_event(input_dev, EV_KEY, keycode, 1);
+ input_sync(input_dev);
+ } else if (delay_timer_finished) {
+ input_event(input_dev, EV_KEY, keycode, 2);
+ input_sync(input_dev);
+ }
} else {
delay_timer_finished = 0;
- input_event(input_dev, EV_KEY, keycode, !0);
+ input_event(input_dev, EV_KEY, keycode, 1);
+ input_sync(input_dev);
}
keyup_timer.expires = jiffies + UP_TIMEOUT;
@@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom)
int __devinit av7110_ir_init(struct av7110 *av7110)
{
static struct proc_dir_entry *e;
+ int err;
if (av_cnt >= sizeof av_list/sizeof av_list[0])
return -ENOSPC;
@@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_REP, input_dev->evbit);
input_register_keys();
- input_register_device(input_dev);
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
input_dev->timer.function = input_repeat_key;
e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 2235ff8b8a1..89ab4b59155 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av)
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
/* Enable DEBI pins */
- saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
+ saa7146_write(saa, MC1, MASK_27 | MASK_11);
/* register CI interface */
budget_av->ca.owner = THIS_MODULE;
@@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av)
return 0;
error:
- saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+ saa7146_write(saa, MC1, MASK_27);
return result;
}
@@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av)
dvb_ca_en50221_release(&budget_av->ca);
/* disable DEBI pins */
- saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+ saa7146_write(saa, MC1, MASK_27);
}
@@ -655,6 +655,10 @@ static struct tda10021_config philips_cu1216_config = {
.demod_address = 0x0c,
};
+static struct tda10021_config philips_cu1216_config_altaddress = {
+ .demod_address = 0x0d,
+};
+
@@ -831,7 +835,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
return -EINVAL;
rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
- params->frequency, 0);
+ params->frequency, 0);
if(rc < 0) return rc;
if (fe->ops.i2c_gate_ctrl)
@@ -914,6 +918,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_TV_STAR_CI 0x0016
#define SUBID_DVBS_EASYWATCH_1 0x001a
#define SUBID_DVBS_EASYWATCH 0x001e
+#define SUBID_DVBC_EASYWATCH 0x002a
#define SUBID_DVBC_KNC1 0x0020
#define SUBID_DVBC_KNC1_PLUS 0x0021
#define SUBID_DVBC_CINERGY1200 0x1156
@@ -947,11 +952,15 @@ static void frontend_init(struct budget_av *budget_av)
/* Enable / PowerON Frontend */
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+ /* Wait for PowerON */
+ msleep(100);
+
/* additional setup necessary for the PLUS cards */
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBC_KNC1_PLUS:
case SUBID_DVBT_KNC1_PLUS:
+ case SUBID_DVBC_EASYWATCH:
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
}
@@ -1006,10 +1015,15 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_KNC1:
case SUBID_DVBC_KNC1_PLUS:
case SUBID_DVBC_CINERGY1200:
+ case SUBID_DVBC_EASYWATCH:
budget_av->reinitialise_demod = 1;
fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
&budget_av->budget.i2c_adap,
read_pwm(budget_av));
+ if (fe == NULL)
+ fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
+ &budget_av->budget.i2c_adap,
+ read_pwm(budget_av));
if (fe) {
budget_av->tda10021_poclkp = 1;
budget_av->tda10021_set_frontend = fe->ops.set_frontend;
@@ -1242,6 +1256,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
@@ -1260,6 +1275,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
+ MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
@@ -1277,7 +1293,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension budget_extension = {
.name = "budget_av",
- .flags = SAA7146_I2C_SHORT_DELAY,
+ .flags = SAA7146_USE_I2C_IRQ,
.pci_tbl = pci_tbl,
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index cd5ec489af1..f2066b47bae 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -37,6 +37,7 @@
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/spinlock.h>
+#include <media/ir-common.h>
#include "dvb_ca_en50221.h"
#include "stv0299.h"
@@ -72,162 +73,218 @@
#define SLOTSTATUS_READY 8
#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+/* Milliseconds during which key presses are regarded as key repeat and during
+ * which the debounce logic is active
+ */
+#define IR_REPEAT_TIMEOUT 350
+
+/* RC5 device wildcard */
+#define IR_DEVICE_ANY 255
+
+/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
+ * this setting allows the superflous sequences to be ignored
+ */
+static int debounce = 0;
+module_param(debounce, int, 0644);
+MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
+
+static int rc5_device = -1;
+module_param(rc5_device, int, 0644);
+MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+struct budget_ci_ir {
+ struct input_dev *dev;
+ struct tasklet_struct msp430_irq_tasklet;
+ char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
+ char phys[32];
+ struct ir_input_state state;
+ int rc5_device;
+};
+
struct budget_ci {
struct budget budget;
- struct input_dev *input_dev;
- struct tasklet_struct msp430_irq_tasklet;
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
int ci_irq;
struct dvb_ca_en50221 ca;
- char ir_dev_name[50];
+ struct budget_ci_ir ir;
u8 tuner_pll_address; /* used for philips_tdm1316l configs */
};
-/* from reading the following remotes:
- Zenith Universal 7 / TV Mode 807 / VCR Mode 837
- 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] = {
- /* 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_MUTE,
- 0,
- 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_BREAK,
- /* 0x2X */
- KEY_CHANNELUP, KEY_CHANNELDOWN,
- KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
- 0, KEY_RESTART, KEY_OK,
- KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
- 0,
- KEY_ENTER, /* VCR mode on Zenith */
- KEY_PAUSE,
- 0,
- KEY_RIGHT, KEY_LEFT,
- 0,
- KEY_MENU, /* FULL SCREEN on Hauppauge */
- 0,
- /* 0x3X */
- KEY_SLOW,
- KEY_PREVIOUS, /* VCR mode on Zenith */
- KEY_REWIND,
- 0,
- KEY_FASTFORWARD,
- KEY_PLAY, KEY_STOP,
- KEY_RECORD,
- KEY_TUNER, /* TV/VCR on Zenith */
- 0,
- KEY_C,
- 0,
- KEY_EXIT,
- KEY_POWER2,
- KEY_TUNER, /* VCR mode on Zenith */
- 0,
-};
-
-static void msp430_ir_debounce(unsigned long data)
+static void msp430_ir_keyup(unsigned long data)
{
- struct input_dev *dev = (struct input_dev *) data;
-
- if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
- input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
- return;
- }
-
- 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 */
+ struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
+ ir_input_nokey(ir->dev, &ir->state);
}
static void msp430_ir_interrupt(unsigned long 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;
+ struct input_dev *dev = budget_ci->ir.dev;
+ static int bounces = 0;
+ int device;
+ int toggle;
+ static int prev_toggle = -1;
+ static u32 ir_key;
+ u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+
+ /*
+ * The msp430 chip can generate two different bytes, command and device
+ *
+ * type1: X1CCCCCC, C = command bits (0 - 63)
+ * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
+ *
+ * More than one command byte may be generated before the device byte
+ * Only when we have both, a correct keypress is generated
+ */
+
+ /* Is this a RC5 command byte? */
+ if (command & 0x40) {
+ if (ir_debug)
+ printk("budget_ci: received command byte 0x%02x\n", command);
+ ir_key = command & 0x3f;
+ return;
+ }
- if (code & 0x40) {
- code &= 0x3f;
+ /* It's a RC5 device byte */
+ if (ir_debug)
+ printk("budget_ci: received device byte 0x%02x\n", command);
+ device = command & 0x1f;
+ toggle = command & 0x20;
- 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 (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
+ return;
- if (!key_map[code]) {
- printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
- return;
- }
+ /* Ignore repeated key sequences if requested */
+ if (toggle == prev_toggle && ir_key == dev->repeat_key &&
+ bounces > 0 && timer_pending(&dev->timer)) {
+ if (ir_debug)
+ printk("budget_ci: debounce logic ignored IR command\n");
+ bounces--;
+ return;
+ }
+ prev_toggle = toggle;
- /* initialize debounce and repeat */
- dev->repeat_key = code;
- /* Zenith remote _always_ sends 2 sequences */
- dev->rep[0] = ~0;
- /* 350 milliseconds */
- dev->timer.expires = jiffies + HZ * 350 / 1000;
- /* MAKE */
- input_event(dev, EV_KEY, key_map[code], !0);
- add_timer(&dev->timer);
+ /* Are we still waiting for a keyup event? */
+ if (del_timer(&dev->timer))
+ ir_input_nokey(dev, &budget_ci->ir.state);
+
+ /* Generate keypress */
+ if (ir_debug)
+ printk("budget_ci: generating keypress 0x%02x\n", ir_key);
+ ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8)));
+
+ /* Do we want to delay the keyup event? */
+ if (debounce) {
+ bounces = debounce;
+ mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
+ } else {
+ ir_input_nokey(dev, &budget_ci->ir.state);
}
}
static int msp430_ir_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
- struct input_dev *input_dev;
- int i;
+ struct input_dev *input_dev = budget_ci->ir.dev;
+ int error;
+
+ budget_ci->ir.dev = input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
+ error = -ENOMEM;
+ goto out1;
+ }
+
+ snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
+ "Budget-CI dvb ir receiver %s", saa->name);
+ snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
+ "pci-%s/ir0", pci_name(saa->pci));
- budget_ci->input_dev = input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
+ input_dev->name = budget_ci->ir.name;
- sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
+ input_dev->phys = budget_ci->ir.phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
+ if (saa->pci->subsystem_vendor) {
+ input_dev->id.vendor = saa->pci->subsystem_vendor;
+ input_dev->id.product = saa->pci->subsystem_device;
+ } else {
+ input_dev->id.vendor = saa->pci->vendor;
+ input_dev->id.product = saa->pci->device;
+ }
+ input_dev->cdev.dev = &saa->pci->dev;
- input_dev->name = budget_ci->ir_dev_name;
+ /* Select keymap and address */
+ switch (budget_ci->budget.dev->pci->subsystem_device) {
+ case 0x100c:
+ case 0x100f:
+ case 0x1010:
+ case 0x1011:
+ case 0x1012:
+ case 0x1017:
+ /* The hauppauge keymap is a superset of these remotes */
+ ir_input_init(input_dev, &budget_ci->ir.state,
+ IR_TYPE_RC5, ir_codes_hauppauge_new);
+
+ if (rc5_device < 0)
+ budget_ci->ir.rc5_device = 0x1f;
+ else
+ budget_ci->ir.rc5_device = rc5_device;
+ break;
+ default:
+ /* unknown remote */
+ ir_input_init(input_dev, &budget_ci->ir.state,
+ IR_TYPE_RC5, ir_codes_budget_ci_old);
+
+ if (rc5_device < 0)
+ budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+ else
+ budget_ci->ir.rc5_device = rc5_device;
+ break;
+ }
- set_bit(EV_KEY, input_dev->evbit);
- for (i = 0; i < ARRAY_SIZE(key_map); i++)
- if (key_map[i])
- set_bit(key_map[i], input_dev->keybit);
+ /* initialise the key-up debounce timeout handler */
+ input_dev->timer.function = msp430_ir_keyup;
+ input_dev->timer.data = (unsigned long) &budget_ci->ir;
- input_register_device(budget_ci->input_dev);
+ error = input_register_device(input_dev);
+ if (error) {
+ printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
+ goto out2;
+ }
- input_dev->timer.function = msp430_ir_debounce;
+ tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
+ (unsigned long) budget_ci);
- saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
+ SAA7146_IER_ENABLE(saa, MASK_06);
saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
return 0;
+
+out2:
+ input_free_device(input_dev);
+out1:
+ return error;
}
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;
+ struct input_dev *dev = budget_ci->ir.dev;
- saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
+ SAA7146_IER_DISABLE(saa, MASK_06);
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
+ tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
- if (del_timer(&dev->timer))
- input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+ if (del_timer(&dev->timer)) {
+ ir_input_nokey(dev, &budget_ci->ir.state);
+ input_sync(dev);
+ }
input_unregister_device(dev);
}
@@ -428,7 +485,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
// enable DEBI pins
- saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
+ saa7146_write(saa, MC1, MASK_27 | MASK_11);
// test if it is there
ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
@@ -480,7 +537,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
} else {
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
}
- saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
+ SAA7146_IER_ENABLE(saa, MASK_03);
}
// enable interface
@@ -502,7 +559,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
return 0;
error:
- saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+ saa7146_write(saa, MC1, MASK_27);
return result;
}
@@ -512,7 +569,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
// disable CI interrupts
if (budget_ci->ci_irq) {
- saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
+ SAA7146_IER_DISABLE(saa, MASK_03);
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
tasklet_kill(&budget_ci->ciintf_irq_tasklet);
}
@@ -530,7 +587,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
dvb_ca_en50221_release(&budget_ci->ca);
// disable DEBI pins
- saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
+ saa7146_write(saa, MC1, MASK_27);
}
static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
@@ -540,7 +597,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
if (*isr & MASK_06)
- tasklet_schedule(&budget_ci->msp430_irq_tasklet);
+ tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
if (*isr & MASK_10)
ttpci_budget_irq10_handler(dev, isr);
@@ -835,7 +892,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
band = 1;
} else if (tuner_frequency < 200000000) {
cp = 6;
- band = 1;
+ band = 2;
} else if (tuner_frequency < 290000000) {
cp = 3;
band = 2;
@@ -1083,24 +1140,23 @@ 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)))
- return -ENOMEM;
+ budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
+ if (!budget_ci) {
+ err = -ENOMEM;
+ goto out1;
+ }
dprintk(2, "budget_ci: %p\n", budget_ci);
- budget_ci->budget.ci_present = 0;
-
dev->ext_priv = budget_ci;
- if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) {
- kfree(budget_ci);
- return err;
- }
-
- tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
- (unsigned long) budget_ci);
+ err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
+ if (err)
+ goto out2;
- msp430_ir_init(budget_ci);
+ err = msp430_ir_init(budget_ci);
+ if (err)
+ goto out3;
ciintf_init(budget_ci);
@@ -1110,6 +1166,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
ttpci_budget_init_hooks(&budget_ci->budget);
return 0;
+
+out3:
+ ttpci_budget_deinit(&budget_ci->budget);
+out2:
+ kfree(budget_ci);
+out1:
+ return err;
}
static int budget_ci_detach(struct saa7146_dev *dev)
@@ -1120,16 +1183,13 @@ static int budget_ci_detach(struct saa7146_dev *dev)
if (budget_ci->budget.ci_present)
ciintf_deinit(budget_ci);
+ msp430_ir_deinit(budget_ci);
if (budget_ci->budget.dvb_frontend) {
dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
dvb_frontend_detach(budget_ci->budget.dvb_frontend);
}
err = ttpci_budget_deinit(&budget_ci->budget);
- tasklet_kill(&budget_ci->msp430_irq_tasklet);
-
- msp430_ir_deinit(budget_ci);
-
// disable frontend and CI interface
saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
@@ -1162,7 +1222,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension budget_extension = {
.name = "budget_ci dvb",
- .flags = SAA7146_I2C_SHORT_DELAY,
+ .flags = SAA7146_USE_I2C_IRQ,
.module = THIS_MODULE,
.pci_tbl = &pci_tbl[0],
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 56f1c80defc..9268a82bada 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension budget_extension = {
.name = "budget dvb",
- .flags = SAA7146_I2C_SHORT_DELAY,
+ .flags = SAA7146_USE_I2C_IRQ,
.module = THIS_MODULE,
.pci_tbl = pci_tbl,
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 10b121ada83..bd6e7baae2e 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
* 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_sync(dec->rc_input_dev);
input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
input_sync(dec->rc_input_dev);
}
@@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
struct input_dev *input_dev;
u8 b[] = { 0x00, 0x01 };
int i;
+ int err;
usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
- dec->rc_input_dev = input_dev = input_allocate_device();
+ input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
@@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
set_bit(rc_keys[i], input_dev->keybit);
- input_register_device(input_dev);
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+ dec->rc_input_dev = input_dev;
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
/* enable irq pipe */
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 42f39a89bc4..a6fb1d6a7b5 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -195,7 +195,7 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf
struct ttusbdecfe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
if (state == NULL)
return NULL;
@@ -215,7 +215,7 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
struct ttusbdecfe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
if (state == NULL)
return NULL;
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index b8fde5cf473..57357db31b8 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -184,6 +184,14 @@ config VIDEO_KS0127
To compile this driver as a module, choose M here: the
module will be called ks0127.
+config VIDEO_OV7670
+ tristate "OmniVision OV7670 sensor support"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This is a Video4Linux2 sensor-level driver for the OmniVision
+ OV7670 VGA camera. It currently only works with the M88ALP01
+ controller.
+
config VIDEO_SAA7110
tristate "Philips SAA7110 video decoder"
depends on VIDEO_V4L1 && I2C
@@ -567,18 +575,6 @@ config VIDEO_ZORAN_AVS6EYES
help
Support for the AverMedia 6 Eyes video surveillance card.
-config VIDEO_ZR36120
- tristate "Zoran ZR36120/36125 Video For Linux"
- depends on PCI && I2C && VIDEO_V4L1 && BROKEN
- help
- Support for ZR36120/ZR36125 based frame grabber/overlay boards.
- This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV,
- and Buster boards. Please read the material in
- <file:Documentation/video4linux/zr36120.txt> for more information.
-
- To compile this driver as a module, choose M here: the
- module will be called zr36120.
-
config VIDEO_MEYE
tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
depends on PCI && SONYPI && VIDEO_V4L1
@@ -670,6 +666,15 @@ config VIDEO_M32R_AR_M64278
To compile this driver as a module, choose M here: the
module will be called arv.
+config VIDEO_CAFE_CCIC
+ tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support"
+ depends on PCI && I2C && VIDEO_V4L2
+ select VIDEO_OV7670
+ ---help---
+ This is a video4linux2 driver for the Marvell 88ALP01 integrated
+ CMOS camera controller. This is the controller found on first-
+ generation OLPC systems.
+
#
# USB Multimedia device configuration
#
@@ -681,6 +686,8 @@ source "drivers/media/video/pvrusb2/Kconfig"
source "drivers/media/video/em28xx/Kconfig"
+source "drivers/media/video/usbvision/Kconfig"
+
source "drivers/media/video/usbvideo/Kconfig"
source "drivers/media/video/et61x251/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index af57abce8a6..9b1f3f06bb7 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -2,7 +2,6 @@
# Makefile for the video capture/playback device drivers.
#
-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-types.o tuner-simple.o \
@@ -23,7 +22,6 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
-obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
@@ -64,6 +62,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o
obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/
obj-$(CONFIG_VIDEO_CX88) += cx88/
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
@@ -92,6 +91,9 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
+obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
+obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
obj-$(CONFIG_USB_SE401) += se401.o
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 6e1ddad9f0c..ab8f970760f 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
memset(i,0,sizeof(*i));
i->index = n;
i->type = V4L2_INPUT_TYPE_CAMERA;
- i->audioset = 0;
+ i->audioset = 1;
if (i->index == bttv_tvcards[btv->c.type].tuner) {
sprintf(i->name, "Television");
i->type = V4L2_INPUT_TYPE_TUNER;
@@ -4050,8 +4050,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
(unsigned long long)pci_resource_start(dev,0));
schedule();
- btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000);
- if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) {
+ btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+ if (NULL == btv->bt848_mmio) {
printk("bttv%d: ioremap() failed\n", btv->c.nr);
result = -EIO;
goto fail1;
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index 70de6c96e20..62b873076e0 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -479,11 +479,7 @@ int __devexit fini_bttv_i2c(struct bttv *btv)
if (0 != btv->i2c_rc)
return 0;
- if (btv->use_i2c_hw) {
- return i2c_del_adapter(&btv->c.i2c_adap);
- } else {
- return i2c_bit_del_bus(&btv->c.i2c_adap);
- }
+ return i2c_del_adapter(&btv->c.i2c_adap);
}
/*
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 933d6db09ac..cbc012f71f5 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data)
/* ---------------------------------------------------------------------- */
+static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+{
+ if (ir->polling) {
+ init_timer(&ir->timer);
+ ir->timer.function = bttv_input_timer;
+ ir->timer.data = (unsigned long)btv;
+ ir->timer.expires = jiffies + HZ;
+ add_timer(&ir->timer);
+ } else if (ir->rc5_gpio) {
+ /* set timer_end for code completion */
+ init_timer(&ir->timer_end);
+ ir->timer_end.function = bttv_rc5_timer_end;
+ ir->timer_end.data = (unsigned long)ir;
+
+ init_timer(&ir->timer_keyup);
+ ir->timer_keyup.function = bttv_rc5_timer_keyup;
+ ir->timer_keyup.data = (unsigned long)ir;
+ }
+}
+
+static void bttv_ir_stop(struct bttv *btv)
+{
+ if (btv->remote->polling) {
+ del_timer_sync(&btv->remote->timer);
+ flush_scheduled_work();
+ }
+
+ if (btv->remote->rc5_gpio) {
+ u32 gpio;
+
+ del_timer_sync(&btv->remote->timer_end);
+ flush_scheduled_work();
+
+ gpio = bttv_gpio_read(&btv->c);
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+ }
+}
+
int bttv_input_init(struct bttv *btv)
{
struct bttv_ir *ir;
IR_KEYTAB_TYPE *ir_codes = NULL;
struct input_dev *input_dev;
int ir_type = IR_TYPE_OTHER;
+ int err = -ENOMEM;
if (!btv->has_remote)
return -ENODEV;
ir = kzalloc(sizeof(*ir),GFP_KERNEL);
input_dev = input_allocate_device();
- if (!ir || !input_dev) {
- kfree(ir);
- input_free_device(input_dev);
- return -ENOMEM;
- }
- memset(ir,0,sizeof(*ir));
+ if (!ir || !input_dev)
+ goto err_out_free;
/* detect & configure */
switch (btv->c.type) {
@@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv)
break;
}
if (NULL == ir_codes) {
- dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
- kfree(ir);
- input_free_device(input_dev);
- return -ENODEV;
+ dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+ err = -ENODEV;
+ goto err_out_free;
}
if (ir->rc5_gpio) {
@@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv)
input_dev->cdev.dev = &btv->c.pci->dev;
btv->remote = ir;
- if (ir->polling) {
- init_timer(&ir->timer);
- ir->timer.function = bttv_input_timer;
- ir->timer.data = (unsigned long)btv;
- ir->timer.expires = jiffies + HZ;
- add_timer(&ir->timer);
- } else if (ir->rc5_gpio) {
- /* set timer_end for code completion */
- init_timer(&ir->timer_end);
- ir->timer_end.function = bttv_rc5_timer_end;
- ir->timer_end.data = (unsigned long)ir;
-
- init_timer(&ir->timer_keyup);
- ir->timer_keyup.function = bttv_rc5_timer_keyup;
- ir->timer_keyup.data = (unsigned long)ir;
- }
+ bttv_ir_start(btv, ir);
/* all done */
- input_register_device(btv->remote->dev);
- printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
+ err = input_register_device(btv->remote->dev);
+ if (err)
+ goto err_out_stop;
/* the remote isn't as bouncy as a keyboard */
ir->dev->rep[REP_DELAY] = repeat_delay;
ir->dev->rep[REP_PERIOD] = repeat_period;
return 0;
+
+ err_out_stop:
+ bttv_ir_stop(btv);
+ btv->remote = NULL;
+ err_out_free:
+ input_free_device(input_dev);
+ kfree(ir);
+ return err;
}
void bttv_input_fini(struct bttv *btv)
@@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv)
if (btv->remote == NULL)
return;
- if (btv->remote->polling) {
- del_timer_sync(&btv->remote->timer);
- flush_scheduled_work();
- }
-
-
- if (btv->remote->rc5_gpio) {
- u32 gpio;
-
- del_timer_sync(&btv->remote->timer_end);
- flush_scheduled_work();
-
- gpio = bttv_gpio_read(&btv->c);
- bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
- }
-
+ bttv_ir_stop(btv);
input_unregister_device(btv->remote->dev);
kfree(btv->remote);
btv->remote = NULL;
diff --git a/drivers/media/video/cafe_ccic-regs.h b/drivers/media/video/cafe_ccic-regs.h
new file mode 100644
index 00000000000..b2c22a0d664
--- /dev/null
+++ b/drivers/media/video/cafe_ccic-regs.h
@@ -0,0 +1,160 @@
+/*
+ * Register definitions for the m88alp01 camera interface. Offsets in bytes
+ * as given in the spec.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc.
+ *
+ * Written by Jonathan Corbet, corbet@lwn.net.
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+#define REG_Y0BAR 0x00
+#define REG_Y1BAR 0x04
+#define REG_Y2BAR 0x08
+/* ... */
+
+#define REG_IMGPITCH 0x24 /* Image pitch register */
+#define IMGP_YP_SHFT 2 /* Y pitch params */
+#define IMGP_YP_MASK 0x00003ffc /* Y pitch field */
+#define IMGP_UVP_SHFT 18 /* UV pitch (planar) */
+#define IMGP_UVP_MASK 0x3ffc0000
+#define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */
+#define IRQ_EOF0 0x00000001 /* End of frame 0 */
+#define IRQ_EOF1 0x00000002 /* End of frame 1 */
+#define IRQ_EOF2 0x00000004 /* End of frame 2 */
+#define IRQ_SOF0 0x00000008 /* Start of frame 0 */
+#define IRQ_SOF1 0x00000010 /* Start of frame 1 */
+#define IRQ_SOF2 0x00000020 /* Start of frame 2 */
+#define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */
+#define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */
+#define IRQ_TWSIR 0x00020000 /* TWSI read */
+#define IRQ_TWSIE 0x00040000 /* TWSI error */
+#define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE)
+#define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2)
+#define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
+#define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */
+#define REG_IRQSTAT 0x30 /* IRQ status / clear */
+
+#define REG_IMGSIZE 0x34 /* Image size */
+#define IMGSZ_V_MASK 0x1fff0000
+#define IMGSZ_V_SHIFT 16
+#define IMGSZ_H_MASK 0x00003fff
+#define REG_IMGOFFSET 0x38 /* IMage offset */
+
+#define REG_CTRL0 0x3c /* Control 0 */
+#define C0_ENABLE 0x00000001 /* Makes the whole thing go */
+
+/* Mask for all the format bits */
+#define C0_DF_MASK 0x00fffffc /* Bits 2-23 */
+
+/* RGB ordering */
+#define C0_RGB4_RGBX 0x00000000
+#define C0_RGB4_XRGB 0x00000004
+#define C0_RGB4_BGRX 0x00000008
+#define C0_RGB4_XBGR 0x0000000c
+#define C0_RGB5_RGGB 0x00000000
+#define C0_RGB5_GRBG 0x00000004
+#define C0_RGB5_GBRG 0x00000008
+#define C0_RGB5_BGGR 0x0000000c
+
+/* Spec has two fields for DIN and DOUT, but they must match, so
+ combine them here. */
+#define C0_DF_YUV 0x00000000 /* Data is YUV */
+#define C0_DF_RGB 0x000000a0 /* ... RGB */
+#define C0_DF_BAYER 0x00000140 /* ... Bayer */
+/* 8-8-8 must be missing from the below - ask */
+#define C0_RGBF_565 0x00000000
+#define C0_RGBF_444 0x00000800
+#define C0_RGB_BGR 0x00001000 /* Blue comes first */
+#define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */
+#define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */
+#define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */
+/* Think that 420 packed must be 111 - ask */
+#define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */
+#define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */
+#define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */
+#define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */
+#define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */
+#define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */
+#define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */
+#define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */
+/* Bayer bits 18,19 if needed */
+#define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */
+#define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */
+#define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */
+#define C0_DOWNSCALE 0x08000000 /* Enable downscaler */
+#define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */
+#define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */
+#define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */
+
+
+#define REG_CTRL1 0x40 /* Control 1 */
+#define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */
+#define C1_ALPHA_SHFT 20
+#define C1_DMAB32 0x00000000 /* 32-byte DMA burst */
+#define C1_DMAB16 0x02000000 /* 16-byte DMA burst */
+#define C1_DMAB64 0x04000000 /* 64-byte DMA burst */
+#define C1_DMAB_MASK 0x06000000
+#define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */
+#define C1_PWRDWN 0x10000000 /* Power down */
+
+#define REG_CLKCTRL 0x88 /* Clock control */
+#define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */
+
+#define REG_GPR 0xb4 /* General purpose register. This
+ controls inputs to the power and reset
+ pins on the OV7670 used with OLPC;
+ other deployments could differ. */
+#define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */
+#define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */
+#define GPR_C1 0x00000002 /* Control 1 value */
+/*
+ * Control 0 is wired to reset on OLPC machines. For ov7x sensors,
+ * it is active low, for 0v6x, instead, it's active high. What
+ * fun.
+ */
+#define GPR_C0 0x00000001 /* Control 0 value */
+
+#define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */
+#define TWSIC0_EN 0x00000001 /* TWSI enable */
+#define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */
+#define TWSIC0_SID 0x000003fc /* Slave ID */
+#define TWSIC0_SID_SHIFT 2
+#define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */
+#define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */
+#define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */
+
+#define REG_TWSIC1 0xbc /* TWSI control 1 */
+#define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */
+#define TWSIC1_ADDR 0x00ff0000 /* Address (register) */
+#define TWSIC1_ADDR_SHIFT 16
+#define TWSIC1_READ 0x01000000 /* Set for read op */
+#define TWSIC1_WSTAT 0x02000000 /* Write status */
+#define TWSIC1_RVALID 0x04000000 /* Read data valid */
+#define TWSIC1_ERROR 0x08000000 /* Something screwed up */
+
+
+#define REG_UBAR 0xc4 /* Upper base address register */
+
+/*
+ * Here's the weird global control registers which are said to live
+ * way up here.
+ */
+#define REG_GL_CSR 0x3004 /* Control/status register */
+#define GCSR_SRS 0x00000001 /* SW Reset set */
+#define GCSR_SRC 0x00000002 /* SW Reset clear */
+#define GCSR_MRS 0x00000004 /* Master reset set */
+#define GCSR_MRC 0x00000008 /* HW Reset clear */
+#define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */
+#define REG_GL_IMASK 0x300c /* Interrupt mask register */
+#define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */
+
+#define REG_LEN REG_GL_IMASK + 4
+
+
+/*
+ * Useful stuff that probably belongs somewhere global.
+ */
+#define VGA_WIDTH 640
+#define VGA_HEIGHT 480
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
new file mode 100644
index 00000000000..3083c8075d1
--- /dev/null
+++ b/drivers/media/video/cafe_ccic.c
@@ -0,0 +1,2228 @@
+/*
+ * A driver for the CMOS camera controller in the Marvell 88ALP01 "cafe"
+ * multifunction chip. Currently works with the Omnivision OV7670
+ * sensor.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc.
+ *
+ * Written by Jonathan Corbet, corbet@lwn.net.
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/jiffies.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include "cafe_ccic-regs.h"
+
+#define CAFE_VERSION 0x000001
+
+
+/*
+ * Parameters.
+ */
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
+MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Video");
+
+/*
+ * Internal DMA buffer management. Since the controller cannot do S/G I/O,
+ * we must have physically contiguous buffers to bring frames into.
+ * These parameters control how many buffers we use, whether we
+ * allocate them at load time (better chance of success, but nails down
+ * memory) or when somebody tries to use the camera (riskier), and,
+ * for load-time allocation, how big they should be.
+ *
+ * The controller can cycle through three buffers. We could use
+ * more by flipping pointers around, but it probably makes little
+ * sense.
+ */
+
+#define MAX_DMA_BUFS 3
+static int alloc_bufs_at_load = 0;
+module_param(alloc_bufs_at_load, bool, 0444);
+MODULE_PARM_DESC(alloc_bufs_at_load,
+ "Non-zero value causes DMA buffers to be allocated at module "
+ "load time. This increases the chances of successfully getting "
+ "those buffers, but at the cost of nailing down the memory from "
+ "the outset.");
+
+static int n_dma_bufs = 3;
+module_param(n_dma_bufs, uint, 0644);
+MODULE_PARM_DESC(n_dma_bufs,
+ "The number of DMA buffers to allocate. Can be either two "
+ "(saves memory, makes timing tighter) or three.");
+
+static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2; /* Worst case */
+module_param(dma_buf_size, uint, 0444);
+MODULE_PARM_DESC(dma_buf_size,
+ "The size of the allocated DMA buffers. If actual operating "
+ "parameters require larger buffers, an attempt to reallocate "
+ "will be made.");
+
+static int min_buffers = 1;
+module_param(min_buffers, uint, 0644);
+MODULE_PARM_DESC(min_buffers,
+ "The minimum number of streaming I/O buffers we are willing "
+ "to work with.");
+
+static int max_buffers = 10;
+module_param(max_buffers, uint, 0644);
+MODULE_PARM_DESC(max_buffers,
+ "The maximum number of streaming I/O buffers an application "
+ "will be allowed to allocate. These buffers are big and live "
+ "in vmalloc space.");
+
+static int flip = 0;
+module_param(flip, bool, 0444);
+MODULE_PARM_DESC(flip,
+ "If set, the sensor will be instructed to flip the image "
+ "vertically.");
+
+
+enum cafe_state {
+ S_NOTREADY, /* Not yet initialized */
+ S_IDLE, /* Just hanging around */
+ S_FLAKED, /* Some sort of problem */
+ S_SINGLEREAD, /* In read() */
+ S_SPECREAD, /* Speculative read (for future read()) */
+ S_STREAMING /* Streaming data */
+};
+
+/*
+ * Tracking of streaming I/O buffers.
+ */
+struct cafe_sio_buffer {
+ struct list_head list;
+ struct v4l2_buffer v4lbuf;
+ char *buffer; /* Where it lives in kernel space */
+ int mapcount;
+ struct cafe_camera *cam;
+};
+
+/*
+ * A description of one of our devices.
+ * Locking: controlled by s_mutex. Certain fields, however, require
+ * the dev_lock spinlock; they are marked as such by comments.
+ * dev_lock is also required for access to device registers.
+ */
+struct cafe_camera
+{
+ enum cafe_state state;
+ unsigned long flags; /* Buffer status, mainly (dev_lock) */
+ int users; /* How many open FDs */
+ struct file *owner; /* Who has data access (v4l2) */
+
+ /*
+ * Subsystem structures.
+ */
+ struct pci_dev *pdev;
+ struct video_device v4ldev;
+ struct i2c_adapter i2c_adapter;
+ struct i2c_client *sensor;
+
+ unsigned char __iomem *regs;
+ struct list_head dev_list; /* link to other devices */
+
+ /* DMA buffers */
+ unsigned int nbufs; /* How many are alloc'd */
+ int next_buf; /* Next to consume (dev_lock) */
+ unsigned int dma_buf_size; /* allocated size */
+ void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */
+ dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
+ unsigned int specframes; /* Unconsumed spec frames (dev_lock) */
+ unsigned int sequence; /* Frame sequence number */
+ unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual buffers */
+
+ /* Streaming buffers */
+ unsigned int n_sbufs; /* How many we have */
+ struct cafe_sio_buffer *sb_bufs; /* The array of housekeeping structs */
+ struct list_head sb_avail; /* Available for data (we own) (dev_lock) */
+ struct list_head sb_full; /* With data (user space owns) (dev_lock) */
+ struct tasklet_struct s_tasklet;
+
+ /* Current operating parameters */
+ enum v4l2_chip_ident sensor_type; /* Currently ov7670 only */
+ struct v4l2_pix_format pix_format;
+
+ /* Locks */
+ struct mutex s_mutex; /* Access to this structure */
+ spinlock_t dev_lock; /* Access to device */
+
+ /* Misc */
+ wait_queue_head_t smbus_wait; /* Waiting on i2c events */
+ wait_queue_head_t iowait; /* Waiting on frame data */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ struct dentry *dfs_regs;
+ struct dentry *dfs_cam_regs;
+#endif
+};
+
+/*
+ * Status flags. Always manipulated with bit operations.
+ */
+#define CF_BUF0_VALID 0 /* Buffers valid - first three */
+#define CF_BUF1_VALID 1
+#define CF_BUF2_VALID 2
+#define CF_DMA_ACTIVE 3 /* A frame is incoming */
+#define CF_CONFIG_NEEDED 4 /* Must configure hardware */
+
+
+
+/*
+ * Start over with DMA buffers - dev_lock needed.
+ */
+static void cafe_reset_buffers(struct cafe_camera *cam)
+{
+ int i;
+
+ cam->next_buf = -1;
+ for (i = 0; i < cam->nbufs; i++)
+ clear_bit(i, &cam->flags);
+ cam->specframes = 0;
+}
+
+static inline int cafe_needs_config(struct cafe_camera *cam)
+{
+ return test_bit(CF_CONFIG_NEEDED, &cam->flags);
+}
+
+static void cafe_set_config_needed(struct cafe_camera *cam, int needed)
+{
+ if (needed)
+ set_bit(CF_CONFIG_NEEDED, &cam->flags);
+ else
+ clear_bit(CF_CONFIG_NEEDED, &cam->flags);
+}
+
+
+
+
+/*
+ * Debugging and related.
+ */
+#define cam_err(cam, fmt, arg...) \
+ dev_err(&(cam)->pdev->dev, fmt, ##arg);
+#define cam_warn(cam, fmt, arg...) \
+ dev_warn(&(cam)->pdev->dev, fmt, ##arg);
+#define cam_dbg(cam, fmt, arg...) \
+ dev_dbg(&(cam)->pdev->dev, fmt, ##arg);
+
+
+/* ---------------------------------------------------------------------*/
+/*
+ * We keep a simple list of known devices to search at open time.
+ */
+static LIST_HEAD(cafe_dev_list);
+static DEFINE_MUTEX(cafe_dev_list_lock);
+
+static void cafe_add_dev(struct cafe_camera *cam)
+{
+ mutex_lock(&cafe_dev_list_lock);
+ list_add_tail(&cam->dev_list, &cafe_dev_list);
+ mutex_unlock(&cafe_dev_list_lock);
+}
+
+static void cafe_remove_dev(struct cafe_camera *cam)
+{
+ mutex_lock(&cafe_dev_list_lock);
+ list_del(&cam->dev_list);
+ mutex_unlock(&cafe_dev_list_lock);
+}
+
+static struct cafe_camera *cafe_find_dev(int minor)
+{
+ struct cafe_camera *cam;
+
+ mutex_lock(&cafe_dev_list_lock);
+ list_for_each_entry(cam, &cafe_dev_list, dev_list) {
+ if (cam->v4ldev.minor == minor)
+ goto done;
+ }
+ cam = NULL;
+ done:
+ mutex_unlock(&cafe_dev_list_lock);
+ return cam;
+}
+
+
+static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev)
+{
+ struct cafe_camera *cam;
+
+ mutex_lock(&cafe_dev_list_lock);
+ list_for_each_entry(cam, &cafe_dev_list, dev_list) {
+ if (cam->pdev == pdev)
+ goto done;
+ }
+ cam = NULL;
+ done:
+ mutex_unlock(&cafe_dev_list_lock);
+ return cam;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/*
+ * Device register I/O
+ */
+static inline void cafe_reg_write(struct cafe_camera *cam, unsigned int reg,
+ unsigned int val)
+{
+ iowrite32(val, cam->regs + reg);
+}
+
+static inline unsigned int cafe_reg_read(struct cafe_camera *cam,
+ unsigned int reg)
+{
+ return ioread32(cam->regs + reg);
+}
+
+
+static inline void cafe_reg_write_mask(struct cafe_camera *cam, unsigned int reg,
+ unsigned int val, unsigned int mask)
+{
+ unsigned int v = cafe_reg_read(cam, reg);
+
+ v = (v & ~mask) | (val & mask);
+ cafe_reg_write(cam, reg, v);
+}
+
+static inline void cafe_reg_clear_bit(struct cafe_camera *cam,
+ unsigned int reg, unsigned int val)
+{
+ cafe_reg_write_mask(cam, reg, 0, val);
+}
+
+static inline void cafe_reg_set_bit(struct cafe_camera *cam,
+ unsigned int reg, unsigned int val)
+{
+ cafe_reg_write_mask(cam, reg, val, val);
+}
+
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * The I2C/SMBUS interface to the camera itself starts here. The
+ * controller handles SMBUS itself, presenting a relatively simple register
+ * interface; all we have to do is to tell it where to route the data.
+ */
+#define CAFE_SMBUS_TIMEOUT (HZ) /* generous */
+
+static int cafe_smbus_write_done(struct cafe_camera *cam)
+{
+ unsigned long flags;
+ int c1;
+
+ /*
+ * We must delay after the interrupt, or the controller gets confused
+ * and never does give us good status. Fortunately, we don't do this
+ * often.
+ */
+ udelay(20);
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ c1 = cafe_reg_read(cam, REG_TWSIC1);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ return (c1 & (TWSIC1_WSTAT|TWSIC1_ERROR)) != TWSIC1_WSTAT;
+}
+
+static int cafe_smbus_write_data(struct cafe_camera *cam,
+ u16 addr, u8 command, u8 value)
+{
+ unsigned int rval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
+ rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */
+ /*
+ * Marvell sez set clkdiv to all 1's for now.
+ */
+ rval |= TWSIC0_CLKDIV;
+ cafe_reg_write(cam, REG_TWSIC0, rval);
+ (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */
+ rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
+ cafe_reg_write(cam, REG_TWSIC1, rval);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ msleep(2); /* Required or things flake */
+
+ wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
+ CAFE_SMBUS_TIMEOUT);
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ rval = cafe_reg_read(cam, REG_TWSIC1);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+ if (rval & TWSIC1_WSTAT) {
+ cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr,
+ command, value);
+ return -EIO;
+ }
+ if (rval & TWSIC1_ERROR) {
+ cam_err(cam, "SMBUS write (%02x/%02x/%02x) error\n", addr,
+ command, value);
+ return -EIO;
+ }
+ return 0;
+}
+
+
+
+static int cafe_smbus_read_done(struct cafe_camera *cam)
+{
+ unsigned long flags;
+ int c1;
+
+ /*
+ * We must delay after the interrupt, or the controller gets confused
+ * and never does give us good status. Fortunately, we don't do this
+ * often.
+ */
+ udelay(20);
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ c1 = cafe_reg_read(cam, REG_TWSIC1);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ return c1 & (TWSIC1_RVALID|TWSIC1_ERROR);
+}
+
+
+
+static int cafe_smbus_read_data(struct cafe_camera *cam,
+ u16 addr, u8 command, u8 *value)
+{
+ unsigned int rval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
+ rval |= TWSIC0_OVMAGIC; /* Make OV sensors work */
+ /*
+ * Marvel sez set clkdiv to all 1's for now.
+ */
+ rval |= TWSIC0_CLKDIV;
+ cafe_reg_write(cam, REG_TWSIC0, rval);
+ (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */
+ rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
+ cafe_reg_write(cam, REG_TWSIC1, rval);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+ wait_event_timeout(cam->smbus_wait,
+ cafe_smbus_read_done(cam), CAFE_SMBUS_TIMEOUT);
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ rval = cafe_reg_read(cam, REG_TWSIC1);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+ if (rval & TWSIC1_ERROR) {
+ cam_err(cam, "SMBUS read (%02x/%02x) error\n", addr, command);
+ return -EIO;
+ }
+ if (! (rval & TWSIC1_RVALID)) {
+ cam_err(cam, "SMBUS read (%02x/%02x) timed out\n", addr,
+ command);
+ return -EIO;
+ }
+ *value = rval & 0xff;
+ return 0;
+}
+
+/*
+ * Perform a transfer over SMBUS. This thing is called under
+ * the i2c bus lock, so we shouldn't race with ourselves...
+ */
+static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ struct cafe_camera *cam = i2c_get_adapdata(adapter);
+ int ret = -EINVAL;
+
+ /*
+ * Refuse to talk to anything but OV cam chips. We should
+ * never even see an attempt to do so, but one never knows.
+ */
+ if (cam->sensor && addr != cam->sensor->addr) {
+ cam_err(cam, "funky smbus addr %d\n", addr);
+ return -EINVAL;
+ }
+ /*
+ * This interface would appear to only do byte data ops. OK
+ * it can do word too, but the cam chip has no use for that.
+ */
+ if (size != I2C_SMBUS_BYTE_DATA) {
+ cam_err(cam, "funky xfer size %d\n", size);
+ return -EINVAL;
+ }
+
+ if (rw == I2C_SMBUS_WRITE)
+ ret = cafe_smbus_write_data(cam, addr, command, data->byte);
+ else if (rw == I2C_SMBUS_READ)
+ ret = cafe_smbus_read_data(cam, addr, command, &data->byte);
+ return ret;
+}
+
+
+static void cafe_smbus_enable_irq(struct cafe_camera *cam)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cafe_reg_set_bit(cam, REG_IRQMASK, TWSIIRQS);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+static u32 cafe_smbus_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_READ_BYTE_DATA |
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+}
+
+static struct i2c_algorithm cafe_smbus_algo = {
+ .smbus_xfer = cafe_smbus_xfer,
+ .functionality = cafe_smbus_func
+};
+
+/* Somebody is on the bus */
+static int cafe_cam_init(struct cafe_camera *cam);
+static void cafe_ctlr_stop_dma(struct cafe_camera *cam);
+static void cafe_ctlr_power_down(struct cafe_camera *cam);
+
+static int cafe_smbus_attach(struct i2c_client *client)
+{
+ struct cafe_camera *cam = i2c_get_adapdata(client->adapter);
+
+ /*
+ * Don't talk to chips we don't recognize.
+ */
+ if (client->driver->id == I2C_DRIVERID_OV7670) {
+ cam->sensor = client;
+ return cafe_cam_init(cam);
+ }
+ return -EINVAL;
+}
+
+static int cafe_smbus_detach(struct i2c_client *client)
+{
+ struct cafe_camera *cam = i2c_get_adapdata(client->adapter);
+
+ if (cam->sensor == client) {
+ cafe_ctlr_stop_dma(cam);
+ cafe_ctlr_power_down(cam);
+ cam_err(cam, "lost the sensor!\n");
+ cam->sensor = NULL; /* Bummer, no camera */
+ cam->state = S_NOTREADY;
+ }
+ return 0;
+}
+
+static int cafe_smbus_setup(struct cafe_camera *cam)
+{
+ struct i2c_adapter *adap = &cam->i2c_adapter;
+ int ret;
+
+ cafe_smbus_enable_irq(cam);
+ adap->id = I2C_HW_SMBUS_CAFE;
+ adap->class = I2C_CLASS_CAM_DIGITAL;
+ adap->owner = THIS_MODULE;
+ adap->client_register = cafe_smbus_attach;
+ adap->client_unregister = cafe_smbus_detach;
+ adap->algo = &cafe_smbus_algo;
+ strcpy(adap->name, "cafe_ccic");
+ i2c_set_adapdata(adap, cam);
+ ret = i2c_add_adapter(adap);
+ if (ret)
+ printk(KERN_ERR "Unable to register cafe i2c adapter\n");
+ return ret;
+}
+
+static void cafe_smbus_shutdown(struct cafe_camera *cam)
+{
+ i2c_del_adapter(&cam->i2c_adapter);
+}
+
+
+/* ------------------------------------------------------------------- */
+/*
+ * Deal with the controller.
+ */
+
+/*
+ * Do everything we think we need to have the interface operating
+ * according to the desired format.
+ */
+static void cafe_ctlr_dma(struct cafe_camera *cam)
+{
+ /*
+ * Store the first two Y buffers (we aren't supporting
+ * planar formats for now, so no UV bufs). Then either
+ * set the third if it exists, or tell the controller
+ * to just use two.
+ */
+ cafe_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]);
+ cafe_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]);
+ if (cam->nbufs > 2) {
+ cafe_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]);
+ cafe_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS);
+ }
+ else
+ cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
+ cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */
+}
+
+static void cafe_ctlr_image(struct cafe_camera *cam)
+{
+ int imgsz;
+ struct v4l2_pix_format *fmt = &cam->pix_format;
+
+ imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
+ (fmt->bytesperline & IMGSZ_H_MASK);
+ cafe_reg_write(cam, REG_IMGSIZE, imgsz);
+ cafe_reg_write(cam, REG_IMGOFFSET, 0);
+ /* YPITCH just drops the last two bits */
+ cafe_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
+ IMGP_YP_MASK);
+ /*
+ * Tell the controller about the image format we are using.
+ */
+ switch (cam->pix_format.pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ cafe_reg_write_mask(cam, REG_CTRL0,
+ C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
+ C0_DF_MASK);
+ break;
+
+ case V4L2_PIX_FMT_RGB444:
+ cafe_reg_write_mask(cam, REG_CTRL0,
+ C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
+ C0_DF_MASK);
+ /* Alpha value? */
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ cafe_reg_write_mask(cam, REG_CTRL0,
+ C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
+ C0_DF_MASK);
+ break;
+
+ default:
+ cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
+ break;
+ }
+ /*
+ * Make sure it knows we want to use hsync/vsync.
+ */
+ cafe_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
+ C0_SIFM_MASK);
+}
+
+
+/*
+ * Configure the controller for operation; caller holds the
+ * device mutex.
+ */
+static int cafe_ctlr_configure(struct cafe_camera *cam)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cafe_ctlr_dma(cam);
+ cafe_ctlr_image(cam);
+ cafe_set_config_needed(cam, 0);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ return 0;
+}
+
+static void cafe_ctlr_irq_enable(struct cafe_camera *cam)
+{
+ /*
+ * Clear any pending interrupts, since we do not
+ * expect to have I/O active prior to enabling.
+ */
+ cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);
+ cafe_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+static void cafe_ctlr_irq_disable(struct cafe_camera *cam)
+{
+ cafe_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+/*
+ * Make the controller start grabbing images. Everything must
+ * be set up before doing this.
+ */
+static void cafe_ctlr_start(struct cafe_camera *cam)
+{
+ /* set_bit performs a read, so no other barrier should be
+ needed here */
+ cafe_reg_set_bit(cam, REG_CTRL0, C0_ENABLE);
+}
+
+static void cafe_ctlr_stop(struct cafe_camera *cam)
+{
+ cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+}
+
+static void cafe_ctlr_init(struct cafe_camera *cam)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ /*
+ * Added magic to bring up the hardware on the B-Test board
+ */
+ cafe_reg_write(cam, 0x3038, 0x8);
+ cafe_reg_write(cam, 0x315c, 0x80008);
+ /*
+ * Go through the dance needed to wake the device up.
+ * Note that these registers are global and shared
+ * with the NAND and SD devices. Interaction between the
+ * three still needs to be examined.
+ */
+ cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */
+ cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC);
+ cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS);
+ mdelay(5); /* FIXME revisit this */
+ cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);
+ cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN);
+ /*
+ * Make sure it's not powered down.
+ */
+ cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+ /*
+ * Turn off the enable bit. It sure should be off anyway,
+ * but it's good to be sure.
+ */
+ cafe_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+ /*
+ * Mask all interrupts.
+ */
+ cafe_reg_write(cam, REG_IRQMASK, 0);
+ /*
+ * Clock the sensor appropriately. Controller clock should
+ * be 48MHz, sensor "typical" value is half that.
+ */
+ cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+
+/*
+ * Stop the controller, and don't return until we're really sure that no
+ * further DMA is going on.
+ */
+static void cafe_ctlr_stop_dma(struct cafe_camera *cam)
+{
+ unsigned long flags;
+
+ /*
+ * Theory: stop the camera controller (whether it is operating
+ * or not). Delay briefly just in case we race with the SOF
+ * interrupt, then wait until no DMA is active.
+ */
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cafe_ctlr_stop(cam);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ mdelay(1);
+ wait_event_timeout(cam->iowait,
+ !test_bit(CF_DMA_ACTIVE, &cam->flags), HZ);
+ if (test_bit(CF_DMA_ACTIVE, &cam->flags))
+ cam_err(cam, "Timeout waiting for DMA to end\n");
+ /* This would be bad news - what now? */
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cam->state = S_IDLE;
+ cafe_ctlr_irq_disable(cam);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/*
+ * Power up and down.
+ */
+static void cafe_ctlr_power_up(struct cafe_camera *cam)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cafe_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+ /*
+ * Put the sensor into operational mode (assumes OLPC-style
+ * wiring). Control 0 is reset - set to 1 to operate.
+ * Control 1 is power down, set to 0 to operate.
+ */
+ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
+ mdelay(1); /* Marvell says 1ms will do it */
+ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
+ mdelay(1); /* Enough? */
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+static void cafe_ctlr_power_down(struct cafe_camera *cam)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1);
+ cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/* -------------------------------------------------------------------- */
+/*
+ * Communications with the sensor.
+ */
+
+static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg)
+{
+ struct i2c_client *sc = cam->sensor;
+ int ret;
+
+ if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL)
+ return -EINVAL;
+ ret = sc->driver->command(sc, cmd, arg);
+ if (ret == -EPERM) /* Unsupported command */
+ return 0;
+ return ret;
+}
+
+static int __cafe_cam_reset(struct cafe_camera *cam)
+{
+ int zero = 0;
+ return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero);
+}
+
+/*
+ * We have found the sensor on the i2c. Let's try to have a
+ * conversation.
+ */
+static int cafe_cam_init(struct cafe_camera *cam)
+{
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ if (cam->state != S_NOTREADY)
+ cam_warn(cam, "Cam init with device in funky state %d",
+ cam->state);
+ ret = __cafe_cam_reset(cam);
+ if (ret)
+ goto out;
+ ret = __cafe_cam_cmd(cam, VIDIOC_INT_G_CHIP_IDENT, &cam->sensor_type);
+ if (ret)
+ goto out;
+// if (cam->sensor->addr != OV7xx0_SID) {
+ if (cam->sensor_type != V4L2_IDENT_OV7670) {
+ cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr);
+ ret = -EINVAL;
+ goto out;
+ }
+/* Get/set parameters? */
+ ret = 0;
+ cam->state = S_IDLE;
+ out:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+/*
+ * Configure the sensor to match the parameters we have. Caller should
+ * hold s_mutex
+ */
+static int cafe_cam_set_flip(struct cafe_camera *cam)
+{
+ struct v4l2_control ctrl;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_VFLIP;
+ ctrl.value = flip;
+ return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl);
+}
+
+
+static int cafe_cam_configure(struct cafe_camera *cam)
+{
+ struct v4l2_format fmt;
+ int ret, zero = 0;
+
+ if (cam->state != S_IDLE)
+ return -EINVAL;
+ fmt.fmt.pix = cam->pix_format;
+ ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero);
+ if (ret == 0)
+ ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt);
+ /*
+ * OV7670 does weird things if flip is set *before* format...
+ */
+ ret += cafe_cam_set_flip(cam);
+ return ret;
+}
+
+/* -------------------------------------------------------------------- */
+/*
+ * DMA buffer management. These functions need s_mutex held.
+ */
+
+/* FIXME: this is inefficient as hell, since dma_alloc_coherent just
+ * does a get_free_pages() call, and we waste a good chunk of an orderN
+ * allocation. Should try to allocate the whole set in one chunk.
+ */
+static int cafe_alloc_dma_bufs(struct cafe_camera *cam, int loadtime)
+{
+ int i;
+
+ cafe_set_config_needed(cam, 1);
+ if (loadtime)
+ cam->dma_buf_size = dma_buf_size;
+ else
+ cam->dma_buf_size = cam->pix_format.sizeimage;
+ if (n_dma_bufs > 3)
+ n_dma_bufs = 3;
+
+ cam->nbufs = 0;
+ for (i = 0; i < n_dma_bufs; i++) {
+ cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev,
+ cam->dma_buf_size, cam->dma_handles + i,
+ GFP_KERNEL);
+ if (cam->dma_bufs[i] == NULL) {
+ cam_warn(cam, "Failed to allocate DMA buffer\n");
+ break;
+ }
+ /* For debug, remove eventually */
+ memset(cam->dma_bufs[i], 0xcc, cam->dma_buf_size);
+ (cam->nbufs)++;
+ }
+
+ switch (cam->nbufs) {
+ case 1:
+ dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,
+ cam->dma_bufs[0], cam->dma_handles[0]);
+ cam->nbufs = 0;
+ case 0:
+ cam_err(cam, "Insufficient DMA buffers, cannot operate\n");
+ return -ENOMEM;
+
+ case 2:
+ if (n_dma_bufs > 2)
+ cam_warn(cam, "Will limp along with only 2 buffers\n");
+ break;
+ }
+ return 0;
+}
+
+static void cafe_free_dma_bufs(struct cafe_camera *cam)
+{
+ int i;
+
+ for (i = 0; i < cam->nbufs; i++) {
+ dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size,
+ cam->dma_bufs[i], cam->dma_handles[i]);
+ cam->dma_bufs[i] = NULL;
+ }
+ cam->nbufs = 0;
+}
+
+
+
+
+
+/* ----------------------------------------------------------------------- */
+/*
+ * Here starts the V4L2 interface code.
+ */
+
+/*
+ * Read an image from the device.
+ */
+static ssize_t cafe_deliver_buffer(struct cafe_camera *cam,
+ char __user *buffer, size_t len, loff_t *pos)
+{
+ int bufno;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ if (cam->next_buf < 0) {
+ cam_err(cam, "deliver_buffer: No next buffer\n");
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ return -EIO;
+ }
+ bufno = cam->next_buf;
+ clear_bit(bufno, &cam->flags);
+ if (++(cam->next_buf) >= cam->nbufs)
+ cam->next_buf = 0;
+ if (! test_bit(cam->next_buf, &cam->flags))
+ cam->next_buf = -1;
+ cam->specframes = 0;
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+
+ if (len > cam->pix_format.sizeimage)
+ len = cam->pix_format.sizeimage;
+ if (copy_to_user(buffer, cam->dma_bufs[bufno], len))
+ return -EFAULT;
+ (*pos) += len;
+ return len;
+}
+
+/*
+ * Get everything ready, and start grabbing frames.
+ */
+static int cafe_read_setup(struct cafe_camera *cam, enum cafe_state state)
+{
+ int ret;
+ unsigned long flags;
+
+ /*
+ * Configuration. If we still don't have DMA buffers,
+ * make one last, desperate attempt.
+ */
+ if (cam->nbufs == 0)
+ if (cafe_alloc_dma_bufs(cam, 0))
+ return -ENOMEM;
+
+ if (cafe_needs_config(cam)) {
+ cafe_cam_configure(cam);
+ ret = cafe_ctlr_configure(cam);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Turn it loose.
+ */
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ cafe_reset_buffers(cam);
+ cafe_ctlr_irq_enable(cam);
+ cam->state = state;
+ cafe_ctlr_start(cam);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ return 0;
+}
+
+
+static ssize_t cafe_v4l_read(struct file *filp,
+ char __user *buffer, size_t len, loff_t *pos)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret;
+
+ /*
+ * Perhaps we're in speculative read mode and already
+ * have data?
+ */
+ mutex_lock(&cam->s_mutex);
+ if (cam->state == S_SPECREAD) {
+ if (cam->next_buf >= 0) {
+ ret = cafe_deliver_buffer(cam, buffer, len, pos);
+ if (ret != 0)
+ goto out_unlock;
+ }
+ } else if (cam->state == S_FLAKED || cam->state == S_NOTREADY) {
+ ret = -EIO;
+ goto out_unlock;
+ } else if (cam->state != S_IDLE) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
+ /*
+ * v4l2: multiple processes can open the device, but only
+ * one gets to grab data from it.
+ */
+ if (cam->owner && cam->owner != filp) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+ cam->owner = filp;
+
+ /*
+ * Do setup if need be.
+ */
+ if (cam->state != S_SPECREAD) {
+ ret = cafe_read_setup(cam, S_SINGLEREAD);
+ if (ret)
+ goto out_unlock;
+ }
+ /*
+ * Wait for something to happen. This should probably
+ * be interruptible (FIXME).
+ */
+ wait_event_timeout(cam->iowait, cam->next_buf >= 0, HZ);
+ if (cam->next_buf < 0) {
+ cam_err(cam, "read() operation timed out\n");
+ cafe_ctlr_stop_dma(cam);
+ ret = -EIO;
+ goto out_unlock;
+ }
+ /*
+ * Give them their data and we should be done.
+ */
+ ret = cafe_deliver_buffer(cam, buffer, len, pos);
+
+ out_unlock:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+
+
+
+
+
+
+/*
+ * Streaming I/O support.
+ */
+
+
+
+static int cafe_vidioc_streamon(struct file *filp, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret = -EINVAL;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ goto out;
+ mutex_lock(&cam->s_mutex);
+ if (cam->state != S_IDLE || cam->n_sbufs == 0)
+ goto out_unlock;
+
+ cam->sequence = 0;
+ ret = cafe_read_setup(cam, S_STREAMING);
+
+ out_unlock:
+ mutex_unlock(&cam->s_mutex);
+ out:
+ return ret;
+}
+
+
+static int cafe_vidioc_streamoff(struct file *filp, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret = -EINVAL;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ goto out;
+ mutex_lock(&cam->s_mutex);
+ if (cam->state != S_STREAMING)
+ goto out_unlock;
+
+ cafe_ctlr_stop_dma(cam);
+ ret = 0;
+
+ out_unlock:
+ mutex_unlock(&cam->s_mutex);
+ out:
+ return ret;
+}
+
+
+
+static int cafe_setup_siobuf(struct cafe_camera *cam, int index)
+{
+ struct cafe_sio_buffer *buf = cam->sb_bufs + index;
+
+ INIT_LIST_HEAD(&buf->list);
+ buf->v4lbuf.length = PAGE_ALIGN(cam->pix_format.sizeimage);
+ buf->buffer = vmalloc_user(buf->v4lbuf.length);
+ if (buf->buffer == NULL)
+ return -ENOMEM;
+ buf->mapcount = 0;
+ buf->cam = cam;
+
+ buf->v4lbuf.index = index;
+ buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf->v4lbuf.field = V4L2_FIELD_NONE;
+ buf->v4lbuf.memory = V4L2_MEMORY_MMAP;
+ /*
+ * Offset: must be 32-bit even on a 64-bit system. video-buf
+ * just uses the length times the index, but the spec warns
+ * against doing just that - vma merging problems. So we
+ * leave a gap between each pair of buffers.
+ */
+ buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;
+ return 0;
+}
+
+static int cafe_free_sio_buffers(struct cafe_camera *cam)
+{
+ int i;
+
+ /*
+ * If any buffers are mapped, we cannot free them at all.
+ */
+ for (i = 0; i < cam->n_sbufs; i++)
+ if (cam->sb_bufs[i].mapcount > 0)
+ return -EBUSY;
+ /*
+ * OK, let's do it.
+ */
+ for (i = 0; i < cam->n_sbufs; i++)
+ vfree(cam->sb_bufs[i].buffer);
+ cam->n_sbufs = 0;
+ kfree(cam->sb_bufs);
+ cam->sb_bufs = NULL;
+ INIT_LIST_HEAD(&cam->sb_avail);
+ INIT_LIST_HEAD(&cam->sb_full);
+ return 0;
+}
+
+
+
+static int cafe_vidioc_reqbufs(struct file *filp, void *priv,
+ struct v4l2_requestbuffers *req)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret;
+
+ /*
+ * Make sure it's something we can do. User pointers could be
+ * implemented without great pain, but that's not been done yet.
+ */
+ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (req->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+ /*
+ * If they ask for zero buffers, they really want us to stop streaming
+ * (if it's happening) and free everything. Should we check owner?
+ */
+ mutex_lock(&cam->s_mutex);
+ if (req->count == 0) {
+ if (cam->state == S_STREAMING)
+ cafe_ctlr_stop_dma(cam);
+ ret = cafe_free_sio_buffers (cam);
+ goto out;
+ }
+ /*
+ * Device needs to be idle and working. We *could* try to do the
+ * right thing in S_SPECREAD by shutting things down, but it
+ * probably doesn't matter.
+ */
+ if (cam->state != S_IDLE || (cam->owner && cam->owner != filp)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ cam->owner = filp;
+
+ if (req->count < min_buffers)
+ req->count = min_buffers;
+ else if (req->count > max_buffers)
+ req->count = max_buffers;
+ if (cam->n_sbufs > 0) {
+ ret = cafe_free_sio_buffers(cam);
+ if (ret)
+ goto out;
+ }
+
+ cam->sb_bufs = kzalloc(req->count*sizeof(struct cafe_sio_buffer),
+ GFP_KERNEL);
+ if (cam->sb_bufs == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ for (cam->n_sbufs = 0; cam->n_sbufs < req->count; (cam->n_sbufs++)) {
+ ret = cafe_setup_siobuf(cam, cam->n_sbufs);
+ if (ret)
+ break;
+ }
+
+ if (cam->n_sbufs == 0) /* no luck at all - ret already set */
+ kfree(cam->sb_bufs);
+ else
+ ret = 0;
+ req->count = cam->n_sbufs; /* In case of partial success */
+
+ out:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+static int cafe_vidioc_querybuf(struct file *filp, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret = -EINVAL;
+
+ mutex_lock(&cam->s_mutex);
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ goto out;
+ if (buf->index < 0 || buf->index >= cam->n_sbufs)
+ goto out;
+ *buf = cam->sb_bufs[buf->index].v4lbuf;
+ ret = 0;
+ out:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+static int cafe_vidioc_qbuf(struct file *filp, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct cafe_camera *cam = filp->private_data;
+ struct cafe_sio_buffer *sbuf;
+ int ret = -EINVAL;
+ unsigned long flags;
+
+ mutex_lock(&cam->s_mutex);
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ goto out;
+ if (buf->index < 0 || buf->index >= cam->n_sbufs)
+ goto out;
+ sbuf = cam->sb_bufs + buf->index;
+ if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) {
+ ret = 0; /* Already queued?? */
+ goto out;
+ }
+ if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_DONE) {
+ /* Spec doesn't say anything, seems appropriate tho */
+ ret = -EBUSY;
+ goto out;
+ }
+ sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED;
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ list_add(&sbuf->list, &cam->sb_avail);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ ret = 0;
+ out:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+static int cafe_vidioc_dqbuf(struct file *filp, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct cafe_camera *cam = filp->private_data;
+ struct cafe_sio_buffer *sbuf;
+ int ret = -EINVAL;
+ unsigned long flags;
+
+ mutex_lock(&cam->s_mutex);
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ goto out_unlock;
+ if (cam->state != S_STREAMING)
+ goto out_unlock;
+ if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
+
+ while (list_empty(&cam->sb_full) && cam->state == S_STREAMING) {
+ mutex_unlock(&cam->s_mutex);
+ if (wait_event_interruptible(cam->iowait,
+ !list_empty(&cam->sb_full))) {
+ ret = -ERESTARTSYS;
+ goto out;
+ }
+ mutex_lock(&cam->s_mutex);
+ }
+
+ if (cam->state != S_STREAMING)
+ ret = -EINTR;
+ else {
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ /* Should probably recheck !list_empty() here */
+ sbuf = list_entry(cam->sb_full.next,
+ struct cafe_sio_buffer, list);
+ list_del_init(&sbuf->list);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+ sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE;
+ *buf = sbuf->v4lbuf;
+ ret = 0;
+ }
+
+ out_unlock:
+ mutex_unlock(&cam->s_mutex);
+ out:
+ return ret;
+}
+
+
+
+static void cafe_v4l_vm_open(struct vm_area_struct *vma)
+{
+ struct cafe_sio_buffer *sbuf = vma->vm_private_data;
+ /*
+ * Locking: done under mmap_sem, so we don't need to
+ * go back to the camera lock here.
+ */
+ sbuf->mapcount++;
+}
+
+
+static void cafe_v4l_vm_close(struct vm_area_struct *vma)
+{
+ struct cafe_sio_buffer *sbuf = vma->vm_private_data;
+
+ mutex_lock(&sbuf->cam->s_mutex);
+ sbuf->mapcount--;
+ /* Docs say we should stop I/O too... */
+ if (sbuf->mapcount == 0)
+ sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED;
+ mutex_unlock(&sbuf->cam->s_mutex);
+}
+
+static struct vm_operations_struct cafe_v4l_vm_ops = {
+ .open = cafe_v4l_vm_open,
+ .close = cafe_v4l_vm_close
+};
+
+
+static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct cafe_camera *cam = filp->private_data;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ int ret = -EINVAL;
+ int i;
+ struct cafe_sio_buffer *sbuf = NULL;
+
+ if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+ /*
+ * Find the buffer they are looking for.
+ */
+ mutex_lock(&cam->s_mutex);
+ for (i = 0; i < cam->n_sbufs; i++)
+ if (cam->sb_bufs[i].v4lbuf.m.offset == offset) {
+ sbuf = cam->sb_bufs + i;
+ break;
+ }
+ if (sbuf == NULL)
+ goto out;
+
+ ret = remap_vmalloc_range(vma, sbuf->buffer, 0);
+ if (ret)
+ goto out;
+ vma->vm_flags |= VM_DONTEXPAND;
+ vma->vm_private_data = sbuf;
+ vma->vm_ops = &cafe_v4l_vm_ops;
+ sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED;
+ cafe_v4l_vm_open(vma);
+ ret = 0;
+ out:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+
+static int cafe_v4l_open(struct inode *inode, struct file *filp)
+{
+ struct cafe_camera *cam;
+
+ cam = cafe_find_dev(iminor(inode));
+ if (cam == NULL)
+ return -ENODEV;
+ filp->private_data = cam;
+
+ mutex_lock(&cam->s_mutex);
+ if (cam->users == 0) {
+ cafe_ctlr_power_up(cam);
+ __cafe_cam_reset(cam);
+ cafe_set_config_needed(cam, 1);
+ /* FIXME make sure this is complete */
+ }
+ (cam->users)++;
+ mutex_unlock(&cam->s_mutex);
+ return 0;
+}
+
+
+static int cafe_v4l_release(struct inode *inode, struct file *filp)
+{
+ struct cafe_camera *cam = filp->private_data;
+
+ mutex_lock(&cam->s_mutex);
+ (cam->users)--;
+ if (filp == cam->owner) {
+ cafe_ctlr_stop_dma(cam);
+ cafe_free_sio_buffers(cam);
+ cam->owner = NULL;
+ }
+ if (cam->users == 0) {
+ cafe_ctlr_power_down(cam);
+ if (! alloc_bufs_at_load)
+ cafe_free_dma_bufs(cam);
+ }
+ mutex_unlock(&cam->s_mutex);
+ return 0;
+}
+
+
+
+static unsigned int cafe_v4l_poll(struct file *filp,
+ struct poll_table_struct *pt)
+{
+ struct cafe_camera *cam = filp->private_data;
+
+ poll_wait(filp, &cam->iowait, pt);
+ if (cam->next_buf >= 0)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+
+
+static int cafe_vidioc_queryctrl(struct file *filp, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+static int cafe_vidioc_g_ctrl(struct file *filp, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+static int cafe_vidioc_s_ctrl(struct file *filp, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct cafe_camera *cam = filp->private_data;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+
+
+
+static int cafe_vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strcpy(cap->driver, "cafe_ccic");
+ strcpy(cap->card, "cafe_ccic");
+ cap->version = CAFE_VERSION;
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+ return 0;
+}
+
+
+/*
+ * The default format we use until somebody says otherwise.
+ */
+static struct v4l2_pix_format cafe_def_pix_format = {
+ .width = VGA_WIDTH,
+ .height = VGA_HEIGHT,
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .field = V4L2_FIELD_NONE,
+ .bytesperline = VGA_WIDTH*2,
+ .sizeimage = VGA_WIDTH*VGA_HEIGHT*2,
+};
+
+static int cafe_vidioc_enum_fmt_cap(struct file *filp,
+ void *priv, struct v4l2_fmtdesc *fmt)
+{
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+
+static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv,
+ struct v4l2_format *fmt)
+{
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
+ struct v4l2_format *fmt)
+{
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ /*
+ * Can't do anything if the device is not idle
+ * Also can't if there are streaming buffers in place.
+ */
+ if (cam->state != S_IDLE || cam->n_sbufs > 0)
+ return -EBUSY;
+ /*
+ * See if the formatting works in principle.
+ */
+ ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt);
+ if (ret)
+ return ret;
+ /*
+ * Now we start to change things for real, so let's do it
+ * under lock.
+ */
+ mutex_lock(&cam->s_mutex);
+ cam->pix_format = fmt->fmt.pix;
+ /*
+ * Make sure we have appropriate DMA buffers.
+ */
+ ret = -ENOMEM;
+ if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
+ cafe_free_dma_bufs(cam);
+ if (cam->nbufs == 0) {
+ if (cafe_alloc_dma_bufs(cam, 0))
+ goto out;
+ }
+ /*
+ * It looks like this might work, so let's program the sensor.
+ */
+ ret = cafe_cam_configure(cam);
+ if (! ret)
+ ret = cafe_ctlr_configure(cam);
+ out:
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+}
+
+/*
+ * Return our stored notion of how the camera is/should be configured.
+ * The V4l2 spec wants us to be smarter, and actually get this from
+ * the camera (and not mess with it at open time). Someday.
+ */
+static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv,
+ struct v4l2_format *f)
+{
+ struct cafe_camera *cam = priv;
+
+ f->fmt.pix = cam->pix_format;
+ return 0;
+}
+
+/*
+ * We only have one input - the sensor - so minimize the nonsense here.
+ */
+static int cafe_vidioc_enum_input(struct file *filp, void *priv,
+ struct v4l2_input *input)
+{
+ if (input->index != 0)
+ return -EINVAL;
+
+ input->type = V4L2_INPUT_TYPE_CAMERA;
+ input->std = V4L2_STD_ALL; /* Not sure what should go here */
+ strcpy(input->name, "Camera");
+ return 0;
+}
+
+static int cafe_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ if (i != 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* from vivi.c */
+static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
+{
+ return 0;
+}
+
+/*
+ * G/S_PARM. Most of this is done by the sensor, but we are
+ * the level which controls the number of read buffers.
+ */
+static int cafe_vidioc_g_parm(struct file *filp, void *priv,
+ struct v4l2_streamparm *parms)
+{
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms);
+ mutex_unlock(&cam->s_mutex);
+ parms->parm.capture.readbuffers = n_dma_bufs;
+ return ret;
+}
+
+static int cafe_vidioc_s_parm(struct file *filp, void *priv,
+ struct v4l2_streamparm *parms)
+{
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms);
+ mutex_unlock(&cam->s_mutex);
+ parms->parm.capture.readbuffers = n_dma_bufs;
+ return ret;
+}
+
+
+static void cafe_v4l_dev_release(struct video_device *vd)
+{
+ struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
+
+ kfree(cam);
+}
+
+
+/*
+ * This template device holds all of those v4l2 methods; we
+ * clone it for specific real devices.
+ */
+
+static struct file_operations cafe_v4l_fops = {
+ .owner = THIS_MODULE,
+ .open = cafe_v4l_open,
+ .release = cafe_v4l_release,
+ .read = cafe_v4l_read,
+ .poll = cafe_v4l_poll,
+ .mmap = cafe_v4l_mmap,
+ .ioctl = video_ioctl2,
+ .llseek = no_llseek,
+};
+
+static struct video_device cafe_v4l_template = {
+ .name = "cafe",
+ .type = VFL_TYPE_GRABBER,
+ .type2 = VID_TYPE_CAPTURE,
+ .minor = -1, /* Get one dynamically */
+ .tvnorms = V4L2_STD_NTSC_M,
+ .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */
+
+ .fops = &cafe_v4l_fops,
+ .release = cafe_v4l_dev_release,
+
+ .vidioc_querycap = cafe_vidioc_querycap,
+ .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap,
+ .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap,
+ .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap,
+ .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap,
+ .vidioc_enum_input = cafe_vidioc_enum_input,
+ .vidioc_g_input = cafe_vidioc_g_input,
+ .vidioc_s_input = cafe_vidioc_s_input,
+ .vidioc_s_std = cafe_vidioc_s_std,
+ .vidioc_reqbufs = cafe_vidioc_reqbufs,
+ .vidioc_querybuf = cafe_vidioc_querybuf,
+ .vidioc_qbuf = cafe_vidioc_qbuf,
+ .vidioc_dqbuf = cafe_vidioc_dqbuf,
+ .vidioc_streamon = cafe_vidioc_streamon,
+ .vidioc_streamoff = cafe_vidioc_streamoff,
+ .vidioc_queryctrl = cafe_vidioc_queryctrl,
+ .vidioc_g_ctrl = cafe_vidioc_g_ctrl,
+ .vidioc_s_ctrl = cafe_vidioc_s_ctrl,
+ .vidioc_g_parm = cafe_vidioc_g_parm,
+ .vidioc_s_parm = cafe_vidioc_s_parm,
+};
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Interrupt handler stuff
+ */
+
+
+
+static void cafe_frame_tasklet(unsigned long data)
+{
+ struct cafe_camera *cam = (struct cafe_camera *) data;
+ int i;
+ unsigned long flags;
+ struct cafe_sio_buffer *sbuf;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ for (i = 0; i < cam->nbufs; i++) {
+ int bufno = cam->next_buf;
+ if (bufno < 0) { /* "will never happen" */
+ cam_err(cam, "No valid bufs in tasklet!\n");
+ break;
+ }
+ if (++(cam->next_buf) >= cam->nbufs)
+ cam->next_buf = 0;
+ if (! test_bit(bufno, &cam->flags))
+ continue;
+ if (list_empty(&cam->sb_avail))
+ break; /* Leave it valid, hope for better later */
+ clear_bit(bufno, &cam->flags);
+ /*
+ * We could perhaps drop the spinlock during this
+ * big copy. Something to consider.
+ */
+ sbuf = list_entry(cam->sb_avail.next,
+ struct cafe_sio_buffer, list);
+ memcpy(sbuf->buffer, cam->dma_bufs[bufno],
+ cam->pix_format.sizeimage);
+ sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage;
+ sbuf->v4lbuf.sequence = cam->buf_seq[bufno];
+ sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
+ sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
+ list_move_tail(&sbuf->list, &cam->sb_full);
+ }
+ if (! list_empty(&cam->sb_full))
+ wake_up(&cam->iowait);
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+
+
+static void cafe_frame_complete(struct cafe_camera *cam, int frame)
+{
+ /*
+ * Basic frame housekeeping.
+ */
+ if (test_bit(frame, &cam->flags) && printk_ratelimit())
+ cam_err(cam, "Frame overrun on %d, frames lost\n", frame);
+ set_bit(frame, &cam->flags);
+ clear_bit(CF_DMA_ACTIVE, &cam->flags);
+ if (cam->next_buf < 0)
+ cam->next_buf = frame;
+ cam->buf_seq[frame] = ++(cam->sequence);
+
+ switch (cam->state) {
+ /*
+ * If in single read mode, try going speculative.
+ */
+ case S_SINGLEREAD:
+ cam->state = S_SPECREAD;
+ cam->specframes = 0;
+ wake_up(&cam->iowait);
+ break;
+
+ /*
+ * If we are already doing speculative reads, and nobody is
+ * reading them, just stop.
+ */
+ case S_SPECREAD:
+ if (++(cam->specframes) >= cam->nbufs) {
+ cafe_ctlr_stop(cam);
+ cafe_ctlr_irq_disable(cam);
+ cam->state = S_IDLE;
+ }
+ wake_up(&cam->iowait);
+ break;
+ /*
+ * For the streaming case, we defer the real work to the
+ * camera tasklet.
+ *
+ * FIXME: if the application is not consuming the buffers,
+ * we should eventually put things on hold and restart in
+ * vidioc_dqbuf().
+ */
+ case S_STREAMING:
+ tasklet_schedule(&cam->s_tasklet);
+ break;
+
+ default:
+ cam_err(cam, "Frame interrupt in non-operational state\n");
+ break;
+ }
+}
+
+
+
+
+static void cafe_frame_irq(struct cafe_camera *cam, unsigned int irqs)
+{
+ unsigned int frame;
+
+ cafe_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */
+ /*
+ * Handle any frame completions. There really should
+ * not be more than one of these, or we have fallen
+ * far behind.
+ */
+ for (frame = 0; frame < cam->nbufs; frame++)
+ if (irqs & (IRQ_EOF0 << frame))
+ cafe_frame_complete(cam, frame);
+ /*
+ * If a frame starts, note that we have DMA active. This
+ * code assumes that we won't get multiple frame interrupts
+ * at once; may want to rethink that.
+ */
+ if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2))
+ set_bit(CF_DMA_ACTIVE, &cam->flags);
+}
+
+
+
+static irqreturn_t cafe_irq(int irq, void *data)
+{
+ struct cafe_camera *cam = data;
+ unsigned int irqs;
+
+ spin_lock(&cam->dev_lock);
+ irqs = cafe_reg_read(cam, REG_IRQSTAT);
+ if ((irqs & ALLIRQS) == 0) {
+ spin_unlock(&cam->dev_lock);
+ return IRQ_NONE;
+ }
+ if (irqs & FRAMEIRQS)
+ cafe_frame_irq(cam, irqs);
+ if (irqs & TWSIIRQS) {
+ cafe_reg_write(cam, REG_IRQSTAT, TWSIIRQS);
+ wake_up(&cam->smbus_wait);
+ }
+ spin_unlock(&cam->dev_lock);
+ return IRQ_HANDLED;
+}
+
+
+/* -------------------------------------------------------------------------- */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * Debugfs stuff.
+ */
+
+static char cafe_debug_buf[1024];
+static struct dentry *cafe_dfs_root;
+
+static void cafe_dfs_setup(void)
+{
+ cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL);
+ if (IS_ERR(cafe_dfs_root)) {
+ cafe_dfs_root = NULL; /* Never mind */
+ printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n");
+ }
+}
+
+static void cafe_dfs_shutdown(void)
+{
+ if (cafe_dfs_root)
+ debugfs_remove(cafe_dfs_root);
+}
+
+static int cafe_dfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t cafe_dfs_read_regs(struct file *file,
+ char __user *buf, size_t count, loff_t *ppos)
+{
+ struct cafe_camera *cam = file->private_data;
+ char *s = cafe_debug_buf;
+ int offset;
+
+ for (offset = 0; offset < 0x44; offset += 4)
+ s += sprintf(s, "%02x: %08x\n", offset,
+ cafe_reg_read(cam, offset));
+ for (offset = 0x88; offset <= 0x90; offset += 4)
+ s += sprintf(s, "%02x: %08x\n", offset,
+ cafe_reg_read(cam, offset));
+ for (offset = 0xb4; offset <= 0xbc; offset += 4)
+ s += sprintf(s, "%02x: %08x\n", offset,
+ cafe_reg_read(cam, offset));
+ for (offset = 0x3000; offset <= 0x300c; offset += 4)
+ s += sprintf(s, "%04x: %08x\n", offset,
+ cafe_reg_read(cam, offset));
+ return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf,
+ s - cafe_debug_buf);
+}
+
+static struct file_operations cafe_dfs_reg_ops = {
+ .owner = THIS_MODULE,
+ .read = cafe_dfs_read_regs,
+ .open = cafe_dfs_open
+};
+
+static ssize_t cafe_dfs_read_cam(struct file *file,
+ char __user *buf, size_t count, loff_t *ppos)
+{
+ struct cafe_camera *cam = file->private_data;
+ char *s = cafe_debug_buf;
+ int offset;
+
+ if (! cam->sensor)
+ return -EINVAL;
+ for (offset = 0x0; offset < 0x8a; offset++)
+ {
+ u8 v;
+
+ cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v);
+ s += sprintf(s, "%02x: %02x\n", offset, v);
+ }
+ return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf,
+ s - cafe_debug_buf);
+}
+
+static struct file_operations cafe_dfs_cam_ops = {
+ .owner = THIS_MODULE,
+ .read = cafe_dfs_read_cam,
+ .open = cafe_dfs_open
+};
+
+
+
+static void cafe_dfs_cam_setup(struct cafe_camera *cam)
+{
+ char fname[40];
+
+ if (!cafe_dfs_root)
+ return;
+ sprintf(fname, "regs-%d", cam->v4ldev.minor);
+ cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
+ cam, &cafe_dfs_reg_ops);
+ sprintf(fname, "cam-%d", cam->v4ldev.minor);
+ cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
+ cam, &cafe_dfs_cam_ops);
+}
+
+
+static void cafe_dfs_cam_shutdown(struct cafe_camera *cam)
+{
+ if (! IS_ERR(cam->dfs_regs))
+ debugfs_remove(cam->dfs_regs);
+ if (! IS_ERR(cam->dfs_cam_regs))
+ debugfs_remove(cam->dfs_cam_regs);
+}
+
+#else
+
+#define cafe_dfs_setup()
+#define cafe_dfs_shutdown()
+#define cafe_dfs_cam_setup(cam)
+#define cafe_dfs_cam_shutdown(cam)
+#endif /* CONFIG_VIDEO_ADV_DEBUG */
+
+
+
+
+/* ------------------------------------------------------------------------*/
+/*
+ * PCI interface stuff.
+ */
+
+static int cafe_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int ret;
+ u16 classword;
+ struct cafe_camera *cam;
+ /*
+ * Make sure we have a camera here - we'll get calls for
+ * the other cafe devices as well.
+ */
+ pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword);
+ if (classword != PCI_CLASS_MULTIMEDIA_VIDEO)
+ return -ENODEV;
+ /*
+ * Start putting together one of our big camera structures.
+ */
+ ret = -ENOMEM;
+ cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL);
+ if (cam == NULL)
+ goto out;
+ mutex_init(&cam->s_mutex);
+ mutex_lock(&cam->s_mutex);
+ spin_lock_init(&cam->dev_lock);
+ cam->state = S_NOTREADY;
+ cafe_set_config_needed(cam, 1);
+ init_waitqueue_head(&cam->smbus_wait);
+ init_waitqueue_head(&cam->iowait);
+ cam->pdev = pdev;
+ cam->pix_format = cafe_def_pix_format;
+ INIT_LIST_HEAD(&cam->dev_list);
+ INIT_LIST_HEAD(&cam->sb_avail);
+ INIT_LIST_HEAD(&cam->sb_full);
+ tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam);
+ /*
+ * Get set up on the PCI bus.
+ */
+ ret = pci_enable_device(pdev);
+ if (ret)
+ goto out_free;
+ pci_set_master(pdev);
+
+ ret = -EIO;
+ cam->regs = pci_iomap(pdev, 0, 0);
+ if (! cam->regs) {
+ printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n");
+ goto out_free;
+ }
+ ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
+ if (ret)
+ goto out_iounmap;
+ cafe_ctlr_init(cam);
+ cafe_ctlr_power_up(cam);
+ /*
+ * Set up I2C/SMBUS communications
+ */
+ mutex_unlock(&cam->s_mutex); /* attach can deadlock */
+ ret = cafe_smbus_setup(cam);
+ if (ret)
+ goto out_freeirq;
+ /*
+ * Get the v4l2 setup done.
+ */
+ mutex_lock(&cam->s_mutex);
+ cam->v4ldev = cafe_v4l_template;
+ cam->v4ldev.debug = 0;
+// cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG;
+ ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1);
+ if (ret)
+ goto out_smbus;
+ /*
+ * If so requested, try to get our DMA buffers now.
+ */
+ if (alloc_bufs_at_load) {
+ if (cafe_alloc_dma_bufs(cam, 1))
+ cam_warn(cam, "Unable to alloc DMA buffers at load"
+ " will try again later.");
+ }
+
+ cafe_dfs_cam_setup(cam);
+ mutex_unlock(&cam->s_mutex);
+ cafe_add_dev(cam);
+ return 0;
+
+ out_smbus:
+ cafe_smbus_shutdown(cam);
+ out_freeirq:
+ cafe_ctlr_power_down(cam);
+ free_irq(pdev->irq, cam);
+ out_iounmap:
+ pci_iounmap(pdev, cam->regs);
+ out_free:
+ kfree(cam);
+ out:
+ return ret;
+}
+
+
+/*
+ * Shut down an initialized device
+ */
+static void cafe_shutdown(struct cafe_camera *cam)
+{
+/* FIXME: Make sure we take care of everything here */
+ cafe_dfs_cam_shutdown(cam);
+ if (cam->n_sbufs > 0)
+ /* What if they are still mapped? Shouldn't be, but... */
+ cafe_free_sio_buffers(cam);
+ cafe_remove_dev(cam);
+ cafe_ctlr_stop_dma(cam);
+ cafe_ctlr_power_down(cam);
+ cafe_smbus_shutdown(cam);
+ cafe_free_dma_bufs(cam);
+ free_irq(cam->pdev->irq, cam);
+ pci_iounmap(cam->pdev, cam->regs);
+ video_unregister_device(&cam->v4ldev);
+ /* kfree(cam); done in v4l_release () */
+}
+
+
+static void cafe_pci_remove(struct pci_dev *pdev)
+{
+ struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+
+ if (cam == NULL) {
+ printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev);
+ return;
+ }
+ mutex_lock(&cam->s_mutex);
+ if (cam->users > 0)
+ cam_warn(cam, "Removing a device with users!\n");
+ cafe_shutdown(cam);
+/* No unlock - it no longer exists */
+}
+
+
+
+
+static struct pci_device_id cafe_ids[] = {
+ { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */
+ { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */
+ { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cafe_ids);
+
+static struct pci_driver cafe_pci_driver = {
+ .name = "cafe1000-ccic",
+ .id_table = cafe_ids,
+ .probe = cafe_pci_probe,
+ .remove = cafe_pci_remove,
+};
+
+
+
+
+static int __init cafe_init(void)
+{
+ int ret;
+
+ printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n",
+ CAFE_VERSION);
+ cafe_dfs_setup();
+ ret = pci_register_driver(&cafe_pci_driver);
+ if (ret) {
+ printk(KERN_ERR "Unable to register cafe_ccic driver\n");
+ goto out;
+ }
+ request_module("ov7670"); /* FIXME want something more general */
+ ret = 0;
+
+ out:
+ return ret;
+}
+
+
+static void __exit cafe_exit(void)
+{
+ pci_unregister_driver(&cafe_pci_driver);
+ cafe_dfs_shutdown();
+}
+
+module_init(cafe_init);
+module_exit(cafe_exit);
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index d82a488f12a..f065ad12cc6 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -118,7 +118,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = file->f_op->unlocked_ioctl(file, cmd, arg);
else if (file->f_op->ioctl) {
lock_kernel();
- ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
+ ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
unlock_kernel();
}
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
index 28dc6a1a1e4..d8e929863a8 100644
--- a/drivers/media/video/cpia2/cpia2_usb.c
+++ b/drivers/media/video/cpia2/cpia2_usb.c
@@ -640,6 +640,10 @@ static int submit_urbs(struct camera_data *cam)
cam->sbuf[i].data =
kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
if (!cam->sbuf[i].data) {
+ while (--i >= 0) {
+ kfree(cam->sbuf[i].data);
+ cam->sbuf[i].data = NULL;
+ }
return -ENOMEM;
}
}
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 657e0b96914..2f5ca71e026 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -742,7 +742,6 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
if (old == NULL || old->width != new->width || old->height != new->height ||
old->video_encoding != new->video_encoding) {
- int is_scaling;
u16 w = new->width;
u16 h = new->height;
@@ -752,20 +751,18 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
}
err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
if (err) return err;
+ }
+ if (new->width != 720 || new->height != (new->is_50hz ? 576 : 480)) {
/* Adjust temporal filter if necessary. The problem with the temporal
filter is that it works well with full resolution capturing, but
not when the capture window is scaled (the filter introduces
- a ghosting effect). So if the capture window changed, and there is
- no updated filter value, then the filter is set depending on whether
- the new window is full resolution or not.
+ a ghosting effect). So if the capture window is scaled, then
+ force the filter to 0.
- For full resolution a setting of 8 really improves the video
+ For full resolution the filter really improves the video
quality, especially if the original video quality is suboptimal. */
- is_scaling = new->width != 720 || new->height != (new->is_50hz ? 576 : 480);
- if (old && old->video_temporal_filter == temporal) {
- temporal = is_scaling ? 0 : 8;
- }
+ temporal = 0;
}
if (old == NULL || old->stream_type != new->stream_type) {
@@ -866,6 +863,7 @@ invalid:
void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
{
int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+ int temporal = p->video_temporal_filter;
/* Stream */
printk(KERN_INFO "%s: Stream: %s\n",
@@ -922,10 +920,13 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
p->video_spatial_filter);
+ if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480)) {
+ temporal = 0;
+ }
printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
prefix,
cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
- p->video_temporal_filter);
+ temporal);
printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
prefix,
cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index f85f2084324..ced13febed8 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -128,7 +128,14 @@ void cx25840_vbi_setup(struct i2c_client *client)
uv_lpf=1;
src_decimation=0x21f;
- if (std == V4L2_STD_PAL_M) {
+ if (std == V4L2_STD_PAL_60) {
+ vblank=26;
+ vblank656=26;
+ burst=0x5b;
+ luma_lpf=2;
+ comb=0x20;
+ sc=0x0a8263;
+ } else if (std == V4L2_STD_PAL_M) {
vblank=20;
vblank656=24;
burst=0x61;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 0f9d9696361..b2a66ba625f 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -53,6 +53,7 @@ config VIDEO_CX88_DVB
select DVB_OR51132 if !DVB_FE_CUSTOMISE
select DVB_CX22702 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
select DVB_NXT200X if !DVB_FE_CUSTOMISE
select DVB_CX24123 if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46738321ada..0cf0360588e 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
#define dprintk(level,fmt, arg...) if (debug >= level) \
printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
-static LIST_HEAD(cx8802_devlist);
/* ------------------------------------------------------------------ */
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
BLACKBIRD_MPEG_CAPTURE,
BLACKBIRD_RAW_BITS_NONE);
- cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+ cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
blackbird_initialize_codec(dev);
cx88_set_scale(dev->core, dev->width, dev->height,
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
}
default:
- return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+ return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
}
return 0;
}
+int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
static unsigned int mpeg_translate_ioctl(unsigned int cmd)
{
return cmd;
@@ -927,33 +930,49 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd)
static int mpeg_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- cmd = mpeg_translate_ioctl( cmd );
- return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+ cmd = cx88_ioctl_translator( cmd );
+ return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
}
static int mpeg_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct cx8802_dev *h,*dev = NULL;
+ struct cx8802_dev *dev = NULL;
struct cx8802_fh *fh;
- struct list_head *list;
+ struct cx8802_driver *drv = NULL;
+ int err;
- list_for_each(list,&cx8802_devlist) {
- h = list_entry(list, struct cx8802_dev, devlist);
- if (h->mpeg_dev->minor == minor)
- dev = h;
- }
- if (NULL == dev)
+ dev = cx8802_get_device(inode);
+
+ dprintk( 1, "%s\n", __FUNCTION__);
+
+ if (dev == NULL)
return -ENODEV;
- if (blackbird_initialize_codec(dev) < 0)
+ /* Make sure we can acquire the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ if (drv) {
+ err = drv->request_acquire(drv);
+ if(err != 0) {
+ dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
+ return err;
+ }
+ }
+
+ if (blackbird_initialize_codec(dev) < 0) {
+ if (drv)
+ drv->request_release(drv);
return -EINVAL;
+ }
dprintk(1,"open minor=%d\n",minor);
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ if (drv)
+ drv->request_release(drv);
return -ENOMEM;
+ }
file->private_data = fh;
fh->dev = dev;
@@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
static int mpeg_release(struct inode *inode, struct file *file)
{
struct cx8802_fh *fh = file->private_data;
+ struct cx8802_dev *dev = NULL;
+ struct cx8802_driver *drv = NULL;
/* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
@@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file)
videobuf_mmap_free(&fh->mpegq);
file->private_data = NULL;
kfree(fh);
+
+ /* Make sure we release the hardware */
+ dev = cx8802_get_device(inode);
+ if (dev == NULL)
+ return -ENODEV;
+
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ if (drv)
+ drv->request_release(drv);
+
return 0;
}
@@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template =
/* ------------------------------------------------------------------ */
+/* The CX8802 MPEG API will call this when we can use the hardware */
+static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+ int err = 0;
+
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ /* By default, core setup will leave the cx22702 out of reset, on the bus.
+ * We left the hardware on power up with the cx22702 active.
+ * We're being given access to re-arrange the GPIOs.
+ * Take the bus off the cx22702 and put the cx23416 on it.
+ */
+ cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */
+ cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */
+ break;
+ default:
+ err = -ENODEV;
+ }
+ return err;
+}
+
+/* The CX8802 MPEG API will call this when we need to release the hardware */
+static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+ int err = 0;
+
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ /* Exit leaving the cx23416 on the bus */
+ break;
+ default:
+ err = -ENODEV;
+ }
+ return err;
+}
+
static void blackbird_unregister_video(struct cx8802_dev *dev)
{
if (dev->mpeg_dev) {
@@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev)
/* ----------------------------------------------------------- */
-static int __devinit blackbird_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static int cx8802_blackbird_probe(struct cx8802_driver *drv)
{
- struct cx8802_dev *dev;
- struct cx88_core *core;
+ struct cx88_core *core = drv->core;
+ struct cx8802_dev *dev = core->dvbdev;
int err;
- /* general setup */
- core = cx88_core_get(pci_dev);
- if (NULL == core)
- return -EINVAL;
+ dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ core->board,
+ core->name,
+ core->pci_bus,
+ core->pci_slot);
err = -ENODEV;
if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
goto fail_core;
- err = -ENOMEM;
- dev = kzalloc(sizeof(*dev),GFP_KERNEL);
- if (NULL == dev)
- goto fail_core;
- dev->pci = pci_dev;
- dev->core = core;
dev->width = 720;
dev->height = 576;
cx2341x_fill_defaults(&dev->params);
@@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
dev->height = 576;
}
- err = cx8802_init_common(dev);
- if (0 != err)
- goto fail_free;
-
/* blackbird stuff */
printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
core->name);
host_setup(dev->core);
- list_add_tail(&dev->devlist,&cx8802_devlist);
blackbird_register_video(dev);
/* initial device configuration: needed ? */
return 0;
- fail_free:
- kfree(dev);
fail_core:
- cx88_core_put(core,pci_dev);
return err;
}
-static void __devexit blackbird_remove(struct pci_dev *pci_dev)
+static int cx8802_blackbird_remove(struct cx8802_driver *drv)
{
- struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-
/* blackbird */
- blackbird_unregister_video(dev);
- list_del(&dev->devlist);
+ blackbird_unregister_video(drv->core->dvbdev);
- /* common */
- cx8802_fini_common(dev);
- cx88_core_put(dev->core,dev->pci);
- kfree(dev);
+ return 0;
}
-static struct pci_device_id cx8802_pci_tbl[] = {
- {
- .vendor = 0x14f1,
- .device = 0x8802,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },{
- /* --- end of list --- */
- }
-};
-MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
-
-static struct pci_driver blackbird_pci_driver = {
- .name = "cx88-blackbird",
- .id_table = cx8802_pci_tbl,
- .probe = blackbird_probe,
- .remove = __devexit_p(blackbird_remove),
-#ifdef CONFIG_PM
- .suspend = cx8802_suspend_common,
- .resume = cx8802_resume_common,
-#endif
+static struct cx8802_driver cx8802_blackbird_driver = {
+ .type_id = CX88_MPEG_BLACKBIRD,
+ .hw_access = CX8802_DRVCTL_SHARED,
+ .probe = cx8802_blackbird_probe,
+ .remove = cx8802_blackbird_remove,
+ .advise_acquire = cx8802_blackbird_advise_acquire,
+ .advise_release = cx8802_blackbird_advise_release,
};
static int blackbird_init(void)
@@ -1176,17 +1212,22 @@ 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_register_driver(&blackbird_pci_driver);
+ cx88_ioctl_hook = mpeg_do_ioctl;
+ cx88_ioctl_translator = mpeg_translate_ioctl;
+ return cx8802_register_driver(&cx8802_blackbird_driver);
}
static void blackbird_fini(void)
{
- pci_unregister_driver(&blackbird_pci_driver);
+ cx8802_unregister_driver(&cx8802_blackbird_driver);
}
module_init(blackbird_init);
module_exit(blackbird_fini);
+EXPORT_SYMBOL(cx88_ioctl_hook);
+EXPORT_SYMBOL(cx88_ioctl_translator);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index f764a57c56b..434b78ab37d 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x0000bde2,
+ .extadc = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x0000bde6,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0000bde6,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x0000bd62,
+ .extadc = 1,
},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
@@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ .extadc = 1,
}},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x00009d80,
+ .extadc = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x00009d76,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x00009d76,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x00009d00,
+ .extadc = 1,
},
.mpeg = CX88_MPEG_BLACKBIRD,
},
@@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
- .mpeg = CX88_MPEG_BLACKBIRD,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 0,
.gpio0 = 0x0000cd73,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 1,
.gpio0 = 0x0000cd73,
+ .extadc = 1,
},{
.type = CX88_VMUX_TELEVISION,
.vmux = 3,
.gpio0 = 0x0000cdb3,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
.vmux = 2,
.gpio0 = 0x0000cdf3,
+ .extadc = 1,
},
+ .mpeg = CX88_MPEG_BLACKBIRD,
},
[CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
/* Alexander Wold <awold@bigfoot.com> */
@@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = {
.mpeg = CX88_MPEG_DVB,
},
[CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
- /* FIXME: Audio not working for s-video / composite inputs. */
.name = "KWorld HardwareMpegTV XPert",
.tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET,
@@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x3de6,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x3de6,
+ .extadc = 1,
}},
.radio = {
.type = CX88_RADIO,
@@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = {
.gpio0 = 0x070b,
}},
},
- [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
- .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
- .tuner_type = TUNER_LG_PAL_NEW_TAPC,
- .radio_type = UNSET,
- .tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
- .input = {{
- .type = CX88_VMUX_TELEVISION,
- .vmux = 0,
- .gpio0 = 0x003fffff,
- .gpio1 = 0x00e00000,
- .gpio2 = 0x003fffff,
- .gpio3 = 0x02000000,
- },{
- .type = CX88_VMUX_COMPOSITE1,
- .vmux = 1,
- .gpio0 = 0x003fffff,
- .gpio1 = 0x00e00000,
- .gpio2 = 0x003fffff,
- .gpio3 = 0x02000000,
- },{
- .type = CX88_VMUX_SVIDEO,
- .vmux = 2,
- .gpio0 = 0x003fffff,
- .gpio1 = 0x00e00000,
- .gpio2 = 0x003fffff,
- .gpio3 = 0x02000000,
- }},
- },
+ [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
+ .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
+ .tuner_type = TUNER_LG_PAL_NEW_TAPC,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x003fffff,
+ .gpio1 = 0x00e00000,
+ .gpio2 = 0x003fffff,
+ .gpio3 = 0x02000000,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x003fffff,
+ .gpio1 = 0x00e00000,
+ .gpio2 = 0x003fffff,
+ .gpio3 = 0x02000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x003fffff,
+ .gpio1 = 0x00e00000,
+ .gpio2 = 0x003fffff,
+ .gpio3 = 0x02000000,
+ }},
+ },
[CX88_BOARD_HAUPPAUGE_HVR1300] = {
.name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
.tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
@@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xe780,
+ .extadc = 1,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xe780,
+ .extadc = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xe780,
+ .extadc = 1,
}},
/* fixme: Add radio support */
- .mpeg = CX88_MPEG_DVB,
+ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
},
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = {
},{
.subvendor = 0x17de,
.subdevice = 0x0840,
+ .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+ },{
+ .subvendor = 0x1421,
+ .subdevice = 0x0305,
.card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
},{
.subvendor = 0x18ac,
@@ -1610,7 +1632,7 @@ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
/* ----------------------------------------------------------------------- */
/* some leadtek specific stuff */
-static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
+static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
/* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
* any others.
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 4b655f2ef27..18997361c75 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -633,12 +633,12 @@ int cx88_reset(struct cx88_core *core)
static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
{
- return (norm->id & V4L2_STD_625_50) ? 922 : 754;
+ return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
}
static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
{
- return (norm->id & V4L2_STD_625_50) ? 186 : 135;
+ return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
}
static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
@@ -648,24 +648,33 @@ static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
{
- static const unsigned int ntsc = 28636360;
- static const unsigned int pal = 35468950;
- static const unsigned int palm = 28604892;
-
if (norm->id & V4L2_STD_PAL_M)
- return palm;
+ return 28604892; // 3.575611 MHz
+
+ if (norm->id & (V4L2_STD_PAL_Nc))
+ return 28656448; // 3.582056 MHz
+
+ if (norm->id & V4L2_STD_NTSC) // All NTSC/M and variants
+ return 28636360; // 3.57954545 MHz +/- 10 Hz
- return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
+ /* SECAM have also different sub carrier for chroma,
+ but step_db and step_dr, at cx88_set_tvnorm already handles that.
+
+ The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
+ */
+
+ return 35468950; // 4.43361875 MHz +/- 5 Hz
}
static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
{
- /* Should always be Line Draw Time / (4*FSC) */
- if (norm->id & V4L2_STD_PAL_M)
- return 909;
+ unsigned int fsc4=norm_fsc8(norm)/2;
- return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
+ /* returns 4*FSC / vtotal / frames per seconds */
+ return (norm->id & V4L2_STD_625_50) ?
+ ((fsc4+312)/625+12)/25 :
+ ((fsc4+262)/525*1001+15000)/30000;
}
static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
@@ -692,7 +701,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
value &= 0x3fe;
cx_write(MO_HDELAY_EVEN, value);
cx_write(MO_HDELAY_ODD, value);
- dprintk(1,"set_scale: hdelay 0x%04x\n", value);
+ dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth);
value = (swidth * 4096 / width) - 4096;
cx_write(MO_HSCALE_EVEN, value);
@@ -1153,7 +1162,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
mutex_lock(&devlist);
cx88_ir_fini(core);
if (0 == core->i2c_rc)
- i2c_bit_del_bus(&core->i2c_adap);
+ i2c_del_adapter(&core->i2c_adap);
list_del(&core->devlist);
iounmap(core->lmmio);
cx88_devcount--;
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 0ef13e7efa2..8b203354fcc 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -42,7 +42,7 @@
#include "cx22702.h"
#include "or51132.h"
#include "lgdt330x.h"
-#include "lg_h06xf.h"
+#include "lgh06xf.h"
#include "nxt200x.h"
#include "cx24123.h"
#include "isl6421.h"
@@ -57,7 +57,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
#define dprintk(level,fmt, arg...) if (debug >= level) \
- printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg)
+ printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
/* ------------------------------------------------------------------ */
@@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q,
return 0;
}
-static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
+static int dvb_buf_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb, enum v4l2_field field)
{
struct cx8802_dev *dev = q->priv_data;
return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
@@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
}
-static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void dvb_buf_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
{
cx88_free_buffer(q, (struct cx88_buffer*)vb);
}
@@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = {
};
/* ------------------------------------------------------------------ */
+
+static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx8802_driver *drv = NULL;
+ int ret = 0;
+
+ drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
+ if (drv) {
+ if (acquire)
+ ret = drv->request_acquire(drv);
+ else
+ ret = drv->request_release(drv);
+ }
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------ */
+
static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
@@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
};
#endif
-static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- u8 pllbuf[4];
- struct cx8802_dev *dev= fe->dvb->priv;
- struct i2c_msg msg =
- { .addr = dev->core->pll_addr, .flags = 0,
- .buf = pllbuf, .len = 4 };
- int err;
-
- dvb_pll_configure(dev->core->pll_desc, pllbuf,
- params->frequency,
- params->u.ofdm.bandwidth);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
- printk(KERN_WARNING "cx88-dvb: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, pllbuf[0], pllbuf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- return 0;
-}
-
static struct zl10353_config dvico_fusionhdtv_hybrid = {
.demod_address = 0x0f,
.no_tuner = 1,
@@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = {
.output_mode = CX22702_SERIAL_OUTPUT,
};
-static struct cx22702_config hauppauge_novat_config = {
- .demod_address = 0x43,
- .output_mode = CX22702_SERIAL_OUTPUT,
-};
-
-static struct cx22702_config hauppauge_hvr1100_config = {
+static struct cx22702_config hauppauge_hvr_config = {
.demod_address = 0x63,
.output_mode = CX22702_SERIAL_OUTPUT,
};
-static struct cx22702_config hauppauge_hvr1300_config = {
- .demod_address = 0x63,
- .output_mode = CX22702_SERIAL_OUTPUT,
-};
-
-static struct cx22702_config hauppauge_hvr3000_config = {
- .demod_address = 0x63,
- .output_mode = CX22702_SERIAL_OUTPUT,
-};
-
-static int or51132_set_ts_param(struct dvb_frontend* fe,
- int is_punctured)
+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;
@@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = {
.set_ts_params = or51132_set_ts_param,
};
-static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
-{
- /* FIXME make this routine use the tuner-simple code.
- * It could probably be shared with a number of ATSC
- * frontends. Many share the same tuner with analog TV. */
-
- struct cx8802_dev *dev= fe->dvb->priv;
- struct cx88_core *core = dev->core;
- u8 buf[4];
- struct i2c_msg msg =
- { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
- int err;
-
- dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
- dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
- __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
- printk(KERN_WARNING "cx88-dvb: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
- return 0;
-}
-
-static int lgdt3303_tuner_set_params(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
-{
- struct cx8802_dev *dev= fe->dvb->priv;
- struct cx88_core *core = dev->core;
-
- /* Put the analog decoder in standby to keep it quiet */
- cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
-
- return lg_h06xf_pll_set(fe, &core->i2c_adap, params);
-}
-
static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
{
struct cx8802_dev *dev= fe->dvb->priv;
@@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = {
.set_ts_params = lgdt330x_set_ts_param,
};
-static int nxt200x_set_ts_param(struct dvb_frontend* fe,
- int is_punctured)
+static int nxt200x_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;
@@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
struct cx8802_dev *dev= fe->dvb->priv;
struct cx88_core *core = dev->core;
- if (voltage == SEC_VOLTAGE_OFF) {
+ if (voltage == SEC_VOLTAGE_OFF)
cx_write(MO_GP0_IO, 0x000006fb);
- } else {
+ else
cx_write(MO_GP0_IO, 0x000006f9);
- }
if (core->prev_set_voltage)
return core->prev_set_voltage(fe, voltage);
@@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev)
switch (dev->core->board) {
case CX88_BOARD_HAUPPAUGE_DVB_T1:
dev->dvb.frontend = dvb_attach(cx22702_attach,
- &hauppauge_novat_config,
+ &connexant_refboard_config,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
@@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR1100LP:
dev->dvb.frontend = dvb_attach(cx22702_attach,
- &hauppauge_hvr1100_config,
- &dev->core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- &dev->core->i2c_adap,
- &dvb_pll_fmd1216me);
- }
- break;
- case CX88_BOARD_HAUPPAUGE_HVR1300:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
- &hauppauge_hvr1300_config,
- &dev->core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- &dev->core->i2c_adap,
- &dvb_pll_fmd1216me);
- }
- break;
- case CX88_BOARD_HAUPPAUGE_HVR3000:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
- &hauppauge_hvr3000_config,
+ &hauppauge_hvr_config,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
- &dev->core->i2c_adap,
- &dvb_pll_fmd1216me);
+ &dev->core->i2c_adap, &dvb_pll_fmd1216me);
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev)
#endif
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
- dev->core->pll_addr = 0x61;
- dev->core->pll_desc = &dvb_pll_thomson_fe6600;
dev->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_hybrid,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ &dev->core->i2c_adap,
+ &dvb_pll_thomson_fe6600);
}
break;
case CX88_BOARD_PCHDTV_HD3000:
- dev->dvb.frontend = dvb_attach(or51132_attach,
- &pchdtv_hd3000,
+ dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
@@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev)
/* Select RF connector callback */
fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
- dev->core->pll_addr = 0x61;
- dev->core->pll_desc = &dvb_pll_microtune_4042;
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ &dev->core->i2c_adap,
+ &dvb_pll_microtune_4042);
}
}
break;
@@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 9);
mdelay(200);
- dev->core->pll_addr = 0x61;
- dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ &dev->core->i2c_adap,
+ &dvb_pll_thomson_dtt761x);
}
}
break;
@@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev)
&fusionhdtv_5_gold,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+ dvb_attach(lgh06xf_attach, dev->dvb.frontend,
+ &dev->core->i2c_adap);
}
}
break;
@@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev)
&pchdtv_hd5500,
&dev->core->i2c_adap);
if (dev->dvb.frontend != NULL) {
- dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+ dvb_attach(lgh06xf_attach, dev->dvb.frontend,
+ &dev->core->i2c_adap);
}
}
break;
@@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
}
break;
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ dev->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ &dev->core->i2c_adap, &dvb_pll_fmd1216me);
+ }
+ break;
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ dev->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+ dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+ &dev->core->i2c_adap, &dvb_pll_fmd1216me);
+ }
+ break;
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->core->name);
@@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
}
+ /* Ensure all frontends negotiate bus access */
+ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
/* Put the analog decoder in standby to keep it quiet */
cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
@@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev)
/* ----------------------------------------------------------- */
-static int __devinit dvb_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+/* CX8802 MPEG -> mini driver - We have been given the hardware */
+static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
{
- struct cx8802_dev *dev;
- struct cx88_core *core;
+ struct cx88_core *core = drv->core;
+ int err = 0;
+ dprintk( 1, "%s\n", __FUNCTION__);
+
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ /* We arrive here with either the cx23416 or the cx22702
+ * on the bus. Take the bus from the cx23416 and enable the
+ * cx22702 demod
+ */
+ cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */
+ cx_clear(MO_GP0_IO, 0x00000004);
+ udelay(1000);
+ break;
+ default:
+ err = -ENODEV;
+ }
+ return err;
+}
+
+/* CX8802 MPEG -> mini driver - We no longer have the hardware */
+static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+ int err = 0;
+ dprintk( 1, "%s\n", __FUNCTION__);
+
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ /* Do Nothing, leave the cx22702 on the bus. */
+ break;
+ default:
+ err = -ENODEV;
+ }
+ return err;
+}
+
+static int cx8802_dvb_probe(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+ struct cx8802_dev *dev = drv->core->dvbdev;
int err;
- /* general setup */
- core = cx88_core_get(pci_dev);
- if (NULL == core)
- return -EINVAL;
+ dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ core->board,
+ core->name,
+ core->pci_bus,
+ core->pci_slot);
err = -ENODEV;
if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
goto fail_core;
- err = -ENOMEM;
- dev = kzalloc(sizeof(*dev),GFP_KERNEL);
- if (NULL == dev)
- goto fail_core;
- dev->pci = pci_dev;
- dev->core = core;
-
- err = cx8802_init_common(dev);
- if (0 != err)
- goto fail_free;
-
#ifdef HAVE_VP3054_I2C
err = vp3054_i2c_probe(dev);
if (0 != err)
- goto fail_free;
+ goto fail_core;
#endif
/* dvb stuff */
@@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
sizeof(struct cx88_buffer),
dev);
err = dvb_register(dev);
- if (0 != err)
- goto fail_fini;
+ if (err != 0)
+ printk("%s dvb_register failed err = %d\n", __FUNCTION__, err);
- /* Maintain a reference to cx88-video can query the 8802 device. */
- core->dvbdev = dev;
- return 0;
-
- fail_fini:
- cx8802_fini_common(dev);
- fail_free:
- kfree(dev);
fail_core:
- cx88_core_put(core,pci_dev);
return err;
}
-static void __devexit dvb_remove(struct pci_dev *pci_dev)
+static int cx8802_dvb_remove(struct cx8802_driver *drv)
{
- struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-
- /* Destroy any 8802 reference. */
- dev->core->dvbdev = NULL;
+ struct cx8802_dev *dev = drv->core->dvbdev;
/* dvb */
videobuf_dvb_unregister(&dev->dvb);
@@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
vp3054_i2c_remove(dev);
#endif
- /* common */
- cx8802_fini_common(dev);
- cx88_core_put(dev->core,dev->pci);
- kfree(dev);
+ return 0;
}
-static struct pci_device_id cx8802_pci_tbl[] = {
- {
- .vendor = 0x14f1,
- .device = 0x8802,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },{
- /* --- end of list --- */
- }
-};
-MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
-
-static struct pci_driver dvb_pci_driver = {
- .name = "cx88-dvb",
- .id_table = cx8802_pci_tbl,
- .probe = dvb_probe,
- .remove = __devexit_p(dvb_remove),
-#ifdef CONFIG_PM
- .suspend = cx8802_suspend_common,
- .resume = cx8802_resume_common,
-#endif
+static struct cx8802_driver cx8802_dvb_driver = {
+ .type_id = CX88_MPEG_DVB,
+ .hw_access = CX8802_DRVCTL_SHARED,
+ .probe = cx8802_dvb_probe,
+ .remove = cx8802_dvb_remove,
+ .advise_acquire = cx8802_dvb_advise_acquire,
+ .advise_release = cx8802_dvb_advise_release,
};
static int dvb_init(void)
@@ -917,12 +848,12 @@ 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_register_driver(&dvb_pci_driver);
+ return cx8802_register_driver(&cx8802_dvb_driver);
}
static void dvb_fini(void)
{
- pci_unregister_driver(&dvb_pci_driver);
+ cx8802_unregister_driver(&cx8802_dvb_driver);
}
module_init(dvb_init);
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index e60a0a52e4b..8136673fe9e 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work)
mod_timer(&ir->timer, timeout);
}
+static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
+{
+ if (ir->polling) {
+ INIT_WORK(&ir->work, cx88_ir_work);
+ 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 */
+ }
+}
+
+static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
+{
+ if (ir->sampling) {
+ cx_write(MO_DDSCFG_IO, 0x0);
+ core->pci_irqmask &= ~(1 << 18);
+ }
+
+ if (ir->polling) {
+ del_timer_sync(&ir->timer);
+ flush_scheduled_work();
+ }
+}
+
/* ---------------------------------------------------------------------- */
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
int ir_type = IR_TYPE_OTHER;
+ int err = -ENOMEM;
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
input_dev = input_allocate_device();
- if (!ir || !input_dev) {
- kfree(ir);
- input_free_device(input_dev);
- return -ENOMEM;
- }
+ if (!ir || !input_dev)
+ goto err_out_free;
ir->input = input_dev;
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
}
if (NULL == ir_codes) {
- kfree(ir);
- input_free_device(input_dev);
- return -ENODEV;
+ err = -ENODEV;
+ goto err_out_free;
}
/* init input device */
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->core = core;
core->ir = ir;
- if (ir->polling) {
- INIT_WORK(&ir->work, cx88_ir_work);
- 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 */
- }
+ cx88_ir_start(core, ir);
/* all done */
- input_register_device(ir->input);
+ err = input_register_device(ir->input);
+ if (err)
+ goto err_out_stop;
return 0;
+
+ err_out_stop:
+ cx88_ir_stop(core, ir);
+ core->ir = NULL;
+ err_out_free:
+ input_free_device(input_dev);
+ kfree(ir);
+ return err;
}
int cx88_ir_fini(struct cx88_core *core)
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core)
if (NULL == ir)
return 0;
- if (ir->sampling) {
- cx_write(MO_DDSCFG_IO, 0x0);
- core->pci_irqmask &= ~(1 << 18);
- }
- if (ir->polling) {
- del_timer(&ir->timer);
- flush_scheduled_work();
- }
-
+ cx88_ir_stop(core, ir);
input_unregister_device(ir->input);
kfree(ir);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 6b23a4e6f66..1fe1a833c7c 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -44,8 +44,12 @@ module_param(debug,int,0644);
MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
#define dprintk(level,fmt, arg...) if (debug >= level) \
- printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg)
+ printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
+#define mpeg_dbg(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
+
+static LIST_HEAD(cx8802_devlist);
/* ------------------------------------------------------------------ */
static int cx8802_start_dma(struct cx8802_dev *dev,
@@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
/* FIXME: this needs a review.
* also: move to cx88-blackbird + cx88-dvb source files? */
- if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) {
- /* Report a warning until the mini driver patch is applied,
- * else the following conditions will set the dma registers incorrectly.
- * This will be removed in the next major patch and changes to the conditions
- * will be made.
- */
- printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__);
- return -EINVAL;
- }
- if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) {
+ dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
+
+ if ( (core->active_type_id == CX88_MPEG_DVB) &&
+ (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
+
+ dprintk( 1, "cx8802_start_dma doing .dvb\n");
/* negedge driven & software reset */
cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
udelay(100);
@@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
udelay(100);
break;
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ break;
default:
cx_write(TS_SOP_STAT, 0x00);
break;
}
cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
udelay(100);
- }
-
- if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+ } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
+ (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) {
+ dprintk( 1, "cx8802_start_dma doing .blackbird\n");
cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
@@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
udelay(100);
+ } else {
+ printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
+ cx88_boards[core->board].mpeg );
+ return -EINVAL;
}
/* reset counter */
@@ -542,8 +548,315 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
return 0;
}
+struct cx8802_dev * cx8802_get_device(struct inode *inode)
+{
+ int minor = iminor(inode);
+ struct cx8802_dev *h = NULL;
+ struct list_head *list;
+
+ list_for_each(list,&cx8802_devlist) {
+ h = list_entry(list, struct cx8802_dev, devlist);
+ if (h->mpeg_dev->minor == minor)
+ return h;
+ }
+
+ return NULL;
+}
+
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
+{
+ struct cx8802_dev *h = NULL;
+ struct cx8802_driver *d = NULL;
+ struct list_head *list;
+ struct list_head *list2;
+
+ list_for_each(list,&cx8802_devlist) {
+ h = list_entry(list, struct cx8802_dev, devlist);
+ if (h != dev)
+ continue;
+
+ list_for_each(list2, &h->drvlist.devlist) {
+ d = list_entry(list2, struct cx8802_driver, devlist);
+
+ /* only unregister the correct driver type */
+ if (d->type_id == btype) {
+ return d;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* Driver asked for hardware access. */
+int cx8802_request_acquire(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+
+ /* Fail a request for hardware if the device is busy. */
+ if (core->active_type_id != CX88_BOARD_NONE)
+ return -EBUSY;
+
+ if (drv->advise_acquire)
+ {
+ core->active_type_id = drv->type_id;
+ drv->advise_acquire(drv);
+
+ mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+ }
+
+ return 0;
+}
+
+/* Driver asked to release hardware. */
+int cx8802_request_release(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+
+ if (drv->advise_release)
+ {
+ drv->advise_release(drv);
+ core->active_type_id = CX88_BOARD_NONE;
+ mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
+ }
+
+ return 0;
+}
+
+static int cx8802_check_driver(struct cx8802_driver *drv)
+{
+ if (drv == NULL)
+ return -ENODEV;
+
+ if ((drv->type_id != CX88_MPEG_DVB) &&
+ (drv->type_id != CX88_MPEG_BLACKBIRD))
+ return -EINVAL;
+
+ if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
+ (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
+ return -EINVAL;
+
+ if ((drv->probe == NULL) ||
+ (drv->remove == NULL) ||
+ (drv->advise_acquire == NULL) ||
+ (drv->advise_release == NULL))
+ return -EINVAL;
+
+ return 0;
+}
+
+int cx8802_register_driver(struct cx8802_driver *drv)
+{
+ struct cx8802_dev *h;
+ struct cx8802_driver *driver;
+ struct list_head *list;
+ int err = 0, i = 0;
+
+ printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
+ drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+ drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+
+ if ((err = cx8802_check_driver(drv)) != 0) {
+ printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
+ return err;
+ }
+
+ list_for_each(list,&cx8802_devlist) {
+ h = list_entry(list, struct cx8802_dev, devlist);
+
+ printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
+ h->core->name,h->pci->subsystem_vendor,
+ h->pci->subsystem_device,cx88_boards[h->core->board].name,
+ h->core->board);
+
+ /* Bring up a new struct for each driver instance */
+ driver = kzalloc(sizeof(*drv),GFP_KERNEL);
+ if (driver == NULL)
+ return -ENOMEM;
+
+ /* Snapshot of the driver registration data */
+ drv->core = h->core;
+ drv->suspend = cx8802_suspend_common;
+ drv->resume = cx8802_resume_common;
+ drv->request_acquire = cx8802_request_acquire;
+ drv->request_release = cx8802_request_release;
+ memcpy(driver, drv, sizeof(*driver));
+
+ err = drv->probe(driver);
+ if (err == 0) {
+ i++;
+ mutex_lock(&drv->core->lock);
+ list_add_tail(&driver->devlist,&h->drvlist.devlist);
+ mutex_unlock(&drv->core->lock);
+ } else {
+ printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
+ }
+
+ }
+ if (i == 0)
+ err = -ENODEV;
+ else
+ err = 0;
+
+ return err;
+}
+
+int cx8802_unregister_driver(struct cx8802_driver *drv)
+{
+ struct cx8802_dev *h;
+ struct cx8802_driver *d;
+ struct list_head *list;
+ struct list_head *list2, *q;
+ int err = 0, i = 0;
+
+ printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
+ drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
+
+ list_for_each(list,&cx8802_devlist) {
+ i++;
+ h = list_entry(list, struct cx8802_dev, devlist);
+
+ printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
+ h->core->name,h->pci->subsystem_vendor,
+ h->pci->subsystem_device,cx88_boards[h->core->board].name,
+ h->core->board);
+
+ list_for_each_safe(list2, q, &h->drvlist.devlist) {
+ d = list_entry(list2, struct cx8802_driver, devlist);
+
+ /* only unregister the correct driver type */
+ if (d->type_id != drv->type_id)
+ continue;
+
+ err = d->remove(d);
+ if (err == 0) {
+ mutex_lock(&drv->core->lock);
+ list_del(list2);
+ mutex_unlock(&drv->core->lock);
+ } else
+ printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
+
+ }
+
+ }
+
+ return err;
+}
+
/* ----------------------------------------------------------- */
+static int __devinit cx8802_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ struct cx8802_dev *dev;
+ struct cx88_core *core;
+ int err;
+
+ /* general setup */
+ core = cx88_core_get(pci_dev);
+ if (NULL == core)
+ return -EINVAL;
+ printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
+
+ err = -ENODEV;
+ if (!cx88_boards[core->board].mpeg)
+ goto fail_core;
+
+ err = -ENOMEM;
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+ if (NULL == dev)
+ goto fail_core;
+ dev->pci = pci_dev;
+ dev->core = core;
+
+ err = cx8802_init_common(dev);
+ if (err != 0)
+ goto fail_free;
+
+ INIT_LIST_HEAD(&dev->drvlist.devlist);
+ list_add_tail(&dev->devlist,&cx8802_devlist);
+
+ /* Maintain a reference so cx88-video can query the 8802 device. */
+ core->dvbdev = dev;
+ return 0;
+
+ fail_free:
+ kfree(dev);
+ fail_core:
+ cx88_core_put(core,pci_dev);
+ return err;
+}
+
+static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+{
+ struct cx8802_dev *dev;
+ struct cx8802_driver *h;
+ struct list_head *list;
+
+ dev = pci_get_drvdata(pci_dev);
+
+ dprintk( 1, "%s\n", __FUNCTION__);
+
+ list_for_each(list,&dev->drvlist.devlist) {
+ h = list_entry(list, struct cx8802_driver, devlist);
+ dprintk( 1, " ->driver\n");
+ if (h->remove == NULL) {
+ printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
+ continue;
+ }
+ printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
+ cx8802_unregister_driver(h);
+ list_del(&dev->drvlist.devlist);
+ }
+
+ /* Destroy any 8802 reference. */
+ dev->core->dvbdev = NULL;
+
+ /* common */
+ cx8802_fini_common(dev);
+ cx88_core_put(dev->core,dev->pci);
+ kfree(dev);
+}
+
+static struct pci_device_id cx8802_pci_tbl[] = {
+ {
+ .vendor = 0x14f1,
+ .device = 0x8802,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },{
+ /* --- end of list --- */
+ }
+};
+MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
+
+static struct pci_driver cx8802_pci_driver = {
+ .name = "cx88-mpeg driver manager",
+ .id_table = cx8802_pci_tbl,
+ .probe = cx8802_probe,
+ .remove = __devexit_p(cx8802_remove),
+};
+
+static int cx8802_init(void)
+{
+ printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
+ (CX88_VERSION_CODE >> 16) & 0xff,
+ (CX88_VERSION_CODE >> 8) & 0xff,
+ CX88_VERSION_CODE & 0xff);
+#ifdef SNAPSHOT
+ printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
+ SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
+#endif
+ return pci_register_driver(&cx8802_pci_driver);
+}
+
+static void cx8802_fini(void)
+{
+ pci_unregister_driver(&cx8802_pci_driver);
+}
+
+module_init(cx8802_init);
+module_exit(cx8802_fini);
EXPORT_SYMBOL(cx8802_buf_prepare);
EXPORT_SYMBOL(cx8802_buf_queue);
EXPORT_SYMBOL(cx8802_cancel_buffers);
@@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers);
EXPORT_SYMBOL(cx8802_init_common);
EXPORT_SYMBOL(cx8802_fini_common);
-EXPORT_SYMBOL(cx8802_suspend_common);
-EXPORT_SYMBOL(cx8802_resume_common);
-
+EXPORT_SYMBOL(cx8802_register_driver);
+EXPORT_SYMBOL(cx8802_unregister_driver);
+EXPORT_SYMBOL(cx8802_get_device);
+EXPORT_SYMBOL(cx8802_get_driver);
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 58ba9f77352..2bd84d351a1 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -38,6 +38,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
+#include <linux/freezer.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
@@ -143,19 +144,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
cx88_start_audio_dma(core);
if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
- /* sets sound input from external adc */
- switch (core->board) {
- case CX88_BOARD_HAUPPAUGE_ROSLYN:
- case CX88_BOARD_KWORLD_MCE200_DELUXE:
- case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
- case CX88_BOARD_PIXELVIEW_PLAYTV_P7000:
- case CX88_BOARD_ASUS_PVR_416:
- cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
- break;
- default:
- cx_set(AUD_CTL, EN_I2SIN_ENABLE);
- }
-
cx_write(AUD_I2SINPUTCNTL, 4);
cx_write(AUD_BAUDRATE, 1);
/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
@@ -974,6 +962,7 @@ int cx88_audio_thread(void *data)
msleep_interruptible(1000);
if (kthread_should_stop())
break;
+ try_to_freeze();
/* just monitor the audio status for now ... */
memset(&t, 0, sizeof(t));
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 90e298d074d..8613378428f 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input)
cx_clear(MO_FILTER_ODD, 0x00002020);
break;
}
+
+ if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
+ /* sets sound input from external adc */
+ if (INPUT(input)->extadc)
+ cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+ else
+ cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+ }
return 0;
}
@@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
mutex_unlock(&core->lock);
return 0;
}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ /* ioctls to allow direct acces to the cx2388x registers */
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != 0)
+ return -EINVAL;
+ /* cx2388x has a 24-bit register space */
+ reg->val = cx_read(reg->reg&0xffffff);
+ return 0;
+ }
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != 0)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ cx_write(reg->reg&0xffffff, reg->val);
+ return 0;
+ }
+#endif
default:
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index 2b4f1970c7d..6068c9bf82c 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -168,7 +168,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev)
dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
return;
- i2c_bit_del_bus(&vp3054_i2c->adap);
+ i2c_del_adapter(&vp3054_i2c->adap);
kfree(vp3054_i2c);
}
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 3bc91aad4fe..a9575ad8ca2 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -74,6 +74,11 @@ enum cx88_board_type {
CX88_MPEG_BLACKBIRD
};
+enum cx8802_board_access {
+ CX8802_DRVCTL_SHARED = 1,
+ CX8802_DRVCTL_EXCLUSIVE = 2,
+};
+
/* ----------------------------------------------------------- */
/* tv norms */
@@ -86,7 +91,7 @@ struct cx88_tvnorm {
static unsigned int inline norm_maxw(struct cx88_tvnorm *norm)
{
- return (norm->id & V4L2_STD_625_50) ? 768 : 640;
+ return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
}
@@ -220,6 +225,7 @@ struct cx88_input {
enum cx88_itype type;
unsigned int vmux;
u32 gpio0, gpio1, gpio2, gpio3;
+ unsigned int extadc:1;
};
struct cx88_board {
@@ -330,6 +336,7 @@ struct cx88_core {
/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
struct cx8802_dev *dvbdev;
+ enum cx88_board_type active_type_id;
};
struct cx8800_dev;
@@ -405,6 +412,31 @@ struct cx8802_suspend_state {
int disabled;
};
+struct cx8802_driver {
+ struct cx88_core *core;
+ struct list_head devlist;
+
+ /* Type of driver and access required */
+ enum cx88_board_type type_id;
+ enum cx8802_board_access hw_access;
+
+ /* MPEG 8802 internal only */
+ int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
+ int (*resume)(struct pci_dev *pci_dev);
+
+ /* MPEG 8802 -> mini driver - Driver probe and configuration */
+ int (*probe)(struct cx8802_driver *drv);
+ int (*remove)(struct cx8802_driver *drv);
+
+ /* MPEG 8802 -> mini driver - Access for hardware control */
+ int (*advise_acquire)(struct cx8802_driver *drv);
+ int (*advise_release)(struct cx8802_driver *drv);
+
+ /* MPEG 8802 <- mini driver - Access for hardware control */
+ int (*request_acquire)(struct cx8802_driver *drv);
+ int (*request_release)(struct cx8802_driver *drv);
+};
+
struct cx8802_dev {
struct cx88_core *core;
spinlock_t slock;
@@ -439,6 +471,9 @@ struct cx8802_dev {
/* mpeg params */
struct cx2341x_mpeg_params params;
+
+ /* List of attached drivers */
+ struct cx8802_driver drvlist;
};
/* ----------------------------------------------------------- */
@@ -571,6 +606,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
int cx88_audio_thread(void *data);
+int cx8802_register_driver(struct cx8802_driver *drv);
+int cx8802_unregister_driver(struct cx8802_driver *drv);
+struct cx8802_dev * cx8802_get_device(struct inode *inode);
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+
/* ----------------------------------------------------------- */
/* cx88-input.c */
@@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
extern const u32 cx88_user_ctrls[];
extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
+/* ----------------------------------------------------------- */
+/* cx88-blackbird.c */
+/* used by cx88-ivtv ioctl emulation layer */
+extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index b1012e92ee0..917021fc299 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -218,7 +218,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
pipesize, packets, transfer_buffer_length);
while (buffers < (s->total_buffer_size << 10)) {
- b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL);
+ b = kzalloc(sizeof (buff_t), GFP_KERNEL);
if (!b) {
err("kzalloc(sizeof(buff_t))==NULL");
goto err;
@@ -659,7 +659,7 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm
switch (cmd) {
case IOCTL_DAB_BULK:
- pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
+ pbulk = kmalloc(sizeof (bulk_transfer_t), GFP_KERNEL);
if (!pbulk) {
ret = -ENOMEM;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 2a461dde480..36e72c207a8 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1674,9 +1674,9 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
if (dev->has_msp34xx) {
/* Send a reset to other chips via gpio */
em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
- udelay(2500);
+ msleep(3);
em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
- udelay(2500);
+ msleep(3);
}
video_mux(dev, 0);
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index ab87e7bfe84..59edf58204d 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
int ir_type;
struct IR_i2c *ir;
struct input_dev *input_dev;
+ int err;
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
- input_free_device(input_dev);
- kfree(ir);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out_free;
}
- memset(ir,0,sizeof(*ir));
ir->c = client_template;
ir->input = input_dev;
@@ -355,32 +354,34 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
break;
case 0x7a:
case 0x47:
+ case 0x71:
/* Handled by saa7134-input */
name = "SAA713x remote";
ir_type = IR_TYPE_OTHER;
break;
default:
/* shouldn't happen */
- printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
- kfree(ir);
- return -1;
+ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
+ err = -ENODEV;
+ goto err_out_free;
}
/* Sets name */
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
- ir->ir_codes=ir_codes;
+ ir->ir_codes = ir_codes;
/* register i2c device
* At device register, IR codes may be changed to be
* board dependent.
*/
- i2c_attach_client(&ir->c);
+ err = i2c_attach_client(&ir->c);
+ if (err)
+ goto err_out_free;
/* If IR not supported or disabled, unregisters driver */
if (ir->get_key == NULL) {
- i2c_detach_client(&ir->c);
- kfree(ir);
- return -1;
+ err = -ENODEV;
+ goto err_out_detach;
}
/* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
@@ -389,15 +390,17 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir->c.dev.bus_id);
/* init + register input device */
- ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
+ ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
input_dev->id.bustype = BUS_I2C;
input_dev->name = ir->c.name;
input_dev->phys = ir->phys;
- /* register event device */
- input_register_device(ir->input);
+ err = input_register_device(ir->input);
+ if (err)
+ goto err_out_detach;
+
printk(DEVNAME ": %s detected at %s [%s]\n",
- ir->input->name,ir->input->phys,adap->name);
+ ir->input->name, ir->input->phys, adap->name);
/* start polling via eventd */
INIT_WORK(&ir->work, ir_work);
@@ -407,6 +410,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
schedule_work(&ir->work);
return 0;
+
+ err_out_detach:
+ i2c_detach_client(&ir->c);
+ err_out_free:
+ input_free_device(input_dev);
+ kfree(ir);
+ return err;
}
static int ir_detach(struct i2c_client *client)
@@ -414,7 +424,7 @@ static int ir_detach(struct i2c_client *client)
struct IR_i2c *ir = i2c_get_clientdata(client);
/* kill outstanding polls */
- del_timer(&ir->timer);
+ del_timer_sync(&ir->timer);
flush_scheduled_work();
/* unregister devices */
@@ -439,7 +449,7 @@ static int ir_probe(struct i2c_adapter *adap)
*/
static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
- static const int probe_saa7134[] = { 0x7a, 0x47, -1 };
+ static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 };
static const int probe_em28XX[] = { 0x30, 0x47, -1 };
const int *probe = NULL;
struct i2c_client c;
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
index c1a377f797d..b6cd21e6dab 100644
--- a/drivers/media/video/ks0127.c
+++ b/drivers/media/video/ks0127.c
@@ -712,13 +712,13 @@ static int ks0127_command(struct i2c_client *client,
*iarg = 0;
status = ks0127_read(ks, KS_STAT);
if (!(status & 0x20)) /* NOVID not set */
- *iarg = (*iarg & DECODER_STATUS_GOOD);
+ *iarg = (*iarg | DECODER_STATUS_GOOD);
if ((status & 0x01)) /* CLOCK set */
- *iarg = (*iarg & DECODER_STATUS_COLOR);
+ *iarg = (*iarg | DECODER_STATUS_COLOR);
if ((status & 0x08)) /* PALDET set */
- *iarg = (*iarg & DECODER_STATUS_PAL);
+ *iarg = (*iarg | DECODER_STATUS_PAL);
else
- *iarg = (*iarg & DECODER_STATUS_NTSC);
+ *iarg = (*iarg | DECODER_STATUS_NTSC);
break;
//Catch any unknown command
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index b083338823d..616a35da191 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -923,7 +923,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
struct video_picture *p = arg;
if (p->depth != 16)
return -EINVAL;
- if (p->palette != VIDEO_PALETTE_YUV422)
+ if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
return -EINVAL;
mutex_lock(&meye.lock);
sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS,
@@ -978,7 +978,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
if (vm->frame >= gbuffers || vm->frame < 0)
return -EINVAL;
- if (vm->format != VIDEO_PALETTE_YUV422)
+ if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV)
return -EINVAL;
if (vm->height * vm->width * 2 > gbufsize)
return -EINVAL;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index e1b56dc13c3..2fb9fe6a1ae 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -633,10 +633,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (((rt->input >> (4 + i * 4)) & 0xf) == 0)
extern_input = 0;
}
- if (extern_input)
- state->mode = MSP_MODE_EXTERN;
- else
- state->mode = MSP_MODE_AM_DETECT;
+ state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT;
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
msp_set_scart(client, sc_in, 0);
msp_set_scart(client, sc1_out, 1);
msp_set_scart(client, sc2_out, 2);
@@ -951,7 +949,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
if (thread_func) {
state->kthread = kthread_run(thread_func, client, "msp34xx");
- if (state->kthread == NULL)
+ if (IS_ERR(state->kthread))
v4l_warn(client, "kernel_thread() failed\n");
msp_wake_thread(client);
}
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index 4c7f85b566a..e1821eb82fb 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -483,7 +483,6 @@ int msp3400c_thread(void *data)
/* no carrier scan, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
state->scan_in_progress = 0;
- state->rxsubchans = V4L2_TUNER_SUB_STEREO;
msp_set_audio(client);
continue;
}
@@ -851,12 +850,15 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
source = 1; /* stereo or A|B */
matrix = 0x20;
break;
- case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1:
- default:
source = 3; /* stereo or A */
matrix = 0x00;
break;
+ case V4L2_TUNER_MODE_STEREO:
+ default:
+ source = 3; /* stereo or A */
+ matrix = 0x20;
+ break;
}
if (in == MSP_DSP_IN_TUNER)
@@ -1030,6 +1032,9 @@ static int msp34xxg_detect_stereo(struct i2c_client *client)
int is_stereo = status & 0x40;
int oldrx = state->rxsubchans;
+ if (state->mode == MSP_MODE_EXTERN)
+ return 0;
+
state->rxsubchans = 0;
if (is_stereo)
state->rxsubchans = V4L2_TUNER_SUB_STEREO;
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index b0aea4002d1..152cc6b3e15 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -160,10 +160,6 @@ static int mxb_probe(struct saa7146_dev* dev)
printk("mxb: saa7111 i2c module not available.\n");
return -ENODEV;
}
- if ((result = request_module("tuner")) < 0) {
- printk("mxb: tuner i2c module not available.\n");
- return -ENODEV;
- }
if ((result = request_module("tea6420")) < 0) {
printk("mxb: tea6420 i2c module not available.\n");
return -ENODEV;
@@ -176,6 +172,10 @@ static int mxb_probe(struct saa7146_dev* dev)
printk("mxb: tda9840 i2c module not available.\n");
return -ENODEV;
}
+ if ((result = request_module("tuner")) < 0) {
+ printk("mxb: tuner i2c module not available.\n");
+ return -ENODEV;
+ }
mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
if( NULL == mxb ) {
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
new file mode 100644
index 00000000000..5ed0adc4ca2
--- /dev/null
+++ b/drivers/media/video/ov7670.c
@@ -0,0 +1,1333 @@
+/*
+ * A V4L2 driver for OmniVision OV7670 cameras.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc. Written
+ * by Jonathan Corbet with substantial inspiration from Mark
+ * McClelland's ovcamchip code.
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <linux/i2c.h>
+
+
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
+MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
+MODULE_LICENSE("GPL");
+
+/*
+ * Basic window sizes. These probably belong somewhere more globally
+ * useful.
+ */
+#define VGA_WIDTH 640
+#define VGA_HEIGHT 480
+#define QVGA_WIDTH 320
+#define QVGA_HEIGHT 240
+#define CIF_WIDTH 352
+#define CIF_HEIGHT 288
+#define QCIF_WIDTH 176
+#define QCIF_HEIGHT 144
+
+/*
+ * Our nominal (default) frame rate.
+ */
+#define OV7670_FRAME_RATE 30
+
+/*
+ * The 7670 sits on i2c with ID 0x42
+ */
+#define OV7670_I2C_ADDR 0x42
+
+/* Registers */
+#define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
+#define REG_BLUE 0x01 /* blue gain */
+#define REG_RED 0x02 /* red gain */
+#define REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */
+#define REG_COM1 0x04 /* Control 1 */
+#define COM1_CCIR656 0x40 /* CCIR656 enable */
+#define REG_BAVE 0x05 /* U/B Average level */
+#define REG_GbAVE 0x06 /* Y/Gb Average level */
+#define REG_AECHH 0x07 /* AEC MS 5 bits */
+#define REG_RAVE 0x08 /* V/R Average level */
+#define REG_COM2 0x09 /* Control 2 */
+#define COM2_SSLEEP 0x10 /* Soft sleep mode */
+#define REG_PID 0x0a /* Product ID MSB */
+#define REG_VER 0x0b /* Product ID LSB */
+#define REG_COM3 0x0c /* Control 3 */
+#define COM3_SWAP 0x40 /* Byte swap */
+#define COM3_SCALEEN 0x08 /* Enable scaling */
+#define COM3_DCWEN 0x04 /* Enable downsamp/crop/window */
+#define REG_COM4 0x0d /* Control 4 */
+#define REG_COM5 0x0e /* All "reserved" */
+#define REG_COM6 0x0f /* Control 6 */
+#define REG_AECH 0x10 /* More bits of AEC value */
+#define REG_CLKRC 0x11 /* Clocl control */
+#define CLK_EXT 0x40 /* Use external clock directly */
+#define CLK_SCALE 0x3f /* Mask for internal clock scale */
+#define REG_COM7 0x12 /* Control 7 */
+#define COM7_RESET 0x80 /* Register reset */
+#define COM7_FMT_MASK 0x38
+#define COM7_FMT_VGA 0x00
+#define COM7_FMT_CIF 0x20 /* CIF format */
+#define COM7_FMT_QVGA 0x10 /* QVGA format */
+#define COM7_FMT_QCIF 0x08 /* QCIF format */
+#define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */
+#define COM7_YUV 0x00 /* YUV */
+#define COM7_BAYER 0x01 /* Bayer format */
+#define COM7_PBAYER 0x05 /* "Processed bayer" */
+#define REG_COM8 0x13 /* Control 8 */
+#define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
+#define COM8_AECSTEP 0x40 /* Unlimited AEC step size */
+#define COM8_BFILT 0x20 /* Band filter enable */
+#define COM8_AGC 0x04 /* Auto gain enable */
+#define COM8_AWB 0x02 /* White balance enable */
+#define COM8_AEC 0x01 /* Auto exposure enable */
+#define REG_COM9 0x14 /* Control 9 - gain ceiling */
+#define REG_COM10 0x15 /* Control 10 */
+#define COM10_HSYNC 0x40 /* HSYNC instead of HREF */
+#define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */
+#define COM10_HREF_REV 0x08 /* Reverse HREF */
+#define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */
+#define COM10_VS_NEG 0x02 /* VSYNC negative */
+#define COM10_HS_NEG 0x01 /* HSYNC negative */
+#define REG_HSTART 0x17 /* Horiz start high bits */
+#define REG_HSTOP 0x18 /* Horiz stop high bits */
+#define REG_VSTART 0x19 /* Vert start high bits */
+#define REG_VSTOP 0x1a /* Vert stop high bits */
+#define REG_PSHFT 0x1b /* Pixel delay after HREF */
+#define REG_MIDH 0x1c /* Manuf. ID high */
+#define REG_MIDL 0x1d /* Manuf. ID low */
+#define REG_MVFP 0x1e /* Mirror / vflip */
+#define MVFP_MIRROR 0x20 /* Mirror image */
+#define MVFP_FLIP 0x10 /* Vertical flip */
+
+#define REG_AEW 0x24 /* AGC upper limit */
+#define REG_AEB 0x25 /* AGC lower limit */
+#define REG_VPT 0x26 /* AGC/AEC fast mode op region */
+#define REG_HSYST 0x30 /* HSYNC rising edge delay */
+#define REG_HSYEN 0x31 /* HSYNC falling edge delay */
+#define REG_HREF 0x32 /* HREF pieces */
+#define REG_TSLB 0x3a /* lots of stuff */
+#define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */
+#define REG_COM11 0x3b /* Control 11 */
+#define COM11_NIGHT 0x80 /* NIght mode enable */
+#define COM11_NMFR 0x60 /* Two bit NM frame rate */
+#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
+#define COM11_50HZ 0x08 /* Manual 50Hz select */
+#define COM11_EXP 0x02
+#define REG_COM12 0x3c /* Control 12 */
+#define COM12_HREF 0x80 /* HREF always */
+#define REG_COM13 0x3d /* Control 13 */
+#define COM13_GAMMA 0x80 /* Gamma enable */
+#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */
+#define COM13_UVSWAP 0x01 /* V before U - w/TSLB */
+#define REG_COM14 0x3e /* Control 14 */
+#define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */
+#define REG_EDGE 0x3f /* Edge enhancement factor */
+#define REG_COM15 0x40 /* Control 15 */
+#define COM15_R10F0 0x00 /* Data range 10 to F0 */
+#define COM15_R01FE 0x80 /* 01 to FE */
+#define COM15_R00FF 0xc0 /* 00 to FF */
+#define COM15_RGB565 0x10 /* RGB565 output */
+#define COM15_RGB555 0x30 /* RGB555 output */
+#define REG_COM16 0x41 /* Control 16 */
+#define COM16_AWBGAIN 0x08 /* AWB gain enable */
+#define REG_COM17 0x42 /* Control 17 */
+#define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */
+#define COM17_CBAR 0x08 /* DSP Color bar */
+
+/*
+ * This matrix defines how the colors are generated, must be
+ * tweaked to adjust hue and saturation.
+ *
+ * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
+ *
+ * They are nine-bit signed quantities, with the sign bit
+ * stored in 0x58. Sign for v-red is bit 0, and up from there.
+ */
+#define REG_CMATRIX_BASE 0x4f
+#define CMATRIX_LEN 6
+#define REG_CMATRIX_SIGN 0x58
+
+
+#define REG_BRIGHT 0x55 /* Brightness */
+#define REG_CONTRAS 0x56 /* Contrast control */
+
+#define REG_GFIX 0x69 /* Fix gain control */
+
+#define REG_RGB444 0x8c /* RGB 444 control */
+#define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */
+#define R444_RGBX 0x01 /* Empty nibble at end */
+
+#define REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */
+#define REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */
+
+#define REG_BD50MAX 0xa5 /* 50hz banding step limit */
+#define REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */
+#define REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */
+#define REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */
+#define REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */
+#define REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
+#define REG_BD60MAX 0xab /* 60hz banding step limit */
+
+
+/*
+ * Information we maintain about a known sensor.
+ */
+struct ov7670_format_struct; /* coming later */
+struct ov7670_info {
+ struct ov7670_format_struct *fmt; /* Current format */
+ unsigned char sat; /* Saturation value */
+ int hue; /* Hue value */
+};
+
+
+
+
+/*
+ * The default register settings, as obtained from OmniVision. There
+ * is really no making sense of most of these - lots of "reserved" values
+ * and such.
+ *
+ * These settings give VGA YUYV.
+ */
+
+struct regval_list {
+ unsigned char reg_num;
+ unsigned char value;
+};
+
+static struct regval_list ov7670_default_regs[] = {
+ { REG_COM7, COM7_RESET },
+/*
+ * Clock scale: 3 = 15fps
+ * 2 = 20fps
+ * 1 = 30fps
+ */
+ { REG_CLKRC, 0x1 }, /* OV: clock scale (30 fps) */
+ { REG_TSLB, 0x04 }, /* OV */
+ { REG_COM7, 0 }, /* VGA */
+ /*
+ * Set the hardware window. These values from OV don't entirely
+ * make sense - hstop is less than hstart. But they work...
+ */
+ { REG_HSTART, 0x13 }, { REG_HSTOP, 0x01 },
+ { REG_HREF, 0xb6 }, { REG_VSTART, 0x02 },
+ { REG_VSTOP, 0x7a }, { REG_VREF, 0x0a },
+
+ { REG_COM3, 0 }, { REG_COM14, 0 },
+ /* Mystery scaling numbers */
+ { 0x70, 0x3a }, { 0x71, 0x35 },
+ { 0x72, 0x11 }, { 0x73, 0xf0 },
+ { 0xa2, 0x02 }, { REG_COM10, 0x0 },
+
+ /* Gamma curve values */
+ { 0x7a, 0x20 }, { 0x7b, 0x10 },
+ { 0x7c, 0x1e }, { 0x7d, 0x35 },
+ { 0x7e, 0x5a }, { 0x7f, 0x69 },
+ { 0x80, 0x76 }, { 0x81, 0x80 },
+ { 0x82, 0x88 }, { 0x83, 0x8f },
+ { 0x84, 0x96 }, { 0x85, 0xa3 },
+ { 0x86, 0xaf }, { 0x87, 0xc4 },
+ { 0x88, 0xd7 }, { 0x89, 0xe8 },
+
+ /* AGC and AEC parameters. Note we start by disabling those features,
+ then turn them only after tweaking the values. */
+ { REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT },
+ { REG_GAIN, 0 }, { REG_AECH, 0 },
+ { REG_COM4, 0x40 }, /* magic reserved bit */
+ { REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+ { REG_BD50MAX, 0x05 }, { REG_BD60MAX, 0x07 },
+ { REG_AEW, 0x95 }, { REG_AEB, 0x33 },
+ { REG_VPT, 0xe3 }, { REG_HAECC1, 0x78 },
+ { REG_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */
+ { REG_HAECC3, 0xd8 }, { REG_HAECC4, 0xd8 },
+ { REG_HAECC5, 0xf0 }, { REG_HAECC6, 0x90 },
+ { REG_HAECC7, 0x94 },
+ { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC },
+
+ /* Almost all of these are magic "reserved" values. */
+ { REG_COM5, 0x61 }, { REG_COM6, 0x4b },
+ { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR },
+ { 0x21, 0x02 }, { 0x22, 0x91 },
+ { 0x29, 0x07 }, { 0x33, 0x0b },
+ { 0x35, 0x0b }, { 0x37, 0x1d },
+ { 0x38, 0x71 }, { 0x39, 0x2a },
+ { REG_COM12, 0x78 }, { 0x4d, 0x40 },
+ { 0x4e, 0x20 }, { REG_GFIX, 0 },
+ { 0x6b, 0x4a }, { 0x74, 0x10 },
+ { 0x8d, 0x4f }, { 0x8e, 0 },
+ { 0x8f, 0 }, { 0x90, 0 },
+ { 0x91, 0 }, { 0x96, 0 },
+ { 0x9a, 0 }, { 0xb0, 0x84 },
+ { 0xb1, 0x0c }, { 0xb2, 0x0e },
+ { 0xb3, 0x82 }, { 0xb8, 0x0a },
+
+ /* More reserved magic, some of which tweaks white balance */
+ { 0x43, 0x0a }, { 0x44, 0xf0 },
+ { 0x45, 0x34 }, { 0x46, 0x58 },
+ { 0x47, 0x28 }, { 0x48, 0x3a },
+ { 0x59, 0x88 }, { 0x5a, 0x88 },
+ { 0x5b, 0x44 }, { 0x5c, 0x67 },
+ { 0x5d, 0x49 }, { 0x5e, 0x0e },
+ { 0x6c, 0x0a }, { 0x6d, 0x55 },
+ { 0x6e, 0x11 }, { 0x6f, 0x9f }, /* "9e for advance AWB" */
+ { 0x6a, 0x40 }, { REG_BLUE, 0x40 },
+ { REG_RED, 0x60 },
+ { REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB },
+
+ /* Matrix coefficients */
+ { 0x4f, 0x80 }, { 0x50, 0x80 },
+ { 0x51, 0 }, { 0x52, 0x22 },
+ { 0x53, 0x5e }, { 0x54, 0x80 },
+ { 0x58, 0x9e },
+
+ { REG_COM16, COM16_AWBGAIN }, { REG_EDGE, 0 },
+ { 0x75, 0x05 }, { 0x76, 0xe1 },
+ { 0x4c, 0 }, { 0x77, 0x01 },
+ { REG_COM13, 0xc3 }, { 0x4b, 0x09 },
+ { 0xc9, 0x60 }, { REG_COM16, 0x38 },
+ { 0x56, 0x40 },
+
+ { 0x34, 0x11 }, { REG_COM11, COM11_EXP|COM11_HZAUTO },
+ { 0xa4, 0x88 }, { 0x96, 0 },
+ { 0x97, 0x30 }, { 0x98, 0x20 },
+ { 0x99, 0x30 }, { 0x9a, 0x84 },
+ { 0x9b, 0x29 }, { 0x9c, 0x03 },
+ { 0x9d, 0x4c }, { 0x9e, 0x3f },
+ { 0x78, 0x04 },
+
+ /* Extra-weird stuff. Some sort of multiplexor register */
+ { 0x79, 0x01 }, { 0xc8, 0xf0 },
+ { 0x79, 0x0f }, { 0xc8, 0x00 },
+ { 0x79, 0x10 }, { 0xc8, 0x7e },
+ { 0x79, 0x0a }, { 0xc8, 0x80 },
+ { 0x79, 0x0b }, { 0xc8, 0x01 },
+ { 0x79, 0x0c }, { 0xc8, 0x0f },
+ { 0x79, 0x0d }, { 0xc8, 0x20 },
+ { 0x79, 0x09 }, { 0xc8, 0x80 },
+ { 0x79, 0x02 }, { 0xc8, 0xc0 },
+ { 0x79, 0x03 }, { 0xc8, 0x40 },
+ { 0x79, 0x05 }, { 0xc8, 0x30 },
+ { 0x79, 0x26 },
+
+ { 0xff, 0xff }, /* END MARKER */
+};
+
+
+/*
+ * Here we'll try to encapsulate the changes for just the output
+ * video format.
+ *
+ * RGB656 and YUV422 come from OV; RGB444 is homebrewed.
+ *
+ * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why.
+ */
+
+
+static struct regval_list ov7670_fmt_yuv422[] = {
+ { REG_COM7, 0x0 }, /* Selects YUV mode */
+ { REG_RGB444, 0 }, /* No RGB444 please */
+ { REG_COM1, 0 },
+ { REG_COM15, COM15_R00FF },
+ { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */
+ { 0x4f, 0x80 }, /* "matrix coefficient 1" */
+ { 0x50, 0x80 }, /* "matrix coefficient 2" */
+ { 0x51, 0 }, /* vb */
+ { 0x52, 0x22 }, /* "matrix coefficient 4" */
+ { 0x53, 0x5e }, /* "matrix coefficient 5" */
+ { 0x54, 0x80 }, /* "matrix coefficient 6" */
+ { REG_COM13, COM13_GAMMA|COM13_UVSAT },
+ { 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_rgb565[] = {
+ { REG_COM7, COM7_RGB }, /* Selects RGB mode */
+ { REG_RGB444, 0 }, /* No RGB444 please */
+ { REG_COM1, 0x0 },
+ { REG_COM15, COM15_RGB565 },
+ { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */
+ { 0x4f, 0xb3 }, /* "matrix coefficient 1" */
+ { 0x50, 0xb3 }, /* "matrix coefficient 2" */
+ { 0x51, 0 }, /* vb */
+ { 0x52, 0x3d }, /* "matrix coefficient 4" */
+ { 0x53, 0xa7 }, /* "matrix coefficient 5" */
+ { 0x54, 0xe4 }, /* "matrix coefficient 6" */
+ { REG_COM13, COM13_GAMMA|COM13_UVSAT },
+ { 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_rgb444[] = {
+ { REG_COM7, COM7_RGB }, /* Selects RGB mode */
+ { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */
+ { REG_COM1, 0x40 }, /* Magic reserved bit */
+ { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */
+ { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */
+ { 0x4f, 0xb3 }, /* "matrix coefficient 1" */
+ { 0x50, 0xb3 }, /* "matrix coefficient 2" */
+ { 0x51, 0 }, /* vb */
+ { 0x52, 0x3d }, /* "matrix coefficient 4" */
+ { 0x53, 0xa7 }, /* "matrix coefficient 5" */
+ { 0x54, 0xe4 }, /* "matrix coefficient 6" */
+ { REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 }, /* Magic rsvd bit */
+ { 0xff, 0xff },
+};
+
+
+
+
+/*
+ * Low-level register I/O.
+ */
+
+static int ov7670_read(struct i2c_client *c, unsigned char reg,
+ unsigned char *value)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(c, reg);
+ if (ret >= 0)
+ *value = (unsigned char) ret;
+ return ret;
+}
+
+
+static int ov7670_write(struct i2c_client *c, unsigned char reg,
+ unsigned char value)
+{
+ return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+
+/*
+ * Write a list of register settings; ff/ff stops the process.
+ */
+static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals)
+{
+ while (vals->reg_num != 0xff || vals->value != 0xff) {
+ int ret = ov7670_write(c, vals->reg_num, vals->value);
+ if (ret < 0)
+ return ret;
+ vals++;
+ }
+ return 0;
+}
+
+
+/*
+ * Stuff that knows about the sensor.
+ */
+static void ov7670_reset(struct i2c_client *client)
+{
+ ov7670_write(client, REG_COM7, COM7_RESET);
+ msleep(1);
+}
+
+
+static int ov7670_init(struct i2c_client *client)
+{
+ return ov7670_write_array(client, ov7670_default_regs);
+}
+
+
+
+static int ov7670_detect(struct i2c_client *client)
+{
+ unsigned char v;
+ int ret;
+
+ ret = ov7670_init(client);
+ if (ret < 0)
+ return ret;
+ ret = ov7670_read(client, REG_MIDH, &v);
+ if (ret < 0)
+ return ret;
+ if (v != 0x7f) /* OV manuf. id. */
+ return -ENODEV;
+ ret = ov7670_read(client, REG_MIDL, &v);
+ if (ret < 0)
+ return ret;
+ if (v != 0xa2)
+ return -ENODEV;
+ /*
+ * OK, we know we have an OmniVision chip...but which one?
+ */
+ ret = ov7670_read(client, REG_PID, &v);
+ if (ret < 0)
+ return ret;
+ if (v != 0x76) /* PID + VER = 0x76 / 0x73 */
+ return -ENODEV;
+ ret = ov7670_read(client, REG_VER, &v);
+ if (ret < 0)
+ return ret;
+ if (v != 0x73) /* PID + VER = 0x76 / 0x73 */
+ return -ENODEV;
+ return 0;
+}
+
+
+/*
+ * Store information about the video data format. The color matrix
+ * is deeply tied into the format, so keep the relevant values here.
+ * The magic matrix nubmers come from OmniVision.
+ */
+static struct ov7670_format_struct {
+ __u8 *desc;
+ __u32 pixelformat;
+ struct regval_list *regs;
+ int cmatrix[CMATRIX_LEN];
+} ov7670_formats[] = {
+ {
+ .desc = "YUYV 4:2:2",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .regs = ov7670_fmt_yuv422,
+ .cmatrix = { 128, -128, 0, -34, -94, 128 },
+ },
+ {
+ .desc = "RGB 444",
+ .pixelformat = V4L2_PIX_FMT_RGB444,
+ .regs = ov7670_fmt_rgb444,
+ .cmatrix = { 179, -179, 0, -61, -176, 228 },
+ },
+ {
+ .desc = "RGB 565",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ .regs = ov7670_fmt_rgb565,
+ .cmatrix = { 179, -179, 0, -61, -176, 228 },
+ },
+};
+#define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0]))
+
+/*
+ * All formats we support are 2 bytes/pixel.
+ */
+#define BYTES_PER_PIXEL 2
+
+/*
+ * Then there is the issue of window sizes. Try to capture the info here.
+ */
+
+/*
+ * QCIF mode is done (by OV) in a very strange way - it actually looks like
+ * VGA with weird scaling options - they do *not* use the canned QCIF mode
+ * which is allegedly provided by the sensor. So here's the weird register
+ * settings.
+ */
+static struct regval_list ov7670_qcif_regs[] = {
+ { REG_COM3, COM3_SCALEEN|COM3_DCWEN },
+ { REG_COM3, COM3_DCWEN },
+ { REG_COM14, COM14_DCWEN | 0x01},
+ { 0x73, 0xf1 },
+ { 0xa2, 0x52 },
+ { 0x7b, 0x1c },
+ { 0x7c, 0x28 },
+ { 0x7d, 0x3c },
+ { 0x7f, 0x69 },
+ { REG_COM9, 0x38 },
+ { 0xa1, 0x0b },
+ { 0x74, 0x19 },
+ { 0x9a, 0x80 },
+ { 0x43, 0x14 },
+ { REG_COM13, 0xc0 },
+ { 0xff, 0xff },
+};
+
+static struct ov7670_win_size {
+ int width;
+ int height;
+ unsigned char com7_bit;
+ int hstart; /* Start/stop values for the camera. Note */
+ int hstop; /* that they do not always make complete */
+ int vstart; /* sense to humans, but evidently the sensor */
+ int vstop; /* will do the right thing... */
+ struct regval_list *regs; /* Regs to tweak */
+/* h/vref stuff */
+} ov7670_win_sizes[] = {
+ /* VGA */
+ {
+ .width = VGA_WIDTH,
+ .height = VGA_HEIGHT,
+ .com7_bit = COM7_FMT_VGA,
+ .hstart = 158, /* These values from */
+ .hstop = 14, /* Omnivision */
+ .vstart = 10,
+ .vstop = 490,
+ .regs = NULL,
+ },
+ /* CIF */
+ {
+ .width = CIF_WIDTH,
+ .height = CIF_HEIGHT,
+ .com7_bit = COM7_FMT_CIF,
+ .hstart = 170, /* Empirically determined */
+ .hstop = 90,
+ .vstart = 14,
+ .vstop = 494,
+ .regs = NULL,
+ },
+ /* QVGA */
+ {
+ .width = QVGA_WIDTH,
+ .height = QVGA_HEIGHT,
+ .com7_bit = COM7_FMT_QVGA,
+ .hstart = 164, /* Empirically determined */
+ .hstop = 20,
+ .vstart = 14,
+ .vstop = 494,
+ .regs = NULL,
+ },
+ /* QCIF */
+ {
+ .width = QCIF_WIDTH,
+ .height = QCIF_HEIGHT,
+ .com7_bit = COM7_FMT_VGA, /* see comment above */
+ .hstart = 456, /* Empirically determined */
+ .hstop = 24,
+ .vstart = 14,
+ .vstop = 494,
+ .regs = ov7670_qcif_regs,
+ },
+};
+
+#define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0]))
+
+
+/*
+ * Store a set of start/stop values into the camera.
+ */
+static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop,
+ int vstart, int vstop)
+{
+ int ret;
+ unsigned char v;
+/*
+ * Horizontal: 11 bits, top 8 live in hstart and hstop. Bottom 3 of
+ * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is
+ * a mystery "edge offset" value in the top two bits of href.
+ */
+ ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff);
+ ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff);
+ ret += ov7670_read(client, REG_HREF, &v);
+ v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
+ msleep(10);
+ ret += ov7670_write(client, REG_HREF, v);
+/*
+ * Vertical: similar arrangement, but only 10 bits.
+ */
+ ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff);
+ ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff);
+ ret += ov7670_read(client, REG_VREF, &v);
+ v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3);
+ msleep(10);
+ ret += ov7670_write(client, REG_VREF, v);
+ return ret;
+}
+
+
+static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt)
+{
+ struct ov7670_format_struct *ofmt;
+
+ if (fmt->index >= N_OV7670_FMTS)
+ return -EINVAL;
+
+ ofmt = ov7670_formats + fmt->index;
+ fmt->flags = 0;
+ strcpy(fmt->description, ofmt->desc);
+ fmt->pixelformat = ofmt->pixelformat;
+ return 0;
+}
+
+
+static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
+ struct ov7670_format_struct **ret_fmt,
+ struct ov7670_win_size **ret_wsize)
+{
+ int index;
+ struct ov7670_win_size *wsize;
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ for (index = 0; index < N_OV7670_FMTS; index++)
+ if (ov7670_formats[index].pixelformat == pix->pixelformat)
+ break;
+ if (index >= N_OV7670_FMTS)
+ return -EINVAL;
+ if (ret_fmt != NULL)
+ *ret_fmt = ov7670_formats + index;
+ /*
+ * Fields: the OV devices claim to be progressive.
+ */
+ if (pix->field == V4L2_FIELD_ANY)
+ pix->field = V4L2_FIELD_NONE;
+ else if (pix->field != V4L2_FIELD_NONE)
+ return -EINVAL;
+ /*
+ * Round requested image size down to the nearest
+ * we support, but not below the smallest.
+ */
+ for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
+ wsize++)
+ if (pix->width >= wsize->width && pix->height >= wsize->height)
+ break;
+ if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
+ wsize--; /* Take the smallest one */
+ if (ret_wsize != NULL)
+ *ret_wsize = wsize;
+ /*
+ * Note the size we'll actually handle.
+ */
+ pix->width = wsize->width;
+ pix->height = wsize->height;
+ pix->bytesperline = pix->width*BYTES_PER_PIXEL;
+ pix->sizeimage = pix->height*pix->bytesperline;
+ return 0;
+}
+
+/*
+ * Set a format.
+ */
+static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
+{
+ int ret;
+ struct ov7670_format_struct *ovfmt;
+ struct ov7670_win_size *wsize;
+ struct ov7670_info *info = i2c_get_clientdata(c);
+ unsigned char com7;
+
+ ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize);
+ if (ret)
+ return ret;
+ /*
+ * COM7 is a pain in the ass, it doesn't like to be read then
+ * quickly written afterward. But we have everything we need
+ * to set it absolutely here, as long as the format-specific
+ * register sets list it first.
+ */
+ com7 = ovfmt->regs[0].value;
+ com7 |= wsize->com7_bit;
+ ov7670_write(c, REG_COM7, com7);
+ /*
+ * Now write the rest of the array. Also store start/stops
+ */
+ ov7670_write_array(c, ovfmt->regs + 1);
+ ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart,
+ wsize->vstop);
+ ret = 0;
+ if (wsize->regs)
+ ret = ov7670_write_array(c, wsize->regs);
+ info->fmt = ovfmt;
+ return 0;
+}
+
+/*
+ * Implement G/S_PARM. There is a "high quality" mode we could try
+ * to do someday; for now, we just do the frame rate tweak.
+ */
+static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
+{
+ struct v4l2_captureparm *cp = &parms->parm.capture;
+ unsigned char clkrc;
+ int ret;
+
+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ ret = ov7670_read(c, REG_CLKRC, &clkrc);
+ if (ret < 0)
+ return ret;
+ memset(cp, 0, sizeof(struct v4l2_captureparm));
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+ cp->timeperframe.numerator = 1;
+ cp->timeperframe.denominator = OV7670_FRAME_RATE;
+ if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1)
+ cp->timeperframe.denominator /= (clkrc & CLK_SCALE);
+ return 0;
+}
+
+static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
+{
+ struct v4l2_captureparm *cp = &parms->parm.capture;
+ struct v4l2_fract *tpf = &cp->timeperframe;
+ unsigned char clkrc;
+ int ret, div;
+
+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (cp->extendedmode != 0)
+ return -EINVAL;
+ /*
+ * CLKRC has a reserved bit, so let's preserve it.
+ */
+ ret = ov7670_read(c, REG_CLKRC, &clkrc);
+ if (ret < 0)
+ return ret;
+ if (tpf->numerator == 0 || tpf->denominator == 0)
+ div = 1; /* Reset to full rate */
+ else
+ div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator;
+ if (div == 0)
+ div = 1;
+ else if (div > CLK_SCALE)
+ div = CLK_SCALE;
+ clkrc = (clkrc & 0x80) | div;
+ tpf->numerator = 1;
+ tpf->denominator = OV7670_FRAME_RATE/div;
+ return ov7670_write(c, REG_CLKRC, clkrc);
+}
+
+
+
+/*
+ * Code for dealing with controls.
+ */
+
+
+
+
+
+static int ov7670_store_cmatrix(struct i2c_client *client,
+ int matrix[CMATRIX_LEN])
+{
+ int i, ret;
+ unsigned char signbits;
+
+ /*
+ * Weird crap seems to exist in the upper part of
+ * the sign bits register, so let's preserve it.
+ */
+ ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits);
+ signbits &= 0xc0;
+
+ for (i = 0; i < CMATRIX_LEN; i++) {
+ unsigned char raw;
+
+ if (matrix[i] < 0) {
+ signbits |= (1 << i);
+ if (matrix[i] < -255)
+ raw = 0xff;
+ else
+ raw = (-1 * matrix[i]) & 0xff;
+ }
+ else {
+ if (matrix[i] > 255)
+ raw = 0xff;
+ else
+ raw = matrix[i] & 0xff;
+ }
+ ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw);
+ }
+ ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits);
+ return ret;
+}
+
+
+/*
+ * Hue also requires messing with the color matrix. It also requires
+ * trig functions, which tend not to be well supported in the kernel.
+ * So here is a simple table of sine values, 0-90 degrees, in steps
+ * of five degrees. Values are multiplied by 1000.
+ *
+ * The following naive approximate trig functions require an argument
+ * carefully limited to -180 <= theta <= 180.
+ */
+#define SIN_STEP 5
+static const int ov7670_sin_table[] = {
+ 0, 87, 173, 258, 342, 422,
+ 499, 573, 642, 707, 766, 819,
+ 866, 906, 939, 965, 984, 996,
+ 1000
+};
+
+static int ov7670_sine(int theta)
+{
+ int chs = 1;
+ int sine;
+
+ if (theta < 0) {
+ theta = -theta;
+ chs = -1;
+ }
+ if (theta <= 90)
+ sine = ov7670_sin_table[theta/SIN_STEP];
+ else {
+ theta -= 90;
+ sine = 1000 - ov7670_sin_table[theta/SIN_STEP];
+ }
+ return sine*chs;
+}
+
+static int ov7670_cosine(int theta)
+{
+ theta = 90 - theta;
+ if (theta > 180)
+ theta -= 360;
+ else if (theta < -180)
+ theta += 360;
+ return ov7670_sine(theta);
+}
+
+
+
+
+static void ov7670_calc_cmatrix(struct ov7670_info *info,
+ int matrix[CMATRIX_LEN])
+{
+ int i;
+ /*
+ * Apply the current saturation setting first.
+ */
+ for (i = 0; i < CMATRIX_LEN; i++)
+ matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7;
+ /*
+ * Then, if need be, rotate the hue value.
+ */
+ if (info->hue != 0) {
+ int sinth, costh, tmpmatrix[CMATRIX_LEN];
+
+ memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int));
+ sinth = ov7670_sine(info->hue);
+ costh = ov7670_cosine(info->hue);
+
+ matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000;
+ matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000;
+ matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000;
+ matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000;
+ matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000;
+ matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000;
+ }
+}
+
+
+
+static int ov7670_t_sat(struct i2c_client *client, int value)
+{
+ struct ov7670_info *info = i2c_get_clientdata(client);
+ int matrix[CMATRIX_LEN];
+ int ret;
+
+ info->sat = value;
+ ov7670_calc_cmatrix(info, matrix);
+ ret = ov7670_store_cmatrix(client, matrix);
+ return ret;
+}
+
+static int ov7670_q_sat(struct i2c_client *client, __s32 *value)
+{
+ struct ov7670_info *info = i2c_get_clientdata(client);
+
+ *value = info->sat;
+ return 0;
+}
+
+static int ov7670_t_hue(struct i2c_client *client, int value)
+{
+ struct ov7670_info *info = i2c_get_clientdata(client);
+ int matrix[CMATRIX_LEN];
+ int ret;
+
+ if (value < -180 || value > 180)
+ return -EINVAL;
+ info->hue = value;
+ ov7670_calc_cmatrix(info, matrix);
+ ret = ov7670_store_cmatrix(client, matrix);
+ return ret;
+}
+
+
+static int ov7670_q_hue(struct i2c_client *client, __s32 *value)
+{
+ struct ov7670_info *info = i2c_get_clientdata(client);
+
+ *value = info->hue;
+ return 0;
+}
+
+
+/*
+ * Some weird registers seem to store values in a sign/magnitude format!
+ */
+static unsigned char ov7670_sm_to_abs(unsigned char v)
+{
+ if ((v & 0x80) == 0)
+ return v + 128;
+ else
+ return 128 - (v & 0x7f);
+}
+
+
+static unsigned char ov7670_abs_to_sm(unsigned char v)
+{
+ if (v > 127)
+ return v & 0x7f;
+ else
+ return (128 - v) | 0x80;
+}
+
+static int ov7670_t_brightness(struct i2c_client *client, int value)
+{
+ unsigned char com8, v;
+ int ret;
+
+ ov7670_read(client, REG_COM8, &com8);
+ com8 &= ~COM8_AEC;
+ ov7670_write(client, REG_COM8, com8);
+ v = ov7670_abs_to_sm(value);
+ ret = ov7670_write(client, REG_BRIGHT, v);
+ return ret;
+}
+
+static int ov7670_q_brightness(struct i2c_client *client, __s32 *value)
+{
+ unsigned char v;
+ int ret = ov7670_read(client, REG_BRIGHT, &v);
+
+ *value = ov7670_sm_to_abs(v);
+ return ret;
+}
+
+static int ov7670_t_contrast(struct i2c_client *client, int value)
+{
+ return ov7670_write(client, REG_CONTRAS, (unsigned char) value);
+}
+
+static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
+{
+ unsigned char v;
+ int ret = ov7670_read(client, REG_CONTRAS, &v);
+
+ *value = v;
+ return ret;
+}
+
+static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
+{
+ int ret;
+ unsigned char v;
+
+ ret = ov7670_read(client, REG_MVFP, &v);
+ *value = (v & MVFP_MIRROR) == MVFP_MIRROR;
+ return ret;
+}
+
+
+static int ov7670_t_hflip(struct i2c_client *client, int value)
+{
+ unsigned char v;
+ int ret;
+
+ ret = ov7670_read(client, REG_MVFP, &v);
+ if (value)
+ v |= MVFP_MIRROR;
+ else
+ v &= ~MVFP_MIRROR;
+ msleep(10); /* FIXME */
+ ret += ov7670_write(client, REG_MVFP, v);
+ return ret;
+}
+
+
+
+static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
+{
+ int ret;
+ unsigned char v;
+
+ ret = ov7670_read(client, REG_MVFP, &v);
+ *value = (v & MVFP_FLIP) == MVFP_FLIP;
+ return ret;
+}
+
+
+static int ov7670_t_vflip(struct i2c_client *client, int value)
+{
+ unsigned char v;
+ int ret;
+
+ ret = ov7670_read(client, REG_MVFP, &v);
+ if (value)
+ v |= MVFP_FLIP;
+ else
+ v &= ~MVFP_FLIP;
+ msleep(10); /* FIXME */
+ ret += ov7670_write(client, REG_MVFP, v);
+ return ret;
+}
+
+
+static struct ov7670_control {
+ struct v4l2_queryctrl qc;
+ int (*query)(struct i2c_client *c, __s32 *value);
+ int (*tweak)(struct i2c_client *c, int value);
+} ov7670_controls[] =
+{
+ {
+ .qc = {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 0x80,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .tweak = ov7670_t_brightness,
+ .query = ov7670_q_brightness,
+ },
+ {
+ .qc = {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0x40, /* XXX ov7670 spec */
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .tweak = ov7670_t_contrast,
+ .query = ov7670_q_contrast,
+ },
+ {
+ .qc = {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 256,
+ .step = 1,
+ .default_value = 0x80,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .tweak = ov7670_t_sat,
+ .query = ov7670_q_sat,
+ },
+ {
+ .qc = {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HUE",
+ .minimum = -180,
+ .maximum = 180,
+ .step = 5,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_SLIDER
+ },
+ .tweak = ov7670_t_hue,
+ .query = ov7670_q_hue,
+ },
+ {
+ .qc = {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .tweak = ov7670_t_vflip,
+ .query = ov7670_q_vflip,
+ },
+ {
+ .qc = {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Horizontal mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ },
+ .tweak = ov7670_t_hflip,
+ .query = ov7670_q_hflip,
+ },
+};
+#define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0]))
+
+static struct ov7670_control *ov7670_find_control(__u32 id)
+{
+ int i;
+
+ for (i = 0; i < N_CONTROLS; i++)
+ if (ov7670_controls[i].qc.id == id)
+ return ov7670_controls + i;
+ return NULL;
+}
+
+
+static int ov7670_queryctrl(struct i2c_client *client,
+ struct v4l2_queryctrl *qc)
+{
+ struct ov7670_control *ctrl = ov7670_find_control(qc->id);
+
+ if (ctrl == NULL)
+ return -EINVAL;
+ *qc = ctrl->qc;
+ return 0;
+}
+
+static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
+ int ret;
+
+ if (octrl == NULL)
+ return -EINVAL;
+ ret = octrl->query(client, &ctrl->value);
+ if (ret >= 0)
+ return 0;
+ return ret;
+}
+
+static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
+ int ret;
+
+ if (octrl == NULL)
+ return -EINVAL;
+ ret = octrl->tweak(client, ctrl->value);
+ if (ret >= 0)
+ return 0;
+ return ret;
+}
+
+
+
+
+
+
+/*
+ * Basic i2c stuff.
+ */
+static struct i2c_driver ov7670_driver;
+
+static int ov7670_attach(struct i2c_adapter *adapter)
+{
+ int ret;
+ struct i2c_client *client;
+ struct ov7670_info *info;
+
+ /*
+ * For now: only deal with adapters we recognize.
+ */
+ if (adapter->id != I2C_HW_SMBUS_CAFE)
+ return -ENODEV;
+
+ client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL);
+ if (! client)
+ return -ENOMEM;
+ client->adapter = adapter;
+ client->addr = OV7670_I2C_ADDR;
+ client->driver = &ov7670_driver,
+ strcpy(client->name, "OV7670");
+ /*
+ * Set up our info structure.
+ */
+ info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL);
+ if (! info) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+ info->fmt = &ov7670_formats[0];
+ info->sat = 128; /* Review this */
+ i2c_set_clientdata(client, info);
+
+ /*
+ * Make sure it's an ov7670
+ */
+ ret = ov7670_detect(client);
+ if (ret)
+ goto out_free_info;
+ i2c_attach_client(client);
+ return 0;
+
+ out_free_info:
+ kfree(info);
+ out_free:
+ kfree(client);
+ return ret;
+}
+
+
+static int ov7670_detach(struct i2c_client *client)
+{
+ i2c_detach_client(client);
+ kfree(i2c_get_clientdata(client));
+ kfree(client);
+ return 0;
+}
+
+
+static int ov7670_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ switch (cmd) {
+ case VIDIOC_INT_G_CHIP_IDENT:
+ * (enum v4l2_chip_ident *) arg = V4L2_IDENT_OV7670;
+ return 0;
+
+ case VIDIOC_INT_RESET:
+ ov7670_reset(client);
+ return 0;
+
+ case VIDIOC_INT_INIT:
+ return ov7670_init(client);
+
+ case VIDIOC_ENUM_FMT:
+ return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg);
+ case VIDIOC_TRY_FMT:
+ return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL);
+ case VIDIOC_S_FMT:
+ return ov7670_s_fmt(client, (struct v4l2_format *) arg);
+ case VIDIOC_QUERYCTRL:
+ return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg);
+ case VIDIOC_S_CTRL:
+ return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
+ case VIDIOC_G_CTRL:
+ return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
+ case VIDIOC_S_PARM:
+ return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
+ case VIDIOC_G_PARM:
+ return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
+ }
+ return -EINVAL;
+}
+
+
+
+static struct i2c_driver ov7670_driver = {
+ .driver = {
+ .name = "ov7670",
+ },
+ .id = I2C_DRIVERID_OV7670,
+ .class = I2C_CLASS_CAM_DIGITAL,
+ .attach_adapter = ov7670_attach,
+ .detach_client = ov7670_detach,
+ .command = ov7670_command,
+};
+
+
+/*
+ * Module initialization
+ */
+static int __init ov7670_mod_init(void)
+{
+ printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n");
+ return i2c_add_driver(&ov7670_driver);
+}
+
+static void __exit ov7670_mod_exit(void)
+{
+ i2c_del_driver(&ov7670_driver);
+}
+
+module_init(ov7670_mod_init);
+module_exit(ov7670_mod_exit);
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 368d6e219fa..86d2884e16c 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -138,7 +138,7 @@ static int grabbuf_alloc(struct planb *pb)
+ MAX_LNUM
#endif /* PLANB_GSCANLINE */
);
- if ((pb->rawbuf = (unsigned char**) kmalloc (npage
+ if ((pb->rawbuf = kmalloc(npage
* sizeof(unsigned long), GFP_KERNEL)) == 0)
return -ENOMEM;
for (i = 0; i < npage; i++) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index c80c26be6e4..848fb233d80 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
sizeof(decoder_ops[0]))) - 1;
hdw->decoder_ctrl = &ctxt->ctrl;
cp->handler = &ctxt->handler;
+ {
+ /*
+ Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
+ of nuttiness for cx25840 causes that module to
+ correctly set up its video scaling. This is really
+ a problem in the cx25840 module itself, but we work
+ around it here. The problem has not been seen in
+ ivtv because there VBI is supported and set up. We
+ don't do VBI here (at least not yet) and thus we
+ never attempted to even set it up.
+ */
+ struct v4l2_format fmt;
+ memset(&fmt,0,sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
+ }
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
cp->client->addr);
return !0;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 1f787333d18..d2004965187 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -356,28 +356,6 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
return 0;
}
-static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
-{
- /* If we're dealing with a 24xxx device, force the horizontal
- maximum to be 720 no matter what, since we can't get the device
- to work properly with any other value. Otherwise just return
- the normal value. */
- *vp = cptr->info->def.type_int.max_value;
- if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
- return 0;
-}
-
-static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
-{
- /* If we're dealing with a 24xxx device, force the horizontal
- minimum to be 720 no matter what, since we can't get the device
- to work properly with any other value. Otherwise just return
- the normal value. */
- *vp = cptr->info->def.type_int.min_value;
- if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
- return 0;
-}
-
static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
{
/* Actual maximum depends on the video standard in effect. */
@@ -758,10 +736,6 @@ static const struct pvr2_ctl_info control_defs[] = {
.default_value = 720,
DEFREF(res_hor),
DEFINT(19,720),
- /* Hook in check for clamp on horizontal resolution in
- order to avoid unsolved problem involving cx25840. */
- .get_max_value = ctrl_hres_max_get,
- .get_min_value = ctrl_hres_min_get,
},{
.desc = "Vertical capture resolution",
.name = "resolution_ver",
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 3b9012f8e38..f9bb41d8f4f 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
}
}
+
+/* This is a special entry point for cases of I2C transaction attempts to
+ the IR receiver. The implementation here simulates the IR receiver by
+ issuing a command to the FX2 firmware and using that response to return
+ what the real I2C receiver would have returned. We use this for 24xxx
+ devices, where the IR receiver chip has been removed and replaced with
+ FX2 related logic. */
+static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
+ u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+ u8 dat[4];
+ unsigned int stat;
+
+ if (!(rlen || wlen)) {
+ /* This is a probe attempt. Just let it succeed. */
+ return 0;
+ }
+
+ /* We don't understand this kind of transaction */
+ if ((wlen != 0) || (rlen == 0)) return -EIO;
+
+ if (rlen < 3) {
+ /* Mike Isely <isely@pobox.com> Appears to be a probe
+ attempt from lirc. Just fill in zeroes and return. If
+ we try instead to do the full transaction here, then bad
+ things seem to happen within the lirc driver module
+ (version 0.8.0-7 sources from Debian, when run under
+ vanilla 2.6.17.6 kernel) - and I don't have the patience
+ to chase it down. */
+ if (rlen > 0) rdata[0] = 0;
+ if (rlen > 1) rdata[1] = 0;
+ return 0;
+ }
+
+ /* Issue a command to the FX2 to read the IR receiver. */
+ LOCK_TAKE(hdw->ctl_lock); do {
+ hdw->cmd_buffer[0] = 0xec;
+ stat = pvr2_send_request(hdw,
+ hdw->cmd_buffer,1,
+ hdw->cmd_buffer,4);
+ dat[0] = hdw->cmd_buffer[0];
+ dat[1] = hdw->cmd_buffer[1];
+ dat[2] = hdw->cmd_buffer[2];
+ dat[3] = hdw->cmd_buffer[3];
+ } while (0); LOCK_GIVE(hdw->ctl_lock);
+
+ /* Give up if that operation failed. */
+ if (stat != 0) return stat;
+
+ /* Mangle the results into something that looks like the real IR
+ receiver. */
+ rdata[2] = 0xc1;
+ if (dat[0] != 1) {
+ /* No code received. */
+ rdata[0] = 0;
+ rdata[1] = 0;
+ } else {
+ u16 val;
+ /* Mash the FX2 firmware-provided IR code into something
+ that the normal i2c chip-level driver expects. */
+ val = dat[1];
+ val <<= 8;
+ val |= dat[2];
+ val >>= 1;
+ val &= ~0x0003;
+ val |= 0x8000;
+ rdata[0] = (val >> 8) & 0xffu;
+ rdata[1] = val & 0xffu;
+ }
+
+ return 0;
+}
+
/* This is a special entry point that is entered if an I2C operation is
attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this
part doesn't work, but we know it is really there. So let's look for
@@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
{
unsigned int idx;
- // The default action for all possible I2C addresses is just to do
- // the transfer normally.
+ /* The default action for all possible I2C addresses is just to do
+ the transfer normally. */
for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
hdw->i2c_func[idx] = pvr2_i2c_basic_op;
}
- // If however we're dealing with new hardware, insert some hacks in
- // the I2C transfer stack to let things work better.
+ /* However, deal with various special cases for 24xxx hardware. */
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
hdw->i2c_func[0x1b] = i2c_hack_wm8775;
hdw->i2c_func[0x44] = i2c_hack_cx25840;
+ hdw->i2c_func[0x18] = i2c_24xxx_ir;
}
// Configure the adapter and set up everything else related to it.
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index f28398dd9d9..c2374ed7ba9 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
/* On 60Hz, it is using a higher Vertical Output Size */
if (!is_50hz)
- res+=(VRES_60HZ-480)>>1;
+ res += (VRES_60HZ - 480) >> 1;
/* height */
saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
@@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
/* Activates task "B" */
saa711x_write(client, R_80_GLOBAL_CNTL_1,
- saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20);
+ saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20);
return 0;
}
@@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
if (std & V4L2_STD_525_60) {
v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
saa711x_writeregs(client, saa7115_cfg_60hz_video);
- saa711x_set_size(client,720,480);
+ saa711x_set_size(client, 720, 480);
} else {
v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
saa711x_writeregs(client, saa7115_cfg_50hz_video);
- saa711x_set_size(client,720,576);
+ saa711x_set_size(client, 720, 576);
}
/* Register 0E - Bits D6-D4 on NO-AUTO mode
@@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
client->driver = &i2c_driver_saa711x;
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
- for (i=0;i<0x0f;i++) {
+ for (i = 0; i < 0x0f; i++) {
saa711x_write(client, 0, i);
- name[i] = (saa711x_read(client, 0) &0x0f) +'0';
- if (name[i]>'9')
- name[i]+='a'-'9'-1;
+ name[i] = (saa711x_read(client, 0) & 0x0f) + '0';
+ if (name[i] > '9')
+ name[i] += 'a' - '9' - 1;
}
- name[i]='\0';
+ name[i] = '\0';
saa711x_write(client, 0, 5);
chip_id = saa711x_read(client, 0) & 0x0f;
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 4abf5c03a74..ffb0f647a86 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -1,10 +1,6 @@
/*
* SAA713x ALSA support for V4L
*
- *
- * Caveats:
- * - Volume doesn't work (it's always at max)
- *
* This program is free software; 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
@@ -614,13 +610,18 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
snd_card_saa7134_pcm_t *pcm;
snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
struct saa7134_dev *dev = saa7134->dev;
- int err;
+ int amux, err;
mutex_lock(&dev->dmasound.lock);
dev->dmasound.read_count = 0;
dev->dmasound.read_offset = 0;
+ amux = dev->input->amux;
+ if ((amux < 1) || (amux > 3))
+ amux = 1;
+ dev->dmasound.input = amux - 1;
+
mutex_unlock(&dev->dmasound.lock);
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
@@ -713,6 +714,8 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
struct snd_ctl_elem_value * ucontrol)
{
snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+ struct saa7134_dev *dev = chip->dev;
+
int change, addr = kcontrol->private_value;
int left, right;
@@ -727,10 +730,52 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
if (right > 20)
right = 20;
spin_lock_irq(&chip->mixer_lock);
- change = chip->mixer_volume[addr][0] != left ||
- chip->mixer_volume[addr][1] != right;
- chip->mixer_volume[addr][0] = left;
- chip->mixer_volume[addr][1] = right;
+ change = 0;
+ if (chip->mixer_volume[addr][0] != left) {
+ change = 1;
+ right = left;
+ }
+ if (chip->mixer_volume[addr][1] != right) {
+ change = 1;
+ left = right;
+ }
+ if (change) {
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ switch (addr) {
+ case MIXER_ADDR_TVTUNER:
+ left = 20;
+ break;
+ case MIXER_ADDR_LINE1:
+ saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10,
+ (left > 10) ? 0x00 : 0x10);
+ break;
+ case MIXER_ADDR_LINE2:
+ saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20,
+ (left > 10) ? 0x00 : 0x20);
+ break;
+ }
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ switch (addr) {
+ case MIXER_ADDR_TVTUNER:
+ left = 20;
+ break;
+ case MIXER_ADDR_LINE1:
+ saa_andorb(0x0594, 0x10,
+ (left > 10) ? 0x00 : 0x10);
+ break;
+ case MIXER_ADDR_LINE2:
+ saa_andorb(0x0594, 0x20,
+ (left > 10) ? 0x00 : 0x20);
+ break;
+ }
+ break;
+ }
+ chip->mixer_volume[addr][0] = left;
+ chip->mixer_volume[addr][1] = right;
+ }
spin_unlock_irq(&chip->mixer_lock);
return change;
}
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 51f0cfdcb68..ae984bbe36b 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2462,14 +2462,17 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 1,
.amux = TV,
.tv = 1,
+ .gpio = 0x0000000,
},{
.name = name_comp1,
.vmux = 3,
.amux = LINE2,
+ .gpio = 0x0200000,
},{
.name = name_svideo,
.vmux = 8,
.amux = LINE2,
+ .gpio = 0x0200000,
}},
.radio = {
.name = name_radio,
@@ -2567,6 +2570,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
+ .gpiomask = 1 << 21,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -2575,15 +2579,20 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_comp1,
.vmux = 3,
- .amux = LINE1,
+ .amux = LINE2, /* unconfirmed, taken from Philips driver */
+ },{
+ .name = name_comp2,
+ .vmux = 0, /* untested, Composite over S-Video */
+ .amux = LINE2,
},{
.name = name_svideo,
- .vmux = 0,
- .amux = LINE1,
+ .vmux = 8,
+ .amux = LINE2,
}},
.radio = {
.name = name_radio,
- .amux = LINE1,
+ .amux = TV,
+ .gpio = 0x0200000,
},
},
[SAA7134_BOARD_CINERGY250PCI] = {
@@ -3022,6 +3031,158 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7134_BOARD_PINNACLE_PCTV_310i] = {
+ .name = "Pinnacle PCTV 310i",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 0x000200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 4,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = name_comp2,
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = {
+ /* Mikhail Fedotov <mo_fedotov@mail.ru> */
+ .name = "Avermedia AVerTV Studio 507",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1256_IH3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .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 = LINE2,
+ .gpio = 0x01,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ .gpio = 0x00,
+ },
+ },
+ [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = {
+ /* Francis Barber <fedora@barber-family.id.au> */
+ .name = "Compro Videomate DVB-T200A",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
+ /* Thomas Genty <tomlohave@gmail.com> */
+ .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ },
+ },
+ [SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
+ .name = "Terratec Cinergy HT PCMCIA",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE1,
+ }},
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3631,6 +3792,36 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x4860,
.driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x11bd,
+ .subdevice = 0x002f,
+ .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0x9715,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1043,
+ .subdevice = 0x4876,
+ .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x0070,
+ .subdevice = 0x6701,
+ .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x153b,
+ .subdevice = 0x1172,
+ .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3717,6 +3908,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
case SAA7134_BOARD_AVERMEDIA_307:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
case SAA7134_BOARD_AVERMEDIA_777:
/* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */
@@ -3725,6 +3917,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
case SAA7134_BOARD_MANLI_MTV001:
case SAA7134_BOARD_MANLI_MTV002:
case SAA7134_BOARD_BEHOLD_409FM:
@@ -3793,7 +3986,9 @@ int saa7134_board_init1(struct saa7134_dev *dev)
break;
/* i2c remotes */
case SAA7134_BOARD_PINNACLE_PCTV_110i:
+ case SAA7134_BOARD_PINNACLE_PCTV_310i:
case SAA7134_BOARD_UPMOST_PURPLE_TV:
+ case SAA7134_BOARD_HAUPPAUGE_HVR1110:
dev->has_remote = SAA7134_REMOTE_I2C;
break;
case SAA7134_BOARD_AVERMEDIA_A169_B:
@@ -3924,9 +4119,11 @@ int saa7134_board_init2(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_PHILIPS_TIGER:
+ case SAA7134_BOARD_PINNACLE_PCTV_310i:
case SAA7134_BOARD_TEVION_DVBT_220RF:
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+ case SAA7134_BOARD_HAUPPAUGE_HVR1110:
/* this is a hybrid board, initialize to analog mode
* and configure firmware eeprom address
*/
@@ -3952,6 +4149,14 @@ int saa7134_board_init2(struct saa7134_dev *dev)
i2c_transfer(&dev->i2c_adap, &msg, 1);
}
break;
+ case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+ /* make the tda10046 find its eeprom */
+ {
+ u8 data[] = { 0x3c, 0x33, 0x60};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+ }
+ break;
case SAA7134_BOARD_KWORLD_ATSC110:
{
/* enable tuner */
@@ -3964,6 +4169,29 @@ int saa7134_board_init2(struct saa7134_dev *dev)
dev->name, i);
}
break;
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+ /* The T200 and the T200A share the same pci id. Consequently,
+ * we are going to query eeprom to try to find out which one we
+ * are actually looking at. */
+
+ /* Don't do this if the board was specifically selected with an
+ * insmod option or if we have the default configuration T200*/
+ if(!dev->autodetected || (dev->eedata[0x41] == 0xd0))
+ break;
+ if(dev->eedata[0x41] == 0x02) {
+ /* Reconfigure board as T200A */
+ dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
+ dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+ dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
+ printk(KERN_INFO "%s: Reconfigured board as %s\n",
+ dev->name, saa7134_boards[dev->board].name);
+ } else {
+ printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
+ dev->name, dev->eedata[0x41]);
+ break;
+ }
+ break;
}
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 5c9e63dfbea..ed038fff3b4 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -889,15 +889,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
must_configure_manually();
dev->board = SAA7134_BOARD_UNKNOWN;
}
+ dev->autodetected = card[dev->nr] != dev->board;
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
if (UNSET != tuner[dev->nr])
dev->tuner_type = tuner[dev->nr];
- printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
- dev->name,pci_dev->subsystem_vendor,
- pci_dev->subsystem_device,saa7134_boards[dev->board].name,
- dev->board, card[dev->nr] == dev->board ?
- "insmod option" : "autodetected");
+ printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ dev->name,pci_dev->subsystem_vendor,
+ pci_dev->subsystem_device,saa7134_boards[dev->board].name,
+ dev->board, dev->autodetected ?
+ "autodetected" : "insmod option");
/* get mmio */
if (!request_mem_region(pci_resource_start(pci_dev,0),
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 6b61d9b2fcb..c33f6a69a24 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -50,6 +50,10 @@ static unsigned int antenna_pwr = 0;
module_param(antenna_pwr, int, 0444);
MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
+static int use_frontend = 0;
+module_param(use_frontend, int, 0644);
+MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
+
/* ------------------------------------------------------------------ */
static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
{
@@ -293,7 +297,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv
return philips_tda6651_pll_set(0x60, fe, params);
}
-static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
+static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
const struct firmware **fw, char *name)
{
struct saa7134_dev *dev = fe->dvb->priv;
@@ -308,7 +312,7 @@ static struct tda1004x_config philips_tu1216_60_config = {
.xtal_freq = TDA10046_XTAL_4M,
.agc_config = TDA10046_AGC_DEFAULT,
.if_freq = TDA10046_FREQ_3617,
- .request_firmware = philips_tu1216_request_firmware,
+ .request_firmware = philips_tda1004x_request_firmware,
};
/* ------------------------------------------------------------------ */
@@ -331,12 +335,12 @@ static struct tda1004x_config philips_tu1216_61_config = {
.xtal_freq = TDA10046_XTAL_4M,
.agc_config = TDA10046_AGC_DEFAULT,
.if_freq = TDA10046_FREQ_3617,
- .request_firmware = philips_tu1216_request_firmware,
+ .request_firmware = philips_tda1004x_request_firmware,
};
/* ------------------------------------------------------------------ */
-static int philips_europa_tuner_init(struct dvb_frontend *fe)
+static int philips_td1316_tuner_init(struct dvb_frontend *fe)
{
struct saa7134_dev *dev = fe->dvb->priv;
static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
@@ -347,18 +351,8 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe)
fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
return -EIO;
- msleep(1);
-
- /* switch the board to dvb mode */
- init_msg.addr = 0x43;
- init_msg.len = 0x02;
- msg[0] = 0x00;
- msg[1] = 0x40;
if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
- if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
- return -EIO;
-
+ fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
}
@@ -367,6 +361,22 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
return philips_tda6651_pll_set(0x61, fe, params);
}
+static int philips_europa_tuner_init(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 msg[] = { 0x00, 0x40};
+ struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+
+ if (philips_td1316_tuner_init(fe))
+ return -EIO;
+ msleep(1);
+ if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+
static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
{
struct saa7134_dev *dev = fe->dvb->priv;
@@ -671,7 +681,7 @@ static struct tda1004x_config tda827x_lifeview_config = {
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
- .agc_config = TDA10046_AGC_TDA827X,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
.if_freq = TDA10046_FREQ_045,
.request_firmware = NULL,
};
@@ -812,32 +822,40 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
}
/* ------------------------------------------------------------------ */
-static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
- int ret;
struct saa7134_dev *dev = fe->dvb->priv;
static u8 tda8290_close[] = { 0x21, 0xc0};
static u8 tda8290_open[] = { 0x21, 0x80};
struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
-
- /* close tda8290 i2c bridge */
- tda8290_msg.buf = tda8290_close;
- ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
- if (ret != 1)
+ if (enable) {
+ tda8290_msg.buf = tda8290_close;
+ } else {
+ tda8290_msg.buf = tda8290_open;
+ }
+ if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1)
return -EIO;
msleep(20);
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ int ret;
+
ret = philips_tda827xa_pll_set(0x61, fe, params);
if (ret != 0)
return ret;
- /* open tda8290 i2c bridge */
- tda8290_msg.buf = tda8290_open;
- i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
- return ret;
+ return 0;
}
static int philips_tiger_tuner_init(struct dvb_frontend *fe)
@@ -867,13 +885,80 @@ static struct tda1004x_config philips_tiger_config = {
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
- .agc_config = TDA10046_AGC_TDA827X,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
+ .if_freq = TDA10046_FREQ_045,
+ .request_firmware = NULL,
+};
+/* ------------------------------------------------------------------ */
+
+static int cinergy_ht_tuner_init(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 data[] = { 0x3c, 0x33, 0x62};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+ if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 data[] = { 0x3c, 0x33, 0x60};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+ philips_tda827xa_tuner_sleep( 0x61, fe);
+ return 0;
+}
+
+static struct tda1004x_config cinergy_ht_config = {
+ .demod_address = 0x08,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_16M,
+ .agc_config = TDA10046_AGC_TDA827X_GP01,
.if_freq = TDA10046_FREQ_045,
.request_firmware = NULL,
};
/* ------------------------------------------------------------------ */
+static struct tda1004x_config pinnacle_pctv_310i_config = {
+ .demod_address = 0x08,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_16M,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
+ .if_freq = TDA10046_FREQ_045,
+ .request_firmware = philips_tda1004x_request_firmware,
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct tda1004x_config hauppauge_hvr_1110_config = {
+ .demod_address = 0x08,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_16M,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
+ .if_freq = TDA10046_FREQ_045,
+ .request_firmware = philips_tda1004x_request_firmware,
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct tda1004x_config asus_p7131_dual_config = {
+ .demod_address = 0x08,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_16M,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
+ .if_freq = TDA10046_FREQ_045,
+ .request_firmware = philips_tda1004x_request_firmware,
+};
+
static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe)
{
struct saa7134_dev *dev = fe->dvb->priv;
@@ -921,7 +1006,7 @@ static struct tda1004x_config lifeview_trio_config = {
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
- .agc_config = TDA10046_AGC_TDA827X_GPL,
+ .agc_config = TDA10046_AGC_TDA827X_GP00,
.if_freq = TDA10046_FREQ_045,
.request_firmware = NULL,
};
@@ -958,7 +1043,7 @@ static struct tda1004x_config ads_tech_duo_config = {
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
- .agc_config = TDA10046_AGC_TDA827X_GPL,
+ .agc_config = TDA10046_AGC_TDA827X_GP00,
.if_freq = TDA10046_FREQ_045,
.request_firmware = NULL,
};
@@ -983,7 +1068,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = {
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
- .agc_config = TDA10046_AGC_TDA827X,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
.if_freq = TDA10046_FREQ_045,
.request_firmware = NULL,
};
@@ -1028,7 +1113,7 @@ static struct tda1004x_config md8800_dvbt_config = {
.invert = 1,
.invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_16M,
- .agc_config = TDA10046_AGC_TDA827X,
+ .agc_config = TDA10046_AGC_TDA827X_GP11,
.if_freq = TDA10046_FREQ_045,
.request_firmware = NULL,
};
@@ -1168,6 +1253,29 @@ static int dvb_init(struct saa7134_dev *dev)
&philips_tiger_config,
&dev->i2c_adap);
if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+ dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+ dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+ dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+ }
+ break;
+ case SAA7134_BOARD_PINNACLE_PCTV_310i:
+ dev->dvb.frontend = dvb_attach(tda10046_attach,
+ &pinnacle_pctv_310i_config,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+ dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+ dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+ dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+ }
+ break;
+ case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+ dev->dvb.frontend = dvb_attach(tda10046_attach,
+ &hauppauge_hvr_1110_config,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
@@ -1175,9 +1283,10 @@ static int dvb_init(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
dev->dvb.frontend = dvb_attach(tda10046_attach,
- &philips_tiger_config,
+ &asus_p7131_dual_config,
&dev->i2c_adap);
if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init;
dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep;
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
@@ -1194,12 +1303,27 @@ static int dvb_init(struct saa7134_dev *dev)
}
break;
case SAA7134_BOARD_FLYDVB_TRIO:
- dev->dvb.frontend = dvb_attach(tda10046_attach,
- &lifeview_trio_config,
- &dev->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
- dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
+ if(! use_frontend) { //terrestrial
+ dev->dvb.frontend = dvb_attach(tda10046_attach,
+ &lifeview_trio_config,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
+ dev->dvb.frontend->ops.tuner_ops.set_params =
+ lifeview_trio_tuner_set_params;
+ }
+ } else { //satellite
+ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
+ &dev->i2c_adap, 0) == NULL) {
+ printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
+ }
+ if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
+ 0x08, 0, 0) == NULL) {
+ printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
+ }
+ }
}
break;
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
@@ -1281,7 +1405,27 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
}
break;
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+ dev->dvb.frontend = dvb_attach(tda10046_attach,
+ &philips_europa_config,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
+ dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+ }
+ break;
+ case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+ dev->dvb.frontend = dvb_attach(tda10046_attach,
+ &cinergy_ht_config,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+ dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init;
+ dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep;
+ dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+ }
+ break;
default:
printk("%s: Huh? unknown DVB card?\n",dev->name);
break;
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 6162550c413..6f9fe86fed9 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -341,6 +341,7 @@ static int attach_inform(struct i2c_client *client)
switch (client->addr) {
case 0x7a:
case 0x47:
+ case 0x71:
{
struct IR_i2c *ir = i2c_get_clientdata(client);
d1printk("%s i2c IR detected (%s).\n",
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index dee83552e68..60b38defd9b 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -112,6 +112,27 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char buf[5], cod4, code3, code4;
+
+ /* poll IR chip */
+ if (5 != i2c_master_recv(&ir->c,buf,5))
+ return -EIO;
+
+ cod4 = buf[4];
+ code4 = (cod4 >> 2);
+ code3 = buf[3];
+ if (code3 == 0)
+ /* no key pressed */
+ return 0;
+
+ /* return key */
+ *ir_key = code4;
+ *ir_raw = code4;
+ return 1;
+}
+
void saa7134_input_irq(struct saa7134_dev *dev)
{
struct saa7134_ir *ir = dev->remote;
@@ -131,6 +152,23 @@ static void saa7134_input_timer(unsigned long data)
mod_timer(&ir->timer, timeout);
}
+static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir)
+{
+ if (ir->polling) {
+ init_timer(&ir->timer);
+ ir->timer.function = saa7134_input_timer;
+ ir->timer.data = (unsigned long)dev;
+ ir->timer.expires = jiffies + HZ;
+ add_timer(&ir->timer);
+ }
+}
+
+static void saa7134_ir_stop(struct saa7134_dev *dev)
+{
+ if (dev->remote->polling)
+ del_timer_sync(&dev->remote->timer);
+}
+
int saa7134_input_init1(struct saa7134_dev *dev)
{
struct saa7134_ir *ir;
@@ -141,6 +179,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
u32 mask_keyup = 0;
int polling = 0;
int ir_type = IR_TYPE_OTHER;
+ int err;
if (dev->has_remote != SAA7134_REMOTE_GPIO)
return -ENODEV;
@@ -184,6 +223,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_307:
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
ir_codes = ir_codes_avermedia;
mask_keycode = 0x0007C8;
@@ -266,9 +306,8 @@ int saa7134_input_init1(struct saa7134_dev *dev)
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
- kfree(ir);
- input_free_device(input_dev);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_out_free;
}
ir->dev = input_dev;
@@ -299,18 +338,22 @@ int saa7134_input_init1(struct saa7134_dev *dev)
}
input_dev->cdev.dev = &dev->pci->dev;
- /* all done */
dev->remote = ir;
- if (ir->polling) {
- init_timer(&ir->timer);
- ir->timer.function = saa7134_input_timer;
- ir->timer.data = (unsigned long)dev;
- ir->timer.expires = jiffies + HZ;
- add_timer(&ir->timer);
- }
+ saa7134_ir_start(dev, ir);
+
+ err = input_register_device(ir->dev);
+ if (err)
+ goto err_out_stop;
- input_register_device(ir->dev);
return 0;
+
+ err_out_stop:
+ saa7134_ir_stop(dev);
+ dev->remote = NULL;
+ err_out_free:
+ input_free_device(input_dev);
+ kfree(ir);
+ return err;
}
void saa7134_input_fini(struct saa7134_dev *dev)
@@ -318,8 +361,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
if (NULL == dev->remote)
return;
- if (dev->remote->polling)
- del_timer_sync(&dev->remote->timer);
+ saa7134_ir_stop(dev);
input_unregister_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
@@ -335,6 +377,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
+ case SAA7134_BOARD_PINNACLE_PCTV_310i:
snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
if (pinnacle_remote == 0) {
ir->get_key = get_key_pinnacle_color;
@@ -349,6 +392,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
ir->get_key = get_key_purpletv;
ir->ir_codes = ir_codes_purpletv;
break;
+ case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+ snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
+ ir->get_key = get_key_hvr1110;
+ ir->ir_codes = ir_codes_hauppauge_new;
+ break;
default:
dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
break;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 7cf96b43025..e88ad7b40c4 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -227,6 +227,11 @@ struct saa7134_format {
#define SAA7134_BOARD_PROTEUS_2309 98
#define SAA7134_BOARD_AVERMEDIA_A16AR 99
#define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100
+#define SAA7134_BOARD_PINNACLE_PCTV_310i 101
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102
+#define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103
+#define SAA7134_BOARD_HAUPPAUGE_HVR1110 104
+#define SAA7134_BOARD_CINERGY_HT_PCMCIA 105
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -446,6 +451,9 @@ struct saa7134_dev {
struct v4l2_prio_state prio;
#endif
+ /* insmod option/autodetected */
+ int autodetected;
+
/* various device info */
unsigned int resources;
struct video_device *video_dev;
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 6d1ef1e2e8e..a1ec3aca3f9 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
if (stv680->sbuf[i].data == NULL) {
PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
- return -1;
+ goto nomem_err;
}
}
@@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
if (stv680->scratch[i].data == NULL) {
PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
- return -1;
+ goto nomem_err;
}
stv680->scratch[i].state = BUFFER_UNUSED;
}
@@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
for (i = 0; i < STV680_NUMSBUF; i++) {
urb = usb_alloc_urb (0, GFP_KERNEL);
if (!urb)
- return -ENOMEM;
+ goto nomem_err;
/* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
usb_fill_bulk_urb (urb, stv680->udev,
@@ -721,6 +721,21 @@ static int stv680_start_stream (struct usb_stv *stv680)
stv680->framecount = 0;
return 0;
+
+ nomem_err:
+ for (i = 0; i < STV680_NUMSCRATCH; i++) {
+ kfree(stv680->scratch[i].data);
+ stv680->scratch[i].data = NULL;
+ }
+ for (i = 0; i < STV680_NUMSBUF; i++) {
+ usb_kill_urb(stv680->urb[i]);
+ usb_free_urb(stv680->urb[i]);
+ stv680->urb[i] = NULL;
+ kfree(stv680->sbuf[i].data);
+ stv680->sbuf[i].data = NULL;
+ }
+ return -ENOMEM;
+
}
static int stv680_stop_stream (struct usb_stv *stv680)
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 87ffb0e84a7..fde576f1101 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -482,6 +482,12 @@ static int tda9887_set_config(struct tuner *t, char *buf)
buf[1] &= ~cQSS;
if (t->tda9887_config & TDA9887_GATING_18)
buf[3] &= ~cGating_36;
+
+ if (t->tda9887_config & TDA9887_GAIN_NORMAL) {
+ radio_stereo.e &= ~cTunerGainLow;
+ radio_mono.e &= ~cTunerGainLow;
+ }
+
return 0;
}
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 40590bae5ff..ee4a493032d 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -267,6 +267,10 @@ static int tuner_fixup_std(struct tuner *t)
{
if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
switch (pal[0]) {
+ case '6':
+ tuner_dbg ("insmod fixup: PAL => PAL-60\n");
+ t->std = V4L2_STD_PAL_60;
+ break;
case 'b':
case 'B':
case 'g':
@@ -443,6 +447,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
printk("%02x ",buffer[i]);
printk("\n");
}
+ /* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */
+ if (adap->id == I2C_HW_SAA7146 && addr < 0x4a)
+ return -ENODEV;
+
/* autodetection code based on the i2c addr */
if (!no_autodetect) {
switch (addr) {
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 63db4e97ae6..1b9b0742f75 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -108,6 +108,7 @@ static int tuner_stereo(struct i2c_client *c)
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FM1256_IH3:
+ case TUNER_LG_NTSC_TAPE:
stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
break;
default:
@@ -421,6 +422,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
case TUNER_PHILIPS_FMD1216ME_MK3:
+ case TUNER_LG_NTSC_TAPE:
buffer[3] = 0x19;
break;
case TUNER_TNF_5335MF:
@@ -465,6 +467,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
config |= TDA9887_INTERCARRIER;
/* if (params->port1_set_for_fm_mono)
config &= ~TDA9887_PORT1_ACTIVE;*/
+ if (params->fm_gain_normal)
+ config |= TDA9887_GAIN_NORMAL;
i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
}
if (4 != (rc = i2c_master_send(c,buffer,4)))
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index 781682373b6..74c3e6f96f1 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -651,6 +651,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
.has_tda9887 = 1,
.port1_invert_for_secam_lc = 1,
.default_pll_gating_18 = 1,
+ .fm_gain_normal=1,
},
};
@@ -672,16 +673,6 @@ static struct tuner_params tuner_panasonic_vp27_params[] = {
},
};
-/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */
-
-static struct tuner_params tuner_lg_ntsc_tape_params[] = {
- {
- .type = TUNER_PARAM_TYPE_NTSC,
- .ranges = tuner_fm1236_mk3_ntsc_ranges,
- .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
- },
-};
-
/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
@@ -1331,8 +1322,8 @@ struct tunertype tuners[] = {
},
[TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
.name = "LG NTSC (TAPE series)",
- .params = tuner_lg_ntsc_tape_params,
- .count = ARRAY_SIZE(tuner_lg_ntsc_tape_params),
+ .params = tuner_fm1236_mk3_params,
+ .count = ARRAY_SIZE(tuner_fm1236_mk3_params),
},
[TUNER_TNF_8831BGFF] = { /* Philips PAL */
.name = "Tenna TNF 8831 BGFF)",
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 6b9ef731b83..4e7c1fa668d 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -184,7 +184,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Thompson DTT757"},
/* 80-89 */
{ TUNER_ABSENT, "Philips FQ1216LME MK3"},
- { TUNER_ABSENT, "LG TAPC G701D"},
+ { TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"},
{ TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
@@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
tvee->has_radio = eeprom_data[i+len-1];
/* old style tag, don't know how to detect
IR presence, mark as unknown. */
- tvee->has_ir = 2;
+ tvee->has_ir = -1;
tvee->model =
eeprom_data[i+8] +
(eeprom_data[i+9] << 8);
@@ -653,13 +653,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
STRM(decoderIC, tvee->decoder_processor),
tvee->decoder_processor);
}
- if (tvee->has_ir == 2)
+ if (tvee->has_ir == -1)
tveeprom_info("has %sradio\n",
tvee->has_radio ? "" : "no ");
else
- tveeprom_info("has %sradio, has %sIR remote\n",
+ tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
tvee->has_radio ? "" : "no ",
- tvee->has_ir ? "" : "no ");
+ (tvee->has_ir & 1) ? "" : "no ",
+ (tvee->has_ir & 2) ? "" : "no ");
}
EXPORT_SYMBOL(tveeprom_hauppauge_analog);
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index bbf2beeeb44..ec0ff2247f0 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table);
static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
{
struct input_dev *input_dev;
+ int error;
usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
@@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
input_dev->private = cam;
- input_register_device(cam->input);
+ error = input_register_device(cam->input);
+ if (error) {
+ warn("Failed to register camera's input device, err: %d\n",
+ error);
+ input_free_device(cam->input);
+ cam->input = NULL;
+ }
}
static void qcm_unregister_input(struct qcm *cam)
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h
index baab9c081b5..17ace394d98 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.h
+++ b/drivers/media/video/usbvideo/quickcam_messenger.h
@@ -35,27 +35,13 @@ struct rgb {
};
struct bayL0 {
-#ifdef __BIG_ENDIAN
- u8 r;
- u8 g;
-#elif __LITTLE_ENDIAN
u8 g;
u8 r;
-#else
-#error not byte order defined
-#endif
};
struct bayL1 {
-#ifdef __BIG_ENDIAN
- u8 g;
- u8 b;
-#elif __LITTLE_ENDIAN
u8 b;
u8 g;
-#else
-#error not byte order defined
-#endif
};
struct cam_size {
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index d8b88024bc2..b560c9d7c51 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -690,7 +690,7 @@ int usbvideo_register(
}
base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);
- cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL);
+ cams = kzalloc(base_size, GFP_KERNEL);
if (cams == NULL) {
err("Failed to allocate %d. bytes for usbvideo struct", base_size);
return -ENOMEM;
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig
new file mode 100644
index 00000000000..fc24ef05b3f
--- /dev/null
+++ b/drivers/media/video/usbvision/Kconfig
@@ -0,0 +1,12 @@
+config VIDEO_USBVISION
+ tristate "USB video devices based on Nogatech NT1003/1004/1005"
+ depends on I2C && VIDEO_V4L2
+ select VIDEO_TUNER
+ select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+ ---help---
+ There are more than 50 different USB video devices based on
+ NT1003/1004/1005 USB Bridges. This driver enables using those
+ devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called usbvision.
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile
new file mode 100644
index 00000000000..9ac92a80c64
--- /dev/null
+++ b/drivers/media/video/usbvision/Makefile
@@ -0,0 +1,5 @@
+usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o
+
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
new file mode 100644
index 00000000000..a40e5838515
--- /dev/null
+++ b/drivers/media/video/usbvision/usbvision-cards.c
@@ -0,0 +1,156 @@
+/*
+ * USBVISION.H
+ * usbvision header file
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/list.h>
+#include <linux/i2c.h>
+#include <media/v4l2-dev.h>
+#include <media/tuner.h>
+#include "usbvision.h"
+
+/* Supported Devices: A table for usbvision.c*/
+struct usbvision_device_data_st usbvision_device_data[] = {
+ {0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"},
+ {0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"},
+ {0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USBView II"},
+ {0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"},
+ {0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"},
+ {0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"},
+ {0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"},
+ {0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Osprey 50"},
+ {0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge USB-Live Model 600"},
+ {0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"},
+ {0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"},
+ {0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"},
+ {0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"},
+ {0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"},
+ {0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"},
+ {0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"},
+ {0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"},
+ {0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "},
+ {0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"},
+ {0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"},
+ {0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"},
+ {0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"},
+ {0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"},
+ {0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"},
+ {0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"},
+ {0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL)"},
+ {0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) MODEL 566"},
+ {0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) 4D23"},
+ {0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"},
+ {0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"},
+ {0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B281"},
+ {0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B283"},
+ {0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40205 Rev B298"},
+ {0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"},
+ {0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 568"},
+ {0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 573"},
+ {0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"},
+ {0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB device Model 40219 Rev E189"},
+ {0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"},
+ {0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"},
+ {0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"},
+ {0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"},
+ {0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"},
+ {0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"},
+ {0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"},
+ {0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"},
+ {0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"},
+ {0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"},
+ {0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"},
+ {0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"},
+ {0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"},
+ {0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"},
+ {0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"},
+ {0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"},
+ {0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"},
+ {0x2400, 0x4200, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"},
+ {} /* Terminating entry */
+};
+
+/* Supported Devices */
+
+struct usb_device_id usbvision_table [] = {
+ { USB_DEVICE(0xFFF0, 0xFFF0) }, /* Custom Dummy USBVision Device */
+ { USB_DEVICE(0x0A6F, 0x0400) }, /* Xanboo */
+ { USB_DEVICE(0x050d, 0x0208) }, /* Belkin USBView II */
+ { USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */
+ { USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 */
+ { USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */
+ { USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */
+ { USB_DEVICE(0x0573, 0x2d00) }, /* Osprey 50 */
+ { USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge USB-Live Model 600 */
+ { USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */
+ { USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */
+ { USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */
+ { USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */
+ { USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */
+ { USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTv-USB USA */
+ { USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTv-USB */
+ { USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTv-USB UK */
+ { USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTv-USB France */
+ { USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTv-USB with FM USA radio */
+ { USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTv-USB (PAL) with FM radio */
+ { USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTv-USB UK with FM Radio */
+ { USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppague WinTv USB Model 602 40201 Rev B285 */
+ { USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppague WinTv USB Model 602 40201 Rev B282 */
+ { USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/
+ { USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */
+ { USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTv-USB II (PAL) with FM radio*/
+ { USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTv-USB II (PAL) Model 566 */
+ { USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTv-USB France 4D23*/
+ { USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTv-USB Model 40209 rev B234 */
+ { USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTv-USB Model 40209 Rev B243 */
+ { USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTv-USB Model 40204 Rev B281 */
+ { USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTv-USB Model 40204 Rev B283 */
+ { USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTv-USB Model 40205 Rev B298 */
+ { USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */
+ { USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */
+ { USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTv-USB III (PAL) FM Model 573 */
+ { USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */
+ { USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTv-USB Model 40219 Rev E189 */
+ { USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */
+ { USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */
+ { USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */
+ { USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */
+ { USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */
+ { USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */
+ { USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */
+ { USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */
+ { USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */
+ { USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */
+ { USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */
+ { USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */
+ { USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */
+ { USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */
+ { USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */
+ { USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */
+ { USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */
+ { USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */
+
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usbvision_table);
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
new file mode 100644
index 00000000000..a807d971e27
--- /dev/null
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -0,0 +1,2535 @@
+/*
+ * usbvision-core.c - driver for NT100x USB video capture devices
+ *
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ * Dwaine Garden <dwainegarden@rogers.com>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/utsname.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+#include <linux/videodev.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include <media/saa7115.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/audiochip.h>
+
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#include "usbvision.h"
+
+static unsigned int core_debug = 0;
+module_param(core_debug,int,0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+static unsigned int force_testpattern = 0;
+module_param(force_testpattern,int,0644);
+MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
+
+static int adjustCompression = 1; // Set the compression to be adaptive
+module_param(adjustCompression, int, 0444);
+MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)");
+
+static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently.
+module_param(SwitchSVideoInput, int, 0444);
+MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)");
+
+#define ENABLE_HEXDUMP 0 /* Enable if you need it */
+
+
+#ifdef USBVISION_DEBUG
+ #define PDEBUG(level, fmt, args...) \
+ if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+ #define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+#define DBG_HEADER 1<<0
+#define DBG_IRQ 1<<1
+#define DBG_ISOC 1<<2
+#define DBG_PARSE 1<<3
+#define DBG_SCRATCH 1<<4
+#define DBG_FUNC 1<<5
+
+static const int max_imgwidth = MAX_FRAME_WIDTH;
+static const int max_imgheight = MAX_FRAME_HEIGHT;
+static const int min_imgwidth = MIN_FRAME_WIDTH;
+static const int min_imgheight = MIN_FRAME_HEIGHT;
+
+/* The value of 'scratch_buf_size' affects quality of the picture
+ * in many ways. Shorter buffers may cause loss of data when client
+ * is too slow. Larger buffers are memory-consuming and take longer
+ * to work with. This setting can be adjusted, but the default value
+ * should be OK for most desktop users.
+ */
+#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer
+static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE;
+
+// Function prototypes
+static int usbvision_request_intra (struct usb_usbvision *usbvision);
+static int usbvision_unrequest_intra (struct usb_usbvision *usbvision);
+static int usbvision_adjust_compression (struct usb_usbvision *usbvision);
+static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision);
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+/*
+ * Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+
+static void *usbvision_rvmalloc(unsigned long size)
+{
+ void *mem;
+ unsigned long adr;
+
+ size = PAGE_ALIGN(size);
+ mem = vmalloc_32(size);
+ if (!mem)
+ return NULL;
+
+ 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;
+}
+
+void usbvision_rvfree(void *mem, unsigned long size)
+{
+ unsigned long adr;
+
+ if (!mem)
+ return;
+
+ size = PAGE_ALIGN(size);
+
+ adr = (unsigned long) mem;
+ while ((long) size > 0) {
+ ClearPageReserved(vmalloc_to_page((void *)adr));
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ vfree(mem);
+}
+
+
+
+#if ENABLE_HEXDUMP
+static void usbvision_hexdump(const unsigned char *data, int len)
+{
+ char tmp[80];
+ int i, k;
+
+ for (i = k = 0; len > 0; i++, len--) {
+ if (i > 0 && (i % 16 == 0)) {
+ printk("%s\n", tmp);
+ k = 0;
+ }
+ k += sprintf(&tmp[k], "%02x ", data[i]);
+ }
+ if (k > 0)
+ printk("%s\n", tmp);
+}
+#endif
+
+/********************************
+ * scratch ring buffer handling
+ ********************************/
+static int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */
+{
+ int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr;
+ if (len < 0) {
+ len += scratch_buf_size;
+ }
+ PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len);
+
+ return len;
+}
+
+
+/* This returns the free space left in the buffer */
+static int scratch_free(struct usb_usbvision *usbvision)
+{
+ int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr;
+ if (free <= 0) {
+ free += scratch_buf_size;
+ }
+ if (free) {
+ free -= 1; /* at least one byte in the buffer must */
+ /* left blank, otherwise there is no chance to differ between full and empty */
+ }
+ PDEBUG(DBG_SCRATCH, "return %d\n", free);
+
+ return free;
+}
+
+
+/* This puts data into the buffer */
+static int scratch_put(struct usb_usbvision *usbvision, unsigned char *data,
+ int len)
+{
+ int len_part;
+
+ if (usbvision->scratch_write_ptr + len < scratch_buf_size) {
+ memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len);
+ usbvision->scratch_write_ptr += len;
+ }
+ else {
+ len_part = scratch_buf_size - usbvision->scratch_write_ptr;
+ memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part);
+ if (len == len_part) {
+ usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */
+ }
+ else {
+ memcpy(usbvision->scratch, data + len_part, len - len_part);
+ usbvision->scratch_write_ptr = len - len_part;
+ }
+ }
+
+ PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr);
+
+ return len;
+}
+
+/* This marks the write_ptr as position of new frame header */
+static void scratch_mark_header(struct usb_usbvision *usbvision)
+{
+ PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr);
+
+ usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] =
+ usbvision->scratch_write_ptr;
+ usbvision->scratch_headermarker_write_ptr += 1;
+ usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER;
+}
+
+/* This gets data from the buffer at the given "ptr" position */
+static int scratch_get_extra(struct usb_usbvision *usbvision,
+ unsigned char *data, int *ptr, int len)
+{
+ int len_part;
+ if (*ptr + len < scratch_buf_size) {
+ memcpy(data, usbvision->scratch + *ptr, len);
+ *ptr += len;
+ }
+ else {
+ len_part = scratch_buf_size - *ptr;
+ memcpy(data, usbvision->scratch + *ptr, len_part);
+ if (len == len_part) {
+ *ptr = 0; /* just set the y_ptr to zero */
+ }
+ else {
+ memcpy(data + len_part, usbvision->scratch, len - len_part);
+ *ptr = len - len_part;
+ }
+ }
+
+ PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr);
+
+ return len;
+}
+
+
+/* This sets the scratch extra read pointer */
+static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr,
+ int len)
+{
+ *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size;
+
+ PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
+}
+
+
+/*This increments the scratch extra read pointer */
+static void scratch_inc_extra_ptr(int *ptr, int len)
+{
+ *ptr = (*ptr + len) % scratch_buf_size;
+
+ PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
+}
+
+
+/* This gets data from the buffer */
+static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data,
+ int len)
+{
+ int len_part;
+ if (usbvision->scratch_read_ptr + len < scratch_buf_size) {
+ memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len);
+ usbvision->scratch_read_ptr += len;
+ }
+ else {
+ len_part = scratch_buf_size - usbvision->scratch_read_ptr;
+ memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part);
+ if (len == len_part) {
+ usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */
+ }
+ else {
+ memcpy(data + len_part, usbvision->scratch, len - len_part);
+ usbvision->scratch_read_ptr = len - len_part;
+ }
+ }
+
+ PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr);
+
+ return len;
+}
+
+
+/* This sets read pointer to next header and returns it */
+static int scratch_get_header(struct usb_usbvision *usbvision,
+ struct usbvision_frame_header *header)
+{
+ int errCode = 0;
+
+ PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr);
+
+ while (usbvision->scratch_headermarker_write_ptr -
+ usbvision->scratch_headermarker_read_ptr != 0) {
+ usbvision->scratch_read_ptr =
+ usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr];
+ usbvision->scratch_headermarker_read_ptr += 1;
+ usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER;
+ scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH);
+ if ((header->magic_1 == USBVISION_MAGIC_1)
+ && (header->magic_2 == USBVISION_MAGIC_2)
+ && (header->headerLength == USBVISION_HEADER_LENGTH)) {
+ errCode = USBVISION_HEADER_LENGTH;
+ header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8);
+ header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8);
+ break;
+ }
+ }
+
+ return errCode;
+}
+
+
+/*This removes len bytes of old data from the buffer */
+static void scratch_rm_old(struct usb_usbvision *usbvision, int len)
+{
+
+ usbvision->scratch_read_ptr += len;
+ usbvision->scratch_read_ptr %= scratch_buf_size;
+ PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr);
+}
+
+
+/*This resets the buffer - kills all data in it too */
+static void scratch_reset(struct usb_usbvision *usbvision)
+{
+ PDEBUG(DBG_SCRATCH, "\n");
+
+ usbvision->scratch_read_ptr = 0;
+ usbvision->scratch_write_ptr = 0;
+ usbvision->scratch_headermarker_read_ptr = 0;
+ usbvision->scratch_headermarker_write_ptr = 0;
+ usbvision->isocstate = IsocState_NoFrame;
+}
+
+int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
+{
+ usbvision->scratch = vmalloc_32(scratch_buf_size);
+ scratch_reset(usbvision);
+ if(usbvision->scratch == NULL) {
+ err("%s: unable to allocate %d bytes for scratch",
+ __FUNCTION__, scratch_buf_size);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void usbvision_scratch_free(struct usb_usbvision *usbvision)
+{
+ if (usbvision->scratch != NULL) {
+ vfree(usbvision->scratch);
+ usbvision->scratch = NULL;
+ }
+}
+
+/*
+ * usbvision_testpattern()
+ *
+ * Procedure forms a test pattern (yellow grid on blue background).
+ *
+ * Parameters:
+ * fullframe: if TRUE then entire frame is filled, otherwise the procedure
+ * continues from the current scanline.
+ * pmode 0: fill the frame with solid blue color (like on VCR or TV)
+ * 1: Draw a colored grid
+ *
+ */
+static void usbvision_testpattern(struct usb_usbvision *usbvision,
+ int fullframe, int pmode)
+{
+ static const char proc[] = "usbvision_testpattern";
+ struct usbvision_frame *frame;
+ unsigned char *f;
+ int num_cell = 0;
+ int scan_length = 0;
+ static int num_pass = 0;
+
+ if (usbvision == NULL) {
+ printk(KERN_ERR "%s: usbvision == NULL\n", proc);
+ return;
+ }
+ if (usbvision->curFrame == NULL) {
+ printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc);
+ return;
+ }
+
+ /* Grab the current frame */
+ frame = usbvision->curFrame;
+
+ /* Optionally start at the beginning */
+ if (fullframe) {
+ frame->curline = 0;
+ frame->scanlength = 0;
+ }
+
+ /* Form every scan line */
+ for (; frame->curline < frame->frmheight; frame->curline++) {
+ int i;
+
+ f = frame->data + (usbvision->curwidth * 3 * frame->curline);
+ for (i = 0; i < usbvision->curwidth; i++) {
+ unsigned char cb = 0x80;
+ unsigned char cg = 0;
+ unsigned char cr = 0;
+
+ if (pmode == 1) {
+ if (frame->curline % 32 == 0)
+ cb = 0, cg = cr = 0xFF;
+ else if (i % 32 == 0) {
+ if (frame->curline % 32 == 1)
+ num_cell++;
+ cb = 0, cg = cr = 0xFF;
+ } else {
+ cb =
+ ((num_cell * 7) +
+ num_pass) & 0xFF;
+ cg =
+ ((num_cell * 5) +
+ num_pass * 2) & 0xFF;
+ cr =
+ ((num_cell * 3) +
+ num_pass * 3) & 0xFF;
+ }
+ } else {
+ /* Just the blue screen */
+ }
+
+ *f++ = cb;
+ *f++ = cg;
+ *f++ = cr;
+ scan_length += 3;
+ }
+ }
+
+ frame->grabstate = FrameState_Done;
+ frame->scanlength += scan_length;
+ ++num_pass;
+
+}
+
+/*
+ * usbvision_decompress_alloc()
+ *
+ * allocates intermediate buffer for decompression
+ */
+int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
+{
+ int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
+ usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
+ if (usbvision->IntraFrameBuffer == NULL) {
+ err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*
+ * usbvision_decompress_free()
+ *
+ * frees intermediate buffer for decompression
+ */
+void usbvision_decompress_free(struct usb_usbvision *usbvision)
+{
+ if (usbvision->IntraFrameBuffer != NULL) {
+ vfree(usbvision->IntraFrameBuffer);
+ usbvision->IntraFrameBuffer = NULL;
+ }
+}
+
+/************************************************************
+ * Here comes the data parsing stuff that is run as interrupt
+ ************************************************************/
+/*
+ * usbvision_find_header()
+ *
+ * Locate one of supported header markers in the scratch buffer.
+ */
+static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision)
+{
+ struct usbvision_frame *frame;
+ int foundHeader = 0;
+
+ frame = usbvision->curFrame;
+
+ while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) {
+ // found header in scratch
+ PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u",
+ frame->isocHeader.magic_2,
+ frame->isocHeader.magic_1,
+ frame->isocHeader.headerLength,
+ frame->isocHeader.frameNum,
+ frame->isocHeader.framePhase,
+ frame->isocHeader.frameLatency,
+ frame->isocHeader.dataFormat,
+ frame->isocHeader.formatParam,
+ frame->isocHeader.frameWidth,
+ frame->isocHeader.frameHeight);
+
+ if (usbvision->requestIntra) {
+ if (frame->isocHeader.formatParam & 0x80) {
+ foundHeader = 1;
+ usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time
+ usbvision_unrequest_intra(usbvision);
+ break;
+ }
+ }
+ else {
+ foundHeader = 1;
+ break;
+ }
+ }
+
+ if (foundHeader) {
+ frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width;
+ frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height;
+ frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3;
+ }
+ else { // no header found
+ PDEBUG(DBG_HEADER, "skipping scratch data, no header");
+ scratch_reset(usbvision);
+ return ParseState_EndParse;
+ }
+
+ // found header
+ if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) {
+ //check isocHeader.frameNum for lost frames
+ if (usbvision->lastIsocFrameNum >= 0) {
+ if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) {
+ // unexpected frame drop: need to request new intra frame
+ PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum);
+ usbvision_request_intra(usbvision);
+ return ParseState_NextFrame;
+ }
+ }
+ usbvision->lastIsocFrameNum = frame->isocHeader.frameNum;
+ }
+ usbvision->header_count++;
+ frame->scanstate = ScanState_Lines;
+ frame->curline = 0;
+
+ if (force_testpattern) {
+ usbvision_testpattern(usbvision, 1, 1);
+ return ParseState_NextFrame;
+ }
+ return ParseState_Continue;
+}
+
+static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision,
+ long *pcopylen)
+{
+ volatile struct usbvision_frame *frame;
+ unsigned char *f;
+ int len;
+ int i;
+ unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components
+ unsigned char rv, gv, bv; // RGB components
+ int clipmask_index, bytes_per_pixel;
+ int stretch_bytes, clipmask_add;
+
+ frame = usbvision->curFrame;
+ f = frame->data + (frame->v4l2_linesize * frame->curline);
+
+ /* Make sure there's enough data for the entire line */
+ len = (frame->isocHeader.frameWidth * 2)+5;
+ if (scratch_len(usbvision) < len) {
+ PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len);
+ return ParseState_Out;
+ }
+
+ if ((frame->curline + 1) >= frame->frmheight) {
+ return ParseState_NextFrame;
+ }
+
+ bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+ stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
+ clipmask_index = frame->curline * MAX_FRAME_WIDTH;
+ clipmask_add = usbvision->stretch_width;
+
+ for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) {
+
+ scratch_get(usbvision, &yuyv[0], 4);
+
+ if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f++ = yuyv[0]; // Y
+ *f++ = yuyv[3]; // U
+ }
+ else {
+
+ YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv);
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_RGB565:
+ *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3));
+ *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv);
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f++ = bv;
+ *f++ = gv;
+ *f++ = rv;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f++ = bv;
+ *f++ = gv;
+ *f++ = rv;
+ f++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2));
+ *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1));
+ break;
+ }
+ }
+ clipmask_index += clipmask_add;
+ f += stretch_bytes;
+
+ if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f++ = yuyv[2]; // Y
+ *f++ = yuyv[1]; // V
+ }
+ else {
+
+ YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv);
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_RGB565:
+ *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3));
+ *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv);
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f++ = bv;
+ *f++ = gv;
+ *f++ = rv;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f++ = bv;
+ *f++ = gv;
+ *f++ = rv;
+ f++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2));
+ *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1));
+ break;
+ }
+ }
+ clipmask_index += clipmask_add;
+ f += stretch_bytes;
+ }
+
+ frame->curline += usbvision->stretch_height;
+ *pcopylen += frame->v4l2_linesize * usbvision->stretch_height;
+
+ if (frame->curline >= frame->frmheight) {
+ return ParseState_NextFrame;
+ }
+ else {
+ return ParseState_Continue;
+ }
+}
+
+/* The decompression routine */
+static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed,
+ unsigned char *Decompressed, int *StartPos,
+ int *BlockTypeStartPos, int Len)
+{
+ int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen;
+ unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator;
+
+ Integrator = 0;
+ Pos = *StartPos;
+ BlockTypePos = *BlockTypeStartPos;
+ MaxPos = 396; //Pos + Len;
+ ExtraPos = Pos;
+ BlockLen = 0;
+ BlockByte = 0;
+ BlockCode = 0;
+ BlockType = 0;
+ BlockTypeByte = 0;
+ BlockTypeLen = 0;
+ RestPixel = Len;
+
+ for (Idx = 0; Idx < Len; Idx++) {
+
+ if (BlockLen == 0) {
+ if (BlockTypeLen==0) {
+ BlockTypeByte = Compressed[BlockTypePos];
+ BlockTypePos++;
+ BlockTypeLen = 4;
+ }
+ BlockType = (BlockTypeByte & 0xC0) >> 6;
+
+ //statistic:
+ usbvision->ComprBlockTypes[BlockType]++;
+
+ Pos = ExtraPos;
+ if (BlockType == 0) {
+ if(RestPixel >= 24) {
+ Idx += 23;
+ RestPixel -= 24;
+ Integrator = Decompressed[Idx];
+ } else {
+ Idx += RestPixel - 1;
+ RestPixel = 0;
+ }
+ } else {
+ BlockCode = Compressed[Pos];
+ Pos++;
+ if (RestPixel >= 24) {
+ BlockLen = 24;
+ } else {
+ BlockLen = RestPixel;
+ }
+ RestPixel -= BlockLen;
+ ExtraPos = Pos + (BlockLen / 4);
+ }
+ BlockTypeByte <<= 2;
+ BlockTypeLen -= 1;
+ }
+ if (BlockLen > 0) {
+ if ((BlockLen%4) == 0) {
+ BlockByte = Compressed[Pos];
+ Pos++;
+ }
+ if (BlockType == 1) { //inter Block
+ Integrator = Decompressed[Idx];
+ }
+ switch (BlockByte & 0xC0) {
+ case 0x03<<6:
+ Integrator += Compressed[ExtraPos];
+ ExtraPos++;
+ break;
+ case 0x02<<6:
+ Integrator += BlockCode;
+ break;
+ case 0x00:
+ Integrator -= BlockCode;
+ break;
+ }
+ Decompressed[Idx] = Integrator;
+ BlockByte <<= 2;
+ BlockLen -= 1;
+ }
+ }
+ *StartPos = ExtraPos;
+ *BlockTypeStartPos = BlockTypePos;
+ return Idx;
+}
+
+
+/*
+ * usbvision_parse_compress()
+ *
+ * Parse compressed frame from the scratch buffer, put
+ * decoded RGB value into the current frame buffer and add the written
+ * number of bytes (RGB) to the *pcopylen.
+ *
+ */
+static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision,
+ long *pcopylen)
+{
+#define USBVISION_STRIP_MAGIC 0x5A
+#define USBVISION_STRIP_LEN_MAX 400
+#define USBVISION_STRIP_HEADER_LEN 3
+
+ struct usbvision_frame *frame;
+ unsigned char *f,*u = NULL ,*v = NULL;
+ unsigned char StripData[USBVISION_STRIP_LEN_MAX];
+ unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN];
+ int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos;
+ int clipmask_index, bytes_per_pixel, rc;
+ int imageSize;
+ unsigned char rv, gv, bv;
+ static unsigned char *Y, *U, *V;
+
+ frame = usbvision->curFrame;
+ imageSize = frame->frmwidth * frame->frmheight;
+ if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
+ (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format
+ //... v4l2_linesize not used here.
+ f = frame->data + (frame->width * frame->curline);
+ } else
+ f = frame->data + (frame->v4l2_linesize * frame->curline);
+
+ if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers
+ // get base of u and b planes add halfoffset
+
+ u = frame->data
+ + imageSize
+ + (frame->frmwidth >>1) * frame->curline ;
+ v = u + (imageSize >>1 );
+
+ } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){
+
+ v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ;
+ u = v + (imageSize >>2) ;
+ }
+
+ if (frame->curline == 0) {
+ usbvision_adjust_compression(usbvision);
+ }
+
+ if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) {
+ return ParseState_Out;
+ }
+
+ //get strip header without changing the scratch_read_ptr
+ scratch_set_extra_ptr(usbvision, &StripPtr, 0);
+ scratch_get_extra(usbvision, &StripHeader[0], &StripPtr,
+ USBVISION_STRIP_HEADER_LEN);
+
+ if (StripHeader[0] != USBVISION_STRIP_MAGIC) {
+ // wrong strip magic
+ usbvision->stripMagicErrors++;
+ return ParseState_NextFrame;
+ }
+
+ if (frame->curline != (int)StripHeader[2]) {
+ //line number missmatch error
+ usbvision->stripLineNumberErrors++;
+ }
+
+ StripLen = 2 * (unsigned int)StripHeader[1];
+ if (StripLen > USBVISION_STRIP_LEN_MAX) {
+ // strip overrun
+ // I think this never happens
+ usbvision_request_intra(usbvision);
+ }
+
+ if (scratch_len(usbvision) < StripLen) {
+ //there is not enough data for the strip
+ return ParseState_Out;
+ }
+
+ if (usbvision->IntraFrameBuffer) {
+ Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline;
+ U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2);
+ V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2);
+ }
+ else {
+ return ParseState_NextFrame;
+ }
+
+ bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+ clipmask_index = frame->curline * MAX_FRAME_WIDTH;
+
+ scratch_get(usbvision, StripData, StripLen);
+
+ IdxEnd = frame->frmwidth;
+ BlockTypePos = USBVISION_STRIP_HEADER_LEN;
+ StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2;
+ BlockPos = StartBlockPos;
+
+ usbvision->BlockPos = BlockPos;
+
+ if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) {
+ //return ParseState_Continue;
+ }
+ if (StripLen > usbvision->maxStripLen) {
+ usbvision->maxStripLen = StripLen;
+ }
+
+ if (frame->curline%2) {
+ if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) {
+ //return ParseState_Continue;
+ }
+ }
+ else {
+ if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) {
+ //return ParseState_Continue;
+ }
+ }
+
+ if (BlockPos > usbvision->comprBlockPos) {
+ usbvision->comprBlockPos = BlockPos;
+ }
+ if (BlockPos > StripLen) {
+ usbvision->stripLenErrors++;
+ }
+
+ for (Idx = 0; Idx < IdxEnd; Idx++) {
+ if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f++ = Y[Idx];
+ *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2];
+ }
+ else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) {
+ *f++ = Y[Idx];
+ if ( Idx & 0x01)
+ *u++ = U[Idx>>1] ;
+ else
+ *v++ = V[Idx>>1];
+ }
+ else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
+ *f++ = Y [Idx];
+ if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){
+
+/* only need do this for 1 in 4 pixels */
+/* intraframe buffer is YUV420 format */
+
+ *u++ = U[Idx >>1];
+ *v++ = V[Idx >>1];
+ }
+
+ }
+ else {
+ YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv);
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_GREY:
+ *f++ = Y[Idx];
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 2));
+ *f++ = (0x03 & (gv >> 6)) | (0x7C & (rv >> 1));
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ *f++ = (0x1F & (bv >> 3)) | (0xE0 & (gv << 3));
+ *f++ = (0x07 & (gv >> 5)) | (0xF8 & rv);
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f++ = bv;
+ *f++ = gv;
+ *f++ = rv;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f++ = bv;
+ *f++ = gv;
+ *f++ = rv;
+ f++;
+ break;
+ }
+ }
+ clipmask_index++;
+ }
+ /* Deal with non-integer no. of bytes for YUV420P */
+ if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 )
+ *pcopylen += frame->v4l2_linesize;
+ else
+ *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
+
+ frame->curline += 1;
+
+ if (frame->curline >= frame->frmheight) {
+ return ParseState_NextFrame;
+ }
+ else {
+ return ParseState_Continue;
+ }
+
+}
+
+
+/*
+ * usbvision_parse_lines_420()
+ *
+ * Parse two lines from the scratch buffer, put
+ * decoded RGB value into the current frame buffer and add the written
+ * number of bytes (RGB) to the *pcopylen.
+ *
+ */
+static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision,
+ long *pcopylen)
+{
+ struct usbvision_frame *frame;
+ unsigned char *f_even = NULL, *f_odd = NULL;
+ unsigned int pixel_per_line, block;
+ int pixel, block_split;
+ int y_ptr, u_ptr, v_ptr, y_odd_offset;
+ const int y_block_size = 128;
+ const int uv_block_size = 64;
+ const int sub_block_size = 32;
+ const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4;
+ const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4;
+ unsigned char y[2], u, v; /* YUV components */
+ int y_, u_, v_, vb, uvg, ur;
+ int r_, g_, b_; /* RGB components */
+ unsigned char g;
+ int clipmask_even_index, clipmask_odd_index, bytes_per_pixel;
+ int clipmask_add, stretch_bytes;
+
+ frame = usbvision->curFrame;
+ f_even = frame->data + (frame->v4l2_linesize * frame->curline);
+ f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height;
+
+ /* Make sure there's enough data for the entire line */
+ /* In this mode usbvision transfer 3 bytes for every 2 pixels */
+ /* I need two lines to decode the color */
+ bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+ stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
+ clipmask_even_index = frame->curline * MAX_FRAME_WIDTH;
+ clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH;
+ clipmask_add = usbvision->stretch_width;
+ pixel_per_line = frame->isocHeader.frameWidth;
+
+ if (scratch_len(usbvision) < (int)pixel_per_line * 3) {
+ //printk(KERN_DEBUG "out of data, need %d\n", len);
+ return ParseState_Out;
+ }
+
+ if ((frame->curline + 1) >= frame->frmheight) {
+ return ParseState_NextFrame;
+ }
+
+ block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines?
+
+ y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size)
+ + block_split * uv_block_size;
+
+ scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset);
+ scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size);
+ scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset
+ + (4 - block_split) * sub_block_size);
+
+ for (block = 0; block < (pixel_per_line / sub_block_size);
+ block++) {
+
+
+ for (pixel = 0; pixel < sub_block_size; pixel +=2) {
+ scratch_get(usbvision, &y[0], 2);
+ scratch_get_extra(usbvision, &u, &u_ptr, 1);
+ scratch_get_extra(usbvision, &v, &v_ptr, 1);
+
+ //I don't use the YUV_TO_RGB macro for better performance
+ v_ = v - 128;
+ u_ = u - 128;
+ vb = 132252 * v_;
+ uvg= -53281 * u_ - 25625 * v_;
+ ur = 104595 * u_;
+
+ if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f_even++ = y[0];
+ *f_even++ = v;
+ }
+ else {
+ y_ = 76284 * (y[0] - 16);
+
+ b_ = (y_ + vb) >> 16;
+ g_ = (y_ + uvg)>> 16;
+ r_ = (y_ + ur) >> 16;
+
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_RGB565:
+ g = LIMIT_RGB(g_);
+ *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+ *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_));
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f_even++ = LIMIT_RGB(b_);
+ *f_even++ = LIMIT_RGB(g_);
+ *f_even++ = LIMIT_RGB(r_);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f_even++ = LIMIT_RGB(b_);
+ *f_even++ = LIMIT_RGB(g_);
+ *f_even++ = LIMIT_RGB(r_);
+ f_even++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ g = LIMIT_RGB(g_);
+ *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+ *f_even++ = (0x03 & ( g >> 6)) |
+ (0x7C & (LIMIT_RGB(r_) >> 1));
+ break;
+ }
+ }
+ clipmask_even_index += clipmask_add;
+ f_even += stretch_bytes;
+
+ if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f_even++ = y[1];
+ *f_even++ = u;
+ }
+ else {
+ y_ = 76284 * (y[1] - 16);
+
+ b_ = (y_ + vb) >> 16;
+ g_ = (y_ + uvg)>> 16;
+ r_ = (y_ + ur) >> 16;
+
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_RGB565:
+ g = LIMIT_RGB(g_);
+ *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+ *f_even++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_));
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f_even++ = LIMIT_RGB(b_);
+ *f_even++ = LIMIT_RGB(g_);
+ *f_even++ = LIMIT_RGB(r_);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f_even++ = LIMIT_RGB(b_);
+ *f_even++ = LIMIT_RGB(g_);
+ *f_even++ = LIMIT_RGB(r_);
+ f_even++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ g = LIMIT_RGB(g_);
+ *f_even++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+ *f_even++ = (0x03 & ( g >> 6)) |
+ (0x7C & (LIMIT_RGB(r_) >> 1));
+ break;
+ }
+ }
+ clipmask_even_index += clipmask_add;
+ f_even += stretch_bytes;
+
+ scratch_get_extra(usbvision, &y[0], &y_ptr, 2);
+
+ if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f_odd++ = y[0];
+ *f_odd++ = v;
+ }
+ else {
+ y_ = 76284 * (y[0] - 16);
+
+ b_ = (y_ + vb) >> 16;
+ g_ = (y_ + uvg)>> 16;
+ r_ = (y_ + ur) >> 16;
+
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_RGB565:
+ g = LIMIT_RGB(g_);
+ *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+ *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_));
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f_odd++ = LIMIT_RGB(b_);
+ *f_odd++ = LIMIT_RGB(g_);
+ *f_odd++ = LIMIT_RGB(r_);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f_odd++ = LIMIT_RGB(b_);
+ *f_odd++ = LIMIT_RGB(g_);
+ *f_odd++ = LIMIT_RGB(r_);
+ f_odd++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ g = LIMIT_RGB(g_);
+ *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+ *f_odd++ = (0x03 & ( g >> 6)) |
+ (0x7C & (LIMIT_RGB(r_) >> 1));
+ break;
+ }
+ }
+ clipmask_odd_index += clipmask_add;
+ f_odd += stretch_bytes;
+
+ if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+ *f_odd++ = y[1];
+ *f_odd++ = u;
+ }
+ else {
+ y_ = 76284 * (y[1] - 16);
+
+ b_ = (y_ + vb) >> 16;
+ g_ = (y_ + uvg)>> 16;
+ r_ = (y_ + ur) >> 16;
+
+ switch (frame->v4l2_format.format) {
+ case V4L2_PIX_FMT_RGB565:
+ g = LIMIT_RGB(g_);
+ *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 3));
+ *f_odd++ = (0x07 & ( g >> 5)) | (0xF8 & LIMIT_RGB(r_));
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ *f_odd++ = LIMIT_RGB(b_);
+ *f_odd++ = LIMIT_RGB(g_);
+ *f_odd++ = LIMIT_RGB(r_);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ *f_odd++ = LIMIT_RGB(b_);
+ *f_odd++ = LIMIT_RGB(g_);
+ *f_odd++ = LIMIT_RGB(r_);
+ f_odd++;
+ break;
+ case V4L2_PIX_FMT_RGB555:
+ g = LIMIT_RGB(g_);
+ *f_odd++ = (0x1F & (LIMIT_RGB(b_) >> 3)) | (0xE0 & (g << 2));
+ *f_odd++ = (0x03 & ( g >> 6)) |
+ (0x7C & (LIMIT_RGB(r_) >> 1));
+ break;
+ }
+ }
+ clipmask_odd_index += clipmask_add;
+ f_odd += stretch_bytes;
+ }
+
+ scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size);
+ scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size]
+ * sub_block_size);
+ scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size]
+ * sub_block_size);
+ scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size]
+ * sub_block_size);
+ }
+
+ scratch_rm_old(usbvision, pixel_per_line * 3 / 2
+ + block_split * sub_block_size);
+
+ frame->curline += 2 * usbvision->stretch_height;
+ *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height;
+
+ if (frame->curline >= frame->frmheight)
+ return ParseState_NextFrame;
+ else
+ return ParseState_Continue;
+}
+
+/*
+ * usbvision_parse_data()
+ *
+ * Generic routine to parse the scratch buffer. It employs either
+ * usbvision_find_header() or usbvision_parse_lines() to do most
+ * of work.
+ *
+ */
+static void usbvision_parse_data(struct usb_usbvision *usbvision)
+{
+ struct usbvision_frame *frame;
+ enum ParseState newstate;
+ long copylen = 0;
+ unsigned long lock_flags;
+
+ frame = usbvision->curFrame;
+
+ PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision));
+
+ while (1) {
+
+ newstate = ParseState_Out;
+ if (scratch_len(usbvision)) {
+ if (frame->scanstate == ScanState_Scanning) {
+ newstate = usbvision_find_header(usbvision);
+ }
+ else if (frame->scanstate == ScanState_Lines) {
+ if (usbvision->isocMode == ISOC_MODE_YUV420) {
+ newstate = usbvision_parse_lines_420(usbvision, &copylen);
+ }
+ else if (usbvision->isocMode == ISOC_MODE_YUV422) {
+ newstate = usbvision_parse_lines_422(usbvision, &copylen);
+ }
+ else if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+ newstate = usbvision_parse_compress(usbvision, &copylen);
+ }
+
+ }
+ }
+ if (newstate == ParseState_Continue) {
+ continue;
+ }
+ else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) {
+ break;
+ }
+ else {
+ return; /* ParseState_EndParse */
+ }
+ }
+
+ if (newstate == ParseState_NextFrame) {
+ frame->grabstate = FrameState_Done;
+ do_gettimeofday(&(frame->timestamp));
+ frame->sequence = usbvision->frame_num;
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ list_move_tail(&(frame->frame), &usbvision->outqueue);
+ usbvision->curFrame = NULL;
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+ usbvision->frame_num++;
+
+ /* This will cause the process to request another frame. */
+ if (waitqueue_active(&usbvision->wait_frame)) {
+ PDEBUG(DBG_PARSE, "Wake up !");
+ wake_up_interruptible(&usbvision->wait_frame);
+ }
+ }
+ else
+ frame->grabstate = FrameState_Grabbing;
+
+
+ /* Update the frame's uncompressed length. */
+ frame->scanlength += copylen;
+}
+
+
+/*
+ * Make all of the blocks of data contiguous
+ */
+static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
+ struct urb *urb)
+{
+ unsigned char *packet_data;
+ int i, totlen = 0;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ int packet_len = urb->iso_frame_desc[i].actual_length;
+ int packet_stat = urb->iso_frame_desc[i].status;
+
+ packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+ /* Detect and ignore errored packets */
+ if (packet_stat) { // packet_stat != 0 ?????????????
+ PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat);
+ usbvision->isocErrCount++;
+ continue;
+ }
+
+ /* Detect and ignore empty packets */
+ if (packet_len < 0) {
+ PDEBUG(DBG_ISOC, "error packet [%d]", i);
+ usbvision->isocSkipCount++;
+ continue;
+ }
+ else if (packet_len == 0) { /* Frame end ????? */
+ PDEBUG(DBG_ISOC, "null packet [%d]", i);
+ usbvision->isocstate=IsocState_NoFrame;
+ usbvision->isocSkipCount++;
+ continue;
+ }
+ else if (packet_len > usbvision->isocPacketSize) {
+ PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i);
+ usbvision->isocSkipCount++;
+ continue;
+ }
+
+ PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len);
+
+ if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins
+ usbvision->isocstate=IsocState_InFrame;
+ scratch_mark_header(usbvision);
+ usbvision_measure_bandwidth(usbvision);
+ PDEBUG(DBG_ISOC, "packet with header");
+ }
+
+ /*
+ * If usbvision continues to feed us with data but there is no
+ * consumption (if, for example, V4L client fell asleep) we
+ * may overflow the buffer. We have to move old data over to
+ * free room for new data. This is bad for old data. If we
+ * just drop new data then it's bad for new data... choose
+ * your favorite evil here.
+ */
+ if (scratch_free(usbvision) < packet_len) {
+
+ usbvision->scratch_ovf_count++;
+ PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d",
+ scratch_len(usbvision), packet_len);
+ scratch_rm_old(usbvision, packet_len - scratch_free(usbvision));
+ }
+
+ /* Now we know that there is enough room in scratch buffer */
+ scratch_put(usbvision, packet_data, packet_len);
+ totlen += packet_len;
+ usbvision->isocDataCount += packet_len;
+ usbvision->isocPacketCount++;
+ }
+#if ENABLE_HEXDUMP
+ if (totlen > 0) {
+ static int foo = 0;
+ if (foo < 1) {
+ printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
+ usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
+ ++foo;
+ }
+ }
+#endif
+ return totlen;
+}
+
+static void usbvision_isocIrq(struct urb *urb)
+{
+ int errCode = 0;
+ int len;
+ struct usb_usbvision *usbvision = urb->context;
+ int i;
+ unsigned long startTime = jiffies;
+ struct usbvision_frame **f;
+
+ /* We don't want to do anything if we are about to be removed! */
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return;
+
+ f = &usbvision->curFrame;
+
+ /* Manage streaming interruption */
+ if (usbvision->streaming == Stream_Interrupt) {
+ usbvision->streaming = Stream_Idle;
+ if ((*f)) {
+ (*f)->grabstate = FrameState_Ready;
+ (*f)->scanstate = ScanState_Scanning;
+ }
+ PDEBUG(DBG_IRQ, "stream interrupted");
+ wake_up_interruptible(&usbvision->wait_stream);
+ }
+
+ /* Copy the data received into our scratch buffer */
+ len = usbvision_compress_isochronous(usbvision, urb);
+
+ usbvision->isocUrbCount++;
+ usbvision->urb_length = len;
+
+ if (usbvision->streaming == Stream_On) {
+
+ /* If we collected enough data let's parse! */
+ if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */
+ /*If we don't have a frame we're current working on, complain */
+ if(!list_empty(&(usbvision->inqueue))) {
+ if (!(*f)) {
+ (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame);
+ }
+ usbvision_parse_data(usbvision);
+ }
+ else {
+ PDEBUG(DBG_IRQ, "received data, but no one needs it");
+ scratch_reset(usbvision);
+ }
+ }
+ }
+ else {
+ PDEBUG(DBG_IRQ, "received data, but no one needs it");
+ scratch_reset(usbvision);
+ }
+
+ usbvision->timeInIrq += jiffies - startTime;
+
+ for (i = 0; i < USBVISION_URB_FRAMES; i++) {
+ urb->iso_frame_desc[i].status = 0;
+ urb->iso_frame_desc[i].actual_length = 0;
+ }
+
+ urb->status = 0;
+ urb->dev = usbvision->dev;
+ errCode = usb_submit_urb (urb, GFP_ATOMIC);
+
+ /* Disable this warning. By design of the driver. */
+ // if(errCode) {
+ // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
+ // }
+
+ return;
+}
+
+/*************************************/
+/* Low level usbvision access functions */
+/*************************************/
+
+/*
+ * usbvision_read_reg()
+ *
+ * return < 0 -> Error
+ * >= 0 -> Data
+ */
+
+int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
+{
+ int errCode = 0;
+ unsigned char buffer[1];
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return -1;
+
+ errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+ 0, (__u16) reg, buffer, 1, HZ);
+
+ if (errCode < 0) {
+ err("%s: failed: error %d", __FUNCTION__, errCode);
+ return errCode;
+ }
+ return buffer[0];
+}
+
+/*
+ * usbvision_write_reg()
+ *
+ * return 1 -> Reg written
+ * 0 -> usbvision is not yet ready
+ * -1 -> Something went wrong
+ */
+
+int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+ unsigned char value)
+{
+ int errCode = 0;
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return 0;
+
+ errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
+
+ if (errCode < 0) {
+ err("%s: failed: error %d", __FUNCTION__, errCode);
+ }
+ return errCode;
+}
+
+
+static void usbvision_ctrlUrb_complete(struct urb *urb)
+{
+ struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context;
+
+ PDEBUG(DBG_IRQ, "");
+ usbvision->ctrlUrbBusy = 0;
+ if (waitqueue_active(&usbvision->ctrlUrb_wq)) {
+ wake_up_interruptible(&usbvision->ctrlUrb_wq);
+ }
+}
+
+
+static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address,
+ unsigned char *data, int len)
+{
+ int errCode = 0;
+
+ PDEBUG(DBG_IRQ, "");
+ if (len > 8) {
+ return -EFAULT;
+ }
+// down(&usbvision->ctrlUrbLock);
+ if (usbvision->ctrlUrbBusy) {
+// up(&usbvision->ctrlUrbLock);
+ return -EBUSY;
+ }
+ usbvision->ctrlUrbBusy = 1;
+// up(&usbvision->ctrlUrbLock);
+
+ usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+ usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE;
+ usbvision->ctrlUrbSetup.wValue = 0;
+ usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address);
+ usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len);
+ usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev,
+ usb_sndctrlpipe(usbvision->dev, 1),
+ (unsigned char *)&usbvision->ctrlUrbSetup,
+ (void *)usbvision->ctrlUrbBuffer, len,
+ usbvision_ctrlUrb_complete,
+ (void *)usbvision);
+
+ memcpy(usbvision->ctrlUrbBuffer, data, len);
+
+ errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC);
+ if (errCode < 0) {
+ // error in usb_submit_urb()
+ usbvision->ctrlUrbBusy = 0;
+ }
+ PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode);
+ return errCode;
+}
+
+
+static int usbvision_init_compression(struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+
+ usbvision->lastIsocFrameNum = -1;
+ usbvision->isocDataCount = 0;
+ usbvision->isocPacketCount = 0;
+ usbvision->isocSkipCount = 0;
+ usbvision->comprLevel = 50;
+ usbvision->lastComprLevel = -1;
+ usbvision->isocUrbCount = 0;
+ usbvision->requestIntra = 1;
+ usbvision->isocMeasureBandwidthCount = 0;
+
+ return errCode;
+}
+
+/* this function measures the used bandwidth since last call
+ * return: 0 : no error
+ * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize
+ */
+static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+
+ if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames
+ usbvision->isocMeasureBandwidthCount++;
+ return errCode;
+ }
+ if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) {
+ usbvision->usedBandwidth = usbvision->isocDataCount /
+ (usbvision->isocPacketCount + usbvision->isocSkipCount) *
+ 100 / usbvision->isocPacketSize;
+ }
+ usbvision->isocMeasureBandwidthCount = 0;
+ usbvision->isocDataCount = 0;
+ usbvision->isocPacketCount = 0;
+ usbvision->isocSkipCount = 0;
+ return errCode;
+}
+
+static int usbvision_adjust_compression (struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+ unsigned char buffer[6];
+
+ PDEBUG(DBG_IRQ, "");
+ if ((adjustCompression) && (usbvision->usedBandwidth > 0)) {
+ usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2;
+ RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100);
+ if (usbvision->comprLevel != usbvision->lastComprLevel) {
+ int distorsion;
+ if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) {
+ buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1
+ buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2
+ distorsion = 7 + 248 * usbvision->comprLevel / 100;
+ buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter)
+ buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra)
+ distorsion = 1 + 42 * usbvision->comprLevel / 100;
+ buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter)
+ buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra)
+ }
+ else { //BRIDGE_NT1003
+ buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1
+ buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2
+ distorsion = 2 + 253 * usbvision->comprLevel / 100;
+ buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7
+ buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11
+ distorsion = 0 + 43 * usbvision->comprLevel / 100;
+ buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7
+ buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8
+ }
+ errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);
+ if (errCode == 0){
+ PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0],
+ buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
+ usbvision->lastComprLevel = usbvision->comprLevel;
+ }
+ }
+ }
+ return errCode;
+}
+
+static int usbvision_request_intra (struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+ unsigned char buffer[1];
+
+ PDEBUG(DBG_IRQ, "");
+ usbvision->requestIntra = 1;
+ buffer[0] = 1;
+ usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
+ return errCode;
+}
+
+static int usbvision_unrequest_intra (struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+ unsigned char buffer[1];
+
+ PDEBUG(DBG_IRQ, "");
+ usbvision->requestIntra = 0;
+ buffer[0] = 0;
+ usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
+ return errCode;
+}
+
+/*******************************
+ * usbvision utility functions
+ *******************************/
+
+int usbvision_power_off(struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+
+ PDEBUG(DBG_FUNC, "");
+
+ errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+ if (errCode == 1) {
+ usbvision->power = 0;
+ }
+ PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode);
+ return errCode;
+}
+
+/*
+ * usbvision_set_video_format()
+ *
+ */
+static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format)
+{
+ static const char proc[] = "usbvision_set_video_format";
+ int rc;
+ unsigned char value[2];
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return 0;
+
+ PDEBUG(DBG_FUNC, "isocMode %#02x", format);
+
+ if ((format != ISOC_MODE_YUV422)
+ && (format != ISOC_MODE_YUV420)
+ && (format != ISOC_MODE_COMPRESS)) {
+ printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420",
+ format);
+ format = ISOC_MODE_YUV420;
+ }
+ value[0] = 0x0A; //TODO: See the effect of the filter
+ value[1] = format;
+ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_ENDPOINT, 0,
+ (__u16) USBVISION_FILT_CONT, value, 2, HZ);
+
+ if (rc < 0) {
+ printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "
+ "reconnect or reload driver.\n", proc, rc);
+ }
+ usbvision->isocMode = format;
+ return rc;
+}
+
+/*
+ * usbvision_set_output()
+ *
+ */
+
+int usbvision_set_output(struct usb_usbvision *usbvision, int width,
+ int height)
+{
+ int errCode = 0;
+ int UsbWidth, UsbHeight;
+ unsigned int frameRate=0, frameDrop=0;
+ unsigned char value[4];
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision)) {
+ return 0;
+ }
+
+ if (width > MAX_USB_WIDTH) {
+ UsbWidth = width / 2;
+ usbvision->stretch_width = 2;
+ }
+ else {
+ UsbWidth = width;
+ usbvision->stretch_width = 1;
+ }
+
+ if (height > MAX_USB_HEIGHT) {
+ UsbHeight = height / 2;
+ usbvision->stretch_height = 2;
+ }
+ else {
+ UsbHeight = height;
+ usbvision->stretch_height = 1;
+ }
+
+ RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH);
+ UsbWidth &= ~(MIN_FRAME_WIDTH-1);
+ RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);
+ UsbHeight &= ~(1);
+
+ PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d",
+ UsbWidth, UsbHeight, width, height,
+ usbvision->stretch_width, usbvision->stretch_height);
+
+ /* I'll not rewrite the same values */
+ if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) {
+ value[0] = UsbWidth & 0xff; //LSB
+ value[1] = (UsbWidth >> 8) & 0x03; //MSB
+ value[2] = UsbHeight & 0xff; //LSB
+ value[3] = (UsbHeight >> 8) & 0x03; //MSB
+
+ errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+ 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
+
+ if (errCode < 0) {
+ err("%s failed: error %d", __FUNCTION__, errCode);
+ return errCode;
+ }
+ usbvision->curwidth = usbvision->stretch_width * UsbWidth;
+ usbvision->curheight = usbvision->stretch_height * UsbHeight;
+ }
+
+ if (usbvision->isocMode == ISOC_MODE_YUV422) {
+ frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2);
+ }
+ else if (usbvision->isocMode == ISOC_MODE_YUV420) {
+ frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8);
+ }
+ else {
+ frameRate = FRAMERATE_MAX;
+ }
+
+ if (usbvision->tvnorm->id & V4L2_STD_625_50) {
+ frameDrop = frameRate * 32 / 25 - 1;
+ }
+ else if (usbvision->tvnorm->id & V4L2_STD_525_60) {
+ frameDrop = frameRate * 32 / 30 - 1;
+ }
+
+ RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX);
+
+ PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop);
+
+ frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled
+
+ /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...
+ => frameSkip = 4;
+ => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
+
+ frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ...
+ => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ...
+ => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125;
+ */
+ errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop);
+ return errCode;
+}
+
+
+/*
+ * usbvision_frames_alloc
+ * allocate the maximum frames this driver can manage
+ */
+int usbvision_frames_alloc(struct usb_usbvision *usbvision)
+{
+ int i;
+
+ /* Allocate memory for the frame buffers */
+ usbvision->max_frame_size = MAX_FRAME_SIZE;
+ usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size;
+ usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size);
+
+ if(usbvision->fbuf == NULL) {
+ err("%s: unable to allocate %d bytes for fbuf ",
+ __FUNCTION__, usbvision->fbuf_size);
+ return -ENOMEM;
+ }
+ spin_lock_init(&usbvision->queue_lock);
+ init_waitqueue_head(&usbvision->wait_frame);
+ init_waitqueue_head(&usbvision->wait_stream);
+
+ /* Allocate all buffers */
+ for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+ usbvision->frame[i].index = i;
+ usbvision->frame[i].grabstate = FrameState_Unused;
+ usbvision->frame[i].data = usbvision->fbuf +
+ i * usbvision->max_frame_size;
+ /*
+ * Set default sizes for read operation.
+ */
+ usbvision->stretch_width = 1;
+ usbvision->stretch_height = 1;
+ usbvision->frame[i].width = usbvision->curwidth;
+ usbvision->frame[i].height = usbvision->curheight;
+ usbvision->frame[i].bytes_read = 0;
+ }
+ return 0;
+}
+
+/*
+ * usbvision_frames_free
+ * frees memory allocated for the frames
+ */
+void usbvision_frames_free(struct usb_usbvision *usbvision)
+{
+ /* Have to free all that memory */
+ if (usbvision->fbuf != NULL) {
+ usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
+ usbvision->fbuf = NULL;
+ }
+}
+/*
+ * usbvision_empty_framequeues()
+ * prepare queues for incoming and outgoing frames
+ */
+void usbvision_empty_framequeues(struct usb_usbvision *usbvision)
+{
+ u32 i;
+
+ INIT_LIST_HEAD(&(usbvision->inqueue));
+ INIT_LIST_HEAD(&(usbvision->outqueue));
+
+ for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+ usbvision->frame[i].grabstate = FrameState_Unused;
+ usbvision->frame[i].bytes_read = 0;
+ }
+}
+
+/*
+ * usbvision_stream_interrupt()
+ * stops streaming
+ */
+int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
+{
+ int ret = 0;
+
+ /* stop reading from the device */
+
+ usbvision->streaming = Stream_Interrupt;
+ ret = wait_event_timeout(usbvision->wait_stream,
+ (usbvision->streaming == Stream_Idle),
+ msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
+ return ret;
+}
+
+/*
+ * usbvision_set_compress_params()
+ *
+ */
+
+static int usbvision_set_compress_params(struct usb_usbvision *usbvision)
+{
+ static const char proc[] = "usbvision_set_compresion_params: ";
+ int rc;
+ unsigned char value[6];
+
+ value[0] = 0x0F; // Intra-Compression cycle
+ value[1] = 0x01; // Reg.45 one line per strip
+ value[2] = 0x00; // Reg.46 Force intra mode on all new frames
+ value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force)
+ value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode.
+ value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression
+
+ //catched values for NT1004
+ // value[0] = 0xFF; // Never apply intra mode automatically
+ // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip
+ // value[2] = 0x01; // Force intra mode on all new frames
+ // value[3] = 0x00; // Strip size 400 Bytes; do not force up
+ // value[4] = 0xA2; //
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return 0;
+
+ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_ENDPOINT, 0,
+ (__u16) USBVISION_INTRA_CYC, value, 5, HZ);
+
+ if (rc < 0) {
+ printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+ "reconnect or reload driver.\n", proc, rc);
+ return rc;
+ }
+
+ if (usbvision->bridgeType == BRIDGE_NT1004) {
+ value[0] = 20; // PCM Threshold 1
+ value[1] = 12; // PCM Threshold 2
+ value[2] = 255; // Distorsion Threshold inter
+ value[3] = 255; // Distorsion Threshold intra
+ value[4] = 43; // Max Distorsion inter
+ value[5] = 43; // Max Distorsion intra
+ }
+ else {
+ value[0] = 20; // PCM Threshold 1
+ value[1] = 12; // PCM Threshold 2
+ value[2] = 255; // Distorsion Threshold d7-d0
+ value[3] = 0; // Distorsion Threshold d11-d8
+ value[4] = 43; // Max Distorsion d7-d0
+ value[5] = 0; // Max Distorsion d8
+ }
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return 0;
+
+ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_ENDPOINT, 0,
+ (__u16) USBVISION_PCM_THR1, value, 6, HZ);
+
+ if (rc < 0) {
+ printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+ "reconnect or reload driver.\n", proc, rc);
+ return rc;
+ }
+
+
+ return rc;
+}
+
+
+/*
+ * usbvision_set_input()
+ *
+ * Set the input (saa711x, ...) size x y and other misc input params
+ * I've no idea if this parameters are right
+ *
+ */
+int usbvision_set_input(struct usb_usbvision *usbvision)
+{
+ static const char proc[] = "usbvision_set_input: ";
+ int rc;
+ unsigned char value[8];
+ unsigned char dvi_yuv_value;
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return 0;
+
+ /* Set input format expected from decoder*/
+ if (usbvision_device_data[usbvision->DevModel].Vin_Reg1 >= 0) {
+ value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1 & 0xff;
+ } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
+ /* SAA7113 uses 8 bit output */
+ value[0] = USBVISION_8_422_SYNC;
+ } else {
+ /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses
+ * as that is how saa7111 is configured */
+ value[0] = USBVISION_16_422_SYNC;
+ /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/
+ }
+
+ rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]);
+ if (rc < 0) {
+ printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+ "reconnect or reload driver.\n", proc, rc);
+ return rc;
+ }
+
+
+ if (usbvision->tvnorm->id & V4L2_STD_PAL) {
+ value[0] = 0xC0;
+ value[1] = 0x02; //0x02C0 -> 704 Input video line length
+ value[2] = 0x20;
+ value[3] = 0x01; //0x0120 -> 288 Input video n. of lines
+ value[4] = 0x60;
+ value[5] = 0x00; //0x0060 -> 96 Input video h offset
+ value[6] = 0x16;
+ value[7] = 0x00; //0x0016 -> 22 Input video v offset
+ } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) {
+ value[0] = 0xC0;
+ value[1] = 0x02; //0x02C0 -> 704 Input video line length
+ value[2] = 0x20;
+ value[3] = 0x01; //0x0120 -> 288 Input video n. of lines
+ value[4] = 0x01;
+ value[5] = 0x00; //0x0001 -> 01 Input video h offset
+ value[6] = 0x01;
+ value[7] = 0x00; //0x0001 -> 01 Input video v offset
+ } else { /* V4L2_STD_NTSC */
+ value[0] = 0xD0;
+ value[1] = 0x02; //0x02D0 -> 720 Input video line length
+ value[2] = 0xF0;
+ value[3] = 0x00; //0x00F0 -> 240 Input video number of lines
+ value[4] = 0x50;
+ value[5] = 0x00; //0x0050 -> 80 Input video h offset
+ value[6] = 0x10;
+ value[7] = 0x00; //0x0010 -> 16 Input video v offset
+ }
+
+ if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) {
+ value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff;
+ value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8;
+ }
+
+ if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) {
+ value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff;
+ value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8;
+ }
+
+ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE, /* USBVISION specific code */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0,
+ (__u16) USBVISION_LXSIZE_I, value, 8, HZ);
+ if (rc < 0) {
+ printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+ "reconnect or reload driver.\n", proc, rc);
+ return rc;
+ }
+
+
+ dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */
+
+ if(usbvision_device_data[usbvision->DevModel].Dvi_yuv >= 0){
+ dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv & 0xff;
+ }
+ else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) {
+ /* This changes as the fine sync control changes. Further investigation necessary */
+ dvi_yuv_value = 0x06;
+ }
+
+ return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value));
+}
+
+
+/*
+ * usbvision_set_dram_settings()
+ *
+ * Set the buffer address needed by the usbvision dram to operate
+ * This values has been taken with usbsnoop.
+ *
+ */
+
+static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
+{
+ int rc;
+ unsigned char value[8];
+
+ if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+ value[0] = 0x42;
+ value[1] = 0x71;
+ value[2] = 0xff;
+ value[3] = 0x00;
+ value[4] = 0x98;
+ value[5] = 0xe0;
+ value[6] = 0x71;
+ value[7] = 0xff;
+ // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte)
+ // FDL: 0x00000-0x0E099 = 57498 Words
+ // VDW: 0x0E3FF-0x3FFFF
+ }
+ else {
+ value[0] = 0x42;
+ value[1] = 0x00;
+ value[2] = 0xff;
+ value[3] = 0x00;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+ value[7] = 0xff;
+ }
+ /* These are the values of the address of the video buffer,
+ * they have to be loaded into the USBVISION_DRM_PRM1-8
+ *
+ * Start address of video output buffer for read: drm_prm1-2 -> 0x00000
+ * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff
+ * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000
+ * Only used in compressed mode
+ * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff
+ * Only used in compressed mode
+ * Start address of video output buffer for write: drm_prm1-7 -> 0x00000
+ * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff
+ */
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return 0;
+
+ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE, /* USBVISION specific code */
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_ENDPOINT, 0,
+ (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
+
+ if (rc < 0) {
+ err("%sERROR=%d", __FUNCTION__, rc);
+ return rc;
+ }
+
+ /* Restart the video buffer logic */
+ if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR |
+ USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0)
+ return rc;
+ rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00);
+
+ return rc;
+}
+
+/*
+ * ()
+ *
+ * Power on the device, enables suspend-resume logic
+ * & reset the isoc End-Point
+ *
+ */
+
+int usbvision_power_on(struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+
+ PDEBUG(DBG_FUNC, "");
+
+ usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+ usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+ USBVISION_SSPND_EN | USBVISION_RES2);
+
+ usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+ USBVISION_SSPND_EN | USBVISION_PWR_VID);
+ errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+ USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2);
+ if (errCode == 1) {
+ usbvision->power = 1;
+ }
+ PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode);
+ return errCode;
+}
+
+
+/*
+ * usbvision timer stuff
+ */
+
+// to call usbvision_power_off from task queue
+static void call_usbvision_power_off(struct work_struct *work)
+{
+ struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork);
+
+ PDEBUG(DBG_FUNC, "");
+ down_interruptible(&usbvision->lock);
+ if(usbvision->user == 0) {
+ usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+
+ usbvision_power_off(usbvision);
+ usbvision->initialized = 0;
+ }
+ up(&usbvision->lock);
+}
+
+static void usbvision_powerOffTimer(unsigned long data)
+{
+ struct usb_usbvision *usbvision = (void *) data;
+
+ PDEBUG(DBG_FUNC, "");
+ del_timer(&usbvision->powerOffTimer);
+ INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off);
+ (void) schedule_work(&usbvision->powerOffWork);
+
+}
+
+void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision)
+{
+ init_timer(&usbvision->powerOffTimer);
+ usbvision->powerOffTimer.data = (long) usbvision;
+ usbvision->powerOffTimer.function = usbvision_powerOffTimer;
+}
+
+void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision)
+{
+ mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME);
+}
+
+void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision)
+{
+ if (timer_pending(&usbvision->powerOffTimer)) {
+ del_timer(&usbvision->powerOffTimer);
+ }
+}
+
+/*
+ * usbvision_begin_streaming()
+ * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no
+ * idea about the rest
+ */
+int usbvision_begin_streaming(struct usb_usbvision *usbvision)
+{
+ int errCode = 0;
+
+ if (usbvision->isocMode == ISOC_MODE_COMPRESS) {
+ usbvision_init_compression(usbvision);
+ }
+ errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID |
+ usbvision->Vin_Reg2_Preset);
+ return errCode;
+}
+
+/*
+ * usbvision_restart_isoc()
+ * Not sure yet if touching here PWR_REG make loose the config
+ */
+
+int usbvision_restart_isoc(struct usb_usbvision *usbvision)
+{
+ int ret;
+
+ if (
+ (ret =
+ usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+ USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0)
+ return ret;
+ if (
+ (ret =
+ usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+ USBVISION_SSPND_EN | USBVISION_PWR_VID |
+ USBVISION_RES2)) < 0)
+ return ret;
+ if (
+ (ret =
+ usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+ USBVISION_KEEP_BLANK | USBVISION_NOHVALID |
+ usbvision->Vin_Reg2_Preset)) < 0) return ret;
+
+ /* TODO: schedule timeout */
+ while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1);
+
+ return 0;
+}
+
+int usbvision_audio_off(struct usb_usbvision *usbvision)
+{
+ if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) {
+ printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n");
+ return -1;
+ }
+ usbvision->AudioMute = 0;
+ usbvision->AudioChannel = USBVISION_AUDIO_MUTE;
+ return 0;
+}
+
+int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel)
+{
+ if (!usbvision->AudioMute) {
+ if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) {
+ printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n");
+ return -1;
+ }
+ }
+ usbvision->AudioChannel = AudioChannel;
+ return 0;
+}
+
+int usbvision_setup(struct usb_usbvision *usbvision,int format)
+{
+ usbvision_set_video_format(usbvision, format);
+ usbvision_set_dram_settings(usbvision);
+ usbvision_set_compress_params(usbvision);
+ usbvision_set_input(usbvision);
+ usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT);
+ usbvision_restart_isoc(usbvision);
+
+ /* cosas del PCM */
+ return USBVISION_IS_OPERATIONAL(usbvision);
+}
+
+/*
+ * usbvision_init_isoc()
+ *
+ */
+int usbvision_init_isoc(struct usb_usbvision *usbvision)
+{
+ struct usb_device *dev = usbvision->dev;
+ int bufIdx, errCode, regValue;
+ const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return -EFAULT;
+
+ usbvision->curFrame = NULL;
+ scratch_reset(usbvision);
+
+ /* Alternate interface 1 is is the biggest frame size */
+ errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive);
+ if (errCode < 0) {
+ usbvision->last_error = errCode;
+ return -EBUSY;
+ }
+
+ regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+ usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
+ PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+
+ usbvision->usb_bandwidth = regValue >> 1;
+ PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+
+
+
+ /* We double buffer the Iso lists */
+
+ for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+ int j, k;
+ struct urb *urb;
+
+ urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+ if (urb == NULL) {
+ err("%s: usb_alloc_urb() failed", __FUNCTION__);
+ return -ENOMEM;
+ }
+ usbvision->sbuf[bufIdx].urb = urb;
+ usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma);
+ urb->dev = dev;
+ urb->context = usbvision;
+ urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->interval = 1;
+ urb->transfer_buffer = usbvision->sbuf[bufIdx].data;
+ urb->complete = usbvision_isocIrq;
+ urb->number_of_packets = USBVISION_URB_FRAMES;
+ urb->transfer_buffer_length =
+ usbvision->isocPacketSize * USBVISION_URB_FRAMES;
+ for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
+ k += usbvision->isocPacketSize) {
+ urb->iso_frame_desc[j].offset = k;
+ urb->iso_frame_desc[j].length = usbvision->isocPacketSize;
+ }
+ }
+
+
+ /* Submit all URBs */
+ for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+ errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL);
+ if (errCode) {
+ err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode);
+ }
+ }
+
+ usbvision->streaming = Stream_Idle;
+ PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
+ return 0;
+}
+
+/*
+ * usbvision_stop_isoc()
+ *
+ * This procedure stops streaming and deallocates URBs. Then it
+ * activates zero-bandwidth alt. setting of the video interface.
+ *
+ */
+void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+{
+ int bufIdx, errCode, regValue;
+ const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+
+ if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
+ return;
+
+ /* Unschedule all of the iso td's */
+ for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
+ usb_kill_urb(usbvision->sbuf[bufIdx].urb);
+ if (usbvision->sbuf[bufIdx].data){
+ usb_buffer_free(usbvision->dev,
+ sb_size,
+ usbvision->sbuf[bufIdx].data,
+ usbvision->sbuf[bufIdx].urb->transfer_dma);
+ }
+ usb_free_urb(usbvision->sbuf[bufIdx].urb);
+ usbvision->sbuf[bufIdx].urb = NULL;
+ }
+
+
+ PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
+ usbvision->streaming = Stream_Off;
+
+ if (!usbvision->remove_pending) {
+
+ /* Set packet size to 0 */
+ errCode = usb_set_interface(usbvision->dev, usbvision->iface,
+ usbvision->ifaceAltInactive);
+ if (errCode < 0) {
+ err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
+ usbvision->last_error = errCode;
+ }
+ regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+ usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
+ PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+
+ usbvision->usb_bandwidth = regValue >> 1;
+ PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+ }
+}
+
+int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
+{
+ int mode[4];
+ int audio[]= {1, 0, 0, 0};
+ struct v4l2_routing route;
+ //channel 0 is TV with audiochannel 1 (tuner mono)
+ //channel 1 is Composite with audio channel 0 (line in)
+ //channel 2 is S-Video with audio channel 0 (line in)
+ //channel 3 is additional video inputs to the device with audio channel 0 (line in)
+
+ RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
+ usbvision->ctl_input = channel;
+ route.input = SAA7115_COMPOSITE1;
+ call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
+ call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input);
+
+ // set the new channel
+ // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video
+ // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red
+
+ switch (usbvision_device_data[usbvision->DevModel].Codec) {
+ case CODEC_SAA7113:
+ if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module.
+ mode[2] = 1;
+ }
+ else {
+ mode[2] = 7;
+ }
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices
+ }
+ else {
+ mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices
+ }
+ break;
+ case CODEC_SAA7111:
+ mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111
+ break;
+ default:
+ mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes
+ }
+ route.input = mode[channel];
+ call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
+ usbvision->channel = channel;
+ usbvision_set_audio(usbvision, audio[channel]);
+ 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/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
new file mode 100644
index 00000000000..858252c1508
--- /dev/null
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -0,0 +1,552 @@
+/*
+ * I2C_ALGO_USB.C
+ * i2c algorithm for USB-I2C Bridges
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ * Dwaine Garden <dwainegarden@rogers.com>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include "usbvision.h"
+
+#define DBG_I2C 1<<0
+#define DBG_ALGO 1<<1
+
+static int i2c_debug = 0;
+
+module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define PDEBUG(level, fmt, args...) \
+ if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+
+static int usbvision_i2c_write(void *data, unsigned char addr, char *buf,
+ short len);
+static int usbvision_i2c_read(void *data, unsigned char addr, char *buf,
+ short len);
+
+static inline int try_write_address(struct i2c_adapter *i2c_adap,
+ unsigned char addr, int retries)
+{
+ void *data;
+ int i, ret = -1;
+ char buf[4];
+
+ data = i2c_get_adapdata(i2c_adap);
+ buf[0] = 0x00;
+ for (i = 0; i <= retries; i++) {
+ ret = (usbvision_i2c_write(data, addr, buf, 1));
+ if (ret == 1)
+ break; /* success! */
+ udelay(5);
+ if (i == retries) /* no success */
+ break;
+ udelay(10);
+ }
+ if (i) {
+ PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr);
+ PDEBUG(DBG_ALGO,"Maybe there's no device at this address");
+ }
+ return ret;
+}
+
+static inline int try_read_address(struct i2c_adapter *i2c_adap,
+ unsigned char addr, int retries)
+{
+ void *data;
+ int i, ret = -1;
+ char buf[4];
+
+ data = i2c_get_adapdata(i2c_adap);
+ for (i = 0; i <= retries; i++) {
+ ret = (usbvision_i2c_read(data, addr, buf, 1));
+ if (ret == 1)
+ break; /* success! */
+ udelay(5);
+ if (i == retries) /* no success */
+ break;
+ udelay(10);
+ }
+ if (i) {
+ PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr);
+ PDEBUG(DBG_ALGO,"Maybe there's no device at this address");
+ }
+ return ret;
+}
+
+static inline int usb_find_address(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msg, int retries,
+ unsigned char *add)
+{
+ unsigned short flags = msg->flags;
+
+ unsigned char addr;
+ int ret;
+ if ((flags & I2C_M_TEN)) {
+ /* a ten bit address */
+ addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+ /* try extended address code... */
+ ret = try_write_address(i2c_adap, addr, retries);
+ if (ret != 1) {
+ err("died at extended address code, while writing");
+ return -EREMOTEIO;
+ }
+ add[0] = addr;
+ if (flags & I2C_M_RD) {
+ /* okay, now switch into reading mode */
+ addr |= 0x01;
+ ret = try_read_address(i2c_adap, addr, retries);
+ if (ret != 1) {
+ err("died at extended address code, while reading");
+ return -EREMOTEIO;
+ }
+ }
+
+ } else { /* normal 7bit address */
+ addr = (msg->addr << 1);
+ if (flags & I2C_M_RD)
+ addr |= 1;
+ if (flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+
+ add[0] = addr;
+ if (flags & I2C_M_RD)
+ ret = try_read_address(i2c_adap, addr, retries);
+ else
+ ret = try_write_address(i2c_adap, addr, retries);
+
+ if (ret != 1) {
+ return -EREMOTEIO;
+ }
+ }
+ return 0;
+}
+
+static int
+usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+ struct i2c_msg *pmsg;
+ void *data;
+ int i, ret;
+ unsigned char addr;
+
+ data = i2c_get_adapdata(i2c_adap);
+
+ for (i = 0; i < num; i++) {
+ pmsg = &msgs[i];
+ ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
+ if (ret != 0) {
+ PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i);
+ return (ret < 0) ? ret : -EREMOTEIO;
+ }
+
+ if (pmsg->flags & I2C_M_RD) {
+ /* read bytes into buffer */
+ ret = (usbvision_i2c_read(data, addr, pmsg->buf, pmsg->len));
+ if (ret < pmsg->len) {
+ return (ret < 0) ? ret : -EREMOTEIO;
+ }
+ } else {
+ /* write bytes from buffer */
+ ret = (usbvision_i2c_write(data, addr, pmsg->buf, pmsg->len));
+ if (ret < pmsg->len) {
+ return (ret < 0) ? ret : -EREMOTEIO;
+ }
+ }
+ }
+ return num;
+}
+
+static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static u32 usb_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm i2c_usb_algo = {
+ .master_xfer = usb_xfer,
+ .smbus_xfer = NULL,
+ .algo_control = algo_control,
+ .functionality = usb_func,
+};
+
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+static int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap)
+{
+ PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]");
+ PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]");
+
+ /* register new adapter to i2c module... */
+
+ adap->algo = &i2c_usb_algo;
+
+ adap->timeout = 100; /* default values, should */
+ adap->retries = 3; /* be replaced by defines */
+
+ i2c_add_adapter(adap);
+
+ PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name);
+
+ return 0;
+}
+
+
+int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap)
+{
+
+ i2c_del_adapter(adap);
+
+ PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name);
+
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* usbvision specific I2C functions */
+/* ----------------------------------------------------------------------- */
+static struct i2c_adapter i2c_adap_template;
+static struct i2c_client i2c_client_template;
+
+int usbvision_init_i2c(struct usb_usbvision *usbvision)
+{
+ memcpy(&usbvision->i2c_adap, &i2c_adap_template,
+ sizeof(struct i2c_adapter));
+ memcpy(&usbvision->i2c_client, &i2c_client_template,
+ sizeof(struct i2c_client));
+
+ sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
+ " #%d", usbvision->vdev->minor & 0x1f);
+ PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
+
+ i2c_set_adapdata(&usbvision->i2c_adap, usbvision);
+ i2c_set_clientdata(&usbvision->i2c_client, usbvision);
+
+ usbvision->i2c_client.adapter = &usbvision->i2c_adap;
+
+ if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) {
+ printk(KERN_ERR "usbvision_init_i2c: can't write reg\n");
+ return -EBUSY;
+ }
+
+#ifdef CONFIG_MODULES
+ /* Request the load of the i2c modules we need */
+ switch (usbvision_device_data[usbvision->DevModel].Codec) {
+ case CODEC_SAA7113:
+ request_module("saa7115");
+ break;
+ case CODEC_SAA7111:
+ request_module("saa7115");
+ break;
+ }
+ if (usbvision_device_data[usbvision->DevModel].Tuner == 1) {
+ request_module("tuner");
+ }
+#endif
+
+ return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap);
+}
+
+void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,
+ void *arg)
+{
+ i2c_clients_command(&usbvision->i2c_adap, cmd, arg);
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+ struct usb_usbvision *usbvision;
+
+ usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
+
+ switch (client->addr << 1) {
+ case 0x43:
+ case 0x4b:
+ {
+ struct tuner_setup tun_setup;
+
+ tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+ tun_setup.type = TUNER_TDA9887;
+ tun_setup.addr = client->addr;
+
+ call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
+
+ break;
+ }
+ case 0x42:
+ PDEBUG(DBG_I2C,"attach_inform: saa7114 detected.");
+ break;
+ case 0x4a:
+ PDEBUG(DBG_I2C,"attach_inform: saa7113 detected.");
+ break;
+ case 0x48:
+ PDEBUG(DBG_I2C,"attach_inform: saa7111 detected.");
+ break;
+ case 0xa0:
+ PDEBUG(DBG_I2C,"attach_inform: eeprom detected.");
+ break;
+
+ default:
+ {
+ struct tuner_setup tun_setup;
+
+ PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1);
+ usbvision->tuner_addr = client->addr;
+
+ if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) {
+ tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+ tun_setup.type = usbvision->tuner_type;
+ tun_setup.addr = usbvision->tuner_addr;
+ call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+ struct usb_usbvision *usbvision;
+
+ usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
+
+ PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name);
+ return 0;
+}
+
+static int
+usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr,
+ char *buf, short len)
+{
+ int rc, retries;
+
+ for (retries = 5;;) {
+ rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr);
+ if (rc < 0)
+ return rc;
+
+ /* Initiate byte read cycle */
+ /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */
+ /* d3 0=Wr 1=Rd */
+ rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
+ (len & 0x07) | 0x18);
+ if (rc < 0)
+ return rc;
+
+ /* Test for Busy and ACK */
+ do {
+ /* USBVISION_SER_CONT -> d4 == 0 busy */
+ rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
+ } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
+ if (rc < 0)
+ return rc;
+
+ /* USBVISION_SER_CONT -> d5 == 1 Not ack */
+ if ((rc & 0x20) == 0) /* Ack? */
+ break;
+
+ /* I2C abort */
+ rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
+ if (rc < 0)
+ return rc;
+
+ if (--retries < 0)
+ return -1;
+ }
+
+ switch (len) {
+ case 4:
+ buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4);
+ case 3:
+ buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3);
+ case 2:
+ buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2);
+ case 1:
+ buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1);
+ break;
+ default:
+ printk(KERN_ERR
+ "usbvision_i2c_read_max4: buffer length > 4\n");
+ }
+
+ if (i2c_debug & DBG_I2C) {
+ int idx;
+ for (idx = 0; idx < len; idx++) {
+ PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr);
+ }
+ }
+ return len;
+}
+
+
+static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision,
+ unsigned char addr, const char *buf,
+ short len)
+{
+ int rc, retries;
+ int i;
+ unsigned char value[6];
+ unsigned char ser_cont;
+
+ ser_cont = (len & 0x07) | 0x10;
+
+ value[0] = addr;
+ value[1] = ser_cont;
+ for (i = 0; i < len; i++)
+ value[i + 2] = buf[i];
+
+ for (retries = 5;;) {
+ rc = usb_control_msg(usbvision->dev,
+ usb_sndctrlpipe(usbvision->dev, 1),
+ USBVISION_OP_CODE,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_ENDPOINT, 0,
+ (__u16) USBVISION_SER_ADRS, value,
+ len + 2, HZ);
+
+ if (rc < 0)
+ return rc;
+
+ rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
+ (len & 0x07) | 0x10);
+ if (rc < 0)
+ return rc;
+
+ /* Test for Busy and ACK */
+ do {
+ rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
+ } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
+ if (rc < 0)
+ return rc;
+
+ if ((rc & 0x20) == 0) /* Ack? */
+ break;
+
+ /* I2C abort */
+ usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
+
+ if (--retries < 0)
+ return -1;
+
+ }
+
+ if (i2c_debug & DBG_I2C) {
+ int idx;
+ for (idx = 0; idx < len; idx++) {
+ PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr);
+ }
+ }
+ return len;
+}
+
+static int usbvision_i2c_write(void *data, unsigned char addr, char *buf,
+ short len)
+{
+ char *bufPtr = buf;
+ int retval;
+ int wrcount = 0;
+ int count;
+ int maxLen = 4;
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
+
+ while (len > 0) {
+ count = (len > maxLen) ? maxLen : len;
+ retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count);
+ if (retval > 0) {
+ len -= count;
+ bufPtr += count;
+ wrcount += count;
+ } else
+ return (retval < 0) ? retval : -EFAULT;
+ }
+ return wrcount;
+}
+
+static int usbvision_i2c_read(void *data, unsigned char addr, char *buf,
+ short len)
+{
+ char temp[4];
+ int retval, i;
+ int rdcount = 0;
+ int count;
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
+
+ while (len > 0) {
+ count = (len > 3) ? 4 : len;
+ retval = usbvision_i2c_read_max4(usbvision, addr, temp, count);
+ if (retval > 0) {
+ for (i = 0; i < len; i++)
+ buf[rdcount + i] = temp[i];
+ len -= count;
+ rdcount += count;
+ } else
+ return (retval < 0) ? retval : -EFAULT;
+ }
+ return rdcount;
+}
+
+static struct i2c_adapter i2c_adap_template = {
+ .owner = THIS_MODULE,
+ .name = "usbvision",
+ .id = I2C_HW_B_BT848, /* FIXME */
+ .client_register = attach_inform,
+ .client_unregister = detach_inform,
+#ifdef I2C_ADAP_CLASS_TV_ANALOG
+ .class = I2C_ADAP_CLASS_TV_ANALOG,
+#else
+ .class = I2C_CLASS_TV_ANALOG,
+#endif
+};
+
+static struct i2c_client i2c_client_template = {
+ .name = "usbvision internal",
+};
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
new file mode 100644
index 00000000000..7243337b771
--- /dev/null
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -0,0 +1,2088 @@
+/*
+ * USB USBVISION Video device driver 0.9.9
+ *
+ *
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *
+ * This module is part of usbvision driver project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Let's call the version 0.... until compression decoding is completely
+ * implemented.
+ *
+ * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach.
+ * It was based on USB CPiA driver written by Peter Pregler,
+ * Scott J. Bertin and Johannes Erdfelt
+ * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler &
+ * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ *
+ * TODO:
+ * - use submit_urb for all setup packets
+ * - Fix memory settings for nt1004. It is 4 times as big as the
+ * nt1003 memory.
+ * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one?
+ * - Clean up the driver.
+ * - optimization for performance.
+ * - Add Videotext capability (VBI). Working on it.....
+ * - Check audio for other devices
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/utsname.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+#include <linux/videodev.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/videodev2.h>
+#include <linux/video_decoder.h>
+#include <linux/i2c.h>
+
+#include <media/saa7115.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/audiochip.h>
+
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#include "usbvision.h"
+
+#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>"
+#define DRIVER_NAME "usbvision"
+#define DRIVER_ALIAS "USBVision"
+#define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
+#define DRIVER_LICENSE "GPL"
+#define USBVISION_DRIVER_VERSION_MAJOR 0
+#define USBVISION_DRIVER_VERSION_MINOR 9
+#define USBVISION_DRIVER_VERSION_PATCHLEVEL 9
+#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL)
+#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL)
+
+#define ENABLE_HEXDUMP 0 /* Enable if you need it */
+
+
+#ifdef USBVISION_DEBUG
+ #define PDEBUG(level, fmt, args...) \
+ if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+ #define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+#define DBG_IOCTL 1<<0
+#define DBG_IO 1<<1
+#define DBG_PROBE 1<<2
+#define DBG_MMAP 1<<3
+
+//String operations
+#define rmspace(str) while(*str==' ') str++;
+#define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++;
+
+
+static int usbvision_nr = 0; // sequential number of usbvision device
+
+static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
+ { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" },
+ { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" },
+ { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" },
+ { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" },
+ { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" },
+ { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" },
+ { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 !
+ { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
+};
+
+/* supported tv norms */
+static struct usbvision_tvnorm tvnorms[] = {
+ {
+ .name = "PAL",
+ .id = V4L2_STD_PAL,
+ }, {
+ .name = "NTSC",
+ .id = V4L2_STD_NTSC,
+ }, {
+ .name = "SECAM",
+ .id = V4L2_STD_SECAM,
+ }, {
+ .name = "PAL-M",
+ .id = V4L2_STD_PAL_M,
+ }
+};
+
+#define TVNORMS ARRAY_SIZE(tvnorms)
+
+// Function prototypes
+static void usbvision_release(struct usb_usbvision *usbvision);
+
+// Default initalization of device driver parameters
+static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint
+static int video_debug = 0; // Set the default Debug Mode of the device driver
+static int PowerOnAtOpen = 1; // Set the default device to power on at startup
+static int video_nr = -1; // Sequential Number of Video Device
+static int radio_nr = -1; // Sequential Number of Radio Device
+static int vbi_nr = -1; // Sequential Number of VBI Device
+static char *CustomDevice=NULL; // Set as nothing....
+
+// Grab parameters for the device driver
+
+#if defined(module_param) // Showing parameters under SYSFS
+module_param(isocMode, int, 0444);
+module_param(video_debug, int, 0444);
+module_param(PowerOnAtOpen, int, 0444);
+module_param(video_nr, int, 0444);
+module_param(radio_nr, int, 0444);
+module_param(vbi_nr, int, 0444);
+module_param(CustomDevice, charp, 0444);
+#else // Old Style
+MODULE_PARAM(isocMode, "i");
+MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver
+MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive
+MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup
+MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently.
+MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...)
+MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...)
+MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...)
+MODULE_PARM(CustomDevice, "s"); // .... CustomDevice
+#endif
+
+MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)");
+MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)");
+MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)");
+MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)");
+MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)");
+MODULE_PARM_DESC(vbi_nr, "Set vbi device number (/dev/vbiX). Default: -1 (autodetect)");
+MODULE_PARM_DESC(CustomDevice, " Define the fine tuning parameters for the device. Default: null");
+
+
+// Misc stuff
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_VERSION(USBVISION_VERSION_STRING);
+MODULE_ALIAS(DRIVER_ALIAS);
+
+
+/****************************************************************************************/
+/* SYSFS Code - Copied from the stv680.c usb module. */
+/* Device information is located at /sys/class/video4linux/video0 */
+/* Device parameters information is located at /sys/module/usbvision */
+/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */
+/****************************************************************************************/
+
+
+#define YES_NO(x) ((x) ? "Yes" : "No")
+
+static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ return video_get_drvdata(vdev);
+}
+
+static ssize_t show_version(struct class_device *cd, char *buf)
+{
+ return sprintf(buf, "%s\n", USBVISION_VERSION_STRING);
+}
+static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
+
+static ssize_t show_model(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString);
+}
+static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+
+static ssize_t show_hue(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ struct v4l2_control ctrl;
+ ctrl.id = V4L2_CID_HUE;
+ ctrl.value = 0;
+ if(usbvision->user)
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+ return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
+
+static ssize_t show_contrast(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ struct v4l2_control ctrl;
+ ctrl.id = V4L2_CID_CONTRAST;
+ ctrl.value = 0;
+ if(usbvision->user)
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+ return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
+
+static ssize_t show_brightness(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ struct v4l2_control ctrl;
+ ctrl.id = V4L2_CID_BRIGHTNESS;
+ ctrl.value = 0;
+ if(usbvision->user)
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+ return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
+
+static ssize_t show_saturation(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ struct v4l2_control ctrl;
+ ctrl.id = V4L2_CID_SATURATION;
+ ctrl.value = 0;
+ if(usbvision->user)
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+ return sprintf(buf, "%d\n", ctrl.value >> 8);
+}
+static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
+
+static ssize_t show_streaming(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0));
+}
+static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
+
+static ssize_t show_compression(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS));
+}
+static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
+
+static ssize_t show_device_bridge(struct class_device *cd, char *buf)
+{
+ struct video_device *vdev = container_of(cd, struct video_device, class_dev);
+ struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+ return sprintf(buf, "%d\n", usbvision->bridgeType);
+}
+static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
+
+static void usbvision_create_sysfs(struct video_device *vdev)
+{
+ int res;
+ if (!vdev)
+ return;
+ do {
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_version);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_model);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_hue);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_contrast);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_brightness);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_saturation);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_streaming);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_compression);
+ if (res<0)
+ break;
+ res=class_device_create_file(&vdev->class_dev,
+ &class_device_attr_bridge);
+ if (res>=0)
+ return;
+ } while (0);
+
+ err("%s error: %d\n", __FUNCTION__, res);
+}
+
+static void usbvision_remove_sysfs(struct video_device *vdev)
+{
+ if (vdev) {
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_version);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_model);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_hue);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_contrast);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_brightness);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_saturation);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_streaming);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_compression);
+ class_device_remove_file(&vdev->class_dev,
+ &class_device_attr_bridge);
+ }
+}
+
+
+/*
+ * usbvision_open()
+ *
+ * This is part of Video 4 Linux API. The driver can be opened by one
+ * client only (checks internal counter 'usbvision->user'). The procedure
+ * then allocates buffers needed for video processing.
+ *
+ */
+static int usbvision_v4l2_open(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ int errCode = 0;
+
+ PDEBUG(DBG_IO, "open");
+
+
+ usbvision_reset_powerOffTimer(usbvision);
+
+ if (usbvision->user)
+ errCode = -EBUSY;
+ else {
+ /* Allocate memory for the frame buffers */
+ errCode = usbvision_frames_alloc(usbvision);
+ if(!errCode) {
+ /* Allocate memory for the scratch ring buffer */
+ errCode = usbvision_scratch_alloc(usbvision);
+ if ((!errCode) && (isocMode==ISOC_MODE_COMPRESS)) {
+ /* Allocate intermediate decompression buffers only if needed */
+ errCode = usbvision_decompress_alloc(usbvision);
+ }
+ }
+ if (errCode) {
+ /* Deallocate all buffers if trouble */
+ usbvision_frames_free(usbvision);
+ usbvision_scratch_free(usbvision);
+ usbvision_decompress_free(usbvision);
+ }
+ }
+
+ /* If so far no errors then we shall start the camera */
+ if (!errCode) {
+ down(&usbvision->lock);
+ if (usbvision->power == 0) {
+ usbvision_power_on(usbvision);
+ usbvision_init_i2c(usbvision);
+ }
+
+ /* Send init sequence only once, it's large! */
+ if (!usbvision->initialized) {
+ int setup_ok = 0;
+ setup_ok = usbvision_setup(usbvision,isocMode);
+ if (setup_ok)
+ usbvision->initialized = 1;
+ else
+ errCode = -EBUSY;
+ }
+
+ if (!errCode) {
+ usbvision_begin_streaming(usbvision);
+ errCode = usbvision_init_isoc(usbvision);
+ /* device needs to be initialized before isoc transfer */
+ usbvision_muxsel(usbvision,0);
+ usbvision->user++;
+ }
+ else {
+ if (PowerOnAtOpen) {
+ usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+ usbvision_power_off(usbvision);
+ usbvision->initialized = 0;
+ }
+ }
+ up(&usbvision->lock);
+ }
+
+ if (errCode) {
+ }
+
+ /* prepare queues */
+ usbvision_empty_framequeues(usbvision);
+
+ PDEBUG(DBG_IO, "success");
+ return errCode;
+}
+
+/*
+ * usbvision_v4l2_close()
+ *
+ * This is part of Video 4 Linux API. The procedure
+ * stops streaming and deallocates all buffers that were earlier
+ * allocated in usbvision_v4l2_open().
+ *
+ */
+static int usbvision_v4l2_close(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+ PDEBUG(DBG_IO, "close");
+ down(&usbvision->lock);
+
+ usbvision_audio_off(usbvision);
+ usbvision_restart_isoc(usbvision);
+ usbvision_stop_isoc(usbvision);
+
+ usbvision_decompress_free(usbvision);
+ usbvision_frames_free(usbvision);
+ usbvision_scratch_free(usbvision);
+
+ usbvision->user--;
+
+ if (PowerOnAtOpen) {
+ /* power off in a little while to avoid off/on every close/open short sequences */
+ usbvision_set_powerOffTimer(usbvision);
+ usbvision->initialized = 0;
+ }
+
+ up(&usbvision->lock);
+
+ if (usbvision->remove_pending) {
+ info("%s: Final disconnect", __FUNCTION__);
+ usbvision_release(usbvision);
+ }
+
+ PDEBUG(DBG_IO, "success");
+
+
+ return 0;
+}
+
+
+/*
+ * usbvision_ioctl()
+ *
+ * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
+ *
+ */
+static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return -EFAULT;
+
+ switch (cmd) {
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ /* ioctls to allow direct acces to the NT100x registers */
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ int errCode;
+
+ if (reg->i2c_id != 0)
+ return -EINVAL;
+ /* NT100x has a 8-bit register space */
+ errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+ if (errCode < 0) {
+ err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
+ }
+ else {
+ reg->val=(unsigned char)errCode;
+ PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
+ (unsigned int)reg->reg, reg->val);
+ errCode = 0; // No error
+ }
+ return errCode;
+ }
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+ int errCode;
+
+ if (reg->i2c_id != 0)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+ if (errCode < 0) {
+ err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
+ }
+ else {
+ PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
+ (unsigned int)reg->reg, reg->val);
+ errCode = 0;
+ }
+ return 0;
+ }
+#endif
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *vc=arg;
+
+ memset(vc, 0, sizeof(*vc));
+ strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+ strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
+ sizeof(vc->card));
+ strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+ sizeof(vc->bus_info));
+ vc->version = USBVISION_DRIVER_VERSION;
+ vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_AUDIO |
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING |
+ (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
+ PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP");
+ return 0;
+ }
+ case VIDIOC_ENUMINPUT:
+ {
+ struct v4l2_input *vi = arg;
+ int chan;
+
+ if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
+ return -EINVAL;
+ if (usbvision->have_tuner) {
+ chan = vi->index;
+ }
+ else {
+ chan = vi->index + 1; //skip Television string
+ }
+ switch(chan) {
+ case 0:
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ strcpy(vi->name, "White Video Input");
+ }
+ else {
+ strcpy(vi->name, "Television");
+ vi->type = V4L2_INPUT_TYPE_TUNER;
+ vi->audioset = 1;
+ vi->tuner = chan;
+ vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM;
+ }
+ break;
+ case 1:
+ vi->type = V4L2_INPUT_TYPE_CAMERA;
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ strcpy(vi->name, "Green Video Input");
+ }
+ else {
+ strcpy(vi->name, "Composite Video Input");
+ }
+ vi->std = V4L2_STD_PAL;
+ break;
+ case 2:
+ vi->type = V4L2_INPUT_TYPE_CAMERA;
+ if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) {
+ strcpy(vi->name, "Yellow Video Input");
+ }
+ else {
+ strcpy(vi->name, "S-Video Input");
+ }
+ vi->std = V4L2_STD_PAL;
+ break;
+ case 3:
+ vi->type = V4L2_INPUT_TYPE_CAMERA;
+ strcpy(vi->name, "Red Video Input");
+ vi->std = V4L2_STD_PAL;
+ break;
+ }
+ PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x",
+ vi->name, vi->index, vi->tuner,vi->type,(int)vi->std);
+ return 0;
+ }
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *e = arg;
+ unsigned int i;
+ int ret;
+
+ i = e->index;
+ if (i >= TVNORMS)
+ return -EINVAL;
+ ret = v4l2_video_std_construct(e, tvnorms[e->index].id,
+ tvnorms[e->index].name);
+ e->index = i;
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+ case VIDIOC_G_INPUT:
+ {
+ int *input = arg;
+ *input = usbvision->ctl_input;
+ return 0;
+ }
+ case VIDIOC_S_INPUT:
+ {
+ int *input = arg;
+ if ((*input >= usbvision->video_inputs) || (*input < 0) )
+ return -EINVAL;
+ usbvision->ctl_input = *input;
+
+ down(&usbvision->lock);
+ usbvision_muxsel(usbvision, usbvision->ctl_input);
+ usbvision_set_input(usbvision);
+ usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight);
+ up(&usbvision->lock);
+ return 0;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
+
+ *id = usbvision->tvnorm->id;
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name);
+ return 0;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ unsigned int i;
+
+ for (i = 0; i < TVNORMS; i++)
+ if (*id == tvnorms[i].id)
+ break;
+ if (i == TVNORMS)
+ for (i = 0; i < TVNORMS; i++)
+ if (*id & tvnorms[i].id)
+ break;
+ if (i == TVNORMS)
+ return -EINVAL;
+
+ down(&usbvision->lock);
+ usbvision->tvnorm = &tvnorms[i];
+
+ call_i2c_clients(usbvision, VIDIOC_S_STD,
+ &usbvision->tvnorm->id);
+
+ up(&usbvision->lock);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name);
+ return 0;
+ }
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *vt = arg;
+
+ if (!usbvision->have_tuner || vt->index) // Only tuner 0
+ return -EINVAL;
+ strcpy(vt->name, "Television");
+ /* Let clients fill in the remainder of this struct */
+ call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc);
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *vt = arg;
+
+ // Only no or one tuner for now
+ if (!usbvision->have_tuner || vt->index)
+ return -EINVAL;
+ /* let clients handle this */
+ call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER");
+ return 0;
+ }
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *freq = arg;
+
+ freq->tuner = 0; // Only one tuner
+ freq->type = V4L2_TUNER_ANALOG_TV;
+ freq->frequency = usbvision->freq;
+ PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
+ return 0;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *freq = arg;
+
+ // Only no or one tuner for now
+ if (!usbvision->have_tuner || freq->tuner)
+ return -EINVAL;
+
+ usbvision->freq = freq->frequency;
+ call_i2c_clients(usbvision, cmd, freq);
+ PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency);
+ return 0;
+ }
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *v = arg;
+ memset(v,0, sizeof(v));
+ strcpy(v->name, "TV");
+ PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO");
+ return 0;
+ }
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *v = arg;
+ if(v->index) {
+ return -EINVAL;
+ }
+ PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO");
+ return 0;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+ int id=ctrl->id;
+
+ memset(ctrl,0,sizeof(*ctrl));
+ ctrl->id=id;
+
+ call_i2c_clients(usbvision, cmd, arg);
+
+ if (ctrl->type)
+ return 0;
+ else
+ return -EINVAL;
+
+ PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+ return 0;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+ call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
+ return 0;
+ }
+ case VIDIOC_REQBUFS:
+ {
+ struct v4l2_requestbuffers *vr = arg;
+ int ret;
+
+ RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
+
+ // Check input validity : the user must do a VIDEO CAPTURE and MMAP method.
+ if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+ (vr->memory != V4L2_MEMORY_MMAP))
+ return -EINVAL;
+
+ if(usbvision->streaming == Stream_On) {
+ if ((ret = usbvision_stream_interrupt(usbvision)))
+ return ret;
+ }
+
+ usbvision_empty_framequeues(usbvision);
+
+ usbvision->curFrame = NULL;
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count);
+ return 0;
+ }
+ case VIDIOC_QUERYBUF:
+ {
+ struct v4l2_buffer *vb = arg;
+ struct usbvision_frame *frame;
+
+ // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called)
+
+ if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
+ return -EINVAL;
+ }
+ if(vb->index>=USBVISION_NUMFRAMES) {
+ return -EINVAL;
+ }
+ // Updating the corresponding frame state
+ vb->flags = 0;
+ frame = &usbvision->frame[vb->index];
+ if(frame->grabstate >= FrameState_Ready)
+ vb->flags |= V4L2_BUF_FLAG_QUEUED;
+ if(frame->grabstate >= FrameState_Done)
+ vb->flags |= V4L2_BUF_FLAG_DONE;
+ if(frame->grabstate == FrameState_Unused)
+ vb->flags |= V4L2_BUF_FLAG_MAPPED;
+ vb->memory = V4L2_MEMORY_MMAP;
+
+ vb->m.offset = vb->index*usbvision->max_frame_size;
+
+ vb->memory = V4L2_MEMORY_MMAP;
+ vb->field = V4L2_FIELD_NONE;
+ vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel;
+ vb->timestamp = usbvision->frame[vb->index].timestamp;
+ vb->sequence = usbvision->frame[vb->index].sequence;
+ return 0;
+ }
+ case VIDIOC_QBUF:
+ {
+ struct v4l2_buffer *vb = arg;
+ struct usbvision_frame *frame;
+ unsigned long lock_flags;
+
+ // FIXME : works only on VIDEO_CAPTURE MODE, MMAP.
+ if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
+ return -EINVAL;
+ }
+ if(vb->index>=USBVISION_NUMFRAMES) {
+ return -EINVAL;
+ }
+
+ frame = &usbvision->frame[vb->index];
+
+ if (frame->grabstate != FrameState_Unused) {
+ return -EAGAIN;
+ }
+
+ /* Mark it as ready and enqueue frame */
+ frame->grabstate = FrameState_Ready;
+ frame->scanstate = ScanState_Scanning;
+ frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */
+
+ vb->flags &= ~V4L2_BUF_FLAG_DONE;
+
+ /* set v4l2_format index */
+ frame->v4l2_format = usbvision->palette;
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index);
+ return 0;
+ }
+ case VIDIOC_DQBUF:
+ {
+ struct v4l2_buffer *vb = arg;
+ int ret;
+ struct usbvision_frame *f;
+ unsigned long lock_flags;
+
+ if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (list_empty(&(usbvision->outqueue))) {
+ if (usbvision->streaming == Stream_Idle)
+ return -EINVAL;
+ ret = wait_event_interruptible
+ (usbvision->wait_frame,
+ !list_empty(&(usbvision->outqueue)));
+ if (ret)
+ return ret;
+ }
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ f = list_entry(usbvision->outqueue.next,
+ struct usbvision_frame, frame);
+ list_del(usbvision->outqueue.next);
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+ f->grabstate = FrameState_Unused;
+
+ vb->memory = V4L2_MEMORY_MMAP;
+ vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE;
+ vb->index = f->index;
+ vb->sequence = f->sequence;
+ vb->timestamp = f->timestamp;
+ vb->field = V4L2_FIELD_NONE;
+ vb->bytesused = f->scanlength;
+
+ return 0;
+ }
+ case VIDIOC_STREAMON:
+ {
+ int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ usbvision->streaming = Stream_On;
+
+ call_i2c_clients(usbvision,VIDIOC_STREAMON , &b);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON");
+
+ return 0;
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ int *type = arg;
+ int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if(usbvision->streaming == Stream_On) {
+ usbvision_stream_interrupt(usbvision);
+ // Stop all video streamings
+ call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
+ }
+ usbvision_empty_framequeues(usbvision);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF");
+ return 0;
+ }
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *vfd = arg;
+
+ if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
+ return -EINVAL;
+ }
+ vfd->flags = 0;
+ vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
+ vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
+ memset(vfd->reserved, 0, sizeof(vfd->reserved));
+ return 0;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *vf = arg;
+
+ switch (vf->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ {
+ vf->fmt.pix.width = usbvision->curwidth;
+ vf->fmt.pix.height = usbvision->curheight;
+ vf->fmt.pix.pixelformat = usbvision->palette.format;
+ vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel;
+ vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight;
+ vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
+ PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s",
+ vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
+ return 0;
+ }
+ default:
+ PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type);
+ return -EINVAL;
+ }
+ return 0;
+ }
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *vf = arg;
+ int formatIdx,ret;
+
+ switch(vf->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ {
+ /* Find requested format in available ones */
+ for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) {
+ if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) {
+ usbvision->palette = usbvision_v4l2_format[formatIdx];
+ break;
+ }
+ }
+ /* robustness */
+ if(formatIdx == USBVISION_SUPPORTED_PALETTES) {
+ return -EINVAL;
+ }
+ RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
+ RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
+
+ vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel;
+ vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
+
+ if(cmd == VIDIOC_TRY_FMT) {
+ PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s",
+ vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
+ return 0;
+ }
+
+ /* stop io in case it is already in progress */
+ if(usbvision->streaming == Stream_On) {
+ if ((ret = usbvision_stream_interrupt(usbvision)))
+ return ret;
+ }
+ usbvision_empty_framequeues(usbvision);
+
+ usbvision->curFrame = NULL;
+
+ // by now we are committed to the new data...
+ down(&usbvision->lock);
+ usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
+ up(&usbvision->lock);
+
+ PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s",
+ vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc);
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl);
+}
+
+
+static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
+ size_t count, loff_t *ppos)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ int noblock = file->f_flags & O_NONBLOCK;
+ unsigned long lock_flags;
+
+ int ret,i;
+ struct usbvision_frame *frame;
+
+ PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock);
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
+ return -EFAULT;
+
+ /* no stream is running, make it running ! */
+ usbvision->streaming = Stream_On;
+ call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL);
+
+ /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */
+ for(i=0;i<USBVISION_NUMFRAMES;i++) {
+ frame = &usbvision->frame[i];
+ if(frame->grabstate == FrameState_Unused) {
+ /* Mark it as ready and enqueue frame */
+ frame->grabstate = FrameState_Ready;
+ frame->scanstate = ScanState_Scanning;
+ frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */
+
+ /* set v4l2_format index */
+ frame->v4l2_format = usbvision->palette;
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ list_add_tail(&frame->frame, &usbvision->inqueue);
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+ }
+ }
+
+ /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */
+ if (list_empty(&(usbvision->outqueue))) {
+ if(noblock)
+ return -EAGAIN;
+
+ ret = wait_event_interruptible
+ (usbvision->wait_frame,
+ !list_empty(&(usbvision->outqueue)));
+ if (ret)
+ return ret;
+ }
+
+ spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+ frame = list_entry(usbvision->outqueue.next,
+ struct usbvision_frame, frame);
+ list_del(usbvision->outqueue.next);
+ spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+ /* An error returns an empty frame */
+ if (frame->grabstate == FrameState_Error) {
+ frame->bytes_read = 0;
+ return 0;
+ }
+
+ PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__,
+ frame->index, frame->bytes_read, frame->scanlength);
+
+ /* copy bytes to user space; we allow for partials reads */
+ if ((count + frame->bytes_read) > (unsigned long)frame->scanlength)
+ count = frame->scanlength - frame->bytes_read;
+
+ if (copy_to_user(buf, frame->data + frame->bytes_read, count)) {
+ return -EFAULT;
+ }
+
+ frame->bytes_read += count;
+ PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__,
+ (unsigned long)count, frame->bytes_read);
+
+ // For now, forget the frame if it has not been read in one shot.
+/* if (frame->bytes_read >= frame->scanlength) {// All data has been read */
+ frame->bytes_read = 0;
+
+ /* Mark it as available to be used again. */
+ frame->grabstate = FrameState_Unused;
+/* } */
+
+ return count;
+}
+
+static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start,
+ start = vma->vm_start;
+ void *pos;
+ u32 i;
+
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+ down(&usbvision->lock);
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision)) {
+ up(&usbvision->lock);
+ return -EFAULT;
+ }
+
+ if (!(vma->vm_flags & VM_WRITE) ||
+ size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) {
+ up(&usbvision->lock);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+ if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff)
+ break;
+ }
+ if (i == USBVISION_NUMFRAMES) {
+ PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range");
+ up(&usbvision->lock);
+ return -EINVAL;
+ }
+
+ /* VM_IO is eventually going to replace PageReserved altogether */
+ vma->vm_flags |= VM_IO;
+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+
+ pos = usbvision->frame[i].data;
+ while (size > 0) {
+
+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+ PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed");
+ up(&usbvision->lock);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ up(&usbvision->lock);
+ return 0;
+}
+
+
+/*
+ * Here comes the stuff for radio on usbvision based devices
+ *
+ */
+static int usbvision_radio_open(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ struct v4l2_frequency freq;
+ int errCode = 0;
+
+ PDEBUG(DBG_IO, "%s:", __FUNCTION__);
+
+ down(&usbvision->lock);
+
+ if (usbvision->user) {
+ err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__);
+ errCode = -EBUSY;
+ }
+ else {
+ if(PowerOnAtOpen) {
+ usbvision_reset_powerOffTimer(usbvision);
+ if (usbvision->power == 0) {
+ usbvision_power_on(usbvision);
+ usbvision_init_i2c(usbvision);
+ }
+ }
+
+ // If so far no errors then we shall start the radio
+ usbvision->radio = 1;
+ call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
+ freq.frequency = 1517; //SWR3 @ 94.8MHz
+ call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq);
+ usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
+ usbvision->user++;
+ }
+
+ if (errCode) {
+ if (PowerOnAtOpen) {
+ usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+ usbvision_power_off(usbvision);
+ usbvision->initialized = 0;
+ }
+ }
+ up(&usbvision->lock);
+ return errCode;
+}
+
+
+static int usbvision_radio_close(struct inode *inode, struct file *file)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+ int errCode = 0;
+
+ PDEBUG(DBG_IO, "");
+
+ down(&usbvision->lock);
+
+ usbvision_audio_off(usbvision);
+ usbvision->radio=0;
+ usbvision->user--;
+
+ if (PowerOnAtOpen) {
+ usbvision_set_powerOffTimer(usbvision);
+ usbvision->initialized = 0;
+ }
+
+ up(&usbvision->lock);
+
+ if (usbvision->remove_pending) {
+ info("%s: Final disconnect", __FUNCTION__);
+ usbvision_release(usbvision);
+ }
+
+
+ PDEBUG(DBG_IO, "success");
+
+ return errCode;
+}
+
+static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct video_device *dev = video_devdata(file);
+ struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision))
+ return -EIO;
+
+ switch (cmd) {
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *vc=arg;
+
+ memset(vc, 0, sizeof(*vc));
+ strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+ strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString,
+ sizeof(vc->card));
+ strlcpy(vc->bus_info, usbvision->dev->dev.bus_id,
+ sizeof(vc->bus_info));
+ vc->version = USBVISION_DRIVER_VERSION;
+ vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
+ PDEBUG(DBG_IO, "VIDIOC_QUERYCAP");
+ return 0;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+ int id=ctrl->id;
+
+ memset(ctrl,0,sizeof(*ctrl));
+ ctrl->id=id;
+
+ call_i2c_clients(usbvision, cmd, arg);
+ PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type);
+
+ if (ctrl->type)
+ return 0;
+ else
+ return -EINVAL;
+
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+ PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+ return 0;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
+ PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value);
+ return 0;
+ }
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (t->index > 0)
+ return -EINVAL;
+
+ memset(t,0,sizeof(*t));
+ strcpy(t->name, "Radio");
+ t->type = V4L2_TUNER_RADIO;
+
+ /* Let clients fill in the remainder of this struct */
+ call_i2c_clients(usbvision,VIDIOC_G_TUNER,t);
+ PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc);
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *vt = arg;
+
+ // Only no or one tuner for now
+ if (!usbvision->have_tuner || vt->index)
+ return -EINVAL;
+ /* let clients handle this */
+ call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
+
+ PDEBUG(DBG_IO, "VIDIOC_S_TUNER");
+ return 0;
+ }
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *a = arg;
+
+ memset(a,0,sizeof(*a));
+ strcpy(a->name,"Radio");
+ PDEBUG(DBG_IO, "VIDIOC_G_AUDIO");
+ return 0;
+ }
+ case VIDIOC_S_AUDIO:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_S_STD:
+ return 0;
+
+ case VIDIOC_G_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ memset(f,0,sizeof(*f));
+
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = usbvision->freq;
+ call_i2c_clients(usbvision, cmd, f);
+ PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency);
+
+ return 0;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ if (f->tuner != 0)
+ return -EINVAL;
+ usbvision->freq = f->frequency;
+ call_i2c_clients(usbvision, cmd, f);
+ PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency);
+
+ return 0;
+ }
+ default:
+ {
+ PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd);
+ return -ENOIOCTLCMD;
+ }
+ }
+ return 0;
+}
+
+
+static int usbvision_radio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl);
+}
+
+
+/*
+ * Here comes the stuff for vbi on usbvision based devices
+ *
+ */
+static int usbvision_vbi_open(struct inode *inode, struct file *file)
+{
+ /* TODO */
+ return -EINVAL;
+
+}
+
+static int usbvision_vbi_close(struct inode *inode, struct file *file)
+{
+ /* TODO */
+ return -EINVAL;
+}
+
+static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ /* TODO */
+ return -EINVAL;
+}
+
+static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, usbvision_do_vbi_ioctl);
+}
+
+
+//
+// Video registration stuff
+//
+
+// Video template
+static struct file_operations usbvision_fops = {
+ .owner = THIS_MODULE,
+ .open = usbvision_v4l2_open,
+ .release = usbvision_v4l2_close,
+ .read = usbvision_v4l2_read,
+ .mmap = usbvision_v4l2_mmap,
+ .ioctl = usbvision_v4l2_ioctl,
+ .llseek = no_llseek,
+};
+static struct video_device usbvision_video_template = {
+ .owner = THIS_MODULE,
+ .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE,
+ .hardware = VID_HARDWARE_USBVISION,
+ .fops = &usbvision_fops,
+ .name = "usbvision-video",
+ .release = video_device_release,
+ .minor = -1,
+};
+
+
+// Radio template
+static struct file_operations usbvision_radio_fops = {
+ .owner = THIS_MODULE,
+ .open = usbvision_radio_open,
+ .release = usbvision_radio_close,
+ .ioctl = usbvision_radio_ioctl,
+ .llseek = no_llseek,
+};
+
+static struct video_device usbvision_radio_template=
+{
+ .owner = THIS_MODULE,
+ .type = VID_TYPE_TUNER,
+ .hardware = VID_HARDWARE_USBVISION,
+ .fops = &usbvision_radio_fops,
+ .release = video_device_release,
+ .name = "usbvision-radio",
+ .minor = -1,
+};
+
+
+// vbi template
+static struct file_operations usbvision_vbi_fops = {
+ .owner = THIS_MODULE,
+ .open = usbvision_vbi_open,
+ .release = usbvision_vbi_close,
+ .ioctl = usbvision_vbi_ioctl,
+ .llseek = no_llseek,
+};
+
+static struct video_device usbvision_vbi_template=
+{
+ .owner = THIS_MODULE,
+ .type = VID_TYPE_TUNER,
+ .hardware = VID_HARDWARE_USBVISION,
+ .fops = &usbvision_vbi_fops,
+ .release = video_device_release,
+ .name = "usbvision-vbi",
+ .minor = -1,
+};
+
+
+static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
+ struct video_device *vdev_template,
+ char *name)
+{
+ struct usb_device *usb_dev = usbvision->dev;
+ struct video_device *vdev;
+
+ if (usb_dev == NULL) {
+ err("%s: usbvision->dev is not set", __FUNCTION__);
+ return NULL;
+ }
+
+ vdev = video_device_alloc();
+ if (NULL == vdev) {
+ return NULL;
+ }
+ *vdev = *vdev_template;
+// vdev->minor = -1;
+ vdev->dev = &usb_dev->dev;
+ snprintf(vdev->name, sizeof(vdev->name), "%s", name);
+ video_set_drvdata(vdev, usbvision);
+ return vdev;
+}
+
+// unregister video4linux devices
+static void usbvision_unregister_video(struct usb_usbvision *usbvision)
+{
+ // vbi Device:
+ if (usbvision->vbi) {
+ PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f);
+ if (usbvision->vbi->minor != -1) {
+ video_unregister_device(usbvision->vbi);
+ }
+ else {
+ video_device_release(usbvision->vbi);
+ }
+ usbvision->vbi = NULL;
+ }
+
+ // Radio Device:
+ if (usbvision->rdev) {
+ PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f);
+ if (usbvision->rdev->minor != -1) {
+ video_unregister_device(usbvision->rdev);
+ }
+ else {
+ video_device_release(usbvision->rdev);
+ }
+ usbvision->rdev = NULL;
+ }
+
+ // Video Device:
+ if (usbvision->vdev) {
+ PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f);
+ if (usbvision->vdev->minor != -1) {
+ video_unregister_device(usbvision->vdev);
+ }
+ else {
+ video_device_release(usbvision->vdev);
+ }
+ usbvision->vdev = NULL;
+ }
+}
+
+// register video4linux devices
+static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
+{
+ // Video Device:
+ usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video");
+ if (usbvision->vdev == NULL) {
+ goto err_exit;
+ }
+ if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) {
+ goto err_exit;
+ }
+ info("USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]", usbvision->nr,usbvision->vdev->minor & 0x1f);
+
+ // Radio Device:
+ if (usbvision_device_data[usbvision->DevModel].Radio) {
+ // usbvision has radio
+ usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio");
+ if (usbvision->rdev == NULL) {
+ goto err_exit;
+ }
+ if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) {
+ goto err_exit;
+ }
+ info("USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]", usbvision->nr, usbvision->rdev->minor & 0x1f);
+ }
+ // vbi Device:
+ if (usbvision_device_data[usbvision->DevModel].vbi) {
+ usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI");
+ if (usbvision->vdev == NULL) {
+ goto err_exit;
+ }
+ if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) {
+ goto err_exit;
+ }
+ info("USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)", usbvision->nr,usbvision->vbi->minor & 0x1f);
+ }
+ // all done
+ return 0;
+
+ err_exit:
+ err("USBVision[%d]: video_register_device() failed", usbvision->nr);
+ usbvision_unregister_video(usbvision);
+ return -1;
+}
+
+/*
+ * usbvision_alloc()
+ *
+ * This code allocates the struct usb_usbvision. It is filled with default values.
+ *
+ * Returns NULL on error, a pointer to usb_usbvision else.
+ *
+ */
+static struct usb_usbvision *usbvision_alloc(struct usb_device *dev)
+{
+ struct usb_usbvision *usbvision;
+
+ if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) {
+ goto err_exit;
+ }
+
+ usbvision->dev = dev;
+
+ init_MUTEX(&usbvision->lock); /* to 1 == available */
+
+ // prepare control urb for control messages during interrupts
+ usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+ if (usbvision->ctrlUrb == NULL) {
+ goto err_exit;
+ }
+ init_waitqueue_head(&usbvision->ctrlUrb_wq);
+ init_MUTEX(&usbvision->ctrlUrbLock); /* to 1 == available */
+
+ usbvision_init_powerOffTimer(usbvision);
+
+ return usbvision;
+
+err_exit:
+ if (usbvision && usbvision->ctrlUrb) {
+ usb_free_urb(usbvision->ctrlUrb);
+ }
+ if (usbvision) {
+ kfree(usbvision);
+ }
+ return NULL;
+}
+
+/*
+ * usbvision_release()
+ *
+ * This code does final release of struct usb_usbvision. This happens
+ * after the device is disconnected -and- all clients closed their files.
+ *
+ */
+static void usbvision_release(struct usb_usbvision *usbvision)
+{
+ PDEBUG(DBG_PROBE, "");
+
+ down(&usbvision->lock);
+
+ usbvision_reset_powerOffTimer(usbvision);
+
+ usbvision->initialized = 0;
+
+ up(&usbvision->lock);
+
+ usbvision_remove_sysfs(usbvision->vdev);
+ usbvision_unregister_video(usbvision);
+
+ if (usbvision->ctrlUrb) {
+ usb_free_urb(usbvision->ctrlUrb);
+ }
+
+ kfree(usbvision);
+
+ PDEBUG(DBG_PROBE, "success");
+}
+
+
+/******************************** usb interface *****************************************/
+
+static void usbvision_configure_video(struct usb_usbvision *usbvision)
+{
+ int model,i;
+
+ if (usbvision == NULL)
+ return;
+
+ model = usbvision->DevModel;
+ usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24;
+
+ if (usbvision_device_data[usbvision->DevModel].Vin_Reg2 >= 0) {
+ usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2 & 0xff;
+ } else {
+ usbvision->Vin_Reg2_Preset = 0;
+ }
+
+ for (i = 0; i < TVNORMS; i++)
+ if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode)
+ break;
+ if (i == TVNORMS)
+ i = 0;
+ usbvision->tvnorm = &tvnorms[i]; /* set default norm */
+
+ usbvision->video_inputs = usbvision_device_data[model].VideoChannels;
+ usbvision->ctl_input = 0;
+
+ /* This should be here to make i2c clients to be able to register */
+ usbvision_audio_off(usbvision); //first switch off audio
+ if (!PowerOnAtOpen) {
+ usbvision_power_on(usbvision); //and then power up the noisy tuner
+ usbvision_init_i2c(usbvision);
+ }
+}
+
+/*
+ * usbvision_probe()
+ *
+ * This procedure queries device descriptor and accepts the interface
+ * if it looks like USBVISION video device
+ *
+ */
+static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ __u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
+ const struct usb_host_interface *interface;
+ struct usb_usbvision *usbvision = NULL;
+ const struct usb_endpoint_descriptor *endpoint;
+ int model;
+
+ PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
+ dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+ /* Is it an USBVISION video dev? */
+ model = 0;
+ for(model = 0; usbvision_device_data[model].idVendor; model++) {
+ if (le16_to_cpu(dev->descriptor.idVendor) != usbvision_device_data[model].idVendor) {
+ continue;
+ }
+ if (le16_to_cpu(dev->descriptor.idProduct) != usbvision_device_data[model].idProduct) {
+ continue;
+ }
+
+ info("%s: %s found", __FUNCTION__, usbvision_device_data[model].ModelString);
+ break;
+ }
+
+ if (usbvision_device_data[model].idVendor == 0) {
+ return -ENODEV; //no matching device
+ }
+ if (usbvision_device_data[model].Interface >= 0) {
+ interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0];
+ }
+ else {
+ interface = &dev->actconfig->interface[ifnum]->altsetting[0];
+ }
+ endpoint = &interface->endpoint[1].desc;
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) {
+ err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum);
+ err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes);
+ return -ENODEV;
+ }
+ if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+ err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum);
+ return -ENODEV;
+ }
+
+ usb_get_dev(dev);
+
+ if ((usbvision = usbvision_alloc(dev)) == NULL) {
+ err("%s: couldn't allocate USBVision struct", __FUNCTION__);
+ return -ENOMEM;
+ }
+ if (dev->descriptor.bNumConfigurations > 1) {
+ usbvision->bridgeType = BRIDGE_NT1004;
+ }
+ else if (usbvision_device_data[model].ModelString == "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)") {
+ usbvision->bridgeType = BRIDGE_NT1005;
+ }
+ else {
+ usbvision->bridgeType = BRIDGE_NT1003;
+ }
+ PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType);
+
+ down(&usbvision->lock);
+
+ usbvision->nr = usbvision_nr++;
+
+ usbvision->have_tuner = usbvision_device_data[model].Tuner;
+ if (usbvision->have_tuner) {
+ usbvision->tuner_type = usbvision_device_data[model].TunerType;
+ }
+
+ usbvision->tuner_addr = ADDR_UNSET;
+
+ usbvision->DevModel = model;
+ usbvision->remove_pending = 0;
+ usbvision->iface = ifnum;
+ usbvision->ifaceAltInactive = 0;
+ usbvision->ifaceAltActive = 1;
+ usbvision->video_endp = endpoint->bEndpointAddress;
+ usbvision->isocPacketSize = 0;
+ usbvision->usb_bandwidth = 0;
+ usbvision->user = 0;
+ usbvision->streaming = Stream_Off;
+ usbvision_register_video(usbvision);
+ usbvision_configure_video(usbvision);
+ up(&usbvision->lock);
+
+
+ usb_set_intfdata (intf, usbvision);
+ usbvision_create_sysfs(usbvision->vdev);
+
+ PDEBUG(DBG_PROBE, "success");
+ return 0;
+}
+
+
+/*
+ * usbvision_disconnect()
+ *
+ * This procedure stops all driver activity, deallocates interface-private
+ * structure (pointed by 'ptr') and after that driver should be removable
+ * with no ill consequences.
+ *
+ */
+static void __devexit usbvision_disconnect(struct usb_interface *intf)
+{
+ struct usb_usbvision *usbvision = usb_get_intfdata(intf);
+
+ PDEBUG(DBG_PROBE, "");
+
+ if (usbvision == NULL) {
+ err("%s: usb_get_intfdata() failed", __FUNCTION__);
+ return;
+ }
+ usb_set_intfdata (intf, NULL);
+
+ down(&usbvision->lock);
+
+ // At this time we ask to cancel outstanding URBs
+ usbvision_stop_isoc(usbvision);
+
+ if (usbvision->power) {
+ usbvision_i2c_usb_del_bus(&usbvision->i2c_adap);
+ usbvision_power_off(usbvision);
+ }
+ usbvision->remove_pending = 1; // Now all ISO data will be ignored
+
+ usb_put_dev(usbvision->dev);
+ usbvision->dev = NULL; // USB device is no more
+
+ up(&usbvision->lock);
+
+ if (usbvision->user) {
+ info("%s: In use, disconnect pending", __FUNCTION__);
+ wake_up_interruptible(&usbvision->wait_frame);
+ wake_up_interruptible(&usbvision->wait_stream);
+ }
+ else {
+ usbvision_release(usbvision);
+ }
+
+ PDEBUG(DBG_PROBE, "success");
+
+}
+
+static struct usb_driver usbvision_driver = {
+ .name = "usbvision",
+ .id_table = usbvision_table,
+ .probe = usbvision_probe,
+ .disconnect = usbvision_disconnect
+};
+
+/*
+ * customdevice_process()
+ *
+ * This procedure preprocesses CustomDevice parameter if any
+ *
+ */
+static void customdevice_process(void)
+{
+ usbvision_device_data[0]=usbvision_device_data[1];
+ usbvision_table[0]=usbvision_table[1];
+
+ if(CustomDevice)
+ {
+ char *parse=CustomDevice;
+
+ PDEBUG(DBG_PROBE, "CustomDevide=%s", CustomDevice);
+
+ /*format is CustomDevice="0x0573 0x4D31 0 7113 3 PAL 1 1 1 5 -1 -1 -1 -1 -1"
+ usbvision_device_data[0].idVendor;
+ usbvision_device_data[0].idProduct;
+ usbvision_device_data[0].Interface;
+ usbvision_device_data[0].Codec;
+ usbvision_device_data[0].VideoChannels;
+ usbvision_device_data[0].VideoNorm;
+ usbvision_device_data[0].AudioChannels;
+ usbvision_device_data[0].Radio;
+ usbvision_device_data[0].Tuner;
+ usbvision_device_data[0].TunerType;
+ usbvision_device_data[0].Vin_Reg1;
+ usbvision_device_data[0].Vin_Reg2;
+ usbvision_device_data[0].X_Offset;
+ usbvision_device_data[0].Y_Offset;
+ usbvision_device_data[0].Dvi_yuv;
+ usbvision_device_data[0].ModelString;
+ */
+
+ rmspace(parse);
+ usbvision_device_data[0].ModelString="USBVISION Custom Device";
+
+ parse+=2;
+ sscanf(parse,"%x",&usbvision_device_data[0].idVendor);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "idVendor=0x%.4X", usbvision_device_data[0].idVendor);
+ parse+=2;
+ sscanf(parse,"%x",&usbvision_device_data[0].idProduct);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "idProduct=0x%.4X", usbvision_device_data[0].idProduct);
+ sscanf(parse,"%d",&usbvision_device_data[0].Interface);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Interface=%d", usbvision_device_data[0].Interface);
+ sscanf(parse,"%d",&usbvision_device_data[0].Codec);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Codec=%d", usbvision_device_data[0].Codec);
+ sscanf(parse,"%d",&usbvision_device_data[0].VideoChannels);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "VideoChannels=%d", usbvision_device_data[0].VideoChannels);
+
+ switch(*parse)
+ {
+ case 'P':
+ PDEBUG(DBG_PROBE, "VideoNorm=PAL");
+ usbvision_device_data[0].VideoNorm=V4L2_STD_PAL;
+ break;
+
+ case 'S':
+ PDEBUG(DBG_PROBE, "VideoNorm=SECAM");
+ usbvision_device_data[0].VideoNorm=V4L2_STD_SECAM;
+ break;
+
+ case 'N':
+ PDEBUG(DBG_PROBE, "VideoNorm=NTSC");
+ usbvision_device_data[0].VideoNorm=V4L2_STD_NTSC;
+ break;
+
+ default:
+ PDEBUG(DBG_PROBE, "VideoNorm=PAL (by default)");
+ usbvision_device_data[0].VideoNorm=V4L2_STD_PAL;
+ break;
+ }
+ goto2next(parse);
+
+ sscanf(parse,"%d",&usbvision_device_data[0].AudioChannels);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "AudioChannels=%d", usbvision_device_data[0].AudioChannels);
+ sscanf(parse,"%d",&usbvision_device_data[0].Radio);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Radio=%d", usbvision_device_data[0].Radio);
+ sscanf(parse,"%d",&usbvision_device_data[0].Tuner);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Tuner=%d", usbvision_device_data[0].Tuner);
+ sscanf(parse,"%d",&usbvision_device_data[0].TunerType);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "TunerType=%d", usbvision_device_data[0].TunerType);
+ sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg1);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Vin_Reg1=%d", usbvision_device_data[0].Vin_Reg1);
+ sscanf(parse,"%d",&usbvision_device_data[0].Vin_Reg2);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Vin_Reg2=%d", usbvision_device_data[0].Vin_Reg2);
+ sscanf(parse,"%d",&usbvision_device_data[0].X_Offset);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "X_Offset=%d", usbvision_device_data[0].X_Offset);
+ sscanf(parse,"%d",&usbvision_device_data[0].Y_Offset);
+ goto2next(parse);
+ PDEBUG(DBG_PROBE, "Y_Offset=%d", usbvision_device_data[0].Y_Offset);
+ sscanf(parse,"%d",&usbvision_device_data[0].Dvi_yuv);
+ PDEBUG(DBG_PROBE, "Dvi_yuv=%d", usbvision_device_data[0].Dvi_yuv);
+
+ //add to usbvision_table also
+ usbvision_table[0].match_flags=USB_DEVICE_ID_MATCH_DEVICE;
+ usbvision_table[0].idVendor=usbvision_device_data[0].idVendor;
+ usbvision_table[0].idProduct=usbvision_device_data[0].idProduct;
+
+ }
+}
+
+
+
+/*
+ * usbvision_init()
+ *
+ * This code is run to initialize the driver.
+ *
+ */
+static int __init usbvision_init(void)
+{
+ int errCode;
+
+ PDEBUG(DBG_PROBE, "");
+
+ PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]");
+ PDEBUG(DBG_IO, "IO debugging is enabled [video]");
+ PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]");
+ PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]");
+
+ /* disable planar mode support unless compression enabled */
+ if (isocMode != ISOC_MODE_COMPRESS ) {
+ // FIXME : not the right way to set supported flag
+ usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420
+ usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P
+ }
+
+ customdevice_process();
+
+ errCode = usb_register(&usbvision_driver);
+
+ if (errCode == 0) {
+ info(DRIVER_DESC " : " USBVISION_VERSION_STRING);
+ PDEBUG(DBG_PROBE, "success");
+ }
+ return errCode;
+}
+
+static void __exit usbvision_exit(void)
+{
+ PDEBUG(DBG_PROBE, "");
+
+ usb_deregister(&usbvision_driver);
+ PDEBUG(DBG_PROBE, "success");
+}
+
+module_init(usbvision_init);
+module_exit(usbvision_exit);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
new file mode 100644
index 00000000000..e2bcaba9387
--- /dev/null
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -0,0 +1,531 @@
+/*
+ * USBVISION.H
+ * usbvision header file
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ * Dwaine Garden <dwainegarden@rogers.com>
+ *
+ *
+ * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ * v4l2 conversion by Thierry Merle <thierry.merle@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef __LINUX_USBVISION_H
+#define __LINUX_USBVISION_H
+
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <linux/videodev2.h>
+
+#define USBVISION_DEBUG /* Turn on debug messages */
+
+#ifndef VID_HARDWARE_USBVISION
+ #define VID_HARDWARE_USBVISION 34 /* USBVision Video Grabber */
+#endif
+
+#define USBVISION_PWR_REG 0x00
+ #define USBVISION_SSPND_EN (1 << 1)
+ #define USBVISION_RES2 (1 << 2)
+ #define USBVISION_PWR_VID (1 << 5)
+ #define USBVISION_E2_EN (1 << 7)
+#define USBVISION_CONFIG_REG 0x01
+#define USBVISION_ADRS_REG 0x02
+#define USBVISION_ALTER_REG 0x03
+#define USBVISION_FORCE_ALTER_REG 0x04
+#define USBVISION_STATUS_REG 0x05
+#define USBVISION_IOPIN_REG 0x06
+ #define USBVISION_IO_1 (1 << 0)
+ #define USBVISION_IO_2 (1 << 1)
+ #define USBVISION_AUDIO_IN 0
+ #define USBVISION_AUDIO_TV 1
+ #define USBVISION_AUDIO_RADIO 2
+ #define USBVISION_AUDIO_MUTE 3
+#define USBVISION_SER_MODE 0x07
+#define USBVISION_SER_ADRS 0x08
+#define USBVISION_SER_CONT 0x09
+#define USBVISION_SER_DAT1 0x0A
+#define USBVISION_SER_DAT2 0x0B
+#define USBVISION_SER_DAT3 0x0C
+#define USBVISION_SER_DAT4 0x0D
+#define USBVISION_EE_DATA 0x0E
+#define USBVISION_EE_LSBAD 0x0F
+#define USBVISION_EE_CONT 0x10
+#define USBVISION_DRM_CONT 0x12
+ #define USBVISION_REF (1 << 0)
+ #define USBVISION_RES_UR (1 << 2)
+ #define USBVISION_RES_FDL (1 << 3)
+ #define USBVISION_RES_VDW (1 << 4)
+#define USBVISION_DRM_PRM1 0x13
+#define USBVISION_DRM_PRM2 0x14
+#define USBVISION_DRM_PRM3 0x15
+#define USBVISION_DRM_PRM4 0x16
+#define USBVISION_DRM_PRM5 0x17
+#define USBVISION_DRM_PRM6 0x18
+#define USBVISION_DRM_PRM7 0x19
+#define USBVISION_DRM_PRM8 0x1A
+#define USBVISION_VIN_REG1 0x1B
+ #define USBVISION_8_422_SYNC 0x01
+ #define USBVISION_16_422_SYNC 0x02
+ #define USBVISION_VSNC_POL (1 << 3)
+ #define USBVISION_HSNC_POL (1 << 4)
+ #define USBVISION_FID_POL (1 << 5)
+ #define USBVISION_HVALID_PO (1 << 6)
+ #define USBVISION_VCLK_POL (1 << 7)
+#define USBVISION_VIN_REG2 0x1C
+ #define USBVISION_AUTO_FID (1 << 0)
+ #define USBVISION_NONE_INTER (1 << 1)
+ #define USBVISION_NOHVALID (1 << 2)
+ #define USBVISION_UV_ID (1 << 3)
+ #define USBVISION_FIX_2C (1 << 4)
+ #define USBVISION_SEND_FID (1 << 5)
+ #define USBVISION_KEEP_BLANK (1 << 7)
+#define USBVISION_LXSIZE_I 0x1D
+#define USBVISION_MXSIZE_I 0x1E
+#define USBVISION_LYSIZE_I 0x1F
+#define USBVISION_MYSIZE_I 0x20
+#define USBVISION_LX_OFFST 0x21
+#define USBVISION_MX_OFFST 0x22
+#define USBVISION_LY_OFFST 0x23
+#define USBVISION_MY_OFFST 0x24
+#define USBVISION_FRM_RATE 0x25
+#define USBVISION_LXSIZE_O 0x26
+#define USBVISION_MXSIZE_O 0x27
+#define USBVISION_LYSIZE_O 0x28
+#define USBVISION_MYSIZE_O 0x29
+#define USBVISION_FILT_CONT 0x2A
+#define USBVISION_VO_MODE 0x2B
+#define USBVISION_INTRA_CYC 0x2C
+#define USBVISION_STRIP_SZ 0x2D
+#define USBVISION_FORCE_INTRA 0x2E
+#define USBVISION_FORCE_UP 0x2F
+#define USBVISION_BUF_THR 0x30
+#define USBVISION_DVI_YUV 0x31
+#define USBVISION_AUDIO_CONT 0x32
+#define USBVISION_AUD_PK_LEN 0x33
+#define USBVISION_BLK_PK_LEN 0x34
+#define USBVISION_PCM_THR1 0x38
+#define USBVISION_PCM_THR2 0x39
+#define USBVISION_DIST_THR_L 0x3A
+#define USBVISION_DIST_THR_H 0x3B
+#define USBVISION_MAX_DIST_L 0x3C
+#define USBVISION_MAX_DIST_H 0x3D
+#define USBVISION_OP_CODE 0x33
+
+#define MAX_BYTES_PER_PIXEL 4
+
+#define MIN_FRAME_WIDTH 64
+#define MAX_USB_WIDTH 320 //384
+#define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/
+
+#define MIN_FRAME_HEIGHT 48
+#define MAX_USB_HEIGHT 240 //288
+#define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/
+
+#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
+#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
+
+#define USBVISION_URB_FRAMES 32
+#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023
+
+#define USBVISION_NUM_HEADERMARKER 20
+#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */
+#define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */
+
+#define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds
+
+
+#define FRAMERATE_MIN 0
+#define FRAMERATE_MAX 31
+
+enum {
+ ISOC_MODE_YUV422 = 0x03,
+ ISOC_MODE_YUV420 = 0x14,
+ ISOC_MODE_COMPRESS = 0x60,
+};
+
+/* This macro restricts an int variable to an inclusive range */
+#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+
+/*
+ * We use macros to do YUV -> RGB conversion because this is
+ * very important for speed and totally unimportant for size.
+ *
+ * YUV -> RGB Conversion
+ * ---------------------
+ *
+ * B = 1.164*(Y-16) + 2.018*(V-128)
+ * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
+ * R = 1.164*(Y-16) + 1.596*(U-128)
+ *
+ * If you fancy integer arithmetics (as you should), hear this:
+ *
+ * 65536*B = 76284*(Y-16) + 132252*(V-128)
+ * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128)
+ * 65536*R = 76284*(Y-16) + 104595*(U-128)
+ *
+ * Make sure the output values are within [0..255] range.
+ */
+#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
+#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
+ int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
+ mm_y = (my) - 16; \
+ mm_u = (mu) - 128; \
+ mm_v = (mv) - 128; \
+ mm_yc= mm_y * 76284; \
+ mm_b = (mm_yc + 132252*mm_v ) >> 16; \
+ mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \
+ mm_r = (mm_yc + 104595*mm_u ) >> 16; \
+ mb = LIMIT_RGB(mm_b); \
+ mg = LIMIT_RGB(mm_g); \
+ mr = LIMIT_RGB(mm_r); \
+}
+
+/* Debugging aid */
+#define USBVISION_SAY_AND_WAIT(what) { \
+ wait_queue_head_t wq; \
+ init_waitqueue_head(&wq); \
+ printk(KERN_INFO "Say: %s\n", what); \
+ interruptible_sleep_on_timeout (&wq, HZ*3); \
+}
+
+/*
+ * This macro checks if usbvision is still operational. The 'usbvision'
+ * pointer must be valid, usbvision->dev must be valid, we are not
+ * removing the device and the device has not erred on us.
+ */
+#define USBVISION_IS_OPERATIONAL(udevice) (\
+ (udevice != NULL) && \
+ ((udevice)->dev != NULL) && \
+ ((udevice)->last_error == 0) && \
+ (!(udevice)->remove_pending))
+
+#define I2C_USB_ADAP_MAX 16
+
+/* ----------------------------------------------------------------- */
+/* usbvision video structures */
+/* ----------------------------------------------------------------- */
+enum ScanState {
+ ScanState_Scanning, /* Scanning for header */
+ ScanState_Lines /* Parsing lines */
+};
+
+/* Completion states of the data parser */
+enum ParseState {
+ ParseState_Continue, /* Just parse next item */
+ ParseState_NextFrame, /* Frame done, send it to V4L */
+ ParseState_Out, /* Not enough data for frame */
+ ParseState_EndParse /* End parsing */
+};
+
+enum FrameState {
+ FrameState_Unused, /* Unused (no MCAPTURE) */
+ FrameState_Ready, /* Ready to start grabbing */
+ FrameState_Grabbing, /* In the process of being grabbed into */
+ FrameState_Done, /* Finished grabbing, but not been synced yet */
+ FrameState_DoneHold, /* Are syncing or reading */
+ FrameState_Error, /* Something bad happened while processing */
+};
+
+/* stream states */
+enum StreamState {
+ Stream_Off, /* Driver streaming is completely OFF */
+ Stream_Idle, /* Driver streaming is ready to be put ON by the application */
+ Stream_Interrupt, /* Driver streaming must be interrupted */
+ Stream_On, /* Driver streaming is put ON by the application */
+};
+
+enum IsocState {
+ IsocState_InFrame, /* Isoc packet is member of frame */
+ IsocState_NoFrame, /* Isoc packet is not member of any frame */
+};
+
+struct usb_device;
+
+struct usbvision_sbuf {
+ char *data;
+ struct urb *urb;
+};
+
+#define USBVISION_MAGIC_1 0x55
+#define USBVISION_MAGIC_2 0xAA
+#define USBVISION_HEADER_LENGTH 0x0c
+#define USBVISION_SAA7111_ADDR 0x48
+#define USBVISION_SAA7113_ADDR 0x4a
+#define USBVISION_IIC_LRACK 0x20
+#define USBVISION_IIC_LRNACK 0x30
+#define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7)
+
+struct usbvision_v4l2_format_st {
+ int supported;
+ int bytes_per_pixel;
+ int depth;
+ int format;
+ char *desc;
+};
+#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format)
+
+struct usbvision_frame_header {
+ unsigned char magic_1; /* 0 magic */
+ unsigned char magic_2; /* 1 magic */
+ unsigned char headerLength; /* 2 */
+ unsigned char frameNum; /* 3 */
+ unsigned char framePhase; /* 4 */
+ unsigned char frameLatency; /* 5 */
+ unsigned char dataFormat; /* 6 */
+ unsigned char formatParam; /* 7 */
+ unsigned char frameWidthLo; /* 8 */
+ unsigned char frameWidthHi; /* 9 */
+ unsigned char frameHeightLo; /* 10 */
+ unsigned char frameHeightHi; /* 11 */
+ __u16 frameWidth; /* 8 - 9 after endian correction*/
+ __u16 frameHeight; /* 10 - 11 after endian correction*/
+};
+
+/* tvnorms */
+struct usbvision_tvnorm {
+ char *name;
+ v4l2_std_id id;
+ /* mode for saa7113h */
+ int mode;
+};
+
+struct usbvision_frame {
+ char *data; /* Frame buffer */
+ struct usbvision_frame_header isocHeader; /* Header from stream */
+
+ int width; /* Width application is expecting */
+ int height; /* Height */
+ int index; /* Frame index */
+ int frmwidth; /* Width the frame actually is */
+ int frmheight; /* Height */
+
+ volatile int grabstate; /* State of grabbing */
+ int scanstate; /* State of scanning */
+
+ struct list_head frame;
+
+ int curline; /* Line of frame we're working on */
+
+ long scanlength; /* uncompressed, raw data length of frame */
+ long bytes_read; /* amount of scanlength that has been read from data */
+ struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/
+ int v4l2_linesize; /* bytes for one videoline*/
+ struct timeval timestamp;
+ int sequence; // How many video frames we send to user
+};
+
+#define CODEC_SAA7113 7113
+#define CODEC_SAA7111 7111
+#define BRIDGE_NT1003 1003
+#define BRIDGE_NT1004 1004
+#define BRIDGE_NT1005 1005
+
+struct usbvision_device_data_st {
+ int idVendor;
+ int idProduct;
+ int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
+ int Codec;
+ int VideoChannels;
+ __u64 VideoNorm;
+ int AudioChannels;
+ int Radio;
+ int vbi;
+ int Tuner;
+ int TunerType;
+ int Vin_Reg1;
+ int Vin_Reg2;
+ int X_Offset;
+ int Y_Offset;
+ int Dvi_yuv;
+ char *ModelString;
+};
+
+/* Declared on usbvision-cards.c */
+extern struct usbvision_device_data_st usbvision_device_data[];
+extern struct usb_device_id usbvision_table[];
+
+struct usb_usbvision {
+ struct video_device *vdev; /* Video Device */
+ struct video_device *rdev; /* Radio Device */
+ struct video_device *vbi; /* VBI Device */
+
+ /* i2c Declaration Section*/
+ struct i2c_adapter i2c_adap;
+ struct i2c_client i2c_client;
+
+ struct urb *ctrlUrb;
+ unsigned char ctrlUrbBuffer[8];
+ int ctrlUrbBusy;
+ struct usb_ctrlrequest ctrlUrbSetup;
+ wait_queue_head_t ctrlUrb_wq; // Processes waiting
+ struct semaphore ctrlUrbLock;
+
+ /* configuration part */
+ int have_tuner;
+ int tuner_type;
+ int tuner_addr;
+ int bridgeType; // NT1003, NT1004, NT1005
+ int channel;
+ int radio;
+ int video_inputs; // # of inputs
+ unsigned long freq;
+ int AudioMute;
+ int AudioChannel;
+ int isocMode; // format of video data for the usb isoc-transfer
+ unsigned int nr; // Number of the device
+
+ /* Device structure */
+ struct usb_device *dev;
+ unsigned char iface; /* Video interface number */
+ unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */
+ unsigned char Vin_Reg2_Preset;
+ struct semaphore lock;
+ struct timer_list powerOffTimer;
+ struct work_struct powerOffWork;
+ int power; /* is the device powered on? */
+ int user; /* user count for exclusive use */
+ int initialized; /* Had we already sent init sequence? */
+ int DevModel; /* What type of USBVISION device we got? */
+ enum StreamState streaming; /* Are we streaming Isochronous? */
+ int last_error; /* What calamity struck us? */
+ int curwidth; /* width of the frame the device is currently set to*/
+ int curheight; /* height of the frame the device is currently set to*/
+ int stretch_width; /* stretch-factor for frame width (from usb to screen)*/
+ int stretch_height; /* stretch-factor for frame height (from usb to screen)*/
+ char *fbuf; /* Videodev buffer area for mmap*/
+ int max_frame_size; /* Bytes in one video frame */
+ int fbuf_size; /* Videodev buffer size */
+ spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */
+ struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */
+ wait_queue_head_t wait_frame; /* Processes waiting */
+ wait_queue_head_t wait_stream; /* Processes waiting */
+ struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header
+ struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer
+ struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering
+ volatile int remove_pending; /* If set then about to exit */
+
+ /* Scratch space from the Isochronous Pipe.*/
+ unsigned char *scratch;
+ int scratch_read_ptr;
+ int scratch_write_ptr;
+ int scratch_headermarker[USBVISION_NUM_HEADERMARKER];
+ int scratch_headermarker_read_ptr;
+ int scratch_headermarker_write_ptr;
+ enum IsocState isocstate;
+ struct usbvision_v4l2_format_st palette;
+
+ struct v4l2_capability vcap; /* Video capabilities */
+ unsigned int ctl_input; /* selected input */
+ struct usbvision_tvnorm *tvnorm; /* selected tv norm */
+ unsigned char video_endp; /* 0x82 for USBVISION devices based */
+
+ // Decompression stuff:
+ unsigned char *IntraFrameBuffer; /* Buffer for reference frame */
+ int BlockPos; //for test only
+ int requestIntra; // 0 = normal; 1 = intra frame is requested;
+ int lastIsocFrameNum; // check for lost isoc frames
+ int isocPacketSize; // need to calculate usedBandwidth
+ int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel
+ int comprLevel; // How strong (100) or weak (0) is compression
+ int lastComprLevel; // How strong (100) or weak (0) was compression
+ int usb_bandwidth; /* Mbit/s */
+
+ /* Statistics that can be overlayed on the screen */
+ unsigned long isocUrbCount; // How many URBs we received so far
+ unsigned long urb_length; /* Length of last URB */
+ unsigned long isocDataCount; /* How many bytes we received */
+ unsigned long header_count; /* How many frame headers we found */
+ unsigned long scratch_ovf_count; /* How many times we overflowed scratch */
+ unsigned long isocSkipCount; /* How many empty ISO packets received */
+ unsigned long isocErrCount; /* How many bad ISO packets received */
+ unsigned long isocPacketCount; // How many packets we totally got
+ unsigned long timeInIrq; // How long do we need for interrupt
+ int isocMeasureBandwidthCount;
+ int frame_num; // How many video frames we send to user
+ int maxStripLen; // How big is the biggest strip
+ int comprBlockPos;
+ int stripLenErrors; // How many times was BlockPos greater than StripLen
+ int stripMagicErrors;
+ int stripLineNumberErrors;
+ int ComprBlockTypes[4];
+};
+
+
+/* --------------------------------------------------------------- */
+/* defined in usbvision-i2c.c */
+/* i2c-algo-usb declaration */
+/* --------------------------------------------------------------- */
+
+int usbvision_i2c_usb_del_bus(struct i2c_adapter *);
+
+
+/* ----------------------------------------------------------------------- */
+/* usbvision specific I2C functions */
+/* ----------------------------------------------------------------------- */
+int usbvision_init_i2c(struct usb_usbvision *usbvision);
+void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg);
+
+/* defined in usbvision-core.c */
+void usbvision_rvfree(void *mem, unsigned long size);
+int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
+int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+ unsigned char value);
+
+int usbvision_frames_alloc(struct usb_usbvision *usbvision);
+void usbvision_frames_free(struct usb_usbvision *usbvision);
+int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
+void usbvision_scratch_free(struct usb_usbvision *usbvision);
+int usbvision_decompress_alloc(struct usb_usbvision *usbvision);
+void usbvision_decompress_free(struct usb_usbvision *usbvision);
+
+int usbvision_setup(struct usb_usbvision *usbvision,int format);
+int usbvision_init_isoc(struct usb_usbvision *usbvision);
+int usbvision_restart_isoc(struct usb_usbvision *usbvision);
+void usbvision_stop_isoc(struct usb_usbvision *usbvision);
+
+int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
+int usbvision_audio_off(struct usb_usbvision *usbvision);
+
+int usbvision_begin_streaming(struct usb_usbvision *usbvision);
+void usbvision_empty_framequeues(struct usb_usbvision *dev);
+int usbvision_stream_interrupt(struct usb_usbvision *dev);
+
+int usbvision_muxsel(struct usb_usbvision *usbvision, int channel);
+int usbvision_set_input(struct usb_usbvision *usbvision);
+int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
+
+void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision);
+void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision);
+void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision);
+int usbvision_power_off(struct usb_usbvision *usbvision);
+int usbvision_power_on(struct usb_usbvision *usbvision);
+
+#endif /* __LINUX_USBVISION_H */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 1d899e2db39..8a13e595304 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -350,6 +350,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
struct video_buffer *buffer = arg;
memset(buffer, 0, sizeof(*buffer));
+ memset(&fbuf2, 0, sizeof(fbuf2));
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
if (err < 0) {
@@ -616,6 +617,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSPICT: /* set tone controls & partial capture format */
{
struct video_picture *pict = arg;
+ memset(&fbuf2, 0, sizeof(fbuf2));
set_v4l_control(inode, file,
V4L2_CID_BRIGHTNESS, pict->brightness, drv);
@@ -708,12 +710,22 @@ v4l_compat_translate_ioctl(struct inode *inode,
}
case VIDIOCSTUNER: /* select a tuner input */
{
- err = 0;
+ struct video_tuner *tun = arg;
+ struct v4l2_tuner t;
+ memset(&t,0,sizeof(t));
+
+ t.index=tun->tuner;
+
+ err = drv(inode, file, VIDIOC_S_INPUT, &t);
+ if (err < 0)
+ dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
+
break;
}
case VIDIOCGFREQ: /* get frequency */
{
unsigned long *freq = arg;
+ memset(&freq2,0,sizeof(freq2));
freq2.tuner = 0;
err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
@@ -726,8 +738,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSFREQ: /* set frequency */
{
unsigned long *freq = arg;
+ memset(&freq2,0,sizeof(freq2));
- freq2.tuner = 0;
drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
freq2.frequency = *freq;
err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
@@ -738,6 +750,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGAUDIO: /* get audio properties/controls */
{
struct video_audio *aud = arg;
+ memset(&aud2,0,sizeof(aud2));
err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
@@ -898,6 +911,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
int *i = arg;
+ memset(&buf2,0,sizeof(buf2));
buf2.index = *i;
buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 78d28b03ec9..b87d571e046 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -87,6 +87,85 @@ MODULE_LICENSE("GPL");
*/
+char *v4l2_norm_to_name(v4l2_std_id id)
+{
+ char *name;
+ u32 myid = id;
+
+ /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
+ 64 bit comparations. So, on that architecture, with some gcc variants,
+ compilation fails. Currently, the max value is 30bit wide.
+ */
+ BUG_ON(myid != id);
+
+ switch (myid) {
+ case V4L2_STD_PAL:
+ name="PAL"; break;
+ case V4L2_STD_PAL_BG:
+ name="PAL-BG"; break;
+ case V4L2_STD_PAL_DK:
+ name="PAL-DK"; break;
+ case V4L2_STD_PAL_B:
+ name="PAL-B"; break;
+ case V4L2_STD_PAL_B1:
+ name="PAL-B1"; break;
+ case V4L2_STD_PAL_G:
+ name="PAL-G"; break;
+ case V4L2_STD_PAL_H:
+ name="PAL-H"; break;
+ case V4L2_STD_PAL_I:
+ name="PAL-I"; break;
+ case V4L2_STD_PAL_D:
+ name="PAL-D"; break;
+ case V4L2_STD_PAL_D1:
+ name="PAL-D1"; break;
+ case V4L2_STD_PAL_K:
+ name="PAL-K"; break;
+ case V4L2_STD_PAL_M:
+ name="PAL-M"; break;
+ case V4L2_STD_PAL_N:
+ name="PAL-N"; break;
+ case V4L2_STD_PAL_Nc:
+ name="PAL-Nc"; break;
+ case V4L2_STD_PAL_60:
+ name="PAL-60"; break;
+ case V4L2_STD_NTSC:
+ name="NTSC"; break;
+ case V4L2_STD_NTSC_M:
+ name="NTSC-M"; break;
+ case V4L2_STD_NTSC_M_JP:
+ name="NTSC-M-JP"; break;
+ case V4L2_STD_NTSC_443:
+ name="NTSC-443"; break;
+ case V4L2_STD_NTSC_M_KR:
+ name="NTSC-M-KR"; break;
+ case V4L2_STD_SECAM:
+ name="SECAM"; break;
+ case V4L2_STD_SECAM_DK:
+ name="SECAM-DK"; break;
+ case V4L2_STD_SECAM_B:
+ name="SECAM-B"; break;
+ case V4L2_STD_SECAM_D:
+ name="SECAM-D"; break;
+ case V4L2_STD_SECAM_G:
+ name="SECAM-G"; break;
+ case V4L2_STD_SECAM_H:
+ name="SECAM-H"; break;
+ case V4L2_STD_SECAM_K:
+ name="SECAM-K"; break;
+ case V4L2_STD_SECAM_K1:
+ name="SECAM-K1"; break;
+ case V4L2_STD_SECAM_L:
+ name="SECAM-L"; break;
+ case V4L2_STD_SECAM_LC:
+ name="SECAM-LC"; break;
+ default:
+ name="Unknown"; break;
+ }
+
+ return name;
+}
+
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs,
@@ -184,11 +263,13 @@ char *v4l2_field_names[] = {
};
char *v4l2_type_names[] = {
- [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
- [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
- [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
- [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
- [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
+ [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap",
+ [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over",
+ [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
+ [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
+ [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
+ [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
+ [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out",
};
static char *v4l2_memory_names[] = {
@@ -1451,6 +1532,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
/* ----------------------------------------------------------------- */
+EXPORT_SYMBOL(v4l2_norm_to_name);
EXPORT_SYMBOL(v4l2_video_std_construct);
EXPORT_SYMBOL(v4l2_prio_init);
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index f429f49901b..6504a586684 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -700,6 +700,7 @@ videobuf_qbuf(struct videobuf_queue *q,
goto done;
}
if (buf->state == STATE_QUEUED ||
+ buf->state == STATE_PREPARED ||
buf->state == STATE_ACTIVE) {
dprintk(1,"qbuf: buffer is already queued or active.\n");
goto done;
@@ -1229,7 +1230,7 @@ videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
vaddr,vma->vm_start,vma->vm_end);
if (vaddr > vma->vm_end)
return NOPAGE_SIGBUS;
- page = alloc_page(GFP_USER);
+ page = alloc_page(GFP_USER | __GFP_DMA32);
if (!page)
return NOPAGE_OOM;
clear_user_page(page_address(page), vaddr, page);
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
index 2ae3fb25063..290e6413565 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/videocodec.c
@@ -346,7 +346,7 @@ videocodec_build_table (void)
size);
kfree(videocodec_buf);
- videocodec_buf = (char *) kmalloc(size, GFP_KERNEL);
+ videocodec_buf = kmalloc(size, GFP_KERNEL);
i = 0;
i += scnprintf(videocodec_buf + i, size - 1,
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index d424a4129d6..6a0e8ca7294 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -105,7 +105,7 @@ static DEFINE_MUTEX(videodev_lock);
struct video_device* video_devdata(struct file *file)
{
- return video_device[iminor(file->f_dentry->d_inode)];
+ return video_device[iminor(file->f_path.dentry->d_inode)];
}
/*
@@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
"bytesused=%d, flags=0x%08d, "
- "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
+ "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
(p->timestamp.tv_sec/3600),
(int)(p->timestamp.tv_sec/60)%60,
(int)(p->timestamp.tv_sec%60),
@@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
p->bytesused,p->flags,
p->field,p->sequence,
prt_names(p->memory,v4l2_memory_names),
- p->m.userptr);
+ p->m.userptr, p->length);
dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
"flags=0x%08d, frames=%d, userbits=0x%08x\n",
tc->hours,tc->minutes,tc->seconds,
@@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s,
static inline void v4l_print_pix_fmt (struct video_device *vfd,
struct v4l2_pix_format *fmt)
{
- dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, "
+ dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, "
"bytesperline=%d sizeimage=%d, colorspace=%d\n",
- fmt->width,fmt->height,fmt->pixelformat,
+ fmt->width,fmt->height,
+ (fmt->pixelformat & 0xff),
+ (fmt->pixelformat >> 8) & 0xff,
+ (fmt->pixelformat >> 16) & 0xff,
+ (fmt->pixelformat >> 24) & 0xff,
prt_names(fmt->field,v4l2_field_names_FIXME),
fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
};
@@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
v4l_print_ioctl(vfd->name, cmd);
}
+ if (_IOC_TYPE(cmd)=='v')
+ return v4l_compat_translate_ioctl(inode,file,cmd,arg,
+ __video_do_ioctl);
+
switch(cmd) {
/* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP:
@@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
if (!ret)
dbgarg (cmd, "index=%d, type=%d, flags=%d, "
- "description=%s,"
- " pixelformat=0x%8x\n",
+ "pixelformat=%c%c%c%c, description='%s'\n",
f->index, f->type, f->flags,
- f->description,
- f->pixelformat);
-
+ (f->pixelformat & 0xff),
+ (f->pixelformat >> 8) & 0xff,
+ (f->pixelformat >> 16) & 0xff,
+ (f->pixelformat >> 24) & 0xff,
+ f->description);
break;
}
case VIDIOC_G_FMT:
@@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *p = arg;
- unsigned int index = p->index;
+ v4l2_std_id id = vfd->tvnorms,curr_id=0;
+ unsigned int index = p->index,i;
- if (!vfd->tvnormsize) {
- printk (KERN_WARNING "%s: no TV norms defined!\n",
- vfd->name);
+ if (index<0) {
+ ret=-EINVAL;
break;
}
- if (index<0 || index >= vfd->tvnormsize) {
- ret=-EINVAL;
- break;
+ /* Return norm array on a canonical way */
+ for (i=0;i<= index && id; i++) {
+ if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
+ curr_id = V4L2_STD_PAL;
+ } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
+ curr_id = V4L2_STD_PAL_BG;
+ } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
+ curr_id = V4L2_STD_PAL_DK;
+ } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
+ curr_id = V4L2_STD_PAL_B;
+ } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
+ curr_id = V4L2_STD_PAL_B1;
+ } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
+ curr_id = V4L2_STD_PAL_G;
+ } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
+ curr_id = V4L2_STD_PAL_H;
+ } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
+ curr_id = V4L2_STD_PAL_I;
+ } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
+ curr_id = V4L2_STD_PAL_D;
+ } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
+ curr_id = V4L2_STD_PAL_D1;
+ } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
+ curr_id = V4L2_STD_PAL_K;
+ } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
+ curr_id = V4L2_STD_PAL_M;
+ } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
+ curr_id = V4L2_STD_PAL_N;
+ } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
+ curr_id = V4L2_STD_PAL_Nc;
+ } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
+ curr_id = V4L2_STD_PAL_60;
+ } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+ curr_id = V4L2_STD_NTSC;
+ } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
+ curr_id = V4L2_STD_NTSC_M;
+ } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
+ curr_id = V4L2_STD_NTSC_M_JP;
+ } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
+ curr_id = V4L2_STD_NTSC_443;
+ } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
+ curr_id = V4L2_STD_NTSC_M_KR;
+ } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
+ curr_id = V4L2_STD_SECAM;
+ } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
+ curr_id = V4L2_STD_SECAM_DK;
+ } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
+ curr_id = V4L2_STD_SECAM_B;
+ } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
+ curr_id = V4L2_STD_SECAM_D;
+ } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
+ curr_id = V4L2_STD_SECAM_G;
+ } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
+ curr_id = V4L2_STD_SECAM_H;
+ } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
+ curr_id = V4L2_STD_SECAM_K;
+ } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
+ curr_id = V4L2_STD_SECAM_K1;
+ } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
+ curr_id = V4L2_STD_SECAM_L;
+ } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
+ curr_id = V4L2_STD_SECAM_LC;
+ } else {
+ break;
+ }
+ id &= ~curr_id;
}
- v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
- vfd->tvnorms[p->index].name);
+ if (i<=index)
+ return -EINVAL;
+
+ v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
p->index = index;
dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
@@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
case VIDIOC_S_STD:
{
- v4l2_std_id *id = arg;
- unsigned int i;
-
- if (!vfd->tvnormsize) {
- printk (KERN_WARNING "%s: no TV norms defined!\n",
- vfd->name);
- break;
- }
+ v4l2_std_id *id = arg,norm;
dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
- /* First search for exact match */
- for (i = 0; i < vfd->tvnormsize; i++)
- if (*id == vfd->tvnorms[i].id)
- break;
- /* Then for a generic video std that contains desired std */
- if (i == vfd->tvnormsize)
- for (i = 0; i < vfd->tvnormsize; i++)
- if (*id & vfd->tvnorms[i].id)
- break;
- if (i == vfd->tvnormsize) {
+ norm = (*id) & vfd->tvnorms;
+ if ( vfd->tvnorms && !norm) /* Check if std is supported */
break;
- }
/* Calls the specific handler */
if (vfd->vidioc_s_std)
- ret=vfd->vidioc_s_std(file, fh, i);
+ ret=vfd->vidioc_s_std(file, fh, &norm);
else
ret=-EINVAL;
/* Updates standard information */
- if (!ret)
- vfd->current_norm=*id;
+ if (ret>=0)
+ vfd->current_norm=norm;
break;
}
@@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *p=arg;
+ __u32 index=p->index;
if (!vfd->vidioc_g_audio)
break;
+
+ memset(p,0,sizeof(*p));
+ p->index=index;
dbgarg(cmd, "Get for index=%d\n", p->index);
ret=vfd->vidioc_g_audio(file, fh, p);
if (!ret)
@@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_g_parm(file, fh, p);
} else {
struct v4l2_standard s;
- int i;
-
- if (!vfd->tvnormsize) {
- printk (KERN_WARNING "%s: no TV norms defined!\n",
- vfd->name);
- break;
- }
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- for (i = 0; i < vfd->tvnormsize; i++)
- if (vfd->tvnorms[i].id == vfd->current_norm)
- break;
- if (i >= vfd->tvnormsize)
- return -EINVAL;
-
v4l2_video_std_construct(&s, vfd->current_norm,
- vfd->tvnorms[i].name);
+ v4l2_norm_to_name(vfd->current_norm));
memset(p,0,sizeof(*p));
@@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *p=arg;
+ __u32 index=p->index;
+
if (!vfd->vidioc_g_tuner)
break;
+
+ memset(p,0,sizeof(*p));
+ p->index=index;
+
ret=vfd->vidioc_g_tuner(file, fh, p);
if (!ret)
dbgarg (cmd, "index=%d, name=%s, type=%d, "
@@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_frequency *p=arg;
if (!vfd->vidioc_g_frequency)
break;
+
+ memset(p,0,sizeof(*p));
+
ret=vfd->vidioc_g_frequency(file, fh, p);
if (!ret)
dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
@@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_log_status(file, fh);
break;
}
-
- /* --- Others --------------------------------------------- */
-
- default:
- ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl);
- }
+ } /* switch */
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
if (ret<0) {
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 6b6dff4d236..a373c142e74 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -782,7 +782,7 @@ static int vino_i2c_add_bus(void)
static int vino_i2c_del_bus(void)
{
- return i2c_sgi_del_bus(&vino_i2c_adapter);
+ return i2c_del_adapter(&vino_i2c_adapter);
}
static int i2c_camera_command(unsigned int cmd, void *arg)
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 9986de5cb3d..d4cf5566673 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -270,10 +270,15 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
char *p,*s,*basep;
struct page *pg;
u8 chr,r,g,b,color;
+ unsigned long flags;
+ spinlock_t spinlock;
+
+ spin_lock_init(&spinlock);
/* Get first addr pointed to pixel position */
oldpg=get_addr_pos(pos,pages,to_addr);
pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT);
+ spin_lock_irqsave(&spinlock,flags);
basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
/* We will just duplicate the second pixel at the packet */
@@ -376,6 +381,8 @@ static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
end:
kunmap_atomic(basep, KM_BOUNCE_READ);
+ spin_unlock_irqrestore(&spinlock,flags);
+
}
static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
{
@@ -535,9 +542,9 @@ static int vivi_start_thread(struct vivi_dmaqueue *dma_q)
dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
- if (dma_q->kthread == NULL) {
+ if (IS_ERR(dma_q->kthread)) {
printk(KERN_ERR "vivi: kernel_thread() failed\n");
- return -EINVAL;
+ return PTR_ERR(dma_q->kthread);
}
dprintk(1,"returning from %s\n",__FUNCTION__);
return 0;
@@ -1044,16 +1051,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return (0);
}
-static struct v4l2_tvnorm tvnorms[] = {
- {
- .name = "NTSC-M",
- .id = V4L2_STD_NTSC_M,
- }
-};
-
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a)
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i)
{
-
return 0;
}
@@ -1333,8 +1332,8 @@ static struct video_device vivi = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
- .tvnorms = tvnorms,
- .tvnormsize = ARRAY_SIZE(tvnorms),
+ .tvnorms = V4L2_STD_NTSC_M,
+ .current_norm = V4L2_STD_NTSC_M,
};
/* -----------------------------------------------------------------
Initialization and module stuff
@@ -1361,8 +1360,6 @@ static int __init vivi_init(void)
dev->vidq.timeout.data = (unsigned long)dev;
init_timer(&dev->vidq.timeout);
- vivi.current_norm = tvnorms[0].id;
-
ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);
printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
return ret;
@@ -1373,7 +1370,9 @@ static void __exit vivi_exit(void)
struct vivi_dev *h;
struct list_head *list;
- list_for_each(list,&vivi_devlist) {
+ while (!list_empty(&vivi_devlist)) {
+ list = vivi_devlist.next;
+ list_del(list);
h = list_entry(list, struct vivi_dev, vivi_devlist);
kfree (h);
}
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 4bdc886abc4..8d14f308f17 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -789,7 +789,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCSPICT:
{
struct video_picture *vpic = arg;
- if (vpic->depth != 16 || vpic->palette != VIDEO_PALETTE_YUV422)
+ if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV))
return -EINVAL;
cam->brightness = vpic->brightness >> 8;
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index ddce2fb8342..9f403af7b04 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -1827,8 +1827,8 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
int err = 0;
/* Work around to avoid FP arithmetics */
- #define __SC(x) ((x) << 10)
- #define __UNSC(x) ((x) >> 10)
+ #define SC(x) ((x) << 10)
+ #define UNSC(x) ((x) >> 10)
/* Make sure we are using a supported resolution */
if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
@@ -1836,15 +1836,15 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
goto error;
/* Scaling factors */
- fw = __SC(win.width) / cam->maxwidth;
- fh = __SC(win.height) / cam->maxheight;
+ fw = SC(win.width) / cam->maxwidth;
+ fh = SC(win.height) / cam->maxheight;
/* Set up the width and height values used by the chip */
if ((win.width > cam->maxwidth) || (win.height > cam->maxheight)) {
cam->vpp_flag |= VPP_UPSCALE;
/* Calculate largest w,h mantaining the same w/h ratio */
- w = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh;
- h = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight;
+ w = (fw >= fh) ? cam->maxwidth : SC(win.width)/fh;
+ h = (fw >= fh) ? SC(win.height)/fw : cam->maxheight;
if (w < cam->minwidth) /* just in case */
w = cam->minwidth;
if (h < cam->minheight) /* just in case */
@@ -1861,8 +1861,8 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
/* Calculate cropped area manteining the right w/h ratio */
if (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE)) {
- cw = (fw >= fh) ? cam->maxwidth : __SC(win.width)/fh;
- ch = (fw >= fh) ? __SC(win.height)/fw : cam->maxheight;
+ cw = (fw >= fh) ? cam->maxwidth : SC(win.width)/fh;
+ ch = (fw >= fh) ? SC(win.height)/fw : cam->maxheight;
} else {
cw = w;
ch = h;
@@ -1901,8 +1901,8 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
/* We have to scale win.x and win.y offsets */
if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE))
|| (cam->vpp_flag & VPP_UPSCALE) ) {
- ax = __SC(win.x)/fw;
- ay = __SC(win.y)/fh;
+ ax = SC(win.x)/fw;
+ ay = SC(win.y)/fh;
} else {
ax = win.x;
ay = win.y;
@@ -1917,8 +1917,8 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
/* Adjust win.x, win.y */
if ( (cam->largeview && !(cam->vpp_flag & VPP_UPSCALE))
|| (cam->vpp_flag & VPP_UPSCALE) ) {
- win.x = __UNSC(ax*fw);
- win.y = __UNSC(ay*fh);
+ win.x = UNSC(ax*fw);
+ win.y = UNSC(ay*fh);
} else {
win.x = ax;
win.y = ay;
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 653822ce391..4d1eb2fba34 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -849,7 +849,7 @@ zoran_register_i2c (struct zoran *zr)
static void
zoran_unregister_i2c (struct zoran *zr)
{
- i2c_bit_del_bus((&zr->i2c_adapter));
+ i2c_del_adapter(&zr->i2c_adapter);
}
/* Check a zoran_params struct for correctness, insert default params */
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 168e431d7c7..b0752767ee4 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -429,7 +429,7 @@ zr36057_set_vfe (struct zoran *zr,
reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
reg |= (DispMode << ZR36057_VFESPFR_DispMode);
- if (format->palette != VIDEO_PALETTE_YUV422)
+ if (format->palette != VIDEO_PALETTE_YUV422 && format->palette != VIDEO_PALETTE_YUYV)
reg |= ZR36057_VFESPFR_LittleEndian;
/* RJ: I don't know, why the following has to be the opposite
* of the corresponding ZR36060 setting, but only this way
@@ -441,6 +441,7 @@ zr36057_set_vfe (struct zoran *zr,
reg |= ZR36057_VFESPFR_TopField;
switch (format->palette) {
+ case VIDEO_PALETTE_YUYV:
case VIDEO_PALETTE_YUV422:
reg |= ZR36057_VFESPFR_YUV422;
break;
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
index c7f6f648836..c374c76b375 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran_procfs.c
@@ -144,7 +144,7 @@ static int zoran_open(struct inode *inode, struct file *file)
static ssize_t zoran_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
- struct zoran *zr = PDE(file->f_dentry->d_inode)->data;
+ struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
char *string, *sp;
char *line, *ldelim, *varname, *svar, *tdelim;
@@ -165,7 +165,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
}
string[count] = 0;
dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
- ZR_DEVNAME(zr), file->f_dentry->d_name.name, count, zr);
+ ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
ldelim = " \t\n";
tdelim = "=";
line = strpbrk(sp, ldelim);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
deleted file mode 100644
index 0cbf564388a..00000000000
--- a/drivers/media/video/zr36120.c
+++ /dev/null
@@ -1,2079 +0,0 @@
-/*
- zr36120.c - Zoran 36120/36125 based framegrabbers
-
- Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#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>
-#include <linux/sched.h>
-#include <linux/video_decoder.h>
-
-#include <asm/uaccess.h>
-
-#include "tuner.h"
-#include "zr36120.h"
-#include "zr36120_mem.h"
-
-/* mark an required function argument unused - lintism */
-#define UNUSED(x) (void)(x)
-
-/* sensible default */
-#ifndef CARDTYPE
-#define CARDTYPE 0
-#endif
-
-/* Anybody who uses more than four? */
-#define ZORAN_MAX 4
-
-static unsigned int triton1=0; /* triton1 chipset? */
-static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE };
-static int video_nr = -1;
-static int vbi_nr = -1;
-
-static struct pci_device_id zr36120_pci_tbl[] = {
- { PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, zr36120_pci_tbl);
-
-MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>");
-MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber");
-MODULE_LICENSE("GPL");
-
-module_param(triton1, uint, 0);
-module_param_array(cardtype, uint, NULL, 0);
-module_param(video_nr, int, 0);
-module_param(vbi_nr, int, 0);
-
-static int zoran_cards;
-static struct zoran zorans[ZORAN_MAX];
-
-/*
- * the meaning of each element can be found in zr36120.h
- * Determining the value of gpdir/gpval can be tricky. The
- * best way is to run the card under the original software
- * and read the values from the general purpose registers
- * 0x28 and 0x2C. How you do that is left as an exercise
- * to the impatient reader :)
- */
-#define T 1 /* to separate the bools from the ints */
-#define F 0
-static struct tvcard tvcards[] = {
- /* reported working by <middelin@polyware.nl> */
-/*0*/ { "Trust Victor II",
- 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
- /* reported working by <Michael.Paxton@aihw.gov.au> */
-/*1*/ { "Aitech WaveWatcher TV-PCI",
- 3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } },
- /* reported working by ? */
-/*2*/ { "Genius Video Wonder PCI Video Capture Card",
- 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
- /* reported working by <Pascal.Gabriel@wanadoo.fr> */
-/*3*/ { "Guillemot Maxi-TV PCI",
- 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } },
- /* reported working by "Craig Whitmore <lennon@igrin.co.nz> */
-/*4*/ { "Quadrant Buster",
- 3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } },
- /* a debug entry which has all inputs mapped */
-/*5*/ { "ZR36120 based framegrabber (all inputs enabled)",
- 6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } }
-};
-#undef T
-#undef F
-#define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0]))
-
-#ifdef __sparc__
-#define ENDIANESS 0
-#else
-#define ENDIANESS ZORAN_VFEC_LE
-#endif
-
-static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = {
-/* n/a */ { "n/a", 0, 0 },
-/* GREY */ { "GRAY", 0, 0 },
-/* HI240 */ { "HI240", 0, 0 },
-/* RGB565 */ { "RGB565", ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 },
-/* RGB24 */ { "RGB24", ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 },
-/* RGB32 */ { "RGB32", ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 },
-/* RGB555 */ { "RGB555", ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 },
-/* YUV422 */ { "YUV422", ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 },
-/* YUYV */ { "YUYV", 0, 0 },
-/* UYVY */ { "UYVY", 0, 0 },
-/* YUV420 */ { "YUV420", 0, 0 },
-/* YUV411 */ { "YUV411", 0, 0 },
-/* RAW */ { "RAW", 0, 0 },
-/* YUV422P */ { "YUV422P", 0, 0 },
-/* YUV411P */ { "YUV411P", 0, 0 }};
-#define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0]))
-#undef ENDIANESS
-
-/* ----------------------------------------------------------------------- */
-/* ZORAN chipset detector */
-/* shamelessly stolen from bttv.c */
-/* Reason for beeing here: we need to detect if we are running on a */
-/* Triton based chipset, and if so, enable a certain bit */
-/* ----------------------------------------------------------------------- */
-static
-void __init handle_chipset(void)
-{
- /* Just in case some nut set this to something dangerous */
- if (triton1)
- triton1 = ZORAN_VDC_TRICOM;
-
- if (pci_pci_problems & PCIPCI_TRITON) {
- printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n");
- triton1 = ZORAN_VDC_TRICOM;
- }
-}
-
-/* ----------------------------------------------------------------------- */
-/* ZORAN functions */
-/* ----------------------------------------------------------------------- */
-
-static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i);
-
-#if 0 /* unused */
-static
-void zoran_dump(struct zoran *ztv)
-{
- char str[256];
- char *p=str; /* shut up, gcc! */
- int i;
-
- for (i=0; i<0x60; i+=4) {
- if ((i % 16) == 0) {
- if (i) printk("%s\n",str);
- p = str;
- p+= sprintf(str, KERN_DEBUG " %04x: ",i);
- }
- p += sprintf(p, "%08x ",zrread(i));
- }
-}
-#endif /* unused */
-
-static
-void reap_states(struct zoran* ztv)
-{
- /* count frames */
- ztv->fieldnr++;
-
- /*
- * Are we busy at all?
- * This depends on if there is a workqueue AND the
- * videotransfer is enabled on the chip...
- */
- if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN))
- {
- struct vidinfo* newitem;
-
- /* did we get a complete frame? */
- if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB)
- return;
-
-DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue));
-
- /* we are done with this buffer, tell everyone */
- ztv->workqueue->status = FBUFFER_DONE;
- ztv->workqueue->fieldnr = ztv->fieldnr;
- /* not good, here for BTTV_FIELDNR reasons */
- ztv->lastfieldnr = ztv->fieldnr;
-
- switch (ztv->workqueue->kindof) {
- case FBUFFER_GRAB:
- wake_up_interruptible(&ztv->grabq);
- break;
- case FBUFFER_VBI:
- wake_up_interruptible(&ztv->vbiq);
- break;
- default:
- printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof);
- }
-
- /* item completed, skip to next item in queue */
- write_lock(&ztv->lock);
- newitem = ztv->workqueue->next;
- ztv->workqueue->next = 0; /* mark completed */
- ztv->workqueue = newitem;
- write_unlock(&ztv->lock);
- }
-
- /*
- * ok, so it seems we have nothing in progress right now.
- * Lets see if we can find some work.
- */
- if (ztv->workqueue)
- {
- struct vidinfo* newitem;
-again:
-
-DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue));
-
- /* loadup the frame settings */
- read_lock(&ztv->lock);
- zoran_set_geo(ztv,ztv->workqueue);
- read_unlock(&ztv->lock);
-
- switch (ztv->workqueue->kindof) {
- case FBUFFER_GRAB:
- case FBUFFER_VBI:
- zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR);
- zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR);
- zror(ZORAN_VDC_VIDEN,ZORAN_VDC);
-
- /* start single-shot grab */
- zror(ZORAN_VSTR_GRAB, ZORAN_VSTR);
- break;
- default:
- printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof);
- write_lock(&ztv->lock);
- newitem = ztv->workqueue->next;
- ztv->workqueue->next = 0;
- ztv->workqueue = newitem;
- write_unlock(&ztv->lock);
- if (newitem)
- goto again; /* yeah, sure.. */
- }
- /* bye for now */
- return;
- }
-DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD));
-
- /*
- * What? Even the workqueue is empty? Am i really here
- * for nothing? Did i come all that way to... do nothing?
- */
-
- /* do we need to overlay? */
- if (test_bit(STATE_OVERLAY, &ztv->state))
- {
- /* are we already overlaying? */
- if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) ||
- !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN))
- {
-DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD));
-
- read_lock(&ztv->lock);
- zoran_set_geo(ztv,&ztv->overinfo);
- read_unlock(&ztv->lock);
-
- zror(ZORAN_OCR_OVLEN, ZORAN_OCR);
- zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR);
- zror(ZORAN_VDC_VIDEN,ZORAN_VDC);
- }
-
- /*
- * leave overlaying on, but turn interrupts off.
- */
- zrand(~ZORAN_ICR_EN,ZORAN_ICR);
- return;
- }
-
- /* do we have any VBI idle time processing? */
- if (test_bit(STATE_VBI, &ztv->state))
- {
- struct vidinfo* item;
- struct vidinfo* lastitem;
-
- /* protect the workqueue */
- write_lock(&ztv->lock);
- lastitem = ztv->workqueue;
- if (lastitem)
- while (lastitem->next) lastitem = lastitem->next;
- for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
- if (item->next == 0 && item->status == FBUFFER_FREE)
- {
-DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item));
- item->status = FBUFFER_BUSY;
- if (!lastitem)
- ztv->workqueue = item;
- else
- lastitem->next = item;
- lastitem = item;
- }
- write_unlock(&ztv->lock);
- if (ztv->workqueue)
- goto again; /* hey, _i_ graduated :) */
- }
-
- /*
- * Then we must be realy IDLE
- */
-DEBUG(printk(CARD_DEBUG "turning off\n",CARD));
- /* nothing further to do, disable DMA and further IRQs */
- zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
- zrand(~ZORAN_ICR_EN,ZORAN_ICR);
-}
-
-static
-void zoran_irq(int irq, void *dev_id)
-{
- u32 stat,estat;
- int count = 0;
- struct zoran *ztv = dev_id;
-
- UNUSED(irq);
- for (;;) {
- /* get/clear interrupt status bits */
- stat=zrread(ZORAN_ISR);
- estat=stat & zrread(ZORAN_ICR);
- if (!estat)
- return;
- zrwrite(estat,ZORAN_ISR);
- IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat));
- IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat));
-
- if (estat & ZORAN_ISR_CODE)
- {
- IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD));
- }
- if (estat & ZORAN_ISR_GIRQ0)
- {
- IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD));
- if (!ztv->card->usegirq1)
- reap_states(ztv);
- }
- if (estat & ZORAN_ISR_GIRQ1)
- {
- IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD));
- if (ztv->card->usegirq1)
- reap_states(ztv);
- }
-
- count++;
- if (count > 10)
- printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat);
- if (count > 20)
- {
- zrwrite(0, ZORAN_ICR);
- printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD);
- }
- }
-}
-
-static
-int zoran_muxsel(struct zoran* ztv, int channel, int norm)
-{
- int rv;
-
- /* set the new video norm */
- rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm);
- if (rv)
- return rv;
- ztv->norm = norm;
-
- /* map the given channel to the cards decoder's channel */
- channel = ztv->card->video_mux[channel] & CHANNEL_MASK;
-
- /* set the new channel */
- rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel);
- return rv;
-}
-
-/* Tell the interrupt handler what to to. */
-static
-void zoran_cap(struct zoran* ztv, int on)
-{
-DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state));
-
- if (on) {
- ztv->running = 1;
-
- /*
- * turn interrupts (back) on. The DMA will be enabled
- * inside the irq handler when it detects a restart.
- */
- zror(ZORAN_ICR_EN,ZORAN_ICR);
- }
- else {
- /*
- * turn both interrupts and DMA off
- */
- zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
- zrand(~ZORAN_ICR_EN,ZORAN_ICR);
-
- ztv->running = 0;
- }
-}
-
-static ulong dmask[] = {
- 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8,
- 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80,
- 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800,
- 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000,
- 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000,
- 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000,
- 0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000,
- 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000
-};
-
-static
-void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp)
-{
- ulong* mtop;
- int ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */
- int i;
-
-DEBUG(printk(KERN_DEBUG " overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count));
-
- for (i=0; i<count; i++) {
- struct video_clip *vp = vcp+i;
- UNUSED(vp);
-DEBUG(printk(KERN_DEBUG " %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->width,vp->height));
- }
-
- /*
- * activate the visible portion of the screen
- * Note we take some shortcuts here, because we
- * know the width can never be < 32. (I.e. a DWORD)
- * We also assume the overlay starts somewhere in
- * the FIRST dword.
- */
- {
- int start = ztv->vidXshift;
- ulong firstd = dmask[start];
- ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31];
- mtop = ztv->overinfo.overlay;
- for (i=0; i<ztv->overinfo.h; i++) {
- int w = ztv->vidWidth;
- ulong* line = mtop;
- if (start & 31) {
- *line++ = firstd;
- w -= 32-(start&31);
- }
- memset(line, ~0, w/8);
- if (w & 31)
- line[w/32] = lastd;
- mtop += ystep;
- }
- }
-
- /* process clipping regions */
- for (i=0; i<count; i++) {
- int h;
- if (vcp->x < 0 || (uint)vcp->x > ztv->overinfo.w ||
- vcp->y < 0 || vcp->y > ztv->overinfo.h ||
- vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w ||
- vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h)
- {
- DEBUG(printk(CARD_DEBUG "invalid clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h));
- if (vcp->x < 0) vcp->x = 0;
- if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w;
- if (vcp->y < 0) vcp->y = 0;
- if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h;
- if (vcp->width < 0) vcp->width = 0;
- if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x;
- if (vcp->height < 0) vcp->height = 0;
- if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y;
-// continue;
- }
-
- mtop = &ztv->overinfo.overlay[vcp->y*ystep];
- for (h=0; h<=vcp->height; h++) {
- int w;
- int x = ztv->vidXshift + vcp->x;
- for (w=0; w<=vcp->width; w++) {
- clear_bit(x&31, &mtop[x/32]);
- x++;
- }
- mtop += ystep;
- }
- ++vcp;
- }
-
- mtop = ztv->overinfo.overlay;
- zrwrite(virt_to_bus(mtop), ZORAN_MTOP);
- zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT);
- zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR);
-}
-
-struct tvnorm
-{
- u16 Wt, Wa, Ht, Ha, HStart, VStart;
-};
-
-static struct tvnorm tvnorms[] = {
- /* PAL-BDGHI */
-/* { 864, 720, 625, 576, 131, 21 },*/
-/*00*/ { 864, 768, 625, 576, 81, 17 },
- /* NTSC */
-/*01*/ { 858, 720, 525, 480, 121, 10 },
- /* SECAM */
-/*02*/ { 864, 720, 625, 576, 131, 21 },
- /* BW50 */
-/*03*/ { 864, 720, 625, 576, 131, 21 },
- /* BW60 */
-/*04*/ { 858, 720, 525, 480, 121, 10 }
-};
-#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
-
-/*
- * Program the chip for a setup as described in the vidinfo struct.
- *
- * Side-effects: calculates vidXshift, vidInterlace,
- * vidHeight, vidWidth which are used in a later stage
- * to calculate the overlay mask
- *
- * This is an internal function, as such it does not check the
- * validity of the struct members... Spectaculair crashes will
- * follow /very/ quick when you're wrong and the chip right :)
- */
-static
-void zoran_set_geo(struct zoran* ztv, struct vidinfo* i)
-{
- ulong top, bot;
- int stride;
- int winWidth, winHeight;
- int maxWidth, maxHeight, maxXOffset, maxYOffset;
- long vfec;
-
-DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay));
-
- /*
- * make sure the DMA transfers are inhibited during our
- * reprogramming of the chip
- */
- zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);
-
- maxWidth = tvnorms[ztv->norm].Wa;
- maxHeight = tvnorms[ztv->norm].Ha/2;
- maxXOffset = tvnorms[ztv->norm].HStart;
- maxYOffset = tvnorms[ztv->norm].VStart;
-
- /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */
- vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) |
- (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24));
-
- /*
- * Set top, bottom ptrs. Since these must be DWORD aligned,
- * possible adjust the x and the width of the window.
- * so the endposition stay the same. The vidXshift will make
- * sure we are not writing pixels before the requested x.
- */
- ztv->vidXshift = 0;
- winWidth = i->w;
- if (winWidth < 0)
- winWidth = -winWidth;
- top = i->busadr + i->x*i->bpp + i->y*i->bpl;
- if (top & 3) {
- ztv->vidXshift = (top & 3) / i->bpp;
- winWidth += ztv->vidXshift;
- DEBUG(printk(KERN_DEBUG " window-x shifted %d pixels left\n",ztv->vidXshift));
- top &= ~3;
- }
-
- /*
- * bottom points to next frame but in interleaved mode we want
- * to 'mix' the 2 frames to one capture, so 'bot' points to one
- * (physical) line below the top line.
- */
- bot = top + i->bpl;
- zrwrite(top,ZORAN_VTOP);
- zrwrite(bot,ZORAN_VBOT);
-
- /*
- * Make sure the winWidth is DWORD aligned too,
- * thereby automaticly making sure the stride to the
- * next line is DWORD aligned too (as required by spec).
- */
- if ((winWidth*i->bpp) & 3) {
-DEBUG(printk(KERN_DEBUG " window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3));
- winWidth += (winWidth*i->bpp) & 3;
- }
-
- /* determine the DispMode and stride */
- if (i->h >= 0 && i->h <= maxHeight) {
- /* single frame grab suffices for this height. */
- vfec |= ZORAN_VFEC_DISPMOD;
- ztv->vidInterlace = 0;
- stride = i->bpl - (winWidth*i->bpp);
- winHeight = i->h;
- }
- else {
- /* interleaving needed for this height */
- ztv->vidInterlace = 1;
- stride = i->bpl*2 - (winWidth*i->bpp);
- winHeight = i->h/2;
- }
- if (winHeight < 0) /* can happen for VBI! */
- winHeight = -winHeight;
-
- /* safety net, sometimes bpl is too short??? */
- if (stride<0) {
-DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride));
- stride = 0;
- }
-
- zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC);
- zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR);
-
- /* remember vidWidth, vidHeight for overlay calculations */
- ztv->vidWidth = winWidth;
- ztv->vidHeight = winHeight;
-DEBUG(printk(KERN_DEBUG " top=%08lx, bottom=%08lx\n",top,bot));
-DEBUG(printk(KERN_DEBUG " winWidth=%d, winHeight=%d\n",winWidth,winHeight));
-DEBUG(printk(KERN_DEBUG " maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight));
-DEBUG(printk(KERN_DEBUG " stride=%d\n",stride));
-
- /*
- * determine horizontal scales and crops
- */
- if (i->w < 0) {
- int Hstart = 1;
- int Hend = Hstart + winWidth;
-DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend));
- zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);
- }
- else {
- int Wa = maxWidth;
- int X = (winWidth*64+Wa-1)/Wa;
- int We = winWidth*64/X;
- int HorDcm = 64-X;
- int hcrop1 = 2*(Wa-We)/4;
- /*
- * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi>
- * found the solution to the color phase shift.
- * See ChangeLog for the full explanation)
- */
- int Hstart = (maxXOffset + hcrop1) | 1;
- int Hend = Hstart + We - 1;
-
-DEBUG(printk(KERN_DEBUG " X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend));
-
- zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);
- vfec |= HorDcm<<14;
-
- if (HorDcm<16)
- vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */
- else if (HorDcm<32)
- vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */
- else if (HorDcm<48)
- vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */
- else vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */
- }
-
- /*
- * Determine vertical scales and crops
- *
- * when height is negative, we want to read starting at line 0
- * One day someone might need access to these lines...
- */
- if (i->h < 0) {
- int Vstart = 0;
- int Vend = Vstart + winHeight;
-DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Vstart, Vend));
- zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);
- }
- else {
- int Ha = maxHeight;
- int Y = (winHeight*64+Ha-1)/Ha;
- int He = winHeight*64/Y;
- int VerDcm = 64-Y;
- int vcrop1 = 2*(Ha-He)/4;
- int Vstart = maxYOffset + vcrop1;
- int Vend = Vstart + He - 1;
-
-DEBUG(printk(KERN_DEBUG " Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend));
- zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);
- vfec |= VerDcm<<8;
- }
-
-DEBUG(printk(KERN_DEBUG " F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name));
-
- /* setup the requested format */
- zrwrite(vfec, ZORAN_VFEC);
-}
-
-static
-void zoran_common_open(struct zoran* ztv, int flags)
-{
- UNUSED(flags);
-
- /* already opened? */
- if (ztv->users++ != 0)
- return;
-
- /* unmute audio */
- /* /what/ audio? */
-
- ztv->state = 0;
-
- /* setup the encoder to the initial values */
- ztv->picture.colour=254<<7;
- ztv->picture.brightness=128<<8;
- ztv->picture.hue=128<<8;
- ztv->picture.contrast=216<<7;
- i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture);
-
- /* default to the composite input since my camera is there */
- zoran_muxsel(ztv, 0, VIDEO_MODE_PAL);
-}
-
-static
-void zoran_common_close(struct zoran* ztv)
-{
- if (--ztv->users != 0)
- return;
-
- /* mute audio */
- /* /what/ audio? */
-
- /* stop the chip */
- zoran_cap(ztv, 0);
-}
-
-/*
- * Open a zoran card. Right now the flags are just a hack
- */
-static int zoran_open(struct video_device *dev, int flags)
-{
- struct zoran *ztv = (struct zoran*)dev;
- struct vidinfo* item;
- char* pos;
-
- DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags));
-
- /*********************************************
- * We really should be doing lazy allocing...
- *********************************************/
- /* allocate a frame buffer */
- if (!ztv->fbuffer)
- ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE);
- if (!ztv->fbuffer) {
- /* could not get a buffer, bail out */
- return -ENOBUFS;
- }
- /* at this time we _always_ have a framebuffer */
- memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE);
-
- if (!ztv->overinfo.overlay)
- ztv->overinfo.overlay = kmalloc(1024*1024/8, GFP_KERNEL);
- if (!ztv->overinfo.overlay) {
- /* could not get an overlay buffer, bail out */
- bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
- return -ENOBUFS;
- }
- /* at this time we _always_ have a overlay */
-
- /* clear buffer status, and give them a DMAable address */
- pos = ztv->fbuffer;
- for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)
- {
- item->status = FBUFFER_FREE;
- item->memadr = pos;
- item->busadr = virt_to_bus(pos);
- pos += ZORAN_MAX_FBUFFER;
- }
-
- /* do the common part of all open's */
- zoran_common_open(ztv, flags);
-
- return 0;
-}
-
-static
-void zoran_close(struct video_device* dev)
-{
- struct zoran *ztv = (struct zoran*)dev;
-
- DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD));
-
- /* driver specific closure */
- clear_bit(STATE_OVERLAY, &ztv->state);
-
- zoran_common_close(ztv);
-
- /*
- * This is sucky but right now I can't find a good way to
- * be sure its safe to free the buffer. We wait 5-6 fields
- * which is more than sufficient to be sure.
- */
- msleep(100); /* Wait 1/10th of a second */
-
- /* free the allocated framebuffer */
- bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
- ztv->fbuffer = 0;
- kfree(ztv->overinfo.overlay);
- ztv->overinfo.overlay = 0;
-
-}
-
-/*
- * This read function could be used reentrant in a SMP situation.
- *
- * This is made possible by the spinlock which is kept till we
- * found and marked a buffer for our own use. The lock must
- * be released as soon as possible to prevent lock contention.
- */
-static
-long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock)
-{
- struct zoran *ztv = (struct zoran*)dev;
- unsigned long max;
- struct vidinfo* unused = 0;
- struct vidinfo* done = 0;
-
- DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock));
-
- /* find ourself a free or completed buffer */
- for (;;) {
- struct vidinfo* item;
-
- write_lock_irq(&ztv->lock);
- for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)
- {
- if (!unused && item->status == FBUFFER_FREE)
- unused = item;
- if (!done && item->status == FBUFFER_DONE)
- done = item;
- }
- if (done || unused)
- break;
-
- /* no more free buffers, wait for them. */
- write_unlock_irq(&ztv->lock);
- if (nonblock)
- return -EWOULDBLOCK;
- interruptible_sleep_on(&ztv->grabq);
- if (signal_pending(current))
- return -EINTR;
- }
-
- /* Do we have 'ready' data? */
- if (!done) {
- /* no? than this will take a while... */
- if (nonblock) {
- write_unlock_irq(&ztv->lock);
- return -EWOULDBLOCK;
- }
-
- /* mark the unused buffer as wanted */
- unused->status = FBUFFER_BUSY;
- unused->w = 320;
- unused->h = 240;
- unused->format = VIDEO_PALETTE_RGB24;
- unused->bpp = palette2fmt[unused->format].bpp;
- unused->bpl = unused->w * unused->bpp;
- unused->next = 0;
- { /* add to tail of queue */
- struct vidinfo* oldframe = ztv->workqueue;
- if (!oldframe) ztv->workqueue = unused;
- else {
- while (oldframe->next) oldframe = oldframe->next;
- oldframe->next = unused;
- }
- }
- write_unlock_irq(&ztv->lock);
-
- /* tell the state machine we want it filled /NOW/ */
- zoran_cap(ztv, 1);
-
- /* wait till this buffer gets grabbed */
- wait_event_interruptible(ztv->grabq,
- (unused->status != FBUFFER_BUSY));
- /* see if a signal did it */
- if (signal_pending(current))
- return -EINTR;
- done = unused;
- }
- else
- write_unlock_irq(&ztv->lock);
-
- /* Yes! we got data! */
- max = done->bpl * done->h;
- if (count > max)
- count = max;
- if (copy_to_user((void*)buf, done->memadr, count))
- count = -EFAULT;
-
- /* keep the engine running */
- done->status = FBUFFER_FREE;
-// zoran_cap(ztv,1);
-
- /* tell listeners this buffer became free */
- wake_up_interruptible(&ztv->grabq);
-
- /* goodbye */
- DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count));
- return count;
-}
-
-static
-long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock)
-{
- struct zoran *ztv = (struct zoran *)dev;
- UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock);
- DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD));
- return -EINVAL;
-}
-
-static
-unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait)
-{
- struct zoran *ztv = (struct zoran *)dev;
- struct vidinfo* item;
- unsigned int mask = 0;
-
- poll_wait(file, &ztv->grabq, wait);
-
- for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)
- if (item->status == FBUFFER_DONE)
- {
- mask |= (POLLIN | POLLRDNORM);
- break;
- }
-
- DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask));
-
- return mask;
-}
-
-/* append a new clipregion to the vector of video_clips */
-static
-void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h)
-{
- vcp[vw->clipcount].x = x;
- vcp[vw->clipcount].y = y;
- vcp[vw->clipcount].width = w;
- vcp[vw->clipcount].height = h;
- vw->clipcount++;
-}
-
-static
-int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
-{
- struct zoran* ztv = (struct zoran*)dev;
-
- switch (cmd) {
- case VIDIOCGCAP:
- {
- struct video_capability c;
- DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD));
-
- strcpy(c.name,ztv->video_dev.name);
- c.type = VID_TYPE_CAPTURE|
- VID_TYPE_OVERLAY|
- VID_TYPE_CLIPPING|
- VID_TYPE_FRAMERAM|
- VID_TYPE_SCALES;
- if (ztv->have_tuner)
- c.type |= VID_TYPE_TUNER;
- if (pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))
- c.type &= ~VID_TYPE_OVERLAY;
- if (ztv->have_decoder) {
- c.channels = ztv->card->video_inputs;
- c.audios = ztv->card->audio_inputs;
- } else
- /* no decoder -> no channels */
- c.channels = c.audios = 0;
- c.maxwidth = 768;
- c.maxheight = 576;
- c.minwidth = 32;
- c.minheight = 32;
- if (copy_to_user(arg,&c,sizeof(c)))
- return -EFAULT;
- break;
- }
-
- case VIDIOCGCHAN:
- {
- struct video_channel v;
- int mux;
- if (copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel));
- v.flags=VIDEO_VC_AUDIO
-#ifdef VIDEO_VC_NORM
- |VIDEO_VC_NORM
-#endif
- ;
- v.tuners=0;
- v.type=VIDEO_TYPE_CAMERA;
-#ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API
- v.norm=VIDEO_MODE_PAL|
- VIDEO_MODE_NTSC|
- VIDEO_MODE_SECAM;
-#else
- v.norm=VIDEO_MODE_PAL;
-#endif
- /* too many inputs? no decoder -> no channels */
- if (!ztv->have_decoder || v.channel < 0 || v.channel >= ztv->card->video_inputs)
- return -EINVAL;
-
- /* now determine the name of the channel */
- mux = ztv->card->video_mux[v.channel];
- if (mux & IS_TUNER) {
- /* lets assume only one tuner, yes? */
- strcpy(v.name,"Television");
- v.type = VIDEO_TYPE_TV;
- if (ztv->have_tuner) {
- v.flags |= VIDEO_VC_TUNER;
- v.tuners = 1;
- }
- }
- else if (mux & IS_SVHS)
- sprintf(v.name,"S-Video-%d",v.channel);
- else
- sprintf(v.name,"CVBS-%d",v.channel);
-
- if (copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- break;
- }
- case VIDIOCSCHAN:
- { /* set video channel */
- struct video_channel v;
- if (copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm));
-
- /* too many inputs? no decoder -> no channels */
- if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0)
- return -EINVAL;
-
- if (v.norm != VIDEO_MODE_PAL &&
- v.norm != VIDEO_MODE_NTSC &&
- v.norm != VIDEO_MODE_SECAM &&
- v.norm != VIDEO_MODE_AUTO)
- return -EOPNOTSUPP;
-
- /* make it happen, nr1! */
- return zoran_muxsel(ztv,v.channel,v.norm);
- }
-
- case VIDIOCGTUNER:
- {
- struct video_tuner v;
- if (copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner));
-
- /* Only no or one tuner for now */
- if (!ztv->have_tuner || v.tuner)
- return -EINVAL;
-
- strcpy(v.name,"Television");
- v.rangelow = 0;
- v.rangehigh = ~0;
- v.flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
- v.mode = ztv->norm;
- v.signal = 0xFFFF; /* unknown */
-
- if (copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- break;
- }
- case VIDIOCSTUNER:
- {
- struct video_tuner v;
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode));
-
- /* Only no or one tuner for now */
- if (!ztv->have_tuner || v.tuner)
- return -EINVAL;
-
- /* and it only has certain valid modes */
- if( v.mode != VIDEO_MODE_PAL &&
- v.mode != VIDEO_MODE_NTSC &&
- v.mode != VIDEO_MODE_SECAM)
- return -EOPNOTSUPP;
-
- /* engage! */
- return zoran_muxsel(ztv,v.tuner,v.mode);
- }
-
- case VIDIOCGPICT:
- {
- struct video_picture p = ztv->picture;
- DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD));
- p.depth = ztv->depth;
- switch (p.depth) {
- case 8: p.palette=VIDEO_PALETTE_YUV422;
- break;
- case 15: p.palette=VIDEO_PALETTE_RGB555;
- break;
- case 16: p.palette=VIDEO_PALETTE_RGB565;
- break;
- case 24: p.palette=VIDEO_PALETTE_RGB24;
- break;
- case 32: p.palette=VIDEO_PALETTE_RGB32;
- break;
- }
- if (copy_to_user(arg, &p, sizeof(p)))
- return -EFAULT;
- break;
- }
- case VIDIOCSPICT:
- {
- struct video_picture p;
- if (copy_from_user(&p, arg,sizeof(p)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette));
-
- /* depth must match with framebuffer */
- if (p.depth != ztv->depth)
- return -EINVAL;
-
- /* check if palette matches this bpp */
- if (p.palette>NRPALETTES ||
- palette2fmt[p.palette].bpp != ztv->overinfo.bpp)
- return -EINVAL;
-
- write_lock_irq(&ztv->lock);
- ztv->overinfo.format = p.palette;
- ztv->picture = p;
- write_unlock_irq(&ztv->lock);
-
- /* tell the decoder */
- i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p);
- break;
- }
-
- case VIDIOCGWIN:
- {
- struct video_window vw;
- DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD));
- read_lock(&ztv->lock);
- vw.x = ztv->overinfo.x;
- vw.y = ztv->overinfo.y;
- vw.width = ztv->overinfo.w;
- vw.height = ztv->overinfo.h;
- vw.chromakey= 0;
- vw.flags = 0;
- if (ztv->vidInterlace)
- vw.flags|=VIDEO_WINDOW_INTERLACE;
- read_unlock(&ztv->lock);
- if (copy_to_user(arg,&vw,sizeof(vw)))
- return -EFAULT;
- break;
- }
- case VIDIOCSWIN:
- {
- struct video_window vw;
- struct video_clip *vcp;
- int on;
- if (copy_from_user(&vw,arg,sizeof(vw)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount));
-
- if (vw.flags)
- return -EINVAL;
-
- if (vw.clipcount <0 || vw.clipcount>256)
- return -EDOM; /* Too many! */
-
- /*
- * Do any clips.
- */
- vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
- if (vcp==NULL)
- return -ENOMEM;
- if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) {
- vfree(vcp);
- return -EFAULT;
- }
-
- on = ztv->running;
- if (on)
- zoran_cap(ztv, 0);
-
- /*
- * strange, it seems xawtv sometimes calls us with 0
- * width and/or height. Ignore these values
- */
- if (vw.x == 0)
- vw.x = ztv->overinfo.x;
- if (vw.y == 0)
- vw.y = ztv->overinfo.y;
-
- /* by now we are committed to the new data... */
- write_lock_irq(&ztv->lock);
- ztv->overinfo.x = vw.x;
- ztv->overinfo.y = vw.y;
- ztv->overinfo.w = vw.width;
- ztv->overinfo.h = vw.height;
- write_unlock_irq(&ztv->lock);
-
- /*
- * Impose display clips
- */
- if (vw.x+vw.width > ztv->swidth)
- new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1);
- if (vw.y+vw.height > ztv->sheight)
- new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1);
-
- /* built the requested clipping zones */
- zoran_set_geo(ztv, &ztv->overinfo);
- zoran_built_overlay(ztv, vw.clipcount, vcp);
- vfree(vcp);
-
- /* if we were on, restart the video engine */
- if (on)
- zoran_cap(ztv, 1);
- break;
- }
-
- case VIDIOCCAPTURE:
- {
- int v;
- if (get_user(v, (int *)arg))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v));
-
- if (v==0) {
- clear_bit(STATE_OVERLAY, &ztv->state);
- zoran_cap(ztv, 1);
- }
- else {
- /* is VIDIOCSFBUF, VIDIOCSWIN done? */
- if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0)
- return -EINVAL;
-
- set_bit(STATE_OVERLAY, &ztv->state);
- zoran_cap(ztv, 1);
- }
- break;
- }
-
- case VIDIOCGFBUF:
- {
- struct video_buffer v;
- DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD));
- read_lock(&ztv->lock);
- v.base = (void *)ztv->overinfo.busadr;
- v.height = ztv->sheight;
- v.width = ztv->swidth;
- v.depth = ztv->depth;
- v.bytesperline = ztv->overinfo.bpl;
- read_unlock(&ztv->lock);
- if(copy_to_user(arg, &v,sizeof(v)))
- return -EFAULT;
- break;
- }
- case VIDIOCSFBUF:
- {
- struct video_buffer v;
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (pcipci_problems & (PCIPCI_FAIL|PCIAGP_FAIL))
- return -ENXIO;
- if (copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline));
-
- if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32)
- return -EINVAL;
- if (v.bytesperline<1)
- return -EINVAL;
- if (ztv->running)
- return -EBUSY;
- write_lock_irq(&ztv->lock);
- ztv->overinfo.busadr = (ulong)v.base;
- ztv->sheight = v.height;
- ztv->swidth = v.width;
- ztv->depth = v.depth; /* bits per pixel */
- ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */
- ztv->overinfo.bpl = v.bytesperline; /* bytes per line */
- write_unlock_irq(&ztv->lock);
- break;
- }
-
- case VIDIOCKEY:
- {
- /* Will be handled higher up .. */
- break;
- }
-
- case VIDIOCSYNC:
- {
- int i;
- if (get_user(i, (int *) arg))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i));
- if (i<0 || i>ZORAN_MAX_FBUFFERS)
- return -EINVAL;
- switch (ztv->grabinfo[i].status) {
- case FBUFFER_FREE:
- return -EINVAL;
- case FBUFFER_BUSY:
- /* wait till this buffer gets grabbed */
- 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:
- ztv->grabinfo[i].status = FBUFFER_FREE;
- /* tell ppl we have a spare buffer */
- wake_up_interruptible(&ztv->grabq);
- break;
- }
- DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i));
- break;
- }
-
- case VIDIOCMCAPTURE:
- {
- struct video_mmap vm;
- struct vidinfo* frame;
- if (copy_from_user(&vm,arg,sizeof(vm)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format));
- if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS ||
- vm.width<32 || vm.width>768 ||
- vm.height<32 || vm.height>576 ||
- vm.format>NRPALETTES ||
- palette2fmt[vm.format].mode == 0)
- return -EINVAL;
-
- /* we are allowed to take over UNUSED and DONE buffers */
- frame = &ztv->grabinfo[vm.frame];
- if (frame->status == FBUFFER_BUSY)
- return -EBUSY;
-
- /* setup the other parameters if they are given */
- write_lock_irq(&ztv->lock);
- frame->w = vm.width;
- frame->h = vm.height;
- frame->format = vm.format;
- frame->bpp = palette2fmt[frame->format].bpp;
- frame->bpl = frame->w*frame->bpp;
- frame->status = FBUFFER_BUSY;
- frame->next = 0;
- { /* add to tail of queue */
- struct vidinfo* oldframe = ztv->workqueue;
- if (!oldframe) ztv->workqueue = frame;
- else {
- while (oldframe->next) oldframe = oldframe->next;
- oldframe->next = frame;
- }
- }
- write_unlock_irq(&ztv->lock);
- zoran_cap(ztv, 1);
- break;
- }
-
- case VIDIOCGMBUF:
- {
- struct video_mbuf mb;
- int i;
- DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD));
- mb.size = ZORAN_MAX_FBUFSIZE;
- mb.frames = ZORAN_MAX_FBUFFERS;
- for (i=0; i<ZORAN_MAX_FBUFFERS; i++)
- mb.offsets[i] = i*ZORAN_MAX_FBUFFER;
- if(copy_to_user(arg, &mb,sizeof(mb)))
- return -EFAULT;
- break;
- }
-
- case VIDIOCGUNIT:
- {
- struct video_unit vu;
- DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD));
- vu.video = ztv->video_dev.minor;
- vu.vbi = ztv->vbi_dev.minor;
- vu.radio = VIDEO_NO_UNIT;
- vu.audio = VIDEO_NO_UNIT;
- vu.teletext = VIDEO_NO_UNIT;
- if(copy_to_user(arg, &vu,sizeof(vu)))
- return -EFAULT;
- break;
- }
-
- case VIDIOCGFREQ:
- {
- unsigned long v = ztv->tuner_freq;
- if (copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD));
- break;
- }
- case VIDIOCSFREQ:
- {
- unsigned long v;
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD));
-
- if (ztv->have_tuner) {
- int fixme = v;
- if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0)
- return -EAGAIN;
- }
- ztv->tuner_freq = v;
- break;
- }
-
- /* Why isn't this in the API?
- * And why doesn't it take a buffer number?
- case BTTV_FIELDNR:
- {
- unsigned long v = ztv->lastfieldnr;
- if (copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD));
- break;
- }
- */
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static
-int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* adr, unsigned long size)
-{
- struct zoran* ztv = (struct zoran*)dev;
- unsigned long start = (unsigned long)adr;
- unsigned long pos;
-
- DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size));
-
- /* sanity checks */
- if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer)
- return -EINVAL;
-
- /* start mapping the whole shabang to user memory */
- pos = (unsigned long)ztv->fbuffer;
- while (size>0) {
- unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT;
- if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED))
- return -EAGAIN;
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- return 0;
-}
-
-static struct video_device zr36120_template=
-{
- .owner = THIS_MODULE,
- .name = "UNSET",
- .type = VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
- .hardware = VID_HARDWARE_ZR36120,
- .open = zoran_open,
- .close = zoran_close,
- .read = zoran_read,
- .write = zoran_write,
- .poll = zoran_poll,
- .ioctl = zoran_ioctl,
- .compat_ioctl = v4l_compat_ioctl32,
- .mmap = zoran_mmap,
- .minor = -1,
-};
-
-static
-int vbi_open(struct video_device *dev, int flags)
-{
- struct zoran *ztv = dev->priv;
- struct vidinfo* item;
-
- DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags));
-
- /*
- * During VBI device open, we continiously grab VBI-like
- * data in the vbi buffer when we have nothing to do.
- * Only when there is an explicit request for VBI data
- * (read call) we /force/ a read.
- */
-
- /* allocate buffers */
- for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
- {
- item->status = FBUFFER_FREE;
-
- /* alloc */
- if (!item->memadr) {
- item->memadr = bmalloc(ZORAN_VBI_BUFSIZE);
- if (!item->memadr) {
- /* could not get a buffer, bail out */
- while (item != ztv->readinfo) {
- item--;
- bfree(item->memadr, ZORAN_VBI_BUFSIZE);
- item->memadr = 0;
- item->busadr = 0;
- }
- return -ENOBUFS;
- }
- }
-
- /* determine the DMAable address */
- item->busadr = virt_to_bus(item->memadr);
- }
-
- /* do the common part of all open's */
- zoran_common_open(ztv, flags);
-
- set_bit(STATE_VBI, &ztv->state);
- /* start read-ahead */
- zoran_cap(ztv, 1);
-
- return 0;
-}
-
-static
-void vbi_close(struct video_device *dev)
-{
- struct zoran *ztv = dev->priv;
- struct vidinfo* item;
-
- DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD));
-
- /* driver specific closure */
- clear_bit(STATE_VBI, &ztv->state);
-
- zoran_common_close(ztv);
-
- /*
- * This is sucky but right now I can't find a good way to
- * be sure its safe to free the buffer. We wait 5-6 fields
- * which is more than sufficient to be sure.
- */
- msleep(100); /* Wait 1/10th of a second */
-
- for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
- {
- if (item->memadr)
- bfree(item->memadr, ZORAN_VBI_BUFSIZE);
- item->memadr = 0;
- }
-
-}
-
-/*
- * This read function could be used reentrant in a SMP situation.
- *
- * This is made possible by the spinlock which is kept till we
- * found and marked a buffer for our own use. The lock must
- * be released as soon as possible to prevent lock contention.
- */
-static
-long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock)
-{
- struct zoran *ztv = dev->priv;
- unsigned long max;
- struct vidinfo* unused = 0;
- struct vidinfo* done = 0;
-
- DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock));
-
- /* find ourself a free or completed buffer */
- for (;;) {
- struct vidinfo* item;
-
- write_lock_irq(&ztv->lock);
- for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) {
- if (!unused && item->status == FBUFFER_FREE)
- unused = item;
- if (!done && item->status == FBUFFER_DONE)
- done = item;
- }
- if (done || unused)
- break;
-
- /* no more free buffers, wait for them. */
- write_unlock_irq(&ztv->lock);
- if (nonblock)
- return -EWOULDBLOCK;
- interruptible_sleep_on(&ztv->vbiq);
- if (signal_pending(current))
- return -EINTR;
- }
-
- /* Do we have 'ready' data? */
- if (!done) {
- /* no? than this will take a while... */
- if (nonblock) {
- write_unlock_irq(&ztv->lock);
- return -EWOULDBLOCK;
- }
-
- /* mark the unused buffer as wanted */
- unused->status = FBUFFER_BUSY;
- unused->next = 0;
- { /* add to tail of queue */
- struct vidinfo* oldframe = ztv->workqueue;
- if (!oldframe) ztv->workqueue = unused;
- else {
- while (oldframe->next) oldframe = oldframe->next;
- oldframe->next = unused;
- }
- }
- write_unlock_irq(&ztv->lock);
-
- /* tell the state machine we want it filled /NOW/ */
- zoran_cap(ztv, 1);
-
- /* wait till this buffer gets grabbed */
- wait_event_interruptible(ztv->vbiq,
- (unused->status != FBUFFER_BUSY));
- /* see if a signal did it */
- if (signal_pending(current))
- return -EINTR;
- done = unused;
- }
- else
- write_unlock_irq(&ztv->lock);
-
- /* Yes! we got data! */
- max = done->bpl * -done->h;
- if (count > max)
- count = max;
-
- /* check if the user gave us enough room to write the data */
- if (!access_ok(VERIFY_WRITE, buf, count)) {
- count = -EFAULT;
- goto out;
- }
-
- /*
- * Now transform/strip the data from YUV to Y-only
- * NB. Assume the Y is in the LSB of the YUV data.
- */
- {
- unsigned char* optr = buf;
- unsigned char* eptr = buf+count;
-
- /* are we beeing accessed from an old driver? */
- if (count == 2*19*2048) {
- /*
- * Extreme HACK, old VBI programs expect 2048 points
- * of data, and we only got 864 orso. Double each
- * datapoint and clear the rest of the line.
- * This way we have appear to have a
- * sample_frequency of 29.5 Mc.
- */
- int x,y;
- unsigned char* iptr = done->memadr+1;
- for (y=done->h; optr<eptr && y<0; y++)
- {
- /* copy to doubled data to userland */
- for (x=0; optr+1<eptr && x<-done->w; x++)
- {
- unsigned char a = iptr[x*2];
- __put_user(a, optr++);
- __put_user(a, optr++);
- }
- /* and clear the rest of the line */
- for (x*=2; optr<eptr && x<done->bpl; x++)
- __put_user(0, optr++);
- /* next line */
- iptr += done->bpl;
- }
- }
- else {
- /*
- * Other (probably newer) programs asked
- * us what geometry we are using, and are
- * reading the correct size.
- */
- int x,y;
- unsigned char* iptr = done->memadr+1;
- for (y=done->h; optr<eptr && y<0; y++)
- {
- /* copy to doubled data to userland */
- for (x=0; optr<eptr && x<-done->w; x++)
- __put_user(iptr[x*2], optr++);
- /* and clear the rest of the line */
- for (;optr<eptr && x<done->bpl; x++)
- __put_user(0, optr++);
- /* next line */
- iptr += done->bpl;
- }
- }
-
- /* API compliance:
- * place the framenumber (half fieldnr) in the last long
- */
- __put_user(done->fieldnr/2, ((ulong*)eptr)[-1]);
- }
-
- /* keep the engine running */
- done->status = FBUFFER_FREE;
- zoran_cap(ztv, 1);
-
- /* tell listeners this buffer just became free */
- wake_up_interruptible(&ztv->vbiq);
-
- /* goodbye */
-out:
- DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count));
- return count;
-}
-
-static
-unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait)
-{
- struct zoran *ztv = dev->priv;
- struct vidinfo* item;
- unsigned int mask = 0;
-
- poll_wait(file, &ztv->vbiq, wait);
-
- for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
- if (item->status == FBUFFER_DONE)
- {
- mask |= (POLLIN | POLLRDNORM);
- break;
- }
-
- DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask));
-
- return mask;
-}
-
-static
-int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-{
- struct zoran* ztv = dev->priv;
-
- switch (cmd) {
- case VIDIOCGVBIFMT:
- {
- struct vbi_format f;
- DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD));
- f.sampling_rate = 14750000UL;
- f.samples_per_line = -ztv->readinfo[0].w;
- f.sample_format = VIDEO_PALETTE_RAW;
- f.start[0] = f.start[1] = ztv->readinfo[0].y;
- f.start[1] += 312;
- f.count[0] = f.count[1] = -ztv->readinfo[0].h;
- f.flags = VBI_INTERLACED;
- if (copy_to_user(arg,&f,sizeof(f)))
- return -EFAULT;
- break;
- }
- case VIDIOCSVBIFMT:
- {
- struct vbi_format f;
- int i;
- if (copy_from_user(&f, arg,sizeof(f)))
- return -EFAULT;
- DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags));
-
- /* lots of parameters are fixed... (PAL) */
- if (f.sampling_rate != 14750000UL ||
- f.samples_per_line > 864 ||
- f.sample_format != VIDEO_PALETTE_RAW ||
- f.start[0] < 0 ||
- f.start[0] != f.start[1]-312 ||
- f.count[0] != f.count[1] ||
- f.start[0]+f.count[0] >= 288 ||
- f.flags != VBI_INTERLACED)
- return -EINVAL;
-
- write_lock_irq(&ztv->lock);
- ztv->readinfo[0].y = f.start[0];
- ztv->readinfo[0].w = -f.samples_per_line;
- ztv->readinfo[0].h = -f.count[0];
- ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp;
- for (i=1; i<ZORAN_VBI_BUFFERS; i++)
- ztv->readinfo[i] = ztv->readinfo[i];
- write_unlock_irq(&ztv->lock);
- break;
- }
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static struct video_device vbi_template=
-{
- .owner = THIS_MODULE,
- .name = "UNSET",
- .type = VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
- .hardware = VID_HARDWARE_ZR36120,
- .open = vbi_open,
- .close = vbi_close,
- .read = vbi_read,
- .write = zoran_write,
- .poll = vbi_poll,
- .ioctl = vbi_ioctl,
- .minor = -1,
-};
-
-/*
- * Scan for a Zoran chip, request the irq and map the io memory
- */
-static
-int __init find_zoran(void)
-{
- int result;
- struct zoran *ztv;
- struct pci_dev *dev = NULL;
- unsigned char revision;
- int zoran_num = 0;
-
- while ((dev = pci_get_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev)))
- {
- /* Ok, a ZR36120/ZR36125 found! */
- ztv = &zorans[zoran_num];
- ztv->dev = dev;
-
- if (pci_enable_device(dev))
- continue;
-
- pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision);
- printk(KERN_INFO "zoran: Zoran %x (rev %d) ",
- dev->device, revision);
- printk("bus: %d, devfn: %d, irq: %d, ",
- dev->bus->number, dev->devfn, dev->irq);
- printk("memory: 0x%08lx.\n", ztv->zoran_adr);
-
- ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000);
- DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem));
-
- result = request_irq(dev->irq, zoran_irq,
- IRQF_SHARED|IRQF_DISABLED,"zoran", ztv);
- if (result==-EINVAL)
- {
- iounmap(ztv->zoran_mem);
- printk(KERN_ERR "zoran: Bad irq number or handler\n");
- continue;
- }
- if (result==-EBUSY)
- printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq);
- if (result < 0) {
- iounmap(ztv->zoran_mem);
- continue;
- }
- /* Enable bus-mastering */
- pci_set_master(dev);
- /* Keep a reference */
- pci_dev_get(dev);
- zoran_num++;
- }
- if(zoran_num)
- printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num);
- return zoran_num;
-}
-
-static
-int __init init_zoran(int card)
-{
- struct zoran *ztv = &zorans[card];
- int i;
-
- /* if the given cardtype valid? */
- if (cardtype[card]>=NRTVCARDS) {
- printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]);
- return -1;
- }
-
- /* reset the zoran */
- zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);
- udelay(10);
- zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI);
- udelay(10);
-
- /* zoran chip specific details */
- ztv->card = tvcards+cardtype[card]; /* point to the selected card */
- ztv->norm = 0; /* PAL */
- ztv->tuner_freq = 0;
-
- /* videocard details */
- ztv->swidth = 800;
- ztv->sheight = 600;
- ztv->depth = 16;
-
- /* State details */
- ztv->fbuffer = 0;
- ztv->overinfo.kindof = FBUFFER_OVERLAY;
- ztv->overinfo.status = FBUFFER_FREE;
- ztv->overinfo.x = 0;
- ztv->overinfo.y = 0;
- ztv->overinfo.w = 768; /* 640 */
- ztv->overinfo.h = 576; /* 480 */
- ztv->overinfo.format = VIDEO_PALETTE_RGB565;
- ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp;
- ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth;
- ztv->overinfo.busadr = 0;
- ztv->overinfo.memadr = 0;
- ztv->overinfo.overlay = 0;
- for (i=0; i<ZORAN_MAX_FBUFFERS; i++) {
- ztv->grabinfo[i] = ztv->overinfo;
- ztv->grabinfo[i].kindof = FBUFFER_GRAB;
- }
- init_waitqueue_head(&ztv->grabq);
-
- /* VBI details */
- ztv->readinfo[0] = ztv->overinfo;
- ztv->readinfo[0].kindof = FBUFFER_VBI;
- ztv->readinfo[0].w = -864;
- ztv->readinfo[0].h = -38;
- ztv->readinfo[0].format = VIDEO_PALETTE_YUV422;
- ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp;
- ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp;
- for (i=1; i<ZORAN_VBI_BUFFERS; i++)
- ztv->readinfo[i] = ztv->readinfo[0];
- init_waitqueue_head(&ztv->vbiq);
-
- /* maintenance data */
- ztv->have_decoder = 0;
- ztv->have_tuner = 0;
- ztv->tuner_type = 0;
- ztv->running = 0;
- ztv->users = 0;
- rwlock_init(&ztv->lock);
- ztv->workqueue = 0;
- ztv->fieldnr = 0;
- ztv->lastfieldnr = 0;
-
- if (triton1)
- zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC);
-
- /* external FL determines TOP frame */
- zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC);
-
- /* set HSpol */
- if (ztv->card->hsync_pos)
- zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH);
- /* set VSpol */
- if (ztv->card->vsync_pos)
- zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV);
-
- /* Set the proper General Purpuse register bits */
- /* implicit: no softreset, 0 waitstates */
- zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI);
- /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */
- zrwrite(ztv->card->gpval<<24,ZORAN_GUEST);
-
- /* clear interrupt status */
- zrwrite(~0, ZORAN_ISR);
-
- /*
- * i2c template
- */
- ztv->i2c = zoran_i2c_bus_template;
- sprintf(ztv->i2c.name,"zoran-%d",card);
- ztv->i2c.data = ztv;
-
- /*
- * Now add the template and register the device unit
- */
- ztv->video_dev = zr36120_template;
- strcpy(ztv->video_dev.name, ztv->i2c.name);
- ztv->video_dev.priv = ztv;
- if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0)
- return -1;
-
- ztv->vbi_dev = vbi_template;
- strcpy(ztv->vbi_dev.name, ztv->i2c.name);
- ztv->vbi_dev.priv = ztv;
- if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) {
- video_unregister_device(&ztv->video_dev);
- return -1;
- }
- i2c_register_bus(&ztv->i2c);
-
- /* set interrupt mask - the PIN enable will be set later */
- zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR);
-
- printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name);
- return 0;
-}
-
-static
-void release_zoran(int max)
-{
- struct zoran *ztv;
- int i;
-
- for (i=0;i<max; i++)
- {
- ztv = &zorans[i];
-
- /* turn off all capturing, DMA and IRQs */
- /* reset the zoran */
- zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);
- udelay(10);
- zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI);
- udelay(10);
-
- /* first disable interrupts before unmapping the memory! */
- zrwrite(0, ZORAN_ICR);
- zrwrite(0xffffffffUL,ZORAN_ISR);
-
- /* free it */
- free_irq(ztv->dev->irq,ztv);
-
- /* unregister i2c_bus */
- i2c_unregister_bus((&ztv->i2c));
-
- /* unmap and free memory */
- if (ztv->zoran_mem)
- iounmap(ztv->zoran_mem);
-
- /* Drop PCI device */
- pci_dev_put(ztv->dev);
-
- video_unregister_device(&ztv->video_dev);
- video_unregister_device(&ztv->vbi_dev);
- }
-}
-
-void __exit zr36120_exit(void)
-{
- release_zoran(zoran_cards);
-}
-
-int __init zr36120_init(void)
-{
- int card;
-
- handle_chipset();
- zoran_cards = find_zoran();
- if (zoran_cards <= 0)
- return -EIO;
-
- /* initialize Zorans */
- for (card=0; card<zoran_cards; card++) {
- if (init_zoran(card) < 0) {
- /* only release the zorans we have registered */
- release_zoran(card);
- return -EIO;
- }
- }
- return 0;
-}
-
-module_init(zr36120_init);
-module_exit(zr36120_exit);
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h
deleted file mode 100644
index a71e485b0f9..00000000000
--- a/drivers/media/video/zr36120.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- zr36120.h - Zoran 36120/36125 based framegrabbers
-
- Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _ZR36120_H
-#define _ZR36120_H
-
-#ifdef __KERNEL__
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-#include <linux/i2c-old.h>
-#include <linux/videodev.h>
-
-#include <asm/io.h>
-
-/*
- * Debug macro's, place an x behind the ) for actual debug-compilation
- * E.g. #define DEBUG(x...) x
- */
-#define DEBUG(x...) /* Debug driver */
-#define IDEBUG(x...) /* Debug interrupt handler */
-#define PDEBUG 0 /* Debug PCI writes */
-
-/* defined in zr36120_i2c */
-extern struct i2c_bus zoran_i2c_bus_template;
-
-#define ZORAN_MAX_FBUFFERS 2
-#define ZORAN_MAX_FBUFFER (768*576*2)
-#define ZORAN_MAX_FBUFSIZE (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER)
-
-#define ZORAN_VBI_BUFFERS 2
-#define ZORAN_VBI_BUFSIZE (22*1024*2)
-
-struct tvcard {
- char* name; /* name of the cardtype */
- int video_inputs; /* number of channels defined in video_mux */
- int audio_inputs; /* number of channels defined in audio_mux */
- __u32 swapi2c:1, /* need to swap i2c wires SDA/SCL? */
- usegirq1:1, /* VSYNC at GIRQ1 instead of GIRQ0? */
- vsync_pos:1, /* positive VSYNC signal? */
- hsync_pos:1, /* positive HSYNC signal? */
- gpdir:8, /* General Purpose Direction register */
- gpval:8; /* General Purpose Value register */
- int video_mux[6]; /* mapping channel number to physical input */
-#define IS_TUNER 0x80
-#define IS_SVHS 0x40
-#define CHANNEL_MASK 0x3F
- int audio_mux[6]; /* mapping channel number to physical input */
-};
-#define TUNER(x) ((x)|IS_TUNER)
-#define SVHS(x) ((x)|IS_SVHS)
-
-struct vidinfo {
- struct vidinfo* next; /* next active buffer */
- uint kindof;
-#define FBUFFER_OVERLAY 0
-#define FBUFFER_GRAB 1
-#define FBUFFER_VBI 2
- uint status;
-#define FBUFFER_FREE 0
-#define FBUFFER_BUSY 1
-#define FBUFFER_DONE 2
- ulong fieldnr; /* # of field, not framer! */
- uint x,y;
- int w,h; /* w,h can be negative! */
- uint format; /* index in palette2fmt[] */
- uint bpp; /* lookup from palette2fmt[] */
- uint bpl; /* calc: width * bpp */
- ulong busadr; /* bus addr for DMA engine */
- char* memadr; /* kernel addr for making copies */
- ulong* overlay; /* kernel addr of overlay mask */
-};
-
-struct zoran
-{
- struct video_device video_dev;
-#define CARD_DEBUG KERN_DEBUG "%s(%lu): "
-#define CARD_INFO KERN_INFO "%s(%lu): "
-#define CARD_ERR KERN_ERR "%s(%lu): "
-#define CARD ztv->video_dev.name,ztv->fieldnr
-
- /* zoran chip specific details */
- struct i2c_bus i2c; /* i2c registration data */
- struct pci_dev* dev; /* ptr to PCI device */
- ulong zoran_adr; /* bus address of IO memory */
- char* zoran_mem; /* kernel address of IO memory */
- struct tvcard* card; /* the cardtype */
- uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */
- uint tuner_freq; /* Current freq in kHz */
- struct video_picture picture; /* Current picture params */
-
- /* videocard details */
- uint swidth; /* screen width */
- uint sheight; /* screen height */
- uint depth; /* depth in bits */
-
- /* State details */
- char* fbuffer; /* framebuffers for mmap */
- struct vidinfo overinfo; /* overlay data */
- struct vidinfo grabinfo[ZORAN_MAX_FBUFFERS]; /* grabbing data*/
- wait_queue_head_t grabq; /* grabbers queue */
-
- /* VBI details */
- struct video_device vbi_dev;
- struct vidinfo readinfo[2]; /* VBI data - flip buffers */
- wait_queue_head_t vbiq; /* vbi queue */
-
- /* maintenance data */
- int have_decoder; /* did we detect a mux? */
- int have_tuner; /* did we detect a tuner? */
- int users; /* howmany video/vbi open? */
- int tuner_type; /* tuner type, when found */
- int running; /* are we rolling? */
- rwlock_t lock;
- long state; /* what is requested of us? */
-#define STATE_OVERLAY 0
-#define STATE_VBI 1
- struct vidinfo* workqueue; /* buffers to grab, head is active */
- ulong fieldnr; /* #field, ticked every VSYNC */
- ulong lastfieldnr; /* #field, ticked every GRAB */
-
- int vidInterlace; /* calculated */
- int vidXshift; /* calculated */
- uint vidWidth; /* calculated */
- uint vidHeight; /* calculated */
-};
-
-#define zrwrite(dat,adr) writel((dat),(char *) (ztv->zoran_mem+(adr)))
-#define zrread(adr) readl(ztv->zoran_mem+(adr))
-
-#if PDEBUG == 0
-#define zrand(dat,adr) zrwrite((dat) & zrread(adr), adr)
-#define zror(dat,adr) zrwrite((dat) | zrread(adr), adr)
-#define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr)
-#else
-#define zrand(dat, adr) \
-do { \
- ulong data = (dat) & zrread((adr)); \
- zrwrite(data, (adr)); \
- if (0 != (~(dat) & zrread((adr)))) \
- printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \
-} while(0)
-
-#define zror(dat, adr) \
-do { \
- ulong data = (dat) | zrread((adr)); \
- zrwrite(data, (adr)); \
- if ((dat) != ((dat) & zrread(adr))) \
- printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \
-} while(0)
-
-#define zraor(dat, mask, adr) \
-do { \
- ulong data; \
- if ((dat) & (mask)) \
- printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \
- data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \
- zrwrite(data,(adr)); \
- if ( (dat) != (~(mask) & zrread((adr))) ) \
- printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \
-} while(0)
-#endif
-
-#endif
-
-/* zoran PCI address space */
-#define ZORAN_VFEH 0x000 /* Video Front End Horizontal Conf. */
-#define ZORAN_VFEH_HSPOL (1<<30)
-#define ZORAN_VFEH_HSTART (0x3FF<<10)
-#define ZORAN_VFEH_HEND (0x3FF<<0)
-
-#define ZORAN_VFEV 0x004 /* Video Front End Vertical Conf. */
-#define ZORAN_VFEV_VSPOL (1<<30)
-#define ZORAN_VFEV_VSTART (0x3FF<<10)
-#define ZORAN_VFEV_VEND (0x3FF<<0)
-
-#define ZORAN_VFEC 0x008 /* Video Front End Scaler and Pixel */
-#define ZORAN_VFEC_EXTFL (1<<26)
-#define ZORAN_VFEC_TOPFIELD (1<<25)
-#define ZORAN_VFEC_VCLKPOL (1<<24)
-#define ZORAN_VFEC_HFILTER (7<<21)
-#define ZORAN_VFEC_HFILTER_1 (0<<21) /* no lumi, 3-tap chromo */
-#define ZORAN_VFEC_HFILTER_2 (1<<21) /* 3-tap lumi, 3-tap chromo */
-#define ZORAN_VFEC_HFILTER_3 (2<<21) /* 4-tap lumi, 4-tap chromo */
-#define ZORAN_VFEC_HFILTER_4 (3<<21) /* 5-tap lumi, 4-tap chromo */
-#define ZORAN_VFEC_HFILTER_5 (4<<21) /* 4-tap lumi, 4-tap chromo */
-#define ZORAN_VFEC_DUPFLD (1<<20)
-#define ZORAN_VFEC_HORDCM (63<<14)
-#define ZORAN_VFEC_VERDCM (63<<8)
-#define ZORAN_VFEC_DISPMOD (1<<6)
-#define ZORAN_VFEC_RGB (3<<3)
-#define ZORAN_VFEC_RGB_YUV422 (0<<3)
-#define ZORAN_VFEC_RGB_RGB888 (1<<3)
-#define ZORAN_VFEC_RGB_RGB565 (2<<3)
-#define ZORAN_VFEC_RGB_RGB555 (3<<3)
-#define ZORAN_VFEC_ERRDIF (1<<2)
-#define ZORAN_VFEC_PACK24 (1<<1)
-#define ZORAN_VFEC_LE (1<<0)
-
-#define ZORAN_VTOP 0x00C /* Video Display "Top" */
-
-#define ZORAN_VBOT 0x010 /* Video Display "Bottom" */
-
-#define ZORAN_VSTR 0x014 /* Video Display Stride */
-#define ZORAN_VSTR_DISPSTRIDE (0xFFFF<<16)
-#define ZORAN_VSTR_VIDOVF (1<<8)
-#define ZORAN_VSTR_SNAPSHOT (1<<1)
-#define ZORAN_VSTR_GRAB (1<<0)
-
-#define ZORAN_VDC 0x018 /* Video Display Conf. */
-#define ZORAN_VDC_VIDEN (1<<31)
-#define ZORAN_VDC_MINPIX (0x1F<<25)
-#define ZORAN_VDC_TRICOM (1<<24)
-#define ZORAN_VDC_VIDWINHT (0x3FF<<12)
-#define ZORAN_VDC_VIDWINWID (0x3FF<<0)
-
-#define ZORAN_MTOP 0x01C /* Masking Map "Top" */
-
-#define ZORAN_MBOT 0x020 /* Masking Map "Bottom" */
-
-#define ZORAN_OCR 0x024 /* Overlay Control */
-#define ZORAN_OCR_OVLEN (1<<15)
-#define ZORAN_OCR_MASKSTRIDE (0xFF<<0)
-
-#define ZORAN_PCI 0x028 /* System, PCI and GPP Control */
-#define ZORAN_PCI_SOFTRESET (1<<24)
-#define ZORAN_PCI_WAITSTATE (3<<16)
-#define ZORAN_PCI_GENPURDIR (0xFF<<0)
-
-#define ZORAN_GUEST 0x02C /* GuestBus Control */
-
-#define ZORAN_CSOURCE 0x030 /* Code Source Address */
-
-#define ZORAN_CTRANS 0x034 /* Code Transfer Control */
-
-#define ZORAN_CMEM 0x038 /* Code Memory Pointer */
-
-#define ZORAN_ISR 0x03C /* Interrupt Status Register */
-#define ZORAN_ISR_CODE (1<<28)
-#define ZORAN_ISR_GIRQ0 (1<<29)
-#define ZORAN_ISR_GIRQ1 (1<<30)
-
-#define ZORAN_ICR 0x040 /* Interrupt Control Register */
-#define ZORAN_ICR_EN (1<<24)
-#define ZORAN_ICR_CODE (1<<28)
-#define ZORAN_ICR_GIRQ0 (1<<29)
-#define ZORAN_ICR_GIRQ1 (1<<30)
-
-#define ZORAN_I2C 0x044 /* I2C-Bus */
-#define ZORAN_I2C_SCL (1<<1)
-#define ZORAN_I2C_SDA (1<<0)
-
-#define ZORAN_POST 0x48 /* PostOffice */
-#define ZORAN_POST_PEN (1<<25)
-#define ZORAN_POST_TIME (1<<24)
-#define ZORAN_POST_DIR (1<<23)
-#define ZORAN_POST_GUESTID (3<<20)
-#define ZORAN_POST_GUEST (7<<16)
-#define ZORAN_POST_DATA (0xFF<<0)
-
-#endif
diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c
deleted file mode 100644
index 21fde43a6ae..00000000000
--- a/drivers/media/video/zr36120_i2c.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- zr36120_i2c.c - Zoran 36120/36125 based framegrabbers
-
- Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-
-#include <linux/video_decoder.h>
-#include <asm/uaccess.h>
-
-#include "tuner.h"
-#include "zr36120.h"
-
-/* ----------------------------------------------------------------------- */
-/* I2C functions */
-/* ----------------------------------------------------------------------- */
-
-/* software I2C functions */
-
-#define I2C_DELAY 10
-
-static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data)
-{
- struct zoran *ztv = (struct zoran*)bus->data;
- unsigned int b = 0;
- if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA;
- if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL;
- zrwrite(b, ZORAN_I2C);
- udelay(I2C_DELAY);
-}
-
-static int i2c_getdataline(struct i2c_bus *bus)
-{
- struct zoran *ztv = (struct zoran*)bus->data;
- if (ztv->card->swapi2c)
- return zrread(ZORAN_I2C) & ZORAN_I2C_SCL;
- return zrread(ZORAN_I2C) & ZORAN_I2C_SDA;
-}
-
-static
-void attach_inform(struct i2c_bus *bus, int id)
-{
- struct zoran *ztv = (struct zoran*)bus->data;
- struct video_decoder_capability dc;
- int rv;
-
- switch (id) {
- case I2C_DRIVERID_VIDEODECODER:
- DEBUG(printk(CARD_INFO "decoder attached\n",CARD));
-
- /* fetch the capabilities of the decoder */
- rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc);
- if (rv) {
- DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD));
- break;
- }
- DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs));
-
- /* Test if the decoder can de VBI transfers */
- if (dc.flags & 16 /*VIDEO_DECODER_VBI*/)
- ztv->have_decoder = 2;
- else
- ztv->have_decoder = 1;
- break;
- case I2C_DRIVERID_TUNER:
- ztv->have_tuner = 1;
- DEBUG(printk(CARD_INFO "tuner attached\n",CARD));
- if (ztv->tuner_type >= 0)
- {
- if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0)
- DEBUG(printk(CARD_INFO "attach_inform; tuner won't be set to type %d\n",CARD,ztv->tuner_type));
- }
- break;
- default:
- DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id));
- break;
- }
-}
-
-static
-void detach_inform(struct i2c_bus *bus, int id)
-{
- struct zoran *ztv = (struct zoran*)bus->data;
-
- switch (id) {
- case I2C_DRIVERID_VIDEODECODER:
- ztv->have_decoder = 0;
- DEBUG(printk(CARD_INFO "decoder detached\n",CARD));
- break;
- case I2C_DRIVERID_TUNER:
- ztv->have_tuner = 0;
- DEBUG(printk(CARD_INFO "tuner detached\n",CARD));
- break;
- default:
- DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id));
- break;
- }
-}
-
-struct i2c_bus zoran_i2c_bus_template =
-{
- "ZR36120",
- I2C_BUSID_ZORAN,
- NULL,
-
- SPIN_LOCK_UNLOCKED,
-
- attach_inform,
- detach_inform,
-
- i2c_setlines,
- i2c_getdataline,
- NULL,
- NULL
-};
diff --git a/drivers/media/video/zr36120_mem.c b/drivers/media/video/zr36120_mem.c
deleted file mode 100644
index 416eaa93b8a..00000000000
--- a/drivers/media/video/zr36120_mem.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- zr36120_mem.c - Zoran 36120/36125 based framegrabbers
-
- Copyright (C) 1998-1999 Pauline Middelink <middelin@polyware.nl>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#ifdef CONFIG_BIGPHYS_AREA
-#include <linux/bigphysarea.h>
-#endif
-
-#include "zr36120.h"
-#include "zr36120_mem.h"
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-void* bmalloc(unsigned long size)
-{
- void* mem;
-#ifdef CONFIG_BIGPHYS_AREA
- mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL);
-#else
- /*
- * The following function got a lot of memory at boottime,
- * so we know its always there...
- */
- mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size));
-#endif
- if (mem) {
- unsigned long adr = (unsigned long)mem;
- while (size > 0) {
- SetPageReserved(virt_to_page(phys_to_virt(adr)));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- }
- return mem;
-}
-
-void bfree(void* mem, unsigned long size)
-{
- if (mem) {
- unsigned long adr = (unsigned long)mem;
- unsigned long siz = size;
- while (siz > 0) {
- ClearPageReserved(virt_to_page(phys_to_virt(adr)));
- adr += PAGE_SIZE;
- siz -= PAGE_SIZE;
- }
-#ifdef CONFIG_BIGPHYS_AREA
- bigphysarea_free_pages(mem);
-#else
- free_pages((unsigned long)mem,get_order(size));
-#endif
- }
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zr36120_mem.h b/drivers/media/video/zr36120_mem.h
deleted file mode 100644
index aad117acc91..00000000000
--- a/drivers/media/video/zr36120_mem.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* either kmalloc() or bigphysarea() alloced memory - continuous */
-void* bmalloc(unsigned long size);
-void bfree(void* mem, unsigned long size);
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 6e068cf1049..b3f28a03b6a 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -5,7 +5,7 @@
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
@@ -73,6 +73,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
/*
* cmd line parameters
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index a4afad4ecab..e316708f76b 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -5,7 +5,7 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
@@ -72,11 +72,11 @@
#endif
#ifndef COPYRIGHT
-#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
+#define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.04.02"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.02"
+#define MPT_LINUX_VERSION_COMMON "3.04.03"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.03"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -1059,7 +1059,7 @@ extern int mpt_stm_index; /* needed by mptstm.c */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#endif /* } __KERNEL__ */
-#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc__)
#define CAST_U32_TO_PTR(x) ((void *)(u64)x)
#define CAST_PTR_TO_U32(x) ((u32)(u64)x)
#else
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 30975ccd994..504632da434 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -4,7 +4,7 @@
* For use with LSI Logic PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
@@ -66,7 +66,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation"
+#define COPYRIGHT "Copyright (c) 1999-2007 LSI Logic Corporation"
#define MODULEAUTHOR "LSI Logic Corporation"
#include "mptbase.h"
#include "mptctl.h"
@@ -79,6 +79,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index 043941882c6..e65a1cf5eb0 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -5,7 +5,7 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ca2f9107f14..c819c23b55b 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -3,7 +3,7 @@
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
@@ -75,6 +75,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
/* Command line args */
#define MPTFC_DEV_LOSS_TMO (60)
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index b7c4407c5e3..2936204d8ad 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -4,7 +4,7 @@
* For use with LSI Logic Fibre Channel PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 2000-2005 LSI Logic Corporation
+ * Copyright (c) 2000-2007 LSI Logic Corporation
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -56,9 +56,11 @@
#include <linux/module.h>
#include <linux/fs.h>
+#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "mptlan"
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 3726ecba570..70ab75e7c26 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -4,7 +4,7 @@
* For use with LSI Logic Fibre Channel PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 2000-2005 LSI Logic Corporation
+ * Copyright (c) 2000-2007 LSI Logic Corporation
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 4f0c530e47b..09e9a9d9641 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -3,9 +3,9 @@
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
- * Copyright (c) 2005-2006 Dell
+ * Copyright (c) 2005-2007 Dell
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -75,6 +75,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
static int mpt_pt_clear;
module_param(mpt_pt_clear, int, 0);
@@ -245,7 +246,8 @@ static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
- printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
+ printk("SAS Address=0x%llX\n", (unsigned long long)
+ le64_to_cpu(sas_address));
printk("Target ID=0x%X\n", pg0->TargetID);
printk("Bus=0x%X\n", pg0->Bus);
/* The PhyNum field specifies the PHY number of the parent
@@ -349,9 +351,9 @@ mptsas_port_delete(struct mptsas_portinfo_details * port_details)
phy_info = port_info->phy_info;
dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
- "bitmask=0x%016llX\n",
- __FUNCTION__, port_details, port_details->num_phys,
- port_details->phy_bitmask));
+ "bitmask=0x%016llX\n", __FUNCTION__, port_details,
+ port_details->num_phys, (unsigned long long)
+ port_details->phy_bitmask));
for (i = 0; i < port_info->num_phys; i++, phy_info++) {
if(phy_info->port_details != port_details)
@@ -476,7 +478,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
sas_address = phy_info->attached.sas_address;
dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
- i, sas_address));
+ i, (unsigned long long)sas_address));
if (!sas_address)
continue;
port_details = phy_info->port_details;
@@ -495,8 +497,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
(1 << phy_info->phy_id);
phy_info->sas_port_add_phy=1;
dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
- "phy_id=%d sas_address=0x%018llX\n",
- i, sas_address));
+ "phy_id=%d sas_address=0x%018llX\n",
+ i, (unsigned long long)sas_address));
phy_info->port_details = port_details;
}
@@ -512,8 +514,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
if (phy_info_cmp->port_details == port_details )
continue;
dsaswideprintk((KERN_DEBUG
- "\t\tphy_id=%d sas_address=0x%018llX\n",
- j, phy_info_cmp->attached.sas_address));
+ "\t\tphy_id=%d sas_address=0x%018llX\n",
+ j, (unsigned long long)
+ phy_info_cmp->attached.sas_address));
if (phy_info_cmp->port_details) {
port_details->rphy =
mptsas_get_rphy(phy_info_cmp);
@@ -546,11 +549,10 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
if (!port_details)
continue;
dsaswideprintk((KERN_DEBUG
- "%s: [%p]: phy_id=%02d num_phys=%02d "
- "bitmask=0x%016llX\n",
- __FUNCTION__,
- port_details, i, port_details->num_phys,
- port_details->phy_bitmask));
+ "%s: [%p]: phy_id=%02d num_phys=%02d "
+ "bitmask=0x%016llX\n", __FUNCTION__,
+ port_details, i, port_details->num_phys,
+ (unsigned long long)port_details->phy_bitmask));
dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
port_details->port, port_details->rphy));
}
@@ -2079,8 +2081,10 @@ mptsas_persist_clear_table(struct work_struct *work)
static void
mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
{
+ int rc;
+
sdev->no_uld_attach = data ? 1 : 0;
- scsi_device_reprobe(sdev);
+ rc = scsi_device_reprobe(sdev);
}
static void
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 2c72c36b817..f0cca3ea93b 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -3,7 +3,7 @@
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
@@ -76,6 +76,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -701,6 +702,17 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
break;
}
}
+ } else if (ioc->bus_type == FC) {
+ /*
+ * The FC IOC may kill a request for variety of
+ * reasons, some of which may be recovered by a
+ * retry, some which are unlikely to be
+ * recovered. Return DID_ERROR instead of
+ * DID_RESET to permit retry of the command,
+ * just not an infinite number of them
+ */
+ sc->result = DID_ERROR << 16;
+ break;
}
/*
@@ -2688,7 +2700,8 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
struct scsi_device *sdev)
{
dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
- hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
+ hd->ioc->name, vtarget->bus_id, vtarget->target_id,
+ sdev->lun, hd));
/* Is LUN supported? If so, upper 2 bits will be 0
* in first byte of inquiry data.
@@ -2770,7 +2783,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
else {
factor = MPT_ULTRA320;
if (scsi_device_qas(sdev)) {
- ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+ ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
noQas = 0;
}
if (sdev->type == TYPE_TAPE &&
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 14a5b6c2e2b..187c8af0890 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -5,7 +5,7 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 36641da5928..203c661d2c7 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -3,7 +3,7 @@
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Copyright (c) 1999-2005 LSI Logic Corporation
+ * Copyright (c) 1999-2007 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
@@ -77,6 +77,7 @@
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
+MODULE_VERSION(my_VERSION);
/* Command line args */
static int mpt_saf_te = MPTSCSIH_SAF_TE;
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index dc388a3ff5e..cbe384fb848 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -18,7 +18,7 @@ extern struct i2o_driver i2o_exec_driver;
extern int i2o_exec_lct_get(struct i2o_controller *);
extern int __init i2o_exec_init(void);
-extern void __exit i2o_exec_exit(void);
+extern void i2o_exec_exit(void);
/* driver */
extern struct bus_type i2o_bus_type;
@@ -26,7 +26,7 @@ extern struct bus_type i2o_bus_type;
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
extern int __init i2o_driver_init(void);
-extern void __exit i2o_driver_exit(void);
+extern void i2o_driver_exit(void);
/* PCI */
extern int __init i2o_pci_init(void);
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 9104b65ff70..d3235f213c8 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -362,7 +362,7 @@ int __init i2o_driver_init(void)
*
* Unregisters the I2O bus and frees driver array.
*/
-void __exit i2o_driver_exit(void)
+void i2o_driver_exit(void)
{
bus_unregister(&i2o_bus_type);
kfree(i2o_drivers);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 902753b2c66..5278aad92bc 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -367,7 +367,7 @@ static int i2o_exec_remove(struct device *dev)
/**
* i2o_exec_lct_modified - Called on LCT NOTIFY reply
- * @work: work struct for a specific controller
+ * @_work: work struct for a specific controller
*
* This function handles asynchronus LCT NOTIFY replies. It parses the
* new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
@@ -595,7 +595,7 @@ int __init i2o_exec_init(void)
*
* Unregisters the Exec OSM from the I2O core.
*/
-void __exit i2o_exec_exit(void)
+void i2o_exec_exit(void)
{
i2o_driver_unregister(&i2o_exec_driver);
};
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 1de30d71167..e33d446e749 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -186,7 +186,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)
if (!dev)
return -ENXIO;
- ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL);
+ ops = kmalloc(kcmd.oplen, GFP_KERNEL);
if (!ops)
return -ENOMEM;
@@ -199,7 +199,7 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)
* It's possible to have a _very_ large table
* and that the user asks for all of it at once...
*/
- res = (u8 *) kmalloc(65536, GFP_KERNEL);
+ res = kmalloc(65536, GFP_KERNEL);
if (!res) {
kfree(ops);
return -ENOMEM;
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index fdb7153f442..8e5e07e4c1c 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -317,7 +317,8 @@ static int __init msi_init(void)
/* Register backlight stuff */
- msibl_device = backlight_device_register("msi-laptop-bl", NULL, &msibl_props);
+ msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL,
+ &msibl_props);
if (IS_ERR(msibl_device))
return PTR_ERR(msibl_device);
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 4633dbc9a90..aa152f31851 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver
*
* Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
*
@@ -11,7 +11,7 @@
*/
/*
- This is the AT91RM9200 MCI driver that has been tested with both MMC cards
+ This is the AT91 MCI driver that has been tested with both MMC cards
and SD-cards. Boards that support write protect are now supported.
The CCAT91SBC001 board does not support SD cards.
@@ -38,8 +38,8 @@
controller to manage the transfers.
A read is done from the controller directly to the scatterlist passed in from the request.
- Due to a bug in the controller, when a read is completed, all the words are byte
- swapped in the scatterlist buffers.
+ Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
+ swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug.
The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
@@ -72,6 +72,7 @@
#include <asm/irq.h>
#include <asm/mach/mmc.h>
#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <asm/arch/at91_mci.h>
#include <asm/arch/at91_pdc.h>
@@ -80,34 +81,18 @@
#undef SUPPORT_4WIRE
-static struct clk *mci_clk;
+#define FL_SENT_COMMAND (1 << 0)
+#define FL_SENT_STOP (1 << 1)
-#define FL_SENT_COMMAND (1 << 0)
-#define FL_SENT_STOP (1 << 1)
+#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
+ | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
+ | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
+#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
+#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
/*
- * Read from a MCI register.
- */
-static inline unsigned long at91_mci_read(unsigned int reg)
-{
- void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
-
- return __raw_readl(mci_base + reg);
-}
-
-/*
- * Write to a MCI register.
- */
-static inline void at91_mci_write(unsigned int reg, unsigned long value)
-{
- void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
-
- __raw_writel(value, mci_base + reg);
-}
-
-/*
* Low level type for this driver
*/
struct at91mci_host
@@ -116,9 +101,14 @@ struct at91mci_host
struct mmc_command *cmd;
struct mmc_request *request;
+ void __iomem *baseaddr;
+ int irq;
+
struct at91_mmc_data *board;
int present;
+ struct clk *mci_clk;
+
/*
* Flag indicating when the command has been sent. This is used to
* work out whether or not to send the stop
@@ -158,7 +148,6 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
for (i = 0; i < len; i++) {
struct scatterlist *sg;
int amount;
- int index;
unsigned int *sgbuffer;
sg = &data->sg[i];
@@ -166,10 +155,15 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
amount = min(size, sg->length);
size -= amount;
- amount /= 4;
- for (index = 0; index < amount; index++)
- *dmabuf++ = swab32(sgbuffer[index]);
+ if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
+ int index;
+
+ for (index = 0; index < (amount / 4); index++)
+ *dmabuf++ = swab32(sgbuffer[index]);
+ }
+ else
+ memcpy(dmabuf, sgbuffer, amount);
kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
@@ -217,13 +211,13 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
/* Check to see if this needs filling */
if (i == 0) {
- if (at91_mci_read(AT91_PDC_RCR) != 0) {
+ if (at91_mci_read(host, AT91_PDC_RCR) != 0) {
pr_debug("Transfer active in current\n");
continue;
}
}
else {
- if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+ if (at91_mci_read(host, AT91_PDC_RNCR) != 0) {
pr_debug("Transfer active in next\n");
continue;
}
@@ -240,12 +234,12 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
if (i == 0) {
- at91_mci_write(AT91_PDC_RPR, sg->dma_address);
- at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+ at91_mci_write(host, AT91_PDC_RPR, sg->dma_address);
+ at91_mci_write(host, AT91_PDC_RCR, sg->length / 4);
}
else {
- at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
- at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+ at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address);
+ at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4);
}
}
@@ -276,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
while (host->in_use_index < host->transfer_index) {
unsigned int *buffer;
- int index;
- int len;
struct scatterlist *sg;
@@ -295,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
data->bytes_xfered += sg->length;
- len = sg->length / 4;
+ if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
+ int index;
- for (index = 0; index < len; index++) {
- buffer[index] = swab32(buffer[index]);
+ for (index = 0; index < (sg->length / 4); index++)
+ buffer[index] = swab32(buffer[index]);
}
+
kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
flush_dcache_page(sg->page);
}
@@ -308,8 +302,8 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
if (host->transfer_index < data->sg_len)
at91mci_pre_dma_read(host);
else {
- at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
- at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+ at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
}
pr_debug("post dma read done\n");
@@ -326,11 +320,11 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
pr_debug("Handling the transmit\n");
/* Disable the transfer */
- at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
/* Now wait for cmd ready */
- at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
- at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
cmd = host->cmd;
if (!cmd) return;
@@ -344,21 +338,23 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
/*
* Enable the controller
*/
-static void at91_mci_enable(void)
+static void at91_mci_enable(struct at91mci_host *host)
{
- at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
- at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
- at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
- at91_mci_write(AT91_MCI_MR, 0x834A);
- at91_mci_write(AT91_MCI_SDCR, 0x0);
+ at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
+ at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
+ at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+ at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+
+ /* use Slot A or B (only one at same time) */
+ at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
}
/*
* Disable the controller
*/
-static void at91_mci_disable(void)
+static void at91_mci_disable(struct at91mci_host *host)
{
- at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+ at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
}
/*
@@ -378,13 +374,13 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
/* Not sure if this is needed */
#if 0
- if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+ if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
pr_debug("Clearing timeout\n");
- at91_mci_write(AT91_MCI_ARGR, 0);
- at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
- while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+ at91_mci_write(host, AT91_MCI_ARGR, 0);
+ at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+ while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
/* spin */
- pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+ pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
}
}
#endif
@@ -431,32 +427,32 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
/*
* Set the arguments and send the command
*/
- pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
- cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+ pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
+ cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
if (!data) {
- at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
- at91_mci_write(AT91_PDC_RPR, 0);
- at91_mci_write(AT91_PDC_RCR, 0);
- at91_mci_write(AT91_PDC_RNPR, 0);
- at91_mci_write(AT91_PDC_RNCR, 0);
- at91_mci_write(AT91_PDC_TPR, 0);
- at91_mci_write(AT91_PDC_TCR, 0);
- at91_mci_write(AT91_PDC_TNPR, 0);
- at91_mci_write(AT91_PDC_TNCR, 0);
-
- at91_mci_write(AT91_MCI_ARGR, cmd->arg);
- at91_mci_write(AT91_MCI_CMDR, cmdr);
+ at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
+ at91_mci_write(host, AT91_PDC_RPR, 0);
+ at91_mci_write(host, AT91_PDC_RCR, 0);
+ at91_mci_write(host, AT91_PDC_RNPR, 0);
+ at91_mci_write(host, AT91_PDC_RNCR, 0);
+ at91_mci_write(host, AT91_PDC_TPR, 0);
+ at91_mci_write(host, AT91_PDC_TCR, 0);
+ at91_mci_write(host, AT91_PDC_TNPR, 0);
+ at91_mci_write(host, AT91_PDC_TNCR, 0);
+
+ at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+ at91_mci_write(host, AT91_MCI_CMDR, cmdr);
return AT91_MCI_CMDRDY;
}
- mr = at91_mci_read(AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
- at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+ mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
+ at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
/*
* Disable the PDC controller
*/
- at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
if (cmdr & AT91_MCI_TRCMD_START) {
data->bytes_xfered = 0;
@@ -485,8 +481,8 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
pr_debug("Transmitting %d bytes\n", host->total_length);
- at91_mci_write(AT91_PDC_TPR, host->physical_address);
- at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+ at91_mci_write(host, AT91_PDC_TPR, host->physical_address);
+ at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4);
ier = AT91_MCI_TXBUFE;
}
}
@@ -496,14 +492,14 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
* the data sheet says
*/
- at91_mci_write(AT91_MCI_ARGR, cmd->arg);
- at91_mci_write(AT91_MCI_CMDR, cmdr);
+ at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
+ at91_mci_write(host, AT91_MCI_CMDR, cmdr);
if (cmdr & AT91_MCI_TRCMD_START) {
if (cmdr & AT91_MCI_TRDIR)
- at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+ at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN);
else
- at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN);
+ at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN);
}
return ier;
}
@@ -520,7 +516,7 @@ static void at91mci_process_command(struct at91mci_host *host, struct mmc_comman
pr_debug("setting ier to %08X\n", ier);
/* Stop on errors or the required value */
- at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
}
/*
@@ -548,19 +544,19 @@ static void at91mci_completed_command(struct at91mci_host *host)
struct mmc_command *cmd = host->cmd;
unsigned int status;
- at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+ at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
- cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
- cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
- cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
- cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+ cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
+ cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
+ cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
+ cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
if (host->buffer) {
dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
host->buffer = NULL;
}
- status = at91_mci_read(AT91_MCI_SR);
+ status = at91_mci_read(host, AT91_MCI_SR);
pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
@@ -611,18 +607,18 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
int clkdiv;
struct at91mci_host *host = mmc_priv(mmc);
- unsigned long at91_master_clock = clk_get_rate(mci_clk);
+ unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
host->bus_mode = ios->bus_mode;
if (ios->clock == 0) {
/* Disable the MCI controller */
- at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+ at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
clkdiv = 0;
}
else {
/* Enable the MCI controller */
- at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+ at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
if ((at91_master_clock % (ios->clock * 2)) == 0)
clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
@@ -634,25 +630,25 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
pr_debug("MMC: Setting controller bus width to 4\n");
- at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+ at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
}
else {
pr_debug("MMC: Setting controller bus width to 1\n");
- at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+ at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
}
/* Set the clock divider */
- at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+ at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
/* maybe switch power to the card */
if (host->board->vcc_pin) {
switch (ios->power_mode) {
case MMC_POWER_OFF:
- at91_set_gpio_output(host->board->vcc_pin, 0);
+ at91_set_gpio_value(host->board->vcc_pin, 0);
break;
case MMC_POWER_UP:
case MMC_POWER_ON:
- at91_set_gpio_output(host->board->vcc_pin, 1);
+ at91_set_gpio_value(host->board->vcc_pin, 1);
break;
}
}
@@ -665,39 +661,40 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
{
struct at91mci_host *host = devid;
int completed = 0;
+ unsigned int int_status, int_mask;
- unsigned int int_status;
+ int_status = at91_mci_read(host, AT91_MCI_SR);
+ int_mask = at91_mci_read(host, AT91_MCI_IMR);
+
+ pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
+ int_status & int_mask);
+
+ int_status = int_status & int_mask;
- int_status = at91_mci_read(AT91_MCI_SR);
- pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
- int_status & at91_mci_read(AT91_MCI_IMR));
-
- if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+ if (int_status & AT91_MCI_ERRORS) {
completed = 1;
+
+ if (int_status & AT91_MCI_UNRE)
+ pr_debug("MMC: Underrun error\n");
+ if (int_status & AT91_MCI_OVRE)
+ pr_debug("MMC: Overrun error\n");
+ if (int_status & AT91_MCI_DTOE)
+ pr_debug("MMC: Data timeout\n");
+ if (int_status & AT91_MCI_DCRCE)
+ pr_debug("MMC: CRC error in data\n");
+ if (int_status & AT91_MCI_RTOE)
+ pr_debug("MMC: Response timeout\n");
+ if (int_status & AT91_MCI_RENDE)
+ pr_debug("MMC: Response end bit error\n");
+ if (int_status & AT91_MCI_RCRCE)
+ pr_debug("MMC: Response CRC error\n");
+ if (int_status & AT91_MCI_RDIRE)
+ pr_debug("MMC: Response direction error\n");
+ if (int_status & AT91_MCI_RINDE)
+ pr_debug("MMC: Response index error\n");
+ } else {
+ /* Only continue processing if no errors */
- int_status &= at91_mci_read(AT91_MCI_IMR);
-
- if (int_status & AT91_MCI_UNRE)
- pr_debug("MMC: Underrun error\n");
- if (int_status & AT91_MCI_OVRE)
- pr_debug("MMC: Overrun error\n");
- if (int_status & AT91_MCI_DTOE)
- pr_debug("MMC: Data timeout\n");
- if (int_status & AT91_MCI_DCRCE)
- pr_debug("MMC: CRC error in data\n");
- if (int_status & AT91_MCI_RTOE)
- pr_debug("MMC: Response timeout\n");
- if (int_status & AT91_MCI_RENDE)
- pr_debug("MMC: Response end bit error\n");
- if (int_status & AT91_MCI_RCRCE)
- pr_debug("MMC: Response CRC error\n");
- if (int_status & AT91_MCI_RDIRE)
- pr_debug("MMC: Response direction error\n");
- if (int_status & AT91_MCI_RINDE)
- pr_debug("MMC: Response index error\n");
-
- /* Only continue processing if no errors */
- if (!completed) {
if (int_status & AT91_MCI_TXBUFE) {
pr_debug("TX buffer empty\n");
at91_mci_handle_transmitted(host);
@@ -705,12 +702,11 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
if (int_status & AT91_MCI_RXBUFF) {
pr_debug("RX buffer full\n");
- at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
}
- if (int_status & AT91_MCI_ENDTX) {
+ if (int_status & AT91_MCI_ENDTX)
pr_debug("Transmit has ended\n");
- }
if (int_status & AT91_MCI_ENDRX) {
pr_debug("Receive has ended\n");
@@ -719,37 +715,33 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
if (int_status & AT91_MCI_NOTBUSY) {
pr_debug("Card is ready\n");
- at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
}
- if (int_status & AT91_MCI_DTIP) {
+ if (int_status & AT91_MCI_DTIP)
pr_debug("Data transfer in progress\n");
- }
- if (int_status & AT91_MCI_BLKE) {
+ if (int_status & AT91_MCI_BLKE)
pr_debug("Block transfer has ended\n");
- }
- if (int_status & AT91_MCI_TXRDY) {
+ if (int_status & AT91_MCI_TXRDY)
pr_debug("Ready to transmit\n");
- }
- if (int_status & AT91_MCI_RXRDY) {
+ if (int_status & AT91_MCI_RXRDY)
pr_debug("Ready to receive\n");
- }
if (int_status & AT91_MCI_CMDRDY) {
pr_debug("Command ready\n");
completed = 1;
}
}
- at91_mci_write(AT91_MCI_IDR, int_status);
if (completed) {
pr_debug("Completed command\n");
- at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+ at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
at91mci_completed_command(host);
- }
+ } else
+ at91_mci_write(host, AT91_MCI_IDR, int_status);
return IRQ_HANDLED;
}
@@ -769,14 +761,14 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
present ? "insert" : "remove");
if (!present) {
pr_debug("****** Resetting SD-card bus width ******\n");
- at91_mci_write(AT91_MCI_SDCR, 0);
+ at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
}
mmc_detect_change(host->mmc, msecs_to_jiffies(100));
}
return IRQ_HANDLED;
}
-int at91_mci_get_ro(struct mmc_host *mmc)
+static int at91_mci_get_ro(struct mmc_host *mmc)
{
int read_only = 0;
struct at91mci_host *host = mmc_priv(mmc);
@@ -802,19 +794,26 @@ static const struct mmc_host_ops at91_mci_ops = {
/*
* Probe for the device
*/
-static int at91_mci_probe(struct platform_device *pdev)
+static int __init at91_mci_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct at91mci_host *host;
+ struct resource *res;
int ret;
pr_debug("Probe MCI devices\n");
- at91_mci_disable();
- at91_mci_enable();
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME))
+ return -EBUSY;
mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
if (!mmc) {
pr_debug("Failed to allocate mmc host\n");
+ release_mem_region(res->start, res->end - res->start + 1);
return -ENOMEM;
}
@@ -833,30 +832,51 @@ static int at91_mci_probe(struct platform_device *pdev)
#ifdef SUPPORT_4WIRE
mmc->caps |= MMC_CAP_4_BIT_DATA;
#else
- printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+ printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
#endif
}
/*
* Get Clock
*/
- mci_clk = clk_get(&pdev->dev, "mci_clk");
- if (IS_ERR(mci_clk)) {
+ host->mci_clk = clk_get(&pdev->dev, "mci_clk");
+ if (IS_ERR(host->mci_clk)) {
printk(KERN_ERR "AT91 MMC: no clock defined.\n");
mmc_free_host(mmc);
+ release_mem_region(res->start, res->end - res->start + 1);
return -ENODEV;
}
- clk_enable(mci_clk); /* Enable the peripheral clock */
+
+ /*
+ * Map I/O region
+ */
+ host->baseaddr = ioremap(res->start, res->end - res->start + 1);
+ if (!host->baseaddr) {
+ clk_put(host->mci_clk);
+ mmc_free_host(mmc);
+ release_mem_region(res->start, res->end - res->start + 1);
+ return -ENOMEM;
+ }
+
+ /*
+ * Reset hardware
+ */
+ clk_enable(host->mci_clk); /* Enable the peripheral clock */
+ at91_mci_disable(host);
+ at91_mci_enable(host);
/*
* Allocate the MCI interrupt
*/
- ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+ host->irq = platform_get_irq(pdev, 0);
+ ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
if (ret) {
- printk(KERN_ERR "Failed to request MCI interrupt\n");
- clk_disable(mci_clk);
- clk_put(mci_clk);
+ printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
+ clk_disable(host->mci_clk);
+ clk_put(host->mci_clk);
mmc_free_host(mmc);
+ iounmap(host->baseaddr);
+ release_mem_region(res->start, res->end - res->start + 1);
return ret;
}
@@ -879,10 +899,10 @@ static int at91_mci_probe(struct platform_device *pdev)
ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
0, DRIVER_NAME, host);
if (ret)
- printk(KERN_ERR "couldn't allocate MMC detect irq\n");
+ printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
}
- pr_debug(KERN_INFO "Added MCI driver\n");
+ pr_debug("Added MCI driver\n");
return 0;
}
@@ -890,10 +910,11 @@ static int at91_mci_probe(struct platform_device *pdev)
/*
* Remove a device
*/
-static int at91_mci_remove(struct platform_device *pdev)
+static int __exit at91_mci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct at91mci_host *host;
+ struct resource *res;
if (!mmc)
return -1;
@@ -905,16 +926,19 @@ static int at91_mci_remove(struct platform_device *pdev)
cancel_delayed_work(&host->mmc->detect);
}
+ at91_mci_disable(host);
mmc_remove_host(mmc);
- at91_mci_disable();
- free_irq(AT91RM9200_ID_MCI, host);
- mmc_free_host(mmc);
+ free_irq(host->irq, host);
- clk_disable(mci_clk); /* Disable the peripheral clock */
- clk_put(mci_clk);
+ clk_disable(host->mci_clk); /* Disable the peripheral clock */
+ clk_put(host->mci_clk);
- platform_set_drvdata(pdev, NULL);
+ iounmap(host->baseaddr);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
+ mmc_free_host(mmc);
+ platform_set_drvdata(pdev, NULL);
pr_debug("MCI Removed\n");
return 0;
@@ -948,8 +972,7 @@ static int at91_mci_resume(struct platform_device *pdev)
#endif
static struct platform_driver at91_mci_driver = {
- .probe = at91_mci_probe,
- .remove = at91_mci_remove,
+ .remove = __exit_p(at91_mci_remove),
.suspend = at91_mci_suspend,
.resume = at91_mci_resume,
.driver = {
@@ -960,7 +983,7 @@ static struct platform_driver at91_mci_driver = {
static int __init at91_mci_init(void)
{
- return platform_driver_register(&at91_mci_driver);
+ return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
}
static void __exit at91_mci_exit(void)
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 447fba5825f..800527cf40d 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host)
host->rx_chan = rxchan;
}
-struct const mmc_host_ops au1xmmc_ops = {
+static const struct mmc_host_ops au1xmmc_ops = {
.request = au1xmmc_request,
.set_ios = au1xmmc_set_ios,
};
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 06e7fcd1922..bfb9ff69320 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -351,9 +351,6 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd,
case MMC_RSP_R3: /* short */
cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
break;
- case MMC_RSP_R6: /* short CRC */
- cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6;
- break;
default:
break;
}
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index a17423a4ed8..3e35a43819f 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -78,8 +78,10 @@ static int mmc_queue_thread(void *d)
spin_unlock_irq(q->queue_lock);
if (!req) {
- if (kthread_should_stop())
+ if (kthread_should_stop()) {
+ set_current_state(TASK_RUNNING);
break;
+ }
up(&mq->thread_sem);
schedule();
down(&mq->thread_sem);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index e9b80e92026..ccfe6561be2 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -42,6 +42,8 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
{
writel(0, host->base + MMCICOMMAND);
+ BUG_ON(host->data);
+
host->mrq = NULL;
host->cmd = NULL;
@@ -198,6 +200,8 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
}
if (!cmd->data || cmd->error != MMC_ERR_NONE) {
+ if (host->data)
+ mmci_stop_data(host);
mmci_request_end(host, cmd->mrq);
} else if (!(cmd->data->flags & MMC_DATA_READ)) {
mmci_start_data(host, cmd->data);
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index 435d331e772..d30540b2761 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -91,7 +91,6 @@
#define DRIVER_NAME "mmci-omap"
-#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
/* Specifies how often in millisecs to poll for card status changes
* when the cover switch is open */
@@ -204,18 +203,22 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
cmdtype = 0;
/* Our hardware needs to know exact type */
- switch (RSP_TYPE(mmc_resp_type(cmd))) {
- case RSP_TYPE(MMC_RSP_R1):
- /* resp 1, resp 1b */
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_NONE:
+ break;
+ case MMC_RSP_R1:
+ case MMC_RSP_R1B:
+ /* resp 1, 1b, 6, 7 */
resptype = 1;
break;
- case RSP_TYPE(MMC_RSP_R2):
+ case MMC_RSP_R2:
resptype = 2;
break;
- case RSP_TYPE(MMC_RSP_R3):
+ case MMC_RSP_R3:
resptype = 3;
break;
default:
+ dev_err(mmc_dev(host->mmc), "Invalid response type: %04x\n", mmc_resp_type(cmd));
break;
}
@@ -581,9 +584,9 @@ static void mmc_omap_switch_timer(unsigned long arg)
schedule_work(&host->switch_work);
}
-static void mmc_omap_switch_handler(void *data)
+static void mmc_omap_switch_handler(struct work_struct *work)
{
- struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+ struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work);
struct mmc_card *card;
static int complained = 0;
int cards = 0, cover_open;
@@ -1116,7 +1119,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
if (host->switch_pin >= 0) {
- INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
+ INIT_WORK(&host->switch_work, mmc_omap_switch_handler);
init_timer(&host->switch_timer);
host->switch_timer.function = mmc_omap_switch_timer;
host->switch_timer.data = (unsigned long) host;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index 471e9f4e053..6073d998b11 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -171,7 +171,7 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
switch (RSP_TYPE(mmc_resp_type(cmd))) {
- case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6 */
+ case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */
cmdat |= CMDAT_RESP_SHORT;
break;
case RSP_TYPE(MMC_RSP_R3):
@@ -355,7 +355,7 @@ static int pxamci_get_ro(struct mmc_host *mmc)
struct pxamci_host *host = mmc_priv(mmc);
if (host->pdata && host->pdata->get_ro)
- return host->pdata->get_ro(mmc->dev);
+ return host->pdata->get_ro(mmc_dev(mmc));
/* Host doesn't support read only detection so assume writeable */
return 0;
}
@@ -383,7 +383,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->power_mode = ios->power_mode;
if (host->pdata && host->pdata->setpower)
- host->pdata->setpower(mmc->dev, ios->vdd);
+ host->pdata->setpower(mmc_dev(mmc), ios->vdd);
if (ios->power_mode == MMC_POWER_ON)
host->cmdat |= CMDAT_INIT;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index cd98117632d..c2d13d7e991 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -1170,8 +1170,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
}
if (pci_resource_len(pdev, first_bar + slot) != 0x100) {
- printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. Aborting.\n");
- return -ENODEV;
+ printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. "
+ "You may experience problems.\n");
}
if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
index e846499a004..fa4a52886b9 100644
--- a/drivers/mmc/tifm_sd.c
+++ b/drivers/mmc/tifm_sd.c
@@ -173,9 +173,6 @@ static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
case MMC_RSP_R3:
rc |= TIFM_MMCSD_RSP_R3;
break;
- case MMC_RSP_R6:
- rc |= TIFM_MMCSD_RSP_R6;
- break;
default:
BUG();
}
@@ -387,7 +384,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd)
writel(TIFM_FIFO_INT_SETALL,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
- writel(long_log2(cmd->data->blksz) - 2,
+ writel(ilog2(cmd->data->blksz) - 2,
sock->addr + SOCK_FIFO_PAGE_SIZE);
writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index a304b34c263..26f75c29944 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -164,9 +164,15 @@ config MTD_CHAR
memory chips, and also use ioctl() to obtain information about
the device, or to erase parts of it.
+config MTD_BLKDEVS
+ tristate "Common interface to block layer for MTD 'translation layers'"
+ depends on MTD && BLOCK
+ default n
+
config MTD_BLOCK
tristate "Caching block device access to MTD devices"
depends on MTD && BLOCK
+ select MTD_BLKDEVS
---help---
Although most flash chips have an erase size too large to be useful
as block devices, it is possible to use MTD devices which are based
@@ -189,6 +195,7 @@ config MTD_BLOCK
config MTD_BLOCK_RO
tristate "Readonly block device access to MTD devices"
depends on MTD_BLOCK!=y && MTD && BLOCK
+ select MTD_BLKDEVS
help
This allows you to mount read-only file systems (such as cramfs)
from an MTD device, without the overhead (and danger) of the caching
@@ -200,6 +207,7 @@ config MTD_BLOCK_RO
config FTL
tristate "FTL (Flash Translation Layer) support"
depends on MTD && BLOCK
+ select MTD_BLKDEVS
---help---
This provides support for the original Flash Translation Layer which
is part of the PCMCIA specification. It uses a kind of pseudo-
@@ -216,6 +224,7 @@ config FTL
config NFTL
tristate "NFTL (NAND Flash Translation Layer) support"
depends on MTD && BLOCK
+ select MTD_BLKDEVS
---help---
This provides support for the NAND Flash Translation Layer which is
used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
@@ -239,6 +248,7 @@ config NFTL_RW
config INFTL
tristate "INFTL (Inverse NAND Flash Translation Layer) support"
depends on MTD && BLOCK
+ select MTD_BLKDEVS
---help---
This provides support for the Inverse NAND Flash Translation
Layer which is used on M-Systems' newer DiskOnChip devices. It
@@ -256,6 +266,7 @@ config INFTL
config RFD_FTL
tristate "Resident Flash Disk (Flash Translation Layer) support"
depends on MTD && BLOCK
+ select MTD_BLKDEVS
---help---
This provides support for the flash translation layer known
as the Resident Flash Disk (RFD), as used by the Embedded BIOS
@@ -265,8 +276,8 @@ config RFD_FTL
config SSFDC
tristate "NAND SSFDC (SmartMedia) read only translation layer"
- depends on MTD
- default n
+ depends on MTD && BLOCK
+ select MTD_BLKDEVS
help
This enables read only access to SmartMedia formatted NAND
flash. You can mount it with FAT file system.
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 1e36b9aed98..c130e6261ad 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -15,13 +15,14 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
# 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
-obj-$(CONFIG_MTD_BLOCK) += mtdblock.o mtd_blkdevs.o
-obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o
-obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o
-obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o
-obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o
-obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o
-obj-$(CONFIG_SSFDC) += ssfdc.o mtd_blkdevs.o
+obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
+obj-$(CONFIG_MTD_BLOCK) += mtdblock.o
+obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o
+obj-$(CONFIG_FTL) += ftl.o
+obj-$(CONFIG_NFTL) += nftl.o
+obj-$(CONFIG_INFTL) += inftl.o
+obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
+obj-$(CONFIG_SSFDC) += ssfdc.o
nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index 6a45be04564..52d51eb91c1 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -207,11 +207,10 @@ static int parse_afs_partitions(struct mtd_info *mtd,
if (!sz)
return ret;
- parts = kmalloc(sz, GFP_KERNEL);
+ parts = kzalloc(sz, GFP_KERNEL);
if (!parts)
return -ENOMEM;
- memset(parts, 0, sz);
str = (char *)(parts + idx);
/*
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
index 16eaca69fb5..e7999f15d85 100644
--- a/drivers/mtd/chips/amd_flash.c
+++ b/drivers/mtd/chips/amd_flash.c
@@ -643,13 +643,12 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
int reg_idx;
int offset;
- mtd = (struct mtd_info*)kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd) {
printk(KERN_WARNING
"%s: kmalloc failed for info structure\n", map->name);
return NULL;
}
- memset(mtd, 0, sizeof(*mtd));
mtd->priv = map;
memset(&temp, 0, sizeof(temp));
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 296159ec518..f69184a92eb 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -337,12 +337,11 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
struct mtd_info *mtd;
int i;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd) {
printk(KERN_ERR "Failed to allocate memory for MTD device\n");
return NULL;
}
- memset(mtd, 0, sizeof(*mtd));
mtd->priv = map;
mtd->type = MTD_NORFLASH;
@@ -2224,6 +2223,8 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
case FL_CFI_QUERY:
case FL_JEDEC_QUERY:
if (chip->oldstate == FL_READY) {
+ /* place the chip in a known state before suspend */
+ map_write(map, CMD(0xFF), cfi->chips[i].start);
chip->oldstate = chip->state;
chip->state = FL_PM_SUSPENDED;
/* No need to wake_up() on this state change -
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 702ae4cd869..e3acd398fb3 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -48,6 +48,7 @@
#define MANUFACTURER_ATMEL 0x001F
#define MANUFACTURER_SST 0x00BF
#define SST49LF004B 0x0060
+#define SST49LF040B 0x0050
#define SST49LF008A 0x005a
#define AT49BV6416 0x00d6
@@ -233,6 +234,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
};
static struct cfi_fixup jedec_fixup_table[] = {
{ MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
+ { MANUFACTURER_SST, SST49LF040B, fixup_use_fwh_lock, NULL, },
{ MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },
{ 0, 0, NULL, NULL }
};
@@ -255,12 +257,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
struct mtd_info *mtd;
int i;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd) {
printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
return NULL;
}
- memset(mtd, 0, sizeof(*mtd));
mtd->priv = map;
mtd->type = MTD_NORFLASH;
@@ -519,10 +520,12 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
goto sleep;
- if (!(mode == FL_READY || mode == FL_POINT
+ if (!( mode == FL_READY
+ || mode == FL_POINT
|| !cfip
|| (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
- || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1))))
+ || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)
+ )))
goto sleep;
/* We could check to see if we're trying to access the sector
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index fae70a5db54..d56849f5f10 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -172,7 +172,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
int i,j;
unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
if (!mtd) {
@@ -181,7 +181,6 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
return NULL;
}
- memset(mtd, 0, sizeof(*mtd));
mtd->priv = map;
mtd->type = MTD_NORFLASH;
mtd->size = devsize * cfi->numchips;
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index cdb0f590b40..2eb696d7b97 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -40,7 +40,7 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
if (mtd) {
if (mtd->size > map->size) {
printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n",
- (unsigned long)mtd->size >> 10,
+ (unsigned long)mtd->size >> 10,
(unsigned long)map->size >> 10);
mtd->size = map->size;
}
@@ -113,13 +113,12 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
}
mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG;
- chip_map = kmalloc(mapsize, GFP_KERNEL);
+ chip_map = kzalloc(mapsize, GFP_KERNEL);
if (!chip_map) {
printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
kfree(cfi.cfiq);
return NULL;
}
- memset (chip_map, 0, mapsize);
set_bit(0, chip_map); /* Mark first chip valid */
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index 2c3f019197c..14e57b2bf84 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -116,11 +116,10 @@ static struct mtd_info *jedec_probe(struct map_info *map)
char Part[200];
memset(&priv,0,sizeof(priv));
- MTD = kmalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
+ MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);
if (!MTD)
return NULL;
- memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));
priv = (struct jedec_private *)&MTD[1];
my_bank_size = map->size;
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 1154dac715a..58e561e8769 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -154,6 +154,7 @@
#define SST39SF010A 0x00B5
#define SST39SF020A 0x00B6
#define SST49LF004B 0x0060
+#define SST49LF040B 0x0050
#define SST49LF008A 0x005a
#define SST49LF030A 0x001C
#define SST49LF040A 0x0051
@@ -1401,6 +1402,20 @@ static const struct amd_flash_info jedec_table[] = {
}
}, {
.mfr_id = MANUFACTURER_SST,
+ .dev_id = SST49LF040B,
+ .name = "SST 49LF040B",
+ .uaddr = {
+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x01000,128),
+ }
+ }, {
+
+ .mfr_id = MANUFACTURER_SST,
.dev_id = SST49LF004B,
.name = "SST 49LF004B",
.uaddr = {
@@ -1874,7 +1889,7 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
/*
- * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing
+ * There is a BIG problem properly ID'ing the JEDEC device and guaranteeing
* the mapped address, unlock addresses, and proper chip ID. This function
* attempts to minimize errors. It is doubtfull that this probe will ever
* be perfect - consequently there should be some module parameters that
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c
index ac01a949b68..fc478c0f93f 100644
--- a/drivers/mtd/chips/map_absent.c
+++ b/drivers/mtd/chips/map_absent.c
@@ -47,13 +47,11 @@ static struct mtd_info *map_absent_probe(struct map_info *map)
{
struct mtd_info *mtd;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd) {
return NULL;
}
- memset(mtd, 0, sizeof(*mtd));
-
map->fldrv = &map_absent_chipdrv;
mtd->priv = map;
mtd->name = map->name;
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c
index 3a66680abfd..5cb6d526366 100644
--- a/drivers/mtd/chips/map_ram.c
+++ b/drivers/mtd/chips/map_ram.c
@@ -55,12 +55,10 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
#endif
/* OK. It seems to be RAM. */
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd)
return NULL;
- memset(mtd, 0, sizeof(*mtd));
-
map->fldrv = &mapram_chipdrv;
mtd->priv = map;
mtd->name = map->name;
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 1b328b1378f..cb27f855074 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -31,12 +31,10 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
{
struct mtd_info *mtd;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd)
return NULL;
- memset(mtd, 0, sizeof(*mtd));
-
map->fldrv = &maprom_chipdrv;
mtd->priv = map;
mtd->name = map->name;
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index 967abbecdff..c9cd3d21ccf 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -112,18 +112,16 @@ static struct mtd_info *sharp_probe(struct map_info *map)
struct sharp_info *sharp = NULL;
int width;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if(!mtd)
return NULL;
- sharp = kmalloc(sizeof(*sharp), GFP_KERNEL);
+ sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
if(!sharp) {
kfree(mtd);
return NULL;
}
- memset(mtd, 0, sizeof(*mtd));
-
width = sharp_probe_map(map,mtd);
if(!width){
kfree(mtd);
@@ -143,7 +141,6 @@ static struct mtd_info *sharp_probe(struct map_info *map)
mtd->writesize = 1;
mtd->name = map->name;
- memset(sharp, 0, sizeof(*sharp));
sharp->chipshift = 23;
sharp->numchips = 1;
sharp->chips[0].start = 0;
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index a7a7bfe3387..23fab14f163 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -163,13 +163,12 @@ static struct mtd_partition * newpart(char *s,
*num_parts = this_part + 1;
alloc_size = *num_parts * sizeof(struct mtd_partition) +
extra_mem_size;
- parts = kmalloc(alloc_size, GFP_KERNEL);
+ parts = kzalloc(alloc_size, GFP_KERNEL);
if (!parts)
{
printk(KERN_ERR ERRP "out of memory\n");
return NULL;
}
- memset(parts, 0, alloc_size);
extra_mem = (unsigned char *)(parts + *num_parts);
}
/* enter this partition (offset will be calculated later if it is zero at this point) */
@@ -346,7 +345,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
*
* This function needs to be visible for bootloaders.
*/
-int mtdpart_setup(char *s)
+static int mtdpart_setup(char *s)
{
cmdline = s;
return 1;
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 401c6a294ba..6d917a4daa9 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -295,10 +295,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
if (!devname)
return NULL;
- dev = kmalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
if (!dev)
return NULL;
- memset(dev, 0, sizeof(*dev));
/* Get a handle on the device */
bdev = open_bdev_excl(devname, O_RDWR, NULL);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 334e078ffaf..78c2511ae9e 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -437,7 +437,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
* or JEDEC get-id commands. Try them ...
*/
DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
- flash->spi->dev.bus_id);
+ spi->dev.bus_id);
return -ENODEV;
}
@@ -447,7 +447,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
}
if (i == ARRAY_SIZE(m25p_data)) {
DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
- flash->spi->dev.bus_id, data->type);
+ spi->dev.bus_id, data->type);
return -ENODEV;
}
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 08dfb899b27..9cff119a202 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -131,11 +131,10 @@ static int __init ms02nv_init_one(ulong addr)
int ret = -ENODEV;
/* The module decodes 8MiB of address space. */
- mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL);
+ mod_res = kzalloc(sizeof(*mod_res), GFP_KERNEL);
if (!mod_res)
return -ENOMEM;
- memset(mod_res, 0, sizeof(*mod_res));
mod_res->name = ms02nv_name;
mod_res->start = addr;
mod_res->end = addr + MS02NV_SLOT_SIZE - 1;
@@ -153,24 +152,21 @@ static int __init ms02nv_init_one(ulong addr)
}
ret = -ENOMEM;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if (!mtd)
goto err_out_mod_res_rel;
- memset(mtd, 0, sizeof(*mtd));
- mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+ mp = kzalloc(sizeof(*mp), GFP_KERNEL);
if (!mp)
goto err_out_mtd;
- memset(mp, 0, sizeof(*mp));
mtd->priv = mp;
mp->resource.module = mod_res;
/* Firmware's diagnostic NVRAM area. */
- diag_res = kmalloc(sizeof(*diag_res), GFP_KERNEL);
+ diag_res = kzalloc(sizeof(*diag_res), GFP_KERNEL);
if (!diag_res)
goto err_out_mp;
- memset(diag_res, 0, sizeof(*diag_res));
diag_res->name = ms02nv_res_diag_ram;
diag_res->start = addr;
diag_res->end = addr + MS02NV_RAM - 1;
@@ -180,11 +176,10 @@ static int __init ms02nv_init_one(ulong addr)
mp->resource.diag_ram = diag_res;
/* User-available general-purpose NVRAM area. */
- user_res = kmalloc(sizeof(*user_res), GFP_KERNEL);
+ user_res = kzalloc(sizeof(*user_res), GFP_KERNEL);
if (!user_res)
goto err_out_diag_res;
- memset(user_res, 0, sizeof(*user_res));
user_res->name = ms02nv_res_user_ram;
user_res->start = addr + MS02NV_RAM;
user_res->end = addr + size - 1;
@@ -194,11 +189,10 @@ static int __init ms02nv_init_one(ulong addr)
mp->resource.user_ram = user_res;
/* Control and status register. */
- csr_res = kmalloc(sizeof(*csr_res), GFP_KERNEL);
+ csr_res = kzalloc(sizeof(*csr_res), GFP_KERNEL);
if (!csr_res)
goto err_out_user_res;
- memset(csr_res, 0, sizeof(*csr_res));
csr_res->name = ms02nv_res_csr;
csr_res->start = addr + MS02NV_CSR;
csr_res->end = addr + MS02NV_CSR + 3;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 5db71604592..a987e917f4e 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -459,7 +459,7 @@ add_dataflash(struct spi_device *spi, char *name,
struct mtd_info *device;
struct flash_platform_data *pdata = spi->dev.platform_data;
- priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL);
+ priv = kzalloc(sizeof *priv, GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -480,7 +480,7 @@ add_dataflash(struct spi_device *spi, char *name,
device->writesize = pagesize;
device->owner = THIS_MODULE;
device->type = MTD_DATAFLASH;
- device->flags = MTD_CAP_NORFLASH;
+ device->flags = MTD_WRITEABLE;
device->erase = dataflash_erase;
device->read = dataflash_read;
device->write = dataflash_write;
@@ -536,7 +536,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
if (status <= 0 || status == 0xff) {
DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
spi->dev.bus_id, status);
- if (status == 0xff)
+ if (status == 0 || status == 0xff)
status = -ENODEV;
return status;
}
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 6c7337f9ebb..56cc1ca7ffd 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -126,12 +126,10 @@ static int register_device(char *name, unsigned long start, unsigned long len)
struct phram_mtd_list *new;
int ret = -ENOMEM;
- new = kmalloc(sizeof(*new), GFP_KERNEL);
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
if (!new)
goto out0;
- memset(new, 0, sizeof(*new));
-
ret = -EIO;
new->mtd.priv = ioremap(start, len);
if (!new->mtd.priv) {
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 542a0c00900..5f49248a485 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -168,19 +168,16 @@ static int register_device(char *name, unsigned long start, unsigned long length
E("slram: Cannot allocate new MTD device.\n");
return(-ENOMEM);
}
- (*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ (*curmtd)->mtdinfo = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
(*curmtd)->next = NULL;
if ((*curmtd)->mtdinfo) {
- memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info));
(*curmtd)->mtdinfo->priv =
- kmalloc(sizeof(slram_priv_t), GFP_KERNEL);
+ kzalloc(sizeof(slram_priv_t), GFP_KERNEL);
if (!(*curmtd)->mtdinfo->priv) {
kfree((*curmtd)->mtdinfo);
(*curmtd)->mtdinfo = NULL;
- } else {
- memset((*curmtd)->mtdinfo->priv,0,sizeof(slram_priv_t));
}
}
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 8a878b34eca..24235d4f1d2 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -1033,7 +1033,7 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
partition_t *partition;
- partition = kmalloc(sizeof(partition_t), GFP_KERNEL);
+ partition = kzalloc(sizeof(partition_t), GFP_KERNEL);
if (!partition) {
printk(KERN_WARNING "No memory to scan for FTL on %s\n",
@@ -1041,8 +1041,6 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
return;
}
- memset(partition, 0, sizeof(partition_t));
-
partition->mbd.mtd = mtd;
if ((scan_header(partition) == 0) &&
@@ -1054,7 +1052,7 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
le32_to_cpu(partition->header.FormattedSize) >> 10);
#endif
partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9;
- partition->mbd.blksize = SECTOR_SIZE;
+
partition->mbd.tr = tr;
partition->mbd.devnum = -1;
if (!add_mtd_blktrans_dev((void *)partition))
@@ -1076,6 +1074,7 @@ struct mtd_blktrans_ops ftl_tr = {
.name = "ftl",
.major = FTL_MAJOR,
.part_bits = PART_BITS,
+ .blksize = SECTOR_SIZE,
.readsect = ftl_readsect,
.writesect = ftl_writesect,
.getgeo = ftl_getgeo,
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 4116535805f..b0e396504e6 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -67,17 +67,16 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
- inftl = kmalloc(sizeof(*inftl), GFP_KERNEL);
+ inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
if (!inftl) {
printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
return;
}
- memset(inftl, 0, sizeof(*inftl));
inftl->mbd.mtd = mtd;
inftl->mbd.devnum = -1;
- inftl->mbd.blksize = 512;
+
inftl->mbd.tr = tr;
if (INFTL_mount(inftl) < 0) {
@@ -163,10 +162,9 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
ops.ooblen = len;
ops.oobbuf = buf;
ops.datbuf = NULL;
- ops.len = len;
res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
- *retlen = ops.retlen;
+ *retlen = ops.oobretlen;
return res;
}
@@ -184,10 +182,9 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
ops.ooblen = len;
ops.oobbuf = buf;
ops.datbuf = NULL;
- ops.len = len;
res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
- *retlen = ops.retlen;
+ *retlen = ops.oobretlen;
return res;
}
@@ -945,6 +942,7 @@ static struct mtd_blktrans_ops inftl_tr = {
.name = "inftl",
.major = INFTL_MAJOR,
.part_bits = INFTL_PARTN_BITS,
+ .blksize = 512,
.getgeo = inftl_getgeo,
.readsect = inftl_readblock,
.writesect = inftl_writeblock,
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index d132ed571f1..f457315579d 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -60,6 +60,15 @@ config MTD_PHYSMAP_BANKWIDTH
Ignore this option if you use run-time physmap configuration
(i.e., run-time calling physmap_configure()).
+config MTD_PHYSMAP_OF
+ tristate "Flash device in physical memory map based on OF descirption"
+ depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM)
+ help
+ This provides a 'mapping' driver which allows the NOR Flash and
+ ROM driver code to communicate with chips which are mapped
+ physically into the CPU's memory. The mapping description here is
+ taken from OF device tree.
+
config MTD_SUN_UFLASH
tristate "Sun Microsystems userflash support"
depends on SPARC && MTD_CFI
@@ -184,6 +193,24 @@ config MTD_ICHXROM
BE VERY CAREFUL.
+config MTD_ESB2ROM
+ tristate "BIOS flash chip on Intel ESB Controller Hub 2"
+ depends on X86 && MTD_JEDECPROBE && PCI
+ help
+ Support for treating the BIOS flash chip on ESB2 motherboards
+ as an MTD device - with this you can reprogram your BIOS.
+
+ BE VERY CAREFUL.
+
+config MTD_CK804XROM
+ tristate "BIOS flash chip on Nvidia CK804"
+ depends on X86 && MTD_JEDECPROBE
+ help
+ Support for treating the BIOS flash chip on nvidia motherboards
+ as an MTD device - with this you can reprogram your BIOS.
+
+ BE VERY CAREFUL.
+
config MTD_SCB2_FLASH
tristate "BIOS flash chip on Intel SCB2 boards"
depends on X86 && MTD_JEDECPROBE
@@ -355,50 +382,6 @@ config MTD_TQM834x
TQ Components TQM834x 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
- help
- This provides a mapping driver for the Integrated Technology
- Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR
- Reference Board. It provides the necessary addressing, length,
- buswidth, vpp code and addition setup of the flash device for
- these boards. In addition, this mapping driver can be used for
- other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/
- LEN/BUSWIDTH parameters. This mapping will provide one mtd device
- using one partition. The start address can be offset from the
- beginning of flash and the len can be less than the total flash
- device size to allow a window into the flash. Both CFI and JEDEC
- probes are called.
-
-config MTD_CSTM_MIPS_IXX_START
- hex "Physical start address of flash mapping"
- depends on MTD_CSTM_MIPS_IXX
- default "0x8000000"
- help
- This is the physical memory location that the MTD driver will
- use for the flash chips on your particular target board.
- Refer to the memory map which should hopefully be in the
- documentation for your board.
-
-config MTD_CSTM_MIPS_IXX_LEN
- hex "Physical length of flash mapping"
- depends on MTD_CSTM_MIPS_IXX
- default "0x4000000"
- help
- This is the total length that the MTD driver will use for the
- flash chips on your particular board. Refer to the memory
- map which should hopefully be in the documentation for your
- board.
-
-config MTD_CSTM_MIPS_IXX_BUSWIDTH
- int "Bus width in octets"
- depends on MTD_CSTM_MIPS_IXX
- default "2"
- help
- This is the total bus width of the mapping of the flash chips
- on your particular board.
-
config MTD_OCELOT
tristate "Momenco Ocelot boot flash device"
depends on MIPS && MOMENCO_OCELOT
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 191c1928bbe..071d0bf922b 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -12,12 +12,13 @@ obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
obj-$(CONFIG_MTD_BAST) += bast-flash.o
obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
-obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
obj-$(CONFIG_MTD_DC21285) += dc21285.o
obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
obj-$(CONFIG_MTD_L440GX) += l440gx.o
obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
+obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o
obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
+obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_MTD_MBX860) += mbx860.o
obj-$(CONFIG_MTD_CEIVA) += ceiva.o
obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
+obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 797caffb20b..78b671172bb 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -44,6 +45,23 @@ struct amd76xrom_map_info {
char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
};
+/* The 2 bits controlling the window size are often set to allow reading
+ * the BIOS, but too small to allow writing, since the lock registers are
+ * 4MiB lower in the address space than the data.
+ *
+ * This is intended to prevent flashing the bios, perhaps accidentally.
+ *
+ * This parameter allows the normal driver to over-ride the BIOS settings.
+ *
+ * The bits are 6 and 7. If both bits are set, it is a 5MiB window.
+ * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a
+ * 64KiB window.
+ *
+ */
+static uint win_size_bits;
+module_param(win_size_bits, uint, 0);
+MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x43 byte, normally set by BIOS.");
+
static struct amd76xrom_window amd76xrom_window = {
.maps = LIST_HEAD_INIT(amd76xrom_window.maps),
};
@@ -95,6 +113,16 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
/* Remember the pci dev I find the window in - already have a ref */
window->pdev = pdev;
+ /* Enable the selected rom window. This is often incorrectly
+ * set up by the BIOS, and the 4MiB offset for the lock registers
+ * requires the full 5MiB of window space.
+ *
+ * This 'write, then read' approach leaves the bits for
+ * other uses of the hardware info.
+ */
+ pci_read_config_byte(pdev, 0x43, &byte);
+ pci_write_config_byte(pdev, 0x43, byte | win_size_bits );
+
/* Assume the rom window is properly setup, and find it's size */
pci_read_config_byte(pdev, 0x43, &byte);
if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
@@ -129,12 +157,6 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
(unsigned long long)window->rsrc.end);
}
-#if 0
-
- /* Enable the selected rom window */
- pci_read_config_byte(pdev, 0x43, &byte);
- pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
-#endif
/* Enable writes through the rom window */
pci_read_config_byte(pdev, 0x40, &byte);
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
index e074bb6787d..fc3b2672d1e 100644
--- a/drivers/mtd/maps/bast-flash.c
+++ b/drivers/mtd/maps/bast-flash.c
@@ -131,7 +131,7 @@ static int bast_flash_probe(struct platform_device *pdev)
info->map.phys = res->start;
info->map.size = res->end - res->start + 1;
- info->map.name = pdev->dev.bus_id;
+ info->map.name = pdev->dev.bus_id;
info->map.bankwidth = 2;
if (info->map.size > AREA_MAXSIZE)
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index 0402c21e291..629e6e2641a 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -122,10 +122,9 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info
/*
* Allocate the map_info structs in one go.
*/
- maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
+ maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
if (!maps)
return -ENOMEM;
- memset(maps, 0, sizeof(struct map_info) * nr);
/*
* Claim and then map the memory regions.
*/
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
new file mode 100644
index 00000000000..238d42e88ec
--- /dev/null
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -0,0 +1,356 @@
+/*
+ * ck804xrom.c
+ *
+ * Normal mappings of chips in physical memory
+ *
+ * Dave Olsen <dolsen@lnxi.com>
+ * Ryan Jackson <rjackson@lnxi.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.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/mtd/cfi.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/list.h>
+
+
+#define MOD_NAME KBUILD_BASENAME
+
+#define ADDRESS_NAME_LEN 18
+
+#define ROM_PROBE_STEP_SIZE (64*1024)
+
+struct ck804xrom_window {
+ void __iomem *virt;
+ unsigned long phys;
+ unsigned long size;
+ struct list_head maps;
+ struct resource rsrc;
+ struct pci_dev *pdev;
+};
+
+struct ck804xrom_map_info {
+ struct list_head list;
+ struct map_info map;
+ struct mtd_info *mtd;
+ struct resource rsrc;
+ char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
+};
+
+
+/* The 2 bits controlling the window size are often set to allow reading
+ * the BIOS, but too small to allow writing, since the lock registers are
+ * 4MiB lower in the address space than the data.
+ *
+ * This is intended to prevent flashing the bios, perhaps accidentally.
+ *
+ * This parameter allows the normal driver to override the BIOS settings.
+ *
+ * The bits are 6 and 7. If both bits are set, it is a 5MiB window.
+ * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a
+ * 64KiB window.
+ *
+ */
+static uint win_size_bits = 0;
+module_param(win_size_bits, uint, 0);
+MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS.");
+
+static struct ck804xrom_window ck804xrom_window = {
+ .maps = LIST_HEAD_INIT(ck804xrom_window.maps),
+};
+
+static void ck804xrom_cleanup(struct ck804xrom_window *window)
+{
+ struct ck804xrom_map_info *map, *scratch;
+ u8 byte;
+
+ if (window->pdev) {
+ /* Disable writes through the rom window */
+ pci_read_config_byte(window->pdev, 0x6d, &byte);
+ pci_write_config_byte(window->pdev, 0x6d, byte & ~1);
+ }
+
+ /* Free all of the mtd devices */
+ list_for_each_entry_safe(map, scratch, &window->maps, list) {
+ if (map->rsrc.parent)
+ release_resource(&map->rsrc);
+
+ del_mtd_device(map->mtd);
+ map_destroy(map->mtd);
+ list_del(&map->list);
+ kfree(map);
+ }
+ if (window->rsrc.parent)
+ release_resource(&window->rsrc);
+
+ if (window->virt) {
+ iounmap(window->virt);
+ window->virt = NULL;
+ window->phys = 0;
+ window->size = 0;
+ }
+ pci_dev_put(window->pdev);
+}
+
+
+static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+ u8 byte;
+ struct ck804xrom_window *window = &ck804xrom_window;
+ struct ck804xrom_map_info *map = NULL;
+ unsigned long map_top;
+
+ /* Remember the pci dev I find the window in */
+ window->pdev = pci_dev_get(pdev);
+
+ /* Enable the selected rom window. This is often incorrectly
+ * set up by the BIOS, and the 4MiB offset for the lock registers
+ * requires the full 5MiB of window space.
+ *
+ * This 'write, then read' approach leaves the bits for
+ * other uses of the hardware info.
+ */
+ pci_read_config_byte(pdev, 0x88, &byte);
+ pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
+
+
+ /* Assume the rom window is properly setup, and find it's size */
+ pci_read_config_byte(pdev, 0x88, &byte);
+
+ if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
+ window->phys = 0xffb00000; /* 5MiB */
+ else if ((byte & (1<<7)) == (1<<7))
+ window->phys = 0xffc00000; /* 4MiB */
+ else
+ window->phys = 0xffff0000; /* 64KiB */
+
+ window->size = 0xffffffffUL - window->phys + 1UL;
+
+ /*
+ * Try to reserve the window mem region. If this fails then
+ * it is likely due to a fragment of the window being
+ * "reserved" by the BIOS. In the case that the
+ * request_mem_region() fails then once the rom size is
+ * discovered we will try to reserve the unreserved fragment.
+ */
+ window->rsrc.name = MOD_NAME;
+ window->rsrc.start = window->phys;
+ window->rsrc.end = window->phys + window->size - 1;
+ window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ if (request_resource(&iomem_resource, &window->rsrc)) {
+ window->rsrc.parent = NULL;
+ printk(KERN_ERR MOD_NAME
+ " %s(): Unable to register resource"
+ " 0x%.016llx-0x%.016llx - kernel bug?\n",
+ __func__,
+ (unsigned long long)window->rsrc.start,
+ (unsigned long long)window->rsrc.end);
+ }
+
+
+ /* Enable writes through the rom window */
+ pci_read_config_byte(pdev, 0x6d, &byte);
+ pci_write_config_byte(pdev, 0x6d, byte | 1);
+
+ /* FIXME handle registers 0x80 - 0x8C the bios region locks */
+
+ /* For write accesses caches are useless */
+ window->virt = ioremap_nocache(window->phys, window->size);
+ if (!window->virt) {
+ printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
+ window->phys, window->size);
+ goto out;
+ }
+
+ /* Get the first address to look for a rom chip at */
+ map_top = window->phys;
+#if 1
+ /* The probe sequence run over the firmware hub lock
+ * registers sets them to 0x7 (no access).
+ * Probe at most the last 4MiB of the address space.
+ */
+ if (map_top < 0xffc00000)
+ map_top = 0xffc00000;
+#endif
+ /* Loop through and look for rom chips. Since we don't know the
+ * starting address for each chip, probe every ROM_PROBE_STEP_SIZE
+ * bytes from the starting address of the window.
+ */
+ while((map_top - 1) < 0xffffffffUL) {
+ struct cfi_private *cfi;
+ unsigned long offset;
+ int i;
+
+ if (!map)
+ map = kmalloc(sizeof(*map), GFP_KERNEL);
+
+ if (!map) {
+ printk(KERN_ERR MOD_NAME ": kmalloc failed");
+ goto out;
+ }
+ memset(map, 0, sizeof(*map));
+ INIT_LIST_HEAD(&map->list);
+ map->map.name = map->map_name;
+ map->map.phys = map_top;
+ offset = map_top - window->phys;
+ map->map.virt = (void __iomem *)
+ (((unsigned long)(window->virt)) + offset);
+ map->map.size = 0xffffffffUL - map_top + 1UL;
+ /* Set the name of the map to the address I am trying */
+ sprintf(map->map_name, "%s @%08lx",
+ MOD_NAME, map->map.phys);
+
+ /* There is no generic VPP support */
+ for(map->map.bankwidth = 32; map->map.bankwidth;
+ map->map.bankwidth >>= 1)
+ {
+ char **probe_type;
+ /* Skip bankwidths that are not supported */
+ if (!map_bankwidth_supported(map->map.bankwidth))
+ continue;
+
+ /* Setup the map methods */
+ simple_map_init(&map->map);
+
+ /* Try all of the probe methods */
+ probe_type = rom_probe_types;
+ for(; *probe_type; probe_type++) {
+ map->mtd = do_map_probe(*probe_type, &map->map);
+ if (map->mtd)
+ goto found;
+ }
+ }
+ map_top += ROM_PROBE_STEP_SIZE;
+ continue;
+ found:
+ /* Trim the size if we are larger than the map */
+ if (map->mtd->size > map->map.size) {
+ printk(KERN_WARNING MOD_NAME
+ " rom(%u) larger than window(%lu). fixing...\n",
+ map->mtd->size, map->map.size);
+ map->mtd->size = map->map.size;
+ }
+ if (window->rsrc.parent) {
+ /*
+ * Registering the MTD device in iomem may not be possible
+ * if there is a BIOS "reserved" and BUSY range. If this
+ * fails then continue anyway.
+ */
+ map->rsrc.name = map->map_name;
+ map->rsrc.start = map->map.phys;
+ map->rsrc.end = map->map.phys + map->mtd->size - 1;
+ map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ if (request_resource(&window->rsrc, &map->rsrc)) {
+ printk(KERN_ERR MOD_NAME
+ ": cannot reserve MTD resource\n");
+ map->rsrc.parent = NULL;
+ }
+ }
+
+ /* Make the whole region visible in the map */
+ map->map.virt = window->virt;
+ map->map.phys = window->phys;
+ cfi = map->map.fldrv_priv;
+ for(i = 0; i < cfi->numchips; i++)
+ cfi->chips[i].start += offset;
+
+ /* Now that the mtd devices is complete claim and export it */
+ map->mtd->owner = THIS_MODULE;
+ if (add_mtd_device(map->mtd)) {
+ map_destroy(map->mtd);
+ map->mtd = NULL;
+ goto out;
+ }
+
+
+ /* Calculate the new value of map_top */
+ map_top += map->mtd->size;
+
+ /* File away the map structure */
+ list_add(&map->list, &window->maps);
+ map = NULL;
+ }
+
+ out:
+ /* Free any left over map structures */
+ if (map)
+ kfree(map);
+
+ /* See if I have any map structures */
+ if (list_empty(&window->maps)) {
+ ck804xrom_cleanup(window);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+
+static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
+{
+ struct ck804xrom_window *window = &ck804xrom_window;
+
+ ck804xrom_cleanup(window);
+}
+
+static struct pci_device_id ck804xrom_pci_tbl[] = {
+ { PCI_VENDOR_ID_NVIDIA, 0x0051,
+ PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
+
+#if 0
+static struct pci_driver ck804xrom_driver = {
+ .name = MOD_NAME,
+ .id_table = ck804xrom_pci_tbl,
+ .probe = ck804xrom_init_one,
+ .remove = ck804xrom_remove_one,
+};
+#endif
+
+static int __init init_ck804xrom(void)
+{
+ struct pci_dev *pdev;
+ struct pci_device_id *id;
+ int retVal;
+ pdev = NULL;
+
+ for(id = ck804xrom_pci_tbl; id->vendor; id++) {
+ pdev = pci_find_device(id->vendor, id->device, NULL);
+ if (pdev)
+ break;
+ }
+ if (pdev) {
+ retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]);
+ pci_dev_put(pdev);
+ return retVal;
+ }
+ return -ENXIO;
+#if 0
+ return pci_module_init(&ck804xrom_driver);
+#endif
+}
+
+static void __exit cleanup_ck804xrom(void)
+{
+ ck804xrom_remove_one(ck804xrom_window.pdev);
+}
+
+module_init(init_ck804xrom);
+module_exit(cleanup_ck804xrom);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>, Dave Olsen <dolsen@lnxi.com>");
+MODULE_DESCRIPTION("MTD map driver for BIOS chips on the Nvidia ck804 southbridge");
+
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c
deleted file mode 100644
index df2c38ef105..00000000000
--- a/drivers/mtd/maps/cstm_mips_ixx.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * $Id: cstm_mips_ixx.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
- *
- * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
- * Config with both CFI and JEDEC device support.
- *
- * Basically physmap.c with the addition of partitions and
- * an array of mapping info to accomodate more than one flash type per board.
- *
- * Copyright 2000 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <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/mtd/partitions.h>
-#include <linux/delay.h>
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-#define CC_GCR 0xB4013818
-#define CC_GPBCR 0xB401380A
-#define CC_GPBDR 0xB4013808
-#define CC_M68K_DEVICE 1
-#define CC_M68K_FUNCTION 6
-#define CC_CONFADDR 0xB8004000
-#define CC_CONFDATA 0xB8004004
-#define CC_FC_FCR 0xB8002004
-#define CC_FC_DCR 0xB8002008
-#define CC_GPACR 0xB4013802
-#define CC_GPAICR 0xB4013804
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp)
-{
- static DEFINE_SPINLOCK(vpp_lock);
- static int vpp_count = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&vpp_lock, flags);
-
- if (vpp) {
- if (!vpp_count++) {
- __u16 data;
- __u8 data1;
- static u8 first = 1;
-
- // Set GPIO port B pin3 to high
- data = *(__u16 *)(CC_GPBCR);
- data = (data & 0xff0f) | 0x0040;
- *(__u16 *)CC_GPBCR = data;
- *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08;
- if (first) {
- first = 0;
- /* need to have this delay for first
- enabling vpp after powerup */
- udelay(40);
- }
- }
- } else {
- if (!--vpp_count) {
- __u16 data;
-
- // Set GPIO port B pin3 to high
- data = *(__u16 *)(CC_GPBCR);
- data = (data & 0xff3f) | 0x0040;
- *(__u16 *)CC_GPBCR = data;
- *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7;
- }
- }
- spin_unlock_irqrestore(&vpp_lock, flags);
-}
-#endif
-
-/* board and partition description */
-
-#define MAX_PHYSMAP_PARTITIONS 8
-struct cstm_mips_ixx_info {
- char *name;
- unsigned long window_addr;
- unsigned long window_size;
- int bankwidth;
- int num_partitions;
-};
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
-const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
-{
- { // 28F128J3A in 2x16 configuration
- "big flash", // name
- 0x08000000, // window_addr
- 0x02000000, // window_size
- 4, // bankwidth
- 1, // num_partitions
- }
-
-};
-static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
-{ // 28F128J3A in 2x16 configuration
- {
- .name = "main partition ",
- .size = 0x02000000, // 128 x 2 x 128k byte sectors
- .offset = 0,
- },
-},
-};
-#else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
-const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
-{
- {
- "MTD flash", // name
- CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr
- CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size
- CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth
- 1, // num_partitions
- },
-
-};
-static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
-{
- {
- .name = "main partition",
- .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN,
- .offset = 0,
- },
-},
-};
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER];
-
-int __init init_cstm_mips_ixx(void)
-{
- int i;
- int jedec;
- struct mtd_info *mymtd;
- struct mtd_partition *parts;
-
- /* Initialize mapping */
- for (i=0;i<PHYSMAP_NUMBER;i++) {
- printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n",
- cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr);
-
-
- cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
- cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
- if (!cstm_mips_ixx_map[i].virt) {
- int j = 0;
- printk(KERN_WARNING "Failed to ioremap\n");
- for (j = 0; j < i; j++) {
- if (cstm_mips_ixx_map[j].virt) {
- iounmap(cstm_mips_ixx_map[j].virt);
- cstm_mips_ixx_map[j].virt = NULL;
- }
- }
- return -EIO;
- }
- cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
- cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size;
- cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth;
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
- cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp;
-#endif
- simple_map_init(&cstm_mips_ixx_map[i]);
- //printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt));
- }
-
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
- setup_ITE_IVR_flash();
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
- for (i=0;i<PHYSMAP_NUMBER;i++) {
- parts = &cstm_mips_ixx_partitions[i][0];
- jedec = 0;
- mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]);
- //printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd);
- if (!mymtd) {
- jedec = 1;
- mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]);
- printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd);
- }
- if (mymtd) {
- mymtd->owner = THIS_MODULE;
-
- cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd;
- add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions);
- }
- else {
- for (i = 0; i < PHYSMAP_NUMBER; i++) {
- if (cstm_mips_ixx_map[i].virt) {
- iounmap(cstm_mips_ixx_map[i].virt);
- cstm_mips_ixx_map[i].virt = NULL;
- }
- }
- return -ENXIO;
- }
- }
- return 0;
-}
-
-static void __exit cleanup_cstm_mips_ixx(void)
-{
- int i;
- struct mtd_info *mymtd;
-
- for (i=0;i<PHYSMAP_NUMBER;i++) {
- mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2;
- if (mymtd) {
- del_mtd_partitions(mymtd);
- map_destroy(mymtd);
- }
- if (cstm_mips_ixx_map[i].virt) {
- iounmap((void *)cstm_mips_ixx_map[i].virt);
- cstm_mips_ixx_map[i].virt = 0;
- }
- }
-}
-#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
-void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data)
-{
- __u32 offset;
-
- offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ;
-
- *(__u32 *)CC_CONFADDR = offset;
- *(__u32 *)CC_CONFDATA = data;
-}
-void setup_ITE_IVR_flash()
-{
- __u32 size, base;
-
- size = 0x0e000000; // 32MiB
- base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit
-
- /* need to set ITE flash to 32 bits instead of default 8 */
-#ifdef CONFIG_MIPS_IVR
- *(__u32 *)CC_FC_FCR = 0x55;
- *(__u32 *)CC_GPACR = 0xfffc;
-#else
- *(__u32 *)CC_FC_FCR = 0x77;
-#endif
- /* turn bursting off */
- *(__u32 *)CC_FC_DCR = 0x0;
-
- /* setup for one chip 4 byte PCI access */
- PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base);
- PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02);
-}
-#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
-
-module_init(init_cstm_mips_ixx);
-module_exit(cleanup_cstm_mips_ixx);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
-MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards");
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
new file mode 100644
index 00000000000..a9d808a617c
--- /dev/null
+++ b/drivers/mtd/maps/esb2rom.c
@@ -0,0 +1,450 @@
+/*
+ * esb2rom.c
+ *
+ * Normal mappings of flash chips in physical memory
+ * through the Intel ESB2 Southbridge.
+ *
+ * This was derived from ichxrom.c in May 2006 by
+ * Lew Glendenning <lglendenning@lnxi.com>
+ *
+ * Eric Biederman, of course, was a major help in this effort.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.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/mtd/cfi.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/list.h>
+
+#define MOD_NAME KBUILD_BASENAME
+
+#define ADDRESS_NAME_LEN 18
+
+#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
+
+#define BIOS_CNTL 0xDC
+#define BIOS_LOCK_ENABLE 0x02
+#define BIOS_WRITE_ENABLE 0x01
+
+/* This became a 16-bit register, and EN2 has disappeared */
+#define FWH_DEC_EN1 0xD8
+#define FWH_F8_EN 0x8000
+#define FWH_F0_EN 0x4000
+#define FWH_E8_EN 0x2000
+#define FWH_E0_EN 0x1000
+#define FWH_D8_EN 0x0800
+#define FWH_D0_EN 0x0400
+#define FWH_C8_EN 0x0200
+#define FWH_C0_EN 0x0100
+#define FWH_LEGACY_F_EN 0x0080
+#define FWH_LEGACY_E_EN 0x0040
+/* reserved 0x0020 and 0x0010 */
+#define FWH_70_EN 0x0008
+#define FWH_60_EN 0x0004
+#define FWH_50_EN 0x0002
+#define FWH_40_EN 0x0001
+
+/* these are 32-bit values */
+#define FWH_SEL1 0xD0
+#define FWH_SEL2 0xD4
+
+#define FWH_8MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+ FWH_70_EN | FWH_60_EN | FWH_50_EN | FWH_40_EN)
+
+#define FWH_7MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+ FWH_70_EN | FWH_60_EN | FWH_50_EN)
+
+#define FWH_6MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+ FWH_70_EN | FWH_60_EN)
+
+#define FWH_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
+ FWH_70_EN)
+
+#define FWH_4MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN)
+
+#define FWH_3_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN | FWH_C8_EN)
+
+#define FWH_3MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN | FWH_D0_EN)
+
+#define FWH_2_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
+ FWH_D8_EN)
+
+#define FWH_2MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN)
+
+#define FWH_1_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN)
+
+#define FWH_1MiB (FWH_F8_EN | FWH_F0_EN)
+
+#define FWH_0_5MiB (FWH_F8_EN)
+
+
+struct esb2rom_window {
+ void __iomem* virt;
+ unsigned long phys;
+ unsigned long size;
+ struct list_head maps;
+ struct resource rsrc;
+ struct pci_dev *pdev;
+};
+
+struct esb2rom_map_info {
+ struct list_head list;
+ struct map_info map;
+ struct mtd_info *mtd;
+ struct resource rsrc;
+ char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
+};
+
+static struct esb2rom_window esb2rom_window = {
+ .maps = LIST_HEAD_INIT(esb2rom_window.maps),
+};
+
+static void esb2rom_cleanup(struct esb2rom_window *window)
+{
+ struct esb2rom_map_info *map, *scratch;
+ u8 byte;
+
+ /* Disable writes through the rom window */
+ pci_read_config_byte(window->pdev, BIOS_CNTL, &byte);
+ pci_write_config_byte(window->pdev, BIOS_CNTL,
+ byte & ~BIOS_WRITE_ENABLE);
+
+ /* Free all of the mtd devices */
+ list_for_each_entry_safe(map, scratch, &window->maps, list) {
+ if (map->rsrc.parent)
+ release_resource(&map->rsrc);
+ del_mtd_device(map->mtd);
+ map_destroy(map->mtd);
+ list_del(&map->list);
+ kfree(map);
+ }
+ if (window->rsrc.parent)
+ release_resource(&window->rsrc);
+ if (window->virt) {
+ iounmap(window->virt);
+ window->virt = NULL;
+ window->phys = 0;
+ window->size = 0;
+ }
+ pci_dev_put(window->pdev);
+}
+
+static int __devinit esb2rom_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+ struct esb2rom_window *window = &esb2rom_window;
+ struct esb2rom_map_info *map = NULL;
+ unsigned long map_top;
+ u8 byte;
+ u16 word;
+
+ /* For now I just handle the ecb2 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 16MiB but it is very painful. Also since
+ * you can only really attach a FWH to an ICHX there
+ * a number of simplifications you can make.
+ *
+ * Also you can page firmware hubs if an 8MiB window isn't enough
+ * but don't currently handle that case either.
+ */
+ window->pdev = pci_dev_get(pdev);
+
+ /* RLG: experiment 2. Force the window registers to the widest values */
+
+/*
+ pci_read_config_word(pdev, FWH_DEC_EN1, &word);
+ printk(KERN_DEBUG "Original FWH_DEC_EN1 : %x\n", word);
+ pci_write_config_byte(pdev, FWH_DEC_EN1, 0xff);
+ pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
+ printk(KERN_DEBUG "New FWH_DEC_EN1 : %x\n", byte);
+
+ pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
+ printk(KERN_DEBUG "Original FWH_DEC_EN2 : %x\n", byte);
+ pci_write_config_byte(pdev, FWH_DEC_EN2, 0x0f);
+ pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
+ printk(KERN_DEBUG "New FWH_DEC_EN2 : %x\n", byte);
+*/
+
+ /* Find a region continuous to the end of the ROM window */
+ window->phys = 0;
+ pci_read_config_word(pdev, FWH_DEC_EN1, &word);
+ printk(KERN_DEBUG "pci_read_config_byte : %x\n", word);
+
+ if ((word & FWH_8MiB) == FWH_8MiB)
+ window->phys = 0xff400000;
+ else if ((word & FWH_7MiB) == FWH_7MiB)
+ window->phys = 0xff500000;
+ else if ((word & FWH_6MiB) == FWH_6MiB)
+ window->phys = 0xff600000;
+ else if ((word & FWH_5MiB) == FWH_5MiB)
+ window->phys = 0xFF700000;
+ else if ((word & FWH_4MiB) == FWH_4MiB)
+ window->phys = 0xffc00000;
+ else if ((word & FWH_3_5MiB) == FWH_3_5MiB)
+ window->phys = 0xffc80000;
+ else if ((word & FWH_3MiB) == FWH_3MiB)
+ window->phys = 0xffd00000;
+ else if ((word & FWH_2_5MiB) == FWH_2_5MiB)
+ window->phys = 0xffd80000;
+ else if ((word & FWH_2MiB) == FWH_2MiB)
+ window->phys = 0xffe00000;
+ else if ((word & FWH_1_5MiB) == FWH_1_5MiB)
+ window->phys = 0xffe80000;
+ else if ((word & FWH_1MiB) == FWH_1MiB)
+ window->phys = 0xfff00000;
+ else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
+ window->phys = 0xfff80000;
+
+ /* reserved 0x0020 and 0x0010 */
+ window->phys -= 0x400000UL;
+ window->size = (0xffffffffUL - window->phys) + 1UL;
+
+ /* Enable writes through the rom window */
+ pci_read_config_byte(pdev, BIOS_CNTL, &byte);
+ if (!(byte & BIOS_WRITE_ENABLE) && (byte & (BIOS_LOCK_ENABLE))) {
+ /* The BIOS will generate an error if I enable
+ * this device, so don't even try.
+ */
+ printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
+ goto out;
+ }
+ pci_write_config_byte(pdev, BIOS_CNTL, byte | BIOS_WRITE_ENABLE);
+
+ /*
+ * Try to reserve the window mem region. If this fails then
+ * it is likely due to the window being "reseved" by the BIOS.
+ */
+ window->rsrc.name = MOD_NAME;
+ window->rsrc.start = window->phys;
+ window->rsrc.end = window->phys + window->size - 1;
+ window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ if (request_resource(&iomem_resource, &window->rsrc)) {
+ window->rsrc.parent = NULL;
+ printk(KERN_DEBUG MOD_NAME
+ ": %s(): Unable to register resource"
+ " 0x%.08llx-0x%.08llx - kernel bug?\n",
+ __func__,
+ (unsigned long long)window->rsrc.start,
+ (unsigned long long)window->rsrc.end);
+ }
+
+ /* Map the firmware hub into my address space. */
+ window->virt = ioremap_nocache(window->phys, window->size);
+ if (!window->virt) {
+ printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
+ window->phys, window->size);
+ goto out;
+ }
+
+ /* Get the first address to look for an rom chip at */
+ map_top = window->phys;
+ if ((window->phys & 0x3fffff) != 0) {
+ /* if not aligned on 4MiB, look 4MiB lower in address space */
+ map_top = window->phys + 0x400000;
+ }
+#if 1
+ /* The probe sequence run over the firmware hub lock
+ * registers sets them to 0x7 (no access).
+ * (Insane hardware design, but most copied Intel's.)
+ * ==> Probe at most the last 4M of the address space.
+ */
+ if (map_top < 0xffc00000)
+ map_top = 0xffc00000;
+#endif
+ /* Loop through and look for rom chips */
+ while ((map_top - 1) < 0xffffffffUL) {
+ struct cfi_private *cfi;
+ unsigned long offset;
+ int i;
+
+ if (!map)
+ map = kmalloc(sizeof(*map), GFP_KERNEL);
+ if (!map) {
+ printk(KERN_ERR MOD_NAME ": kmalloc failed");
+ goto out;
+ }
+ memset(map, 0, sizeof(*map));
+ INIT_LIST_HEAD(&map->list);
+ map->map.name = map->map_name;
+ map->map.phys = map_top;
+ offset = map_top - window->phys;
+ map->map.virt = (void __iomem *)
+ (((unsigned long)(window->virt)) + offset);
+ map->map.size = 0xffffffffUL - map_top + 1UL;
+ /* Set the name of the map to the address I am trying */
+ sprintf(map->map_name, "%s @%08lx",
+ MOD_NAME, map->map.phys);
+
+ /* Firmware hubs only use vpp when being programmed
+ * in a factory setting. So in-place programming
+ * needs to use a different method.
+ */
+ for(map->map.bankwidth = 32; map->map.bankwidth;
+ map->map.bankwidth >>= 1) {
+ char **probe_type;
+ /* Skip bankwidths that are not supported */
+ if (!map_bankwidth_supported(map->map.bankwidth))
+ continue;
+
+ /* Setup the map methods */
+ simple_map_init(&map->map);
+
+ /* Try all of the probe methods */
+ probe_type = rom_probe_types;
+ for(; *probe_type; probe_type++) {
+ map->mtd = do_map_probe(*probe_type, &map->map);
+ if (map->mtd)
+ goto found;
+ }
+ }
+ map_top += ROM_PROBE_STEP_SIZE;
+ continue;
+ found:
+ /* Trim the size if we are larger than the map */
+ if (map->mtd->size > map->map.size) {
+ printk(KERN_WARNING MOD_NAME
+ " rom(%u) larger than window(%lu). fixing...\n",
+ map->mtd->size, map->map.size);
+ map->mtd->size = map->map.size;
+ }
+ if (window->rsrc.parent) {
+ /*
+ * Registering the MTD device in iomem may not be possible
+ * if there is a BIOS "reserved" and BUSY range. If this
+ * fails then continue anyway.
+ */
+ map->rsrc.name = map->map_name;
+ map->rsrc.start = map->map.phys;
+ map->rsrc.end = map->map.phys + map->mtd->size - 1;
+ map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ if (request_resource(&window->rsrc, &map->rsrc)) {
+ printk(KERN_ERR MOD_NAME
+ ": cannot reserve MTD resource\n");
+ map->rsrc.parent = NULL;
+ }
+ }
+
+ /* Make the whole region visible in the map */
+ map->map.virt = window->virt;
+ map->map.phys = window->phys;
+ cfi = map->map.fldrv_priv;
+ for(i = 0; i < cfi->numchips; i++)
+ cfi->chips[i].start += offset;
+
+ /* Now that the mtd devices is complete claim and export it */
+ map->mtd->owner = THIS_MODULE;
+ if (add_mtd_device(map->mtd)) {
+ map_destroy(map->mtd);
+ map->mtd = NULL;
+ goto out;
+ }
+
+ /* Calculate the new value of map_top */
+ map_top += map->mtd->size;
+
+ /* File away the map structure */
+ list_add(&map->list, &window->maps);
+ map = NULL;
+ }
+
+ out:
+ /* Free any left over map structures */
+ kfree(map);
+
+ /* See if I have any map structures */
+ if (list_empty(&window->maps)) {
+ esb2rom_cleanup(window);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __devexit esb2rom_remove_one (struct pci_dev *pdev)
+{
+ struct esb2rom_window *window = &esb2rom_window;
+ esb2rom_cleanup(window);
+}
+
+static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = {
+ { 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, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { 0, },
+};
+
+#if 0
+MODULE_DEVICE_TABLE(pci, esb2rom_pci_tbl);
+
+static struct pci_driver esb2rom_driver = {
+ .name = MOD_NAME,
+ .id_table = esb2rom_pci_tbl,
+ .probe = esb2rom_init_one,
+ .remove = esb2rom_remove_one,
+};
+#endif
+
+static int __init init_esb2rom(void)
+{
+ struct pci_dev *pdev;
+ struct pci_device_id *id;
+ int retVal;
+
+ pdev = NULL;
+ for (id = esb2rom_pci_tbl; id->vendor; id++) {
+ printk(KERN_DEBUG "device id = %x\n", id->device);
+ pdev = pci_get_device(id->vendor, id->device, NULL);
+ if (pdev) {
+ printk(KERN_DEBUG "matched device = %x\n", id->device);
+ break;
+ }
+ }
+ if (pdev) {
+ printk(KERN_DEBUG "matched device id %x\n", id->device);
+ retVal = esb2rom_init_one(pdev, &esb2rom_pci_tbl[0]);
+ pci_dev_put(pdev);
+ printk(KERN_DEBUG "retVal = %d\n", retVal);
+ return retVal;
+ }
+ return -ENXIO;
+#if 0
+ return pci_register_driver(&esb2rom_driver);
+#endif
+}
+
+static void __exit cleanup_esb2rom(void)
+{
+ esb2rom_remove_one(esb2rom_window.pdev);
+}
+
+module_init(init_esb2rom);
+module_exit(cleanup_esb2rom);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lew Glendenning <lglendenning@lnxi.com>");
+MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ESB2 southbridge");
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index c8db01b3e45..6946d802e6f 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -75,14 +75,12 @@ static int armflash_probe(struct platform_device *dev)
int err;
void __iomem *base;
- info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
+ info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL);
if (!info) {
err = -ENOMEM;
goto out;
}
- memset(info, 0, sizeof(struct armflash_info));
-
info->plat = plat;
if (plat && plat->init) {
err = plat->init();
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index f9e8e5bcbc3..9f53c655af3 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -20,6 +20,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/cfi.h>
#include <linux/reboot.h>
+#include <linux/err.h>
#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <asm/io.h>
@@ -178,7 +179,7 @@ int nettel_eraseconfig(void)
init_waitqueue_head(&wait_q);
mtd = get_mtd_device(NULL, 2);
- if (mtd) {
+ if (!IS_ERR(mtd)) {
nettel_erase.mtd = mtd;
nettel_erase.callback = nettel_erasecallback;
nettel_erase.callback = NULL;
@@ -471,7 +472,7 @@ out_unmap2:
iounmap(nettel_amd_map.virt);
return(rc);
-
+
}
/****************************************************************************/
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index 418afffb2d8..e8d9ae53567 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -78,12 +78,10 @@ static int __devinit omapflash_probe(struct platform_device *pdev)
struct resource *res = pdev->resource;
unsigned long size = res->end - res->start + 1;
- info = kmalloc(sizeof(struct omapflash_info), GFP_KERNEL);
+ info = kzalloc(sizeof(struct omapflash_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- memset(info, 0, sizeof(struct omapflash_info));
-
if (!request_mem_region(res->start, size, "flash")) {
err = -EBUSY;
goto out_free_info;
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 995347b1beb..eaeb56a4070 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -735,11 +735,10 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
struct pcmciamtd_dev *dev;
/* Create new memory card device */
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) return -ENOMEM;
DEBUG(1, "dev=0x%p", dev);
- memset(dev, 0, sizeof(*dev));
dev->p_dev = link;
link->priv = dev;
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index d1717763f71..28c5ffd7523 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -89,15 +89,14 @@ static int physmap_flash_probe(struct platform_device *dev)
return -ENODEV;
printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
- (unsigned long long)dev->resource->end - dev->resource->start + 1,
+ (unsigned long long)(dev->resource->end - dev->resource->start + 1),
(unsigned long long)dev->resource->start);
- info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+ info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
goto err_out;
}
- memset(info, 0, sizeof(*info));
platform_set_drvdata(dev, info);
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
new file mode 100644
index 00000000000..7efe744ad31
--- /dev/null
+++ b/drivers/mtd/maps/physmap_of.c
@@ -0,0 +1,255 @@
+/*
+ * Normal mappings of chips in physical memory for OF devices
+ *
+ * Copyright (C) 2006 MontaVista Software Inc.
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+
+struct physmap_flash_info {
+ struct mtd_info *mtd;
+ struct map_info map;
+ struct resource *res;
+#ifdef CONFIG_MTD_PARTITIONS
+ int nr_parts;
+ struct mtd_partition *parts;
+#endif
+};
+
+static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+static int parse_flash_partitions(struct device_node *node,
+ struct mtd_partition **parts)
+{
+ int i, plen, retval = -ENOMEM;
+ const u32 *part;
+ const char *name;
+
+ part = get_property(node, "partitions", &plen);
+ if (part == NULL)
+ goto err;
+
+ retval = plen / (2 * sizeof(u32));
+ *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL);
+ if (*parts == NULL) {
+ printk(KERN_ERR "Can't allocate the flash partition data!\n");
+ goto err;
+ }
+
+ name = get_property(node, "partition-names", &plen);
+
+ for (i = 0; i < retval; i++) {
+ (*parts)[i].offset = *part++;
+ (*parts)[i].size = *part & ~1;
+ if (*part++ & 1) /* bit 0 set signifies read only partition */
+ (*parts)[i].mask_flags = MTD_WRITEABLE;
+
+ if (name != NULL && plen > 0) {
+ int len = strlen(name) + 1;
+
+ (*parts)[i].name = (char *)name;
+ plen -= len;
+ name += len;
+ } else
+ (*parts)[i].name = "unnamed";
+ }
+err:
+ return retval;
+}
+#endif
+
+static int of_physmap_remove(struct of_device *dev)
+{
+ struct physmap_flash_info *info;
+
+ info = dev_get_drvdata(&dev->dev);
+ if (info == NULL)
+ return 0;
+ dev_set_drvdata(&dev->dev, NULL);
+
+ if (info->mtd != NULL) {
+#ifdef CONFIG_MTD_PARTITIONS
+ if (info->nr_parts) {
+ del_mtd_partitions(info->mtd);
+ kfree(info->parts);
+ } else {
+ del_mtd_device(info->mtd);
+ }
+#else
+ del_mtd_device(info->mtd);
+#endif
+ map_destroy(info->mtd);
+ }
+
+ if (info->map.virt != NULL)
+ iounmap(info->map.virt);
+
+ if (info->res != NULL) {
+ release_resource(info->res);
+ kfree(info->res);
+ }
+
+ return 0;
+}
+
+static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match)
+{
+ struct device_node *dp = dev->node;
+ struct resource res;
+ struct physmap_flash_info *info;
+ const char **probe_type;
+ const char *of_probe;
+ const u32 *width;
+ int err;
+
+
+ if (of_address_to_resource(dp, 0, &res)) {
+ dev_err(&dev->dev, "Can't get the flash mapping!\n");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n",
+ (unsigned long long)res.end - res.start + 1,
+ (unsigned long long)res.start);
+
+ info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+ if (info == NULL) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ memset(info, 0, sizeof(*info));
+
+ dev_set_drvdata(&dev->dev, info);
+
+ info->res = request_mem_region(res.start, res.end - res.start + 1,
+ dev->dev.bus_id);
+ if (info->res == NULL) {
+ dev_err(&dev->dev, "Could not reserve memory region\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ width = get_property(dp, "bank-width", NULL);
+ if (width == NULL) {
+ dev_err(&dev->dev, "Can't get the flash bank width!\n");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ info->map.name = dev->dev.bus_id;
+ info->map.phys = res.start;
+ info->map.size = res.end - res.start + 1;
+ info->map.bankwidth = *width;
+
+ info->map.virt = ioremap(info->map.phys, info->map.size);
+ if (info->map.virt == NULL) {
+ dev_err(&dev->dev, "Failed to ioremap flash region\n");
+ err = EIO;
+ goto err_out;
+ }
+
+ simple_map_init(&info->map);
+
+ of_probe = get_property(dp, "probe-type", NULL);
+ if (of_probe == NULL) {
+ probe_type = rom_probe_types;
+ for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
+ info->mtd = do_map_probe(*probe_type, &info->map);
+ } else if (!strcmp(of_probe, "CFI"))
+ info->mtd = do_map_probe("cfi_probe", &info->map);
+ else if (!strcmp(of_probe, "JEDEC"))
+ info->mtd = do_map_probe("jedec_probe", &info->map);
+ else {
+ if (strcmp(of_probe, "ROM"))
+ dev_dbg(&dev->dev, "map_probe: don't know probe type "
+ "'%s', mapping as rom\n");
+ info->mtd = do_map_probe("mtd_rom", &info->map);
+ }
+ if (info->mtd == NULL) {
+ dev_err(&dev->dev, "map_probe failed\n");
+ err = -ENXIO;
+ goto err_out;
+ }
+ info->mtd->owner = THIS_MODULE;
+
+#ifdef CONFIG_MTD_PARTITIONS
+ err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
+ if (err > 0) {
+ add_mtd_partitions(info->mtd, info->parts, err);
+ } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) {
+ dev_info(&dev->dev, "Using OF partition information\n");
+ add_mtd_partitions(info->mtd, info->parts, err);
+ info->nr_parts = err;
+ } else
+#endif
+
+ add_mtd_device(info->mtd);
+ return 0;
+
+err_out:
+ of_physmap_remove(dev);
+ return err;
+
+ return 0;
+
+
+}
+
+static struct of_device_id of_physmap_match[] = {
+ {
+ .type = "rom",
+ .compatible = "direct-mapped"
+ },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, of_physmap_match);
+
+
+static struct of_platform_driver of_physmap_flash_driver = {
+ .name = "physmap-flash",
+ .match_table = of_physmap_match,
+ .probe = of_physmap_probe,
+ .remove = of_physmap_remove,
+};
+
+static int __init of_physmap_init(void)
+{
+ return of_register_platform_driver(&of_physmap_flash_driver);
+}
+
+static void __exit of_physmap_exit(void)
+{
+ of_unregister_platform_driver(&of_physmap_flash_driver);
+}
+
+module_init(of_physmap_init);
+module_exit(of_physmap_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
+MODULE_DESCRIPTION("Configurable MTD map driver for OF");
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 5d3c75451ca..2b6504ecbbd 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -147,14 +147,13 @@ static int platram_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) {
dev_err(&pdev->dev, "no memory for flash info\n");
err = -ENOMEM;
goto exit_error;
}
- memset(info, 0, sizeof(*info));
platform_set_drvdata(pdev, info);
info->dev = &pdev->dev;
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 950bf1c5784..f904e6bd02e 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -273,14 +273,12 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
/*
* Allocate the map_info structs in one go.
*/
- info = kmalloc(size, GFP_KERNEL);
+ info = kzalloc(size, GFP_KERNEL);
if (!info) {
ret = -ENOMEM;
goto out;
}
- memset(info, 0, size);
-
if (plat->init) {
ret = plat->init();
if (ret)
diff --git a/drivers/mtd/maps/tqm834x.c b/drivers/mtd/maps/tqm834x.c
index 58e5912bd38..9adc970e55e 100644
--- a/drivers/mtd/maps/tqm834x.c
+++ b/drivers/mtd/maps/tqm834x.c
@@ -132,20 +132,16 @@ static int __init init_tqm834x_mtd(void)
pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx);
- map_banks[idx] =
- (struct map_info *)kmalloc(sizeof(struct map_info),
- GFP_KERNEL);
+ map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
if (map_banks[idx] == NULL) {
ret = -ENOMEM;
goto error_mem;
}
- memset((void *)map_banks[idx], 0, sizeof(struct map_info));
- map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
+ map_banks[idx]->name = kzalloc(16, GFP_KERNEL);
if (map_banks[idx]->name == NULL) {
ret = -ENOMEM;
goto error_mem;
}
- memset((void *)map_banks[idx]->name, 0, 16);
sprintf(map_banks[idx]->name, "TQM834x-%d", idx);
map_banks[idx]->size = flash_size;
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 19578ba84ee..37e4ded9b60 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -134,14 +134,13 @@ int __init init_tqm_mtd(void)
printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
- map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL);
+ map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
if(map_banks[idx] == NULL) {
ret = -ENOMEM;
/* FIXME: What if some MTD devices were probed already? */
goto error_mem;
}
- memset((void *)map_banks[idx], 0, sizeof(struct map_info));
map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
if (!map_banks[idx]->name) {
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 178b53b56be..b879a66daa9 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -42,19 +42,20 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
unsigned long block, nsect;
char *buf;
- block = req->sector;
- nsect = req->current_nr_sectors;
+ block = req->sector << 9 >> tr->blkshift;
+ nsect = req->current_nr_sectors << 9 >> tr->blkshift;
+
buf = req->buffer;
if (!blk_fs_request(req))
return 0;
- if (block + nsect > get_capacity(req->rq_disk))
+ if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk))
return 0;
switch(rq_data_dir(req)) {
case READ:
- for (; nsect > 0; nsect--, block++, buf += 512)
+ for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->readsect(dev, block, buf))
return 0;
return 1;
@@ -63,7 +64,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
if (!tr->writesect)
return 0;
- for (; nsect > 0; nsect--, block++, buf += 512)
+ for (; nsect > 0; nsect--, block++, buf += tr->blksize)
if (tr->writesect(dev, block, buf))
return 0;
return 1;
@@ -297,7 +298,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
/* 2.5 has capacity in units of 512 bytes while still
having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
- set_capacity(gd, (new->size * new->blksize) >> 9);
+ set_capacity(gd, (new->size * tr->blksize) >> 9);
gd->private_data = new;
new->blkcore_priv = gd;
@@ -372,12 +373,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
if (!blktrans_notifier.list.next)
register_mtd_user(&blktrans_notifier);
- tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
+ tr->blkcore_priv = kzalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);
if (!tr->blkcore_priv)
return -ENOMEM;
- memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));
-
mutex_lock(&mtd_table_mutex);
ret = register_blkdev(tr->major, tr->name);
@@ -401,6 +400,8 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
}
tr->blkcore_priv->rq->queuedata = tr;
+ blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
+ tr->blkshift = ffs(tr->blksize) - 1;
ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL);
if (ret < 0) {
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 04ed34694b1..952da30b174 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -278,11 +278,10 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
}
/* OK, it's not open. Create cache info for it */
- mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
+ mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
if (!mtdblk)
return -ENOMEM;
- memset(mtdblk, 0, sizeof(*mtdblk));
mtdblk->count = 1;
mtdblk->mtd = mtd;
@@ -339,16 +338,14 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev)
static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
- struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return;
- memset(dev, 0, sizeof(*dev));
-
dev->mtd = mtd;
dev->devnum = mtd->index;
- dev->blksize = 512;
+
dev->size = mtd->size >> 9;
dev->tr = tr;
@@ -368,6 +365,7 @@ static struct mtd_blktrans_ops mtdblock_tr = {
.name = "mtdblock",
.major = 31,
.part_bits = 0,
+ .blksize = 512,
.open = mtdblock_open,
.flush = mtdblock_flush,
.release = mtdblock_release,
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index 29563ed258a..f79dbb49b1a 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -33,16 +33,14 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev,
static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
- struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return;
- memset(dev, 0, sizeof(*dev));
-
dev->mtd = mtd;
dev->devnum = mtd->index;
- dev->blksize = 512;
+
dev->size = mtd->size >> 9;
dev->tr = tr;
dev->readonly = 1;
@@ -60,6 +58,7 @@ static struct mtd_blktrans_ops mtdblock_tr = {
.name = "mtdblock",
.major = 31,
.part_bits = 0,
+ .blksize = 512,
.readsect = mtdblock_readsect,
.writesect = mtdblock_writesect,
.add_mtd = mtdblock_add_mtd,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 5b6acfcb2b8..3013d0883b9 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/fs.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -100,8 +101,8 @@ static int mtd_open(struct inode *inode, struct file *file)
mtd = get_mtd_device(NULL, devnum);
- if (!mtd)
- return -ENODEV;
+ if (IS_ERR(mtd))
+ return PTR_ERR(mtd);
if (MTD_ABSENT == mtd->type) {
put_mtd_device(mtd);
@@ -431,7 +432,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if(!(file->f_mode & 2))
return -EPERM;
- erase=kmalloc(sizeof(struct erase_info),GFP_KERNEL);
+ erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
if (!erase)
ret = -ENOMEM;
else {
@@ -440,7 +441,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
init_waitqueue_head(&waitq);
- memset (erase,0,sizeof(struct erase_info));
if (copy_from_user(&erase->addr, argp,
sizeof(struct erase_info_user))) {
kfree(erase);
@@ -499,13 +499,12 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (ret)
return ret;
- ops.len = buf.length;
ops.ooblen = buf.length;
ops.ooboffs = buf.start & (mtd->oobsize - 1);
ops.datbuf = NULL;
ops.mode = MTD_OOB_PLACE;
- if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs))
+ if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
return -EINVAL;
ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
@@ -520,7 +519,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
buf.start &= ~(mtd->oobsize - 1);
ret = mtd->write_oob(mtd, buf.start, &ops);
- if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen,
+ if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen,
sizeof(uint32_t)))
ret = -EFAULT;
@@ -548,7 +547,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (ret)
return ret;
- ops.len = buf.length;
ops.ooblen = buf.length;
ops.ooboffs = buf.start & (mtd->oobsize - 1);
ops.datbuf = NULL;
@@ -564,10 +562,10 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
buf.start &= ~(mtd->oobsize - 1);
ret = mtd->read_oob(mtd, buf.start, &ops);
- if (put_user(ops.retlen, (uint32_t __user *)argp))
+ if (put_user(ops.oobretlen, (uint32_t __user *)argp))
ret = -EFAULT;
- else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf,
- ops.retlen))
+ else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf,
+ ops.oobretlen))
ret = -EFAULT;
kfree(ops.oobbuf);
@@ -616,6 +614,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
sizeof(oi.oobfree));
+ oi.eccbytes = mtd->ecclayout->eccbytes;
if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
return -EFAULT;
@@ -715,7 +714,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (!mtd->ecclayout)
return -EOPNOTSUPP;
- if (copy_to_user(argp, &mtd->ecclayout,
+ if (copy_to_user(argp, mtd->ecclayout,
sizeof(struct nand_ecclayout)))
return -EFAULT;
break;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 1fea631b585..06902683bc2 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -247,7 +247,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
struct mtd_oob_ops devops = *ops;
int i, err, ret = 0;
- ops->retlen = 0;
+ ops->retlen = ops->oobretlen = 0;
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
@@ -263,6 +263,7 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
err = subdev->read_oob(subdev, from, &devops);
ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
/* Save information about bitflips! */
if (unlikely(err)) {
@@ -278,14 +279,18 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
return err;
}
- devops.len = ops->len - ops->retlen;
- if (!devops.len)
- return ret;
-
- if (devops.datbuf)
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return ret;
devops.datbuf += devops.retlen;
- if (devops.oobbuf)
- devops.oobbuf += devops.ooblen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return ret;
+ devops.oobbuf += ops->oobretlen;
+ }
from = 0;
}
@@ -321,14 +326,18 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
if (err)
return err;
- devops.len = ops->len - ops->retlen;
- if (!devops.len)
- return 0;
-
- if (devops.datbuf)
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return 0;
devops.datbuf += devops.retlen;
- if (devops.oobbuf)
- devops.oobbuf += devops.ooblen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return 0;
+ devops.oobbuf += devops.oobretlen;
+ }
to = 0;
}
return -EINVAL;
@@ -699,14 +708,13 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
/* allocate the device structure */
size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
- concat = kmalloc(size, GFP_KERNEL);
+ concat = kzalloc(size, GFP_KERNEL);
if (!concat) {
printk
("memory allocation error while creating concatenated device \"%s\"\n",
name);
return NULL;
}
- memset(concat, 0, size);
concat->subdev = (struct mtd_info **) (concat + 1);
/*
@@ -764,6 +772,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.ecc_stats.badblocks +=
subdev[i]->ecc_stats.badblocks;
if (concat->mtd.writesize != subdev[i]->writesize ||
+ concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
concat->mtd.oobsize != subdev[i]->oobsize ||
concat->mtd.ecctype != subdev[i]->ecctype ||
concat->mtd.eccsize != subdev[i]->eccsize ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c4d26de7434..7070110aba2 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -15,6 +15,7 @@
#include <linux/timer.h>
#include <linux/major.h>
#include <linux/fs.h>
+#include <linux/err.h>
#include <linux/ioctl.h>
#include <linux/init.h>
#include <linux/mtd/compatmac.h>
@@ -192,14 +193,14 @@ int unregister_mtd_user (struct mtd_notifier *old)
* Given a number and NULL address, return the num'th entry in the device
* table, if any. Given an address and num == -1, search the device table
* for a device with that address and return if it's still present. Given
- * both, return the num'th driver only if its address matches. Return NULL
- * if not.
+ * both, return the num'th driver only if its address matches. Return
+ * error code if not.
*/
struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
{
struct mtd_info *ret = NULL;
- int i;
+ int i, err = -ENODEV;
mutex_lock(&mtd_table_mutex);
@@ -213,14 +214,73 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
ret = NULL;
}
- if (ret && !try_module_get(ret->owner))
- ret = NULL;
+ if (!ret)
+ goto out_unlock;
+
+ if (!try_module_get(ret->owner))
+ goto out_unlock;
- if (ret)
- ret->usecount++;
+ if (ret->get_device) {
+ err = ret->get_device(ret);
+ if (err)
+ goto out_put;
+ }
+ ret->usecount++;
mutex_unlock(&mtd_table_mutex);
return ret;
+
+out_put:
+ module_put(ret->owner);
+out_unlock:
+ mutex_unlock(&mtd_table_mutex);
+ return ERR_PTR(err);
+}
+
+/**
+ * get_mtd_device_nm - obtain a validated handle for an MTD device by
+ * device name
+ * @name: MTD device name to open
+ *
+ * This function returns MTD device description structure in case of
+ * success and an error code in case of failure.
+ */
+
+struct mtd_info *get_mtd_device_nm(const char *name)
+{
+ int i, err = -ENODEV;
+ struct mtd_info *mtd = NULL;
+
+ mutex_lock(&mtd_table_mutex);
+
+ for (i = 0; i < MAX_MTD_DEVICES; i++) {
+ if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
+ mtd = mtd_table[i];
+ break;
+ }
+ }
+
+ if (!mtd)
+ goto out_unlock;
+
+ if (!try_module_get(mtd->owner))
+ goto out_unlock;
+
+ if (mtd->get_device) {
+ err = mtd->get_device(mtd);
+ if (err)
+ goto out_put;
+ }
+
+ mtd->usecount++;
+ mutex_unlock(&mtd_table_mutex);
+ return mtd;
+
+out_put:
+ module_put(mtd->owner);
+out_unlock:
+ mutex_unlock(&mtd_table_mutex);
+ return ERR_PTR(err);
}
void put_mtd_device(struct mtd_info *mtd)
@@ -229,6 +289,8 @@ void put_mtd_device(struct mtd_info *mtd)
mutex_lock(&mtd_table_mutex);
c = --mtd->usecount;
+ if (mtd->put_device)
+ mtd->put_device(mtd);
mutex_unlock(&mtd_table_mutex);
BUG_ON(c < 0);
@@ -236,7 +298,7 @@ void put_mtd_device(struct mtd_info *mtd)
}
/* default_mtd_writev - default mtd writev method for MTD devices that
- * dont implement their own
+ * don't implement their own
*/
int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
@@ -264,13 +326,14 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
return ret;
}
-EXPORT_SYMBOL(add_mtd_device);
-EXPORT_SYMBOL(del_mtd_device);
-EXPORT_SYMBOL(get_mtd_device);
-EXPORT_SYMBOL(put_mtd_device);
-EXPORT_SYMBOL(register_mtd_user);
-EXPORT_SYMBOL(unregister_mtd_user);
-EXPORT_SYMBOL(default_mtd_writev);
+EXPORT_SYMBOL_GPL(add_mtd_device);
+EXPORT_SYMBOL_GPL(del_mtd_device);
+EXPORT_SYMBOL_GPL(get_mtd_device);
+EXPORT_SYMBOL_GPL(get_mtd_device_nm);
+EXPORT_SYMBOL_GPL(put_mtd_device);
+EXPORT_SYMBOL_GPL(register_mtd_user);
+EXPORT_SYMBOL_GPL(unregister_mtd_user);
+EXPORT_SYMBOL_GPL(default_mtd_writev);
#ifdef CONFIG_PROC_FS
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 06a930372b7..bafd2fba87b 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -94,7 +94,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
if (from >= mtd->size)
return -EINVAL;
- if (from + ops->len > mtd->size)
+ if (ops->datbuf && from + ops->len > mtd->size)
return -EINVAL;
res = part->master->read_oob(part->master, from + part->offset, ops);
@@ -161,7 +161,7 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
if (to >= mtd->size)
return -EINVAL;
- if (to + ops->len > mtd->size)
+ if (ops->datbuf && to + ops->len > mtd->size)
return -EINVAL;
return part->master->write_oob(part->master, to + part->offset, ops);
}
@@ -323,14 +323,13 @@ int add_mtd_partitions(struct mtd_info *master,
for (i = 0; i < nbparts; i++) {
/* allocate the partition structure */
- slave = kmalloc (sizeof(*slave), GFP_KERNEL);
+ slave = kzalloc (sizeof(*slave), GFP_KERNEL);
if (!slave) {
printk ("memory allocation error while creating partitions for \"%s\"\n",
master->name);
del_mtd_partitions(master);
return -ENOMEM;
}
- memset(slave, 0, sizeof(*slave));
list_add(&slave->list, &mtd_partitions);
/* set up the MTD object for this partition */
@@ -341,6 +340,7 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.oobsize = master->oobsize;
slave->mtd.ecctype = master->ecctype;
slave->mtd.eccsize = master->eccsize;
+ slave->mtd.subpage_sft = master->subpage_sft;
slave->mtd.name = parts[i].name;
slave->mtd.bank_size = master->bank_size;
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1831340e5f5..358f55a82db 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -90,6 +90,7 @@ config MTD_NAND_RTC_FROM4
depends on MTD_NAND && SH_SOLUTION_ENGINE
select REED_SOLOMON
select REED_SOLOMON_DEC8
+ select BITREVERSE
help
This enables the driver for the Renesas Technology AG-AND
flash interface board (FROM_BOARD4)
@@ -132,6 +133,7 @@ config MTD_NAND_S3C2410_HWECC
config MTD_NAND_NDFC
tristate "NDFC NanD Flash Controller"
depends on MTD_NAND && 44x
+ select MTD_NAND_ECC_SMC
help
NDFC Nand Flash Controllers are integrated in EP44x SoCs
@@ -219,6 +221,13 @@ config MTD_NAND_SHARPSL
tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
depends on MTD_NAND && ARCH_PXA
+config MTD_NAND_CAFE
+ tristate "NAND support for OLPC CAFÉ chip"
+ depends on PCI
+ help
+ Use NAND flash attached to the CAFÉ chip designed for the $100
+ laptop.
+
config MTD_NAND_CS553X
tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
@@ -232,6 +241,13 @@ config MTD_NAND_CS553X
If you say "m", the module will be called "cs553x_nand.ko".
+config MTD_NAND_AT91
+ bool "Support for NAND Flash / SmartMedia on AT91"
+ depends on MTD_NAND && ARCH_AT91
+ help
+ Enables support for NAND Flash / Smart Media Card interface
+ on Atmel AT91 processors.
+
config MTD_NAND_NANDSIM
tristate "Support for NAND Flash Simulator"
depends on MTD_NAND && MTD_PARTITIONS
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index f74759351c9..f7a53f0b701 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
+obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
@@ -22,5 +23,7 @@ obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o
obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
+obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
-nand-objs = nand_base.o nand_bbt.o
+nand-objs := nand_base.o nand_bbt.o
+cafe_nand-objs := cafe.o cafe_ecc.o
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
new file mode 100644
index 00000000000..14b80cc90a7
--- /dev/null
+++ b/drivers/mtd/nand/at91_nand.c
@@ -0,0 +1,223 @@
+/*
+ * drivers/mtd/nand/at91_nand.c
+ *
+ * Copyright (C) 2003 Rick Bronson
+ *
+ * Derived from drivers/mtd/nand/autcpu12.c
+ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ * Derived from drivers/mtd/spia.c
+ * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+struct at91_nand_host {
+ struct nand_chip nand_chip;
+ struct mtd_info mtd;
+ void __iomem *io_base;
+ struct at91_nand_data *board;
+};
+
+/*
+ * Hardware specific access to control-lines
+ */
+static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct at91_nand_host *host = nand_chip->priv;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (ctrl & NAND_CLE)
+ writeb(cmd, host->io_base + (1 << host->board->cle));
+ else
+ writeb(cmd, host->io_base + (1 << host->board->ale));
+}
+
+/*
+ * Read the Device Ready pin.
+ */
+static int at91_nand_device_ready(struct mtd_info *mtd)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct at91_nand_host *host = nand_chip->priv;
+
+ return at91_get_gpio_value(host->board->rdy_pin);
+}
+
+/*
+ * Enable NAND.
+ */
+static void at91_nand_enable(struct at91_nand_host *host)
+{
+ if (host->board->enable_pin)
+ at91_set_gpio_value(host->board->enable_pin, 0);
+}
+
+/*
+ * Disable NAND.
+ */
+static void at91_nand_disable(struct at91_nand_host *host)
+{
+ if (host->board->enable_pin)
+ at91_set_gpio_value(host->board->enable_pin, 1);
+}
+
+/*
+ * Probe for the NAND device.
+ */
+static int __init at91_nand_probe(struct platform_device *pdev)
+{
+ struct at91_nand_host *host;
+ struct mtd_info *mtd;
+ struct nand_chip *nand_chip;
+ int res;
+
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *partitions = NULL;
+ int num_partitions = 0;
+#endif
+
+ /* Allocate memory for the device structure (and zero it) */
+ host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
+ if (!host) {
+ printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
+ return -ENOMEM;
+ }
+
+ host->io_base = ioremap(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start + 1);
+ if (host->io_base == NULL) {
+ printk(KERN_ERR "at91_nand: ioremap failed\n");
+ kfree(host);
+ return -EIO;
+ }
+
+ mtd = &host->mtd;
+ nand_chip = &host->nand_chip;
+ host->board = pdev->dev.platform_data;
+
+ nand_chip->priv = host; /* link the private data structures */
+ mtd->priv = nand_chip;
+ mtd->owner = THIS_MODULE;
+
+ /* Set address of NAND IO lines */
+ nand_chip->IO_ADDR_R = host->io_base;
+ nand_chip->IO_ADDR_W = host->io_base;
+ nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
+ nand_chip->dev_ready = at91_nand_device_ready;
+ nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
+ nand_chip->chip_delay = 20; /* 20us command delay time */
+
+ if (host->board->bus_width_16) /* 16-bit bus width */
+ nand_chip->options |= NAND_BUSWIDTH_16;
+
+ platform_set_drvdata(pdev, host);
+ at91_nand_enable(host);
+
+ if (host->board->det_pin) {
+ if (at91_get_gpio_value(host->board->det_pin)) {
+ printk ("No SmartMedia card inserted.\n");
+ res = ENXIO;
+ goto out;
+ }
+ }
+
+ /* Scan to find existance of the device */
+ if (nand_scan(mtd, 1)) {
+ res = -ENXIO;
+ goto out;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (host->board->partition_info)
+ partitions = host->board->partition_info(mtd->size, &num_partitions);
+
+ if ((!partitions) || (num_partitions == 0)) {
+ printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
+ res = ENXIO;
+ goto release;
+ }
+
+ res = add_mtd_partitions(mtd, partitions, num_partitions);
+#else
+ res = add_mtd_device(mtd);
+#endif
+
+ if (!res)
+ return res;
+
+release:
+ nand_release(mtd);
+out:
+ at91_nand_disable(host);
+ platform_set_drvdata(pdev, NULL);
+ iounmap(host->io_base);
+ kfree(host);
+ return res;
+}
+
+/*
+ * Remove a NAND device.
+ */
+static int __devexit at91_nand_remove(struct platform_device *pdev)
+{
+ struct at91_nand_host *host = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = &host->mtd;
+
+ nand_release(mtd);
+
+ at91_nand_disable(host);
+
+ iounmap(host->io_base);
+ kfree(host);
+
+ return 0;
+}
+
+static struct platform_driver at91_nand_driver = {
+ .probe = at91_nand_probe,
+ .remove = at91_nand_remove,
+ .driver = {
+ .name = "at91_nand",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91_nand_init(void)
+{
+ return platform_driver_register(&at91_nand_driver);
+}
+
+
+static void __exit at91_nand_exit(void)
+{
+ platform_driver_unregister(&at91_nand_driver);
+}
+
+
+module_init(at91_nand_init);
+module_exit(at91_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
new file mode 100644
index 00000000000..65f9bd3ceeb
--- /dev/null
+++ b/drivers/mtd/nand/cafe.c
@@ -0,0 +1,771 @@
+/*
+ * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
+ *
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ */
+
+#define DEBUG
+
+#include <linux/device.h>
+#undef DEBUG
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <asm/io.h>
+
+#define CAFE_NAND_CTRL1 0x00
+#define CAFE_NAND_CTRL2 0x04
+#define CAFE_NAND_CTRL3 0x08
+#define CAFE_NAND_STATUS 0x0c
+#define CAFE_NAND_IRQ 0x10
+#define CAFE_NAND_IRQ_MASK 0x14
+#define CAFE_NAND_DATA_LEN 0x18
+#define CAFE_NAND_ADDR1 0x1c
+#define CAFE_NAND_ADDR2 0x20
+#define CAFE_NAND_TIMING1 0x24
+#define CAFE_NAND_TIMING2 0x28
+#define CAFE_NAND_TIMING3 0x2c
+#define CAFE_NAND_NONMEM 0x30
+#define CAFE_NAND_ECC_RESULT 0x3C
+#define CAFE_NAND_DMA_CTRL 0x40
+#define CAFE_NAND_DMA_ADDR0 0x44
+#define CAFE_NAND_DMA_ADDR1 0x48
+#define CAFE_NAND_ECC_SYN01 0x50
+#define CAFE_NAND_ECC_SYN23 0x54
+#define CAFE_NAND_ECC_SYN45 0x58
+#define CAFE_NAND_ECC_SYN67 0x5c
+#define CAFE_NAND_READ_DATA 0x1000
+#define CAFE_NAND_WRITE_DATA 0x2000
+
+#define CAFE_GLOBAL_CTRL 0x3004
+#define CAFE_GLOBAL_IRQ 0x3008
+#define CAFE_GLOBAL_IRQ_MASK 0x300c
+#define CAFE_NAND_RESET 0x3034
+
+int cafe_correct_ecc(unsigned char *buf,
+ unsigned short *chk_syndrome_list);
+
+struct cafe_priv {
+ struct nand_chip nand;
+ struct pci_dev *pdev;
+ void __iomem *mmio;
+ uint32_t ctl1;
+ uint32_t ctl2;
+ int datalen;
+ int nr_data;
+ int data_pos;
+ int page_addr;
+ dma_addr_t dmaaddr;
+ unsigned char *dmabuf;
+};
+
+static int usedma = 1;
+module_param(usedma, int, 0644);
+
+static int skipbbt = 0;
+module_param(skipbbt, int, 0644);
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+static int regdebug = 0;
+module_param(regdebug, int, 0644);
+
+static int checkecc = 1;
+module_param(checkecc, int, 0644);
+
+static int slowtiming = 0;
+module_param(slowtiming, int, 0644);
+
+/* Hrm. Why isn't this already conditional on something in the struct device? */
+#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
+
+/* Make it easier to switch to PIO if we need to */
+#define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr)
+#define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr)
+
+static int cafe_device_ready(struct mtd_info *mtd)
+{
+ struct cafe_priv *cafe = mtd->priv;
+ int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000);
+ uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
+
+ cafe_writel(cafe, irqs, NAND_IRQ);
+
+ cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
+ result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ),
+ cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK));
+
+ return result;
+}
+
+
+static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+ struct cafe_priv *cafe = mtd->priv;
+
+ if (usedma)
+ memcpy(cafe->dmabuf + cafe->datalen, buf, len);
+ else
+ memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len);
+
+ cafe->datalen += len;
+
+ cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
+ len, cafe->datalen);
+}
+
+static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ struct cafe_priv *cafe = mtd->priv;
+
+ if (usedma)
+ memcpy(buf, cafe->dmabuf + cafe->datalen, len);
+ else
+ memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len);
+
+ cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
+ len, cafe->datalen);
+ cafe->datalen += len;
+}
+
+static uint8_t cafe_read_byte(struct mtd_info *mtd)
+{
+ struct cafe_priv *cafe = mtd->priv;
+ uint8_t d;
+
+ cafe_read_buf(mtd, &d, 1);
+ cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
+
+ return d;
+}
+
+static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+ int column, int page_addr)
+{
+ struct cafe_priv *cafe = mtd->priv;
+ int adrbytes = 0;
+ uint32_t ctl1;
+ uint32_t doneint = 0x80000000;
+
+ cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
+ command, column, page_addr);
+
+ if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
+ /* Second half of a command we already calculated */
+ cafe_writel(cafe, cafe->ctl2 | 0x100 | command, NAND_CTRL2);
+ ctl1 = cafe->ctl1;
+ cafe->ctl2 &= ~(1<<30);
+ cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
+ cafe->ctl1, cafe->nr_data);
+ goto do_command;
+ }
+ /* Reset ECC engine */
+ cafe_writel(cafe, 0, NAND_CTRL2);
+
+ /* Emulate NAND_CMD_READOOB on large-page chips */
+ if (mtd->writesize > 512 &&
+ command == NAND_CMD_READOOB) {
+ column += mtd->writesize;
+ command = NAND_CMD_READ0;
+ }
+
+ /* FIXME: Do we need to send read command before sending data
+ for small-page chips, to position the buffer correctly? */
+
+ if (column != -1) {
+ cafe_writel(cafe, column, NAND_ADDR1);
+ adrbytes = 2;
+ if (page_addr != -1)
+ goto write_adr2;
+ } else if (page_addr != -1) {
+ cafe_writel(cafe, page_addr & 0xffff, NAND_ADDR1);
+ page_addr >>= 16;
+ write_adr2:
+ cafe_writel(cafe, page_addr, NAND_ADDR2);
+ adrbytes += 2;
+ if (mtd->size > mtd->writesize << 16)
+ adrbytes++;
+ }
+
+ cafe->data_pos = cafe->datalen = 0;
+
+ /* Set command valid bit */
+ ctl1 = 0x80000000 | command;
+
+ /* Set RD or WR bits as appropriate */
+ if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
+ ctl1 |= (1<<26); /* rd */
+ /* Always 5 bytes, for now */
+ cafe->datalen = 4;
+ /* And one address cycle -- even for STATUS, since the controller doesn't work without */
+ adrbytes = 1;
+ } else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
+ command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) {
+ ctl1 |= 1<<26; /* rd */
+ /* For now, assume just read to end of page */
+ cafe->datalen = mtd->writesize + mtd->oobsize - column;
+ } else if (command == NAND_CMD_SEQIN)
+ ctl1 |= 1<<25; /* wr */
+
+ /* Set number of address bytes */
+ if (adrbytes)
+ ctl1 |= ((adrbytes-1)|8) << 27;
+
+ if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) {
+ /* Ignore the first command of a pair; the hardware
+ deals with them both at once, later */
+ cafe->ctl1 = ctl1;
+ cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
+ cafe->ctl1, cafe->datalen);
+ return;
+ }
+ /* RNDOUT and READ0 commands need a following byte */
+ if (command == NAND_CMD_RNDOUT)
+ cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_RNDOUTSTART, NAND_CTRL2);
+ else if (command == NAND_CMD_READ0 && mtd->writesize > 512)
+ cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_READSTART, NAND_CTRL2);
+
+ do_command:
+ cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
+ cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2));
+
+ /* NB: The datasheet lies -- we really should be subtracting 1 here */
+ cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN);
+ cafe_writel(cafe, 0x90000000, NAND_IRQ);
+ if (usedma && (ctl1 & (3<<25))) {
+ uint32_t dmactl = 0xc0000000 + cafe->datalen;
+ /* If WR or RD bits set, set up DMA */
+ if (ctl1 & (1<<26)) {
+ /* It's a read */
+ dmactl |= (1<<29);
+ /* ... so it's done when the DMA is done, not just
+ the command. */
+ doneint = 0x10000000;
+ }
+ cafe_writel(cafe, dmactl, NAND_DMA_CTRL);
+ }
+ cafe->datalen = 0;
+
+ if (unlikely(regdebug)) {
+ int i;
+ printk("About to write command %08x to register 0\n", ctl1);
+ for (i=4; i< 0x5c; i+=4)
+ printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
+ }
+
+ cafe_writel(cafe, ctl1, NAND_CTRL1);
+ /* Apply this short delay always to ensure that we do wait tWB in
+ * any case on any machine. */
+ ndelay(100);
+
+ if (1) {
+ int c = 500000;
+ uint32_t irqs;
+
+ while (c--) {
+ irqs = cafe_readl(cafe, NAND_IRQ);
+ if (irqs & doneint)
+ break;
+ udelay(1);
+ if (!(c % 100000))
+ cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
+ cpu_relax();
+ }
+ cafe_writel(cafe, doneint, NAND_IRQ);
+ cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
+ command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
+ }
+
+ WARN_ON(cafe->ctl2 & (1<<30));
+
+ switch (command) {
+
+ case NAND_CMD_CACHEDPROG:
+ case NAND_CMD_PAGEPROG:
+ case NAND_CMD_ERASE1:
+ case NAND_CMD_ERASE2:
+ case NAND_CMD_SEQIN:
+ case NAND_CMD_RNDIN:
+ case NAND_CMD_STATUS:
+ case NAND_CMD_DEPLETE1:
+ case NAND_CMD_RNDOUT:
+ case NAND_CMD_STATUS_ERROR:
+ case NAND_CMD_STATUS_ERROR0:
+ case NAND_CMD_STATUS_ERROR1:
+ case NAND_CMD_STATUS_ERROR2:
+ case NAND_CMD_STATUS_ERROR3:
+ cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
+ return;
+ }
+ nand_wait_ready(mtd);
+ cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
+}
+
+static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
+{
+ //struct cafe_priv *cafe = mtd->priv;
+ // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+}
+
+static int cafe_nand_interrupt(int irq, void *id)
+{
+ struct mtd_info *mtd = id;
+ struct cafe_priv *cafe = mtd->priv;
+ uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
+ cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
+ if (!irqs)
+ return IRQ_NONE;
+
+ cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
+ return IRQ_HANDLED;
+}
+
+static void cafe_nand_bug(struct mtd_info *mtd)
+{
+ BUG();
+}
+
+static int cafe_nand_write_oob(struct mtd_info *mtd,
+ struct nand_chip *chip, int page)
+{
+ int status = 0;
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+ status = chip->waitfunc(mtd, chip);
+
+ return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+/* Don't use -- use nand_read_oob_std for now */
+static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+ int page, int sndcmd)
+{
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ return 1;
+}
+/**
+ * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ *
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf)
+{
+ struct cafe_priv *cafe = mtd->priv;
+
+ cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
+ cafe_readl(cafe, NAND_ECC_RESULT),
+ cafe_readl(cafe, NAND_ECC_SYN01));
+
+ chip->read_buf(mtd, buf, mtd->writesize);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
+ unsigned short syn[8];
+ int i;
+
+ for (i=0; i<8; i+=2) {
+ uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
+ syn[i] = tmp & 0xfff;
+ syn[i+1] = (tmp >> 16) & 0xfff;
+ }
+
+ if ((i = cafe_correct_ecc(buf, syn)) < 0) {
+ dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
+ cafe_readl(cafe, NAND_ADDR2) * 2048);
+ for (i=0; i< 0x5c; i+=4)
+ printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
+ mtd->ecc_stats.failed++;
+ } else {
+ dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i);
+ mtd->ecc_stats.corrected += i;
+ }
+ }
+
+
+ return 0;
+}
+
+static struct nand_ecclayout cafe_oobinfo_2048 = {
+ .eccbytes = 14,
+ .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
+ .oobfree = {{14, 50}}
+};
+
+/* Ick. The BBT code really ought to be able to work this bit out
+ for itself from the above, at least for the 2KiB case */
+static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
+static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
+
+static uint8_t cafe_bbt_pattern_512[] = { 0xBB };
+static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
+
+
+static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 14,
+ .len = 4,
+ .veroffs = 18,
+ .maxblocks = 4,
+ .pattern = cafe_bbt_pattern_2048
+};
+
+static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 14,
+ .len = 4,
+ .veroffs = 18,
+ .maxblocks = 4,
+ .pattern = cafe_mirror_pattern_2048
+};
+
+static struct nand_ecclayout cafe_oobinfo_512 = {
+ .eccbytes = 14,
+ .eccpos = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
+ .oobfree = {{14, 2}}
+};
+
+static struct nand_bbt_descr cafe_bbt_main_descr_512 = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 14,
+ .len = 1,
+ .veroffs = 15,
+ .maxblocks = 4,
+ .pattern = cafe_bbt_pattern_512
+};
+
+static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 14,
+ .len = 1,
+ .veroffs = 15,
+ .maxblocks = 4,
+ .pattern = cafe_mirror_pattern_512
+};
+
+
+static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf)
+{
+ struct cafe_priv *cafe = mtd->priv;
+
+ chip->write_buf(mtd, buf, mtd->writesize);
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ /* Set up ECC autogeneration */
+ cafe->ctl2 |= (1<<30);
+}
+
+static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int page, int cached, int raw)
+{
+ int status;
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+ if (unlikely(raw))
+ chip->ecc.write_page_raw(mtd, chip, buf);
+ else
+ chip->ecc.write_page(mtd, chip, buf);
+
+ /*
+ * Cached progamming disabled for now, Not sure if its worth the
+ * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+ */
+ cached = 0;
+
+ if (!cached || !(chip->options & NAND_CACHEPRG)) {
+
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+ status = chip->waitfunc(mtd, chip);
+ /*
+ * See if operation failed and additional status checks are
+ * available
+ */
+ if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+ status = chip->errstat(mtd, chip, FL_WRITING, status,
+ page);
+
+ if (status & NAND_STATUS_FAIL)
+ return -EIO;
+ } else {
+ chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
+ status = chip->waitfunc(mtd, chip);
+ }
+
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+ /* Send command to read back the data */
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+ if (chip->verify_buf(mtd, buf, mtd->writesize))
+ return -EIO;
+#endif
+ return 0;
+}
+
+static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+ return 0;
+}
+
+static int __devinit cafe_nand_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct mtd_info *mtd;
+ struct cafe_priv *cafe;
+ uint32_t ctrl;
+ int err = 0;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_set_master(pdev);
+
+ mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
+ if (!mtd) {
+ dev_warn(&pdev->dev, "failed to alloc mtd_info\n");
+ return -ENOMEM;
+ }
+ cafe = (void *)(&mtd[1]);
+
+ mtd->priv = cafe;
+ mtd->owner = THIS_MODULE;
+
+ cafe->pdev = pdev;
+ cafe->mmio = pci_iomap(pdev, 0, 0);
+ if (!cafe->mmio) {
+ dev_warn(&pdev->dev, "failed to iomap\n");
+ err = -ENOMEM;
+ goto out_free_mtd;
+ }
+ cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers),
+ &cafe->dmaaddr, GFP_KERNEL);
+ if (!cafe->dmabuf) {
+ err = -ENOMEM;
+ goto out_ior;
+ }
+ cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
+
+ cafe->nand.cmdfunc = cafe_nand_cmdfunc;
+ cafe->nand.dev_ready = cafe_device_ready;
+ cafe->nand.read_byte = cafe_read_byte;
+ cafe->nand.read_buf = cafe_read_buf;
+ cafe->nand.write_buf = cafe_write_buf;
+ cafe->nand.select_chip = cafe_select_chip;
+
+ cafe->nand.chip_delay = 0;
+
+ /* Enable the following for a flash based bad block table */
+ cafe->nand.options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR | NAND_OWN_BUFFERS;
+
+ if (skipbbt) {
+ cafe->nand.options |= NAND_SKIP_BBTSCAN;
+ cafe->nand.block_bad = cafe_nand_block_bad;
+ }
+
+ /* Start off by resetting the NAND controller completely */
+ cafe_writel(cafe, 1, NAND_RESET);
+ cafe_writel(cafe, 0, NAND_RESET);
+
+ cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+
+ /* Timings from Marvell's test code (not verified or calculated by us) */
+ if (!slowtiming) {
+ cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
+ cafe_writel(cafe, 0x24121212, NAND_TIMING2);
+ cafe_writel(cafe, 0x11000000, NAND_TIMING3);
+ } else {
+ cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
+ cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
+ cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
+ }
+ cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+ err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd);
+ if (err) {
+ dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
+
+ goto out_free_dma;
+ }
+#if 1
+ /* Disable master reset, enable NAND clock */
+ ctrl = cafe_readl(cafe, GLOBAL_CTRL);
+ ctrl &= 0xffffeff0;
+ ctrl |= 0x00007000;
+ cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
+ cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
+ cafe_writel(cafe, 0, NAND_DMA_CTRL);
+
+ cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
+ cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
+
+ /* Set up DMA address */
+ cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
+ if (sizeof(cafe->dmaaddr) > 4)
+ /* Shift in two parts to shut the compiler up */
+ cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
+ else
+ cafe_writel(cafe, 0, NAND_DMA_ADDR1);
+
+ cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
+ cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
+
+ /* Enable NAND IRQ in global IRQ mask register */
+ cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
+ cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
+ cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
+#endif
+#if 1
+ mtd->writesize=2048;
+ mtd->oobsize = 0x40;
+ memset(cafe->dmabuf, 0x5a, 2112);
+ cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+#endif
+#if 0
+ cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
+ // nand_wait_ready(mtd);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+ cafe->nand.read_byte(mtd);
+#endif
+#if 0
+ writel(0x84600070, cafe->mmio);
+ udelay(10);
+ cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
+#endif
+ /* Scan to find existance of the device */
+ if (nand_scan_ident(mtd, 1)) {
+ err = -ENXIO;
+ goto out_irq;
+ }
+
+ cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
+ if (mtd->writesize == 2048)
+ cafe->ctl2 |= 1<<29; /* 2KiB page size */
+
+ /* Set up ECC according to the type of chip we found */
+ if (mtd->writesize == 2048) {
+ cafe->nand.ecc.layout = &cafe_oobinfo_2048;
+ cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
+ cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
+ } else if (mtd->writesize == 512) {
+ cafe->nand.ecc.layout = &cafe_oobinfo_512;
+ cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
+ cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
+ } else {
+ printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",
+ mtd->writesize);
+ goto out_irq;
+ }
+ cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
+ cafe->nand.ecc.size = mtd->writesize;
+ cafe->nand.ecc.bytes = 14;
+ cafe->nand.ecc.hwctl = (void *)cafe_nand_bug;
+ cafe->nand.ecc.calculate = (void *)cafe_nand_bug;
+ cafe->nand.ecc.correct = (void *)cafe_nand_bug;
+ cafe->nand.write_page = cafe_nand_write_page;
+ cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
+ cafe->nand.ecc.write_oob = cafe_nand_write_oob;
+ cafe->nand.ecc.read_page = cafe_nand_read_page;
+ cafe->nand.ecc.read_oob = cafe_nand_read_oob;
+
+ err = nand_scan_tail(mtd);
+ if (err)
+ goto out_irq;
+
+ pci_set_drvdata(pdev, mtd);
+ add_mtd_device(mtd);
+ goto out;
+
+ out_irq:
+ /* Disable NAND IRQ in global IRQ mask register */
+ cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
+ free_irq(pdev->irq, mtd);
+ out_free_dma:
+ dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+ out_ior:
+ pci_iounmap(pdev, cafe->mmio);
+ out_free_mtd:
+ kfree(mtd);
+ out:
+ return err;
+}
+
+static void __devexit cafe_nand_remove(struct pci_dev *pdev)
+{
+ struct mtd_info *mtd = pci_get_drvdata(pdev);
+ struct cafe_priv *cafe = mtd->priv;
+
+ del_mtd_device(mtd);
+ /* Disable NAND IRQ in global IRQ mask register */
+ cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
+ free_irq(pdev->irq, mtd);
+ nand_release(mtd);
+ pci_iounmap(pdev, cafe->mmio);
+ dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+ kfree(mtd);
+}
+
+static struct pci_device_id cafe_nand_tbl[] = {
+ { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 }
+};
+
+MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
+
+static struct pci_driver cafe_nand_pci_driver = {
+ .name = "CAFÉ NAND",
+ .id_table = cafe_nand_tbl,
+ .probe = cafe_nand_probe,
+ .remove = __devexit_p(cafe_nand_remove),
+#ifdef CONFIG_PMx
+ .suspend = cafe_nand_suspend,
+ .resume = cafe_nand_resume,
+#endif
+};
+
+static int cafe_nand_init(void)
+{
+ return pci_register_driver(&cafe_nand_pci_driver);
+}
+
+static void cafe_nand_exit(void)
+{
+ pci_unregister_driver(&cafe_nand_pci_driver);
+}
+module_init(cafe_nand_init);
+module_exit(cafe_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
+
+/* Correct ECC for 2048 bytes of 0xff:
+ 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
+
+/* dwmw2's B-test board, in case of completely screwing it:
+Bad eraseblock 2394 at 0x12b40000
+Bad eraseblock 2627 at 0x14860000
+Bad eraseblock 3349 at 0x1a2a0000
+*/
diff --git a/drivers/mtd/nand/cafe_ecc.c b/drivers/mtd/nand/cafe_ecc.c
new file mode 100644
index 00000000000..1b9fa05a447
--- /dev/null
+++ b/drivers/mtd/nand/cafe_ecc.c
@@ -0,0 +1,1381 @@
+/* Error correction for CAFÉ NAND controller
+ *
+ * © 2006 Marvell, Inc.
+ * Author: Tom Chiou
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+static unsigned short gf4096_mul(unsigned short, unsigned short);
+static unsigned short gf64_mul(unsigned short, unsigned short);
+static unsigned short gf4096_inv(unsigned short);
+static unsigned short err_pos(unsigned short);
+static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short *);
+static void zero_4x5_col3(unsigned short[4][5]);
+static void zero_4x5_col2(unsigned short[4][5]);
+static void zero_4x5_col1(unsigned short[4][5]);
+static void swap_4x5_rows(unsigned short[4][5], int, int, int);
+static void swap_2x3_rows(unsigned short m[2][3]);
+static void solve_4x5(unsigned short m[4][5], unsigned short *, int *);
+static void sort_coefs(int *, unsigned short *, int);
+static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short *);
+static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short,
+ unsigned short *);
+static void zero_3x4_col2(unsigned short[3][4]);
+static void zero_3x4_col1(unsigned short[3][4]);
+static void swap_3x4_rows(unsigned short[3][4], int, int, int);
+static void solve_3x4(unsigned short[3][4], unsigned short *, int *);
+static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short,
+ unsigned short *);
+
+static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short *);
+static void find_2x2_soln(unsigned short, unsigned short, unsigned short,
+ unsigned short, unsigned short, unsigned short,
+ unsigned short *);
+static void solve_2x3(unsigned short[2][3], unsigned short *);
+static int chk_no_err_only(unsigned short *, unsigned short *);
+static int chk_1_err_only(unsigned short *, unsigned short *);
+static int chk_2_err_only(unsigned short *, unsigned short *);
+static int chk_3_err_only(unsigned short *, unsigned short *);
+static int chk_4_err_only(unsigned short *, unsigned short *);
+
+static unsigned short gf64_mul(unsigned short a, unsigned short b)
+{
+ unsigned short tmp1, tmp2, tmp3, tmp4, tmp5;
+ unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c;
+
+ tmp1 = ((a) ^ (a >> 5));
+ tmp2 = ((a >> 4) ^ (a >> 5));
+ tmp3 = ((a >> 3) ^ (a >> 4));
+ tmp4 = ((a >> 2) ^ (a >> 3));
+ tmp5 = ((a >> 1) ^ (a >> 2));
+
+ c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^
+ ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1;
+
+ c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^
+ (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1;
+
+ c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^
+ (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1;
+
+ c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^
+ (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1;
+
+ c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^
+ ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1;
+
+ c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^
+ ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1;
+
+ c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5);
+
+ return c;
+}
+
+static unsigned short gf4096_mul(unsigned short a, unsigned short b)
+{
+ unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c;
+
+ ah = (a >> 6) & 0x3f;
+ al = a & 0x3f;
+ bh = (b >> 6) & 0x3f;
+ bl = b & 0x3f;
+ alxah = al ^ ah;
+ blxbh = bl ^ bh;
+
+ ablh = gf64_mul(alxah, blxbh);
+ albl = gf64_mul(al, bl);
+ ahbh = gf64_mul(ah, bh);
+
+ ahbhB = ((ahbh & 0x1) << 5) |
+ ((ahbh & 0x20) >> 1) |
+ ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1);
+
+ c = ((ablh ^ albl) << 6) | (ahbhB ^ albl);
+ return c;
+}
+
+static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats)
+{
+ find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats);
+}
+
+static void find_3bit_err_coefs(unsigned short s0, unsigned short s1,
+ unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs)
+{
+ unsigned short m[3][4];
+ int row_order[3];
+
+ row_order[0] = 0;
+ row_order[1] = 1;
+ row_order[2] = 2;
+ m[0][0] = s2;
+ m[0][1] = s1;
+ m[0][2] = s0;
+ m[0][3] = s3;
+ m[1][0] = s3;
+ m[1][1] = s2;
+ m[1][2] = s1;
+ m[1][3] = s4;
+ m[2][0] = s4;
+ m[2][1] = s3;
+ m[2][2] = s2;
+ m[2][3] = s5;
+
+ if (m[0][2] != 0x0) {
+ zero_3x4_col2(m);
+ } else if (m[1][2] != 0x0) {
+ swap_3x4_rows(m, 0, 1, 4);
+ zero_3x4_col2(m);
+ } else if (m[2][2] != 0x0) {
+ swap_3x4_rows(m, 0, 2, 4);
+ zero_3x4_col2(m);
+ } else {
+ printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n");
+ }
+
+ if (m[1][1] != 0x0) {
+ zero_3x4_col1(m);
+ } else if (m[2][1] != 0x0) {
+ swap_3x4_rows(m, 1, 2, 4);
+ zero_3x4_col1(m);
+ } else {
+ printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n");
+ }
+
+ /* solve coefs */
+ solve_3x4(m, coefs, row_order);
+}
+
+static void zero_3x4_col2(unsigned short m[3][4])
+{
+ unsigned short minv1, minv2;
+
+ minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2]));
+ minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2]));
+ m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
+ m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
+ m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1);
+ m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
+ m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
+ m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2);
+}
+
+static void zero_3x4_col1(unsigned short m[3][4])
+{
+ unsigned short minv;
+ minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1]));
+ m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv);
+ m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv);
+}
+
+static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width)
+{
+ unsigned short tmp0;
+ int cnt;
+ for (cnt = 0; cnt < col_width; cnt++) {
+ tmp0 = m[i][cnt];
+ m[i][cnt] = m[j][cnt];
+ m[j][cnt] = tmp0;
+ }
+}
+
+static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order)
+{
+ unsigned short tmp[3];
+ tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0]));
+ tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1]));
+ tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2]));
+ sort_coefs(row_order, tmp, 3);
+ coefs[0] = tmp[0];
+ coefs[1] = tmp[1];
+ coefs[2] = tmp[2];
+}
+
+static void find_3bit_err_pats(unsigned short s0, unsigned short s1,
+ unsigned short s2, unsigned short r0,
+ unsigned short r1, unsigned short r2,
+ unsigned short *pats)
+{
+ find_2x2_soln(r0 ^ r2, r1 ^ r2,
+ gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2),
+ gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats);
+ pats[2] = s0 ^ pats[0] ^ pats[1];
+}
+
+static void find_4bit_err_coefs(unsigned short s0, unsigned short s1,
+ unsigned short s2, unsigned short s3,
+ unsigned short s4, unsigned short s5,
+ unsigned short s6, unsigned short s7,
+ unsigned short *coefs)
+{
+ unsigned short m[4][5];
+ int row_order[4];
+
+ row_order[0] = 0;
+ row_order[1] = 1;
+ row_order[2] = 2;
+ row_order[3] = 3;
+
+ m[0][0] = s3;
+ m[0][1] = s2;
+ m[0][2] = s1;
+ m[0][3] = s0;
+ m[0][4] = s4;
+ m[1][0] = s4;
+ m[1][1] = s3;
+ m[1][2] = s2;
+ m[1][3] = s1;
+ m[1][4] = s5;
+ m[2][0] = s5;
+ m[2][1] = s4;
+ m[2][2] = s3;
+ m[2][3] = s2;
+ m[2][4] = s6;
+ m[3][0] = s6;
+ m[3][1] = s5;
+ m[3][2] = s4;
+ m[3][3] = s3;
+ m[3][4] = s7;
+
+ if (m[0][3] != 0x0) {
+ zero_4x5_col3(m);
+ } else if (m[1][3] != 0x0) {
+ swap_4x5_rows(m, 0, 1, 5);
+ zero_4x5_col3(m);
+ } else if (m[2][3] != 0x0) {
+ swap_4x5_rows(m, 0, 2, 5);
+ zero_4x5_col3(m);
+ } else if (m[3][3] != 0x0) {
+ swap_4x5_rows(m, 0, 3, 5);
+ zero_4x5_col3(m);
+ } else {
+ printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n");
+ }
+
+ if (m[1][2] != 0x0) {
+ zero_4x5_col2(m);
+ } else if (m[2][2] != 0x0) {
+ swap_4x5_rows(m, 1, 2, 5);
+ zero_4x5_col2(m);
+ } else if (m[3][2] != 0x0) {
+ swap_4x5_rows(m, 1, 3, 5);
+ zero_4x5_col2(m);
+ } else {
+ printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n");
+ }
+
+ if (m[2][1] != 0x0) {
+ zero_4x5_col1(m);
+ } else if (m[3][1] != 0x0) {
+ swap_4x5_rows(m, 2, 3, 5);
+ zero_4x5_col1(m);
+ } else {
+ printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n");
+ }
+
+ solve_4x5(m, coefs, row_order);
+}
+
+static void zero_4x5_col3(unsigned short m[4][5])
+{
+ unsigned short minv1, minv2, minv3;
+
+ minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3]));
+ minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3]));
+ minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3]));
+
+ m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1);
+ m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1);
+ m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1);
+ m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1);
+ m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2);
+ m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2);
+ m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2);
+ m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2);
+ m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3);
+ m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3);
+ m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3);
+ m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3);
+}
+
+static void zero_4x5_col2(unsigned short m[4][5])
+{
+ unsigned short minv2, minv3;
+
+ minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2]));
+ minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2]));
+
+ m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2);
+ m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2);
+ m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2);
+ m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3);
+ m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3);
+ m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3);
+}
+
+static void zero_4x5_col1(unsigned short m[4][5])
+{
+ unsigned short minv;
+
+ minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1]));
+
+ m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv);
+ m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv);
+}
+
+static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width)
+{
+ unsigned short tmp0;
+ int cnt;
+
+ for (cnt = 0; cnt < col_width; cnt++) {
+ tmp0 = m[i][cnt];
+ m[i][cnt] = m[j][cnt];
+ m[j][cnt] = tmp0;
+ }
+}
+
+static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order)
+{
+ unsigned short tmp[4];
+
+ tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0]));
+ tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1]));
+ tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2]));
+ tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^
+ gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3]));
+ sort_coefs(row_order, tmp, 4);
+ coefs[0] = tmp[0];
+ coefs[1] = tmp[1];
+ coefs[2] = tmp[2];
+ coefs[3] = tmp[3];
+}
+
+static void sort_coefs(int *order, unsigned short *soln, int len)
+{
+ int cnt, start_cnt, least_ord, least_cnt;
+ unsigned short tmp0;
+ for (start_cnt = 0; start_cnt < len; start_cnt++) {
+ for (cnt = start_cnt; cnt < len; cnt++) {
+ if (cnt == start_cnt) {
+ least_ord = order[cnt];
+ least_cnt = start_cnt;
+ } else {
+ if (least_ord > order[cnt]) {
+ least_ord = order[cnt];
+ least_cnt = cnt;
+ }
+ }
+ }
+ if (least_cnt != start_cnt) {
+ tmp0 = order[least_cnt];
+ order[least_cnt] = order[start_cnt];
+ order[start_cnt] = tmp0;
+ tmp0 = soln[least_cnt];
+ soln[least_cnt] = soln[start_cnt];
+ soln[start_cnt] = tmp0;
+ }
+ }
+}
+
+static void find_4bit_err_pats(unsigned short s0, unsigned short s1,
+ unsigned short s2, unsigned short s3,
+ unsigned short z1, unsigned short z2,
+ unsigned short z3, unsigned short z4,
+ unsigned short *pats)
+{
+ unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1,
+ z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3;
+ unsigned short tmp0, tmp1, tmp2, tmp3;
+
+ z4_z1 = z4 ^ z1;
+ z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3);
+ z4_z2 = z4 ^ z2;
+ s0z4_s1 = gf4096_mul(s0, z4) ^ s1;
+ z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1);
+ z4_z3 = z4 ^ z3;
+ z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2);
+ s1z4_s2 = gf4096_mul(s1, z4) ^ s2;
+ z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3);
+ z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1);
+ z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2);
+ s2z4_s3 = gf4096_mul(s2, z4) ^ s3;
+
+ //find err pat 0,1
+ find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^
+ gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2,
+ z3z4_z3z3) ^
+ gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1,
+ z3z3z4_z3z3z3) ^
+ gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3),
+ gf4096_mul(z2z4_z2z2,
+ z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2,
+ z3z4_z3z3),
+ gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2,
+ z4_z3),
+ gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats);
+ tmp0 = pats[0];
+ tmp1 = pats[1];
+ tmp2 = pats[0] ^ pats[1] ^ s0;
+ tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1;
+
+ //find err pat 2,3
+ find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats);
+ pats[2] = pats[0];
+ pats[3] = pats[1];
+ pats[0] = tmp0;
+ pats[1] = tmp1;
+}
+
+static void find_2x2_soln(unsigned short c00, unsigned short c01,
+ unsigned short c10, unsigned short c11,
+ unsigned short lval0, unsigned short lval1,
+ unsigned short *soln)
+{
+ unsigned short m[2][3];
+ m[0][0] = c00;
+ m[0][1] = c01;
+ m[0][2] = lval0;
+ m[1][0] = c10;
+ m[1][1] = c11;
+ m[1][2] = lval1;
+
+ if (m[0][1] != 0x0) {
+ /* */
+ } else if (m[1][1] != 0x0) {
+ swap_2x3_rows(m);
+ } else {
+ printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n");
+ }
+
+ solve_2x3(m, soln);
+}
+
+static void swap_2x3_rows(unsigned short m[2][3])
+{
+ unsigned short tmp0;
+ int cnt;
+
+ for (cnt = 0; cnt < 3; cnt++) {
+ tmp0 = m[0][cnt];
+ m[0][cnt] = m[1][cnt];
+ m[1][cnt] = tmp0;
+ }
+}
+
+static void solve_2x3(unsigned short m[2][3], unsigned short *coefs)
+{
+ unsigned short minv;
+
+ minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1]));
+ m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv);
+ m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv);
+ coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0]));
+ coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1]));
+}
+
+static unsigned char gf64_inv[64] = {
+ 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25,
+ 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6,
+ 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41,
+ 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32
+};
+
+static unsigned short gf4096_inv(unsigned short din)
+{
+ unsigned short alahxal, ah2B, deno, inv, bl, bh;
+ unsigned short ah, al, ahxal;
+ unsigned short dout;
+
+ ah = (din >> 6) & 0x3f;
+ al = din & 0x3f;
+ ahxal = ah ^ al;
+ ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) |
+ ((ah >> 1) & 0x10) |
+ ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) |
+ ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1);
+ alahxal = gf64_mul(ahxal, al);
+ deno = alahxal ^ ah2B;
+ inv = gf64_inv[deno];
+ bl = gf64_mul(inv, ahxal);
+ bh = gf64_mul(inv, ah);
+ dout = ((bh & 0x3f) << 6) | (bl & 0x3f);
+ return (((bh & 0x3f) << 6) | (bl & 0x3f));
+}
+
+static unsigned short err_pos_lut[4096] = {
+ 0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff,
+ 0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff,
+ 0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff,
+ 0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff,
+ 0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7,
+ 0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff,
+ 0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff,
+ 0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f,
+ 0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8,
+ 0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe,
+ 0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff,
+ 0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1,
+ 0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff,
+ 0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff,
+ 0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff,
+ 0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8,
+ 0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e,
+ 0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff,
+ 0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff,
+ 0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff,
+ 0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535,
+ 0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d,
+ 0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff,
+ 0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5,
+ 0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff,
+ 0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294,
+ 0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff,
+ 0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4,
+ 0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f,
+ 0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b,
+ 0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff,
+ 0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff,
+ 0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff,
+ 0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158,
+ 0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a,
+ 0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff,
+ 0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff,
+ 0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017,
+ 0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a,
+ 0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351,
+ 0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff,
+ 0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff,
+ 0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074,
+ 0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da,
+ 0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433,
+ 0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285,
+ 0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff,
+ 0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d,
+ 0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff,
+ 0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff,
+ 0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331,
+ 0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff,
+ 0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6,
+ 0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3,
+ 0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff,
+ 0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf,
+ 0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc,
+ 0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381,
+ 0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff,
+ 0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f,
+ 0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff,
+ 0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488,
+ 0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442,
+ 0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6,
+ 0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1,
+ 0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae,
+ 0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff,
+ 0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff,
+ 0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2,
+ 0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec,
+ 0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134,
+ 0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b,
+ 0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff,
+ 0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff,
+ 0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff,
+ 0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5,
+ 0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff,
+ 0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff,
+ 0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff,
+ 0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff,
+ 0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2,
+ 0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff,
+ 0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff,
+ 0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff,
+ 0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff,
+ 0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff,
+ 0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff,
+ 0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff,
+ 0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8,
+ 0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb,
+ 0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff,
+ 0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff,
+ 0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd,
+ 0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff,
+ 0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8,
+ 0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9,
+ 0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f,
+ 0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7,
+ 0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff,
+ 0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d,
+ 0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178,
+ 0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff,
+ 0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba,
+ 0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff,
+ 0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e,
+ 0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff,
+ 0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6,
+ 0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff,
+ 0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff,
+ 0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc,
+ 0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6,
+ 0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5,
+ 0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff,
+ 0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc,
+ 0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff,
+ 0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3,
+ 0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff,
+ 0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6,
+ 0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff,
+ 0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a,
+ 0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff,
+ 0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff,
+ 0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff,
+ 0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff,
+ 0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7,
+ 0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff,
+ 0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff,
+ 0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af,
+ 0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff,
+ 0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2,
+ 0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff,
+ 0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff,
+ 0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff,
+ 0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339,
+ 0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff,
+ 0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff,
+ 0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402,
+ 0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff,
+ 0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368,
+ 0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b,
+ 0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f,
+ 0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff,
+ 0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1,
+ 0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff,
+ 0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff,
+ 0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb,
+ 0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc,
+ 0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097,
+ 0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431,
+ 0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1,
+ 0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff,
+ 0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6,
+ 0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd,
+ 0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff,
+ 0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb,
+ 0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff,
+ 0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd,
+ 0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff,
+ 0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff,
+ 0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519,
+ 0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff,
+ 0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084,
+ 0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0,
+ 0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c,
+ 0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f,
+ 0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a,
+ 0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211,
+ 0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff,
+ 0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff,
+ 0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff,
+ 0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff,
+ 0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff,
+ 0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff,
+ 0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180,
+ 0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0,
+ 0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004,
+ 0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302,
+ 0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff,
+ 0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff,
+ 0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272,
+ 0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff,
+ 0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344,
+ 0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff,
+ 0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e,
+ 0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d,
+ 0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff,
+ 0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330,
+ 0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042,
+ 0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364,
+ 0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff,
+ 0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff,
+ 0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f,
+ 0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb,
+ 0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e,
+ 0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c,
+ 0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194,
+ 0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff,
+ 0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff,
+ 0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff,
+ 0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff,
+ 0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6,
+ 0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff,
+ 0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290,
+ 0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff,
+ 0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9,
+ 0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d,
+ 0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff,
+ 0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9,
+ 0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167,
+ 0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020,
+ 0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347,
+ 0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff,
+ 0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff,
+ 0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff,
+ 0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff,
+ 0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff,
+ 0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039,
+ 0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096,
+ 0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff,
+ 0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8,
+ 0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff,
+ 0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd,
+ 0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e,
+ 0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f,
+ 0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff,
+ 0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7,
+ 0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb,
+ 0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff,
+ 0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078,
+ 0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300,
+ 0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200,
+ 0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f,
+ 0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff,
+ 0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216,
+ 0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d,
+ 0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0,
+ 0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff,
+ 0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff,
+ 0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff,
+ 0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff,
+ 0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff,
+ 0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff,
+ 0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086,
+ 0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff,
+ 0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444,
+ 0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110,
+ 0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099,
+ 0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da,
+ 0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff,
+ 0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff,
+ 0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff,
+ 0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff,
+ 0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff,
+ 0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283,
+ 0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff,
+ 0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff,
+ 0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff,
+ 0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff,
+ 0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff,
+ 0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195,
+ 0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff,
+ 0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff,
+ 0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff,
+ 0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff,
+ 0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff,
+ 0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245,
+ 0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff,
+ 0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6,
+ 0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+ 0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1,
+ 0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da,
+ 0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff,
+ 0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff,
+ 0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5,
+ 0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223,
+ 0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002
+};
+
+static unsigned short err_pos(unsigned short din)
+{
+ BUG_ON(din > 4096);
+ return err_pos_lut[din];
+}
+static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+ if ((chk_syndrome_list[0] | chk_syndrome_list[1] |
+ chk_syndrome_list[2] | chk_syndrome_list[3] |
+ chk_syndrome_list[4] | chk_syndrome_list[5] |
+ chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) {
+ return -EINVAL;
+ } else {
+ err_info[0] = 0x0;
+ return 0;
+ }
+}
+static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+ unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+ tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0]));
+ tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1]));
+ tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2]));
+ tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3]));
+ tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4]));
+ tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5]));
+ tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6]));
+ if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) {
+ err_info[0] = 0x1; // encode 1-symbol error as 0x1
+ err_info[1] = err_pos(tmp0);
+ err_info[1] = (unsigned short)(0x55e - err_info[1]);
+ err_info[5] = chk_syndrome_list[0];
+ return 0;
+ } else
+ return -EINVAL;
+}
+static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+ unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ unsigned short coefs[4];
+ unsigned short err_pats[4];
+ int found_num_root = 0;
+ unsigned short bit2_root0, bit2_root1;
+ unsigned short bit2_root0_inv, bit2_root1_inv;
+ unsigned short err_loc_eqn, test_root;
+ unsigned short bit2_loc0, bit2_loc1;
+ unsigned short bit2_pat0, bit2_pat1;
+
+ find_2x2_soln(chk_syndrome_list[1],
+ chk_syndrome_list[0],
+ chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs);
+ for (test_root = 0x1; test_root < 0xfff; test_root++) {
+ err_loc_eqn =
+ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
+ if (err_loc_eqn == 0x0) {
+ if (found_num_root == 0) {
+ bit2_root0 = test_root;
+ found_num_root = 1;
+ } else if (found_num_root == 1) {
+ bit2_root1 = test_root;
+ found_num_root = 2;
+ break;
+ }
+ }
+ }
+ if (found_num_root != 2)
+ return -EINVAL;
+ else {
+ bit2_root0_inv = gf4096_inv(bit2_root0);
+ bit2_root1_inv = gf4096_inv(bit2_root1);
+ find_2bit_err_pats(chk_syndrome_list[0],
+ chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats);
+ bit2_pat0 = err_pats[0];
+ bit2_pat1 = err_pats[1];
+ //for(x+1)
+ tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv)); //rinv0^4
+ tmp1 = gf4096_mul(bit2_root0_inv, tmp0); //rinv0^5
+ tmp2 = gf4096_mul(bit2_root0_inv, tmp1); //rinv0^6
+ tmp3 = gf4096_mul(bit2_root0_inv, tmp2); //rinv0^7
+ tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv)); //rinv1^4
+ tmp5 = gf4096_mul(bit2_root1_inv, tmp4); //rinv1^5
+ tmp6 = gf4096_mul(bit2_root1_inv, tmp5); //rinv1^6
+ tmp7 = gf4096_mul(bit2_root1_inv, tmp6); //rinv1^7
+ //check if only 2-bit error
+ if ((chk_syndrome_list[4] ==
+ (gf4096_mul(bit2_pat0, tmp0) ^
+ gf4096_mul(bit2_pat1,
+ tmp4))) & (chk_syndrome_list[5] ==
+ (gf4096_mul(bit2_pat0, tmp1) ^
+ gf4096_mul(bit2_pat1,
+ tmp5))) &
+ (chk_syndrome_list[6] ==
+ (gf4096_mul(bit2_pat0, tmp2) ^
+ gf4096_mul(bit2_pat1,
+ tmp6))) & (chk_syndrome_list[7] ==
+ (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) {
+ if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) {
+ return -EINVAL;
+ } else {
+ bit2_loc0 = 0x55e - err_pos(bit2_root0_inv);
+ bit2_loc1 = 0x55e - err_pos(bit2_root1_inv);
+ err_info[0] = 0x2; // encode 2-symbol error as 0x2
+ err_info[1] = bit2_loc0;
+ err_info[2] = bit2_loc1;
+ err_info[5] = bit2_pat0;
+ err_info[6] = bit2_pat1;
+ return 0;
+ }
+ } else
+ return -EINVAL;
+ }
+}
+static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+ unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ unsigned short coefs[4];
+ unsigned short err_pats[4];
+ int found_num_root = 0;
+ unsigned short bit3_root0, bit3_root1, bit3_root2;
+ unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv;
+ unsigned short err_loc_eqn, test_root;
+
+ find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1],
+ chk_syndrome_list[2], chk_syndrome_list[3],
+ chk_syndrome_list[4], chk_syndrome_list[5], coefs);
+
+ for (test_root = 0x1; test_root < 0xfff; test_root++) {
+ err_loc_eqn = gf4096_mul(coefs[2],
+ gf4096_mul(gf4096_mul(test_root, test_root),
+ test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root))
+ ^ gf4096_mul(coefs[0], test_root) ^ 0x1;
+
+ if (err_loc_eqn == 0x0) {
+ if (found_num_root == 0) {
+ bit3_root0 = test_root;
+ found_num_root = 1;
+ } else if (found_num_root == 1) {
+ bit3_root1 = test_root;
+ found_num_root = 2;
+ } else if (found_num_root == 2) {
+ bit3_root2 = test_root;
+ found_num_root = 3;
+ break;
+ }
+ }
+ }
+ if (found_num_root != 3)
+ return -EINVAL;
+ else {
+ bit3_root0_inv = gf4096_inv(bit3_root0);
+ bit3_root1_inv = gf4096_inv(bit3_root1);
+ bit3_root2_inv = gf4096_inv(bit3_root2);
+
+ find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1],
+ chk_syndrome_list[2], bit3_root0_inv,
+ bit3_root1_inv, bit3_root2_inv, err_pats);
+
+ //check if only 3-bit error
+ tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv);
+ tmp0 = gf4096_mul(tmp0, tmp0);
+ tmp0 = gf4096_mul(tmp0, bit3_root0_inv);
+ tmp0 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^6
+ tmp1 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^7
+ tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv);
+ tmp2 = gf4096_mul(tmp2, tmp2);
+ tmp2 = gf4096_mul(tmp2, bit3_root1_inv);
+ tmp2 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^6
+ tmp3 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^7
+ tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv);
+ tmp4 = gf4096_mul(tmp4, tmp4);
+ tmp4 = gf4096_mul(tmp4, bit3_root2_inv);
+ tmp4 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^6
+ tmp5 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^7
+
+ //check if only 3 errors
+ if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^
+ gf4096_mul(err_pats[1], tmp2) ^
+ gf4096_mul(err_pats[2], tmp4))) &
+ (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^
+ gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) {
+ if ((err_pos(bit3_root0_inv) == 0xfff) |
+ (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) {
+ return -EINVAL;
+ } else {
+ err_info[0] = 0x3;
+ err_info[1] = (0x55e - err_pos(bit3_root0_inv));
+ err_info[2] = (0x55e - err_pos(bit3_root1_inv));
+ err_info[3] = (0x55e - err_pos(bit3_root2_inv));
+ err_info[5] = err_pats[0];
+ err_info[6] = err_pats[1];
+ err_info[7] = err_pats[2];
+ return 0;
+ }
+ } else
+ return -EINVAL;
+ }
+}
+static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+{
+ unsigned short coefs[4];
+ unsigned short err_pats[4];
+ int found_num_root = 0;
+ unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3;
+ unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv;
+ unsigned short err_loc_eqn, test_root;
+
+ find_4bit_err_coefs(chk_syndrome_list[0],
+ chk_syndrome_list[1],
+ chk_syndrome_list[2],
+ chk_syndrome_list[3],
+ chk_syndrome_list[4],
+ chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs);
+
+ for (test_root = 0x1; test_root < 0xfff; test_root++) {
+ err_loc_eqn =
+ gf4096_mul(coefs[3],
+ gf4096_mul(gf4096_mul
+ (gf4096_mul(test_root, test_root),
+ test_root),
+ test_root)) ^ gf4096_mul(coefs[2],
+ gf4096_mul
+ (gf4096_mul(test_root, test_root), test_root))
+ ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root)
+ ^ 0x1;
+ if (err_loc_eqn == 0x0) {
+ if (found_num_root == 0) {
+ bit4_root0 = test_root;
+ found_num_root = 1;
+ } else if (found_num_root == 1) {
+ bit4_root1 = test_root;
+ found_num_root = 2;
+ } else if (found_num_root == 2) {
+ bit4_root2 = test_root;
+ found_num_root = 3;
+ } else {
+ found_num_root = 4;
+ bit4_root3 = test_root;
+ break;
+ }
+ }
+ }
+ if (found_num_root != 4) {
+ return -EINVAL;
+ } else {
+ bit4_root0_inv = gf4096_inv(bit4_root0);
+ bit4_root1_inv = gf4096_inv(bit4_root1);
+ bit4_root2_inv = gf4096_inv(bit4_root2);
+ bit4_root3_inv = gf4096_inv(bit4_root3);
+ find_4bit_err_pats(chk_syndrome_list[0],
+ chk_syndrome_list[1],
+ chk_syndrome_list[2],
+ chk_syndrome_list[3],
+ bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats);
+ err_info[0] = 0x4;
+ err_info[1] = (0x55e - err_pos(bit4_root0_inv));
+ err_info[2] = (0x55e - err_pos(bit4_root1_inv));
+ err_info[3] = (0x55e - err_pos(bit4_root2_inv));
+ err_info[4] = (0x55e - err_pos(bit4_root3_inv));
+ err_info[5] = err_pats[0];
+ err_info[6] = err_pats[1];
+ err_info[7] = err_pats[2];
+ err_info[8] = err_pats[3];
+ return 0;
+ }
+}
+
+void correct_12bit_symbol(unsigned char *buf, unsigned short sym,
+ unsigned short val)
+{
+ if (unlikely(sym > 1366)) {
+ printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym);
+ } else if (sym == 0) {
+ buf[0] ^= val;
+ } else if (sym & 1) {
+ buf[1+(3*(sym-1))/2] ^= (val >> 4);
+ buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4);
+ } else {
+ buf[2+(3*(sym-2))/2] ^= (val >> 8);
+ buf[3+(3*(sym-2))/2] ^= (val & 0xff);
+ }
+}
+
+static int debugecc = 0;
+module_param(debugecc, int, 0644);
+
+int cafe_correct_ecc(unsigned char *buf,
+ unsigned short *chk_syndrome_list)
+{
+ unsigned short err_info[9];
+ int i;
+
+ if (debugecc) {
+ printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n",
+ chk_syndrome_list[0], chk_syndrome_list[1],
+ chk_syndrome_list[2], chk_syndrome_list[3],
+ chk_syndrome_list[4], chk_syndrome_list[5],
+ chk_syndrome_list[6], chk_syndrome_list[7]);
+ for (i=0; i < 2048; i+=16) {
+ printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ i,
+ buf[i], buf[i+1], buf[i+2], buf[i+3],
+ buf[i+4], buf[i+5], buf[i+6], buf[i+7],
+ buf[i+8], buf[i+9], buf[i+10], buf[i+11],
+ buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
+ }
+ for ( ; i < 2112; i+=16) {
+ printk(KERN_WARNING "O %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ i - 2048,
+ buf[i], buf[i+1], buf[i+2], buf[i+3],
+ buf[i+4], buf[i+5], buf[i+6], buf[i+7],
+ buf[i+8], buf[i+9], buf[i+10], buf[i+11],
+ buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
+ }
+ }
+
+
+
+ if (chk_no_err_only(chk_syndrome_list, err_info) &&
+ chk_1_err_only(chk_syndrome_list, err_info) &&
+ chk_2_err_only(chk_syndrome_list, err_info) &&
+ chk_3_err_only(chk_syndrome_list, err_info) &&
+ chk_4_err_only(chk_syndrome_list, err_info)) {
+ return -EIO;
+ }
+
+ for (i=0; i < err_info[0]; i++) {
+ if (debugecc)
+ printk(KERN_WARNING "Correct symbol %d with 0x%03x\n",
+ err_info[1+i], err_info[5+i]);
+
+ correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]);
+ }
+
+ return err_info[0];
+}
+
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 94924d52a9b..8296305c829 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -11,7 +11,7 @@
* published by the Free Software Foundation.
*
* Overview:
- * This is a device driver for the NAND flash controller found on
+ * This is a device driver for the NAND flash controller found on
* the AMD CS5535/CS5536 companion chipsets for the Geode processor.
*
*/
@@ -303,7 +303,7 @@ static int __init cs553x_init(void)
err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
}
- /* Register all devices together here. This means we can easily hack it to
+ /* Register all devices together here. This means we can easily hack it to
do mtdconcat etc. if we want to. */
for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
if (cs553x_mtd[i]) {
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 6107f532855..12608c13cce 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1635,13 +1635,12 @@ static int __init doc_probe(unsigned long physadr)
len = sizeof(struct mtd_info) +
sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
- mtd = kmalloc(len, GFP_KERNEL);
+ mtd = kzalloc(len, GFP_KERNEL);
if (!mtd) {
printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
ret = -ENOMEM;
goto fail;
}
- memset(mtd, 0, len);
nand = (struct nand_chip *) (mtd + 1);
doc = (struct doc_priv *) (nand + 1);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 41bfcae1fbf..dfe56e03e48 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -362,7 +362,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
* access
*/
ofs += mtd->oobsize;
- chip->ops.len = 2;
+ chip->ops.len = chip->ops.ooblen = 2;
chip->ops.datbuf = NULL;
chip->ops.oobbuf = buf;
chip->ops.ooboffs = chip->badblockpos & ~0x01;
@@ -755,7 +755,7 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
+ * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
@@ -795,7 +795,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
+ * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
@@ -839,7 +839,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
@@ -897,12 +897,11 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip structure
* @oob: oob destination address
* @ops: oob ops structure
+ * @len: size of oob to transfer
*/
static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
- struct mtd_oob_ops *ops)
+ struct mtd_oob_ops *ops, size_t len)
{
- size_t len = ops->ooblen;
-
switch(ops->mode) {
case MTD_OOB_PLACE:
@@ -960,6 +959,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
int sndcmd = 1;
int ret = 0;
uint32_t readlen = ops->len;
+ uint32_t oobreadlen = ops->ooblen;
uint8_t *bufpoi, *oob, *buf;
stats = mtd->ecc_stats;
@@ -971,7 +971,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
page = realpage & chip->pagemask;
col = (int)(from & (mtd->writesize - 1));
- chip->oob_poi = chip->buffers->oobrbuf;
buf = ops->datbuf;
oob = ops->oobbuf;
@@ -1007,10 +1006,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (unlikely(oob)) {
/* Raw mode does data:oob:data:oob */
- if (ops->mode != MTD_OOB_RAW)
- oob = nand_transfer_oob(chip, oob, ops);
- else
- buf = nand_transfer_oob(chip, buf, ops);
+ if (ops->mode != MTD_OOB_RAW) {
+ int toread = min(oobreadlen,
+ chip->ecc.layout->oobavail);
+ if (toread) {
+ oob = nand_transfer_oob(chip,
+ oob, ops, toread);
+ oobreadlen -= toread;
+ }
+ } else
+ buf = nand_transfer_oob(chip,
+ buf, ops, mtd->oobsize);
}
if (!(chip->options & NAND_NO_READRDY)) {
@@ -1057,6 +1063,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
}
ops->retlen = ops->len - (size_t) readlen;
+ if (oob)
+ ops->oobretlen = ops->ooblen - oobreadlen;
if (ret)
return ret;
@@ -1257,12 +1265,18 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
int page, realpage, chipnr, sndcmd = 1;
struct nand_chip *chip = mtd->priv;
int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
- int readlen = ops->len;
+ int readlen = ops->ooblen;
+ int len;
uint8_t *buf = ops->oobbuf;
DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
(unsigned long long)from, readlen);
+ if (ops->mode == MTD_OOB_RAW)
+ len = mtd->oobsize;
+ else
+ len = chip->ecc.layout->oobavail;
+
chipnr = (int)(from >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
@@ -1270,11 +1284,11 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
realpage = (int)(from >> chip->page_shift);
page = realpage & chip->pagemask;
- chip->oob_poi = chip->buffers->oobrbuf;
-
while(1) {
sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
- buf = nand_transfer_oob(chip, buf, ops);
+
+ len = min(len, readlen);
+ buf = nand_transfer_oob(chip, buf, ops, len);
if (!(chip->options & NAND_NO_READRDY)) {
/*
@@ -1289,7 +1303,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
nand_wait_ready(mtd);
}
- readlen -= ops->ooblen;
+ readlen -= len;
if (!readlen)
break;
@@ -1311,7 +1325,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
sndcmd = 1;
}
- ops->retlen = ops->len;
+ ops->oobretlen = ops->ooblen;
return 0;
}
@@ -1332,7 +1346,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
ops->retlen = 0;
/* Do not allow reads past end of device */
- if ((from + ops->len) > mtd->size) {
+ if (ops->datbuf && (from + ops->len) > mtd->size) {
DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
"Attempt read beyond end of device\n");
return -EINVAL;
@@ -1375,7 +1389,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
+ * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
@@ -1401,7 +1415,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
+ * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
@@ -1429,7 +1443,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
+ * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
@@ -1577,7 +1591,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
return NULL;
}
-#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
+#define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0
/**
* nand_do_write_ops - [Internal] NAND write with ECC
@@ -1590,15 +1604,16 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
{
- int chipnr, realpage, page, blockmask;
+ int chipnr, realpage, page, blockmask, column;
struct nand_chip *chip = mtd->priv;
uint32_t writelen = ops->len;
uint8_t *oob = ops->oobbuf;
uint8_t *buf = ops->datbuf;
- int bytes = mtd->writesize;
- int ret;
+ int ret, subpage;
ops->retlen = 0;
+ if (!writelen)
+ return 0;
/* reject writes, which are not page aligned */
if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
@@ -1607,8 +1622,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
return -EINVAL;
}
- if (!writelen)
- return 0;
+ column = to & (mtd->writesize - 1);
+ subpage = column || (writelen & (mtd->writesize - 1));
+
+ if (subpage && oob)
+ return -EINVAL;
chipnr = (int)(to >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
@@ -1626,15 +1644,29 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
(chip->pagebuf << chip->page_shift) < (to + ops->len))
chip->pagebuf = -1;
- chip->oob_poi = chip->buffers->oobwbuf;
+ /* If we're not given explicit OOB data, let it be 0xFF */
+ if (likely(!oob))
+ memset(chip->oob_poi, 0xff, mtd->oobsize);
while(1) {
+ int bytes = mtd->writesize;
int cached = writelen > bytes && page != blockmask;
+ uint8_t *wbuf = buf;
+
+ /* Partial page write ? */
+ if (unlikely(column || writelen < (mtd->writesize - 1))) {
+ cached = 0;
+ bytes = min_t(int, bytes - column, (int) writelen);
+ chip->pagebuf = -1;
+ memset(chip->buffers->databuf, 0xff, mtd->writesize);
+ memcpy(&chip->buffers->databuf[column], buf, bytes);
+ wbuf = chip->buffers->databuf;
+ }
if (unlikely(oob))
oob = nand_fill_oob(chip, oob, ops);
- ret = chip->write_page(mtd, chip, buf, page, cached,
+ ret = chip->write_page(mtd, chip, wbuf, page, cached,
(ops->mode == MTD_OOB_RAW));
if (ret)
break;
@@ -1643,6 +1675,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if (!writelen)
break;
+ column = 0;
buf += bytes;
realpage++;
@@ -1655,10 +1688,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
}
}
- if (unlikely(oob))
- memset(chip->oob_poi, 0xff, mtd->oobsize);
-
ops->retlen = ops->len - writelen;
+ if (unlikely(oob))
+ ops->oobretlen = ops->ooblen;
return ret;
}
@@ -1714,10 +1746,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
struct nand_chip *chip = mtd->priv;
DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)ops->len);
+ (unsigned int)to, (int)ops->ooblen);
/* Do not allow write past end of page */
- if ((ops->ooboffs + ops->len) > mtd->oobsize) {
+ if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) {
DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
"Attempt to write past end of page\n");
return -EINVAL;
@@ -1745,7 +1777,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
if (page == chip->pagebuf)
chip->pagebuf = -1;
- chip->oob_poi = chip->buffers->oobwbuf;
memset(chip->oob_poi, 0xff, mtd->oobsize);
nand_fill_oob(chip, ops->oobbuf, ops);
status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
@@ -1754,7 +1785,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
if (status)
return status;
- ops->retlen = ops->len;
+ ops->oobretlen = ops->ooblen;
return 0;
}
@@ -1774,7 +1805,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
ops->retlen = 0;
/* Do not allow writes past end of device */
- if ((to + ops->len) > mtd->size) {
+ if (ops->datbuf && (to + ops->len) > mtd->size) {
DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
"Attempt read beyond end of device\n");
return -EINVAL;
@@ -2188,8 +2219,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
/* Newer devices have all the information in additional id bytes */
if (!type->pagesize) {
int extid;
- /* The 3rd id byte contains non relevant data ATM */
- extid = chip->read_byte(mtd);
+ /* The 3rd id byte holds MLC / multichip data */
+ chip->cellinfo = chip->read_byte(mtd);
/* The 4th id byte is the important one */
extid = chip->read_byte(mtd);
/* Calc pagesize */
@@ -2349,8 +2380,8 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!chip->buffers)
return -ENOMEM;
- /* Preset the internal oob write buffer */
- memset(chip->buffers->oobwbuf, 0xff, mtd->oobsize);
+ /* Set the internal oob buffer location, just after the page data */
+ chip->oob_poi = chip->buffers->databuf + mtd->writesize;
/*
* If no default placement scheme is given, select an appropriate one
@@ -2469,6 +2500,24 @@ int nand_scan_tail(struct mtd_info *mtd)
}
chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
+ /*
+ * Allow subpage writes up to ecc.steps. Not possible for MLC
+ * FLASH.
+ */
+ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+ !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+ switch(chip->ecc.steps) {
+ case 2:
+ mtd->subpage_sft = 1;
+ break;
+ case 4:
+ case 8:
+ mtd->subpage_sft = 2;
+ break;
+ }
+ }
+ chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
+
/* Initialize state */
chip->state = FL_READY;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 9402653eb09..5e121ceaa59 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -333,7 +333,6 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
struct mtd_oob_ops ops;
int j, ret;
- ops.len = mtd->oobsize;
ops.ooblen = mtd->oobsize;
ops.oobbuf = buf;
ops.ooboffs = 0;
@@ -676,10 +675,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
"bad block table\n");
}
/* Read oob data */
- ops.len = (len >> this->page_shift) * mtd->oobsize;
+ ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
ops.oobbuf = &buf[len];
res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
- if (res < 0 || ops.retlen != ops.len)
+ if (res < 0 || ops.oobretlen != ops.ooblen)
goto outerr;
/* Calc the byte offset in the buffer */
@@ -961,14 +960,12 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
struct nand_bbt_descr *md = this->bbt_md;
len = mtd->size >> (this->bbt_erase_shift + 2);
- /* Allocate memory (2bit per block) */
- this->bbt = kmalloc(len, GFP_KERNEL);
+ /* Allocate memory (2bit per block) and clear the memory bad block table */
+ this->bbt = kzalloc(len, GFP_KERNEL);
if (!this->bbt) {
printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
return -ENOMEM;
}
- /* Clear the memory bad block table */
- memset(this->bbt, 0x00, len);
/* If no primary table decriptor is given, scan the device
* to build a memory based bad block table
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index dd438ca47d9..fde593e5e63 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -112,7 +112,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
/* Calculate final ECC code */
-#ifdef CONFIG_NAND_ECC_SMC
+#ifdef CONFIG_MTD_NAND_ECC_SMC
ecc_code[0] = ~tmp2;
ecc_code[1] = ~tmp1;
#else
@@ -148,7 +148,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
{
uint8_t s0, s1, s2;
-#ifdef CONFIG_NAND_ECC_SMC
+#ifdef CONFIG_MTD_NAND_ECC_SMC
s0 = calc_ecc[0] ^ read_ecc[0];
s1 = calc_ecc[1] ^ read_ecc[1];
s2 = calc_ecc[2] ^ read_ecc[2];
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 545ff252d81..c3bca9590ad 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -37,10 +37,6 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
-#ifdef CONFIG_NS_ABS_POS
-#include <asm/io.h>
-#endif
-
/* Default simulator parameters values */
#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -164,7 +160,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero");
/* After a command is input, the simulator goes to one of the following states */
#define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */
#define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */
-#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
+#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
#define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */
#define STATE_CMD_READOOB 0x00000005 /* read OOB area */
#define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */
@@ -231,6 +227,14 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero");
#define NS_MAX_PREVSTATES 1
/*
+ * A union to represent flash memory contents and flash buffer.
+ */
+union ns_mem {
+ u_char *byte; /* for byte access */
+ uint16_t *word; /* for 16-bit word access */
+};
+
+/*
* The structure which describes all the internal simulator data.
*/
struct nandsim {
@@ -247,17 +251,11 @@ struct nandsim {
uint16_t npstates; /* number of previous states saved */
uint16_t stateidx; /* current state index */
- /* The simulated NAND flash image */
- union flash_media {
- u_char *byte;
- uint16_t *word;
- } mem;
+ /* The simulated NAND flash pages array */
+ union ns_mem *pages;
/* Internal buffer of page + OOB size bytes */
- union internal_buffer {
- u_char *byte; /* for byte access */
- uint16_t *word; /* for 16-bit word access */
- } buf;
+ union ns_mem buf;
/* NAND flash "geometry" */
struct nandsin_geometry {
@@ -346,12 +344,49 @@ static struct mtd_info *nsmtd;
static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
/*
+ * Allocate array of page pointers and initialize the array to NULL
+ * pointers.
+ *
+ * RETURNS: 0 if success, -ENOMEM if memory alloc fails.
+ */
+static int alloc_device(struct nandsim *ns)
+{
+ int i;
+
+ ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
+ if (!ns->pages) {
+ NS_ERR("alloc_map: unable to allocate page array\n");
+ return -ENOMEM;
+ }
+ for (i = 0; i < ns->geom.pgnum; i++) {
+ ns->pages[i].byte = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * Free any allocated pages, and free the array of page pointers.
+ */
+static void free_device(struct nandsim *ns)
+{
+ int i;
+
+ if (ns->pages) {
+ for (i = 0; i < ns->geom.pgnum; i++) {
+ if (ns->pages[i].byte)
+ kfree(ns->pages[i].byte);
+ }
+ vfree(ns->pages);
+ }
+}
+
+/*
* Initialize the nandsim structure.
*
* RETURNS: 0 if success, -ERRNO if failure.
*/
-static int
-init_nandsim(struct mtd_info *mtd)
+static int init_nandsim(struct mtd_info *mtd)
{
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
struct nandsim *ns = (struct nandsim *)(chip->priv);
@@ -405,7 +440,7 @@ init_nandsim(struct mtd_info *mtd)
}
} else {
if (ns->geom.totsz <= (128 << 20)) {
- ns->geom.pgaddrbytes = 5;
+ ns->geom.pgaddrbytes = 4;
ns->geom.secaddrbytes = 2;
} else {
ns->geom.pgaddrbytes = 5;
@@ -439,23 +474,8 @@ init_nandsim(struct mtd_info *mtd)
printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
printk("options: %#x\n", ns->options);
- /* Map / allocate and initialize the flash image */
-#ifdef CONFIG_NS_ABS_POS
- ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob);
- if (!ns->mem.byte) {
- NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n",
- (void *)CONFIG_NS_ABS_POS);
- return -ENOMEM;
- }
-#else
- ns->mem.byte = vmalloc(ns->geom.totszoob);
- if (!ns->mem.byte) {
- NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n",
- ns->geom.totszoob);
- return -ENOMEM;
- }
- memset(ns->mem.byte, 0xFF, ns->geom.totszoob);
-#endif
+ if (alloc_device(ns) != 0)
+ goto error;
/* Allocate / initialize the internal buffer */
ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
@@ -474,11 +494,7 @@ init_nandsim(struct mtd_info *mtd)
return 0;
error:
-#ifdef CONFIG_NS_ABS_POS
- iounmap(ns->mem.byte);
-#else
- vfree(ns->mem.byte);
-#endif
+ free_device(ns);
return -ENOMEM;
}
@@ -486,16 +502,10 @@ error:
/*
* Free the nandsim structure.
*/
-static void
-free_nandsim(struct nandsim *ns)
+static void free_nandsim(struct nandsim *ns)
{
kfree(ns->buf.byte);
-
-#ifdef CONFIG_NS_ABS_POS
- iounmap(ns->mem.byte);
-#else
- vfree(ns->mem.byte);
-#endif
+ free_device(ns);
return;
}
@@ -503,8 +513,7 @@ free_nandsim(struct nandsim *ns)
/*
* Returns the string representation of 'state' state.
*/
-static char *
-get_state_name(uint32_t state)
+static char *get_state_name(uint32_t state)
{
switch (NS_STATE(state)) {
case STATE_CMD_READ0:
@@ -562,8 +571,7 @@ get_state_name(uint32_t state)
*
* RETURNS: 1 if wrong command, 0 if right.
*/
-static int
-check_command(int cmd)
+static int check_command(int cmd)
{
switch (cmd) {
@@ -589,8 +597,7 @@ check_command(int cmd)
/*
* Returns state after command is accepted by command number.
*/
-static uint32_t
-get_state_by_command(unsigned command)
+static uint32_t get_state_by_command(unsigned command)
{
switch (command) {
case NAND_CMD_READ0:
@@ -626,8 +633,7 @@ get_state_by_command(unsigned command)
/*
* Move an address byte to the correspondent internal register.
*/
-static inline void
-accept_addr_byte(struct nandsim *ns, u_char bt)
+static inline void accept_addr_byte(struct nandsim *ns, u_char bt)
{
uint byte = (uint)bt;
@@ -645,8 +651,7 @@ accept_addr_byte(struct nandsim *ns, u_char bt)
/*
* Switch to STATE_READY state.
*/
-static inline void
-switch_to_ready_state(struct nandsim *ns, u_char status)
+static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
{
NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY));
@@ -705,8 +710,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status)
* -1 - several matches.
* 0 - operation is found.
*/
-static int
-find_operation(struct nandsim *ns, uint32_t flag)
+static int find_operation(struct nandsim *ns, uint32_t flag)
{
int opsfound = 0;
int i, j, idx = 0;
@@ -791,14 +795,93 @@ find_operation(struct nandsim *ns, uint32_t flag)
}
/*
+ * Returns a pointer to the current page.
+ */
+static inline union ns_mem *NS_GET_PAGE(struct nandsim *ns)
+{
+ return &(ns->pages[ns->regs.row]);
+}
+
+/*
+ * Retuns a pointer to the current byte, within the current page.
+ */
+static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
+{
+ return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
+}
+
+/*
+ * Fill the NAND buffer with data read from the specified page.
+ */
+static void read_page(struct nandsim *ns, int num)
+{
+ union ns_mem *mypage;
+
+ mypage = NS_GET_PAGE(ns);
+ if (mypage->byte == NULL) {
+ NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
+ memset(ns->buf.byte, 0xFF, num);
+ } else {
+ NS_DBG("read_page: page %d allocated, reading from %d\n",
+ ns->regs.row, ns->regs.column + ns->regs.off);
+ memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
+ }
+}
+
+/*
+ * Erase all pages in the specified sector.
+ */
+static void erase_sector(struct nandsim *ns)
+{
+ union ns_mem *mypage;
+ int i;
+
+ mypage = NS_GET_PAGE(ns);
+ for (i = 0; i < ns->geom.pgsec; i++) {
+ if (mypage->byte != NULL) {
+ NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
+ kfree(mypage->byte);
+ mypage->byte = NULL;
+ }
+ mypage++;
+ }
+}
+
+/*
+ * Program the specified page with the contents from the NAND buffer.
+ */
+static int prog_page(struct nandsim *ns, int num)
+{
+ int i;
+ union ns_mem *mypage;
+ u_char *pg_off;
+
+ mypage = NS_GET_PAGE(ns);
+ if (mypage->byte == NULL) {
+ NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
+ mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
+ if (mypage->byte == NULL) {
+ NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
+ return -1;
+ }
+ memset(mypage->byte, 0xFF, ns->geom.pgszoob);
+ }
+
+ pg_off = NS_PAGE_BYTE_OFF(ns);
+ for (i = 0; i < num; i++)
+ pg_off[i] &= ns->buf.byte[i];
+
+ return 0;
+}
+
+/*
* If state has any action bit, perform this action.
*
* RETURNS: 0 if success, -1 if error.
*/
-static int
-do_state_action(struct nandsim *ns, uint32_t action)
+static int do_state_action(struct nandsim *ns, uint32_t action)
{
- int i, num;
+ int num;
int busdiv = ns->busw == 8 ? 1 : 2;
action &= ACTION_MASK;
@@ -822,7 +905,7 @@ do_state_action(struct nandsim *ns, uint32_t action)
break;
}
num = ns->geom.pgszoob - ns->regs.off - ns->regs.column;
- memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num);
+ read_page(ns, num);
NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n",
num, NS_RAW_OFFSET(ns) + ns->regs.off);
@@ -863,7 +946,7 @@ do_state_action(struct nandsim *ns, uint32_t action)
ns->regs.row, NS_RAW_OFFSET(ns));
NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift));
- memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob);
+ erase_sector(ns);
NS_MDELAY(erase_delay);
@@ -886,8 +969,8 @@ do_state_action(struct nandsim *ns, uint32_t action)
return -1;
}
- for (i = 0; i < num; i++)
- ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i];
+ if (prog_page(ns, num) == -1)
+ return -1;
NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
@@ -928,8 +1011,7 @@ do_state_action(struct nandsim *ns, uint32_t action)
/*
* Switch simulator's state.
*/
-static void
-switch_state(struct nandsim *ns)
+static void switch_state(struct nandsim *ns)
{
if (ns->op) {
/*
@@ -1070,8 +1152,7 @@ switch_state(struct nandsim *ns)
}
}
-static u_char
-ns_nand_read_byte(struct mtd_info *mtd)
+static u_char ns_nand_read_byte(struct mtd_info *mtd)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
u_char outb = 0x00;
@@ -1144,8 +1225,7 @@ ns_nand_read_byte(struct mtd_info *mtd)
return outb;
}
-static void
-ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
+static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
@@ -1308,15 +1388,13 @@ static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
ns_nand_write_byte(mtd, cmd);
}
-static int
-ns_device_ready(struct mtd_info *mtd)
+static int ns_device_ready(struct mtd_info *mtd)
{
NS_DBG("device_ready\n");
return 1;
}
-static uint16_t
-ns_nand_read_word(struct mtd_info *mtd)
+static uint16_t ns_nand_read_word(struct mtd_info *mtd)
{
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
@@ -1325,8 +1403,7 @@ ns_nand_read_word(struct mtd_info *mtd)
return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
}
-static void
-ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
@@ -1353,8 +1430,7 @@ ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
}
}
-static void
-ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
@@ -1407,8 +1483,7 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
return;
}
-static int
-ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len);
@@ -1436,14 +1511,12 @@ static int __init ns_init_module(void)
}
/* Allocate and initialize mtd_info, nand_chip and nandsim structures */
- nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
+ nsmtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip)
+ sizeof(struct nandsim), GFP_KERNEL);
if (!nsmtd) {
NS_ERR("unable to allocate core structures.\n");
return -ENOMEM;
}
- memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) +
- sizeof(struct nandsim));
chip = (struct nand_chip *)(nsmtd + 1);
nsmtd->priv = (void *)chip;
nand = (struct nandsim *)(chip + 1);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 039c759cfbf..fd7a8d5ba29 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -56,7 +56,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
} else
ccr |= NDFC_CCR_RESET_CE;
- writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
}
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index f8c49645324..9189ec8f243 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/rslib.h>
+#include <linux/bitrev.h>
#include <linux/module.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/mtd.h>
@@ -152,47 +153,6 @@ static struct nand_ecclayout rtc_from4_nand_oobinfo = {
.oobfree = {{32, 32}}
};
-/* Aargh. I missed the reversed bit order, when I
- * was talking to Renesas about the FPGA.
- *
- * The table is used for bit reordering and inversion
- * of the ecc byte which we get from the FPGA
- */
-static uint8_t revbits[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,
-};
-
#endif
/*
@@ -397,7 +357,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
/* Read the syndrom pattern from the FPGA and correct the bitorder */
rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
for (i = 0; i < 8; i++) {
- ecc[i] = revbits[(*rs_ecc) & 0xFF];
+ ecc[i] = bitrev8(*rs_ecc);
rs_ecc++;
}
@@ -496,7 +456,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
rtn = nand_do_read(mtd, page, len, &retlen, buf);
/* if read failed or > 1-bit error corrected */
- if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
+ if (rtn || (mtd->ecc_stats.corrected - corrected) > 1)
er_stat |= 1 << 1;
kfree(buf);
}
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index ff5cef24d5b..8b3203571ee 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -283,7 +283,7 @@ static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-
+
if (cmd == NAND_CMD_NONE)
return;
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index b5a5f8da472..4b1ba4fcfcd 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -57,17 +57,16 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
DEBUG(MTD_DEBUG_LEVEL1, "NFTL: add_mtd for %s\n", mtd->name);
- nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
+ nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
if (!nftl) {
printk(KERN_WARNING "NFTL: out of memory for data structures\n");
return;
}
- memset(nftl, 0, sizeof(*nftl));
nftl->mbd.mtd = mtd;
nftl->mbd.devnum = -1;
- nftl->mbd.blksize = 512;
+
nftl->mbd.tr = tr;
if (NFTL_mount(nftl) < 0) {
@@ -147,10 +146,9 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
ops.ooblen = len;
ops.oobbuf = buf;
ops.datbuf = NULL;
- ops.len = len;
res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
- *retlen = ops.retlen;
+ *retlen = ops.oobretlen;
return res;
}
@@ -168,10 +166,9 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
ops.ooblen = len;
ops.oobbuf = buf;
ops.datbuf = NULL;
- ops.len = len;
res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
- *retlen = ops.retlen;
+ *retlen = ops.oobretlen;
return res;
}
@@ -797,6 +794,7 @@ static struct mtd_blktrans_ops nftl_tr = {
.name = "nftl",
.major = NFTL_MAJOR,
.part_bits = NFTL_PARTN_BITS,
+ .blksize = 512,
.getgeo = nftl_getgeo,
.readsect = nftl_readblock,
#ifdef CONFIG_NFTL_RW
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index af06a80f44d..3d44d040a47 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -45,12 +45,10 @@ static int __devinit generic_onenand_probe(struct device *dev)
unsigned long size = res->end - res->start + 1;
int err;
- info = kmalloc(sizeof(struct onenand_info), GFP_KERNEL);
+ info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- memset(info, 0, sizeof(struct onenand_info));
-
if (!request_mem_region(res->start, size, dev->driver->name)) {
err = -EBUSY;
goto out_free_info;
@@ -63,6 +61,7 @@ static int __devinit generic_onenand_probe(struct device *dev)
}
info->onenand.mmcontrol = pdata->mmcontrol;
+ info->onenand.irq = platform_get_irq(pdev, 0);
info->mtd.name = pdev->dev.bus_id;
info->mtd.priv = &info->onenand;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 8ed68b28afe..2da6bb26353 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
@@ -191,8 +192,6 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
struct onenand_chip *this = mtd->priv;
int value, readcmd = 0, block_cmd = 0;
int block, page;
- /* Now we use page size operation */
- int sectors = 4, count = 4;
/* Address translation */
switch (cmd) {
@@ -244,6 +243,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
}
if (page != -1) {
+ /* Now we use page size operation */
+ int sectors = 4, count = 4;
int dataram;
switch (cmd) {
@@ -297,7 +298,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
unsigned long timeout;
unsigned int flags = ONENAND_INT_MASTER;
unsigned int interrupt = 0;
- unsigned int ctrl, ecc;
+ unsigned int ctrl;
/* The 20 msec is enough */
timeout = jiffies + msecs_to_jiffies(20);
@@ -309,7 +310,6 @@ static int onenand_wait(struct mtd_info *mtd, int state)
if (state != FL_READING)
cond_resched();
- touch_softlockup_watchdog();
}
/* To get correct interrupt status in timeout case */
interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -317,28 +317,126 @@ static int onenand_wait(struct mtd_info *mtd, int state)
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
if (ctrl & ONENAND_CTRL_ERROR) {
- /* It maybe occur at initial bad block */
DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
- /* Clear other interrupt bits for preventing ECC error */
- interrupt &= ONENAND_INT_MASTER;
- }
-
- if (ctrl & ONENAND_CTRL_LOCK) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
- return -EACCES;
+ if (ctrl & ONENAND_CTRL_LOCK)
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");
+ return ctrl;
}
if (interrupt & ONENAND_INT_READ) {
- ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
- if (ecc & ONENAND_ECC_2BIT_ALL) {
+ int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+ if (ecc) {
DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
- return -EBADMSG;
+ if (ecc & ONENAND_ECC_2BIT_ALL) {
+ mtd->ecc_stats.failed++;
+ return ecc;
+ } else if (ecc & ONENAND_ECC_1BIT_ALL)
+ mtd->ecc_stats.corrected++;
}
}
return 0;
}
+/*
+ * onenand_interrupt - [DEFAULT] onenand interrupt handler
+ * @param irq onenand interrupt number
+ * @param dev_id interrupt data
+ *
+ * complete the work
+ */
+static irqreturn_t onenand_interrupt(int irq, void *data)
+{
+ struct onenand_chip *this = (struct onenand_chip *) data;
+
+ /* To handle shared interrupt */
+ if (!this->complete.done)
+ complete(&this->complete);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * onenand_interrupt_wait - [DEFAULT] wait until the command is done
+ * @param mtd MTD device structure
+ * @param state state to select the max. timeout value
+ *
+ * Wait for command done.
+ */
+static int onenand_interrupt_wait(struct mtd_info *mtd, int state)
+{
+ struct onenand_chip *this = mtd->priv;
+
+ wait_for_completion(&this->complete);
+
+ return onenand_wait(mtd, state);
+}
+
+/*
+ * onenand_try_interrupt_wait - [DEFAULT] try interrupt wait
+ * @param mtd MTD device structure
+ * @param state state to select the max. timeout value
+ *
+ * Try interrupt based wait (It is used one-time)
+ */
+static int onenand_try_interrupt_wait(struct mtd_info *mtd, int state)
+{
+ struct onenand_chip *this = mtd->priv;
+ unsigned long remain, timeout;
+
+ /* We use interrupt wait first */
+ this->wait = onenand_interrupt_wait;
+
+ timeout = msecs_to_jiffies(100);
+ remain = wait_for_completion_timeout(&this->complete, timeout);
+ if (!remain) {
+ printk(KERN_INFO "OneNAND: There's no interrupt. "
+ "We use the normal wait\n");
+
+ /* Release the irq */
+ free_irq(this->irq, this);
+
+ this->wait = onenand_wait;
+ }
+
+ return onenand_wait(mtd, state);
+}
+
+/*
+ * onenand_setup_wait - [OneNAND Interface] setup onenand wait method
+ * @param mtd MTD device structure
+ *
+ * There's two method to wait onenand work
+ * 1. polling - read interrupt status register
+ * 2. interrupt - use the kernel interrupt method
+ */
+static void onenand_setup_wait(struct mtd_info *mtd)
+{
+ struct onenand_chip *this = mtd->priv;
+ int syscfg;
+
+ init_completion(&this->complete);
+
+ if (this->irq <= 0) {
+ this->wait = onenand_wait;
+ return;
+ }
+
+ if (request_irq(this->irq, &onenand_interrupt,
+ IRQF_SHARED, "onenand", this)) {
+ /* If we can't get irq, use the normal wait */
+ this->wait = onenand_wait;
+ return;
+ }
+
+ /* Enable interrupt */
+ syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
+ syscfg |= ONENAND_SYS_CFG1_IOBE;
+ this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
+
+ this->wait = onenand_try_interrupt_wait;
+}
+
/**
* onenand_bufferram_offset - [DEFAULT] BufferRAM offset
* @param mtd MTD data structure
@@ -609,9 +707,10 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
struct onenand_chip *this = mtd->priv;
+ struct mtd_ecc_stats stats;
int read = 0, column;
int thislen;
- int ret = 0;
+ int ret = 0, boundary = 0;
DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
@@ -627,38 +726,61 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
/* TODO handling oob */
- while (read < len) {
- thislen = min_t(int, mtd->writesize, len - read);
-
- column = from & (mtd->writesize - 1);
- if (column + thislen > mtd->writesize)
- thislen = mtd->writesize - column;
-
- if (!onenand_check_bufferram(mtd, from)) {
- this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
-
- ret = this->wait(mtd, FL_READING);
- /* First copy data and check return value for ECC handling */
- onenand_update_bufferram(mtd, from, 1);
- }
-
- this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
-
- read += thislen;
-
- if (read == len)
- break;
-
- if (ret) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
- goto out;
- }
-
- from += thislen;
- buf += thislen;
- }
+ stats = mtd->ecc_stats;
+
+ /* Read-while-load method */
+
+ /* Do first load to bufferRAM */
+ if (read < len) {
+ if (!onenand_check_bufferram(mtd, from)) {
+ this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
+ ret = this->wait(mtd, FL_READING);
+ onenand_update_bufferram(mtd, from, !ret);
+ }
+ }
+
+ thislen = min_t(int, mtd->writesize, len - read);
+ column = from & (mtd->writesize - 1);
+ if (column + thislen > mtd->writesize)
+ thislen = mtd->writesize - column;
+
+ while (!ret) {
+ /* If there is more to load then start next load */
+ from += thislen;
+ if (read + thislen < len) {
+ this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
+ /*
+ * Chip boundary handling in DDP
+ * Now we issued chip 1 read and pointed chip 1
+ * bufferam so we have to point chip 0 bufferam.
+ */
+ if (this->device_id & ONENAND_DEVICE_IS_DDP &&
+ unlikely(from == (this->chipsize >> 1))) {
+ this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2);
+ boundary = 1;
+ } else
+ boundary = 0;
+ ONENAND_SET_PREV_BUFFERRAM(this);
+ }
+ /* While load is going, read from last bufferRAM */
+ this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
+ /* See if we are done */
+ read += thislen;
+ if (read == len)
+ break;
+ /* Set up for next read from bufferRAM */
+ if (unlikely(boundary))
+ this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2);
+ ONENAND_SET_NEXT_BUFFERRAM(this);
+ buf += thislen;
+ thislen = min_t(int, mtd->writesize, len - read);
+ column = 0;
+ cond_resched();
+ /* Now wait for load */
+ ret = this->wait(mtd, FL_READING);
+ onenand_update_bufferram(mtd, from, !ret);
+ }
-out:
/* Deselect and wake up anyone waiting on the device */
onenand_release_device(mtd);
@@ -668,7 +790,14 @@ out:
* retlen == desired len and result == -EBADMSG
*/
*retlen = read;
- return ret;
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ if (ret)
+ return ret;
+
+ return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
}
/**
@@ -705,6 +834,8 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
column = from & (mtd->oobsize - 1);
while (read < len) {
+ cond_resched();
+
thislen = mtd->oobsize - column;
thislen = min_t(int, thislen, len);
@@ -717,16 +848,16 @@ int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+ if (ret) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);
+ goto out;
+ }
+
read += thislen;
if (read == len)
break;
- if (ret) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret);
- goto out;
- }
-
buf += thislen;
/* Read more? */
@@ -756,8 +887,8 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
{
BUG_ON(ops->mode != MTD_OOB_PLACE);
- return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len,
- &ops->retlen, ops->oobbuf);
+ return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->ooblen,
+ &ops->oobretlen, ops->oobbuf);
}
#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
@@ -804,6 +935,10 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
void __iomem *dataram0, *dataram1;
int ret = 0;
+ /* In partial page write, just skip it */
+ if ((addr & (mtd->writesize - 1)) != 0)
+ return 0;
+
this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
ret = this->wait(mtd, FL_READING);
@@ -826,7 +961,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
#define onenand_verify_oob(...) (0)
#endif
-#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
+#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)
/**
* onenand_write - [MTD Interface] write buffer to FLASH
@@ -844,6 +979,7 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
struct onenand_chip *this = mtd->priv;
int written = 0;
int ret = 0;
+ int column, subpage;
DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -862,45 +998,63 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
return -EINVAL;
}
+ column = to & (mtd->writesize - 1);
+ subpage = column || (len & (mtd->writesize - 1));
+
/* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_WRITING);
/* Loop until all data write */
while (written < len) {
- int thislen = min_t(int, mtd->writesize, len - written);
-
- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
+ int bytes = mtd->writesize;
+ int thislen = min_t(int, bytes, len - written);
+ u_char *wbuf = (u_char *) buf;
+
+ cond_resched();
+
+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes);
+
+ /* Partial page write */
+ if (subpage) {
+ bytes = min_t(int, bytes - column, (int) len);
+ memset(this->page_buf, 0xff, mtd->writesize);
+ memcpy(this->page_buf + column, buf, bytes);
+ wbuf = this->page_buf;
+ /* Even though partial write, we need page size */
+ thislen = mtd->writesize;
+ }
- this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
+ this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen);
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
- onenand_update_bufferram(mtd, to, 1);
+ /* In partial page write we don't update bufferram */
+ onenand_update_bufferram(mtd, to, !subpage);
ret = this->wait(mtd, FL_WRITING);
if (ret) {
DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
- goto out;
+ break;
}
- written += thislen;
-
/* Only check verify write turn on */
- ret = onenand_verify_page(mtd, (u_char *) buf, to);
+ ret = onenand_verify_page(mtd, (u_char *) wbuf, to);
if (ret) {
DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
- goto out;
+ break;
}
+ written += thislen;
+
if (written == len)
break;
+ column = 0;
to += thislen;
buf += thislen;
}
-out:
/* Deselect and wake up anyone waiting on the device */
onenand_release_device(mtd);
@@ -944,6 +1098,8 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
while (written < len) {
int thislen = min_t(int, mtd->oobsize, len - written);
+ cond_resched();
+
column = to & (mtd->oobsize - 1);
this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
@@ -999,8 +1155,8 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
{
BUG_ON(ops->mode != MTD_OOB_PLACE);
- return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len,
- &ops->retlen, ops->oobbuf);
+ return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->ooblen,
+ &ops->oobretlen, ops->oobbuf);
}
/**
@@ -1071,6 +1227,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASING;
while (len) {
+ cond_resched();
/* Check if we have a bad block, we do not erase bad blocks */
if (onenand_block_checkbad(mtd, addr, 0, 0)) {
@@ -1084,10 +1241,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
ret = this->wait(mtd, FL_ERASING);
/* Check, if it is write protected */
if (ret) {
- if (ret == -EPERM)
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n");
- else
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
instr->state = MTD_ERASE_FAILED;
instr->fail_addr = addr;
goto erase_exit;
@@ -1129,7 +1283,6 @@ static void onenand_sync(struct mtd_info *mtd)
onenand_release_device(mtd);
}
-
/**
* onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
* @param mtd MTD device structure
@@ -1196,32 +1349,38 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
}
/**
- * onenand_unlock - [MTD Interface] Unlock block(s)
+ * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s)
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
- * @param len number of bytes to unlock
+ * @param len number of bytes to lock or unlock
*
- * Unlock one or more blocks
+ * Lock or unlock one or more blocks
*/
-static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
{
struct onenand_chip *this = mtd->priv;
int start, end, block, value, status;
+ int wp_status_mask;
start = ofs >> this->erase_shift;
end = len >> this->erase_shift;
+ if (cmd == ONENAND_CMD_LOCK)
+ wp_status_mask = ONENAND_WP_LS;
+ else
+ wp_status_mask = ONENAND_WP_US;
+
/* Continuous lock scheme */
if (this->options & ONENAND_HAS_CONT_LOCK) {
/* Set start block address */
this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
/* Set end block address */
this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
- /* Write unlock command */
- this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+ /* Write lock command */
+ this->command(mtd, cmd, 0, 0);
/* There's no return value */
- this->wait(mtd, FL_UNLOCKING);
+ this->wait(mtd, FL_LOCKING);
/* Sanity check */
while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1230,7 +1389,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
/* Check lock status */
status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
- if (!(status & ONENAND_WP_US))
+ if (!(status & wp_status_mask))
printk(KERN_ERR "wp status = 0x%x\n", status);
return 0;
@@ -1246,11 +1405,11 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
/* Set start block address */
this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
- /* Write unlock command */
- this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0);
+ /* Write lock command */
+ this->command(mtd, cmd, 0, 0);
/* There's no return value */
- this->wait(mtd, FL_UNLOCKING);
+ this->wait(mtd, FL_LOCKING);
/* Sanity check */
while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1259,7 +1418,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
/* Check lock status */
status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
- if (!(status & ONENAND_WP_US))
+ if (!(status & wp_status_mask))
printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
}
@@ -1267,6 +1426,32 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
}
/**
+ * onenand_lock - [MTD Interface] Lock block(s)
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ * @param len number of bytes to unlock
+ *
+ * Lock one or more blocks
+ */
+static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
+}
+
+/**
+ * onenand_unlock - [MTD Interface] Unlock block(s)
+ * @param mtd MTD device structure
+ * @param ofs offset relative to mtd start
+ * @param len number of bytes to unlock
+ *
+ * Unlock one or more blocks
+ */
+static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+}
+
+/**
* onenand_check_lock_status - [OneNAND Interface] Check lock status
* @param this onenand chip data structure
*
@@ -1310,7 +1495,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
/* There's no return value */
- this->wait(mtd, FL_UNLOCKING);
+ this->wait(mtd, FL_LOCKING);
/* Sanity check */
while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
@@ -1334,7 +1519,7 @@ static int onenand_unlock_all(struct mtd_info *mtd)
return 0;
}
- mtd->unlock(mtd, 0x0, this->chipsize);
+ onenand_unlock(mtd, 0x0, this->chipsize);
return 0;
}
@@ -1762,7 +1947,7 @@ static int onenand_probe(struct mtd_info *mtd)
/* Read manufacturer and device IDs from Register */
maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
- ver_id= this->read_word(this->base + ONENAND_REG_VERSION_ID);
+ ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
/* Check OneNAND device */
if (maf_id != bram_maf_id || dev_id != bram_dev_id)
@@ -1846,7 +2031,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
if (!this->command)
this->command = onenand_command;
if (!this->wait)
- this->wait = onenand_wait;
+ onenand_setup_wait(mtd);
if (!this->read_bufferram)
this->read_bufferram = onenand_read_bufferram;
@@ -1883,23 +2068,30 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
init_waitqueue_head(&this->wq);
spin_lock_init(&this->chip_lock);
+ /*
+ * Allow subpage writes up to oobsize.
+ */
switch (mtd->oobsize) {
case 64:
this->ecclayout = &onenand_oob_64;
+ mtd->subpage_sft = 2;
break;
case 32:
this->ecclayout = &onenand_oob_32;
+ mtd->subpage_sft = 1;
break;
default:
printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
mtd->oobsize);
+ mtd->subpage_sft = 0;
/* To prevent kernel oops */
this->ecclayout = &onenand_oob_32;
break;
}
+ this->subpagesize = mtd->writesize >> mtd->subpage_sft;
mtd->ecclayout = this->ecclayout;
/* Fill in remaining MTD driver data */
@@ -1922,7 +2114,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
#endif
mtd->sync = onenand_sync;
- mtd->lock = NULL;
+ mtd->lock = onenand_lock;
mtd->unlock = onenand_unlock;
mtd->suspend = onenand_suspend;
mtd->resume = onenand_resume;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 1b00dac3d7d..98f8fd1c637 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -93,13 +93,15 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
readlen, &retlen, &buf[0]);
- if (ret)
+ /* If it is a initial bad block, just ignore it */
+ if (ret && !(ret & ONENAND_CTRL_LOAD))
return ret;
if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
i >> 1, (unsigned int) from);
+ mtd->ecc_stats.badblocks++;
break;
}
}
@@ -177,14 +179,12 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
int len, ret = 0;
len = mtd->size >> (this->erase_shift + 2);
- /* Allocate memory (2bit per block) */
- bbm->bbt = kmalloc(len, GFP_KERNEL);
+ /* Allocate memory (2bit per block) and clear the memory bad block table */
+ bbm->bbt = kzalloc(len, GFP_KERNEL);
if (!bbm->bbt) {
printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
return -ENOMEM;
}
- /* Clear the memory bad block table */
- memset(bbm->bbt, 0x00, len);
/* Set the bad block position */
bbm->badblockpos = ONENAND_BADBLOCK_POS;
@@ -230,14 +230,12 @@ int onenand_default_bbt(struct mtd_info *mtd)
struct onenand_chip *this = mtd->priv;
struct bbm_info *bbm;
- this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL);
+ this->bbm = kzalloc(sizeof(struct bbm_info), GFP_KERNEL);
if (!this->bbm)
return -ENOMEM;
bbm = this->bbm;
- memset(bbm, 0, sizeof(struct bbm_info));
-
/* 1KB page has same configuration as 2KB page */
if (!bbm->badblock_pattern)
bbm->badblock_pattern = &largepage_memorybased;
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 5b58523e4d4..035cd9b0cc0 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -96,7 +96,19 @@ static int parse_redboot_partitions(struct mtd_info *master,
*/
if (swab32(buf[i].size) == master->erasesize) {
int j;
- for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) {
+ for (j = 0; j < numslots; ++j) {
+
+ /* A single 0xff denotes a deleted entry.
+ * Two of them in a row is the end of the table.
+ */
+ if (buf[j].name[0] == 0xff) {
+ if (buf[j].name[1] == 0xff) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
/* The unsigned long fields were written with the
* wrong byte sex, name and pad have no byte sex.
*/
@@ -110,6 +122,9 @@ static int parse_redboot_partitions(struct mtd_info *master,
}
}
break;
+ } else {
+ /* re-calculate of real numslots */
+ numslots = buf[i].size / sizeof(struct fis_image_desc);
}
}
if (i == numslots) {
@@ -123,8 +138,13 @@ static int parse_redboot_partitions(struct mtd_info *master,
for (i = 0; i < numslots; i++) {
struct fis_list *new_fl, **prev;
- if (buf[i].name[0] == 0xff)
- continue;
+ if (buf[i].name[0] == 0xff) {
+ if (buf[i].name[1] == 0xff) {
+ break;
+ } else {
+ continue;
+ }
+ }
if (!redboot_checksum(&buf[i]))
break;
@@ -165,15 +185,13 @@ static int parse_redboot_partitions(struct mtd_info *master,
}
}
#endif
- parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
+ parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
if (!parts) {
ret = -ENOMEM;
goto out;
}
- memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
-
nullname = (char *)&parts[nrparts];
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
if (nulllen > 0) {
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index fa4362fb4dd..d4b1ba8f23e 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -768,7 +768,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
if (mtd->type != MTD_NORFLASH)
return;
- part = kcalloc(1, sizeof(struct partition), GFP_KERNEL);
+ part = kzalloc(sizeof(struct partition), GFP_KERNEL);
if (!part)
return;
@@ -787,7 +787,6 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
if (scan_header(part) == 0) {
part->mbd.size = part->sector_count;
- part->mbd.blksize = SECTOR_SIZE;
part->mbd.tr = tr;
part->mbd.devnum = -1;
if (!(mtd->flags & MTD_WRITEABLE))
@@ -829,6 +828,8 @@ struct mtd_blktrans_ops rfd_ftl_tr = {
.name = "rfd",
.major = RFD_FTL_MAJOR,
.part_bits = PART_BITS,
+ .blksize = SECTOR_SIZE,
+
.readsect = rfd_ftl_readsect,
.writesect = rfd_ftl_writesect,
.getgeo = rfd_ftl_getgeo,
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 79d3bb659bf..a5f3d60047d 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -172,13 +172,12 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
ops.mode = MTD_OOB_RAW;
ops.ooboffs = 0;
- ops.ooblen = mtd->oobsize;
- ops.len = OOB_SIZE;
+ ops.ooblen = OOB_SIZE;
ops.oobbuf = buf;
ops.datbuf = NULL;
ret = mtd->read_oob(mtd, offs, &ops);
- if (ret < 0 || ops.retlen != OOB_SIZE)
+ if (ret < 0 || ops.oobretlen != OOB_SIZE)
return -1;
return 0;
@@ -312,7 +311,6 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
ssfdc->mbd.mtd = mtd;
ssfdc->mbd.devnum = -1;
- ssfdc->mbd.blksize = SECTOR_SIZE;
ssfdc->mbd.tr = tr;
ssfdc->mbd.readonly = 1;
@@ -447,6 +445,7 @@ static struct mtd_blktrans_ops ssfdcr_tr = {
.name = "ssfdc",
.major = SSFDCR_MAJOR,
.part_bits = SSFDCR_PARTN_BITS,
+ .blksize = SECTOR_SIZE,
.getgeo = ssfdcr_getgeo,
.readsect = ssfdcr_readsect,
.add_mtd = ssfdcr_add_mtd,
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 7733697f777..2d5ba076471 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -500,7 +500,7 @@ int lance_open (struct net_device *dev)
int res;
/* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
- if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev))
+ if (request_irq(lp->irq, lance_interrupt, SA_SHIRQ, lp->name, dev))
return -EAGAIN;
res = lance_reset(dev);
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 458dd9f830c..6f93a765e56 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -617,13 +617,15 @@ rx_next:
* this round of polling
*/
if (rx_work) {
+ unsigned long flags;
+
if (cpr16(IntrStatus) & cp_rx_intr_mask)
goto rx_status_loop;
- local_irq_disable();
+ local_irq_save(flags);
cpw16_f(IntrMask, cp_intr_mask);
__netif_rx_complete(dev);
- local_irq_enable();
+ local_irq_restore(flags);
return 0; /* done */
}
@@ -763,17 +765,18 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
struct cp_private *cp = netdev_priv(dev);
unsigned entry;
u32 eor, flags;
+ unsigned long intr_flags;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
int mss = 0;
- spin_lock_irq(&cp->lock);
+ spin_lock_irqsave(&cp->lock, intr_flags);
/* This is a hard error, log it. */
if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) {
netif_stop_queue(dev);
- spin_unlock_irq(&cp->lock);
+ spin_unlock_irqrestore(&cp->lock, intr_flags);
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
return 1;
@@ -906,7 +909,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
netif_stop_queue(dev);
- spin_unlock_irq(&cp->lock);
+ spin_unlock_irqrestore(&cp->lock, intr_flags);
cpw8(TxPoll, NormalTxPoll);
dev->trans_start = jiffies;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 931028f672d..35ad5cff18e 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -2131,14 +2131,15 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
}
if (done) {
+ unsigned long flags;
/*
* Order is important since data can get interrupted
* again when we think we are done.
*/
- local_irq_disable();
+ local_irq_save(flags);
RTL_W16_F(IntrMask, rtl8139_intr_mask);
__netif_rx_complete(dev);
- local_irq_enable();
+ local_irq_restore(flags);
}
spin_unlock(&tp->rx_lock);
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 8236f26ffd4..640d7ca2ebc 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -1066,8 +1066,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
short length = skb->len;
dev->trans_start = jiffies;
- DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%x) called\n", dev->name,
- skb->len, (unsigned int)skb->data));
+ DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%p) called\n",
+ dev->name, skb->len, skb->data));
if (skb->len < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
@@ -1246,7 +1246,8 @@ struct net_device * __init i82596_probe(int unit)
dev->priv = (void *)(dev->mem_start);
lp = dev->priv;
- DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
+ DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%zd bytes), "
+ "lp->scb at 0x%08lx\n",
dev->name, (unsigned long)lp,
sizeof(struct i596_private), (unsigned long)&lp->scb));
memset((void *) lp, 0, sizeof(struct i596_private));
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f59be5eeda9..79eade7e9d9 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2384,6 +2384,14 @@ config CHELSIO_T1_1G
Enables support for Chelsio's gigabit Ethernet PCI cards. If you
are using only 10G cards say 'N' here.
+config CHELSIO_T1_NAPI
+ bool "Use Rx Polling (NAPI)"
+ depends on CHELSIO_T1
+ default y
+ help
+ NAPI is a driver API designed to reduce CPU and interrupt load
+ when the driver is receiving lots of packets from the card.
+
config EHEA
tristate "eHEA Ethernet support"
depends on IBMEBUS
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 602ed31a5dd..9305eb9b1b9 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -349,22 +349,11 @@ static void __init trif_probe2(int unit)
#endif
-/*
- * The loopback device is global so it can be directly referenced
- * by the network code. Also, it must be first on device list.
- */
-extern int loopback_init(void);
-
/* Statically configured drivers -- order matters here. */
static int __init net_olddevs_init(void)
{
int num;
- if (loopback_init()) {
- printk(KERN_ERR "Network loopback device setup failed\n");
- }
-
-
#ifdef CONFIG_SBNI
for (num = 0; num < 8; ++num)
sbni_probe(num);
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index d4e40816907..954191119d3 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -311,9 +311,10 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
#endif
dev->base_addr = ioaddr;
+ dev->irq = IRQ_AMIGA_PORTS;
/* Install the Interrupt handler */
- i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
+ i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
if (i) return i;
for(i = 0; i < ETHER_ADDR_LEN; i++) {
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index b98592a8bac..f22e46dfd77 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -186,7 +186,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static int ipddp_create(struct ipddp_route *new_rt)
{
- struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL);
+ struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL);
if (rt == NULL)
return -ENOMEM;
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 8ebd68e2af9..dd698b033a6 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -780,12 +780,10 @@ static struct ethtool_ops ep93xx_ethtool_ops = {
struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data)
{
struct net_device *dev;
- struct ep93xx_priv *ep;
dev = alloc_etherdev(sizeof(struct ep93xx_priv));
if (dev == NULL)
return NULL;
- ep = netdev_priv(dev);
memcpy(dev->dev_addr, data->dev_addr, ETH_ALEN);
@@ -840,9 +838,9 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
struct ep93xx_priv *ep;
int err;
- data = pdev->dev.platform_data;
if (pdev == NULL)
return -ENODEV;
+ data = pdev->dev.platform_data;
dev = ep93xx_dev_alloc(data);
if (dev == NULL) {
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 474a4e3438d..303a8d94ad4 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -110,6 +110,11 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
static void b44_halt(struct b44 *);
static void b44_init_rings(struct b44 *);
+
+#define B44_FULL_RESET 1
+#define B44_FULL_RESET_SKIP_PHY 2
+#define B44_PARTIAL_RESET 3
+
static void b44_init_hw(struct b44 *, int);
static int dma_desc_align_mask;
@@ -752,7 +757,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dest_idx * sizeof(dest_desc),
DMA_BIDIRECTIONAL);
- pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
+ pci_dma_sync_single_for_device(bp->pdev, le32_to_cpu(src_desc->addr),
RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
}
@@ -879,12 +884,14 @@ static int b44_poll(struct net_device *netdev, int *budget)
}
if (bp->istat & ISTAT_ERRORS) {
- spin_lock_irq(&bp->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->lock, flags);
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
netif_wake_queue(bp->dev);
- spin_unlock_irq(&bp->lock);
+ spin_unlock_irqrestore(&bp->lock, flags);
done = 1;
}
@@ -952,7 +959,7 @@ static void b44_tx_timeout(struct net_device *dev)
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET);
spin_unlock_irq(&bp->lock);
@@ -1069,7 +1076,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
b44_halt(bp);
dev->mtu = new_mtu;
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET);
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
@@ -1366,12 +1373,12 @@ static int b44_set_mac_addr(struct net_device *dev, void *p)
* packet processing. Invoked with bp->lock held.
*/
static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp, int full_reset)
+static void b44_init_hw(struct b44 *bp, int reset_kind)
{
u32 val;
b44_chip_reset(bp);
- if (full_reset) {
+ if (reset_kind == B44_FULL_RESET) {
b44_phy_reset(bp);
b44_setup_phy(bp);
}
@@ -1388,7 +1395,10 @@ static void b44_init_hw(struct b44 *bp, int full_reset)
bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
- if (full_reset) {
+ if (reset_kind == B44_PARTIAL_RESET) {
+ bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+ (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ } else {
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
@@ -1399,9 +1409,6 @@ static void b44_init_hw(struct b44 *bp, int full_reset)
bp->rx_prod = bp->rx_pending;
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
- } else {
- bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
}
val = br32(bp, B44_ENET_CTRL);
@@ -1418,7 +1425,7 @@ static int b44_open(struct net_device *dev)
goto out;
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET);
b44_check_phy(bp);
@@ -1627,7 +1634,7 @@ static int b44_close(struct net_device *dev)
netif_poll_enable(dev);
if (bp->flags & B44_FLAG_WOL_ENABLE) {
- b44_init_hw(bp, 0);
+ b44_init_hw(bp, B44_PARTIAL_RESET);
b44_setup_wol(bp);
}
@@ -1903,7 +1910,7 @@ static int b44_set_ringparam(struct net_device *dev,
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET);
netif_wake_queue(bp->dev);
spin_unlock_irq(&bp->lock);
@@ -1946,7 +1953,7 @@ static int b44_set_pauseparam(struct net_device *dev,
if (bp->flags & B44_FLAG_PAUSE_AUTO) {
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET);
} else {
__b44_set_flow_ctrl(bp, bp->flags);
}
@@ -2302,7 +2309,7 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
free_irq(dev->irq, dev);
if (bp->flags & B44_FLAG_WOL_ENABLE) {
- b44_init_hw(bp, 0);
+ b44_init_hw(bp, B44_PARTIAL_RESET);
b44_setup_wol(bp);
}
pci_disable_device(pdev);
@@ -2313,21 +2320,32 @@ static int b44_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct b44 *bp = netdev_priv(dev);
+ int rc = 0;
pci_restore_state(pdev);
- pci_enable_device(pdev);
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ printk(KERN_ERR PFX "%s: pci_enable_device failed\n",
+ dev->name);
+ return rc;
+ }
+
pci_set_master(pdev);
if (!netif_running(dev))
return 0;
- if (request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev))
+ rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
+ if (rc) {
printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
+ pci_disable_device(pdev);
+ return rc;
+ }
spin_lock_irq(&bp->lock);
b44_init_rings(bp);
- b44_init_hw(bp, 1);
+ b44_init_hw(bp, B44_FULL_RESET);
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 5bacb7587df..ee7b75b976b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -57,8 +57,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.5.1"
-#define DRV_MODULE_RELDATE "November 15, 2006"
+#define DRV_MODULE_VERSION "1.5.5"
+#define DRV_MODULE_RELDATE "February 1, 2007"
#define RUN_AT(x) (jiffies + (x))
@@ -217,9 +217,16 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp)
u32 diff;
smp_mb();
- diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
- if (diff > MAX_TX_DESC_CNT)
- diff = (diff & MAX_TX_DESC_CNT) - 1;
+
+ /* The ring uses 256 indices for 255 entries, one of them
+ * needs to be skipped.
+ */
+ diff = bp->tx_prod - bp->tx_cons;
+ if (unlikely(diff >= TX_DESC_CNT)) {
+ diff &= 0xffff;
+ if (diff == TX_DESC_CNT)
+ diff = MAX_TX_DESC_CNT;
+ }
return (bp->tx_ring_size - diff);
}
@@ -1338,8 +1345,6 @@ bnx2_init_copper_phy(struct bnx2 *bp)
{
u32 val;
- bp->phy_flags |= PHY_CRC_FIX_FLAG;
-
if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
bnx2_write_phy(bp, 0x18, 0x0c00);
bnx2_write_phy(bp, 0x17, 0x000a);
@@ -1351,6 +1356,14 @@ bnx2_init_copper_phy(struct bnx2 *bp)
bnx2_write_phy(bp, 0x18, 0x0400);
}
+ if (bp->phy_flags & PHY_DIS_EARLY_DAC_FLAG) {
+ bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS,
+ MII_BNX2_DSP_EXPAND_REG | 0x8);
+ bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
+ val &= ~(1 << 8);
+ bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
+ }
+
if (bp->dev->mtu > 1500) {
/* Set extended packet length bit */
bnx2_write_phy(bp, 0x18, 0x7);
@@ -2510,7 +2523,7 @@ bnx2_init_cpus(struct bnx2 *bp)
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
fw = &bnx2_cp_fw_09;
- load_cpu_fw(bp, &cpu_reg, fw);
+ rc = load_cpu_fw(bp, &cpu_reg, fw);
if (rc)
goto init_cpu_err;
}
@@ -3078,7 +3091,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
int buf_size)
{
u32 written, offset32, len32;
- u8 *buf, start[4], end[4], *flash_buffer = NULL;
+ u8 *buf, start[4], end[4], *align_buf = NULL, *flash_buffer = NULL;
int rc = 0;
int align_start, align_end;
@@ -3089,7 +3102,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
if ((align_start = (offset32 & 3))) {
offset32 &= ~3;
- len32 += align_start;
+ len32 += (4 - align_start);
if ((rc = bnx2_nvram_read(bp, offset32, start, 4)))
return rc;
}
@@ -3106,16 +3119,17 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
}
if (align_start || align_end) {
- buf = kmalloc(len32, GFP_KERNEL);
- if (buf == 0)
+ align_buf = kmalloc(len32, GFP_KERNEL);
+ if (align_buf == NULL)
return -ENOMEM;
if (align_start) {
- memcpy(buf, start, 4);
+ memcpy(align_buf, start, 4);
}
if (align_end) {
- memcpy(buf + len32 - 4, end, 4);
+ memcpy(align_buf + len32 - 4, end, 4);
}
- memcpy(buf + align_start, data_buf, buf_size);
+ memcpy(align_buf + align_start, data_buf, buf_size);
+ buf = align_buf;
}
if (bp->flash_info->buffered == 0) {
@@ -3249,11 +3263,8 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
}
nvram_write_end:
- if (bp->flash_info->buffered == 0)
- kfree(flash_buffer);
-
- if (align_start || align_end)
- kfree(buf);
+ kfree(flash_buffer);
+ kfree(align_buf);
return rc;
}
@@ -3998,7 +4009,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
if (!skb)
return -ENOMEM;
packet = skb_put(skb, pkt_size);
- memcpy(packet, bp->mac_addr, 6);
+ memcpy(packet, bp->dev->dev_addr, 6);
memset(packet + 6, 0x0, 8);
for (i = 14; i < pkt_size; i++)
packet[i] = (unsigned char) (i & 0xff);
@@ -5638,6 +5649,44 @@ poll_bnx2(struct net_device *dev)
}
#endif
+static void __devinit
+bnx2_get_5709_media(struct bnx2 *bp)
+{
+ u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
+ u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID;
+ u32 strap;
+
+ if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
+ return;
+ else if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) {
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ return;
+ }
+
+ if (val & BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
+ strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
+ else
+ strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
+
+ if (PCI_FUNC(bp->pdev->devfn) == 0) {
+ switch (strap) {
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ return;
+ }
+ } else {
+ switch (strap) {
+ case 0x1:
+ case 0x2:
+ case 0x4:
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ return;
+ }
+ }
+}
+
static int __devinit
bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
{
@@ -5804,9 +5853,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE);
if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
- BNX2_SHM_HDR_SIGNATURE_SIG)
- bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0);
- else
+ BNX2_SHM_HDR_SIGNATURE_SIG) {
+ u32 off = PCI_FUNC(pdev->devfn) << 2;
+
+ bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0 + off);
+ } else
bp->shmem_base = HOST_VIEW_SHMEM_BASE;
/* Get the permanent MAC address. First we need to make sure the
@@ -5858,10 +5909,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->phy_addr = 1;
/* Disable WOL support if we are running on a SERDES chip. */
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- if (CHIP_BOND_ID(bp) != BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
- bp->phy_flags |= PHY_SERDES_FLAG;
- } else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
+ if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ bnx2_get_5709_media(bp);
+ else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
bp->phy_flags |= PHY_SERDES_FLAG;
if (bp->phy_flags & PHY_SERDES_FLAG) {
@@ -5873,7 +5923,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
}
- }
+ } else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
+ CHIP_NUM(bp) == CHIP_NUM_5708)
+ bp->phy_flags |= PHY_CRC_FIX_FLAG;
+ else if (CHIP_ID(bp) == CHIP_ID_5709_A0)
+ bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG;
if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
(CHIP_ID(bp) == CHIP_ID_5708_B0) ||
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 13b6f9b11e0..ccbdf81c659 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6288,6 +6288,10 @@ struct l2_fhdr {
#define BCM5708S_TX_ACTL3 0x17
+#define MII_BNX2_DSP_RW_PORT 0x15
+#define MII_BNX2_DSP_ADDRESS 0x17
+#define MII_BNX2_DSP_EXPAND_REG 0x0f00
+
#define MIN_ETHERNET_PACKET_SIZE 60
#define MAX_ETHERNET_PACKET_SIZE 1514
#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
@@ -6489,6 +6493,7 @@ struct bnx2 {
#define PHY_INT_MODE_MASK_FLAG 0x300
#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
#define PHY_INT_MODE_LINK_READY_FLAG 0x200
+#define PHY_DIS_EARLY_DAC_FLAG 0x400
u32 chip_id;
/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
@@ -6512,6 +6517,7 @@ struct bnx2 {
#define CHIP_ID_5708_A0 0x57080000
#define CHIP_ID_5708_B0 0x57081000
#define CHIP_ID_5708_B1 0x57081010
+#define CHIP_ID_5709_A0 0x57090000
#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index dc434fb6da8..0978c9ac6d2 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -151,8 +151,8 @@ struct slave {
struct slave *next;
struct slave *prev;
int delay;
- u32 jiffies;
- u32 last_arp_rx;
+ unsigned long jiffies;
+ unsigned long last_arp_rx;
s8 link; /* one of BOND_LINK_XXXX */
s8 state; /* one of BOND_STATE_XXXX */
u32 original_flags;
@@ -242,7 +242,8 @@ extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slav
return bond->params.arp_validate & (1 << slave->state);
}
-extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave)
+extern inline unsigned long slave_last_rx(struct bonding *bond,
+ struct slave *slave)
{
if (slave_do_arp_validate(bond, slave))
return slave->last_arp_rx;
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index bae1de1e780..7845eaf6f29 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -395,7 +395,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
* Allocate the main control structure for this instance.
*/
maxmaxcode = MAXCODE(bits);
- db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),
+ db = kmalloc(sizeof (struct bsd_db),
GFP_KERNEL);
if (!db)
{
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index de48eadddbc..fd5d821f3f2 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -220,9 +220,8 @@ static int cxgb_up(struct adapter *adapter)
t1_interrupts_clear(adapter);
- adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0;
- err = request_irq(adapter->pdev->irq,
- t1_select_intr_handler(adapter),
+ adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
+ err = request_irq(adapter->pdev->irq, t1_interrupt,
adapter->params.has_msi ? 0 : IRQF_SHARED,
adapter->name, adapter);
if (err) {
@@ -764,18 +763,7 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
{
struct adapter *adapter = dev->priv;
- /*
- * If RX coalescing is requested we use NAPI, otherwise interrupts.
- * This choice can be made only when all ports and the TOE are off.
- */
- if (adapter->open_device_map == 0)
- adapter->params.sge.polling = c->use_adaptive_rx_coalesce;
-
- if (adapter->params.sge.polling) {
- adapter->params.sge.rx_coalesce_usecs = 0;
- } else {
- adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
- }
+ adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
@@ -944,7 +932,7 @@ static void t1_netpoll(struct net_device *dev)
struct adapter *adapter = dev->priv;
local_irq_save(flags);
- t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
+ t1_interrupt(adapter->pdev->irq, adapter);
local_irq_restore(flags);
}
#endif
@@ -1165,7 +1153,10 @@ static int __devinit init_one(struct pci_dev *pdev,
#ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = t1_netpoll;
#endif
+#ifdef CONFIG_CHELSIO_T1_NAPI
netdev->weight = 64;
+ netdev->poll = t1_poll;
+#endif
SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
}
diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c
index c7731b6f9de..82fed1dd500 100644
--- a/drivers/net/chelsio/my3126.c
+++ b/drivers/net/chelsio/my3126.c
@@ -170,9 +170,10 @@ static struct cphy *my3126_phy_create(adapter_t *adapter,
{
struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
- if (cphy)
- cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
+ if (!cphy)
+ return NULL;
+ cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
cphy->bmsr = 0;
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 0ca8d876e16..659cb2252e4 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1413,16 +1413,20 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
st->vlan_xtract++;
- if (adapter->params.sge.polling)
+#ifdef CONFIG_CHELSIO_T1_NAPI
vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
ntohs(p->vlan));
- else
+#else
vlan_hwaccel_rx(skb, adapter->vlan_grp,
ntohs(p->vlan));
- } else if (adapter->params.sge.polling)
+#endif
+ } else {
+#ifdef CONFIG_CHELSIO_T1_NAPI
netif_receive_skb(skb);
- else
+#else
netif_rx(skb);
+#endif
+ }
return 0;
}
@@ -1572,6 +1576,7 @@ static int process_responses(struct adapter *adapter, int budget)
return budget;
}
+#ifdef CONFIG_CHELSIO_T1_NAPI
/*
* A simpler version of process_responses() that handles only pure (i.e.,
* non data-carrying) responses. Such respones are too light-weight to justify
@@ -1619,92 +1624,76 @@ static int process_pure_responses(struct adapter *adapter, struct respQ_e *e)
* or protection from interrupts as data interrupts are off at this point and
* other adapter interrupts do not interfere.
*/
-static int t1_poll(struct net_device *dev, int *budget)
+int t1_poll(struct net_device *dev, int *budget)
{
struct adapter *adapter = dev->priv;
int effective_budget = min(*budget, dev->quota);
-
int work_done = process_responses(adapter, effective_budget);
+
*budget -= work_done;
dev->quota -= work_done;
if (work_done >= effective_budget)
return 1;
+ spin_lock_irq(&adapter->async_lock);
__netif_rx_complete(dev);
-
- /*
- * Because we don't atomically flush the following write it is
- * possible that in very rare cases it can reach the device in a way
- * that races with a new response being written plus an error interrupt
- * causing the NAPI interrupt handler below to return unhandled status
- * to the OS. To protect against this would require flushing the write
- * and doing both the write and the flush with interrupts off. Way too
- * expensive and unjustifiable given the rarity of the race.
- */
writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
- return 0;
-}
+ writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
+ adapter->regs + A_PL_ENABLE);
+ spin_unlock_irq(&adapter->async_lock);
-/*
- * Returns true if the device is already scheduled for polling.
- */
-static inline int napi_is_scheduled(struct net_device *dev)
-{
- return test_bit(__LINK_STATE_RX_SCHED, &dev->state);
+ return 0;
}
/*
* NAPI version of the main interrupt handler.
*/
-static irqreturn_t t1_interrupt_napi(int irq, void *data)
+irqreturn_t t1_interrupt(int irq, void *data)
{
- int handled;
struct adapter *adapter = data;
+ struct net_device *dev = adapter->sge->netdev;
struct sge *sge = adapter->sge;
- struct respQ *q = &adapter->sge->respQ;
+ u32 cause;
+ int handled = 0;
- /*
- * Clear the SGE_DATA interrupt first thing. Normally the NAPI
- * handler has control of the response queue and the interrupt handler
- * can look at the queue reliably only once it knows NAPI is off.
- * We can't wait that long to clear the SGE_DATA interrupt because we
- * could race with t1_poll rearming the SGE interrupt, so we need to
- * clear the interrupt speculatively and really early on.
- */
- writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+ cause = readl(adapter->regs + A_PL_CAUSE);
+ if (cause == 0 || cause == ~0)
+ return IRQ_NONE;
spin_lock(&adapter->async_lock);
- if (!napi_is_scheduled(sge->netdev)) {
+ if (cause & F_PL_INTR_SGE_DATA) {
+ struct respQ *q = &adapter->sge->respQ;
struct respQ_e *e = &q->entries[q->cidx];
- if (e->GenerationBit == q->genbit) {
- if (e->DataValid ||
- process_pure_responses(adapter, e)) {
- if (likely(__netif_rx_schedule_prep(sge->netdev)))
- __netif_rx_schedule(sge->netdev);
- else if (net_ratelimit())
- printk(KERN_INFO
- "NAPI schedule failure!\n");
- } else
- writel(q->cidx, adapter->regs + A_SG_SLEEPING);
-
- handled = 1;
- goto unlock;
- } else
- writel(q->cidx, adapter->regs + A_SG_SLEEPING);
- } else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) {
- printk(KERN_ERR "data interrupt while NAPI running\n");
- }
-
- handled = t1_slow_intr_handler(adapter);
+ handled = 1;
+ writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
+
+ if (e->GenerationBit == q->genbit &&
+ __netif_rx_schedule_prep(dev)) {
+ if (e->DataValid || process_pure_responses(adapter, e)) {
+ /* mask off data IRQ */
+ writel(adapter->slow_intr_mask,
+ adapter->regs + A_PL_ENABLE);
+ __netif_rx_schedule(sge->netdev);
+ goto unlock;
+ }
+ /* no data, no NAPI needed */
+ netif_poll_enable(dev);
+
+ }
+ writel(q->cidx, adapter->regs + A_SG_SLEEPING);
+ } else
+ handled = t1_slow_intr_handler(adapter);
+
if (!handled)
sge->stats.unhandled_irqs++;
- unlock:
+unlock:
spin_unlock(&adapter->async_lock);
return IRQ_RETVAL(handled != 0);
}
+#else
/*
* Main interrupt handler, optimized assuming that we took a 'DATA'
* interrupt.
@@ -1720,7 +1709,7 @@ static irqreturn_t t1_interrupt_napi(int irq, void *data)
* 5. If we took an interrupt, but no valid respQ descriptors was found we
* let the slow_intr_handler run and do error handling.
*/
-static irqreturn_t t1_interrupt(int irq, void *cookie)
+irqreturn_t t1_interrupt(int irq, void *cookie)
{
int work_done;
struct respQ_e *e;
@@ -1752,11 +1741,7 @@ static irqreturn_t t1_interrupt(int irq, void *cookie)
spin_unlock(&adapter->async_lock);
return IRQ_RETVAL(work_done != 0);
}
-
-irq_handler_t t1_select_intr_handler(adapter_t *adapter)
-{
- return adapter->params.sge.polling ? t1_interrupt_napi : t1_interrupt;
-}
+#endif
/*
* Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
@@ -2033,7 +2018,6 @@ static void sge_tx_reclaim_cb(unsigned long data)
*/
int t1_sge_set_coalesce_params(struct sge *sge, struct sge_params *p)
{
- sge->netdev->poll = t1_poll;
sge->fixed_intrtimer = p->rx_coalesce_usecs *
core_ticks_per_usec(sge->adapter);
writel(sge->fixed_intrtimer, sge->adapter->regs + A_SG_INTRTIMER);
@@ -2234,7 +2218,6 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter,
p->coalesce_enable = 0;
p->sample_interval_usecs = 0;
- p->polling = 0;
return sge;
nomem_port:
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 7ceb0117d03..d132a0ef2a2 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -76,7 +76,9 @@ struct sge *t1_sge_create(struct adapter *, struct sge_params *);
int t1_sge_configure(struct sge *, struct sge_params *);
int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
void t1_sge_destroy(struct sge *);
-irq_handler_t t1_select_intr_handler(adapter_t *adapter);
+irqreturn_t t1_interrupt(int irq, void *cookie);
+int t1_poll(struct net_device *, int *);
+
int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
void t1_set_vlan_accel(struct adapter *adapter, int on_off);
void t1_sge_start(struct sge *);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 03bf164f9e8..0cefef5e3f0 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1930,9 +1930,8 @@ static int e100_rx_alloc_list(struct nic *nic)
nic->rx_to_use = nic->rx_to_clean = NULL;
nic->ru_running = RU_UNINITIALIZED;
- if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC)))
+ if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
return -ENOMEM;
- memset(nic->rxs, 0, sizeof(struct rx) * count);
for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
@@ -2719,12 +2718,11 @@ 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);
-#ifdef CONFIG_E100_NAPI
if (netif_running(netdev))
netif_poll_disable(nic->netdev);
-#endif
del_timer_sync(&nic->watchdog);
netif_carrier_off(nic->netdev);
+ netif_device_detach(netdev);
pci_save_state(pdev);
@@ -2737,6 +2735,7 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
}
pci_disable_device(pdev);
+ free_irq(pdev->irq, netdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
@@ -2760,16 +2759,13 @@ static int e100_resume(struct pci_dev *pdev)
}
#endif /* CONFIG_PM */
-
static void e100_shutdown(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
-#ifdef CONFIG_E100_NAPI
if (netif_running(netdev))
netif_poll_disable(nic->netdev);
-#endif
del_timer_sync(&nic->watchdog);
netif_carrier_off(nic->netdev);
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index da459f7177c..fb96c87f9e5 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -100,6 +100,9 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
{ "rx_header_split", E1000_STAT(rx_hdr_split) },
{ "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
+ { "tx_smbus", E1000_STAT(stats.mgptc) },
+ { "rx_smbus", E1000_STAT(stats.mgprc) },
+ { "dropped_smbus", E1000_STAT(stats.mgpdc) },
};
#define E1000_QUEUE_STATS_LEN 0
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 3655d902b0b..9be44699300 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -308,141 +308,160 @@ e1000_phy_init_script(struct e1000_hw *hw)
int32_t
e1000_set_mac_type(struct e1000_hw *hw)
{
- DEBUGFUNC("e1000_set_mac_type");
-
- switch (hw->device_id) {
- case E1000_DEV_ID_82542:
- switch (hw->revision_id) {
- case E1000_82542_2_0_REV_ID:
- hw->mac_type = e1000_82542_rev2_0;
- break;
- case E1000_82542_2_1_REV_ID:
- hw->mac_type = e1000_82542_rev2_1;
- break;
- default:
- /* Invalid 82542 revision ID */
- return -E1000_ERR_MAC_TYPE;
- }
- break;
- case E1000_DEV_ID_82543GC_FIBER:
- case E1000_DEV_ID_82543GC_COPPER:
- hw->mac_type = e1000_82543;
- break;
- case E1000_DEV_ID_82544EI_COPPER:
- case E1000_DEV_ID_82544EI_FIBER:
- case E1000_DEV_ID_82544GC_COPPER:
- case E1000_DEV_ID_82544GC_LOM:
- hw->mac_type = e1000_82544;
- break;
- case E1000_DEV_ID_82540EM:
- case E1000_DEV_ID_82540EM_LOM:
- case E1000_DEV_ID_82540EP:
- case E1000_DEV_ID_82540EP_LOM:
- case E1000_DEV_ID_82540EP_LP:
- hw->mac_type = e1000_82540;
- break;
- case E1000_DEV_ID_82545EM_COPPER:
- case E1000_DEV_ID_82545EM_FIBER:
- hw->mac_type = e1000_82545;
- break;
- case E1000_DEV_ID_82545GM_COPPER:
- case E1000_DEV_ID_82545GM_FIBER:
- case E1000_DEV_ID_82545GM_SERDES:
- hw->mac_type = e1000_82545_rev_3;
- break;
- case E1000_DEV_ID_82546EB_COPPER:
- case E1000_DEV_ID_82546EB_FIBER:
- case E1000_DEV_ID_82546EB_QUAD_COPPER:
- hw->mac_type = e1000_82546;
- break;
- case E1000_DEV_ID_82546GB_COPPER:
- case E1000_DEV_ID_82546GB_FIBER:
- case E1000_DEV_ID_82546GB_SERDES:
- case E1000_DEV_ID_82546GB_PCIE:
- case E1000_DEV_ID_82546GB_QUAD_COPPER:
- case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
- hw->mac_type = e1000_82546_rev_3;
- break;
- case E1000_DEV_ID_82541EI:
- case E1000_DEV_ID_82541EI_MOBILE:
- case E1000_DEV_ID_82541ER_LOM:
- hw->mac_type = e1000_82541;
- break;
- case E1000_DEV_ID_82541ER:
- case E1000_DEV_ID_82541GI:
- case E1000_DEV_ID_82541GI_LF:
- case E1000_DEV_ID_82541GI_MOBILE:
- hw->mac_type = e1000_82541_rev_2;
- break;
- case E1000_DEV_ID_82547EI:
- case E1000_DEV_ID_82547EI_MOBILE:
- hw->mac_type = e1000_82547;
- break;
- case E1000_DEV_ID_82547GI:
- hw->mac_type = e1000_82547_rev_2;
- break;
- case E1000_DEV_ID_82571EB_COPPER:
- case E1000_DEV_ID_82571EB_FIBER:
- case E1000_DEV_ID_82571EB_SERDES:
- case E1000_DEV_ID_82571EB_QUAD_COPPER:
- case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
- hw->mac_type = e1000_82571;
- break;
- case E1000_DEV_ID_82572EI_COPPER:
- case E1000_DEV_ID_82572EI_FIBER:
- case E1000_DEV_ID_82572EI_SERDES:
- case E1000_DEV_ID_82572EI:
- hw->mac_type = e1000_82572;
- break;
- case E1000_DEV_ID_82573E:
- case E1000_DEV_ID_82573E_IAMT:
- case E1000_DEV_ID_82573L:
- hw->mac_type = e1000_82573;
- break;
- case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
- case E1000_DEV_ID_80003ES2LAN_SERDES_SPT:
- case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
- case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
- hw->mac_type = e1000_80003es2lan;
- break;
- case E1000_DEV_ID_ICH8_IGP_M_AMT:
- case E1000_DEV_ID_ICH8_IGP_AMT:
- case E1000_DEV_ID_ICH8_IGP_C:
- case E1000_DEV_ID_ICH8_IFE:
- case E1000_DEV_ID_ICH8_IFE_GT:
- case E1000_DEV_ID_ICH8_IFE_G:
- case E1000_DEV_ID_ICH8_IGP_M:
- hw->mac_type = e1000_ich8lan;
- break;
- default:
- /* Should never have loaded on this device */
- return -E1000_ERR_MAC_TYPE;
- }
-
- switch (hw->mac_type) {
- case e1000_ich8lan:
- hw->swfwhw_semaphore_present = TRUE;
- hw->asf_firmware_present = TRUE;
- break;
- case e1000_80003es2lan:
- hw->swfw_sync_present = TRUE;
- /* fall through */
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- hw->eeprom_semaphore_present = TRUE;
- /* fall through */
- case e1000_82541:
- case e1000_82547:
- case e1000_82541_rev_2:
- case e1000_82547_rev_2:
- hw->asf_firmware_present = TRUE;
- break;
- default:
- break;
- }
-
- return E1000_SUCCESS;
+ DEBUGFUNC("e1000_set_mac_type");
+
+ switch (hw->device_id) {
+ case E1000_DEV_ID_82542:
+ switch (hw->revision_id) {
+ case E1000_82542_2_0_REV_ID:
+ hw->mac_type = e1000_82542_rev2_0;
+ break;
+ case E1000_82542_2_1_REV_ID:
+ hw->mac_type = e1000_82542_rev2_1;
+ break;
+ default:
+ /* Invalid 82542 revision ID */
+ return -E1000_ERR_MAC_TYPE;
+ }
+ break;
+ case E1000_DEV_ID_82543GC_FIBER:
+ case E1000_DEV_ID_82543GC_COPPER:
+ hw->mac_type = e1000_82543;
+ break;
+ case E1000_DEV_ID_82544EI_COPPER:
+ case E1000_DEV_ID_82544EI_FIBER:
+ case E1000_DEV_ID_82544GC_COPPER:
+ case E1000_DEV_ID_82544GC_LOM:
+ hw->mac_type = e1000_82544;
+ break;
+ case E1000_DEV_ID_82540EM:
+ case E1000_DEV_ID_82540EM_LOM:
+ case E1000_DEV_ID_82540EP:
+ case E1000_DEV_ID_82540EP_LOM:
+ case E1000_DEV_ID_82540EP_LP:
+ hw->mac_type = e1000_82540;
+ break;
+ case E1000_DEV_ID_82545EM_COPPER:
+ case E1000_DEV_ID_82545EM_FIBER:
+ hw->mac_type = e1000_82545;
+ break;
+ case E1000_DEV_ID_82545GM_COPPER:
+ case E1000_DEV_ID_82545GM_FIBER:
+ case E1000_DEV_ID_82545GM_SERDES:
+ hw->mac_type = e1000_82545_rev_3;
+ break;
+ case E1000_DEV_ID_82546EB_COPPER:
+ case E1000_DEV_ID_82546EB_FIBER:
+ case E1000_DEV_ID_82546EB_QUAD_COPPER:
+ hw->mac_type = e1000_82546;
+ break;
+ case E1000_DEV_ID_82546GB_COPPER:
+ case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82546GB_SERDES:
+ case E1000_DEV_ID_82546GB_PCIE:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+ hw->mac_type = e1000_82546_rev_3;
+ break;
+ case E1000_DEV_ID_82541EI:
+ case E1000_DEV_ID_82541EI_MOBILE:
+ case E1000_DEV_ID_82541ER_LOM:
+ hw->mac_type = e1000_82541;
+ break;
+ case E1000_DEV_ID_82541ER:
+ case E1000_DEV_ID_82541GI:
+ case E1000_DEV_ID_82541GI_LF:
+ case E1000_DEV_ID_82541GI_MOBILE:
+ hw->mac_type = e1000_82541_rev_2;
+ break;
+ case E1000_DEV_ID_82547EI:
+ case E1000_DEV_ID_82547EI_MOBILE:
+ hw->mac_type = e1000_82547;
+ break;
+ case E1000_DEV_ID_82547GI:
+ hw->mac_type = e1000_82547_rev_2;
+ break;
+ case E1000_DEV_ID_82571EB_COPPER:
+ case E1000_DEV_ID_82571EB_FIBER:
+ case E1000_DEV_ID_82571EB_SERDES:
+ case E1000_DEV_ID_82571EB_QUAD_COPPER:
+ case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
+ hw->mac_type = e1000_82571;
+ break;
+ case E1000_DEV_ID_82572EI_COPPER:
+ case E1000_DEV_ID_82572EI_FIBER:
+ case E1000_DEV_ID_82572EI_SERDES:
+ case E1000_DEV_ID_82572EI:
+ hw->mac_type = e1000_82572;
+ break;
+ case E1000_DEV_ID_82573E:
+ case E1000_DEV_ID_82573E_IAMT:
+ case E1000_DEV_ID_82573L:
+ hw->mac_type = e1000_82573;
+ break;
+ case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
+ case E1000_DEV_ID_80003ES2LAN_SERDES_SPT:
+ case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
+ case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
+ hw->mac_type = e1000_80003es2lan;
+ break;
+ case E1000_DEV_ID_ICH8_IGP_M_AMT:
+ case E1000_DEV_ID_ICH8_IGP_AMT:
+ case E1000_DEV_ID_ICH8_IGP_C:
+ case E1000_DEV_ID_ICH8_IFE:
+ case E1000_DEV_ID_ICH8_IFE_GT:
+ case E1000_DEV_ID_ICH8_IFE_G:
+ case E1000_DEV_ID_ICH8_IGP_M:
+ hw->mac_type = e1000_ich8lan;
+ break;
+ default:
+ /* Should never have loaded on this device */
+ return -E1000_ERR_MAC_TYPE;
+ }
+
+ switch (hw->mac_type) {
+ case e1000_ich8lan:
+ hw->swfwhw_semaphore_present = TRUE;
+ hw->asf_firmware_present = TRUE;
+ break;
+ case e1000_80003es2lan:
+ hw->swfw_sync_present = TRUE;
+ /* fall through */
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_82573:
+ hw->eeprom_semaphore_present = TRUE;
+ /* fall through */
+ case e1000_82541:
+ case e1000_82547:
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+ hw->asf_firmware_present = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ /* The 82543 chip does not count tx_carrier_errors properly in
+ * FD mode
+ */
+ if (hw->mac_type == e1000_82543)
+ hw->bad_tx_carr_stats_fd = TRUE;
+
+ /* capable of receiving management packets to the host */
+ if (hw->mac_type >= e1000_82571)
+ hw->has_manc2h = TRUE;
+
+ /* In rare occasions, ESB2 systems would end up started without
+ * the RX unit being turned on.
+ */
+ if (hw->mac_type == e1000_80003es2lan)
+ hw->rx_needs_kicking = TRUE;
+
+ if (hw->mac_type > e1000_82544)
+ hw->has_smbus = TRUE;
+
+ return E1000_SUCCESS;
}
/*****************************************************************************
@@ -6575,7 +6594,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
- hw->bus_type = e1000_bus_type_unknown;
+ hw->bus_type = e1000_bus_type_pci;
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
@@ -7817,9 +7836,8 @@ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
fwsm = E1000_READ_REG(hw, FWSM);
factps = E1000_READ_REG(hw, FACTPS);
- if (((fwsm & E1000_FWSM_MODE_MASK) ==
- (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)) &&
- (factps & E1000_FACTPS_MNGCG))
+ if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
+ e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
return TRUE;
} else
if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 3321fb13bfa..d6710588334 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1301,165 +1301,170 @@ struct e1000_ffvt_entry {
#define E1000_82542_RSSIR E1000_RSSIR
#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC
+#define E1000_82542_MANC2H E1000_MANC2H
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
- uint64_t crcerrs;
- uint64_t algnerrc;
- uint64_t symerrs;
- uint64_t rxerrc;
- uint64_t txerrc;
- uint64_t mpc;
- uint64_t scc;
- uint64_t ecol;
- uint64_t mcc;
- uint64_t latecol;
- uint64_t colc;
- uint64_t dc;
- uint64_t tncrs;
- uint64_t sec;
- uint64_t cexterr;
- uint64_t rlec;
- uint64_t xonrxc;
- uint64_t xontxc;
- uint64_t xoffrxc;
- uint64_t xofftxc;
- uint64_t fcruc;
- uint64_t prc64;
- uint64_t prc127;
- uint64_t prc255;
- uint64_t prc511;
- uint64_t prc1023;
- uint64_t prc1522;
- uint64_t gprc;
- uint64_t bprc;
- uint64_t mprc;
- uint64_t gptc;
- uint64_t gorcl;
- uint64_t gorch;
- uint64_t gotcl;
- uint64_t gotch;
- uint64_t rnbc;
- uint64_t ruc;
- uint64_t rfc;
- uint64_t roc;
- uint64_t rlerrc;
- uint64_t rjc;
- uint64_t mgprc;
- uint64_t mgpdc;
- uint64_t mgptc;
- uint64_t torl;
- uint64_t torh;
- uint64_t totl;
- uint64_t toth;
- uint64_t tpr;
- uint64_t tpt;
- uint64_t ptc64;
- uint64_t ptc127;
- uint64_t ptc255;
- uint64_t ptc511;
- uint64_t ptc1023;
- uint64_t ptc1522;
- uint64_t mptc;
- uint64_t bptc;
- uint64_t tsctc;
- uint64_t tsctfc;
- uint64_t iac;
- uint64_t icrxptc;
- uint64_t icrxatc;
- uint64_t ictxptc;
- uint64_t ictxatc;
- uint64_t ictxqec;
- uint64_t ictxqmtc;
- uint64_t icrxdmtc;
- uint64_t icrxoc;
+ uint64_t crcerrs;
+ uint64_t algnerrc;
+ uint64_t symerrs;
+ uint64_t rxerrc;
+ uint64_t txerrc;
+ uint64_t mpc;
+ uint64_t scc;
+ uint64_t ecol;
+ uint64_t mcc;
+ uint64_t latecol;
+ uint64_t colc;
+ uint64_t dc;
+ uint64_t tncrs;
+ uint64_t sec;
+ uint64_t cexterr;
+ uint64_t rlec;
+ uint64_t xonrxc;
+ uint64_t xontxc;
+ uint64_t xoffrxc;
+ uint64_t xofftxc;
+ uint64_t fcruc;
+ uint64_t prc64;
+ uint64_t prc127;
+ uint64_t prc255;
+ uint64_t prc511;
+ uint64_t prc1023;
+ uint64_t prc1522;
+ uint64_t gprc;
+ uint64_t bprc;
+ uint64_t mprc;
+ uint64_t gptc;
+ uint64_t gorcl;
+ uint64_t gorch;
+ uint64_t gotcl;
+ uint64_t gotch;
+ uint64_t rnbc;
+ uint64_t ruc;
+ uint64_t rfc;
+ uint64_t roc;
+ uint64_t rlerrc;
+ uint64_t rjc;
+ uint64_t mgprc;
+ uint64_t mgpdc;
+ uint64_t mgptc;
+ uint64_t torl;
+ uint64_t torh;
+ uint64_t totl;
+ uint64_t toth;
+ uint64_t tpr;
+ uint64_t tpt;
+ uint64_t ptc64;
+ uint64_t ptc127;
+ uint64_t ptc255;
+ uint64_t ptc511;
+ uint64_t ptc1023;
+ uint64_t ptc1522;
+ uint64_t mptc;
+ uint64_t bptc;
+ uint64_t tsctc;
+ uint64_t tsctfc;
+ uint64_t iac;
+ uint64_t icrxptc;
+ uint64_t icrxatc;
+ uint64_t ictxptc;
+ uint64_t ictxatc;
+ uint64_t ictxqec;
+ uint64_t ictxqmtc;
+ uint64_t icrxdmtc;
+ uint64_t icrxoc;
};
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t __iomem *hw_addr;
- uint8_t __iomem *flash_address;
- e1000_mac_type mac_type;
- e1000_phy_type phy_type;
- uint32_t phy_init_script;
- e1000_media_type media_type;
- void *back;
- struct e1000_shadow_ram *eeprom_shadow_ram;
- uint32_t flash_bank_size;
- uint32_t flash_base_addr;
- e1000_fc_type fc;
- e1000_bus_speed bus_speed;
- e1000_bus_width bus_width;
- e1000_bus_type bus_type;
- struct e1000_eeprom_info eeprom;
- e1000_ms_type master_slave;
- e1000_ms_type original_master_slave;
- e1000_ffe_config ffe_config_state;
- uint32_t asf_firmware_present;
- uint32_t eeprom_semaphore_present;
- uint32_t swfw_sync_present;
- uint32_t swfwhw_semaphore_present;
- unsigned long io_base;
- uint32_t phy_id;
- uint32_t phy_revision;
- uint32_t phy_addr;
- uint32_t original_fc;
- uint32_t txcw;
- uint32_t autoneg_failed;
- uint32_t max_frame_size;
- uint32_t min_frame_size;
- uint32_t mc_filter_type;
- uint32_t num_mc_addrs;
- uint32_t collision_delta;
- uint32_t tx_packet_delta;
- uint32_t ledctl_default;
- uint32_t ledctl_mode1;
- uint32_t ledctl_mode2;
- boolean_t tx_pkt_filtering;
- struct e1000_host_mng_dhcp_cookie mng_cookie;
- uint16_t phy_spd_default;
- uint16_t autoneg_advertised;
- uint16_t pci_cmd_word;
- uint16_t fc_high_water;
- uint16_t fc_low_water;
- uint16_t fc_pause_time;
- uint16_t current_ifs_val;
- uint16_t ifs_min_val;
- uint16_t ifs_max_val;
- uint16_t ifs_step_size;
- uint16_t ifs_ratio;
- uint16_t device_id;
- uint16_t vendor_id;
- uint16_t subsystem_id;
- uint16_t subsystem_vendor_id;
- uint8_t revision_id;
- uint8_t autoneg;
- uint8_t mdix;
- uint8_t forced_speed_duplex;
- uint8_t wait_autoneg_complete;
- uint8_t dma_fairness;
- uint8_t mac_addr[NODE_ADDRESS_SIZE];
- uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
- boolean_t disable_polarity_correction;
- boolean_t speed_downgraded;
- e1000_smart_speed smart_speed;
- e1000_dsp_config dsp_config_state;
- boolean_t get_link_status;
- boolean_t serdes_link_down;
- boolean_t tbi_compatibility_en;
- boolean_t tbi_compatibility_on;
- boolean_t laa_is_present;
- boolean_t phy_reset_disable;
- boolean_t initialize_hw_bits_disable;
- boolean_t fc_send_xon;
- boolean_t fc_strict_ieee;
- boolean_t report_tx_early;
- boolean_t adaptive_ifs;
- boolean_t ifs_params_forced;
- boolean_t in_ifs_mode;
- boolean_t mng_reg_access_disabled;
- boolean_t leave_av_bit_off;
- boolean_t kmrn_lock_loss_workaround_disabled;
+ uint8_t __iomem *hw_addr;
+ uint8_t __iomem *flash_address;
+ e1000_mac_type mac_type;
+ e1000_phy_type phy_type;
+ uint32_t phy_init_script;
+ e1000_media_type media_type;
+ void *back;
+ struct e1000_shadow_ram *eeprom_shadow_ram;
+ uint32_t flash_bank_size;
+ uint32_t flash_base_addr;
+ e1000_fc_type fc;
+ e1000_bus_speed bus_speed;
+ e1000_bus_width bus_width;
+ e1000_bus_type bus_type;
+ struct e1000_eeprom_info eeprom;
+ e1000_ms_type master_slave;
+ e1000_ms_type original_master_slave;
+ e1000_ffe_config ffe_config_state;
+ uint32_t asf_firmware_present;
+ uint32_t eeprom_semaphore_present;
+ uint32_t swfw_sync_present;
+ uint32_t swfwhw_semaphore_present;
+ unsigned long io_base;
+ uint32_t phy_id;
+ uint32_t phy_revision;
+ uint32_t phy_addr;
+ uint32_t original_fc;
+ uint32_t txcw;
+ uint32_t autoneg_failed;
+ uint32_t max_frame_size;
+ uint32_t min_frame_size;
+ uint32_t mc_filter_type;
+ uint32_t num_mc_addrs;
+ uint32_t collision_delta;
+ uint32_t tx_packet_delta;
+ uint32_t ledctl_default;
+ uint32_t ledctl_mode1;
+ uint32_t ledctl_mode2;
+ boolean_t tx_pkt_filtering;
+ struct e1000_host_mng_dhcp_cookie mng_cookie;
+ uint16_t phy_spd_default;
+ uint16_t autoneg_advertised;
+ uint16_t pci_cmd_word;
+ uint16_t fc_high_water;
+ uint16_t fc_low_water;
+ uint16_t fc_pause_time;
+ uint16_t current_ifs_val;
+ uint16_t ifs_min_val;
+ uint16_t ifs_max_val;
+ uint16_t ifs_step_size;
+ uint16_t ifs_ratio;
+ uint16_t device_id;
+ uint16_t vendor_id;
+ uint16_t subsystem_id;
+ uint16_t subsystem_vendor_id;
+ uint8_t revision_id;
+ uint8_t autoneg;
+ uint8_t mdix;
+ uint8_t forced_speed_duplex;
+ uint8_t wait_autoneg_complete;
+ uint8_t dma_fairness;
+ uint8_t mac_addr[NODE_ADDRESS_SIZE];
+ uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
+ boolean_t disable_polarity_correction;
+ boolean_t speed_downgraded;
+ e1000_smart_speed smart_speed;
+ e1000_dsp_config dsp_config_state;
+ boolean_t get_link_status;
+ boolean_t serdes_link_down;
+ boolean_t tbi_compatibility_en;
+ boolean_t tbi_compatibility_on;
+ boolean_t laa_is_present;
+ boolean_t phy_reset_disable;
+ boolean_t initialize_hw_bits_disable;
+ boolean_t fc_send_xon;
+ boolean_t fc_strict_ieee;
+ boolean_t report_tx_early;
+ boolean_t adaptive_ifs;
+ boolean_t ifs_params_forced;
+ boolean_t in_ifs_mode;
+ boolean_t mng_reg_access_disabled;
+ boolean_t leave_av_bit_off;
+ boolean_t kmrn_lock_loss_workaround_disabled;
+ boolean_t bad_tx_carr_stats_fd;
+ boolean_t has_manc2h;
+ boolean_t rx_needs_kicking;
+ boolean_t has_smbus;
};
@@ -2418,6 +2423,7 @@ struct e1000_host_command_info {
#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */
#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
+#define E1000_PBA_20K 0x0014
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
#define E1000_PBA_30K 0x001E
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 73f3a85fd23..c6259c7127f 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -213,6 +213,12 @@ static void e1000_netpoll (struct net_device *netdev);
extern void e1000_check_options(struct e1000_adapter *adapter);
+#define COPYBREAK_DEFAULT 256
+static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
+module_param(copybreak, uint, 0644);
+MODULE_PARM_DESC(copybreak,
+ "Maximum size of packet that is copied to a new buffer on receive");
+
static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state);
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
@@ -264,7 +270,13 @@ e1000_init_module(void)
printk(KERN_INFO "%s\n", e1000_copyright);
ret = pci_register_driver(&e1000_driver);
-
+ if (copybreak != COPYBREAK_DEFAULT) {
+ if (copybreak == 0)
+ printk(KERN_INFO "e1000: copybreak disabled\n");
+ else
+ printk(KERN_INFO "e1000: copybreak enabled for "
+ "packets <= %u bytes\n", copybreak);
+ }
return ret;
}
@@ -464,6 +476,52 @@ e1000_get_hw_control(struct e1000_adapter *adapter)
}
}
+static void
+e1000_init_manageability(struct e1000_adapter *adapter)
+{
+ if (adapter->en_mng_pt) {
+ uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
+
+ /* disable hardware interception of ARP */
+ manc &= ~(E1000_MANC_ARP_EN);
+
+ /* enable receiving management packets to the host */
+ /* this will probably generate destination unreachable messages
+ * from the host OS, but the packets will be handled on SMBUS */
+ if (adapter->hw.has_manc2h) {
+ uint32_t manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+
+ manc |= E1000_MANC_EN_MNG2HOST;
+#define E1000_MNG2HOST_PORT_623 (1 << 5)
+#define E1000_MNG2HOST_PORT_664 (1 << 6)
+ manc2h |= E1000_MNG2HOST_PORT_623;
+ manc2h |= E1000_MNG2HOST_PORT_664;
+ E1000_WRITE_REG(&adapter->hw, MANC2H, manc2h);
+ }
+
+ E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ }
+}
+
+static void
+e1000_release_manageability(struct e1000_adapter *adapter)
+{
+ if (adapter->en_mng_pt) {
+ uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
+
+ /* re-enable hardware interception of ARP */
+ manc |= E1000_MANC_ARP_EN;
+
+ if (adapter->hw.has_manc2h)
+ manc &= ~E1000_MANC_EN_MNG2HOST;
+
+ /* don't explicitly have to mess with MANC2H since
+ * MANC has an enable disable that gates MANC2H */
+
+ E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ }
+}
+
int
e1000_up(struct e1000_adapter *adapter)
{
@@ -475,6 +533,7 @@ e1000_up(struct e1000_adapter *adapter)
e1000_set_multi(netdev);
e1000_restore_vlan(adapter);
+ e1000_init_manageability(adapter);
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
@@ -497,7 +556,8 @@ e1000_up(struct e1000_adapter *adapter)
clear_bit(__E1000_DOWN, &adapter->flags);
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+ /* fire a link change interrupt to start the watchdog */
+ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
return 0;
}
@@ -614,16 +674,34 @@ e1000_reinit_locked(struct e1000_adapter *adapter)
void
e1000_reset(struct e1000_adapter *adapter)
{
- uint32_t pba, manc;
+ uint32_t pba = 0, tx_space, min_tx_space, min_rx_space;
uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
+ boolean_t legacy_pba_adjust = FALSE;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
*/
switch (adapter->hw.mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ case e1000_82544:
+ case e1000_82540:
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ legacy_pba_adjust = TRUE;
+ pba = E1000_PBA_48K;
+ break;
+ case e1000_82545:
+ case e1000_82545_rev_3:
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ pba = E1000_PBA_48K;
+ break;
case e1000_82547:
case e1000_82547_rev_2:
+ legacy_pba_adjust = TRUE;
pba = E1000_PBA_30K;
break;
case e1000_82571:
@@ -632,27 +710,80 @@ e1000_reset(struct e1000_adapter *adapter)
pba = E1000_PBA_38K;
break;
case e1000_82573:
- pba = E1000_PBA_12K;
+ pba = E1000_PBA_20K;
break;
case e1000_ich8lan:
pba = E1000_PBA_8K;
- break;
- default:
- pba = E1000_PBA_48K;
+ case e1000_undefined:
+ case e1000_num_macs:
break;
}
- if ((adapter->hw.mac_type != e1000_82573) &&
- (adapter->netdev->mtu > E1000_RXBUFFER_8192))
- pba -= 8; /* allocate more FIFO for Tx */
+ if (legacy_pba_adjust == TRUE) {
+ if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
+ pba -= 8; /* allocate more FIFO for Tx */
+ if (adapter->hw.mac_type == e1000_82547) {
+ adapter->tx_fifo_head = 0;
+ adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
+ adapter->tx_fifo_size =
+ (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
+ atomic_set(&adapter->tx_fifo_stall, 0);
+ }
+ } else if (adapter->hw.max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ /* adjust PBA for jumbo frames */
+ E1000_WRITE_REG(&adapter->hw, PBA, pba);
+
+ /* To maintain wire speed transmits, the Tx FIFO should be
+ * large enough to accomodate two full transmit packets,
+ * rounded up to the next 1KB and expressed in KB. Likewise,
+ * the Rx FIFO should be large enough to accomodate at least
+ * one full receive packet and is similarly rounded up and
+ * expressed in KB. */
+ pba = E1000_READ_REG(&adapter->hw, PBA);
+ /* upper 16 bits has Tx packet buffer allocation size in KB */
+ tx_space = pba >> 16;
+ /* lower 16 bits has Rx packet buffer allocation size in KB */
+ pba &= 0xffff;
+ /* don't include ethernet FCS because hardware appends/strips */
+ min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE +
+ VLAN_TAG_SIZE;
+ min_tx_space = min_rx_space;
+ min_tx_space *= 2;
+ E1000_ROUNDUP(min_tx_space, 1024);
+ min_tx_space >>= 10;
+ E1000_ROUNDUP(min_rx_space, 1024);
+ min_rx_space >>= 10;
+
+ /* If current Tx allocation is less than the min Tx FIFO size,
+ * and the min Tx FIFO size is less than the current Rx FIFO
+ * allocation, take space away from current Rx allocation */
+ if (tx_space < min_tx_space &&
+ ((min_tx_space - tx_space) < pba)) {
+ pba = pba - (min_tx_space - tx_space);
+
+ /* PCI/PCIx hardware has PBA alignment constraints */
+ switch (adapter->hw.mac_type) {
+ case e1000_82545 ... e1000_82546_rev_3:
+ pba &= ~(E1000_PBA_8K - 1);
+ break;
+ default:
+ break;
+ }
- if (adapter->hw.mac_type == e1000_82547) {
- adapter->tx_fifo_head = 0;
- adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
- adapter->tx_fifo_size =
- (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
- atomic_set(&adapter->tx_fifo_stall, 0);
+ /* if short on rx space, rx wins and must trump tx
+ * adjustment or use Early Receive if available */
+ if (pba < min_rx_space) {
+ switch (adapter->hw.mac_type) {
+ case e1000_82573:
+ /* ERT enabled in e1000_configure_rx */
+ break;
+ default:
+ pba = min_rx_space;
+ break;
+ }
+ }
+ }
}
E1000_WRITE_REG(&adapter->hw, PBA, pba);
@@ -685,6 +816,20 @@ e1000_reset(struct e1000_adapter *adapter)
if (e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
+
+ /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
+ if (adapter->hw.mac_type >= e1000_82544 &&
+ adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ adapter->hw.autoneg == 1 &&
+ adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
+ uint32_t ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ /* clear phy power management bit if we are in gig only mode,
+ * which if enabled will attempt negotiation to 100Mb, which
+ * can cause a loss of link at power off or driver unload */
+ ctrl &= ~E1000_CTRL_SWDPIN3;
+ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ }
+
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
@@ -705,14 +850,7 @@ e1000_reset(struct e1000_adapter *adapter)
phy_data);
}
- if ((adapter->en_mng_pt) &&
- (adapter->hw.mac_type >= e1000_82540) &&
- (adapter->hw.mac_type < e1000_82571) &&
- (adapter->hw.media_type == e1000_media_type_copper)) {
- manc = E1000_READ_REG(&adapter->hw, MANC);
- manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
- }
+ e1000_release_manageability(adapter);
}
/**
@@ -1078,22 +1216,13 @@ e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t manc;
#ifdef CONFIG_E1000_NAPI
int i;
#endif
flush_scheduled_work();
- if (adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.mac_type < e1000_82571 &&
- adapter->hw.media_type == e1000_media_type_copper) {
- manc = E1000_READ_REG(&adapter->hw, MANC);
- if (manc & E1000_MANC_SMBUS_EN) {
- manc |= E1000_MANC_ARP_EN;
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
- }
- }
+ e1000_release_manageability(adapter);
/* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant. */
@@ -1531,9 +1660,9 @@ e1000_configure_tx(struct e1000_adapter *adapter)
}
/* Set the default values for the Tx Inter Packet Gap timer */
-
- if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes)
+ if (adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes))
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
else
tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
@@ -2528,6 +2657,13 @@ e1000_watchdog(unsigned long data)
netif_wake_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
adapter->smartspeed = 0;
+ } else {
+ /* make sure the receive unit is started */
+ if (adapter->hw.rx_needs_kicking) {
+ struct e1000_hw *hw = &adapter->hw;
+ uint32_t rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+ }
}
} else {
if (netif_carrier_ok(netdev)) {
@@ -2628,29 +2764,34 @@ static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
if (packets == 0)
goto update_itr_done;
-
switch (itr_setting) {
case lowest_latency:
- if ((packets < 5) && (bytes > 512))
+ /* jumbo frames get bulk treatment*/
+ if (bytes/packets > 8000)
+ retval = bulk_latency;
+ else if ((packets < 5) && (bytes > 512))
retval = low_latency;
break;
case low_latency: /* 50 usec aka 20000 ints/s */
if (bytes > 10000) {
- if ((packets < 10) ||
- ((bytes/packets) > 1200))
+ /* jumbo frames need bulk latency setting */
+ if (bytes/packets > 8000)
+ retval = bulk_latency;
+ else if ((packets < 10) || ((bytes/packets) > 1200))
retval = bulk_latency;
else if ((packets > 35))
retval = lowest_latency;
- } else if (packets <= 2 && bytes < 512)
+ } else if (bytes/packets > 2000)
+ retval = bulk_latency;
+ else if (packets <= 2 && bytes < 512)
retval = lowest_latency;
break;
case bulk_latency: /* 250 usec aka 4000 ints/s */
if (bytes > 25000) {
if (packets > 35)
retval = low_latency;
- } else {
- if (bytes < 6000)
- retval = low_latency;
+ } else if (bytes < 6000) {
+ retval = low_latency;
}
break;
}
@@ -2679,17 +2820,20 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
adapter->tx_itr,
adapter->total_tx_packets,
adapter->total_tx_bytes);
+ /* conservative mode (itr 3) eliminates the lowest_latency setting */
+ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
+ adapter->tx_itr = low_latency;
+
adapter->rx_itr = e1000_update_itr(adapter,
adapter->rx_itr,
adapter->total_rx_packets,
adapter->total_rx_bytes);
+ /* conservative mode (itr 3) eliminates the lowest_latency setting */
+ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
+ adapter->rx_itr = low_latency;
current_itr = max(adapter->rx_itr, adapter->tx_itr);
- /* conservative mode eliminates the lowest_latency setting */
- if (current_itr == lowest_latency && (adapter->itr_setting == 3))
- current_itr = low_latency;
-
switch (current_itr) {
/* counts and packets in update_itr are dependent on these numbers */
case lowest_latency:
@@ -3168,6 +3312,16 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (skb->data_len && (hdr_len == (skb->len - skb->data_len))) {
switch (adapter->hw.mac_type) {
unsigned int pull_size;
+ case e1000_82544:
+ /* Make sure we have room to chop off 4 bytes,
+ * and that the end alignment will work out to
+ * this hardware's requirements
+ * NOTE: this is a TSO only workaround
+ * if end byte alignment not correct move us
+ * into the next dword */
+ if ((unsigned long)(skb->tail - 1) & 4)
+ break;
+ /* fall through */
case e1000_82571:
case e1000_82572:
case e1000_82573:
@@ -3419,12 +3573,11 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
netdev->mtu = new_mtu;
+ adapter->hw.max_frame_size = max_frame;
if (netif_running(netdev))
e1000_reinit_locked(adapter);
- adapter->hw.max_frame_size = max_frame;
-
return 0;
}
@@ -3573,6 +3726,11 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
adapter->net_stats.tx_window_errors = adapter->stats.latecol;
adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
+ if (adapter->hw.bad_tx_carr_stats_fd &&
+ adapter->link_duplex == FULL_DUPLEX) {
+ adapter->net_stats.tx_carrier_errors = 0;
+ adapter->stats.tncrs = 0;
+ }
/* Tx Dropped needs to be maintained elsewhere */
@@ -3590,6 +3748,13 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->phy_stats.receive_errors += phy_tmp;
}
+ /* Management Stats */
+ if (adapter->hw.has_smbus) {
+ adapter->stats.mgptc += E1000_READ_REG(hw, MGTPTC);
+ adapter->stats.mgprc += E1000_READ_REG(hw, MGTPRC);
+ adapter->stats.mgpdc += E1000_READ_REG(hw, MGTPDC);
+ }
+
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
#ifdef CONFIG_PCI_MSI
@@ -3868,11 +4033,11 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
cleaned = (i == eop);
if (cleaned) {
- /* this packet count is wrong for TSO but has a
- * tendency to make dynamic ITR change more
- * towards bulk */
+ struct sk_buff *skb = buffer_info->skb;
+ unsigned int segs = skb_shinfo(skb)->gso_segs;
+ total_tx_packets += segs;
total_tx_packets++;
- total_tx_bytes += buffer_info->skb->len;
+ total_tx_bytes += skb->len;
}
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->upper.data = 0;
@@ -4094,8 +4259,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
/* code added for copybreak, this should improve
* performance for small packets with large amounts
* of reassembly being done in the stack */
-#define E1000_CB_LENGTH 256
- if (length < E1000_CB_LENGTH) {
+ if (length < copybreak) {
struct sk_buff *new_skb =
netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
if (new_skb) {
@@ -4253,7 +4417,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
/* page alloc/put takes too long and effects small packet
* throughput, so unsplit small packets and save the alloc/put*/
- if (l1 && ((length + l1) <= adapter->rx_ps_bsize0)) {
+ if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) {
u8 *vaddr;
/* there is no documentation about how to call
* kmap_atomic, so we can't hold the mapping
@@ -4998,7 +5162,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t ctrl, ctrl_ext, rctl, manc, status;
+ uint32_t ctrl, ctrl_ext, rctl, status;
uint32_t wufc = adapter->wol;
#ifdef CONFIG_PM
int retval = 0;
@@ -5067,16 +5231,12 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
pci_enable_wake(pdev, PCI_D3cold, 0);
}
- if (adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.mac_type < e1000_82571 &&
- adapter->hw.media_type == e1000_media_type_copper) {
- manc = E1000_READ_REG(&adapter->hw, MANC);
- if (manc & E1000_MANC_SMBUS_EN) {
- manc |= E1000_MANC_ARP_EN;
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
- pci_enable_wake(pdev, PCI_D3hot, 1);
- pci_enable_wake(pdev, PCI_D3cold, 1);
- }
+ e1000_release_manageability(adapter);
+
+ /* make sure adapter isn't asleep if manageability is enabled */
+ if (adapter->en_mng_pt) {
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ pci_enable_wake(pdev, PCI_D3cold, 1);
}
if (adapter->hw.phy_type == e1000_phy_igp_3)
@@ -5102,7 +5262,7 @@ e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t manc, err;
+ uint32_t err;
pci_set_power_state(pdev, PCI_D0);
e1000_pci_restore_state(adapter);
@@ -5122,19 +5282,13 @@ e1000_resume(struct pci_dev *pdev)
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+ e1000_init_manageability(adapter);
+
if (netif_running(netdev))
e1000_up(adapter);
netif_device_attach(netdev);
- if (adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.mac_type < e1000_82571 &&
- adapter->hw.media_type == e1000_media_type_copper) {
- manc = E1000_READ_REG(&adapter->hw, MANC);
- manc &= ~(E1000_MANC_ARP_EN);
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
- }
-
/* If the controller is 82573 and f/w is AMT, do not set
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
@@ -5235,7 +5389,8 @@ static void e1000_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t manc, swsm;
+
+ e1000_init_manageability(adapter);
if (netif_running(netdev)) {
if (e1000_up(adapter)) {
@@ -5246,26 +5401,14 @@ static void e1000_io_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
- if (adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.mac_type < e1000_82571 &&
- adapter->hw.media_type == e1000_media_type_copper) {
- manc = E1000_READ_REG(&adapter->hw, MANC);
- manc &= ~(E1000_MANC_ARP_EN);
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
- }
-
- switch (adapter->hw.mac_type) {
- case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
- if (netif_running(netdev))
- mod_timer(&adapter->watchdog_timer, jiffies);
}
/* e1000_main.c */
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index cbfcd7f2889..cf2a279307e 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -487,7 +487,9 @@ e1000_check_options(struct e1000_adapter *adapter)
e1000_validate_option(&adapter->itr, &opt,
adapter);
/* save the setting, because the dynamic bits change itr */
- adapter->itr_setting = adapter->itr;
+ /* clear the lower two bits because they are
+ * used as control */
+ adapter->itr_setting = adapter->itr & ~3;
break;
}
} else {
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 39ad9f73d1e..272e1ec51aa 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0043"
+#define DRV_VERSION "EHEA_0045"
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 83fa32f7239..9de2d38a532 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -558,12 +558,12 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
u32 qp_token;
eqe = ehea_poll_eq(port->qp_eq);
- ehea_debug("eqe=%p", eqe);
+
while (eqe) {
- ehea_debug("*eqe=%lx", *(u64*)eqe);
- eqe = ehea_poll_eq(port->qp_eq);
qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
- ehea_debug("next eqe=%p", eqe);
+ ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
+ eqe->entry, qp_token);
+ eqe = ehea_poll_eq(port->qp_eq);
}
return IRQ_HANDLED;
@@ -575,8 +575,9 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
int i;
for (i = 0; i < adapter->num_ports; i++)
- if (adapter->port[i]->logical_port_id == logical_port)
- return adapter->port[i];
+ if (adapter->port[i])
+ if (adapter->port[i]->logical_port_id == logical_port)
+ return adapter->port[i];
return NULL;
}
@@ -642,6 +643,8 @@ int ehea_sense_port_attr(struct ehea_port *port)
break;
}
+ port->autoneg = 1;
+
/* Number of default QPs */
port->num_def_qps = cb0->num_default_qps;
@@ -728,10 +731,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
}
} else {
if (hret == H_AUTHORITY) {
- ehea_info("Hypervisor denied setting port speed. Either"
- " this partition is not authorized to set "
- "port speed or another partition has modified"
- " port speed first.");
+ ehea_info("Hypervisor denied setting port speed");
ret = -EPERM;
} else {
ret = -EIO;
@@ -998,7 +998,7 @@ static int ehea_configure_port(struct ehea_port *port)
| EHEA_BMASK_SET(PXLY_RC_JUMBO_FRAME, 1);
for (i = 0; i < port->num_def_qps; i++)
- cb0->default_qpn_arr[i] = port->port_res[i].qp->init_attr.qp_nr;
+ cb0->default_qpn_arr[i] = port->port_res[0].qp->init_attr.qp_nr;
if (netif_msg_ifup(port))
ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port");
@@ -1485,11 +1485,12 @@ out:
static void ehea_promiscuous_error(u64 hret, int enable)
{
- ehea_info("Hypervisor denied %sabling promiscuous mode.%s",
- enable == 1 ? "en" : "dis",
- hret != H_AUTHORITY ? "" : " Another partition owning a "
- "logical port on the same physical port might have altered "
- "promiscuous mode first.");
+ if (hret == H_AUTHORITY)
+ ehea_info("Hypervisor denied %sabling promiscuous mode",
+ enable == 1 ? "en" : "dis");
+ else
+ ehea_error("failed %sabling promiscuous mode",
+ enable == 1 ? "en" : "dis");
}
static void ehea_promiscuous(struct net_device *dev, int enable)
@@ -2267,6 +2268,8 @@ static void ehea_tx_watchdog(struct net_device *dev)
int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
{
struct hcp_query_ehea *cb;
+ struct device_node *lhea_dn = NULL;
+ struct device_node *eth_dn = NULL;
u64 hret;
int ret;
@@ -2283,7 +2286,18 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
goto out_herr;
}
- adapter->num_ports = cb->num_ports;
+ /* Determine the number of available logical ports
+ * by counting the child nodes of the lhea OFDT entry
+ */
+ adapter->num_ports = 0;
+ lhea_dn = of_find_node_by_name(lhea_dn, "lhea");
+ do {
+ eth_dn = of_get_next_child(lhea_dn, eth_dn);
+ if (eth_dn)
+ adapter->num_ports++;
+ } while ( eth_dn );
+ of_node_put(lhea_dn);
+
adapter->max_mc_mac = cb->max_mc_mac - 1;
ret = 0;
@@ -2302,6 +2316,7 @@ static int ehea_setup_single_port(struct ehea_port *port,
struct ehea_adapter *adapter = port->adapter;
struct hcp_ehea_port_cb4 *cb4;
u32 *dn_log_port_id;
+ int jumbo = 0;
sema_init(&port->port_lock, 1);
port->state = EHEA_PORT_DOWN;
@@ -2334,8 +2349,6 @@ static int ehea_setup_single_port(struct ehea_port *port,
INIT_LIST_HEAD(&port->mc_list->list);
- ehea_set_portspeed(port, EHEA_SPEED_AUTONEG);
-
ret = ehea_sense_port_attr(port);
if (ret)
goto out;
@@ -2345,13 +2358,25 @@ static int ehea_setup_single_port(struct ehea_port *port,
if (!cb4) {
ehea_error("no mem for cb4");
} else {
- cb4->jumbo_frame = 1;
- hret = ehea_h_modify_ehea_port(adapter->handle,
- port->logical_port_id,
- H_PORT_CB4, H_PORT_CB4_JUMBO,
- cb4);
- if (hret != H_SUCCESS) {
- ehea_info("Jumbo frames not activated");
+ hret = ehea_h_query_ehea_port(adapter->handle,
+ port->logical_port_id,
+ H_PORT_CB4,
+ H_PORT_CB4_JUMBO, cb4);
+
+ if (hret == H_SUCCESS) {
+ if (cb4->jumbo_frame)
+ jumbo = 1;
+ else {
+ cb4->jumbo_frame = 1;
+ hret = ehea_h_modify_ehea_port(adapter->handle,
+ port->
+ logical_port_id,
+ H_PORT_CB4,
+ H_PORT_CB4_JUMBO,
+ cb4);
+ if (hret == H_SUCCESS)
+ jumbo = 1;
+ }
}
kfree(cb4);
}
@@ -2390,6 +2415,9 @@ static int ehea_setup_single_port(struct ehea_port *port,
goto out_free;
}
+ ehea_info("%s: Jumbo frames are %sabled", dev->name,
+ jumbo == 1 ? "en" : "dis");
+
port->netdev = dev;
ret = 0;
goto out;
@@ -2471,14 +2499,16 @@ static int __devinit ehea_probe(struct ibmebus_dev *dev,
adapter_handle = (u64*)get_property(dev->ofdev.node, "ibm,hea-handle",
NULL);
- if (!adapter_handle) {
+ if (adapter_handle)
+ adapter->handle = *adapter_handle;
+
+ if (!adapter->handle) {
dev_err(&dev->ofdev.dev, "failed getting handle for adapter"
" '%s'\n", dev->ofdev.node->full_name);
ret = -ENODEV;
goto out_free_ad;
}
- adapter->handle = *adapter_handle;
adapter->pd = EHEA_PD_ID;
dev->ofdev.dev.driver_data = adapter;
@@ -2568,6 +2598,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
destroy_workqueue(adapter->ehea_wq);
ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
+ tasklet_kill(&adapter->neq_tasklet);
ehea_destroy_eq(adapter->neq);
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 0cfc2bc1a27..37716e05e80 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -94,6 +94,7 @@ static long ehea_plpar_hcall9(unsigned long opcode,
{
long ret;
int i, sleep_msecs;
+ u8 cb_cat;
for (i = 0; i < 5; i++) {
ret = plpar_hcall9(opcode, outs,
@@ -106,7 +107,13 @@ static long ehea_plpar_hcall9(unsigned long opcode,
continue;
}
- if (ret < H_SUCCESS)
+ cb_cat = EHEA_BMASK_GET(H_MEHEAPORT_CAT, arg2);
+
+ if ((ret < H_SUCCESS) && !(((ret == H_AUTHORITY)
+ && (opcode == H_MODIFY_HEA_PORT))
+ && (((cb_cat == H_PORT_CB4) && ((arg3 == H_PORT_CB4_JUMBO)
+ || (arg3 == H_PORT_CB4_SPEED))) || ((cb_cat == H_PORT_CB7)
+ && (arg3 == H_PORT_CB7_DUCQPN)))))
ehea_error("opcode=%lx ret=%lx"
" arg1=%lx arg2=%lx arg3=%lx arg4=%lx"
" arg5=%lx arg6=%lx arg7=%lx arg8=%lx"
@@ -120,7 +127,6 @@ static long ehea_plpar_hcall9(unsigned long opcode,
outs[0], outs[1], outs[2], outs[3],
outs[4], outs[5], outs[6], outs[7],
outs[8]);
-
return ret;
}
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 439f4133829..93f2b7a2216 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -3,8 +3,7 @@
*
* Note: This driver is a cleanroom reimplementation based on reverse
* engineered documentation written by Carl-Daniel Hailfinger
- * and Andrew de Quincey. It's neither supported nor endorsed
- * by NVIDIA Corp. Use at your own risk.
+ * and Andrew de Quincey.
*
* NVIDIA, nForce and other NVIDIA marks are trademarks or registered
* trademarks of NVIDIA Corporation in the United States and other
@@ -14,7 +13,7 @@
* Copyright (C) 2004 Andrew de Quincey (wol support)
* Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
* IRQ rate fixes, bigendian fixes, cleanups, verification)
- * Copyright (c) 2004 NVIDIA Corporation
+ * Copyright (c) 2004,5,6 NVIDIA 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
@@ -235,6 +234,7 @@ enum {
#define NVREG_XMITCTL_HOST_SEMA_MASK 0x0000f000
#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
#define NVREG_XMITCTL_HOST_LOADED 0x00004000
+#define NVREG_XMITCTL_TX_PATH_EN 0x01000000
NvRegTransmitterStatus = 0x088,
#define NVREG_XMITSTAT_BUSY 0x01
@@ -250,6 +250,7 @@ enum {
#define NVREG_OFFLOAD_NORMAL RX_NIC_BUFSIZE
NvRegReceiverControl = 0x094,
#define NVREG_RCVCTL_START 0x01
+#define NVREG_RCVCTL_RX_PATH_EN 0x01000000
NvRegReceiverStatus = 0x98,
#define NVREG_RCVSTAT_BUSY 0x01
@@ -1170,16 +1171,21 @@ static void nv_start_rx(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
+ u32 rx_ctrl = readl(base + NvRegReceiverControl);
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
/* Already running? Stop it. */
- if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
- writel(0, base + NvRegReceiverControl);
+ if ((readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) && !np->mac_in_use) {
+ rx_ctrl &= ~NVREG_RCVCTL_START;
+ writel(rx_ctrl, base + NvRegReceiverControl);
pci_push(base);
}
writel(np->linkspeed, base + NvRegLinkSpeed);
pci_push(base);
- writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
+ rx_ctrl |= NVREG_RCVCTL_START;
+ if (np->mac_in_use)
+ rx_ctrl &= ~NVREG_RCVCTL_RX_PATH_EN;
+ writel(rx_ctrl, base + NvRegReceiverControl);
dprintk(KERN_DEBUG "%s: nv_start_rx to duplex %d, speed 0x%08x.\n",
dev->name, np->duplex, np->linkspeed);
pci_push(base);
@@ -1187,39 +1193,59 @@ static void nv_start_rx(struct net_device *dev)
static void nv_stop_rx(struct net_device *dev)
{
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
+ u32 rx_ctrl = readl(base + NvRegReceiverControl);
dprintk(KERN_DEBUG "%s: nv_stop_rx\n", dev->name);
- writel(0, base + NvRegReceiverControl);
+ if (!np->mac_in_use)
+ rx_ctrl &= ~NVREG_RCVCTL_START;
+ else
+ rx_ctrl |= NVREG_RCVCTL_RX_PATH_EN;
+ writel(rx_ctrl, base + NvRegReceiverControl);
reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
KERN_INFO "nv_stop_rx: ReceiverStatus remained busy");
udelay(NV_RXSTOP_DELAY2);
- writel(0, base + NvRegLinkSpeed);
+ if (!np->mac_in_use)
+ writel(0, base + NvRegLinkSpeed);
}
static void nv_start_tx(struct net_device *dev)
{
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
+ u32 tx_ctrl = readl(base + NvRegTransmitterControl);
dprintk(KERN_DEBUG "%s: nv_start_tx\n", dev->name);
- writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl);
+ tx_ctrl |= NVREG_XMITCTL_START;
+ if (np->mac_in_use)
+ tx_ctrl &= ~NVREG_XMITCTL_TX_PATH_EN;
+ writel(tx_ctrl, base + NvRegTransmitterControl);
pci_push(base);
}
static void nv_stop_tx(struct net_device *dev)
{
+ struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
+ u32 tx_ctrl = readl(base + NvRegTransmitterControl);
dprintk(KERN_DEBUG "%s: nv_stop_tx\n", dev->name);
- writel(0, base + NvRegTransmitterControl);
+ if (!np->mac_in_use)
+ tx_ctrl &= ~NVREG_XMITCTL_START;
+ else
+ tx_ctrl |= NVREG_XMITCTL_TX_PATH_EN;
+ writel(tx_ctrl, base + NvRegTransmitterControl);
reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
KERN_INFO "nv_stop_tx: TransmitterStatus remained busy");
udelay(NV_TXSTOP_DELAY2);
- writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
+ if (!np->mac_in_use)
+ writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+ base + NvRegTransmitPoll);
}
static void nv_txrx_reset(struct net_device *dev)
@@ -2576,14 +2602,15 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
int pkts, limit = min(*budget, dev->quota);
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
+ unsigned long flags;
pkts = nv_rx_process(dev, limit);
if (nv_alloc_rx(dev)) {
- spin_lock_irq(&np->lock);
+ spin_lock_irqsave(&np->lock, flags);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock_irq(&np->lock);
+ spin_unlock_irqrestore(&np->lock, flags);
}
if (pkts < limit) {
@@ -2591,13 +2618,15 @@ static int nv_napi_poll(struct net_device *dev, int *budget)
netif_rx_complete(dev);
/* re-enable receive interrupts */
- spin_lock_irq(&np->lock);
+ spin_lock_irqsave(&np->lock, flags);
+
np->irqmask |= NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
else
writel(np->irqmask, base + NvRegIrqMask);
- spin_unlock_irq(&np->lock);
+
+ spin_unlock_irqrestore(&np->lock, flags);
return 0;
} else {
/* used up our quantum, so reschedule */
@@ -4146,20 +4175,6 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
return 0;
}
-/* Indicate to mgmt unit whether driver is loaded or not */
-static void nv_mgmt_driver_loaded(struct net_device *dev, int loaded)
-{
- u8 __iomem *base = get_hwbase(dev);
- u32 tx_ctrl;
-
- tx_ctrl = readl(base + NvRegTransmitterControl);
- if (loaded)
- tx_ctrl |= NVREG_XMITCTL_HOST_LOADED;
- else
- tx_ctrl &= ~NVREG_XMITCTL_HOST_LOADED;
- writel(tx_ctrl, base + NvRegTransmitterControl);
-}
-
static int nv_open(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -4657,33 +4672,24 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
if (id->driver_data & DEV_HAS_MGMT_UNIT) {
- writel(0x1, base + 0x204); pci_push(base);
- msleep(500);
/* management unit running on the mac? */
- np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
- if (np->mac_in_use) {
- u32 mgmt_sync;
- /* management unit setup the phy already? */
- mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK;
- if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) {
- if (!nv_mgmt_acquire_sema(dev)) {
- for (i = 0; i < 5000; i++) {
- msleep(1);
- mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK;
- if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY)
- continue;
- if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT)
- phyinitialized = 1;
- break;
+ if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) {
+ np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
+ dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use);
+ for (i = 0; i < 5000; i++) {
+ msleep(1);
+ if (nv_mgmt_acquire_sema(dev)) {
+ /* management unit setup the phy already? */
+ if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
+ NVREG_XMITCTL_SYNC_PHY_INIT) {
+ /* phy is inited by mgmt unit */
+ phyinitialized = 1;
+ dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
+ } else {
+ /* we need to init the phy */
}
- } else {
- /* we need to init the phy */
+ break;
}
- } else if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) {
- /* phy is inited by SMU */
- phyinitialized = 1;
- } else {
- /* we need to init the phy */
}
}
}
@@ -4722,10 +4728,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (!phyinitialized) {
/* reset it */
phy_init(dev);
- }
-
- if (id->driver_data & DEV_HAS_MGMT_UNIT) {
- nv_mgmt_driver_loaded(dev, 1);
+ } else {
+ /* see if it is a gigabit phy */
+ u32 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+ if (mii_status & PHY_GIGABIT) {
+ np->gigabit = PHY_GIGABIT;
+ }
}
/* set default link speed settings */
@@ -4747,8 +4755,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
out_error:
if (phystate_orig)
writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
- if (np->mac_in_use)
- nv_mgmt_driver_loaded(dev, 0);
pci_set_drvdata(pci_dev, NULL);
out_freering:
free_rings(dev);
@@ -4778,9 +4784,6 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
writel(np->orig_mac[0], base + NvRegMacAddrA);
writel(np->orig_mac[1], base + NvRegMacAddrB);
- if (np->mac_in_use)
- nv_mgmt_driver_loaded(dev, 0);
-
/* free all structures */
free_rings(dev);
iounmap(get_hwbase(dev));
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index c2c5fd419bd..ff683947730 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -104,9 +104,9 @@ static int do_pd_setup(struct fs_enet_private *fep)
fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
if (fep->interrupt < 0)
return -EINVAL;
-
+
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- fep->fec.fecp =(void*)r->start;
+ fep->fec.fecp = ioremap(r->start, r->end - r->start + 1);
if(fep->fec.fecp == NULL)
return -EINVAL;
@@ -319,11 +319,14 @@ static void restart(struct net_device *dev)
* Clear any outstanding interrupt.
*/
FW(fecp, ievent, 0xffc0);
+#ifndef CONFIG_PPC_MERGE
FW(fecp, ivec, (fep->interrupt / 2) << 29);
-
+#else
+ FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
+#endif
/*
- * adjust to speed (only for DUET & RMII)
+ * adjust to speed (only for DUET & RMII)
*/
#ifdef CONFIG_DUET
if (fpi->use_rmii) {
@@ -418,6 +421,7 @@ static void stop(struct net_device *dev)
static void pre_request_irq(struct net_device *dev, int irq)
{
+#ifndef CONFIG_PPC_MERGE
immap_t *immap = fs_enet_immap;
u32 siel;
@@ -431,6 +435,7 @@ static void pre_request_irq(struct net_device *dev, int irq)
siel &= ~(0x80000000 >> (irq & ~1));
out_be32(&immap->im_siu_conf.sc_siel, siel);
}
+#endif
}
static void post_free_irq(struct net_device *dev, int irq)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 95ec5872c50..afd7fca7c6c 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -121,13 +121,13 @@ static int do_pd_setup(struct fs_enet_private *fep)
return -EINVAL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- fep->scc.sccp = (void *)r->start;
+ fep->scc.sccp = ioremap(r->start, r->end - r->start + 1);
if (fep->scc.sccp == NULL)
return -EINVAL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
- fep->scc.ep = (void *)r->start;
+ fep->scc.ep = ioremap(r->start, r->end - r->start + 1);
if (fep->scc.ep == NULL)
return -EINVAL;
@@ -397,6 +397,7 @@ static void stop(struct net_device *dev)
static void pre_request_irq(struct net_device *dev, int irq)
{
+#ifndef CONFIG_PPC_MERGE
immap_t *immap = fs_enet_immap;
u32 siel;
@@ -410,6 +411,7 @@ static void pre_request_irq(struct net_device *dev, int irq)
siel &= ~(0x80000000 >> (irq & ~1));
out_be32(&immap->im_siu_conf.sc_siel, siel);
}
+#endif
}
static void post_free_irq(struct net_device *dev, int irq)
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 92420f007b9..760d04a671f 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -325,11 +325,6 @@ static int sp_rebuild_header(struct sk_buff *skb)
static void sp_setup(struct net_device *dev)
{
- static char ax25_bcast[AX25_ADDR_LEN] =
- {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
- static char ax25_test[AX25_ADDR_LEN] =
- {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
/* Finish setting up the DEVICE info. */
dev->mtu = SIXP_MTU;
dev->hard_start_xmit = sp_xmit;
@@ -347,8 +342,8 @@ static void sp_setup(struct net_device *dev)
dev->tx_timeout = NULL;
/* Only activated in AX.25 mode */
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
SET_MODULE_OWNER(dev);
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 896aa02000d..feb0ada7a02 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -113,7 +113,7 @@ config SCC_TRXECHO
config BAYCOM_SER_FDX
tristate "BAYCOM ser12 fullduplex driver for AX.25"
- depends on AX25
+ depends on AX25 && !S390
select CRC_CCITT
---help---
This is one of two drivers for Baycom style simple amateur radio
@@ -133,7 +133,7 @@ config BAYCOM_SER_FDX
config BAYCOM_SER_HDX
tristate "BAYCOM ser12 halfduplex driver for AX.25"
- depends on AX25
+ depends on AX25 && !S390
select CRC_CCITT
---help---
This is one of two drivers for Baycom style simple amateur radio
@@ -181,7 +181,7 @@ config BAYCOM_EPP
config YAM
tristate "YAM driver for AX.25"
- depends on AX25
+ depends on AX25 && !S390
help
The YAM is a modem for packet radio which connects to the serial
port and includes some of the functions of a Terminal Node
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 3c33d6f6a6a..153b6dc80af 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -1141,12 +1141,6 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
*/
static void baycom_probe(struct net_device *dev)
{
- static char ax25_bcast[AX25_ADDR_LEN] = {
- 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1
- };
- static char ax25_nocall[AX25_ADDR_LEN] = {
- 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1
- };
const struct hdlcdrv_channel_params dflt_ch_params = {
20, 2, 10, 40, 0
};
@@ -1182,8 +1176,8 @@ static void baycom_probe(struct net_device *dev)
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN);
dev->tx_queue_len = 16;
/* New style flags */
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 889f338132f..5b788d84011 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -88,11 +88,6 @@
static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n";
-static unsigned char ax25_bcast[AX25_ADDR_LEN] =
- {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static unsigned char ax25_defaddr[AX25_ADDR_LEN] =
- {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static char bpq_eth_addr[6];
@@ -487,8 +482,8 @@ static void bpq_setup(struct net_device *dev)
dev->do_ioctl = bpq_ioctl;
dev->destructor = free_netdev;
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_defaddr, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
dev->flags = 0;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index e6e721aff6f..0fbb414b5a4 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -264,12 +264,6 @@ 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 };
-static char ax25_test[7] __initdata =
- { 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1,
-'1' << 1 };
/* Global variables */
@@ -443,8 +437,8 @@ static void __init dev_setup(struct net_device *dev)
dev->mtu = 1500;
dev->addr_len = AX25_ADDR_LEN;
dev->tx_queue_len = 64;
- memcpy(dev->broadcast, ax25_broadcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
}
static int __init setup_adapter(int card_base, int type, int n)
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index dacc7687b97..452873e7c68 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -63,18 +63,6 @@
/* --------------------------------------------------------------------- */
-/*
- * The name of the card. Is used for messages and in the requests for
- * io regions, irqs and dma channels
- */
-
-static char ax25_bcast[AX25_ADDR_LEN] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_nocall[AX25_ADDR_LEN] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
-/* --------------------------------------------------------------------- */
-
#define KISS_VERBOSE
/* --------------------------------------------------------------------- */
@@ -709,8 +697,8 @@ static void hdlcdrv_setup(struct net_device *dev)
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
dev->tx_queue_len = 16;
}
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d8715b200c1..d08fbc39664 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -672,11 +672,6 @@ static struct net_device_stats *ax_get_stats(struct net_device *dev)
static void ax_setup(struct net_device *dev)
{
- static char ax25_bcast[AX25_ADDR_LEN] =
- {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
- static char ax25_test[AX25_ADDR_LEN] =
- {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
-
/* Finish setting up the DEVICE info. */
dev->mtu = AX_MTU;
dev->hard_start_xmit = ax_xmit;
@@ -691,8 +686,8 @@ static void ax_setup(struct net_device *dev)
dev->hard_header = ax_header;
dev->rebuild_header = ax_rebuild_header;
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
}
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index ec9b6d9b6f0..2ce047e9d26 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1540,11 +1540,6 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc)
/* * Network driver methods * */
/* ******************************************************************** */
-static unsigned char ax25_bcast[AX25_ADDR_LEN] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static unsigned char ax25_nocall[AX25_ADDR_LEN] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
/* ----> Initialize device <----- */
static void scc_net_setup(struct net_device *dev)
@@ -1562,8 +1557,8 @@ static void scc_net_setup(struct net_device *dev)
dev->do_ioctl = scc_net_ioctl;
dev->tx_timeout = NULL;
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
dev->flags = 0;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 3c4455bd466..6d74f08720d 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -156,11 +156,6 @@ static struct net_device *yam_devs[NR_PORTS];
static struct yam_mcs *yam_data;
-static char ax25_bcast[7] =
-{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
-static char ax25_test[7] =
-{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
-
static DEFINE_TIMER(yam_timer, NULL, 0, 0);
/* --------------------------------------------------------------------- */
@@ -1115,8 +1110,8 @@ static void yam_setup(struct net_device *dev)
dev->hard_header_len = AX25_MAX_HEADER_LEN;
dev->mtu = AX25_MTU;
dev->addr_len = AX25_ADDR_LEN;
- memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
}
static int __init yam_init_driver(void)
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c
index 9c643f2a8d5..c991cb82ff2 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/hplance.c
@@ -77,6 +77,7 @@ static int __devinit hplance_init_one(struct dio_dev *d,
{
struct net_device *dev;
int err = -ENOMEM;
+ int i;
dev = alloc_etherdev(sizeof(struct hplance_private));
if (!dev)
@@ -93,6 +94,15 @@ static int __devinit hplance_init_one(struct dio_dev *d,
goto out_release_mem_region;
dio_set_drvdata(d, dev);
+
+ printk(KERN_INFO "%s: %s; select code %d, addr %2.2x", dev->name, d->name, d->scode, dev->dev_addr[0]);
+
+ for (i=1; i<6; i++) {
+ printk(":%2.2x", dev->dev_addr[i]);
+ }
+
+ printk(", irq %d\n", d->ipl);
+
return 0;
out_release_mem_region:
@@ -119,8 +129,6 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
struct hplance_private *lp;
int i;
- printk(KERN_INFO "%s: %s; select code %d, addr", dev->name, d->name, d->scode);
-
/* reset the board */
out_8(va+DIO_IDOFF, 0xff);
udelay(100); /* ariba! ariba! udelay! udelay! */
@@ -143,7 +151,6 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
*/
dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
| (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
- printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]);
}
lp = netdev_priv(dev);
@@ -160,7 +167,6 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
- printk(", irq %d\n", lp->lance.irq);
}
/* This is disgusting. We have to check the DIO status register for ack every
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c
index 4a97024061e..9074f76ee2b 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.c
+++ b/drivers/net/ibm_emac/ibm_emac_phy.c
@@ -309,7 +309,7 @@ int mii_phy_probe(struct mii_phy *phy, int address)
{
struct mii_phy_def *def;
int i;
- u32 id;
+ int id;
phy->autoneg = AUTONEG_DISABLE;
phy->advertising = 0;
@@ -324,6 +324,8 @@ int mii_phy_probe(struct mii_phy *phy, int address)
/* Read ID and find matching entry */
id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2);
+ if (id < 0)
+ return -ENODEV;
for (i = 0; (def = mii_phy_table[i]) != NULL; i++)
if ((id & def->phy_id_mask) == def->phy_id)
break;
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index c26a4b8e552..ca2b21f9d44 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -154,8 +154,8 @@ static int ifb_xmit(struct sk_buff *skb, struct net_device *dev)
int ret = 0;
u32 from = G_TC_FROM(skb->tc_verd);
- stats->tx_packets++;
- stats->tx_bytes+=skb->len;
+ stats->rx_packets++;
+ stats->rx_bytes+=skb->len;
if (!from || !skb->input_dev) {
dropped:
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 16620bd97fb..11af0ae7510 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1603,7 +1603,7 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
irda_qos_bits_to_value (&self->qos);
/* Allocate twice the size to guarantee alignment */
- self->ringbuf = (void *) kmalloc (OBOE_RING_LEN << 1, GFP_KERNEL);
+ self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL);
if (!self->ringbuf)
{
printk (KERN_ERR DRIVER_NAME ": can't allocate DMA buffers\n");
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6e95645e724..340ee99652e 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -441,25 +441,13 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
goto drop;
}
- /* Make sure there is room for IrDA-USB header. The actual
- * allocation will be done lower in skb_push().
- * Also, we don't use directly skb_cow(), because it require
- * headroom >= 16, which force unnecessary copies - Jean II */
- if (skb_headroom(skb) < self->header_length) {
- IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
- if (skb_cow(skb, self->header_length)) {
- IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
- goto drop;
- }
- }
+ memcpy(self->tx_buff + self->header_length, skb->data, skb->len);
/* Change setting for next frame */
-
if (self->capability & IUC_STIR421X) {
__u8 turnaround_time;
- __u8* frame;
+ __u8* frame = self->tx_buff;
turnaround_time = get_turnaround_time( skb );
- frame= skb_push(skb, self->header_length);
irda_usb_build_header(self, frame, 0);
frame[2] = turnaround_time;
if ((skb->len != 0) &&
@@ -472,17 +460,17 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
frame[1] = 0;
}
} else {
- irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
+ irda_usb_build_header(self, self->tx_buff, 0);
}
/* FIXME: Make macro out of this one */
((struct irda_skb_cb *)skb->cb)->context = self;
- usb_fill_bulk_urb(urb, self->usbdev,
+ usb_fill_bulk_urb(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
- skb->data, IRDA_SKB_MAX_MTU,
+ self->tx_buff, skb->len + self->header_length,
write_bulk_callback, skb);
- urb->transfer_buffer_length = skb->len;
+
/* This flag (URB_ZERO_PACKET) indicates that what we send is not
* a continuous stream of data but separate packets.
* In this case, the USB layer will insert an empty USB frame (TD)
@@ -1455,6 +1443,9 @@ static inline void irda_usb_close(struct irda_usb_cb *self)
/* Remove the speed buffer */
kfree(self->speed_buff);
self->speed_buff = NULL;
+
+ kfree(self->tx_buff);
+ self->tx_buff = NULL;
}
/********************** USB CONFIG SUBROUTINES **********************/
@@ -1524,8 +1515,6 @@ 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 */
- IRDA_ASSERT(self->bulk_out_mtu == 64, ;);
return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0));
}
@@ -1747,15 +1736,20 @@ static int irda_usb_probe(struct usb_interface *intf,
/* Don't change this buffer size and allocation without doing
* some heavy and complete testing. Don't ask why :-(
* Jean II */
- self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
+ self->speed_buff = kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
if (self->speed_buff == NULL)
goto err_out_3;
memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
+ self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length,
+ GFP_KERNEL);
+ if (self->tx_buff == NULL)
+ goto err_out_4;
+
ret = irda_usb_open(self);
if (ret)
- goto err_out_4;
+ goto err_out_5;
IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self);
@@ -1766,14 +1760,14 @@ static int irda_usb_probe(struct usb_interface *intf,
self->needspatch = (ret < 0);
if (self->needspatch) {
IRDA_ERROR("STIR421X: Couldn't upload patch\n");
- goto err_out_5;
+ goto err_out_6;
}
/* replace IrDA class descriptor with what patched device is now reporting */
irda_desc = irda_usb_find_class_desc (self->usbintf);
if (irda_desc == NULL) {
ret = -ENODEV;
- goto err_out_5;
+ goto err_out_6;
}
if (self->irda_desc)
kfree (self->irda_desc);
@@ -1782,9 +1776,10 @@ static int irda_usb_probe(struct usb_interface *intf,
}
return 0;
-
-err_out_5:
+err_out_6:
unregister_netdev(self->netdev);
+err_out_5:
+ kfree(self->tx_buff);
err_out_4:
kfree(self->speed_buff);
err_out_3:
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index 6b2271f18e7..e846c38224a 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -156,6 +156,7 @@ struct irda_usb_cb {
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos;
char *speed_buff; /* Buffer for speed changes */
+ char *tx_buff;
struct timeval stamp;
struct timeval now;
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 654a68b490a..3098960dc2a 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -164,7 +164,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
/* Allocate memory if needed */
if (self->tx_buff.truesize > 0) {
- self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ self->tx_buff.head = kmalloc(self->tx_buff.truesize,
GFP_KERNEL);
if (self->tx_buff.head == NULL) {
IRDA_ERROR("%s(), can't allocate memory for "
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 6a98b7ae497..ad1857364d5 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -117,7 +117,7 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
{
struct sirtty_cb *priv = dev->priv;
struct tty_struct *tty;
- struct termios old_termios;
+ struct ktermios old_termios;
int cflag;
IRDA_ASSERT(priv != NULL, return -1;);
@@ -318,7 +318,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
{
- struct termios old_termios;
+ struct ktermios old_termios;
int cflag;
lock_kernel();
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index c14a74634fd..20d306fea4c 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -59,7 +59,7 @@
#include <asm/byteorder.h>
#include <asm/unaligned.h>
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 18c68193bf1..e2b1af61845 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -166,7 +166,7 @@ static void vlsi_proc_pdev(struct seq_file *seq, struct pci_dev *pdev)
unsigned i;
seq_printf(seq, "\n%s (vid/did: %04x/%04x)\n",
- PCIDEV_NAME(pdev), (int)pdev->vendor, (int)pdev->device);
+ pci_name(pdev), (int)pdev->vendor, (int)pdev->device);
seq_printf(seq, "pci-power-state: %u\n", (unsigned) pdev->current_state);
seq_printf(seq, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n",
pdev->irq, (unsigned)pci_resource_start(pdev, 0), (unsigned long long)pdev->dma_mask);
@@ -1401,7 +1401,7 @@ static void vlsi_tx_timeout(struct net_device *ndev)
if (vlsi_start_hw(idev))
IRDA_ERROR("%s: failed to restart hw - %s(%s) unusable!\n",
- __FUNCTION__, PCIDEV_NAME(idev->pdev), ndev->name);
+ __FUNCTION__, pci_name(idev->pdev), ndev->name);
else
netif_start_queue(ndev);
}
@@ -1643,7 +1643,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->current_state = 0; /* hw must be running now */
IRDA_MESSAGE("%s: IrDA PCI controller %s detected\n",
- drivername, PCIDEV_NAME(pdev));
+ drivername, pci_name(pdev));
if ( !pci_resource_start(pdev,0)
|| !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) {
@@ -1728,7 +1728,7 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
- IRDA_MESSAGE("%s: %s removed\n", drivername, PCIDEV_NAME(pdev));
+ IRDA_MESSAGE("%s: %s removed\n", drivername, pci_name(pdev));
}
#ifdef CONFIG_PM
@@ -1748,7 +1748,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
if (!ndev) {
IRDA_ERROR("%s - %s: no netdevice \n",
- __FUNCTION__, PCIDEV_NAME(pdev));
+ __FUNCTION__, pci_name(pdev));
return 0;
}
idev = ndev->priv;
@@ -1759,7 +1759,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
pdev->current_state = state.event;
}
else
- IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state.event);
+ IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event);
up(&idev->sem);
return 0;
}
@@ -1787,7 +1787,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
if (!ndev) {
IRDA_ERROR("%s - %s: no netdevice \n",
- __FUNCTION__, PCIDEV_NAME(pdev));
+ __FUNCTION__, pci_name(pdev));
return 0;
}
idev = ndev->priv;
@@ -1795,7 +1795,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
if (pdev->current_state == 0) {
up(&idev->sem);
IRDA_WARNING("%s - %s: already resumed\n",
- __FUNCTION__, PCIDEV_NAME(pdev));
+ __FUNCTION__, pci_name(pdev));
return 0;
}
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index c37f0bc4c7f..2d3b773d8e3 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -41,39 +41,6 @@
#define PCI_CLASS_SUBCLASS_MASK 0xffff
#endif
-/* in recent 2.5 interrupt handlers have non-void return value */
-#ifndef IRQ_RETVAL
-typedef void irqreturn_t;
-#define IRQ_NONE
-#define IRQ_HANDLED
-#define IRQ_RETVAL(x)
-#endif
-
-/* some stuff need to check kernelversion. Not all 2.5 stuff was present
- * in early 2.5.x - the test is merely to separate 2.4 from 2.5
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-/* PDE() introduced in 2.5.4 */
-#ifdef CONFIG_PROC_FS
-#define PDE(inode) ((inode)->i_private)
-#endif
-
-/* irda crc16 calculation exported in 2.5.42 */
-#define irda_calc_crc16(fcs,buf,len) (GOOD_FCS)
-
-/* we use this for unified pci device name access */
-#define PCIDEV_NAME(pdev) ((pdev)->name)
-
-#else /* 2.5 or later */
-
-/* whatever we get from the associated struct device - bus:slot:dev.fn id */
-#define PCIDEV_NAME(pdev) (pci_name(pdev))
-
-#endif
-
/* ================================================================ */
/* non-standard PCI registers */
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index d6f4f185bf3..2194b567239 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -73,7 +73,7 @@
#include <asm/abs_addr.h>
#include <asm/iseries/mf.h>
#include <asm/uaccess.h>
-
+#include <asm/firmware.h>
#include <asm/iseries/hv_lp_config.h>
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_event.h>
@@ -1668,7 +1668,7 @@ static struct vio_driver veth_driver = {
* Module initialization/cleanup
*/
-void __exit veth_module_cleanup(void)
+static void __exit veth_module_cleanup(void)
{
int i;
struct veth_lpar_connection *cnx;
@@ -1697,11 +1697,14 @@ void __exit veth_module_cleanup(void)
}
module_exit(veth_module_cleanup);
-int __init veth_module_init(void)
+static int __init veth_module_init(void)
{
int i;
int rc;
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
this_lp = HvLpConfig_getLpIndex_outline();
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 50ffe90488f..f4aba4355b1 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -171,6 +171,7 @@ struct ixgb_adapter {
/* TX */
struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
+ unsigned int restart_queue;
unsigned long timeo_start;
uint32_t tx_cmd_type;
uint64_t hw_csum_tx_good;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index cd22523fb03..82c044d6e08 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -79,6 +79,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
{"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
{"tx_deferred_ok", IXGB_STAT(stats.dc)},
{"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
+ {"tx_restart_queue", IXGB_STAT(restart_queue) },
{"rx_long_length_errors", IXGB_STAT(stats.roc)},
{"rx_short_length_errors", IXGB_STAT(stats.ruc)},
#ifdef NETIF_F_TSO
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index 02089b64e42..ecbf45861c6 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -399,8 +399,9 @@ ixgb_init_rx_addrs(struct ixgb_hw *hw)
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
for(i = 1; i < IXGB_RAR_ENTRIES; i++) {
- IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+ /* Write high reg first to disable the AV bit first */
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+ IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
}
return;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index e628126c9c4..a083a918923 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -36,7 +36,7 @@ static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "1.0.117-k2"DRIVERNAPI
+#define DRV_VERSION "1.0.126-k2"DRIVERNAPI
char ixgb_driver_version[] = DRV_VERSION;
static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -1287,6 +1287,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
struct ixgb_buffer *buffer_info;
int len = skb->len;
unsigned int offset = 0, size, count = 0, i;
+ unsigned int mss = skb_shinfo(skb)->gso_size;
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
unsigned int f;
@@ -1298,6 +1299,11 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, IXGB_MAX_DATA_PER_TXD);
+ /* Workaround for premature desc write-backs
+ * in TSO mode. Append 4-byte sentinel desc */
+ if (unlikely(mss && !nr_frags && size == len && size > 8))
+ size -= 4;
+
buffer_info->length = size;
WARN_ON(buffer_info->dma != 0);
buffer_info->dma =
@@ -1324,6 +1330,13 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, IXGB_MAX_DATA_PER_TXD);
+
+ /* Workaround for premature desc write-backs
+ * in TSO mode. Append 4-byte sentinel desc */
+ if (unlikely(mss && !nr_frags && size == len
+ && size > 8))
+ size -= 4;
+
buffer_info->length = size;
buffer_info->dma =
pci_map_page(adapter->pdev,
@@ -1398,11 +1411,43 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
IXGB_WRITE_REG(&adapter->hw, TDT, i);
}
+static int __ixgb_maybe_stop_tx(struct net_device *netdev, int size)
+{
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+
+ netif_stop_queue(netdev);
+ /* Herbert's original patch had:
+ * smp_mb__after_netif_stop_queue();
+ * but since that doesn't exist yet, just open code it. */
+ smp_mb();
+
+ /* We need to check again in a case another CPU has just
+ * made room available. */
+ if (likely(IXGB_DESC_UNUSED(tx_ring) < size))
+ return -EBUSY;
+
+ /* A reprieve! */
+ netif_start_queue(netdev);
+ ++adapter->restart_queue;
+ return 0;
+}
+
+static int ixgb_maybe_stop_tx(struct net_device *netdev,
+ struct ixgb_desc_ring *tx_ring, int size)
+{
+ if (likely(IXGB_DESC_UNUSED(tx_ring) >= size))
+ return 0;
+ return __ixgb_maybe_stop_tx(netdev, size);
+}
+
+
/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \
(((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
- MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
+#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) /* skb->date */ + \
+ MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 /* for context */ \
+ + 1 /* one more needed for sentinel TSO workaround */
static int
ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1430,7 +1475,8 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
spin_lock_irqsave(&adapter->tx_lock, flags);
#endif
- if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+ if (unlikely(ixgb_maybe_stop_tx(netdev, &adapter->tx_ring,
+ DESC_NEEDED))) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_BUSY;
@@ -1468,8 +1514,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
#ifdef NETIF_F_LLTX
/* Make sure there is space in the ring for the next send. */
- if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED))
- netif_stop_queue(netdev);
+ ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 82c10dec1b5..2b739fd584f 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -229,9 +229,11 @@ struct net_device loopback_dev = {
};
/* Setup and register the loopback device. */
-int __init loopback_init(void)
+static int __init loopback_init(void)
{
return register_netdev(&loopback_dev);
};
+module_init(loopback_init);
+
EXPORT_SYMBOL(loopback_dev);
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index b833016f182..177c502f738 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -884,7 +884,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
dev->trans_start = jiffies;
- tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
+ tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
if (tx_cmd == NULL) {
printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
lp->stats.tx_dropped++;
@@ -1266,7 +1266,7 @@ static void set_multicast_list(struct net_device *dev) {
if (dev->mc_count > 0) {
struct dev_mc_list *dmi;
char *cp;
- cmd = (struct i596_cmd *)kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
+ cmd = kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
if (cmd == NULL) {
printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name);
return;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index bd0ce98c939..25b559b5d5e 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -264,12 +264,12 @@ static void macb_update_stats(struct macb *bp)
WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
for(; p < end; p++, reg++)
- *p += readl(reg);
+ *p += __raw_readl(reg);
}
-static void macb_periodic_task(void *arg)
+static void macb_periodic_task(struct work_struct *work)
{
- struct macb *bp = arg;
+ struct macb *bp = container_of(work, struct macb, periodic_task.work);
macb_update_stats(bp);
macb_check_media(bp, 1, 0);
@@ -1088,7 +1088,7 @@ static int __devinit macb_probe(struct platform_device *pdev)
dev->base_addr = regs->start;
- INIT_WORK(&bp->periodic_task, macb_periodic_task, bp);
+ INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
mutex_init(&bp->mdio_mutex);
init_completion(&bp->mdio_complete);
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index 8c253db6988..27bf0ae0f0b 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -250,9 +250,9 @@
/* Register access macros */
#define macb_readl(port,reg) \
- readl((port)->regs + MACB_##reg)
+ __raw_readl((port)->regs + MACB_##reg)
#define macb_writel(port,reg,value) \
- writel((value), (port)->regs + MACB_##reg)
+ __raw_writel((value), (port)->regs + MACB_##reg)
struct dma_desc {
u32 addr;
@@ -377,7 +377,7 @@ struct macb {
unsigned int rx_pending, tx_pending;
- struct work_struct periodic_task;
+ struct delayed_work periodic_task;
struct mutex mdio_mutex;
struct completion mdio_complete;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index c41ae4286ee..b3bf8642273 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -314,6 +314,13 @@ int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
while (mp->tx_desc_count > 0) {
spin_lock_irqsave(&mp->lock, flags);
+
+ /* tx_desc_count might have changed before acquiring the lock */
+ if (mp->tx_desc_count <= 0) {
+ spin_unlock_irqrestore(&mp->lock, flags);
+ return released;
+ }
+
tx_index = mp->tx_used_desc_q;
desc = &mp->p_tx_desc_area[tx_index];
cmd_sts = desc->cmd_sts;
@@ -332,13 +339,13 @@ int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
if (skb)
mp->tx_skb[tx_index] = NULL;
- spin_unlock_irqrestore(&mp->lock, flags);
-
if (cmd_sts & ETH_ERROR_SUMMARY) {
printk("%s: Error in TX\n", dev->name);
mp->stats.tx_errors++;
}
+ spin_unlock_irqrestore(&mp->lock, flags);
+
if (cmd_sts & ETH_TX_FIRST_DESC)
dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE);
else
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 81f127a78af..61cbd4a6044 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -71,7 +71,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.0.0"
+#define MYRI10GE_VERSION_STR "1.2.0"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -92,8 +92,13 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
+#define MYRI10GE_ALLOC_ORDER 0
+#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
+#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
+
struct myri10ge_rx_buffer_state {
- struct sk_buff *skb;
+ struct page *page;
+ int page_offset;
DECLARE_PCI_UNMAP_ADDR(bus)
DECLARE_PCI_UNMAP_LEN(len)
};
@@ -116,9 +121,14 @@ struct myri10ge_rx_buf {
u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */
struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */
struct myri10ge_rx_buffer_state *info;
+ struct page *page;
+ dma_addr_t bus;
+ int page_offset;
int cnt;
+ int fill_cnt;
int alloc_fail;
int mask; /* number of rx slots -1 */
+ int watchdog_needed;
};
struct myri10ge_tx_buf {
@@ -150,6 +160,7 @@ struct myri10ge_priv {
struct myri10ge_rx_buf rx_big;
struct myri10ge_rx_done rx_done;
int small_bytes;
+ int big_bytes;
struct net_device *dev;
struct net_device_stats stats;
u8 __iomem *sram;
@@ -188,8 +199,6 @@ struct myri10ge_priv {
unsigned long serial_number;
int vendor_specific_offset;
int fw_multicast_support;
- u32 devctl;
- u16 msi_flags;
u32 read_dma;
u32 write_dma;
u32 read_write_dma;
@@ -217,7 +226,7 @@ module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n");
static int myri10ge_msi = 1; /* enable msi by default */
-module_param(myri10ge_msi, int, S_IRUGO);
+module_param(myri10ge_msi, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");
static int myri10ge_intr_coal_delay = 25;
@@ -238,11 +247,6 @@ module_param(myri10ge_force_firmware, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_force_firmware,
"Force firmware to assume aligned completions\n");
-static int myri10ge_skb_cross_4k = 0;
-module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(myri10ge_skb_cross_4k,
- "Can a small skb cross a 4KB boundary?\n");
-
static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
module_param(myri10ge_initial_mtu, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");
@@ -266,6 +270,14 @@ static int myri10ge_debug = -1; /* defaults above */
module_param(myri10ge_debug, int, 0);
MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
+static int myri10ge_fill_thresh = 256;
+module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");
+
+static int myri10ge_wcfifo = 1;
+module_param(myri10ge_wcfifo, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
+
#define MYRI10GE_FW_OFFSET 1024*1024
#define MYRI10GE_HIGHPART_TO_U32(X) \
(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -273,9 +285,9 @@ MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
-static inline void put_be32(__be32 val, __be32 __iomem *p)
+static inline void put_be32(__be32 val, __be32 __iomem * p)
{
- __raw_writel((__force __u32)val, (__force void __iomem *)p);
+ __raw_writel((__force __u32) val, (__force void __iomem *)p);
}
static int
@@ -711,12 +723,10 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
status |=
myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0);
- if (!mgp->msi_enabled) {
- status |= myri10ge_send_cmd
- (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0);
- mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
+ status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
+ &cmd, 0);
+ mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
- }
status |= myri10ge_send_cmd
(mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0);
mgp->intr_coal_delay_ptr = (__iomem __be32 *) (mgp->sram + cmd.data0);
@@ -804,194 +814,179 @@ myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
mb();
}
-/*
- * Set of routines to get a new receive buffer. Any buffer which
- * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
- * wdma restrictions. We also try to align any smaller allocation to
- * at least a 16 byte boundary for efficiency. We assume the linux
- * memory allocator works by powers of 2, and will not return memory
- * smaller than 2KB which crosses a 4KB boundary. If it does, we fall
- * back to allocating 2x as much space as required.
- *
- * We intend to replace large (>4KB) skb allocations by using
- * pages directly and building a fraglist in the near future.
- */
-
-static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev,
- int bytes)
-{
- struct sk_buff *skb;
- unsigned long data, roundup;
-
- skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD);
- if (skb == NULL)
- return NULL;
-
- /* Correct skb->truesize so that socket buffer
- * accounting is not confused the rounding we must
- * do to satisfy alignment constraints.
- */
- skb->truesize -= 4096;
-
- data = (unsigned long)(skb->data);
- roundup = (-data) & (4095);
- skb_reserve(skb, roundup);
- return skb;
-}
-
-/* Allocate 2x as much space as required and use whichever portion
- * does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev,
- unsigned int bytes)
+static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
{
- struct sk_buff *skb;
- unsigned long data, boundary;
-
- skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1);
- if (unlikely(skb == NULL))
- return NULL;
-
- /* Correct skb->truesize so that socket buffer
- * accounting is not confused the rounding we must
- * do to satisfy alignment constraints.
- */
- skb->truesize -= bytes + MXGEFW_PAD;
-
- data = (unsigned long)(skb->data);
- boundary = (data + 4095UL) & ~4095UL;
- if ((boundary - data) >= (bytes + MXGEFW_PAD))
- return skb;
+ struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
- skb_reserve(skb, boundary - data);
- return skb;
+ if ((skb->protocol == htons(ETH_P_8021Q)) &&
+ (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
+ vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
+ skb->csum = hw_csum;
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
}
-/* Allocate just enough space, and verify that the allocated
- * space does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev,
- int bytes)
+static inline void
+myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
+ struct skb_frag_struct *rx_frags, int len, int hlen)
{
- struct sk_buff *skb;
- unsigned long roundup, data, end;
-
- skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD);
- if (unlikely(skb == NULL))
- return NULL;
-
- /* Round allocated buffer to 16 byte boundary */
- data = (unsigned long)(skb->data);
- roundup = (-data) & 15UL;
- skb_reserve(skb, roundup);
- /* Verify that the data buffer does not cross a page boundary */
- data = (unsigned long)(skb->data);
- end = data + bytes + MXGEFW_PAD - 1;
- if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) {
- printk(KERN_NOTICE
- "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
- myri10ge_skb_cross_4k = 1;
- dev_kfree_skb_any(skb);
- skb = myri10ge_alloc_small_safe(dev, bytes);
- }
- return skb;
+ struct skb_frag_struct *skb_frags;
+
+ skb->len = skb->data_len = len;
+ skb->truesize = len + sizeof(struct sk_buff);
+ /* attach the page(s) */
+
+ skb_frags = skb_shinfo(skb)->frags;
+ while (len > 0) {
+ memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
+ len -= rx_frags->size;
+ skb_frags++;
+ rx_frags++;
+ skb_shinfo(skb)->nr_frags++;
+ }
+
+ /* pskb_may_pull is not available in irq context, but
+ * skb_pull() (for ether_pad and eth_type_trans()) requires
+ * the beginning of the packet in skb_headlen(), move it
+ * manually */
+ memcpy(skb->data, va, hlen);
+ skb_shinfo(skb)->frags[0].page_offset += hlen;
+ skb_shinfo(skb)->frags[0].size -= hlen;
+ skb->data_len -= hlen;
+ skb->tail += hlen;
+ skb_pull(skb, MXGEFW_PAD);
}
-static inline int
-myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp,
- int bytes, int idx)
+static void
+myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+ int bytes, int watchdog)
{
- struct net_device *dev = mgp->dev;
- struct pci_dev *pdev = mgp->pdev;
- struct sk_buff *skb;
- dma_addr_t bus;
- int len, retval = 0;
+ struct page *page;
+ int idx;
- bytes += VLAN_HLEN; /* account for 802.1q vlan tag */
+ if (unlikely(rx->watchdog_needed && !watchdog))
+ return;
- if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
- skb = myri10ge_alloc_big(dev, bytes);
- else if (myri10ge_skb_cross_4k)
- skb = myri10ge_alloc_small_safe(dev, bytes);
- else
- skb = myri10ge_alloc_small(dev, bytes);
+ /* try to refill entire ring */
+ while (rx->fill_cnt != (rx->cnt + rx->mask + 1)) {
+ idx = rx->fill_cnt & rx->mask;
- if (unlikely(skb == NULL)) {
- rx->alloc_fail++;
- retval = -ENOBUFS;
- goto done;
- }
-
- /* set len so that it only covers the area we
- * need mapped for DMA */
- len = bytes + MXGEFW_PAD;
-
- bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
- rx->info[idx].skb = skb;
- pci_unmap_addr_set(&rx->info[idx], bus, bus);
- pci_unmap_len_set(&rx->info[idx], len, len);
- rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus));
- rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
-
-done:
- /* copy 8 descriptors (64-bytes) to the mcp at a time */
- if ((idx & 7) == 7) {
- if (rx->wc_fifo == NULL)
- myri10ge_submit_8rx(&rx->lanai[idx - 7],
- &rx->shadow[idx - 7]);
- else {
- mb();
- myri10ge_pio_copy(rx->wc_fifo,
- &rx->shadow[idx - 7], 64);
+ if ((bytes < MYRI10GE_ALLOC_SIZE / 2) &&
+ (rx->page_offset + bytes <= MYRI10GE_ALLOC_SIZE)) {
+ /* we can use part of previous page */
+ get_page(rx->page);
+ } else {
+ /* we need a new page */
+ page =
+ alloc_pages(GFP_ATOMIC | __GFP_COMP,
+ MYRI10GE_ALLOC_ORDER);
+ if (unlikely(page == NULL)) {
+ if (rx->fill_cnt - rx->cnt < 16)
+ rx->watchdog_needed = 1;
+ return;
+ }
+ rx->page = page;
+ rx->page_offset = 0;
+ rx->bus = pci_map_page(mgp->pdev, page, 0,
+ MYRI10GE_ALLOC_SIZE,
+ PCI_DMA_FROMDEVICE);
+ }
+ rx->info[idx].page = rx->page;
+ rx->info[idx].page_offset = rx->page_offset;
+ /* note that this is the address of the start of the
+ * page */
+ pci_unmap_addr_set(&rx->info[idx], bus, rx->bus);
+ rx->shadow[idx].addr_low =
+ htonl(MYRI10GE_LOWPART_TO_U32(rx->bus) + rx->page_offset);
+ rx->shadow[idx].addr_high =
+ htonl(MYRI10GE_HIGHPART_TO_U32(rx->bus));
+
+ /* start next packet on a cacheline boundary */
+ rx->page_offset += SKB_DATA_ALIGN(bytes);
+ rx->fill_cnt++;
+
+ /* copy 8 descriptors to the firmware at a time */
+ if ((idx & 7) == 7) {
+ if (rx->wc_fifo == NULL)
+ myri10ge_submit_8rx(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7]);
+ else {
+ mb();
+ myri10ge_pio_copy(rx->wc_fifo,
+ &rx->shadow[idx - 7], 64);
+ }
}
}
- return retval;
}
-static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
+static inline void
+myri10ge_unmap_rx_page(struct pci_dev *pdev,
+ struct myri10ge_rx_buffer_state *info, int bytes)
{
- struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
-
- if ((skb->protocol == htons(ETH_P_8021Q)) &&
- (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
- vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
- skb->csum = hw_csum;
- skb->ip_summed = CHECKSUM_COMPLETE;
+ /* unmap the recvd page if we're the only or last user of it */
+ if (bytes >= MYRI10GE_ALLOC_SIZE / 2 ||
+ (info->page_offset + 2 * bytes) > MYRI10GE_ALLOC_SIZE) {
+ pci_unmap_page(pdev, (pci_unmap_addr(info, bus)
+ & ~(MYRI10GE_ALLOC_SIZE - 1)),
+ MYRI10GE_ALLOC_SIZE, PCI_DMA_FROMDEVICE);
}
}
-static inline unsigned long
+#define MYRI10GE_HLEN 64 /* The number of bytes to copy from a
+ * page into an skb */
+
+static inline int
myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
int bytes, int len, __wsum csum)
{
- dma_addr_t bus;
struct sk_buff *skb;
- int idx, unmap_len;
+ struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
+ int i, idx, hlen, remainder;
+ struct pci_dev *pdev = mgp->pdev;
+ struct net_device *dev = mgp->dev;
+ u8 *va;
+ len += MXGEFW_PAD;
idx = rx->cnt & rx->mask;
- rx->cnt++;
+ va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
+ prefetch(va);
+ /* Fill skb_frag_struct(s) with data from our receive */
+ for (i = 0, remainder = len; remainder > 0; i++) {
+ myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
+ rx_frags[i].page = rx->info[idx].page;
+ rx_frags[i].page_offset = rx->info[idx].page_offset;
+ if (remainder < MYRI10GE_ALLOC_SIZE)
+ rx_frags[i].size = remainder;
+ else
+ rx_frags[i].size = MYRI10GE_ALLOC_SIZE;
+ rx->cnt++;
+ idx = rx->cnt & rx->mask;
+ remainder -= MYRI10GE_ALLOC_SIZE;
+ }
+
+ hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
- /* save a pointer to the received skb */
- skb = rx->info[idx].skb;
- bus = pci_unmap_addr(&rx->info[idx], bus);
- unmap_len = pci_unmap_len(&rx->info[idx], len);
+ /* allocate an skb to attach the page(s) to. */
- /* try to replace the received skb */
- if (myri10ge_getbuf(rx, mgp, bytes, idx)) {
- /* drop the frame -- the old skbuf is re-cycled */
- mgp->stats.rx_dropped += 1;
+ skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
+ if (unlikely(skb == NULL)) {
+ mgp->stats.rx_dropped++;
+ do {
+ i--;
+ put_page(rx_frags[i].page);
+ } while (i != 0);
return 0;
}
- /* unmap the recvd skb */
- pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE);
-
- /* mcp implicitly skips 1st bytes so that packet is properly
- * aligned */
- skb_reserve(skb, MXGEFW_PAD);
-
- /* set the length of the frame */
- skb_put(skb, len);
+ /* Attach the pages to the skb, and trim off any padding */
+ myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
+ if (skb_shinfo(skb)->frags[0].size <= 0) {
+ put_page(skb_shinfo(skb)->frags[0].page);
+ skb_shinfo(skb)->nr_frags = 0;
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->dev = dev;
- skb->protocol = eth_type_trans(skb, mgp->dev);
if (mgp->csum_flag) {
if ((skb->protocol == htons(ETH_P_IP)) ||
(skb->protocol == htons(ETH_P_IPV6))) {
@@ -1000,9 +995,8 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
} else
myri10ge_vlan_ip_csum(skb, csum);
}
-
netif_receive_skb(skb);
- mgp->dev->last_rx = jiffies;
+ dev->last_rx = jiffies;
return 1;
}
@@ -1079,7 +1073,7 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
length, checksum);
else
rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big,
- mgp->dev->mtu + ETH_HLEN,
+ mgp->big_bytes,
length, checksum);
rx_packets += rx_ok;
rx_bytes += rx_ok * (unsigned long)length;
@@ -1094,6 +1088,14 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
rx_done->cnt = cnt;
mgp->stats.rx_packets += rx_packets;
mgp->stats.rx_bytes += rx_bytes;
+
+ /* restock receive rings if needed */
+ if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh)
+ myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+ mgp->small_bytes + MXGEFW_PAD, 0);
+ if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh)
+ myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
+
}
static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
@@ -1484,56 +1486,48 @@ static int myri10ge_allocate_rings(struct net_device *dev)
goto abort_with_rx_small_info;
/* Fill the receive rings */
+ mgp->rx_big.cnt = 0;
+ mgp->rx_small.cnt = 0;
+ mgp->rx_big.fill_cnt = 0;
+ mgp->rx_small.fill_cnt = 0;
+ mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE;
+ mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE;
+ mgp->rx_small.watchdog_needed = 0;
+ mgp->rx_big.watchdog_needed = 0;
+ myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+ mgp->small_bytes + MXGEFW_PAD, 0);
- for (i = 0; i <= mgp->rx_small.mask; i++) {
- status = myri10ge_getbuf(&mgp->rx_small, mgp,
- mgp->small_bytes, i);
- if (status) {
- printk(KERN_ERR
- "myri10ge: %s: alloced only %d small bufs\n",
- dev->name, i);
- goto abort_with_rx_small_ring;
- }
+ if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) {
+ printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n",
+ dev->name, mgp->rx_small.fill_cnt);
+ goto abort_with_rx_small_ring;
}
- for (i = 0; i <= mgp->rx_big.mask; i++) {
- status =
- myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i);
- if (status) {
- printk(KERN_ERR
- "myri10ge: %s: alloced only %d big bufs\n",
- dev->name, i);
- goto abort_with_rx_big_ring;
- }
+ myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0);
+ if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) {
+ printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n",
+ dev->name, mgp->rx_big.fill_cnt);
+ goto abort_with_rx_big_ring;
}
return 0;
abort_with_rx_big_ring:
- for (i = 0; i <= mgp->rx_big.mask; i++) {
- if (mgp->rx_big.info[i].skb != NULL)
- dev_kfree_skb_any(mgp->rx_big.info[i].skb);
- if (pci_unmap_len(&mgp->rx_big.info[i], len))
- pci_unmap_single(mgp->pdev,
- pci_unmap_addr(&mgp->rx_big.info[i],
- bus),
- pci_unmap_len(&mgp->rx_big.info[i],
- len),
- PCI_DMA_FROMDEVICE);
+ for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) {
+ int idx = i & mgp->rx_big.mask;
+ myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx],
+ mgp->big_bytes);
+ put_page(mgp->rx_big.info[idx].page);
}
abort_with_rx_small_ring:
- for (i = 0; i <= mgp->rx_small.mask; i++) {
- if (mgp->rx_small.info[i].skb != NULL)
- dev_kfree_skb_any(mgp->rx_small.info[i].skb);
- if (pci_unmap_len(&mgp->rx_small.info[i], len))
- pci_unmap_single(mgp->pdev,
- pci_unmap_addr(&mgp->rx_small.info[i],
- bus),
- pci_unmap_len(&mgp->rx_small.info[i],
- len),
- PCI_DMA_FROMDEVICE);
+ for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) {
+ int idx = i & mgp->rx_small.mask;
+ myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx],
+ mgp->small_bytes + MXGEFW_PAD);
+ put_page(mgp->rx_small.info[idx].page);
}
+
kfree(mgp->rx_big.info);
abort_with_rx_small_info:
@@ -1566,30 +1560,24 @@ static void myri10ge_free_rings(struct net_device *dev)
mgp = netdev_priv(dev);
- for (i = 0; i <= mgp->rx_big.mask; i++) {
- if (mgp->rx_big.info[i].skb != NULL)
- dev_kfree_skb_any(mgp->rx_big.info[i].skb);
- if (pci_unmap_len(&mgp->rx_big.info[i], len))
- pci_unmap_single(mgp->pdev,
- pci_unmap_addr(&mgp->rx_big.info[i],
- bus),
- pci_unmap_len(&mgp->rx_big.info[i],
- len),
- PCI_DMA_FROMDEVICE);
- }
-
- for (i = 0; i <= mgp->rx_small.mask; i++) {
- if (mgp->rx_small.info[i].skb != NULL)
- dev_kfree_skb_any(mgp->rx_small.info[i].skb);
- if (pci_unmap_len(&mgp->rx_small.info[i], len))
- pci_unmap_single(mgp->pdev,
- pci_unmap_addr(&mgp->rx_small.info[i],
- bus),
- pci_unmap_len(&mgp->rx_small.info[i],
- len),
- PCI_DMA_FROMDEVICE);
+ for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) {
+ idx = i & mgp->rx_big.mask;
+ if (i == mgp->rx_big.fill_cnt - 1)
+ mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE;
+ myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx],
+ mgp->big_bytes);
+ put_page(mgp->rx_big.info[idx].page);
}
+ for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) {
+ idx = i & mgp->rx_small.mask;
+ if (i == mgp->rx_small.fill_cnt - 1)
+ mgp->rx_small.info[idx].page_offset =
+ MYRI10GE_ALLOC_SIZE;
+ myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx],
+ mgp->small_bytes + MXGEFW_PAD);
+ put_page(mgp->rx_small.info[idx].page);
+ }
tx = &mgp->tx;
while (tx->done != tx->req) {
idx = tx->done & tx->mask;
@@ -1631,6 +1619,41 @@ static void myri10ge_free_rings(struct net_device *dev)
mgp->tx.req_list = NULL;
}
+static int myri10ge_request_irq(struct myri10ge_priv *mgp)
+{
+ struct pci_dev *pdev = mgp->pdev;
+ int status;
+
+ if (myri10ge_msi) {
+ status = pci_enable_msi(pdev);
+ if (status != 0)
+ dev_err(&pdev->dev,
+ "Error %d setting up MSI; falling back to xPIC\n",
+ status);
+ else
+ mgp->msi_enabled = 1;
+ } else {
+ mgp->msi_enabled = 0;
+ }
+ status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
+ mgp->dev->name, mgp);
+ if (status != 0) {
+ dev_err(&pdev->dev, "failed to allocate IRQ\n");
+ if (mgp->msi_enabled)
+ pci_disable_msi(pdev);
+ }
+ return status;
+}
+
+static void myri10ge_free_irq(struct myri10ge_priv *mgp)
+{
+ struct pci_dev *pdev = mgp->pdev;
+
+ free_irq(pdev->irq, mgp);
+ if (mgp->msi_enabled)
+ pci_disable_msi(pdev);
+}
+
static int myri10ge_open(struct net_device *dev)
{
struct myri10ge_priv *mgp;
@@ -1646,10 +1669,13 @@ static int myri10ge_open(struct net_device *dev)
status = myri10ge_reset(mgp);
if (status != 0) {
printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name);
- mgp->running = MYRI10GE_ETH_STOPPED;
- return -ENXIO;
+ goto abort_with_nothing;
}
+ status = myri10ge_request_irq(mgp);
+ if (status != 0)
+ goto abort_with_nothing;
+
/* decide what small buffer size to use. For good TCP rx
* performance, it is important to not receive 1514 byte
* frames into jumbo buffers, as it confuses the socket buffer
@@ -1657,19 +1683,18 @@ static int myri10ge_open(struct net_device *dev)
*/
if (dev->mtu <= ETH_DATA_LEN)
- mgp->small_bytes = 128; /* enough for a TCP header */
+ /* enough for a TCP header */
+ mgp->small_bytes = (128 > SMP_CACHE_BYTES)
+ ? (128 - MXGEFW_PAD)
+ : (SMP_CACHE_BYTES - MXGEFW_PAD);
else
- mgp->small_bytes = ETH_FRAME_LEN; /* enough for an ETH_DATA_LEN frame */
+ /* enough for a vlan encapsulated ETH_DATA_LEN frame */
+ mgp->small_bytes = VLAN_ETH_FRAME_LEN;
/* Override the small buffer size? */
if (myri10ge_small_bytes > 0)
mgp->small_bytes = myri10ge_small_bytes;
- /* If the user sets an obscenely small MTU, adjust the small
- * bytes down to nearly nothing */
- if (mgp->small_bytes >= (dev->mtu + ETH_HLEN))
- mgp->small_bytes = 64;
-
/* get the lanai pointers to the send and receive rings */
status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
@@ -1690,10 +1715,10 @@ static int myri10ge_open(struct net_device *dev)
"myri10ge: %s: failed to get ring sizes or locations\n",
dev->name);
mgp->running = MYRI10GE_ETH_STOPPED;
- return -ENXIO;
+ goto abort_with_irq;
}
- if (mgp->mtrr >= 0) {
+ if (myri10ge_wcfifo && mgp->mtrr >= 0) {
mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
mgp->rx_small.wc_fifo =
(u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
@@ -1705,17 +1730,23 @@ static int myri10ge_open(struct net_device *dev)
mgp->rx_big.wc_fifo = NULL;
}
- status = myri10ge_allocate_rings(dev);
- if (status != 0)
- goto abort_with_nothing;
-
/* Firmware needs the big buff size as a power of 2. Lie and
* tell him the buffer is larger, because we only use 1
* buffer/pkt, and the mtu will prevent overruns.
*/
- big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD;
- while ((big_pow2 & (big_pow2 - 1)) != 0)
- big_pow2++;
+ big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
+ if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
+ while ((big_pow2 & (big_pow2 - 1)) != 0)
+ big_pow2++;
+ mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
+ } else {
+ big_pow2 = MYRI10GE_ALLOC_SIZE;
+ mgp->big_bytes = big_pow2;
+ }
+
+ status = myri10ge_allocate_rings(dev);
+ if (status != 0)
+ goto abort_with_irq;
/* now give firmware buffers sizes, and MTU */
cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
@@ -1778,6 +1809,9 @@ static int myri10ge_open(struct net_device *dev)
abort_with_rings:
myri10ge_free_rings(dev);
+abort_with_irq:
+ myri10ge_free_irq(mgp);
+
abort_with_nothing:
mgp->running = MYRI10GE_ETH_STOPPED;
return -ENOMEM;
@@ -1814,7 +1848,7 @@ static int myri10ge_close(struct net_device *dev)
printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
netif_tx_disable(dev);
-
+ myri10ge_free_irq(mgp);
myri10ge_free_rings(dev);
mgp->running = MYRI10GE_ETH_STOPPED;
@@ -2206,7 +2240,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
struct myri10ge_cmd cmd;
struct myri10ge_priv *mgp;
struct dev_mc_list *mc_list;
- __be32 data[2] = {0, 0};
+ __be32 data[2] = { 0, 0 };
int err;
mgp = netdev_priv(dev);
@@ -2488,34 +2522,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
}
}
-static void myri10ge_save_state(struct myri10ge_priv *mgp)
-{
- struct pci_dev *pdev = mgp->pdev;
- int cap;
-
- pci_save_state(pdev);
- /* now save PCIe and MSI state that Linux will not
- * save for us */
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &mgp->devctl);
- cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
- pci_read_config_word(pdev, cap + PCI_MSI_FLAGS, &mgp->msi_flags);
-}
-
-static void myri10ge_restore_state(struct myri10ge_priv *mgp)
-{
- struct pci_dev *pdev = mgp->pdev;
- int cap;
-
- /* restore PCIe and MSI state that linux will not */
- cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- pci_write_config_dword(pdev, cap + PCI_CAP_ID_EXP, mgp->devctl);
- cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
- pci_write_config_word(pdev, cap + PCI_MSI_FLAGS, mgp->msi_flags);
-
- pci_restore_state(pdev);
-}
-
#ifdef CONFIG_PM
static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -2536,11 +2542,10 @@ static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
rtnl_unlock();
}
myri10ge_dummy_rdma(mgp, 0);
- free_irq(pdev->irq, mgp);
- myri10ge_save_state(mgp);
+ pci_save_state(pdev);
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
- return 0;
+
+ return pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
static int myri10ge_resume(struct pci_dev *pdev)
@@ -2562,34 +2567,33 @@ static int myri10ge_resume(struct pci_dev *pdev)
mgp->dev->name);
return -EIO;
}
- myri10ge_restore_state(mgp);
+
+ status = pci_restore_state(pdev);
+ if (status)
+ return status;
status = pci_enable_device(pdev);
- if (status < 0) {
+ if (status) {
dev_err(&pdev->dev, "failed to enable device\n");
- return -EIO;
+ return status;
}
pci_set_master(pdev);
- status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
- netdev->name, mgp);
- if (status != 0) {
- dev_err(&pdev->dev, "failed to allocate IRQ\n");
- goto abort_with_enabled;
- }
-
myri10ge_reset(mgp);
myri10ge_dummy_rdma(mgp, 1);
/* Save configuration space to be restored if the
* nic resets due to a parity error */
- myri10ge_save_state(mgp);
+ pci_save_state(pdev);
if (netif_running(netdev)) {
rtnl_lock();
- myri10ge_open(netdev);
+ status = myri10ge_open(netdev);
rtnl_unlock();
+ if (status != 0)
+ goto abort_with_enabled;
+
}
netif_device_attach(netdev);
@@ -2625,7 +2629,7 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
static void myri10ge_watchdog(struct work_struct *work)
{
struct myri10ge_priv *mgp =
- container_of(work, struct myri10ge_priv, watchdog_work);
+ container_of(work, struct myri10ge_priv, watchdog_work);
u32 reboot;
int status;
u16 cmd, vendor;
@@ -2647,7 +2651,11 @@ static void myri10ge_watchdog(struct work_struct *work)
* when the driver was loaded, or the last time the
* nic was resumed from power saving mode.
*/
- myri10ge_restore_state(mgp);
+ pci_restore_state(mgp->pdev);
+
+ /* save state again for accounting reasons */
+ pci_save_state(mgp->pdev);
+
} else {
/* if we get back -1's from our slot, perhaps somebody
* powered off our card. Don't try to reset it in
@@ -2698,6 +2706,21 @@ static void myri10ge_watchdog_timer(unsigned long arg)
struct myri10ge_priv *mgp;
mgp = (struct myri10ge_priv *)arg;
+
+ if (mgp->rx_small.watchdog_needed) {
+ myri10ge_alloc_rx_pages(mgp, &mgp->rx_small,
+ mgp->small_bytes + MXGEFW_PAD, 1);
+ if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >=
+ myri10ge_fill_thresh)
+ mgp->rx_small.watchdog_needed = 0;
+ }
+ if (mgp->rx_big.watchdog_needed) {
+ myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1);
+ if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >=
+ myri10ge_fill_thresh)
+ mgp->rx_big.watchdog_needed = 0;
+ }
+
if (mgp->tx.req != mgp->tx.done &&
mgp->tx.done == mgp->watchdog_tx_done &&
mgp->watchdog_tx_req != mgp->watchdog_tx_done)
@@ -2848,23 +2871,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto abort_with_firmware;
}
- if (myri10ge_msi) {
- status = pci_enable_msi(pdev);
- if (status != 0)
- dev_err(&pdev->dev,
- "Error %d setting up MSI; falling back to xPIC\n",
- status);
- else
- mgp->msi_enabled = 1;
- }
-
- status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
- netdev->name, mgp);
- if (status != 0) {
- dev_err(&pdev->dev, "failed to allocate IRQ\n");
- goto abort_with_firmware;
- }
-
pci_set_drvdata(pdev, mgp);
if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
@@ -2876,7 +2882,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->hard_start_xmit = myri10ge_xmit;
netdev->get_stats = myri10ge_get_stats;
netdev->base_addr = mgp->iomem_base;
- netdev->irq = pdev->irq;
netdev->change_mtu = myri10ge_change_mtu;
netdev->set_multicast_list = myri10ge_set_multicast_list;
netdev->set_mac_address = myri10ge_set_mac_address;
@@ -2886,9 +2891,18 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->poll = myri10ge_poll;
netdev->weight = myri10ge_napi_weight;
+ /* make sure we can get an irq, and that MSI can be
+ * setup (if available). Also ensure netdev->irq
+ * is set to correct value if MSI is enabled */
+ status = myri10ge_request_irq(mgp);
+ if (status != 0)
+ goto abort_with_firmware;
+ netdev->irq = pdev->irq;
+ myri10ge_free_irq(mgp);
+
/* Save configuration space to be restored if the
* nic resets due to a parity error */
- myri10ge_save_state(mgp);
+ pci_save_state(pdev);
/* Setup the watchdog timer */
setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
@@ -2899,19 +2913,17 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
status = register_netdev(netdev);
if (status != 0) {
dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
- goto abort_with_irq;
+ goto abort_with_state;
}
dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
(mgp->msi_enabled ? "MSI" : "xPIC"),
- pdev->irq, mgp->tx.boundary, mgp->fw_name,
+ netdev->irq, mgp->tx.boundary, mgp->fw_name,
(mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
return 0;
-abort_with_irq:
- free_irq(pdev->irq, mgp);
- if (mgp->msi_enabled)
- pci_disable_msi(pdev);
+abort_with_state:
+ pci_restore_state(pdev);
abort_with_firmware:
myri10ge_dummy_rdma(mgp, 0);
@@ -2962,12 +2974,12 @@ static void myri10ge_remove(struct pci_dev *pdev)
flush_scheduled_work();
netdev = mgp->dev;
unregister_netdev(netdev);
- free_irq(pdev->irq, mgp);
- if (mgp->msi_enabled)
- pci_disable_msi(pdev);
myri10ge_dummy_rdma(mgp, 0);
+ /* avoid a memory leak */
+ pci_restore_state(pdev);
+
bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
dma_free_coherent(&pdev->dev, bytes,
mgp->rx_done.entry, mgp->rx_done.bus);
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index b5410bee5f2..e8598b80922 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -63,12 +63,11 @@
#include "netxen_nic_hw.h"
-#define NETXEN_NIC_BUILD_NO "1"
+#define NETXEN_NIC_BUILD_NO "2"
#define _NETXEN_NIC_LINUX_MAJOR 3
#define _NETXEN_NIC_LINUX_MINOR 3
-#define _NETXEN_NIC_LINUX_SUBVERSION 2
-#define NETXEN_NIC_LINUX_VERSIONID "3.3.2" "-" NETXEN_NIC_BUILD_NO
-#define NETXEN_NIC_FW_VERSIONID "3.3.2"
+#define _NETXEN_NIC_LINUX_SUBVERSION 3
+#define NETXEN_NIC_LINUX_VERSIONID "3.3.3" "-" NETXEN_NIC_BUILD_NO
#define RCV_DESC_RINGSIZE \
(sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
@@ -137,7 +136,7 @@ extern struct workqueue_struct *netxen_workq;
#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
#define MAX_RX_BUFFER_LENGTH 1760
-#define MAX_RX_JUMBO_BUFFER_LENGTH 9046
+#define MAX_RX_JUMBO_BUFFER_LENGTH 8062
#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512)
#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2)
#define RX_JUMBO_DMA_MAP_LEN \
@@ -199,9 +198,9 @@ enum {
(RCV_DESC_NORMAL)))
#define MAX_CMD_DESCRIPTORS 1024
-#define MAX_RCV_DESCRIPTORS 32768
-#define MAX_JUMBO_RCV_DESCRIPTORS 4096
-#define MAX_LRO_RCV_DESCRIPTORS 2048
+#define MAX_RCV_DESCRIPTORS 16384
+#define MAX_JUMBO_RCV_DESCRIPTORS 1024
+#define MAX_LRO_RCV_DESCRIPTORS 64
#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS
#define MAX_RCV_DESC MAX_RCV_DESCRIPTORS
@@ -240,49 +239,39 @@ extern unsigned long long netxen_dma_mask;
typedef u32 netxen_ctx_msg;
-#define _netxen_set_bits(config_word, start, bits, val) {\
- unsigned long long mask = (((1ULL << (bits)) - 1) << (start)); \
- unsigned long long value = (val); \
- (config_word) &= ~mask; \
- (config_word) |= (((value) << (start)) & mask); \
-}
-
#define netxen_set_msg_peg_id(config_word, val) \
- _netxen_set_bits(config_word, 0, 2, val)
+ ((config_word) &= ~3, (config_word) |= val & 3)
#define netxen_set_msg_privid(config_word) \
- set_bit(2, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 2)
#define netxen_set_msg_count(config_word, val) \
- _netxen_set_bits(config_word, 3, 15, val)
+ ((config_word) &= ~(0x7fff<<3), (config_word) |= (val & 0x7fff) << 3)
#define netxen_set_msg_ctxid(config_word, val) \
- _netxen_set_bits(config_word, 18, 10, val)
+ ((config_word) &= ~(0x3ff<<18), (config_word) |= (val & 0x3ff) << 18)
#define netxen_set_msg_opcode(config_word, val) \
- _netxen_set_bits(config_word, 28, 4, val)
+ ((config_word) &= ~(0xf<<24), (config_word) |= (val & 0xf) << 24)
struct netxen_rcv_context {
- u32 rcv_ring_addr_lo;
- u32 rcv_ring_addr_hi;
- u32 rcv_ring_size;
- u32 rsrvd;
+ __le64 rcv_ring_addr;
+ __le32 rcv_ring_size;
+ __le32 rsrvd;
};
struct netxen_ring_ctx {
/* one command ring */
- u64 cmd_consumer_offset;
- u32 cmd_ring_addr_lo;
- u32 cmd_ring_addr_hi;
- u32 cmd_ring_size;
- u32 rsrvd;
+ __le64 cmd_consumer_offset;
+ __le64 cmd_ring_addr;
+ __le32 cmd_ring_size;
+ __le32 rsrvd;
/* three receive rings */
struct netxen_rcv_context rcv_ctx[3];
/* one status ring */
- u32 sts_ring_addr_lo;
- u32 sts_ring_addr_hi;
- u32 sts_ring_size;
+ __le64 sts_ring_addr;
+ __le32 sts_ring_size;
- u32 ctx_id;
+ __le32 ctx_id;
} __attribute__ ((aligned(64)));
/*
@@ -306,81 +295,85 @@ struct netxen_ring_ctx {
((cmd_desc)->port_ctxid |= ((var) & 0x0F))
#define netxen_set_cmd_desc_flags(cmd_desc, val) \
- _netxen_set_bits((cmd_desc)->flags_opcode, 0, 7, val)
+ ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x7f), \
+ (cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f))
#define netxen_set_cmd_desc_opcode(cmd_desc, val) \
- _netxen_set_bits((cmd_desc)->flags_opcode, 7, 6, val)
+ ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \
+ (cmd_desc)->flags_opcode |= cpu_to_le16((val) & (0x3f<<7)))
#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
- _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 0, 8, val);
+ ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \
+ (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff))
#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
- _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 8, 24, val);
+ ((cmd_desc)->num_of_buffers_total_length &= cpu_to_le32(0xff), \
+ (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 24))
#define netxen_get_cmd_desc_opcode(cmd_desc) \
- (((cmd_desc)->flags_opcode >> 7) & 0x003F)
+ ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F)
#define netxen_get_cmd_desc_totallength(cmd_desc) \
- (((cmd_desc)->num_of_buffers_total_length >> 8) & 0x0FFFFFF)
+ (le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8)
struct cmd_desc_type0 {
u8 tcp_hdr_offset; /* For LSO only */
u8 ip_hdr_offset; /* For LSO only */
/* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */
- u16 flags_opcode;
+ __le16 flags_opcode;
/* Bit pattern: 0-7 total number of segments,
8-31 Total size of the packet */
- u32 num_of_buffers_total_length;
+ __le32 num_of_buffers_total_length;
union {
struct {
- u32 addr_low_part2;
- u32 addr_high_part2;
+ __le32 addr_low_part2;
+ __le32 addr_high_part2;
};
- u64 addr_buffer2;
+ __le64 addr_buffer2;
};
- u16 reference_handle; /* changed to u16 to add mss */
- u16 mss; /* passed by NDIS_PACKET for LSO */
+ __le16 reference_handle; /* changed to u16 to add mss */
+ __le16 mss; /* passed by NDIS_PACKET for LSO */
/* Bit pattern 0-3 port, 0-3 ctx id */
u8 port_ctxid;
u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */
- u16 conn_id; /* IPSec offoad only */
+ __le16 conn_id; /* IPSec offoad only */
union {
struct {
- u32 addr_low_part3;
- u32 addr_high_part3;
+ __le32 addr_low_part3;
+ __le32 addr_high_part3;
};
- u64 addr_buffer3;
+ __le64 addr_buffer3;
};
union {
struct {
- u32 addr_low_part1;
- u32 addr_high_part1;
+ __le32 addr_low_part1;
+ __le32 addr_high_part1;
};
- u64 addr_buffer1;
+ __le64 addr_buffer1;
};
- u16 buffer1_length;
- u16 buffer2_length;
- u16 buffer3_length;
- u16 buffer4_length;
+ __le16 buffer1_length;
+ __le16 buffer2_length;
+ __le16 buffer3_length;
+ __le16 buffer4_length;
union {
struct {
- u32 addr_low_part4;
- u32 addr_high_part4;
+ __le32 addr_low_part4;
+ __le32 addr_high_part4;
};
- u64 addr_buffer4;
+ __le64 addr_buffer4;
};
- u64 unused;
+ __le64 unused;
} __attribute__ ((aligned(64)));
/* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
struct rcv_desc {
- u16 reference_handle;
- u16 reserved;
- u32 buffer_length; /* allocated buffer length (usually 2K) */
- u64 addr_buffer;
+ __le16 reference_handle;
+ __le16 reserved;
+ __le32 buffer_length; /* allocated buffer length (usually 2K) */
+ __le64 addr_buffer;
};
/* opcode field in status_desc */
@@ -406,36 +399,36 @@ struct rcv_desc {
(((status_desc)->lro & 0x80) >> 7)
#define netxen_get_sts_port(status_desc) \
- ((status_desc)->status_desc_data & 0x0F)
+ (le64_to_cpu((status_desc)->status_desc_data) & 0x0F)
#define netxen_get_sts_status(status_desc) \
- (((status_desc)->status_desc_data >> 4) & 0x0F)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 4) & 0x0F)
#define netxen_get_sts_type(status_desc) \
- (((status_desc)->status_desc_data >> 8) & 0x0F)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 8) & 0x0F)
#define netxen_get_sts_totallength(status_desc) \
- (((status_desc)->status_desc_data >> 12) & 0xFFFF)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 12) & 0xFFFF)
#define netxen_get_sts_refhandle(status_desc) \
- (((status_desc)->status_desc_data >> 28) & 0xFFFF)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 28) & 0xFFFF)
#define netxen_get_sts_prot(status_desc) \
- (((status_desc)->status_desc_data >> 44) & 0x0F)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 44) & 0x0F)
#define netxen_get_sts_owner(status_desc) \
- (((status_desc)->status_desc_data >> 56) & 0x03)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 56) & 0x03)
#define netxen_get_sts_opcode(status_desc) \
- (((status_desc)->status_desc_data >> 58) & 0x03F)
+ ((le64_to_cpu((status_desc)->status_desc_data) >> 58) & 0x03F)
#define netxen_clear_sts_owner(status_desc) \
((status_desc)->status_desc_data &= \
- ~(((unsigned long long)3) << 56 ))
+ ~cpu_to_le64(((unsigned long long)3) << 56 ))
#define netxen_set_sts_owner(status_desc, val) \
((status_desc)->status_desc_data |= \
- (((unsigned long long)((val) & 0x3)) << 56 ))
+ cpu_to_le64(((unsigned long long)((val) & 0x3)) << 56 ))
struct status_desc {
/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
28-43 reference_handle, 44-47 protocol, 48-52 unused
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
- u64 status_desc_data;
- u32 hash_value;
+ __le64 status_desc_data;
+ __le32 hash_value;
u8 hash_type;
u8 msg_type;
u8 unused;
@@ -852,8 +845,6 @@ struct netxen_adapter {
spinlock_t tx_lock;
spinlock_t lock;
struct work_struct watchdog_task;
- struct work_struct tx_timeout_task;
- struct net_device *netdev;
struct timer_list watchdog_timer;
u32 curr_window;
@@ -887,7 +878,6 @@ struct netxen_adapter {
struct netxen_recv_context recv_ctx[MAX_RCV_CTX];
int is_up;
- int number;
struct netxen_dummy_dma dummy_dma;
/* Context interface shared between card and host */
@@ -950,6 +940,7 @@ struct netxen_port {
struct pci_dev *pdev;
struct net_device_stats net_stats;
struct netxen_port_stats stats;
+ struct work_struct tx_timeout_task;
};
#define PCI_OFFSET_FIRST_RANGE(adapter, off) \
@@ -1008,9 +999,9 @@ void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, int port,
void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port,
long enable);
int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, long reg,
- __le32 * readval);
+ __u32 * readval);
int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy,
- long reg, __le32 val);
+ long reg, __u32 val);
/* Functions available from netxen_nic_hw.c */
int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu);
@@ -1027,14 +1018,6 @@ int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
int len);
int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
int len);
-int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
-int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
-int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter,
- u64 off, void *data, int size);
-int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter,
- u64 off, void *data, int size);
void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
unsigned long off, int data);
@@ -1067,9 +1050,6 @@ void netxen_tso_check(struct netxen_adapter *adapter,
struct cmd_desc_type0 *desc, struct sk_buff *skb);
int netxen_nic_hw_resources(struct netxen_adapter *adapter);
void netxen_nic_clear_stats(struct netxen_adapter *adapter);
-int
-netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
- struct netxen_port *port);
int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
void netxen_watchdog_task(struct work_struct *work);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 2ab4885cc95..c381d77a733 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -42,7 +42,6 @@
#include "netxen_nic_hw.h"
#include "netxen_nic.h"
#include "netxen_nic_phan_reg.h"
-#include "netxen_nic_ioctl.h"
struct netxen_nic_stats {
char stat_string[ETH_GSTRING_LEN];
@@ -79,8 +78,7 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
{"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
};
-#define NETXEN_NIC_STATS_LEN \
- sizeof(netxen_nic_gstrings_stats) / sizeof(struct netxen_nic_stats)
+#define NETXEN_NIC_STATS_LEN ARRAY_SIZE(netxen_nic_gstrings_stats)
static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_offline", "EEPROM_Test_offline",
@@ -220,7 +218,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
- __le32 status;
+ __u32 status;
/* read which mode */
if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -228,7 +226,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
if (adapter->phy_write
&& adapter->phy_write(adapter, port->portnum,
NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
- (__le32) ecmd->autoneg) != 0)
+ ecmd->autoneg) != 0)
return -EIO;
else
port->link_autoneg = ecmd->autoneg;
@@ -281,7 +279,7 @@ static int netxen_nic_get_regs_len(struct net_device *dev)
}
struct netxen_niu_regs {
- __le32 reg[NETXEN_NIC_REGS_COUNT];
+ __u32 reg[NETXEN_NIC_REGS_COUNT];
};
static struct netxen_niu_regs niu_registers[] = {
@@ -374,7 +372,7 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
{
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
- __le32 mode, *regs_buff = p;
+ __u32 mode, *regs_buff = p;
void __iomem *addr;
int i, window;
@@ -417,7 +415,7 @@ static u32 netxen_nic_get_link(struct net_device *dev)
{
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
- __le32 status;
+ __u32 status;
/* read which mode */
if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -484,13 +482,13 @@ netxen_nic_get_pauseparam(struct net_device *dev,
{
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
- __le32 val;
+ __u32 val;
if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
/* get flow control settings */
netxen_nic_read_w0(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
- (u32 *) & val);
+ &val);
pause->rx_pause = netxen_gb_get_rx_flowctl(val);
pause->tx_pause = netxen_gb_get_tx_flowctl(val);
/* get autoneg settings */
@@ -504,7 +502,7 @@ netxen_nic_set_pauseparam(struct net_device *dev,
{
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
- __le32 val;
+ __u32 val;
unsigned int autoneg;
/* read mode */
@@ -524,13 +522,13 @@ netxen_nic_set_pauseparam(struct net_device *dev,
netxen_nic_write_w0(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
- *(u32 *) (&val));
+ *&val);
/* set autoneg */
autoneg = pause->autoneg;
if (adapter->phy_write
&& adapter->phy_write(adapter, port->portnum,
NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
- (__le32) autoneg) != 0)
+ autoneg) != 0)
return -EIO;
else {
port->link_autoneg = pause->autoneg;
@@ -545,7 +543,7 @@ static int netxen_nic_reg_test(struct net_device *dev)
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
u32 data_read, data_written, save;
- __le32 mode;
+ __u32 mode;
/*
* first test the "Read Only" registers by writing which mode
@@ -711,7 +709,6 @@ netxen_nic_get_ethtool_stats(struct net_device *dev,
(netxen_nic_gstrings_stats[index].sizeof_stat ==
sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
}
-
}
struct ethtool_ops netxen_nic_ethtool_ops = {
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 9147b6048df..f263232f499 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -95,7 +95,7 @@ void netxen_nic_set_multi(struct net_device *netdev)
struct netxen_port *port = netdev_priv(netdev);
struct netxen_adapter *adapter = port->adapter;
struct dev_mc_list *mc_ptr;
- __le32 netxen_mac_addr_cntl_data = 0;
+ __u32 netxen_mac_addr_cntl_data = 0;
mc_ptr = netdev->mc_list;
if (netdev->flags & IFF_PROMISC) {
@@ -236,8 +236,9 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
}
memset(addr, 0, sizeof(struct netxen_ring_ctx));
adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
- adapter->ctx_desc->cmd_consumer_offset = adapter->ctx_desc_phys_addr
- + sizeof(struct netxen_ring_ctx);
+ adapter->ctx_desc->cmd_consumer_offset =
+ cpu_to_le64(adapter->ctx_desc_phys_addr +
+ sizeof(struct netxen_ring_ctx));
adapter->cmd_consumer = (uint32_t *) (((char *)addr) +
sizeof(struct netxen_ring_ctx));
@@ -253,11 +254,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
return -ENOMEM;
}
- adapter->ctx_desc->cmd_ring_addr_lo =
- hw->cmd_desc_phys_addr & 0xffffffffUL;
- adapter->ctx_desc->cmd_ring_addr_hi =
- ((u64) hw->cmd_desc_phys_addr >> 32);
- adapter->ctx_desc->cmd_ring_size = adapter->max_tx_desc_count;
+ adapter->ctx_desc->cmd_ring_addr =
+ cpu_to_le64(hw->cmd_desc_phys_addr);
+ adapter->ctx_desc->cmd_ring_size =
+ cpu_to_le32(adapter->max_tx_desc_count);
hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
@@ -278,12 +278,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
return err;
}
rcv_desc->desc_head = (struct rcv_desc *)addr;
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_lo =
- rcv_desc->phys_addr & 0xffffffffUL;
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_hi =
- ((u64) rcv_desc->phys_addr >> 32);
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+ cpu_to_le64(rcv_desc->phys_addr);
adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
- rcv_desc->max_rx_desc_count;
+ cpu_to_le32(rcv_desc->max_rx_desc_count);
}
addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
@@ -297,11 +295,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
return err;
}
recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
- adapter->ctx_desc->sts_ring_addr_lo =
- recv_ctx->rcv_status_desc_phys_addr & 0xffffffffUL;
- adapter->ctx_desc->sts_ring_addr_hi =
- ((u64) recv_ctx->rcv_status_desc_phys_addr >> 32);
- adapter->ctx_desc->sts_ring_size = adapter->max_rx_desc_count;
+ adapter->ctx_desc->sts_ring_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ adapter->ctx_desc->sts_ring_size =
+ cpu_to_le32(adapter->max_rx_desc_count);
}
/* Window = 1 */
@@ -376,7 +373,7 @@ void netxen_tso_check(struct netxen_adapter *adapter,
((skb->nh.iph)->ihl * sizeof(u32)) +
((skb->h.th)->doff * sizeof(u32));
netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
- } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (skb->nh.iph->protocol == IPPROTO_TCP) {
netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
} else if (skb->nh.iph->protocol == IPPROTO_UDP) {
@@ -387,10 +384,6 @@ void netxen_tso_check(struct netxen_adapter *adapter,
}
adapter->stats.xmitcsummed++;
desc->tcp_hdr_offset = skb->h.raw - skb->data;
- netxen_set_cmd_desc_totallength(desc,
- cpu_to_le32
- (netxen_get_cmd_desc_totallength
- (desc)));
desc->ip_hdr_offset = skb->nh.raw - skb->data;
}
@@ -867,9 +860,9 @@ netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
void netxen_nic_set_link_parameters(struct netxen_port *port)
{
struct netxen_adapter *adapter = port->adapter;
- __le32 status;
- __le32 autoneg;
- __le32 mode;
+ __u32 status;
+ __u32 autoneg;
+ __u32 mode;
netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
@@ -984,7 +977,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
_NETXEN_NIC_LINUX_MAJOR, fw_major);
adapter->driver_mismatch = 1;
}
- if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
+ if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
+ fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
printk(KERN_ERR "The mismatch in driver version and firmware "
"version minor number\n"
"Driver version minor number = %d \t"
@@ -997,297 +991,3 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
fw_major, fw_minor);
}
-int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off)
-{
- int data;
- netxen_nic_hw_read_wx(adapter, off, &data, 4);
- return data;
-}
-
-int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off,
- void *data, int len)
-{
- void *addr;
- u64 offset = off;
- u8 *mem_ptr = NULL;
- unsigned long mem_base;
- unsigned long mem_page;
-
- if (ADDR_IN_WINDOW1(off)) {
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- if (!addr) {
- mem_base = pci_resource_start(adapter->ahw.pdev, 0);
- offset = NETXEN_CRB_NORMAL(off);
- mem_page = offset & PAGE_MASK;
- if (mem_page != ((offset + len - 1) & PAGE_MASK))
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE * 2);
- else
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL) {
- return 1;
- }
- addr = mem_ptr;
- addr += offset & (PAGE_SIZE - 1);
- }
- } else {
- addr = pci_base_offset(adapter, off);
- if (!addr) {
- mem_base = pci_resource_start(adapter->ahw.pdev, 0);
- mem_page = off & PAGE_MASK;
- if (mem_page != ((off + len - 1) & PAGE_MASK))
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE * 2);
- else
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL) {
- return 1;
- }
- addr = mem_ptr;
- addr += off & (PAGE_SIZE - 1);
- }
- netxen_nic_pci_change_crbwindow(adapter, 0);
- }
- switch (len) {
- case 1:
- writeb(*(u8 *) data, addr);
- break;
- case 2:
- writew(*(u16 *) data, addr);
- break;
- case 4:
- writel(*(u32 *) data, addr);
- break;
- case 8:
- writeq(*(u64 *) data, addr);
- break;
- default:
- DPRINTK(INFO,
- "writing data %lx to offset %llx, num words=%d\n",
- *(unsigned long *)data, off, (len >> 3));
-
- netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
- (len >> 3));
- break;
- }
-
- if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
- if (mem_ptr)
- iounmap(mem_ptr);
- return 0;
-}
-
-int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off,
- void *data, int len)
-{
- void *addr;
- u64 offset;
- u8 *mem_ptr = NULL;
- unsigned long mem_base;
- unsigned long mem_page;
-
- if (ADDR_IN_WINDOW1(off)) {
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- if (!addr) {
- mem_base = pci_resource_start(adapter->ahw.pdev, 0);
- offset = NETXEN_CRB_NORMAL(off);
- mem_page = offset & PAGE_MASK;
- if (mem_page != ((offset + len - 1) & PAGE_MASK))
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE * 2);
- else
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL) {
- *(u8 *) data = 0;
- return 1;
- }
- addr = mem_ptr;
- addr += offset & (PAGE_SIZE - 1);
- }
- } else {
- addr = pci_base_offset(adapter, off);
- if (!addr) {
- mem_base = pci_resource_start(adapter->ahw.pdev, 0);
- mem_page = off & PAGE_MASK;
- if (mem_page != ((off + len - 1) & PAGE_MASK))
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE * 2);
- else
- mem_ptr =
- ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL)
- return 1;
- addr = mem_ptr;
- addr += off & (PAGE_SIZE - 1);
- }
- netxen_nic_pci_change_crbwindow(adapter, 0);
- }
- switch (len) {
- case 1:
- *(u8 *) data = readb(addr);
- break;
- case 2:
- *(u16 *) data = readw(addr);
- break;
- case 4:
- *(u32 *) data = readl(addr);
- break;
- case 8:
- *(u64 *) data = readq(addr);
- break;
- default:
- netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
- (len >> 3));
- break;
- }
- if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
- if (mem_ptr)
- iounmap(mem_ptr);
- return 0;
-}
-
-int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter, u64 off,
- void *data, int size)
-{
- void *addr;
- int ret = 0;
- u8 *mem_ptr = NULL;
- unsigned long mem_base;
- unsigned long mem_page;
-
- if (data == NULL || off > (128 * 1024 * 1024)) {
- printk(KERN_ERR "%s: data: %p off:%llx\n",
- netxen_nic_driver_name, data, off);
- return 1;
- }
- off = netxen_nic_pci_set_window(adapter, off);
- /* Corner case : Malicious user tried to break the driver by reading
- last few bytes in ranges and tries to read further addresses.
- */
- if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) {
- printk(KERN_ERR "%s: Invalid access to memory address range"
- " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off,
- off + size);
- return 1;
- }
- addr = pci_base_offset(adapter, off);
- DPRINTK(INFO, "writing data %llx to offset %llx\n",
- *(unsigned long long *)data, off);
- if (!addr) {
- mem_base = pci_resource_start(adapter->ahw.pdev, 0);
- mem_page = off & PAGE_MASK;
- /* Map two pages whenever user tries to access addresses in two
- consecutive pages.
- */
- if (mem_page != ((off + size - 1) & PAGE_MASK))
- mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
- else
- mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL) {
- return 1;
- }
- addr = mem_ptr;
- addr += off & (PAGE_SIZE - 1);
- }
- switch (size) {
- case 1:
- writeb(*(u8 *) data, addr);
- break;
- case 2:
- writew(*(u16 *) data, addr);
- break;
- case 4:
- writel(*(u32 *) data, addr);
- break;
- case 8:
- writeq(*(u64 *) data, addr);
- break;
- default:
- DPRINTK(INFO,
- "writing data %lx to offset %llx, num words=%d\n",
- *(unsigned long *)data, off, (size >> 3));
-
- netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
- (size >> 3));
- break;
- }
-
- if (mem_ptr)
- iounmap(mem_ptr);
- DPRINTK(INFO, "wrote %llx\n", *(unsigned long long *)data);
-
- return ret;
-}
-
-int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter,
- u64 off, void *data, int size)
-{
- void *addr;
- int ret = 0;
- u8 *mem_ptr = NULL;
- unsigned long mem_base;
- unsigned long mem_page;
-
- if (data == NULL || off > (128 * 1024 * 1024)) {
- printk(KERN_ERR "%s: data: %p off:%llx\n",
- netxen_nic_driver_name, data, off);
- return 1;
- }
- off = netxen_nic_pci_set_window(adapter, off);
- /* Corner case : Malicious user tried to break the driver by reading
- last few bytes in ranges and tries to read further addresses.
- */
- if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) {
- printk(KERN_ERR "%s: Invalid access to memory address range"
- " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off,
- off + size);
- return 1;
- }
- addr = pci_base_offset(adapter, off);
- if (!addr) {
- mem_base = pci_resource_start(adapter->ahw.pdev, 0);
- mem_page = off & PAGE_MASK;
- /* Map two pages whenever user tries to access addresses in two
- consecutive pages.
- */
- if (mem_page != ((off + size - 1) & PAGE_MASK))
- mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
- else
- mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL) {
- *(u8 *) data = 0;
- return 1;
- }
- addr = mem_ptr;
- addr += off & (PAGE_SIZE - 1);
- }
- switch (size) {
- case 1:
- *(u8 *) data = readb(addr);
- break;
- case 2:
- *(u16 *) data = readw(addr);
- break;
- case 4:
- *(u32 *) data = readl(addr);
- break;
- case 8:
- *(u64 *) data = readq(addr);
- break;
- default:
- netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
- (size >> 3));
- break;
- }
-
- if (mem_ptr)
- iounmap(mem_ptr);
- DPRINTK(INFO, "read %llx\n", *(unsigned long long *)data);
-
- return ret;
-}
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index 0685633a9c1..ab1112eb1b0 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -124,28 +124,28 @@ typedef enum {
*/
#define netxen_gb_enable_tx(config_word) \
- set_bit(0, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 0)
#define netxen_gb_enable_rx(config_word) \
- set_bit(2, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 2)
#define netxen_gb_tx_flowctl(config_word) \
- set_bit(4, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 4)
#define netxen_gb_rx_flowctl(config_word) \
- set_bit(5, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 5)
#define netxen_gb_tx_reset_pb(config_word) \
- set_bit(16, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 16)
#define netxen_gb_rx_reset_pb(config_word) \
- set_bit(17, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 17)
#define netxen_gb_tx_reset_mac(config_word) \
- set_bit(18, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 18)
#define netxen_gb_rx_reset_mac(config_word) \
- set_bit(19, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 19)
#define netxen_gb_soft_reset(config_word) \
- set_bit(31, (unsigned long*)(&config_word))
+ ((config_word) |= 1 << 31)
#define netxen_gb_unset_tx_flowctl(config_word) \
- clear_bit(4, (unsigned long *)(&config_word))
+ ((config_word) &= ~(1 << 4))
#define netxen_gb_unset_rx_flowctl(config_word) \
- clear_bit(5, (unsigned long*)(&config_word))
+ ((config_word) &= ~(1 << 5))
#define netxen_gb_get_tx_synced(config_word) \
_netxen_crb_get_bit((config_word), 1)
@@ -171,15 +171,15 @@ typedef enum {
*/
#define netxen_gb_set_duplex(config_word) \
- set_bit(0, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 0)
#define netxen_gb_set_crc_enable(config_word) \
- set_bit(1, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 1)
#define netxen_gb_set_padshort(config_word) \
- set_bit(2, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 2)
#define netxen_gb_set_checklength(config_word) \
- set_bit(4, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 4)
#define netxen_gb_set_hugeframes(config_word) \
- set_bit(5, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 5)
#define netxen_gb_set_preamblelen(config_word, val) \
((config_word) |= ((val) << 12) & 0xF000)
#define netxen_gb_set_intfmode(config_word, val) \
@@ -190,9 +190,9 @@ typedef enum {
#define netxen_gb_set_mii_mgmt_clockselect(config_word, val) \
((config_word) |= ((val) & 0x07))
#define netxen_gb_mii_mgmt_reset(config_word) \
- set_bit(31, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 31)
#define netxen_gb_mii_mgmt_unset(config_word) \
- clear_bit(31, (unsigned long*)&config_word)
+ ((config_word) &= ~(1 << 31))
/*
* NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
@@ -201,7 +201,7 @@ typedef enum {
*/
#define netxen_gb_mii_mgmt_set_read_cycle(config_word) \
- set_bit(0, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 0)
#define netxen_gb_mii_mgmt_reg_addr(config_word, val) \
((config_word) |= ((val) & 0x1F))
#define netxen_gb_mii_mgmt_phy_addr(config_word, val) \
@@ -274,9 +274,9 @@ typedef enum {
#define netxen_set_phy_speed(config_word, val) \
((config_word) |= ((val & 0x03) << 14))
#define netxen_set_phy_duplex(config_word) \
- set_bit(13, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 13)
#define netxen_clear_phy_duplex(config_word) \
- clear_bit(13, (unsigned long*)&config_word)
+ ((config_word) &= ~(1 << 13))
#define netxen_get_phy_jabber(config_word) \
_netxen_crb_get_bit(config_word, 0)
@@ -350,11 +350,11 @@ typedef enum {
_netxen_crb_get_bit(config_word, 15)
#define netxen_set_phy_int_link_status_changed(config_word) \
- set_bit(10, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 10)
#define netxen_set_phy_int_autoneg_completed(config_word) \
- set_bit(11, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 11)
#define netxen_set_phy_int_speed_changed(config_word) \
- set_bit(14, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 14)
/*
* NIU Mode Register.
@@ -382,22 +382,22 @@ typedef enum {
*/
#define netxen_set_gb_drop_gb0(config_word) \
- set_bit(0, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 0)
#define netxen_set_gb_drop_gb1(config_word) \
- set_bit(1, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 1)
#define netxen_set_gb_drop_gb2(config_word) \
- set_bit(2, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 2)
#define netxen_set_gb_drop_gb3(config_word) \
- set_bit(3, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 3)
#define netxen_clear_gb_drop_gb0(config_word) \
- clear_bit(0, (unsigned long*)&config_word)
+ ((config_word) &= ~(1 << 0))
#define netxen_clear_gb_drop_gb1(config_word) \
- clear_bit(1, (unsigned long*)&config_word)
+ ((config_word) &= ~(1 << 1))
#define netxen_clear_gb_drop_gb2(config_word) \
- clear_bit(2, (unsigned long*)&config_word)
+ ((config_word) &= ~(1 << 2))
#define netxen_clear_gb_drop_gb3(config_word) \
- clear_bit(3, (unsigned long*)&config_word)
+ ((config_word) &= ~(1 << 3))
/*
* NIU XG MAC Config Register
@@ -413,7 +413,7 @@ typedef enum {
*/
#define netxen_xg_soft_reset(config_word) \
- set_bit(4, (unsigned long*)&config_word)
+ ((config_word) |= 1 << 4)
/*
* MAC Control Register
@@ -433,19 +433,19 @@ typedef enum {
#define netxen_nic_mcr_set_id_pool0(config, val) \
((config) |= ((val) &0x03))
#define netxen_nic_mcr_set_enable_xtnd0(config) \
- (set_bit(3, (unsigned long *)&(config)))
+ ((config) |= 1 << 3)
#define netxen_nic_mcr_set_id_pool1(config, val) \
((config) |= (((val) & 0x03) << 4))
#define netxen_nic_mcr_set_enable_xtnd1(config) \
- (set_bit(6, (unsigned long *)&(config)))
+ ((config) |= 1 << 6)
#define netxen_nic_mcr_set_id_pool2(config, val) \
((config) |= (((val) & 0x03) << 8))
#define netxen_nic_mcr_set_enable_xtnd2(config) \
- (set_bit(10, (unsigned long *)&(config)))
+ ((config) |= 1 << 10)
#define netxen_nic_mcr_set_id_pool3(config, val) \
((config) |= (((val) & 0x03) << 12))
#define netxen_nic_mcr_set_enable_xtnd3(config) \
- (set_bit(14, (unsigned long *)&(config)))
+ ((config) |= 1 << 14)
#define netxen_nic_mcr_set_mode_select(config, val) \
((config) |= (((val) & 0x03) << 24))
#define netxen_nic_mcr_set_enable_pool(config, val) \
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 869725f0bb1..973af96337a 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -35,7 +35,6 @@
#include <linux/delay.h>
#include "netxen_nic.h"
#include "netxen_nic_hw.h"
-#include "netxen_nic_ioctl.h"
#include "netxen_nic_phan_reg.h"
struct crb_addr_pair {
@@ -691,8 +690,7 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
desc_head = recv_ctx->rcv_status_desc_head;
desc = &desc_head[consumer];
- if (((le16_to_cpu(netxen_get_sts_owner(desc)))
- & STATUS_OWNER_HOST))
+ if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)
return 1;
}
@@ -788,11 +786,11 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)];
struct pci_dev *pdev = port->pdev;
struct net_device *netdev = port->netdev;
- int index = le16_to_cpu(netxen_get_sts_refhandle(desc));
+ int index = netxen_get_sts_refhandle(desc);
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
struct netxen_rx_buffer *buffer;
struct sk_buff *skb;
- u32 length = le16_to_cpu(netxen_get_sts_totallength(desc));
+ u32 length = netxen_get_sts_totallength(desc);
u32 desc_ctx;
struct netxen_rcv_desc_ctx *rcv_desc;
int ret;
@@ -919,9 +917,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
*/
while (count < max) {
desc = &desc_head[consumer];
- if (!
- (le16_to_cpu(netxen_get_sts_owner(desc)) &
- STATUS_OWNER_HOST)) {
+ if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) {
DPRINTK(ERR, "desc %p ownedby %x\n", desc,
netxen_get_sts_owner(desc));
break;
@@ -1023,7 +1019,7 @@ int netxen_process_cmd_ring(unsigned long data)
&& netif_carrier_ok(port->netdev))
&& ((jiffies - port->netdev->trans_start) >
port->netdev->watchdog_timeo)) {
- SCHEDULE_WORK(&port->adapter->tx_timeout_task);
+ SCHEDULE_WORK(&port->tx_timeout_task);
}
last_consumer = get_next_index(last_consumer,
@@ -1138,13 +1134,13 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
*/
dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
PCI_DMA_FROMDEVICE);
- pdesc->addr_buffer = dma;
+ pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = dma;
/* make a rcv descriptor */
- pdesc->reference_handle = buffer->ref_handle;
- pdesc->buffer_length = rcv_desc->dma_size;
+ pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
DPRINTK(INFO, "done writing descripter\n");
producer =
get_next_index(producer, rcv_desc->max_rx_desc_count);
@@ -1232,8 +1228,8 @@ void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx,
PCI_DMA_FROMDEVICE);
/* make a rcv descriptor */
- pdesc->reference_handle = le16_to_cpu(buffer->ref_handle);
- pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size);
+ pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+ pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
DPRINTK(INFO, "done writing descripter\n");
producer =
@@ -1273,52 +1269,6 @@ int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
return 0;
}
-int
-netxen_nic_fill_statistics(struct netxen_adapter *adapter,
- struct netxen_port *port,
- struct netxen_statistics *netxen_stats)
-{
- void __iomem *addr;
-
- if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_BYTE_CNT,
- &(netxen_stats->tx_bytes));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_FRAME_CNT,
- &(netxen_stats->tx_packets));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_BYTE_CNT,
- &(netxen_stats->rx_bytes));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_FRAME_CNT,
- &(netxen_stats->rx_packets));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_AGGR_ERROR_CNT,
- &(netxen_stats->rx_errors));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_CRC_ERROR_CNT,
- &(netxen_stats->rx_crc_errors));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
- &(netxen_stats->
- rx_long_length_error));
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
- &(netxen_stats->
- rx_short_length_error));
-
- netxen_nic_pci_change_crbwindow(adapter, 1);
- } else {
- spin_lock_bh(&adapter->tx_lock);
- netxen_stats->tx_bytes = port->stats.txbytes;
- netxen_stats->tx_packets = port->stats.xmitedframes +
- port->stats.xmitfinished;
- netxen_stats->rx_bytes = port->stats.rxbytes;
- netxen_stats->rx_packets = port->stats.no_rcv;
- netxen_stats->rx_errors = port->stats.rcvdbadskb;
- netxen_stats->tx_errors = port->stats.nocmddescriptor;
- netxen_stats->rx_short_length_error = port->stats.uplcong;
- netxen_stats->rx_long_length_error = port->stats.uphcong;
- netxen_stats->rx_crc_errors = 0;
- netxen_stats->rx_mac_errors = 0;
- spin_unlock_bh(&adapter->tx_lock);
- }
- return 0;
-}
void netxen_nic_clear_stats(struct netxen_adapter *adapter)
{
@@ -1332,193 +1282,3 @@ void netxen_nic_clear_stats(struct netxen_adapter *adapter)
}
}
-int
-netxen_nic_clear_statistics(struct netxen_adapter *adapter,
- struct netxen_port *port)
-{
- int data = 0;
-
- netxen_nic_pci_change_crbwindow(adapter, 0);
-
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_BYTE_CNT, &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_FRAME_CNT,
- &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_BYTE_CNT, &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_FRAME_CNT,
- &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_AGGR_ERROR_CNT,
- &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_CRC_ERROR_CNT,
- &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
- &data);
- netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
- &data);
-
- netxen_nic_pci_change_crbwindow(adapter, 1);
- netxen_nic_clear_stats(adapter);
- return 0;
-}
-
-int
-netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
- struct netxen_port *port)
-{
- struct netxen_nic_ioctl_data data;
- struct netxen_nic_ioctl_data *up_data;
- int retval = 0;
- struct netxen_statistics netxen_stats;
-
- up_data = (void *)u_data;
-
- DPRINTK(INFO, "doing ioctl for %p\n", adapter);
- if (copy_from_user(&data, (void __user *)up_data, sizeof(data))) {
- /* evil user tried to crash the kernel */
- DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data));
- retval = -EFAULT;
- goto error_out;
- }
-
- /* Shouldn't access beyond legal limits of "char u[64];" member */
- if (!data.ptr && (data.size > sizeof(data.u))) {
- /* evil user tried to crash the kernel */
- DPRINTK(ERR, "bad size: %d\n", data.size);
- retval = -EFAULT;
- goto error_out;
- }
-
- switch (data.cmd) {
- case netxen_nic_cmd_pci_read:
- if ((retval = netxen_nic_hw_read_ioctl(adapter, data.off,
- &(data.u), data.size)))
- goto error_out;
- if (copy_to_user
- ((void __user *)&(up_data->u), &(data.u), data.size)) {
- DPRINTK(ERR, "bad copy to userland: %d\n",
- (int)sizeof(data));
- retval = -EFAULT;
- goto error_out;
- }
- data.rv = 0;
- break;
-
- case netxen_nic_cmd_pci_write:
- if ((retval = netxen_nic_hw_write_ioctl(adapter, data.off,
- &(data.u), data.size)))
- goto error_out;
- data.rv = 0;
- break;
-
- case netxen_nic_cmd_pci_mem_read:
- if (netxen_nic_pci_mem_read_ioctl(adapter, data.off, &(data.u),
- data.size)) {
- DPRINTK(ERR, "Failed to read the data.\n");
- retval = -EFAULT;
- goto error_out;
- }
- if (copy_to_user
- ((void __user *)&(up_data->u), &(data.u), data.size)) {
- DPRINTK(ERR, "bad copy to userland: %d\n",
- (int)sizeof(data));
- retval = -EFAULT;
- goto error_out;
- }
- data.rv = 0;
- break;
-
- case netxen_nic_cmd_pci_mem_write:
- if ((retval = netxen_nic_pci_mem_write_ioctl(adapter, data.off,
- &(data.u),
- data.size)))
- goto error_out;
- data.rv = 0;
- break;
-
- case netxen_nic_cmd_pci_config_read:
- switch (data.size) {
- case 1:
- data.rv = pci_read_config_byte(adapter->ahw.pdev,
- data.off,
- (char *)&(data.u));
- break;
- case 2:
- data.rv = pci_read_config_word(adapter->ahw.pdev,
- data.off,
- (short *)&(data.u));
- break;
- case 4:
- data.rv = pci_read_config_dword(adapter->ahw.pdev,
- data.off,
- (u32 *) & (data.u));
- break;
- }
- if (copy_to_user
- ((void __user *)&(up_data->u), &(data.u), data.size)) {
- DPRINTK(ERR, "bad copy to userland: %d\n",
- (int)sizeof(data));
- retval = -EFAULT;
- goto error_out;
- }
- break;
-
- case netxen_nic_cmd_pci_config_write:
- switch (data.size) {
- case 1:
- data.rv = pci_write_config_byte(adapter->ahw.pdev,
- data.off,
- *(char *)&(data.u));
- break;
- case 2:
- data.rv = pci_write_config_word(adapter->ahw.pdev,
- data.off,
- *(short *)&(data.u));
- break;
- case 4:
- data.rv = pci_write_config_dword(adapter->ahw.pdev,
- data.off,
- *(u32 *) & (data.u));
- break;
- }
- break;
-
- case netxen_nic_cmd_get_stats:
- data.rv =
- netxen_nic_fill_statistics(adapter, port, &netxen_stats);
- if (copy_to_user
- ((void __user *)(up_data->ptr), (void *)&netxen_stats,
- sizeof(struct netxen_statistics))) {
- DPRINTK(ERR, "bad copy to userland: %d\n",
- (int)sizeof(netxen_stats));
- retval = -EFAULT;
- goto error_out;
- }
- up_data->rv = data.rv;
- break;
-
- case netxen_nic_cmd_clear_stats:
- data.rv = netxen_nic_clear_statistics(adapter, port);
- up_data->rv = data.rv;
- break;
-
- case netxen_nic_cmd_get_version:
- if (copy_to_user
- ((void __user *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID,
- sizeof(NETXEN_NIC_LINUX_VERSIONID))) {
- DPRINTK(ERR, "bad copy to userland: %d\n",
- (int)sizeof(data));
- retval = -EFAULT;
- goto error_out;
- }
- break;
-
- default:
- DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter);
- retval = -EOPNOTSUPP;
- goto error_out;
- }
- put_user(data.rv, (&(up_data->rv)));
- DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
-
- error_out:
- return retval;
-}
diff --git a/drivers/net/netxen/netxen_nic_ioctl.h b/drivers/net/netxen/netxen_nic_ioctl.h
deleted file mode 100644
index 1221fa52755..00000000000
--- a/drivers/net/netxen/netxen_nic_ioctl.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.
- *
- * Contact Information:
- * info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- */
-
-#ifndef __NETXEN_NIC_IOCTL_H__
-#define __NETXEN_NIC_IOCTL_H__
-
-#include <linux/sockios.h>
-
-#define NETXEN_CMD_START SIOCDEVPRIVATE
-#define NETXEN_NIC_CMD (NETXEN_CMD_START + 1)
-#define NETXEN_NIC_NAME (NETXEN_CMD_START + 2)
-#define NETXEN_NIC_NAME_LEN 16
-#define NETXEN_NIC_NAME_RSP "NETXEN-UNM"
-
-typedef enum {
- netxen_nic_cmd_none = 0,
- netxen_nic_cmd_pci_read,
- netxen_nic_cmd_pci_write,
- netxen_nic_cmd_pci_mem_read,
- netxen_nic_cmd_pci_mem_write,
- netxen_nic_cmd_pci_config_read,
- netxen_nic_cmd_pci_config_write,
- netxen_nic_cmd_get_stats,
- netxen_nic_cmd_clear_stats,
- netxen_nic_cmd_get_version
-} netxen_nic_ioctl_cmd_t;
-
-struct netxen_nic_ioctl_data {
- u32 cmd;
- u32 unused1;
- u64 off;
- u32 size;
- u32 rv;
- char u[64];
- void *ptr;
-};
-
-struct netxen_statistics {
- u64 rx_packets;
- u64 tx_packets;
- u64 rx_bytes;
- u64 rx_errors;
- u64 tx_bytes;
- u64 tx_errors;
- u64 rx_crc_errors;
- u64 rx_short_length_error;
- u64 rx_long_length_error;
- u64 rx_mac_errors;
-};
-
-#endif /* __NETXEN_NIC_IOCTL_H_ */
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
index 1b45f50fa6a..be366e48007 100644
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ b/drivers/net/netxen/netxen_nic_isr.c
@@ -79,7 +79,7 @@ void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno,
void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
u32 enable)
{
- __le32 int_src;
+ __u32 int_src;
struct netxen_port *port;
/* This should clear the interrupt source */
@@ -110,7 +110,7 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
/* write it down later.. */
if ((netxen_get_phy_int_speed_changed(int_src))
|| (netxen_get_phy_int_link_status_changed(int_src))) {
- __le32 status;
+ __u32 status;
DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
@@ -157,7 +157,8 @@ void netxen_nic_isr_other(struct netxen_adapter *adapter)
for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) {
linkup = val & 1;
if (linkup != (qg_linksup & 1)) {
- printk(KERN_INFO "%s: PORT %d link %s\n",
+ printk(KERN_INFO "%s: %s PORT %d link %s\n",
+ adapter->port[portno]->netdev->name,
netxen_nic_driver_name, portno,
((linkup == 0) ? "down" : "up"));
netxen_indicate_link_status(adapter, portno, linkup);
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 575b71b6720..69c1b9d23a1 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -38,7 +38,6 @@
#include "netxen_nic.h"
#define DEFINE_GLOBAL_RECV_CRB
#include "netxen_nic_phan_reg.h"
-#include "netxen_nic_ioctl.h"
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
@@ -53,8 +52,6 @@ char netxen_nic_driver_name[] = "netxen-nic";
static char netxen_nic_driver_string[] = "NetXen Network Driver version "
NETXEN_NIC_LINUX_VERSIONID;
-struct netxen_adapter *g_adapter = NULL;
-
#define NETXEN_NETDEV_WEIGHT 120
#define NETXEN_ADAPTER_UP_MAGIC 777
#define NETXEN_NIC_PEG_TUNE 0
@@ -75,8 +72,6 @@ static void netxen_tx_timeout(struct net_device *netdev);
static void netxen_tx_timeout_task(struct work_struct *work);
static void netxen_watchdog(unsigned long);
static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
-static int netxen_nic_ioctl(struct net_device *netdev,
- struct ifreq *ifr, int cmd);
static int netxen_nic_poll(struct net_device *dev, int *budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void netxen_nic_poll_controller(struct net_device *netdev);
@@ -90,6 +85,8 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
{PCI_DEVICE(0x4040, 0x0003)},
{PCI_DEVICE(0x4040, 0x0004)},
{PCI_DEVICE(0x4040, 0x0005)},
+ {PCI_DEVICE(0x4040, 0x0024)},
+ {PCI_DEVICE(0x4040, 0x0025)},
{0,}
};
@@ -120,7 +117,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *mem_ptr1 = NULL;
void __iomem *mem_ptr2 = NULL;
- u8 *db_ptr = NULL;
+ u8 __iomem *db_ptr = NULL;
unsigned long mem_base, mem_len, db_base, db_len;
int pci_using_dac, i, err;
int ring;
@@ -129,7 +126,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct netxen_cmd_buffer *cmd_buf_arr = NULL;
u64 mac_addr[FLASH_NUM_PORTS + 1];
int valid_mac = 0;
- static int netxen_cards_found = 0;
printk(KERN_INFO "%s \n", netxen_nic_driver_string);
/* In current scheme, we use only PCI function 0 */
@@ -195,7 +191,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
db_len);
db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
- if (db_ptr == 0UL) {
+ if (!db_ptr) {
printk(KERN_ERR "%s: Failed to allocate doorbell map.",
netxen_nic_driver_name);
err = -EIO;
@@ -220,9 +216,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_dbunmap;
}
- if (netxen_cards_found == 0) {
- g_adapter = adapter;
- }
adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS;
adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
@@ -383,7 +376,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->set_multicast_list = netxen_nic_set_multi;
netdev->set_mac_address = netxen_nic_set_mac;
netdev->change_mtu = netxen_nic_change_mtu;
- netdev->do_ioctl = netxen_nic_ioctl;
netdev->tx_timeout = netxen_tx_timeout;
netdev->watchdog_timeo = HZ;
@@ -428,8 +420,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->dev_addr);
}
}
- adapter->netdev = netdev;
- INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
+ INIT_WORK(&port->tx_timeout_task, netxen_tx_timeout_task);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -444,6 +435,11 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->port[i] = port;
}
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ netxen_pinit_from_rom(adapter, 0);
+ udelay(500);
+ netxen_load_firmware(adapter);
+ netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
/*
* delay a while to ensure that the Pegs are up & running.
* Otherwise, we might see some flaky behaviour.
@@ -461,7 +457,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- adapter->number = netxen_cards_found;
adapter->driver_mismatch = 0;
return 0;
@@ -531,6 +526,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netxen_nic_stop_all_ports(adapter);
/* leave the hw in the same state as reboot */
+ netxen_pinit_from_rom(adapter, 0);
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
netxen_load_firmware(adapter);
netxen_free_adapter_offload(adapter);
@@ -822,7 +819,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pbuf = &adapter->cmd_buf_arr[producer];
if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
pbuf->mss = skb_shinfo(skb)->gso_size;
- hwdesc->mss = skb_shinfo(skb)->gso_size;
+ hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
} else {
pbuf->mss = 0;
hwdesc->mss = 0;
@@ -885,7 +882,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
hwdesc->addr_buffer3 = cpu_to_le64(temp_dma);
break;
case 3:
- hwdesc->buffer4_length = temp_len;
+ hwdesc->buffer4_length = cpu_to_le16(temp_len);
hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
break;
}
@@ -956,11 +953,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
static void netxen_watchdog(unsigned long v)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)v;
- if (adapter != g_adapter) {
- printk("%s: ***BUG*** adapter[%p] != g_adapter[%p]\n",
- __FUNCTION__, adapter, g_adapter);
- return;
- }
SCHEDULE_WORK(&adapter->watchdog_task);
}
@@ -969,23 +961,23 @@ static void netxen_tx_timeout(struct net_device *netdev)
{
struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
- SCHEDULE_WORK(&port->adapter->tx_timeout_task);
+ SCHEDULE_WORK(&port->tx_timeout_task);
}
static void netxen_tx_timeout_task(struct work_struct *work)
{
- struct netxen_adapter *adapter =
- container_of(work, struct netxen_adapter, tx_timeout_task);
- struct net_device *netdev = adapter->netdev;
+ struct netxen_port *port =
+ container_of(work, struct netxen_port, tx_timeout_task);
+ struct net_device *netdev = port->netdev;
unsigned long flags;
printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
netxen_nic_driver_name, netdev->name);
- spin_lock_irqsave(&adapter->lock, flags);
+ spin_lock_irqsave(&port->adapter->lock, flags);
netxen_nic_close(netdev);
netxen_nic_open(netdev);
- spin_unlock_irqrestore(&adapter->lock, flags);
+ spin_unlock_irqrestore(&port->adapter->lock, flags);
netdev->trans_start = jiffies;
netif_wake_queue(netdev);
}
@@ -1137,47 +1129,6 @@ static void netxen_nic_poll_controller(struct net_device *netdev)
enable_irq(adapter->irq);
}
#endif
-/*
- * netxen_nic_ioctl () We provide the tcl/phanmon support through these
- * ioctls.
- */
-static int
-netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
- int err = 0;
- unsigned long nr_bytes = 0;
- struct netxen_port *port = netdev_priv(netdev);
- struct netxen_adapter *adapter = port->adapter;
- char dev_name[NETXEN_NIC_NAME_LEN];
-
- DPRINTK(INFO, "doing ioctl for %s\n", netdev->name);
- switch (cmd) {
- case NETXEN_NIC_CMD:
- err = netxen_nic_do_ioctl(adapter, (void *)ifr->ifr_data, port);
- break;
-
- case NETXEN_NIC_NAME:
- DPRINTK(INFO, "ioctl cmd for NetXen\n");
- if (ifr->ifr_data) {
- sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP,
- port->portnum);
- nr_bytes =
- copy_to_user((char __user *)ifr->ifr_data, dev_name,
- NETXEN_NIC_NAME_LEN);
- if (nr_bytes)
- err = -EIO;
-
- }
- break;
-
- default:
- DPRINTK(INFO, "ioctl cmd %x not supported\n", cmd);
- err = -EOPNOTSUPP;
- break;
- }
-
- return err;
-}
static struct pci_driver netxen_driver = {
.name = netxen_nic_driver_name,
@@ -1193,7 +1144,7 @@ static int __init netxen_init_module(void)
if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0)
return -ENOMEM;
- return pci_module_init(&netxen_driver);
+ return pci_register_driver(&netxen_driver);
}
module_init(netxen_init_module);
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 4987dc765d9..40d7003a371 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -89,15 +89,15 @@ static inline int phy_unlock(struct netxen_adapter *adapter)
*
*/
int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
- long reg, __le32 * readval)
+ long reg, __u32 * readval)
{
long timeout = 0;
long result = 0;
long restore = 0;
- __le32 address;
- __le32 command;
- __le32 status;
- __le32 mac_cfg0;
+ __u32 address;
+ __u32 command;
+ __u32 status;
+ __u32 mac_cfg0;
if (phy_lock(adapter) != 0) {
return -1;
@@ -112,7 +112,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
- __le32 temp;
+ __u32 temp;
temp = 0;
netxen_gb_tx_reset_pb(temp);
netxen_gb_rx_reset_pb(temp);
@@ -184,15 +184,15 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
*
*/
int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
- long phy, long reg, __le32 val)
+ long phy, long reg, __u32 val)
{
long timeout = 0;
long result = 0;
long restore = 0;
- __le32 address;
- __le32 command;
- __le32 status;
- __le32 mac_cfg0;
+ __u32 address;
+ __u32 command;
+ __u32 status;
+ __u32 mac_cfg0;
/*
* MII mgmt all goes through port 0 MAC interface, so it
@@ -203,7 +203,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
- __le32 temp;
+ __u32 temp;
temp = 0;
netxen_gb_tx_reset_pb(temp);
netxen_gb_rx_reset_pb(temp);
@@ -269,7 +269,7 @@ int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
int port)
{
int result = 0;
- __le32 enable = 0;
+ __u32 enable = 0;
netxen_set_phy_int_link_status_changed(enable);
netxen_set_phy_int_autoneg_completed(enable);
netxen_set_phy_int_speed_changed(enable);
@@ -402,7 +402,7 @@ void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
{
int result = 0;
- __le32 status;
+ __u32 status;
if (adapter->disable_phy_interrupts)
adapter->disable_phy_interrupts(adapter, port);
mdelay(2);
@@ -410,7 +410,7 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
if (0 ==
netxen_niu_gbe_phy_read(adapter, port,
NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
- (__le32 *) & status)) {
+ &status)) {
if (netxen_get_phy_link(status)) {
if (netxen_get_phy_speed(status) == 2) {
netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
@@ -489,7 +489,7 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
int port, long enable)
{
int result = 0;
- __le32 int_src;
+ __u32 int_src;
printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
" (device enable = %d)\n", (int)port, (int)enable);
@@ -530,7 +530,7 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
printk(KERN_INFO PFX "autoneg_error ");
if ((netxen_get_phy_int_speed_changed(int_src))
|| (netxen_get_phy_int_link_status_changed(int_src))) {
- __le32 status;
+ __u32 status;
printk(KERN_INFO PFX
"speed_changed or link status changed");
@@ -583,9 +583,9 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
int phy, netxen_ethernet_macaddr_t * addr)
{
- u64 result = 0;
- __le32 stationhigh;
- __le32 stationlow;
+ u32 stationhigh;
+ u32 stationlow;
+ u8 val[8];
if (addr == NULL)
return -EINVAL;
@@ -598,10 +598,10 @@ int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
&stationlow, 4))
return -EIO;
+ ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
+ ((__le32 *)val)[0] = cpu_to_le32(stationlow);
- result = (u64) netxen_gb_get_stationaddress_low(stationlow);
- result |= (u64) stationhigh << 16;
- memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+ memcpy(addr, val + 2, 6);
return 0;
}
@@ -613,24 +613,25 @@ int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
int netxen_niu_macaddr_set(struct netxen_port *port,
netxen_ethernet_macaddr_t addr)
{
- __le32 temp = 0;
+ u8 temp[4];
+ u32 val;
struct netxen_adapter *adapter = port->adapter;
int phy = port->portnum;
unsigned char mac_addr[6];
int i;
for (i = 0; i < 10; i++) {
- memcpy(&temp, addr, 2);
- temp <<= 16;
+ temp[0] = temp[1] = 0;
+ memcpy(temp + 2, addr, 2);
+ val = le32_to_cpu(*(__le32 *)temp);
if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &temp, 4))
+ (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
return -EIO;
- temp = 0;
-
- memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
+ memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
+ val = le32_to_cpu(*(__le32 *)temp);
if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &temp, 4))
+ (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
return -2;
netxen_niu_macaddr_get(adapter, phy,
@@ -659,9 +660,9 @@ int netxen_niu_macaddr_set(struct netxen_port *port,
int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
int port, netxen_niu_gbe_ifmode_t mode)
{
- __le32 mac_cfg0;
- __le32 mac_cfg1;
- __le32 mii_cfg;
+ __u32 mac_cfg0;
+ __u32 mac_cfg1;
+ __u32 mii_cfg;
if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
return -EINVAL;
@@ -736,7 +737,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
/* Disable a GbE interface */
int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port)
{
- __le32 mac_cfg0;
+ __u32 mac_cfg0;
if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
return -EINVAL;
@@ -752,7 +753,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port)
/* Disable an XG interface */
int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port)
{
- __le32 mac_cfg;
+ __u32 mac_cfg;
if (port != 0)
return -EINVAL;
@@ -769,7 +770,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port)
int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
netxen_niu_prom_mode_t mode)
{
- __le32 reg;
+ __u32 reg;
if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
return -EINVAL;
@@ -826,22 +827,21 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
int netxen_niu_xg_macaddr_set(struct netxen_port *port,
netxen_ethernet_macaddr_t addr)
{
- __le32 temp = 0;
+ u8 temp[4];
+ u32 val;
struct netxen_adapter *adapter = port->adapter;
- memcpy(&temp, addr, 2);
- temp = cpu_to_le32(temp);
- temp <<= 16;
+ temp[0] = temp[1] = 0;
+ memcpy(temp + 2, addr, 2);
+ val = le32_to_cpu(*(__le32 *)temp);
if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
- &temp, 4))
+ &val, 4))
return -EIO;
- temp = 0;
-
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
- temp = cpu_to_le32(temp);
+ val = le32_to_cpu(*(__le32 *)temp);
if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
- &temp, 4))
+ &val, 4))
return -EIO;
return 0;
@@ -854,9 +854,9 @@ int netxen_niu_xg_macaddr_set(struct netxen_port *port,
int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
netxen_ethernet_macaddr_t * addr)
{
- __le32 stationhigh;
- __le32 stationlow;
- u64 result;
+ u32 stationhigh;
+ u32 stationlow;
+ u8 val[8];
if (addr == NULL)
return -EINVAL;
@@ -869,10 +869,10 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&stationlow, 4))
return -EIO;
+ ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
+ ((__le32 *)val)[0] = cpu_to_le32(stationlow);
- result = ((u64) stationlow) >> 16;
- result |= (u64) stationhigh << 16;
- memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+ memcpy(addr, val + 2, 6);
return 0;
}
@@ -880,7 +880,7 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
int port, netxen_niu_prom_mode_t mode)
{
- __le32 reg;
+ __u32 reg;
if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
return -EINVAL;
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 794cc61819d..448bf4a7801 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -281,7 +281,6 @@ static int tc574_probe(struct pcmcia_device *link)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
/* The EL3-specific entries in the device structure. */
dev->hard_start_xmit = &el3_start_xmit;
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 1e73ff7d5d8..461e8274ef6 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -195,7 +195,6 @@ static int tc589_probe(struct pcmcia_device *link)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
/* The EL3-specific entries in the device structure. */
SET_MODULE_OWNER(dev);
@@ -607,11 +606,14 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
kio_addr_t ioaddr = dev->base_addr;
struct el3_private *priv = netdev_priv(dev);
+ unsigned long flags;
DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
"status %4.4x.\n", dev->name, (long)skb->len,
inw(ioaddr + EL3_STATUS));
+ spin_lock_irqsave(&priv->lock, flags);
+
priv->stats.tx_bytes += skb->len;
/* Put out the doubleword header... */
@@ -629,6 +631,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
pop_tx_status(dev);
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
@@ -730,14 +733,13 @@ static void media_check(unsigned long arg)
if (!netif_device_present(dev)) goto reschedule;
- EL3WINDOW(1);
/* Check for pending interrupt with expired latency timer: with
this, we can limp along even if the interrupt is blocked */
if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
(inb(ioaddr + EL3_TIMER) == 0xff)) {
if (!lp->fast_poll)
printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
- el3_interrupt(dev->irq, lp);
+ el3_interrupt(dev->irq, dev);
lp->fast_poll = HZ;
}
if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 91f65e91cd5..0d1c7a41c9c 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -173,7 +173,6 @@ static int com20020_probe(struct pcmcia_device *p_dev)
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->conf.Attributes = CONF_ENABLE_IRQ;
p_dev->conf.IntType = INT_MEMORY_AND_IO;
- p_dev->conf.Present = PRESENT_OPTION;
p_dev->irq.Instance = info->dev = dev;
p_dev->priv = info;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 2b1238e2dbd..d88e9b2e93c 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1617,6 +1617,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
@@ -1667,6 +1668,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
+ PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 8478dca3d8d..5879e7c3698 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -576,7 +576,6 @@ xirc2ps_probe(struct pcmcia_device *link)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
link->irq.Handler = xirc2ps_interrupt;
link->irq.Instance = dev;
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 096d4a100bf..86135397f43 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -349,7 +349,7 @@ static int __init fixed_init(void)
fixed_mdio_register_device(0, 100, 1);
#endif
-#ifdef CONFIX_FIXED_MII_10_FDX
+#ifdef CONFIG_FIXED_MII_10_FDX
fixed_mdio_register_device(0, 10, 1);
#endif
return 0;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index e175f3910b1..9765fa66146 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -286,6 +286,7 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
return 0;
}
+EXPORT_SYMBOL(phy_ethtool_sset);
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
{
@@ -302,7 +303,7 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
return 0;
}
-
+EXPORT_SYMBOL(phy_ethtool_gset);
/* Note that this function is currently incompatible with the
* PHYCONTROL layer. It changes registers without regard to
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index b01fc70a57d..a4d7529ef41 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -50,7 +50,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
struct phy_device *dev;
/* We allocate the device, and initialize the
* default values */
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (NULL == dev)
return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
index f54c55242f4..72c8d6628f5 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp_deflate.c
@@ -121,7 +121,7 @@ static void *z_comp_alloc(unsigned char *options, int opt_len)
if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
return NULL;
- state = (struct ppp_deflate_state *) kmalloc(sizeof(*state),
+ state = kmalloc(sizeof(*state),
GFP_KERNEL);
if (state == NULL)
return NULL;
@@ -341,7 +341,7 @@ static void *z_decomp_alloc(unsigned char *options, int opt_len)
if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
return NULL;
- state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
return NULL;
diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c
index f3655fd772f..d5bdd257465 100644
--- a/drivers/net/ppp_mppe.c
+++ b/drivers/net/ppp_mppe.c
@@ -200,7 +200,7 @@ static void *mppe_alloc(unsigned char *options, int optlen)
|| options[0] != CI_MPPE || options[1] != CILEN_MPPE)
goto out;
- state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
goto out;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d79d141a601..8844c20eac2 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -208,6 +208,15 @@ static void ql_write_common_reg(struct ql3_adapter *qdev,
return;
}
+static void ql_write_nvram_reg(struct ql3_adapter *qdev,
+ u32 __iomem *reg, u32 value)
+{
+ writel(value, reg);
+ readl(reg);
+ udelay(1);
+ return;
+}
+
static void ql_write_page0_reg(struct ql3_adapter *qdev,
u32 __iomem *reg, u32 value)
{
@@ -336,9 +345,9 @@ static void fm93c56a_select(struct ql3_adapter *qdev)
qdev->mem_map_registers;
qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1;
- ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+ ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
- ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+ ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
((ISP_NVRAM_MASK << 16) | qdev->eeprom_cmd_data));
}
@@ -355,14 +364,14 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr)
qdev->mem_map_registers;
/* Clock in a zero, then do the start bit */
- ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+ ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
AUBURN_EEPROM_DO_1);
- ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+ ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
AUBURN_EEPROM_CLK_RISE);
- ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+ ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
AUBURN_EEPROM_CLK_FALL);
@@ -378,20 +387,20 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr)
* If the bit changed, then change the DO state to
* match
*/
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
eeprom_cmd_data | dataBit);
previousBit = dataBit;
}
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
eeprom_cmd_data | dataBit |
AUBURN_EEPROM_CLK_RISE);
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
@@ -412,20 +421,20 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr)
* If the bit changed, then change the DO state to
* match
*/
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
eeprom_cmd_data | dataBit);
previousBit = dataBit;
}
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
eeprom_cmd_data | dataBit |
AUBURN_EEPROM_CLK_RISE);
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->
@@ -443,7 +452,7 @@ static void fm93c56a_deselect(struct ql3_adapter *qdev)
struct ql3xxx_port_registers __iomem *port_regs =
qdev->mem_map_registers;
qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0;
- ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+ ql_write_nvram_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
}
@@ -461,12 +470,12 @@ static void fm93c56a_datain(struct ql3_adapter *qdev, unsigned short *value)
/* Read the data bits */
/* The first bit is a dummy. Clock right over it. */
for (i = 0; i < dataBits; i++) {
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
AUBURN_EEPROM_CLK_RISE);
- ql_write_common_reg(qdev,
+ ql_write_nvram_reg(qdev,
&port_regs->CommonRegs.
serialPortInterfaceReg,
ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
@@ -3370,7 +3379,6 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, &pdev->dev);
- ndev->features = NETIF_F_LLTX;
if (pci_using_dac)
ndev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index f83b41d4cb0..577babd4c93 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -225,7 +225,6 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
static int rx_copybreak = 200;
static int use_dac;
-static int ignore_parity_err;
static struct {
u32 msg_enable;
} debug = { -1 };
@@ -471,8 +470,6 @@ module_param(use_dac, int, 0);
MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
module_param_named(debug, debug.msg_enable, int, 0);
MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
-module_param_named(ignore_parity_err, ignore_parity_err, bool, 0);
-MODULE_PARM_DESC(ignore_parity_err, "Ignore PCI parity error as target. Default: false");
MODULE_LICENSE("GPL");
MODULE_VERSION(RTL8169_VERSION);
@@ -1885,7 +1882,6 @@ static void rtl8169_hw_start(struct net_device *dev)
(tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03) ||
(tp->mac_version == RTL_GIGA_MAC_VER_04))
- RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
rtl8169_set_rx_tx_config_registers(tp);
cmd = RTL_R16(CPlusCmd);
@@ -2388,7 +2384,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
*
* Feel free to adjust to your needs.
*/
- if (ignore_parity_err)
+ if (pdev->broken_parity_status)
pci_cmd &= ~PCI_COMMAND_PARITY;
else
pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 250cdbeefdf..1dd66b8ea0f 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -556,10 +556,9 @@ static int init_shared_mem(struct s2io_nic *nic)
}
}
- nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL);
+ nic->ufo_in_band_v = kcalloc(size, sizeof(u64), GFP_KERNEL);
if (!nic->ufo_in_band_v)
return -ENOMEM;
- memset(nic->ufo_in_band_v, 0, size);
/* Allocation and initialization of RXDs in Rings */
size = 0;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index b70ed79d412..45d91b15910 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1562,7 +1562,7 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
__le16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
- ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
+ ((u16 *)dev->dev_addr)[i] = le16_to_cpu(w);
}
sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index b60f0451f6c..45283f3f95e 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -60,7 +60,7 @@
#define LINK_HZ (HZ/2)
MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
@@ -749,7 +749,7 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)
struct skge_element *e;
int i;
- ring->start = kcalloc(sizeof(*e), ring->count, GFP_KERNEL);
+ ring->start = kcalloc(ring->count, sizeof(*e), GFP_KERNEL);
if (!ring->start)
return -ENOMEM;
@@ -2920,6 +2920,7 @@ static int skge_poll(struct net_device *dev, int *budget)
struct skge_hw *hw = skge->hw;
struct skge_ring *ring = &skge->rx_ring;
struct skge_element *e;
+ unsigned long flags;
int to_do = min(dev->quota, *budget);
int work_done = 0;
@@ -2957,12 +2958,12 @@ static int skge_poll(struct net_device *dev, int *budget)
if (work_done >= to_do)
return 1; /* not done */
- spin_lock_irq(&hw->hw_lock);
+ spin_lock_irqsave(&hw->hw_lock, flags);
__netif_rx_complete(dev);
hw->intr_mask |= irqmask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
skge_read32(hw, B0_IMSK);
- spin_unlock_irq(&hw->hw_lock);
+ spin_unlock_irqrestore(&hw->hw_lock, flags);
return 0;
}
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index fb1d2c30c1b..822dd0b1313 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -569,8 +569,8 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
onoff = !onoff;
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-
if (onoff)
/* Turn off phy power saving */
reg1 &= ~phy_power[port];
@@ -579,6 +579,7 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
sky2_pci_read32(hw, PCI_DEV_REG1);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
udelay(100);
}
@@ -1511,6 +1512,13 @@ static int sky2_down(struct net_device *dev)
imask &= ~portirq_msk[port];
sky2_write32(hw, B0_IMSK, imask);
+ /*
+ * Both ports share the NAPI poll on port 0, so if necessary undo the
+ * the disable that is done in dev_close.
+ */
+ if (sky2->port == 0 && hw->ports > 1)
+ netif_poll_enable(dev);
+
sky2_gmac_reset(hw, port);
/* Stop transmitter */
@@ -3658,6 +3666,6 @@ module_init(sky2_init_module);
module_exit(sky2_cleanup_module);
MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver");
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 39c2152a07f..a0806d262fc 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -229,10 +229,10 @@ static int sl_realloc_bufs(struct slip *sl, int mtu)
if (len < 576 * 2)
len = 576 * 2;
- xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
- rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+ xbuff = kmalloc(len + 4, GFP_ATOMIC);
+ rbuff = kmalloc(len + 4, GFP_ATOMIC);
#ifdef SL_INCLUDE_CSLIP
- cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+ cbuff = kmalloc(len + 4, GFP_ATOMIC);
#endif
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 2c4343395a4..43af6143844 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -148,6 +148,8 @@ struct smc911x_local {
int tx_throttle;
spinlock_t lock;
+ struct net_device *netdev;
+
#ifdef SMC_USE_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
@@ -948,10 +950,11 @@ static void smc911x_phy_check_media(struct net_device *dev, int init)
* of autonegotiation.) If the RPC ANEG bit is cleared, the selection
* is controlled by the RPC SPEED and RPC DPLX bits.
*/
-static void smc911x_phy_configure(void *data)
+static void smc911x_phy_configure(struct work_struct *work)
{
- struct net_device *dev = data;
- struct smc911x_local *lp = netdev_priv(dev);
+ struct smc911x_local *lp = container_of(work, struct smc911x_local,
+ phy_configure);
+ struct net_device *dev = lp->netdev;
unsigned long ioaddr = dev->base_addr;
int phyaddr = lp->mii.phy_id;
int my_phy_caps; /* My PHY capabilities */
@@ -965,11 +968,11 @@ static void smc911x_phy_configure(void *data)
* We should not be called if phy_type is zero.
*/
if (lp->phy_type == 0)
- goto smc911x_phy_configure_exit;
+ goto smc911x_phy_configure_exit_nolock;
if (smc911x_phy_reset(dev, phyaddr)) {
printk("%s: PHY reset timed out\n", dev->name);
- goto smc911x_phy_configure_exit;
+ goto smc911x_phy_configure_exit_nolock;
}
spin_lock_irqsave(&lp->lock, flags);
@@ -1038,6 +1041,7 @@ static void smc911x_phy_configure(void *data)
smc911x_phy_configure_exit:
spin_unlock_irqrestore(&lp->lock, flags);
+smc911x_phy_configure_exit_nolock:
lp->work_pending = 0;
}
@@ -1331,7 +1335,7 @@ smc911x_rx_dma_irq(int dma, void *data)
static void smc911x_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
- smc911x_interrupt(dev->irq, dev, NULL);
+ smc911x_interrupt(dev->irq, dev);
enable_irq(dev->irq);
}
#endif
@@ -1495,6 +1499,8 @@ static void smc911x_set_multicast_list(struct net_device *dev)
static int
smc911x_open(struct net_device *dev)
{
+ struct smc911x_local *lp = netdev_priv(dev);
+
DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
/*
@@ -1511,7 +1517,7 @@ smc911x_open(struct net_device *dev)
smc911x_reset(dev);
/* Configure the PHY, initialize the link state */
- smc911x_phy_configure(dev);
+ smc911x_phy_configure(&lp->phy_configure);
/* Turn on Tx + Rx */
smc911x_enable(dev);
@@ -2060,7 +2066,7 @@ static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr)
dev->poll_controller = smc911x_poll_controller;
#endif
- INIT_WORK(&lp->phy_configure, smc911x_phy_configure, dev);
+ INIT_WORK(&lp->phy_configure, smc911x_phy_configure);
lp->mii.phy_id_mask = 0x1f;
lp->mii.reg_num_mask = 0x1f;
lp->mii.force_media = 0;
@@ -2154,6 +2160,7 @@ static int smc911x_drv_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct resource *res;
+ struct smc911x_local *lp;
unsigned int *addr;
int ret;
@@ -2183,6 +2190,8 @@ static int smc911x_drv_probe(struct platform_device *pdev)
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);
+ lp = netdev_priv(ndev);
+ lp->netdev = ndev;
addr = ioremap(res->start, SMC911X_IO_EXTENT);
if (!addr) {
@@ -2204,7 +2213,6 @@ out:
}
#ifdef SMC_USE_DMA
else {
- struct smc911x_local *lp = netdev_priv(ndev);
lp->physaddr = res->start;
lp->dev = &pdev->dev;
}
@@ -2275,7 +2283,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
smc911x_reset(ndev);
smc911x_enable(ndev);
if (lp->phy_type != 0)
- smc911x_phy_configure(ndev);
+ smc911x_phy_configure(&lp->phy_configure);
netif_device_attach(ndev);
}
}
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 9367c574477..d2767e6584a 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -362,96 +362,6 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#define SMC_IRQ_FLAGS (0)
-#elif defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 1
-#define SMC_NOWAIT 1
-
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_inl(a, r) readl((a) + (r))
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (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)
-
-#define SMC_IRQ_FLAGS (0)
-
-#elif defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 1
-#define SMC_NOWAIT 1
-
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_inl(a, r) readl((a) + (r))
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (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)
-
-#define SMC_IRQ_FLAGS (0)
-
-#elif defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 1
-#define SMC_NOWAIT 1
-
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_inl(a, r) readl((a) + (r))
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (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)
-
-#define SMC_IRQ_FLAGS (0)
-
-#elif defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 1
-#define SMC_NOWAIT 1
-
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_inl(a, r) readl((a) + (r))
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (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)
-
-#define SMC_IRQ_FLAGS (0)
-
-#elif defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 1
-#define SMC_NOWAIT 1
-
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_inl(a, r) readl((a) + (r))
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (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)
-
-#define SMC_IRQ_FLAGS (0)
-
#else
#define SMC_CAN_USE_8BIT 1
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index ebb6aa39f9c..8ea2fc1b96c 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1925,6 +1925,8 @@ spider_net_stop(struct net_device *netdev)
/* release chains */
spider_net_release_tx_chain(card, 1);
+ spider_net_free_rx_chain_contents(card);
+
spider_net_free_chain(card, &card->tx_chain);
spider_net_free_chain(card, &card->rx_chain);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 785e4a535f9..616be8d0fa8 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -90,7 +90,8 @@
#define ADVERTISE_MASK (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full | \
+ SUPPORTED_Pause | SUPPORTED_Autoneg)
#define DRV_NAME "sungem"
#define DRV_VERSION "0.98"
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 49800b25907..d21991ee88c 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -3,10 +3,9 @@
*
* This file could be shared with other drivers.
*
- * (c) 2002, Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org)
*
* TODO:
- * - Implement WOL
* - Add support for PHYs that provide an IRQ line
* - Eventually moved the entire polling state machine in
* there (out of the eth driver), so that it can easily be
@@ -152,6 +151,44 @@ static int bcm5221_suspend(struct mii_phy* phy)
return 0;
}
+static int bcm5241_init(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_STAT2);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
+ data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+ data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ return 0;
+}
+
+static int bcm5241_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_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
+
+ return 0;
+}
+
static int bcm5400_init(struct mii_phy* phy)
{
u16 data;
@@ -373,6 +410,10 @@ static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
phy_write(phy, MII_ADVERTISE, adv);
/* Setup 1000BT advertise */
@@ -436,12 +477,15 @@ static int bcm54xx_read_link(struct mii_phy *phy)
val = phy_read(phy, MII_BCM5400_AUXSTATUS);
link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
- phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
+ phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
+ DUPLEX_FULL : DUPLEX_HALF;
phy->speed = phy_BCM5400_link_table[link_mode][2] ?
SPEED_1000 :
- (phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
+ (phy_BCM5400_link_table[link_mode][1] ?
+ SPEED_100 : SPEED_10);
val = phy_read(phy, MII_LPA);
- phy->pause = ((val & LPA_PAUSE) != 0);
+ phy->pause = (phy->duplex == DUPLEX_FULL) &&
+ ((val & LPA_PAUSE) != 0);
}
/* On non-aneg, we assume what we put in BMCR is the speed,
* though magic-aneg shouldn't prevent this case from occurring
@@ -450,6 +494,28 @@ static int bcm54xx_read_link(struct mii_phy *phy)
return 0;
}
+static int marvell88e1111_init(struct mii_phy* phy)
+{
+ u16 rev;
+
+ /* magic init sequence for rev 0 */
+ rev = phy_read(phy, MII_PHYSID2) & 0x000f;
+ if (rev == 0) {
+ phy_write(phy, 0x1d, 0x000a);
+ phy_write(phy, 0x1e, 0x0821);
+
+ phy_write(phy, 0x1d, 0x0006);
+ phy_write(phy, 0x1e, 0x8600);
+
+ phy_write(phy, 0x1d, 0x000b);
+ phy_write(phy, 0x1e, 0x0100);
+
+ phy_write(phy, 0x1d, 0x0004);
+ phy_write(phy, 0x1e, 0x4850);
+ }
+ return 0;
+}
+
static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
{
u16 ctl, adv;
@@ -471,6 +537,10 @@ static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
phy_write(phy, MII_ADVERTISE, adv);
/* Setup 1000BT advertise & enable crossover detect
@@ -549,7 +619,7 @@ static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
static int marvell_read_link(struct mii_phy *phy)
{
- u16 status;
+ u16 status, pmask;
if (phy->autoneg) {
status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
@@ -565,7 +635,9 @@ static int marvell_read_link(struct mii_phy *phy)
phy->duplex = DUPLEX_FULL;
else
phy->duplex = DUPLEX_HALF;
- phy->pause = 0; /* XXX Check against spec ! */
+ pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE |
+ MII_M1011_PHY_SPEC_STATUS_RX_PAUSE;
+ phy->pause = (status & pmask) == pmask;
}
/* On non-aneg, we assume what we put in BMCR is the speed,
* though magic-aneg shouldn't prevent this case from occurring
@@ -595,6 +667,10 @@ static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
+ if (advertise & ADVERTISED_Pause)
+ adv |= ADVERTISE_PAUSE_CAP;
+ if (advertise & ADVERTISED_Asym_Pause)
+ adv |= ADVERTISE_PAUSE_ASYM;
phy_write(phy, MII_ADVERTISE, adv);
/* Start/Restart aneg */
@@ -666,7 +742,8 @@ static int genmii_read_link(struct mii_phy *phy)
phy->speed = SPEED_100;
else
phy->speed = SPEED_10;
- phy->pause = 0;
+ phy->pause = (phy->duplex == DUPLEX_FULL) &&
+ ((lpa & LPA_PAUSE) != 0);
}
/* On non-aneg, we assume what we put in BMCR is the speed,
* though magic-aneg shouldn't prevent this case from occurring
@@ -676,11 +753,19 @@ static int genmii_read_link(struct mii_phy *phy)
}
-#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
-#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
- SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
+#define MII_BASIC_FEATURES \
+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | \
+ SUPPORTED_Pause)
+
+/* On gigabit capable PHYs, we advertise Pause support but not asym pause
+ * support for now as I'm not sure it's supported and Darwin doesn't do
+ * it neither. --BenH.
+ */
+#define MII_GBIT_FEATURES \
+ (MII_BASIC_FEATURES | \
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
/* Broadcom BCM 5201 */
static struct mii_phy_ops bcm5201_phy_ops = {
@@ -720,6 +805,24 @@ static struct mii_phy_def bcm5221_phy_def = {
.ops = &bcm5221_phy_ops
};
+/* Broadcom BCM 5241 */
+static struct mii_phy_ops bcm5241_phy_ops = {
+ .suspend = bcm5241_suspend,
+ .init = bcm5241_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link,
+};
+static struct mii_phy_def bcm5241_phy_def = {
+ .phy_id = 0x0143bc30,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5241",
+ .features = MII_BASIC_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5241_phy_ops
+};
+
/* Broadcom BCM 5400 */
static struct mii_phy_ops bcm5400_phy_ops = {
.init = bcm5400_init,
@@ -854,11 +957,8 @@ static struct mii_phy_def bcm5462V_phy_def = {
.ops = &bcm5462V_phy_ops
};
-/* Marvell 88E1101 (Apple seem to deal with 2 different revs,
- * I masked out the 8 last bits to get both, but some specs
- * would be useful here) --BenH.
- */
-static struct mii_phy_ops marvell_phy_ops = {
+/* Marvell 88E1101 amd 88E1111 */
+static struct mii_phy_ops marvell88e1101_phy_ops = {
.suspend = generic_suspend,
.setup_aneg = marvell_setup_aneg,
.setup_forced = marvell_setup_forced,
@@ -866,13 +966,41 @@ static struct mii_phy_ops marvell_phy_ops = {
.read_link = marvell_read_link
};
-static struct mii_phy_def marvell_phy_def = {
- .phy_id = 0x01410c00,
- .phy_id_mask = 0xffffff00,
- .name = "Marvell 88E1101",
+static struct mii_phy_ops marvell88e1111_phy_ops = {
+ .init = marvell88e1111_init,
+ .suspend = generic_suspend,
+ .setup_aneg = marvell_setup_aneg,
+ .setup_forced = marvell_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = marvell_read_link
+};
+
+/* two revs in darwin for the 88e1101 ... I could use a datasheet
+ * to get the proper names...
+ */
+static struct mii_phy_def marvell88e1101v1_phy_def = {
+ .phy_id = 0x01410c20,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101v1",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &marvell88e1101_phy_ops
+};
+static struct mii_phy_def marvell88e1101v2_phy_def = {
+ .phy_id = 0x01410c60,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101v2",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &marvell88e1101_phy_ops
+};
+static struct mii_phy_def marvell88e1111_phy_def = {
+ .phy_id = 0x01410cc0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1111",
.features = MII_GBIT_FEATURES,
.magic_aneg = 1,
- .ops = &marvell_phy_ops
+ .ops = &marvell88e1111_phy_ops
};
/* Generic implementation for most 10/100 PHYs */
@@ -895,6 +1023,7 @@ static struct mii_phy_def genmii_phy_def = {
static struct mii_phy_def* mii_phy_table[] = {
&bcm5201_phy_def,
&bcm5221_phy_def,
+ &bcm5241_phy_def,
&bcm5400_phy_def,
&bcm5401_phy_def,
&bcm5411_phy_def,
@@ -902,7 +1031,9 @@ static struct mii_phy_def* mii_phy_table[] = {
&bcm5421k2_phy_def,
&bcm5461_phy_def,
&bcm5462V_phy_def,
- &marvell_phy_def,
+ &marvell88e1101v1_phy_def,
+ &marvell88e1101v2_phy_def,
+ &marvell88e1111_phy_def,
&genmii_phy_def,
NULL
};
diff --git a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h
index 8ee1ca0471c..1d70ba6f9f1 100644
--- a/drivers/net/sungem_phy.h
+++ b/drivers/net/sungem_phy.h
@@ -30,7 +30,7 @@ struct mii_phy_def
struct mii_phy
{
struct mii_phy_def* def;
- int advertising;
+ u32 advertising;
int mii_id;
/* 1: autoneg enabled, 0: disabled */
@@ -85,6 +85,9 @@ extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
#define MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE 0x0001
#define MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR 0x0004
+/* MII BCM5241 Additional registers */
+#define MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR 0x0008
+
/* MII BCM5400 1000-BASET Control register */
#define MII_BCM5400_GB_CONTROL 0x09
#define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200
@@ -115,5 +118,7 @@ extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000
#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000
#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800
+#define MII_M1011_PHY_SPEC_STATUS_TX_PAUSE 0x0008
+#define MII_M1011_PHY_SPEC_STATUS_RX_PAUSE 0x0004
#endif /* __SUNGEM_PHY_H__ */
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 571320ae87a..f4bf62c2a7a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -68,8 +68,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.70"
-#define DRV_MODULE_RELDATE "December 1, 2006"
+#define DRV_MODULE_VERSION "3.72"
+#define DRV_MODULE_RELDATE "January 8, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -959,6 +959,13 @@ static int tg3_phy_reset(struct tg3 *tp)
u32 phy_status;
int err;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val;
+
+ val = tr32(GRC_MISC_CFG);
+ tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
+ udelay(40);
+ }
err = tg3_readphy(tp, MII_BMSR, &phy_status);
err |= tg3_readphy(tp, MII_BMSR, &phy_status);
if (err != 0)
@@ -1008,7 +1015,12 @@ out:
else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
- tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_ADJUST_TRIM) {
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
+ tg3_writephy(tp, MII_TG3_TEST1,
+ MII_TG3_TEST1_TRIM_EN | 0x4);
+ } else
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
}
/* Set Extended packet length bit (bit 14) on all chips that */
@@ -1170,7 +1182,15 @@ static void tg3_power_down_phy(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
return;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 val;
+
+ tg3_bmcr_reset(tp);
+ val = tr32(GRC_MISC_CFG);
+ tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
+ udelay(40);
+ return;
+ } else {
tg3_writephy(tp, MII_TG3_EXT_CTRL,
MII_TG3_EXT_CTRL_FORCE_LED_OFF);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
@@ -4426,7 +4446,7 @@ static void tg3_free_consistent(struct tg3 *tp)
*/
static int tg3_alloc_consistent(struct tg3 *tp)
{
- tp->rx_std_buffers = kmalloc((sizeof(struct ring_info) *
+ tp->rx_std_buffers = kzalloc((sizeof(struct ring_info) *
(TG3_RX_RING_SIZE +
TG3_RX_JUMBO_RING_SIZE)) +
(sizeof(struct tx_ring_info) *
@@ -4435,13 +4455,6 @@ static int tg3_alloc_consistent(struct tg3 *tp)
if (!tp->rx_std_buffers)
return -ENOMEM;
- memset(tp->rx_std_buffers, 0,
- (sizeof(struct ring_info) *
- (TG3_RX_RING_SIZE +
- TG3_RX_JUMBO_RING_SIZE)) +
- (sizeof(struct tx_ring_info) *
- TG3_TX_RING_SIZE));
-
tp->rx_jumbo_buffers = &tp->rx_std_buffers[TG3_RX_RING_SIZE];
tp->tx_buffers = (struct tx_ring_info *)
&tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE];
@@ -6988,6 +7001,8 @@ static int tg3_open(struct net_device *dev)
struct tg3 *tp = netdev_priv(dev);
int err;
+ netif_carrier_off(tp->dev);
+
tg3_full_lock(tp, 0);
err = tg3_set_power_state(tp, PCI_D0);
@@ -7981,6 +7996,10 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
tp->link_config.duplex = cmd->duplex;
}
+ tp->link_config.orig_speed = tp->link_config.speed;
+ tp->link_config.orig_duplex = tp->link_config.duplex;
+ tp->link_config.orig_autoneg = tp->link_config.autoneg;
+
if (netif_running(dev))
tg3_setup_phy(tp, 1);
@@ -10789,9 +10808,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
+ if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
+ tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
}
@@ -11923,6 +11944,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
*/
pci_save_state(tp->pdev);
+ pci_set_drvdata(pdev, dev);
+
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
@@ -11930,8 +11953,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
- pci_set_drvdata(pdev, dev);
-
printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ",
dev->name,
tp->board_part_number,
@@ -11962,8 +11983,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(pdev->dma_mask == DMA_32BIT_MASK) ? 32 :
(((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64));
- netif_carrier_off(tp->dev);
-
return 0;
err_out_iounmap:
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index dfaf4ed127b..80f59ac7ec5 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1350,6 +1350,7 @@
#define GRC_MISC_CFG_BOARD_ID_5788 0x00010000
#define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000
#define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000
+#define GRC_MISC_CFG_EPHY_IDDQ 0x00200000
#define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000
#define GRC_LOCAL_CTRL 0x00006808
#define GRC_LCLCTRL_INT_ACTIVE 0x00000001
@@ -1657,6 +1658,9 @@
#define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */
#define MII_TG3_EPHY_SHADOW_EN 0x80
+#define MII_TG3_TEST1 0x1e
+#define MII_TG3_TEST1_TRIM_EN 0x0010
+
/* 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
@@ -2255,6 +2259,7 @@ struct tg3 {
#define TG3_FLG2_1SHOT_MSI 0x10000000
#define TG3_FLG2_PHY_JITTER_BUG 0x20000000
#define TG3_FLG2_NO_FWARE_REPORTED 0x40000000
+#define TG3_FLG2_PHY_ADJUST_TRIM 0x80000000
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 1f05511fa39..7e4b23c7c1b 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -29,6 +29,7 @@
#include <linux/fsl_devices.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
+#include <linux/workqueue.h>
#include <asm/of_platform.h>
#include <asm/uaccess.h>
@@ -194,9 +195,9 @@ static void enqueue(struct list_head *node, struct list_head *lh)
{
unsigned long flags;
- spin_lock_irqsave(ugeth_lock, flags);
+ spin_lock_irqsave(&ugeth_lock, flags);
list_add_tail(node, lh);
- spin_unlock_irqrestore(ugeth_lock, flags);
+ spin_unlock_irqrestore(&ugeth_lock, flags);
}
#endif /* CONFIG_UGETH_FILTERING */
@@ -204,14 +205,14 @@ static struct list_head *dequeue(struct list_head *lh)
{
unsigned long flags;
- spin_lock_irqsave(ugeth_lock, flags);
+ spin_lock_irqsave(&ugeth_lock, flags);
if (!list_empty(lh)) {
struct list_head *node = lh->next;
list_del(node);
- spin_unlock_irqrestore(ugeth_lock, flags);
+ spin_unlock_irqrestore(&ugeth_lock, flags);
return node;
} else {
- spin_unlock_irqrestore(ugeth_lock, flags);
+ spin_unlock_irqrestore(&ugeth_lock, flags);
return NULL;
}
}
@@ -472,7 +473,7 @@ static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont)
kfree(enet_addr_cont);
}
-static int set_mac_addr(__be16 __iomem *reg, u8 *mac)
+static void set_mac_addr(__be16 __iomem *reg, u8 *mac)
{
out_be16(&reg[0], ((u16)mac[5] << 8) | mac[4]);
out_be16(&reg[1], ((u16)mac[3] << 8) | mac[2]);
@@ -1852,6 +1853,8 @@ static int init_phy(struct net_device *dev)
mii_info->mdio_read = &read_phy_reg;
mii_info->mdio_write = &write_phy_reg;
+ spin_lock_init(&mii_info->mdio_lock);
+
ugeth->mii_info = mii_info;
spin_lock_irq(&ugeth->lock);
@@ -3918,10 +3921,11 @@ static irqreturn_t phy_interrupt(int irq, void *dev_id)
}
/* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void ugeth_phy_change(void *data)
+static void ugeth_phy_change(struct work_struct *work)
{
- struct net_device *dev = (struct net_device *)data;
- struct ucc_geth_private *ugeth = netdev_priv(dev);
+ struct ucc_geth_private *ugeth =
+ container_of(work, struct ucc_geth_private, tq);
+ struct net_device *dev = ugeth->dev;
struct ucc_geth *ug_regs;
int result = 0;
@@ -4078,7 +4082,7 @@ static int ucc_geth_open(struct net_device *dev)
#endif /* CONFIG_UGETH_NAPI */
/* Set up the PHY change work queue */
- INIT_WORK(&ugeth->tq, ugeth_phy_change, dev);
+ INIT_WORK(&ugeth->tq, ugeth_phy_change);
init_timer(&ugeth->phy_info_timer);
ugeth->phy_info_timer.function = &ugeth_phy_startup_timer;
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
index 5360ec05eaa..3c86592ce03 100644
--- a/drivers/net/ucc_geth_phy.c
+++ b/drivers/net/ucc_geth_phy.c
@@ -68,8 +68,31 @@ static int gbit_config_aneg(struct ugeth_mii_info *mii_info);
static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
static int genmii_update_link(struct ugeth_mii_info *mii_info);
static int genmii_read_status(struct ugeth_mii_info *mii_info);
-u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum);
-void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val);
+
+static u16 ucc_geth_phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
+{
+ u16 retval;
+ unsigned long flags;
+
+ ugphy_vdbg("%s: IN", __FUNCTION__);
+
+ spin_lock_irqsave(&mii_info->mdio_lock, flags);
+ retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+ spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+ return retval;
+}
+
+static void ucc_geth_phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
+{
+ unsigned long flags;
+
+ ugphy_vdbg("%s: IN", __FUNCTION__);
+
+ spin_lock_irqsave(&mii_info->mdio_lock, flags);
+ mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
+ spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
/* Write value to the PHY for this device to the register at regnum, */
/* waiting until the write is done before it returns. All PHY */
@@ -184,7 +207,7 @@ static void config_genmii_advert(struct ugeth_mii_info *mii_info)
advertise = mii_info->advertising;
/* Setup standard advertisement */
- adv = phy_read(mii_info, MII_ADVERTISE);
+ adv = ucc_geth_phy_read(mii_info, MII_ADVERTISE);
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
if (advertise & ADVERTISED_10baseT_Half)
adv |= ADVERTISE_10HALF;
@@ -194,7 +217,7 @@ static void config_genmii_advert(struct ugeth_mii_info *mii_info)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
- phy_write(mii_info, MII_ADVERTISE, adv);
+ ucc_geth_phy_write(mii_info, MII_ADVERTISE, adv);
}
static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
@@ -204,7 +227,7 @@ static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
- ctrl = phy_read(mii_info, MII_BMCR);
+ ctrl = ucc_geth_phy_read(mii_info, MII_BMCR);
ctrl &=
~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
@@ -234,7 +257,7 @@ static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
break;
}
- phy_write(mii_info, MII_BMCR, ctrl);
+ ucc_geth_phy_write(mii_info, MII_BMCR, ctrl);
}
/* Enable and Restart Autonegotiation */
@@ -244,9 +267,9 @@ static void genmii_restart_aneg(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
- ctl = phy_read(mii_info, MII_BMCR);
+ ctl = ucc_geth_phy_read(mii_info, MII_BMCR);
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
- phy_write(mii_info, MII_BMCR, ctl);
+ ucc_geth_phy_write(mii_info, MII_BMCR, ctl);
}
static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
@@ -261,14 +284,14 @@ static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
config_genmii_advert(mii_info);
advertise = mii_info->advertising;
- adv = phy_read(mii_info, MII_1000BASETCONTROL);
+ adv = ucc_geth_phy_read(mii_info, MII_1000BASETCONTROL);
adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
MII_1000BASETCONTROL_HALFDUPLEXCAP);
if (advertise & SUPPORTED_1000baseT_Half)
adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
if (advertise & SUPPORTED_1000baseT_Full)
adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
- phy_write(mii_info, MII_1000BASETCONTROL, adv);
+ ucc_geth_phy_write(mii_info, MII_1000BASETCONTROL, adv);
/* Start/Restart aneg */
genmii_restart_aneg(mii_info);
@@ -298,10 +321,10 @@ static int genmii_update_link(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Do a fake read */
- phy_read(mii_info, MII_BMSR);
+ ucc_geth_phy_read(mii_info, MII_BMSR);
/* Read link and autonegotiation status */
- status = phy_read(mii_info, MII_BMSR);
+ status = ucc_geth_phy_read(mii_info, MII_BMSR);
if ((status & BMSR_LSTATUS) == 0)
mii_info->link = 0;
else
@@ -329,7 +352,7 @@ static int genmii_read_status(struct ugeth_mii_info *mii_info)
return err;
if (mii_info->autoneg) {
- status = phy_read(mii_info, MII_LPA);
+ status = ucc_geth_phy_read(mii_info, MII_LPA);
if (status & (LPA_10FULL | LPA_100FULL))
mii_info->duplex = DUPLEX_FULL;
@@ -352,9 +375,9 @@ static int marvell_init(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
- phy_write(mii_info, 0x14, 0x0cd2);
- phy_write(mii_info, MII_BMCR,
- phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+ ucc_geth_phy_write(mii_info, 0x14, 0x0cd2);
+ ucc_geth_phy_write(mii_info, MII_BMCR,
+ ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
msleep(4000);
return 0;
@@ -367,13 +390,13 @@ static int marvell_config_aneg(struct ugeth_mii_info *mii_info)
/* The Marvell PHY has an errata which requires
* that certain registers get written in order
* to restart autonegotiation */
- phy_write(mii_info, MII_BMCR, BMCR_RESET);
+ ucc_geth_phy_write(mii_info, MII_BMCR, BMCR_RESET);
- phy_write(mii_info, 0x1d, 0x1f);
- phy_write(mii_info, 0x1e, 0x200c);
- phy_write(mii_info, 0x1d, 0x5);
- phy_write(mii_info, 0x1e, 0);
- phy_write(mii_info, 0x1e, 0x100);
+ ucc_geth_phy_write(mii_info, 0x1d, 0x1f);
+ ucc_geth_phy_write(mii_info, 0x1e, 0x200c);
+ ucc_geth_phy_write(mii_info, 0x1d, 0x5);
+ ucc_geth_phy_write(mii_info, 0x1e, 0);
+ ucc_geth_phy_write(mii_info, 0x1e, 0x100);
gbit_config_aneg(mii_info);
@@ -398,7 +421,7 @@ static int marvell_read_status(struct ugeth_mii_info *mii_info)
* are as set */
if (mii_info->autoneg && mii_info->link) {
int speed;
- status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+ status = ucc_geth_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
/* Get the duplexity */
if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
@@ -430,7 +453,7 @@ static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Clear the interrupts by reading the reg */
- phy_read(mii_info, MII_M1011_IEVENT);
+ ucc_geth_phy_read(mii_info, MII_M1011_IEVENT);
return 0;
}
@@ -440,9 +463,9 @@ static int marvell_config_intr(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+ ucc_geth_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
else
- phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+ ucc_geth_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
return 0;
}
@@ -451,9 +474,9 @@ static int cis820x_init(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
- phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
+ ucc_geth_phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
MII_CIS8201_AUXCONSTAT_INIT);
- phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
+ ucc_geth_phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
return 0;
}
@@ -477,7 +500,7 @@ static int cis820x_read_status(struct ugeth_mii_info *mii_info)
if (mii_info->autoneg && mii_info->link) {
int speed;
- status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+ status = ucc_geth_phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
mii_info->duplex = DUPLEX_FULL;
else
@@ -505,7 +528,7 @@ static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info)
{
ugphy_vdbg("%s: IN", __FUNCTION__);
- phy_read(mii_info, MII_CIS8201_ISTAT);
+ ucc_geth_phy_read(mii_info, MII_CIS8201_ISTAT);
return 0;
}
@@ -515,9 +538,9 @@ static int cis820x_config_intr(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+ ucc_geth_phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
else
- phy_write(mii_info, MII_CIS8201_IMASK, 0);
+ ucc_geth_phy_write(mii_info, MII_CIS8201_IMASK, 0);
return 0;
}
@@ -541,7 +564,7 @@ static int dm9161_read_status(struct ugeth_mii_info *mii_info)
/* If we aren't autonegotiating, assume speeds
* are as set */
if (mii_info->autoneg && mii_info->link) {
- status = phy_read(mii_info, MII_DM9161_SCSR);
+ status = ucc_geth_phy_read(mii_info, MII_DM9161_SCSR);
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
mii_info->speed = SPEED_100;
else
@@ -572,7 +595,7 @@ static void dm9161_timer(unsigned long data)
{
struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
struct dm9161_private *priv = mii_info->priv;
- u16 status = phy_read(mii_info, MII_BMSR);
+ u16 status = ucc_geth_phy_read(mii_info, MII_BMSR);
ugphy_vdbg("%s: IN", __FUNCTION__);
@@ -599,11 +622,11 @@ static int dm9161_init(struct ugeth_mii_info *mii_info)
/* Reset is not done yet */
priv->resetdone = 0;
- phy_write(mii_info, MII_BMCR,
- phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+ ucc_geth_phy_write(mii_info, MII_BMCR,
+ ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
- phy_write(mii_info, MII_BMCR,
- phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
+ ucc_geth_phy_write(mii_info, MII_BMCR,
+ ucc_geth_phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
config_genmii_advert(mii_info);
/* Start/Restart aneg */
@@ -634,7 +657,7 @@ static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Clear the interrupts by reading the reg */
- phy_read(mii_info, MII_DM9161_INTR);
+ ucc_geth_phy_read(mii_info, MII_DM9161_INTR);
return 0;
@@ -645,9 +668,9 @@ static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
- phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
+ ucc_geth_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
else
- phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
+ ucc_geth_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
return 0;
}
@@ -718,31 +741,6 @@ static struct phy_info *phy_info[] = {
NULL
};
-u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
-{
- u16 retval;
- unsigned long flags;
-
- ugphy_vdbg("%s: IN", __FUNCTION__);
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
- return retval;
-}
-
-void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
-{
- unsigned long flags;
-
- ugphy_vdbg("%s: IN", __FUNCTION__);
-
- spin_lock_irqsave(&mii_info->mdio_lock, flags);
- mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
- spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
/* Use the PHY ID registers to determine what type of PHY is attached
* to device dev. return a struct phy_info structure describing that PHY
*/
@@ -757,11 +755,11 @@ struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
/* Grab the bits from PHYIR1, and put them in the upper half */
- phy_reg = phy_read(mii_info, MII_PHYSID1);
+ phy_reg = ucc_geth_phy_read(mii_info, MII_PHYSID1);
phy_ID = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
- phy_reg = phy_read(mii_info, MII_PHYSID2);
+ phy_reg = ucc_geth_phy_read(mii_info, MII_PHYSID2);
phy_ID |= (phy_reg & 0xffff);
/* loop through all the known PHY types, and find one that */
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 74f894795a1..8e5d82051bd 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -265,15 +265,19 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
static int velocity_suspend(struct pci_dev *pdev, pm_message_t state);
static int velocity_resume(struct pci_dev *pdev);
+static DEFINE_SPINLOCK(velocity_dev_list_lock);
+static LIST_HEAD(velocity_dev_list);
+
+#endif
+
+#if defined(CONFIG_PM) && defined(CONFIG_INET)
+
static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
static struct notifier_block velocity_inetaddr_notifier = {
.notifier_call = velocity_netdev_event,
};
-static DEFINE_SPINLOCK(velocity_dev_list_lock);
-static LIST_HEAD(velocity_dev_list);
-
static void velocity_register_notifier(void)
{
register_inetaddr_notifier(&velocity_inetaddr_notifier);
@@ -284,12 +288,12 @@ static void velocity_unregister_notifier(void)
unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
}
-#else /* CONFIG_PM */
+#else
#define velocity_register_notifier() do {} while (0)
#define velocity_unregister_notifier() do {} while (0)
-#endif /* !CONFIG_PM */
+#endif
/*
* Internal board variants. At the moment we have only one
@@ -3132,7 +3136,7 @@ static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
}
/* Finally, invert the result once to get the correct data */
crc = ~crc;
- return bitreverse(crc) >> 16;
+ return bitrev32(crc) >> 16;
}
/**
@@ -3292,6 +3296,8 @@ static int velocity_resume(struct pci_dev *pdev)
return 0;
}
+#ifdef CONFIG_INET
+
static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
{
struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
@@ -3312,4 +3318,6 @@ static int velocity_netdev_event(struct notifier_block *nb, unsigned long notifi
}
return NOTIFY_DONE;
}
+
+#endif
#endif
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index d5ab9cf1325..21f76f51c95 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -382,7 +382,7 @@ config SDLA
# Wan router core.
config WAN_ROUTER_DRIVERS
- bool "WAN router drivers"
+ tristate "WAN router drivers"
depends on WAN && WAN_ROUTER
---help---
Connect LAN to WAN via Linux box.
@@ -393,7 +393,8 @@ config WAN_ROUTER_DRIVERS
<file:Documentation/networking/wan-router.txt>.
Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
+ kernel except for how subordinate drivers may be built:
+ saying N will just cause the configurator to skip all
the questions about WAN router drivers.
If unsure, say N.
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index e1bf8b93f95..6c7dfb50143 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -974,12 +974,12 @@ static int cosa_open(struct inode *inode, struct file *file)
unsigned long flags;
int n;
- if ((n=iminor(file->f_dentry->d_inode)>>CARD_MINOR_BITS)
+ if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS)
>= nr_cards)
return -ENODEV;
cosa = cosa_cards+n;
- if ((n=iminor(file->f_dentry->d_inode)
+ if ((n=iminor(file->f_path.dentry->d_inode)
& ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
return -ENODEV;
chan = cosa->chan + n;
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index a4f735723c4..a02c5fb4056 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -231,7 +231,7 @@ static struct sv11_device *sv11_init(int iobase, int irq)
return NULL;
}
- sv=(struct sv11_device *)kmalloc(sizeof(struct sv11_device), GFP_KERNEL);
+ sv = kmalloc(sizeof(struct sv11_device), GFP_KERNEL);
if(!sv)
goto fail3;
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 36d1c3ff707..62184dee377 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -3455,7 +3455,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if ((err = pci_enable_device(pdev)) < 0)
return err;
- card = (pc300_t *) kmalloc(sizeof(pc300_t), GFP_KERNEL);
+ card = kmalloc(sizeof(pc300_t), GFP_KERNEL);
if (card == NULL) {
printk("PC300 found at RAM 0x%016llx, "
"but could not allocate card structure.\n",
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index b2a23aed442..5873c346e7e 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -784,7 +784,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
continue;
}
- new = (st_cpc_rx_buf *)kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
+ new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
if (new == 0) {
cpc_tty_rx_disc_frame(pc300chan);
continue;
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 9c3ccc66914..1c9edd97acc 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -123,8 +123,8 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
unsigned char *xbuff, *rbuff;
int len = 2* newmtu;
- xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
- rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
+ xbuff = kmalloc(len + 4, GFP_ATOMIC);
+ rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL)
{
@@ -465,11 +465,11 @@ static int x25_asy_open(struct net_device *dev)
len = dev->mtu * 2;
- sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+ sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
if (sl->rbuff == NULL) {
goto norbuff;
}
- sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+ sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
if (sl->xbuff == NULL) {
goto noxbuff;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 2ec2e5afce6..91b752e3d07 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -2701,8 +2701,8 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
/* extract core_id, core_rev, core_vendor */
- core_id = (sb_id_hi & 0xFFF0) >> 4;
- core_rev = (sb_id_hi & 0xF);
+ core_id = (sb_id_hi & 0x8FF0) >> 4;
+ core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
@@ -2873,7 +2873,10 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
- sbimconfiglow |= 0x32;
+ if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+ sbimconfiglow |= 0x32;
+ else
+ sbimconfiglow |= 0x53;
bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
}
@@ -3077,7 +3080,7 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
if (err)
goto out;
- if (bcm->current_core->rev < 6 ||
+ if (bcm->current_core->rev < 6 &&
bcm->current_core->id == BCM43xx_COREID_PCI) {
value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
value |= (1 << backplane_flag_nr);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 974a8e5bec8..efb8cf3bd8a 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -1253,7 +1253,7 @@ static char * ap_auth_make_challenge(struct ap_data *ap)
return NULL;
}
- tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
+ tmpbuf = kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);
if (tmpbuf == NULL) {
PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n");
return NULL;
diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c
index 24fc387bba6..c7678e67697 100644
--- a/drivers/net/wireless/hostap/hostap_download.c
+++ b/drivers/net/wireless/hostap/hostap_download.c
@@ -201,7 +201,7 @@ static u8 * prism2_read_pda(struct net_device *dev)
0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
};
- buf = (u8 *) kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
+ buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
if (buf == NULL)
return NULL;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index a394a23b9a2..3079378fb8c 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2252,7 +2252,7 @@ static int hostap_tx_compl_read(local_info_t *local, int error,
if (txdesc->sw_support) {
len = le16_to_cpu(txdesc->data_len);
if (len < PRISM2_DATA_MAXLEN) {
- *payload = (char *) kmalloc(len, GFP_ATOMIC);
+ *payload = kmalloc(len, GFP_ATOMIC);
if (*payload == NULL ||
hfa384x_from_bap(dev, BAP0, *payload, len)) {
PDEBUG(DEBUG_EXTRA, "%s: could not read TX "
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 3b7b8063ff1..cb08bc5db2b 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3829,7 +3829,7 @@ static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p)
p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
return -EINVAL;
- param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+ param = kmalloc(p->length, GFP_KERNEL);
if (param == NULL)
return -ENOMEM;
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 0796be9d9e7..04c19cefa1d 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -250,7 +250,7 @@ u16 hostap_tx_callback_register(local_info_t *local,
unsigned long flags;
struct hostap_tx_callback_info *entry;
- entry = (struct hostap_tx_callback_info *) kmalloc(sizeof(*entry),
+ entry = kmalloc(sizeof(*entry),
GFP_ATOMIC);
if (entry == NULL)
return 0;
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index dd9ba4aad7b..b85857a8487 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2246,7 +2246,7 @@ static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
if (priv->snapshot[0])
return 1;
for (i = 0; i < 0x30; i++) {
- priv->snapshot[i] = (u8 *) kmalloc(0x1000, GFP_ATOMIC);
+ priv->snapshot[i] = kmalloc(0x1000, GFP_ATOMIC);
if (!priv->snapshot[i]) {
IPW_DEBUG_INFO("%s: Error allocating snapshot "
"buffer %d\n", priv->net_dev->name, i);
@@ -2664,7 +2664,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
break;
}
#endif
- if (stats.len < sizeof(u->rx_data.header))
+ if (stats.len < sizeof(struct ieee80211_hdr_3addr))
break;
switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) {
case IEEE80211_FTYPE_MGMT:
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 644b4741ef7..a009ab51771 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -406,7 +406,6 @@ static int netwave_probe(struct pcmcia_device *link)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
/* Netwave private struct init. link/dev/node already taken care of,
* other stuff zero'd - Jean II */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 96606ed1007..838d510213c 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -2775,7 +2775,7 @@ prism54_hostapd(struct net_device *ndev, struct iw_point *p)
p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
return -EINVAL;
- param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+ param = kmalloc(p->length, GFP_KERNEL);
if (param == NULL)
return -ENOMEM;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 88e10c9bc4a..47b2ccb6a63 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -331,7 +331,6 @@ static int ray_probe(struct pcmcia_device *p_dev)
p_dev->conf.Attributes = CONF_ENABLE_IRQ;
p_dev->conf.IntType = INT_MEMORY_AND_IO;
p_dev->conf.ConfigIndex = 1;
- p_dev->conf.Present = PRESENT_OPTION;
p_dev->priv = dev;
p_dev->irq.Instance = dev;
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 337c692f6fd..ce3a8bac66f 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -798,7 +798,7 @@ static unsigned int get_baud(struct tty_struct *tty)
*/
static void set_baud(struct tty_struct *tty, unsigned int baudcode)
{
- struct termios old_termios = *(tty->termios);
+ struct ktermios old_termios = *(tty->termios);
tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */
tty->termios->c_cflag |= baudcode; /* Set the new baud setting */
tty->driver->set_termios(tty, &old_termios);
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 233d906c08f..5eb81638e84 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -603,7 +603,7 @@ static wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char se
if(lp->wavepoint_table.num_wavepoints==MAX_WAVEPOINTS)
return NULL;
- new_wavepoint=(wavepoint_history *) kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);
+ new_wavepoint = kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);
if(new_wavepoint==NULL)
return NULL;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 583e0d655a9..c250f08c8dd 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1928,7 +1928,6 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
p_dev->conf.Attributes = CONF_ENABLE_IRQ;
p_dev->conf.IntType = INT_MEMORY_AND_IO;
p_dev->conf.ConfigIndex = 1;
- p_dev->conf.Present = PRESENT_OPTION;
dev = alloc_etherdev(sizeof(struct wl3501_card));
if (!dev)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 77e11ddad83..78ea72fb8f0 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -101,7 +101,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
/* Allocate a single memory block for values and addresses. */
count16 = 2*count;
- a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
+ a16 = kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
GFP_NOFS);
if (!a16) {
dev_dbg_f(zd_chip_dev(chip),
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 00ca704ece3..a08524191b5 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -41,6 +41,8 @@ static void housekeeping_disable(struct zd_mac *mac);
static void set_multicast_hash_handler(struct work_struct *work);
+static void do_rx(unsigned long mac_ptr);
+
int zd_mac_init(struct zd_mac *mac,
struct net_device *netdev,
struct usb_interface *intf)
@@ -53,6 +55,10 @@ int zd_mac_init(struct zd_mac *mac,
INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work);
+ skb_queue_head_init(&mac->rx_queue);
+ tasklet_init(&mac->rx_tasklet, do_rx, (unsigned long)mac);
+ tasklet_disable(&mac->rx_tasklet);
+
ieee_init(ieee);
softmac_init(ieee80211_priv(netdev));
zd_chip_init(&mac->chip, netdev, intf);
@@ -140,6 +146,8 @@ out:
void zd_mac_clear(struct zd_mac *mac)
{
flush_workqueue(zd_workqueue);
+ skb_queue_purge(&mac->rx_queue);
+ tasklet_kill(&mac->rx_tasklet);
zd_chip_clear(&mac->chip);
ZD_ASSERT(!spin_is_locked(&mac->lock));
ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -168,6 +176,8 @@ int zd_mac_open(struct net_device *netdev)
struct zd_chip *chip = &mac->chip;
int r;
+ tasklet_enable(&mac->rx_tasklet);
+
r = zd_chip_enable_int(chip);
if (r < 0)
goto out;
@@ -218,6 +228,8 @@ int zd_mac_stop(struct net_device *netdev)
*/
zd_chip_disable_rx(chip);
+ skb_queue_purge(&mac->rx_queue);
+ tasklet_disable(&mac->rx_tasklet);
housekeeping_disable(mac);
ieee80211softmac_stop(netdev);
@@ -470,13 +482,13 @@ static void bssinfo_change(struct net_device *netdev, u32 changes)
if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) {
/* Set RTS rate to highest available basic rate */
- u8 rate = ieee80211softmac_highest_supported_rate(softmac,
+ u8 hi_rate = ieee80211softmac_highest_supported_rate(softmac,
&bssinfo->supported_rates, 1);
- rate = rate_to_zd_rate(rate);
+ hi_rate = rate_to_zd_rate(hi_rate);
spin_lock_irqsave(&mac->lock, flags);
- if (rate != mac->rts_rate) {
- mac->rts_rate = rate;
+ if (hi_rate != mac->rts_rate) {
+ mac->rts_rate = hi_rate;
need_set_rts_cts = 1;
}
spin_unlock_irqrestore(&mac->lock, flags);
@@ -1072,43 +1084,75 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
return 0;
}
-int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length)
+static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
{
int r;
struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
struct ieee80211_rx_stats stats;
const struct rx_status *status;
- struct sk_buff *skb;
- if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
- IEEE80211_FCS_LEN + sizeof(struct rx_status))
- return -EINVAL;
+ if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
+ IEEE80211_FCS_LEN + sizeof(struct rx_status))
+ {
+ dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
+ skb->len);
+ goto free_skb;
+ }
- r = fill_rx_stats(&stats, &status, mac, buffer, length);
- if (r)
- return r;
+ r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
+ if (r) {
+ /* Only packets with rx errors are included here. */
+ goto free_skb;
+ }
- length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+
- sizeof(struct rx_status);
- buffer += ZD_PLCP_HEADER_SIZE;
+ __skb_pull(skb, ZD_PLCP_HEADER_SIZE);
+ __skb_trim(skb, skb->len -
+ (IEEE80211_FCS_LEN + sizeof(struct rx_status)));
- update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi);
+ update_qual_rssi(mac, skb->data, skb->len, stats.signal,
+ status->signal_strength);
- r = filter_rx(ieee, buffer, length, &stats);
- if (r <= 0)
- return r;
+ r = filter_rx(ieee, skb->data, skb->len, &stats);
+ if (r <= 0) {
+ if (r < 0)
+ dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+ goto free_skb;
+ }
- skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
- if (!skb)
- return -ENOMEM;
if (ieee->iw_mode == IW_MODE_MONITOR)
- fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac,
+ fill_rt_header(skb_push(skb, sizeof(struct zd_rt_hdr)), mac,
&stats, status);
- memcpy(skb_put(skb, length), buffer, length);
r = ieee80211_rx(ieee, skb, &stats);
- if (!r)
- dev_kfree_skb_any(skb);
+ if (r)
+ return;
+free_skb:
+ /* We are always in a soft irq. */
+ dev_kfree_skb(skb);
+}
+
+static void do_rx(unsigned long mac_ptr)
+{
+ struct zd_mac *mac = (struct zd_mac *)mac_ptr;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&mac->rx_queue)) != NULL)
+ zd_mac_rx(mac, skb);
+}
+
+int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
+ if (!skb) {
+ dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+ return -ENOMEM;
+ }
+ skb_reserve(skb, sizeof(struct zd_rt_hdr));
+ memcpy(__skb_put(skb, length), buffer, length);
+ skb_queue_tail(&mac->rx_queue, skb);
+ tasklet_schedule(&mac->rx_tasklet);
return 0;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index f0cf05dc7d3..faf4c7828d4 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -138,6 +138,9 @@ struct zd_mac {
struct delayed_work set_rts_cts_work;
struct delayed_work set_basic_rates_work;
+ struct tasklet_struct rx_tasklet;
+ struct sk_buff_head rx_queue;
+
unsigned int stats_count;
u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
@@ -193,7 +196,7 @@ int zd_mac_stop(struct net_device *netdev);
int zd_mac_set_mac_address(struct net_device *dev, void *p);
void zd_mac_set_multicast_list(struct net_device *netdev);
-int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
+int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length);
int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index aa782e88754..605e96e7405 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -598,13 +598,13 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
n = l+k;
if (n > length)
return;
- zd_mac_rx(mac, buffer+l, k);
+ zd_mac_rx_irq(mac, buffer+l, k);
if (i >= 2)
return;
l = (n+3) & ~3;
}
} else {
- zd_mac_rx(mac, buffer, length);
+ zd_mac_rx_irq(mac, buffer, length);
}
}
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 43e521e9912..78c2e6e4b42 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -220,8 +220,8 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm)
continue;
if (!(vma->vm_flags & VM_EXECUTABLE))
continue;
- cookie = fast_get_dcookie(vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
+ cookie = fast_get_dcookie(vma->vm_file->f_path.dentry,
+ vma->vm_file->f_path.mnt);
break;
}
@@ -246,8 +246,8 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o
continue;
if (vma->vm_file) {
- cookie = fast_get_dcookie(vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
+ cookie = fast_get_dcookie(vma->vm_file->f_path.dentry,
+ vma->vm_file->f_path.mnt);
*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
vma->vm_start;
} else {
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 12bab64a62a..6fb3f7979f2 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -874,7 +874,7 @@ void *iosapic_register(unsigned long hpa)
return NULL;
}
- isi = (struct iosapic_info *)kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+ isi = kzalloc(sizeof(struct iosapic_info), GFP_KERNEL);
if (!isi) {
BUG();
return NULL;
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index c7fa28a28b9..36c6a1bfe55 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -82,9 +82,6 @@ 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_IP32
tristate "SGI IP32 builtin port (EXPERIMENTAL)"
depends on SGI_IP32 && PARPORT && EXPERIMENTAL
@@ -158,5 +155,8 @@ config PARPORT_1284
transfer modes. Also say Y if you want device ID information to
appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N.
+config PARPORT_NOT_PC
+ bool
+
endmenu
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index f1dd81a1d59..3cfb0a3575e 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -19,7 +19,7 @@ config PCI_MSI
config PCI_MULTITHREAD_PROBE
bool "PCI Multi-threaded probe (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ depends on PCI && EXPERIMENTAL && BROKEN
help
Say Y here if you want the PCI core to spawn a new thread for
every PCI device that is probed. This can cause a huge
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 6e780db9454..adce4204d87 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -76,7 +76,8 @@ config HOTPLUG_PCI_IBM
config HOTPLUG_PCI_ACPI
tristate "ACPI PCI Hotplug driver"
- depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI)
+ depends on HOTPLUG_PCI
+ depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
help
Say Y here if you have a system that supports PCI Hotplug using
ACPI.
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 0b9d0db1590..bd1faebf61a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1682,7 +1682,7 @@ int __init acpiphp_glue_init(void)
*
* This function frees all data allocated in acpiphp_glue_init()
*/
-void __exit acpiphp_glue_exit(void)
+void acpiphp_glue_exit(void)
{
acpi_pci_unregister_driver(&acpi_pci_hp_driver);
}
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index bd40aee10e1..7f03881a8b6 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -319,13 +319,12 @@ static int ibm_get_table_from_acpi(char **bufp)
if (bufp == NULL)
goto read_table_done;
- lbuf = kmalloc(size, GFP_KERNEL);
+ lbuf = kzalloc(size, GFP_KERNEL);
dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
__FUNCTION__, package->package.count, size, lbuf);
if (lbuf) {
*bufp = lbuf;
- memset(lbuf, 0, size);
} else {
size = -ENOMEM;
goto read_table_done;
diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
index 298a6cfd840..ae5e974c45a 100644
--- a/drivers/pci/hotplug/cpqphp_nvram.c
+++ b/drivers/pci/hotplug/cpqphp_nvram.c
@@ -520,7 +520,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
return 2;
while (nummem--) {
- mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!mem_node)
break;
@@ -548,7 +548,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
}
while (numpmem--) {
- p_mem_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!p_mem_node)
break;
@@ -576,7 +576,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
}
while (numio--) {
- io_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!io_node)
break;
@@ -604,7 +604,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
}
while (numbus--) {
- bus_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
+ bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
if (!bus_node)
break;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6d3f580f266..25d3aadfddb 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1320,7 +1320,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
DBG_ENTER_ROUTINE
spin_lock_init(&list_lock);
- php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
+ php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
if (!php_ctlr) { /* allocate controller state data */
err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index b771196a654..3009193f005 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -47,21 +47,11 @@ static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
return retval;
}
-static struct hotplug_slot_attribute hotplug_slot_attr_location = {
+static struct hotplug_slot_attribute php_attr_location = {
.attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
.show = location_read_file,
};
-static void rpaphp_sysfs_add_attr_location (struct hotplug_slot *slot)
-{
- sysfs_create_file(&slot->kobj, &hotplug_slot_attr_location.attr);
-}
-
-static void rpaphp_sysfs_remove_attr_location (struct hotplug_slot *slot)
-{
- sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_location.attr);
-}
-
/* free up the memory used by a slot */
static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
{
@@ -145,7 +135,7 @@ int rpaphp_deregister_slot(struct slot *slot)
list_del(&slot->rpaphp_slot_list);
/* remove "phy_location" file */
- rpaphp_sysfs_remove_attr_location(php_slot);
+ sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
retval = pci_hp_deregister(php_slot);
if (retval)
@@ -160,36 +150,45 @@ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
int rpaphp_register_slot(struct slot *slot)
{
+ struct hotplug_slot *php_slot = slot->hotplug_slot;
int retval;
dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
__FUNCTION__, slot->dn->full_name, slot->index, slot->name,
slot->power_domain, slot->type);
+
/* should not try to register the same slot twice */
- if (is_registered(slot)) { /* should't be here */
+ if (is_registered(slot)) {
err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
- rpaphp_release_slot(slot->hotplug_slot);
- return -EAGAIN;
+ retval = -EAGAIN;
+ goto register_fail;
}
- retval = pci_hp_register(slot->hotplug_slot);
+
+ retval = pci_hp_register(php_slot);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
- rpaphp_release_slot(slot->hotplug_slot);
- return retval;
+ goto register_fail;
}
-
- /* create "phy_locatoin" file */
- rpaphp_sysfs_add_attr_location(slot->hotplug_slot);
- /* add slot to our internal list */
- dbg("%s adding slot[%s] to rpaphp_slot_list\n",
- __FUNCTION__, slot->name);
+ /* create "phy_location" file */
+ retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
+ if (retval) {
+ err("sysfs_create_file failed with error %d\n", retval);
+ goto sysfs_fail;
+ }
+ /* add slot to our internal list */
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
info("Slot [%s](PCI location=%s) registered\n", slot->name,
slot->location);
num_slots++;
return 0;
+
+sysfs_fail:
+ pci_hp_deregister(php_slot);
+register_fail:
+ rpaphp_release_slot(php_slot);
+ return retval;
}
int rpaphp_get_power_status(struct slot *slot, u8 * value)
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 50757695844..3ca6a4f574b 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -47,11 +47,17 @@ extern int shpchp_poll_time;
extern int shpchp_debug;
extern struct workqueue_struct *shpchp_wq;
-/*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
-#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
+#define dbg(format, arg...) \
+ do { \
+ if (shpchp_debug) \
+ printk("%s: " format, MY_NAME , ## arg); \
+ } while (0)
+#define err(format, arg...) \
+ printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
+#define info(format, arg...) \
+ printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
+#define warn(format, arg...) \
+ printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
#define SLOT_NAME_SIZE 10
struct slot {
@@ -83,34 +89,27 @@ struct event_info {
struct controller {
struct mutex crit_sect; /* critical section mutex */
struct mutex cmd_lock; /* command lock */
- struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev;
struct list_head slot_list;
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
- u8 bus;
- u8 device;
- u8 function;
u8 slot_device_offset;
- u8 add_support;
u32 pcix_misc2_reg; /* for amd pogo errata */
- enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
- u8 slot_bus; /* Bus where the slots handled by this controller sit */
u32 cap_offset;
unsigned long mmio_base;
unsigned long mmio_size;
+ void __iomem *creg;
+ struct timer_list poll_timer;
};
-
/* Define AMD SHPC ID */
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
/* AMD PCIX bridge registers */
-
#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
#define PCIX_MISCII_OFFSET 0x48
#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
@@ -145,8 +144,6 @@ struct controller {
#define POWERON_STATE 3
#define POWEROFF_STATE 4
-#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400
-
/* Error messages */
#define INTERLOCK_OPEN 0x00000002
#define ADD_NOT_SUPPORTED 0x00000003
@@ -158,50 +155,32 @@ struct controller {
#define WRONG_BUS_FREQUENCY 0x0000000D
#define POWER_FAILURE 0x0000000E
-#define REMOVE_NOT_SUPPORTED 0x00000003
-
-#define DISABLE_CARD 1
-
-/*
- * error Messages
- */
-#define msg_initialization_err "Initialization failure, error=%d\n"
-#define msg_button_on "PCI slot #%s - powering on due to button press.\n"
-#define msg_button_off "PCI slot #%s - powering off due to button press.\n"
-#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n"
-
-/* sysfs functions for the hotplug controller info */
extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
-
-extern int shpchp_sysfs_enable_slot(struct slot *slot);
-extern int shpchp_sysfs_disable_slot(struct slot *slot);
-
-extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
-extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
-extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
-extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
-
-/* pci functions */
-extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
-extern int shpchp_configure_device(struct slot *p_slot);
-extern int shpchp_unconfigure_device(struct slot *p_slot);
-extern void shpchp_remove_ctrl_files(struct controller *ctrl);
-extern void cleanup_slots(struct controller *ctrl);
-extern void queue_pushbutton_work(struct work_struct *work);
-
+extern void shpchp_remove_ctrl_files(struct controller *ctrl);
+extern int shpchp_sysfs_enable_slot(struct slot *slot);
+extern int shpchp_sysfs_disable_slot(struct slot *slot);
+extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
+extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
+extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
+extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
+extern int shpchp_configure_device(struct slot *p_slot);
+extern int shpchp_unconfigure_device(struct slot *p_slot);
+extern void cleanup_slots(struct controller *ctrl);
+extern void queue_pushbutton_work(struct work_struct *work);
+extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
#ifdef CONFIG_ACPI
static inline int get_hp_params_from_firmware(struct pci_dev *dev,
- struct hotplug_params *hpp)
+ struct hotplug_params *hpp)
{
if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
return -ENODEV;
return 0;
}
-#define get_hp_hw_control_from_firmware(pdev) \
- do { \
- if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
- acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
+#define get_hp_hw_control_from_firmware(pdev) \
+ do { \
+ if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
+ acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\
} while (0)
#else
#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
@@ -222,108 +201,40 @@ struct ctrl_reg {
volatile u32 serr_loc;
volatile u32 serr_intr_enable;
volatile u32 slot1;
- volatile u32 slot2;
- volatile u32 slot3;
- volatile u32 slot4;
- volatile u32 slot5;
- volatile u32 slot6;
- volatile u32 slot7;
- volatile u32 slot8;
- volatile u32 slot9;
- volatile u32 slot10;
- volatile u32 slot11;
- volatile u32 slot12;
} __attribute__ ((packed));
/* offsets to the controller registers based on the above structure layout */
enum ctrl_offsets {
- BASE_OFFSET = offsetof(struct ctrl_reg, base_offset),
- SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1),
- SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2),
- SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config),
- SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config),
- MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl),
- PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface),
- CMD = offsetof(struct ctrl_reg, cmd),
- CMD_STATUS = offsetof(struct ctrl_reg, cmd_status),
- INTR_LOC = offsetof(struct ctrl_reg, intr_loc),
- SERR_LOC = offsetof(struct ctrl_reg, serr_loc),
- SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable),
- SLOT1 = offsetof(struct ctrl_reg, slot1),
- SLOT2 = offsetof(struct ctrl_reg, slot2),
- SLOT3 = offsetof(struct ctrl_reg, slot3),
- SLOT4 = offsetof(struct ctrl_reg, slot4),
- SLOT5 = offsetof(struct ctrl_reg, slot5),
- SLOT6 = offsetof(struct ctrl_reg, slot6),
- SLOT7 = offsetof(struct ctrl_reg, slot7),
- SLOT8 = offsetof(struct ctrl_reg, slot8),
- SLOT9 = offsetof(struct ctrl_reg, slot9),
- SLOT10 = offsetof(struct ctrl_reg, slot10),
- SLOT11 = offsetof(struct ctrl_reg, slot11),
- SLOT12 = offsetof(struct ctrl_reg, slot12),
-};
-typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
-struct php_ctlr_state_s {
- struct php_ctlr_state_s *pnext;
- struct pci_dev *pci_dev;
- unsigned int irq;
- unsigned long flags; /* spinlock's */
- u32 slot_device_offset;
- u32 num_slots;
- struct timer_list int_poll_timer; /* Added for poll event */
- php_intr_callback_t attention_button_callback;
- php_intr_callback_t switch_change_callback;
- php_intr_callback_t presence_change_callback;
- php_intr_callback_t power_fault_callback;
- void *callback_instance_id;
- void __iomem *creg; /* Ptr to controller register space */
+ BASE_OFFSET = offsetof(struct ctrl_reg, base_offset),
+ SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1),
+ SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2),
+ SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config),
+ SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config),
+ MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl),
+ PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface),
+ CMD = offsetof(struct ctrl_reg, cmd),
+ CMD_STATUS = offsetof(struct ctrl_reg, cmd_status),
+ INTR_LOC = offsetof(struct ctrl_reg, intr_loc),
+ SERR_LOC = offsetof(struct ctrl_reg, serr_loc),
+ SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable),
+ SLOT1 = offsetof(struct ctrl_reg, slot1),
};
-/* Inline functions */
-
-/* Inline functions to check the sanity of a pointer that is passed to us */
-static inline int slot_paranoia_check (struct slot *slot, const char *function)
-{
- if (!slot) {
- dbg("%s - slot == NULL", function);
- return -1;
- }
- if (!slot->hotplug_slot) {
- dbg("%s - slot->hotplug_slot == NULL!", function);
- return -1;
- }
- return 0;
-}
-
-static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
+static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot)
{
- struct slot *slot;
-
- if (!hotplug_slot) {
- dbg("%s - hotplug_slot == NULL\n", function);
- return NULL;
- }
-
- slot = (struct slot *)hotplug_slot->private;
- if (slot_paranoia_check (slot, function))
- return NULL;
- return slot;
+ return hotplug_slot->private;
}
-static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
+static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device)
{
struct slot *slot;
- if (!ctrl)
- return NULL;
-
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (slot->device == device)
return slot;
}
err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
-
return NULL;
}
@@ -400,44 +311,27 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
}
-enum php_ctlr_type {
- PCI,
- ISA,
- ACPI
-};
-
-int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
-
-int shpc_get_ctlr_slot_config( struct controller *ctrl,
- int *num_ctlr_slots,
- int *first_device_num,
- int *physical_slot_num,
- int *updown,
- int *flags);
-
struct hpc_ops {
- int (*power_on_slot ) (struct slot *slot);
- int (*slot_enable ) (struct slot *slot);
- int (*slot_disable ) (struct slot *slot);
- int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed);
- int (*get_power_status) (struct slot *slot, u8 *status);
- int (*get_attention_status) (struct slot *slot, u8 *status);
- int (*set_attention_status) (struct slot *slot, u8 status);
- int (*get_latch_status) (struct slot *slot, u8 *status);
- int (*get_adapter_status) (struct slot *slot, u8 *status);
-
- int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed);
- int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed);
- int (*get_adapter_speed) (struct slot *slot, enum pci_bus_speed *speed);
- int (*get_mode1_ECC_cap) (struct slot *slot, u8 *mode);
- int (*get_prog_int) (struct slot *slot, u8 *prog_int);
-
- int (*query_power_fault) (struct slot *slot);
- void (*green_led_on) (struct slot *slot);
- void (*green_led_off) (struct slot *slot);
- void (*green_led_blink) (struct slot *slot);
- void (*release_ctlr) (struct controller *ctrl);
- int (*check_cmd_status) (struct controller *ctrl);
+ int (*power_on_slot)(struct slot *slot);
+ int (*slot_enable)(struct slot *slot);
+ int (*slot_disable)(struct slot *slot);
+ int (*set_bus_speed_mode)(struct slot *slot, enum pci_bus_speed speed);
+ int (*get_power_status)(struct slot *slot, u8 *status);
+ int (*get_attention_status)(struct slot *slot, u8 *status);
+ int (*set_attention_status)(struct slot *slot, u8 status);
+ int (*get_latch_status)(struct slot *slot, u8 *status);
+ int (*get_adapter_status)(struct slot *slot, u8 *status);
+ int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
+ int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
+ int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed);
+ int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode);
+ int (*get_prog_int)(struct slot *slot, u8 *prog_int);
+ int (*query_power_fault)(struct slot *slot);
+ void (*green_led_on)(struct slot *slot);
+ void (*green_led_off)(struct slot *slot);
+ void (*green_led_blink)(struct slot *slot);
+ void (*release_ctlr)(struct controller *ctrl);
+ int (*check_cmd_status)(struct controller *ctrl);
};
#endif /* _SHPCHP_H */
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 4eac85b3d90..590cd3cbe01 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -104,23 +104,6 @@ static void make_slot_name(struct slot *slot)
slot->bus, slot->number);
}
-
-
-
-static int
-shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
- u8 busnum, u8 devnum)
-{
- int offset = devnum - ctrl->slot_device_offset;
-
- dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
- ctrl->slot_num_inc, offset);
- *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
- return 0;
-}
-
-
-
static int init_slots(struct controller *ctrl)
{
struct slot *slot;
@@ -128,7 +111,6 @@ static int init_slots(struct controller *ctrl)
struct hotplug_slot_info *info;
int retval = -ENOMEM;
int i;
- u32 sun;
for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
@@ -149,16 +131,11 @@ static int init_slots(struct controller *ctrl)
slot->hp_slot = i;
slot->ctrl = ctrl;
- slot->bus = ctrl->slot_bus;
+ slot->bus = ctrl->pci_dev->subordinate->number;
slot->device = ctrl->slot_device_offset + i;
slot->hpc_ops = ctrl->hpc_ops;
+ slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
mutex_init(&slot->lock);
-
- if (shpchprm_get_physical_slot_number(ctrl, &sun,
- slot->bus, slot->device))
- goto error_info;
-
- slot->number = sun;
INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
/* register this slot with the hotplug pci core */
@@ -211,42 +188,12 @@ void cleanup_slots(struct controller *ctrl)
}
}
-static int get_ctlr_slot_config(struct controller *ctrl)
-{
- int num_ctlr_slots;
- int first_device_num;
- int physical_slot_num;
- int updown;
- int rc;
- int flags;
-
- rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots,
- &first_device_num, &physical_slot_num,
- &updown, &flags);
- if (rc) {
- err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n",
- __FUNCTION__, ctrl->bus, ctrl->device);
- return -1;
- }
-
- ctrl->num_slots = num_ctlr_slots;
- ctrl->slot_device_offset = first_device_num;
- ctrl->first_slot = physical_slot_num;
- ctrl->slot_num_inc = updown; /* either -1 or 1 */
-
- dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d "
- "(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num,
- physical_slot_num, updown, ctrl->bus, ctrl->device);
-
- return 0;
-}
-
/*
* set_attention_status - Turns the Amber LED for a slot on, off or blink
*/
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -258,7 +205,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
static int enable_slot (struct hotplug_slot *hotplug_slot)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -267,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
static int disable_slot (struct hotplug_slot *hotplug_slot)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -276,7 +223,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -290,7 +237,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -304,7 +251,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -318,7 +265,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -332,7 +279,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -344,7 +291,7 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -358,7 +305,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
- struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+ struct slot *slot = get_slot(hotplug_slot);
int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
@@ -385,9 +332,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int rc;
struct controller *ctrl;
- struct slot *t_slot;
- int first_device_num; /* first PCI device number */
- int num_ctlr_slots; /* number of slots implemented */
if (!is_shpc_capable(pdev))
return -ENODEV;
@@ -408,47 +352,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, ctrl);
- ctrl->bus = pdev->bus->number;
- ctrl->slot_bus = pdev->subordinate->number;
- ctrl->device = PCI_SLOT(pdev->devfn);
- ctrl->function = PCI_FUNC(pdev->devfn);
-
- dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
- ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
-
- /*
- * Save configuration headers for this and subordinate PCI buses
- */
- rc = get_ctlr_slot_config(ctrl);
- if (rc) {
- err(msg_initialization_err, rc);
- goto err_out_release_ctlr;
- }
- first_device_num = ctrl->slot_device_offset;
- num_ctlr_slots = ctrl->num_slots;
-
- ctrl->add_support = 1;
-
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
- err(msg_initialization_err, 6);
+ err("%s: slot initialization failed\n", SHPC_MODULE_NAME);
goto err_out_release_ctlr;
}
- /* Now hpc_functions (slot->hpc_ops->functions) are ready */
- t_slot = shpchp_find_slot(ctrl, first_device_num);
-
- /* Check for operation bus speed */
- rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed);
- dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot);
-
- if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) {
- err(SHPC_MODULE_NAME ": Can't get current bus speed. "
- "Set to 33MHz PCI.\n");
- ctrl->speed = PCI_SPEED_33MHz;
- }
-
rc = shpchp_create_ctrl_files(ctrl);
if (rc)
goto err_cleanup_slots;
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 158ac783609..6bb84734cd6 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -57,9 +57,8 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
return 0;
}
-u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
+u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
{
- struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u32 event_type;
@@ -81,9 +80,8 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
}
-u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
+u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
{
- struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u8 getstatus;
u32 event_type;
@@ -120,9 +118,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
return 1;
}
-u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
+u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
{
- struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u32 event_type;
@@ -154,9 +151,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
return 1;
}
-u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
+u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
{
- struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u32 event_type;
@@ -497,10 +493,12 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = BLINKINGOFF_STATE;
- info(msg_button_off, p_slot->name);
+ info("PCI slot #%s - powering off due to button "
+ "press.\n", p_slot->name);
} else {
p_slot->state = BLINKINGON_STATE;
- info(msg_button_on, p_slot->name);
+ info("PCI slot #%s - powering on due to button "
+ "press.\n", p_slot->name);
}
/* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot);
@@ -523,7 +521,8 @@ static void handle_button_press_event(struct slot *p_slot)
else
p_slot->hpc_ops->green_led_off(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- info(msg_button_cancel, p_slot->name);
+ info("PCI slot #%s - action canceled due to button press\n",
+ p_slot->name);
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 83a5226ba9e..b7bede4b7c2 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -212,44 +212,40 @@
#define SLOT_SERR_INT_MASK 0x3
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
-static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */
-static int ctlr_seq_num = 0; /* Controller sequenc # */
-static spinlock_t list_lock;
-
static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
static irqreturn_t shpc_isr(int irq, void *dev_id);
-static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec);
+static void start_int_poll_timer(struct controller *ctrl, int sec);
static int hpc_check_cmd_status(struct controller *ctrl);
static inline u8 shpc_readb(struct controller *ctrl, int reg)
{
- return readb(ctrl->hpc_ctlr_handle->creg + reg);
+ return readb(ctrl->creg + reg);
}
static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val)
{
- writeb(val, ctrl->hpc_ctlr_handle->creg + reg);
+ writeb(val, ctrl->creg + reg);
}
static inline u16 shpc_readw(struct controller *ctrl, int reg)
{
- return readw(ctrl->hpc_ctlr_handle->creg + reg);
+ return readw(ctrl->creg + reg);
}
static inline void shpc_writew(struct controller *ctrl, int reg, u16 val)
{
- writew(val, ctrl->hpc_ctlr_handle->creg + reg);
+ writew(val, ctrl->creg + reg);
}
static inline u32 shpc_readl(struct controller *ctrl, int reg)
{
- return readl(ctrl->hpc_ctlr_handle->creg + reg);
+ return readl(ctrl->creg + reg);
}
static inline void shpc_writel(struct controller *ctrl, int reg, u32 val)
{
- writel(val, ctrl->hpc_ctlr_handle->creg + reg);
+ writel(val, ctrl->creg + reg);
}
static inline int shpc_indirect_read(struct controller *ctrl, int index,
@@ -268,21 +264,20 @@ static inline int shpc_indirect_read(struct controller *ctrl, int index,
/*
* This is the interrupt polling timeout function.
*/
-static void int_poll_timeout(unsigned long lphp_ctlr)
+static void int_poll_timeout(unsigned long data)
{
- struct php_ctlr_state_s *php_ctlr =
- (struct php_ctlr_state_s *)lphp_ctlr;
+ struct controller *ctrl = (struct controller *)data;
DBG_ENTER_ROUTINE
/* Poll for interrupt events. regs == NULL => polling */
- shpc_isr(0, php_ctlr->callback_instance_id);
+ shpc_isr(0, ctrl);
- init_timer(&php_ctlr->int_poll_timer);
+ init_timer(&ctrl->poll_timer);
if (!shpchp_poll_time)
shpchp_poll_time = 2; /* default polling interval is 2 sec */
- start_int_poll_timer(php_ctlr, shpchp_poll_time);
+ start_int_poll_timer(ctrl, shpchp_poll_time);
DBG_LEAVE_ROUTINE
}
@@ -290,16 +285,16 @@ static void int_poll_timeout(unsigned long lphp_ctlr)
/*
* This function starts the interrupt polling timer.
*/
-static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec)
+static void start_int_poll_timer(struct controller *ctrl, int sec)
{
/* Clamp to sane value */
if ((sec <= 0) || (sec > 60))
sec = 2;
- php_ctlr->int_poll_timer.function = &int_poll_timeout;
- php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;
- php_ctlr->int_poll_timer.expires = jiffies + sec * HZ;
- add_timer(&php_ctlr->int_poll_timer);
+ ctrl->poll_timer.function = &int_poll_timeout;
+ ctrl->poll_timer.data = (unsigned long)ctrl;
+ ctrl->poll_timer.expires = jiffies + sec * HZ;
+ add_timer(&ctrl->poll_timer);
}
static inline int is_ctrl_busy(struct controller *ctrl)
@@ -666,33 +661,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK);
}
-int shpc_get_ctlr_slot_config(struct controller *ctrl,
- int *num_ctlr_slots, /* number of slots in this HPC */
- int *first_device_num, /* PCI dev num of the first slot in this SHPC */
- int *physical_slot_num, /* phy slot num of the first slot in this SHPC */
- int *updown, /* physical_slot_num increament: 1 or -1 */
- int *flags)
-{
- u32 slot_config;
-
- DBG_ENTER_ROUTINE
-
- slot_config = shpc_readl(ctrl, SLOT_CONFIG);
- *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8;
- *num_ctlr_slots = slot_config & SLOT_NUM;
- *physical_slot_num = (slot_config & PSN) >> 16;
- *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
-
- dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num);
-
- DBG_LEAVE_ROUTINE
- return 0;
-}
-
static void hpc_release_ctlr(struct controller *ctrl)
{
- struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
- struct php_ctlr_state_s *p, *p_prev;
int i;
u32 slot_reg, serr_int;
@@ -722,40 +692,15 @@ static void hpc_release_ctlr(struct controller *ctrl)
serr_int &= ~SERR_INTR_RSVDZ_MASK;
shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
- if (shpchp_poll_mode) {
- del_timer(&php_ctlr->int_poll_timer);
- } else {
- if (php_ctlr->irq) {
- free_irq(php_ctlr->irq, ctrl);
- php_ctlr->irq = 0;
- pci_disable_msi(php_ctlr->pci_dev);
- }
- }
-
- if (php_ctlr->pci_dev) {
- iounmap(php_ctlr->creg);
- release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
- php_ctlr->pci_dev = NULL;
- }
-
- spin_lock(&list_lock);
- p = php_ctlr_list_head;
- p_prev = NULL;
- while (p) {
- if (p == php_ctlr) {
- if (p_prev)
- p_prev->pnext = p->pnext;
- else
- php_ctlr_list_head = p->pnext;
- break;
- } else {
- p_prev = p;
- p = p->pnext;
- }
+ if (shpchp_poll_mode)
+ del_timer(&ctrl->poll_timer);
+ else {
+ free_irq(ctrl->pci_dev->irq, ctrl);
+ pci_disable_msi(ctrl->pci_dev);
}
- spin_unlock(&list_lock);
- kfree(php_ctlr);
+ iounmap(ctrl->creg);
+ release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
/*
* If this is the last controller to be released, destroy the
@@ -764,8 +709,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
if (atomic_dec_and_test(&shpchp_num_controllers))
destroy_workqueue(shpchp_wq);
-DBG_LEAVE_ROUTINE
-
+ DBG_LEAVE_ROUTINE
}
static int hpc_power_on_slot(struct slot * slot)
@@ -891,7 +835,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
static irqreturn_t shpc_isr(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
- struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
u32 serr_int, slot_reg, intr_loc, intr_loc2;
int hp_slot;
@@ -942,20 +885,16 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
__FUNCTION__, hp_slot, slot_reg);
if (slot_reg & MRL_CHANGE_DETECTED)
- php_ctlr->switch_change_callback(
- hp_slot, php_ctlr->callback_instance_id);
+ shpchp_handle_switch_change(hp_slot, ctrl);
if (slot_reg & BUTTON_PRESS_DETECTED)
- php_ctlr->attention_button_callback(
- hp_slot, php_ctlr->callback_instance_id);
+ shpchp_handle_attention_button(hp_slot, ctrl);
if (slot_reg & PRSNT_CHANGE_DETECTED)
- php_ctlr->presence_change_callback(
- hp_slot , php_ctlr->callback_instance_id);
+ shpchp_handle_presence_change(hp_slot, ctrl);
if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
- php_ctlr->power_fault_callback(
- hp_slot, php_ctlr->callback_instance_id);
+ shpchp_handle_power_fault(hp_slot, ctrl);
/* Clear all slot events */
slot_reg &= ~SLOT_REG_RSVDZ_MASK;
@@ -1114,10 +1053,8 @@ static struct hpc_ops shpchp_hpc_ops = {
.release_ctlr = hpc_release_ctlr,
};
-int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
+int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
{
- struct php_ctlr_state_s *php_ctlr, *p;
- void *instance_id = ctrl;
int rc = -1, num_slots = 0;
u8 hp_slot;
u32 shpc_base_offset;
@@ -1128,16 +1065,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
- spin_lock_init(&list_lock);
- php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL);
-
- if (!php_ctlr) { /* allocate controller state data */
- err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
- goto abort;
- }
-
- php_ctlr->pci_dev = pdev; /* save pci_dev in context */
-
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450)) {
/* amd shpc driver doesn't use Base Offset; assume 0 */
@@ -1147,20 +1074,20 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
if (!ctrl->cap_offset) {
err("%s : cap_offset == 0\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
if (rc) {
err("%s: cannot read base_offset\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
rc = shpc_indirect_read(ctrl, 3, &tempdword);
if (rc) {
err("%s: cannot read slot config\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
num_slots = tempdword & SLOT_NUM;
dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
@@ -1170,7 +1097,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
if (rc) {
err("%s: cannot read creg (index = %d)\n",
__FUNCTION__, i);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
tempdword);
@@ -1187,24 +1114,24 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
rc = pci_enable_device(pdev);
if (rc) {
err("%s: pci_enable_device failed\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
err("%s: cannot reserve MMIO region\n", __FUNCTION__);
rc = -1;
- goto abort_free_ctlr;
+ goto abort;
}
- php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
- if (!php_ctlr->creg) {
+ ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
+ if (!ctrl->creg) {
err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
ctrl->mmio_size, ctrl->mmio_base);
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
rc = -1;
- goto abort_free_ctlr;
+ goto abort;
}
- dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
+ dbg("%s: ctrl->creg %p\n", __FUNCTION__, ctrl->creg);
mutex_init(&ctrl->crit_sect);
mutex_init(&ctrl->cmd_lock);
@@ -1212,23 +1139,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
/* Setup wait queue */
init_waitqueue_head(&ctrl->queue);
- /* Find the IRQ */
- php_ctlr->irq = pdev->irq;
- php_ctlr->attention_button_callback = shpchp_handle_attention_button,
- php_ctlr->switch_change_callback = shpchp_handle_switch_change;
- php_ctlr->presence_change_callback = shpchp_handle_presence_change;
- php_ctlr->power_fault_callback = shpchp_handle_power_fault;
- php_ctlr->callback_instance_id = instance_id;
-
- ctrl->hpc_ctlr_handle = php_ctlr;
ctrl->hpc_ops = &shpchp_hpc_ops;
/* Return PCI Controller Info */
slot_config = shpc_readl(ctrl, SLOT_CONFIG);
- php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
- php_ctlr->num_slots = slot_config & SLOT_NUM;
- dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset);
- dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots);
+ ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
+ ctrl->num_slots = slot_config & SLOT_NUM;
+ ctrl->first_slot = (slot_config & PSN) >> 16;
+ ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
@@ -1243,7 +1161,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
/* Mask the MRL sensor SERR Mask of individual slot in
* Slot SERR-INT Mask & clear all the existing event if any
*/
- for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
+ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
hp_slot, slot_reg);
@@ -1255,24 +1173,27 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
}
- if (shpchp_poll_mode) {/* Install interrupt polling code */
- /* Install and start the interrupt polling timer */
- init_timer(&php_ctlr->int_poll_timer);
- start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */
+ if (shpchp_poll_mode) {
+ /* Install interrupt polling timer. Start with 10 sec delay */
+ init_timer(&ctrl->poll_timer);
+ start_int_poll_timer(ctrl, 10);
} else {
/* Installs the interrupt handler */
rc = pci_enable_msi(pdev);
if (rc) {
info("Can't get msi for the hotplug controller\n");
info("Use INTx for the hotplug controller\n");
- } else
- php_ctlr->irq = pdev->irq;
+ }
- rc = request_irq(php_ctlr->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *) ctrl);
- dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
+ rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
+ MY_NAME, (void *)ctrl);
+ dbg("%s: request_irq %d for hpc%d (returns %d)\n",
+ __FUNCTION__, ctrl->pci_dev->irq,
+ atomic_read(&shpchp_num_controllers), rc);
if (rc) {
- err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
- goto abort_free_ctlr;
+ err("Can't get irq %d for the hotplug controller\n",
+ ctrl->pci_dev->irq);
+ goto abort_iounmap;
}
}
dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
@@ -1280,24 +1201,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
PCI_FUNC(pdev->devfn), pdev->irq);
get_hp_hw_control_from_firmware(pdev);
- /* Add this HPC instance into the HPC list */
- spin_lock(&list_lock);
- if (php_ctlr_list_head == 0) {
- php_ctlr_list_head = php_ctlr;
- p = php_ctlr_list_head;
- p->pnext = NULL;
- } else {
- p = php_ctlr_list_head;
-
- while (p->pnext)
- p = p->pnext;
-
- p->pnext = php_ctlr;
- }
- spin_unlock(&list_lock);
-
- ctlr_seq_num++;
-
/*
* If this is the first controller to be initialized,
* initialize the shpchpd work queue
@@ -1306,14 +1209,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
shpchp_wq = create_singlethread_workqueue("shpchpd");
if (!shpchp_wq) {
rc = -ENOMEM;
- goto abort_free_ctlr;
+ goto abort_iounmap;
}
}
/*
* Unmask all event interrupts of all slots
*/
- for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
+ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
hp_slot, slot_reg);
@@ -1336,10 +1239,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
return 0;
/* We end up here for the many possible ways to fail this API. */
-abort_free_ctlr:
- if (php_ctlr->creg)
- iounmap(php_ctlr->creg);
- kfree(php_ctlr);
+abort_iounmap:
+ iounmap(ctrl->creg);
abort:
DBG_LEAVE_ROUTINE
return rc;
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 0a8d1cce9fa..279c940a003 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -99,14 +99,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
int pos;
int irq;
- pos = pci_find_capability(dev, PCI_CAP_ID_HT);
- while (pos) {
- u8 subtype;
- pci_read_config_byte(dev, pos + 3, &subtype);
- if (subtype == HT_CAPTYPE_IRQ)
- break;
- pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT);
- }
+ pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
if (!pos)
return -EINVAL;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e5ae3a0c13b..92d5e8db0de 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -150,8 +150,7 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
}
/**
- * pci_match_device - Tell if a PCI device structure has a matching
- * PCI device id structure
+ * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
* @drv: the PCI driver to match against
* @dev: the PCI device structure to match against
*
@@ -162,14 +161,9 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
const struct pci_device_id *pci_match_device(struct pci_driver *drv,
struct pci_dev *dev)
{
- const struct pci_device_id *id;
struct pci_dynid *dynid;
- id = pci_match_id(drv->id_table, dev);
- if (id)
- return id;
-
- /* static ids didn't match, lets look at the dynamic ones */
+ /* Look at the dynamic ids first, before the static ones */
spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (pci_match_one_device(&dynid->id, dev)) {
@@ -178,7 +172,8 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv,
}
}
spin_unlock(&drv->dynids.lock);
- return NULL;
+
+ return pci_match_id(drv->id_table, dev);
}
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
@@ -357,6 +352,8 @@ static int pci_device_resume_early(struct device * dev)
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
+ pci_fixup_device(pci_fixup_resume, pci_dev);
+
if (drv && drv->resume_early)
error = drv->resume_early(pci_dev);
return error;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5a14b73cf3a..206c834d263 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -68,12 +68,14 @@ pci_max_busnr(void)
#endif /* 0 */
-static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
+#define PCI_FIND_CAP_TTL 48
+
+static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
+ u8 pos, int cap, int *ttl)
{
u8 id;
- int ttl = 48;
- while (ttl--) {
+ while ((*ttl)--) {
pci_bus_read_config_byte(bus, devfn, pos, &pos);
if (pos < 0x40)
break;
@@ -89,6 +91,14 @@ static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos,
return 0;
}
+static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
+ u8 pos, int cap)
+{
+ int ttl = PCI_FIND_CAP_TTL;
+
+ return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
+}
+
int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
{
return __pci_find_next_cap(dev->bus, dev->devfn,
@@ -96,10 +106,10 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
}
EXPORT_SYMBOL_GPL(pci_find_next_capability);
-static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
+static int __pci_bus_find_cap_start(struct pci_bus *bus,
+ unsigned int devfn, u8 hdr_type)
{
u16 status;
- u8 pos;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
@@ -108,15 +118,14 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
switch (hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
- pos = PCI_CAPABILITY_LIST;
- break;
+ return PCI_CAPABILITY_LIST;
case PCI_HEADER_TYPE_CARDBUS:
- pos = PCI_CB_CAPABILITY_LIST;
- break;
+ return PCI_CB_CAPABILITY_LIST;
default:
return 0;
}
- return __pci_find_next_cap(bus, devfn, pos, cap);
+
+ return 0;
}
/**
@@ -140,7 +149,13 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
*/
int pci_find_capability(struct pci_dev *dev, int cap)
{
- return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap);
+ int pos;
+
+ pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
+ if (pos)
+ pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
+
+ return pos;
}
/**
@@ -158,11 +173,16 @@ int pci_find_capability(struct pci_dev *dev, int cap)
*/
int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
{
+ int pos;
u8 hdr_type;
pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
- return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
+ pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & 0x7f);
+ if (pos)
+ pos = __pci_find_next_cap(bus, devfn, pos, cap);
+
+ return pos;
}
/**
@@ -214,6 +234,75 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
}
EXPORT_SYMBOL_GPL(pci_find_ext_capability);
+static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
+{
+ int rc, ttl = PCI_FIND_CAP_TTL;
+ u8 cap, mask;
+
+ if (ht_cap == HT_CAPTYPE_SLAVE || ht_cap == HT_CAPTYPE_HOST)
+ mask = HT_3BIT_CAP_MASK;
+ else
+ mask = HT_5BIT_CAP_MASK;
+
+ pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos,
+ PCI_CAP_ID_HT, &ttl);
+ while (pos) {
+ rc = pci_read_config_byte(dev, pos + 3, &cap);
+ if (rc != PCIBIOS_SUCCESSFUL)
+ return 0;
+
+ if ((cap & mask) == ht_cap)
+ return pos;
+
+ pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn,
+ pos + PCI_CAP_LIST_NEXT,
+ PCI_CAP_ID_HT, &ttl);
+ }
+
+ return 0;
+}
+/**
+ * pci_find_next_ht_capability - query a device's Hypertransport capabilities
+ * @dev: PCI device to query
+ * @pos: Position from which to continue searching
+ * @ht_cap: Hypertransport capability code
+ *
+ * To be used in conjunction with pci_find_ht_capability() to search for
+ * all capabilities matching @ht_cap. @pos should always be a value returned
+ * from pci_find_ht_capability().
+ *
+ * NB. To be 100% safe against broken PCI devices, the caller should take
+ * steps to avoid an infinite loop.
+ */
+int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap)
+{
+ return __pci_find_next_ht_cap(dev, pos + PCI_CAP_LIST_NEXT, ht_cap);
+}
+EXPORT_SYMBOL_GPL(pci_find_next_ht_capability);
+
+/**
+ * pci_find_ht_capability - query a device's Hypertransport capabilities
+ * @dev: PCI device to query
+ * @ht_cap: Hypertransport capability code
+ *
+ * Tell if a device supports a given Hypertransport capability.
+ * Returns an address within the device's PCI configuration space
+ * or 0 in case the device does not support the request capability.
+ * The address points to the PCI capability, of type PCI_CAP_ID_HT,
+ * which has a Hypertransport capability matching @ht_cap.
+ */
+int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
+{
+ int pos;
+
+ pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
+ if (pos)
+ pos = __pci_find_next_ht_cap(dev, pos, ht_cap);
+
+ return pos;
+}
+EXPORT_SYMBOL_GPL(pci_find_ht_capability);
+
/**
* pci_find_parent_resource - return resource region of parent bus of given region
* @dev: PCI device structure contains resources to be searched
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 55866b6b26f..6f5fabbd14e 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -148,7 +148,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
{
struct aer_rpc *rpc;
- if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
+ if (!(rpc = kmalloc(sizeof(struct aer_rpc),
GFP_KERNEL)))
return NULL;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index b4da7954611..f17e7ed2b2a 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -90,7 +90,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
return -ENODEV;
pci_set_master(dev);
- if (!dev->irq) {
+ if (!dev->irq && dev->pin) {
printk(KERN_WARNING
"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
__FUNCTION__, dev->device, dev->vendor);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6a3c1e72890..0e0401dd02c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -639,6 +639,8 @@ static void pci_read_irq(struct pci_dev *dev)
dev->irq = irq;
}
+#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
+
/**
* pci_setup_device - fill in class and map information of a device
* @dev: the device structure to fill
@@ -692,18 +694,18 @@ static int pci_setup_device(struct pci_dev * dev)
if ((progif & 1) == 0) {
dev->resource[0].start = 0x1F0;
dev->resource[0].end = 0x1F7;
- dev->resource[0].flags = IORESOURCE_IO;
+ dev->resource[0].flags = LEGACY_IO_RESOURCE;
dev->resource[1].start = 0x3F6;
dev->resource[1].end = 0x3F6;
- dev->resource[1].flags = IORESOURCE_IO;
+ dev->resource[1].flags = LEGACY_IO_RESOURCE;
}
if ((progif & 4) == 0) {
dev->resource[2].start = 0x170;
dev->resource[2].end = 0x177;
- dev->resource[2].flags = IORESOURCE_IO;
+ dev->resource[2].flags = LEGACY_IO_RESOURCE;
dev->resource[3].start = 0x376;
dev->resource[3].end = 0x376;
- dev->resource[3].flags = IORESOURCE_IO;
+ dev->resource[3].flags = LEGACY_IO_RESOURCE;
}
}
break;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 99cf3337976..4a6760a3b31 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -23,7 +23,7 @@ static loff_t
proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
{
loff_t new = -1;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
mutex_lock(&inode->i_mutex);
switch (whence) {
@@ -48,7 +48,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
static ssize_t
proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
- const struct inode *ino = file->f_dentry->d_inode;
+ const struct inode *ino = file->f_path.dentry->d_inode;
const struct proc_dir_entry *dp = PDE(ino);
struct pci_dev *dev = dp->data;
unsigned int pos = *ppos;
@@ -130,7 +130,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
static ssize_t
proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
{
- const struct inode *ino = file->f_dentry->d_inode;
+ const struct inode *ino = file->f_path.dentry->d_inode;
const struct proc_dir_entry *dp = PDE(ino);
struct pci_dev *dev = dp->data;
int pos = *ppos;
@@ -245,7 +245,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
#ifdef HAVE_PCI_MMAP
static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
const struct proc_dir_entry *dp = PDE(inode);
struct pci_dev *dev = dp->data;
struct pci_filp_private *fpriv = file->private_data;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 9ca9b9bf616..c913ea4e545 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -36,7 +36,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRID
/* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441FX/PPro MTRRs */
-static void __devinit quirk_passive_release(struct pci_dev *dev)
+static void quirk_passive_release(struct pci_dev *dev)
{
struct pci_dev *d = NULL;
unsigned char dlc;
@@ -53,6 +53,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -134,7 +135,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quir
* Updated based on further information from the site and also on
* information provided by VIA
*/
-static void __devinit quirk_vialatency(struct pci_dev *dev)
+static void quirk_vialatency(struct pci_dev *dev)
{
struct pci_dev *p;
u8 rev;
@@ -185,6 +186,10 @@ exit:
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
+/* Must restore this on a resume from RAM */
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
/*
* VIA Apollo VP3 needs ETBF on BT848/878
@@ -532,7 +537,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235
* TODO: When we have device-specific interrupt routers,
* this code will go away from quirks.
*/
-static void __devinit quirk_via_ioapic(struct pci_dev *dev)
+static void quirk_via_ioapic(struct pci_dev *dev)
{
u8 tmp;
@@ -548,6 +553,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
pci_write_config_byte (dev, 0x58, tmp);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
/*
* VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
@@ -555,7 +561,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_i
* Set this bit to get rid of cycle wastage.
* Otherwise uncritical.
*/
-static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
+static void quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
{
u8 misc_control2;
#define BYPASS_APIC_DEASSERT 8
@@ -567,6 +573,7 @@ static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert);
/*
* The AMD io apic can hang the box when an apic irq is masked.
@@ -600,7 +607,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
#define AMD8131_revB0 0x11
#define AMD8131_MISC 0x40
#define AMD8131_NIOAMODE_BIT 0
-static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
+static void quirk_amd_8131_ioapic(struct pci_dev *dev)
{
unsigned char revid, tmp;
@@ -616,6 +623,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
#endif /* CONFIG_X86_IO_APIC */
@@ -641,48 +649,67 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
+
/*
- * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
- * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
- * when written, it makes an internal connection to the PIC.
- * For these devices, this register is defined to be 4 bits wide.
- * Normally this is fine. However for IO-APIC motherboards, or
- * non-x86 architectures (yes Via exists on PPC among other places),
- * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
- * interrupts delivered properly.
- *
- * Some of the on-chip devices are actually '586 devices' so they are
- * listed here.
+ * VIA bridges which have VLink
*/
-static int via_irq_fixup_needed = -1;
+static int via_vlink_dev_lo = -1, via_vlink_dev_hi = 18;
-/*
- * As some VIA hardware is available in PCI-card form, we need to restrict
- * this quirk to VIA PCI hardware built onto VIA-based motherboards only.
- * We try to locate a VIA southbridge before deciding whether the quirk
- * should be applied.
+static void quirk_via_bridge(struct pci_dev *dev)
+{
+ /* See what bridge we have and find the device ranges */
+ switch (dev->device) {
+ case PCI_DEVICE_ID_VIA_82C686:
+ /* The VT82C686 is special, it attaches to PCI and can have
+ any device number. All its subdevices are functions of
+ that single device. */
+ via_vlink_dev_lo = PCI_SLOT(dev->devfn);
+ via_vlink_dev_hi = PCI_SLOT(dev->devfn);
+ break;
+ case PCI_DEVICE_ID_VIA_8237:
+ case PCI_DEVICE_ID_VIA_8237A:
+ via_vlink_dev_lo = 15;
+ break;
+ case PCI_DEVICE_ID_VIA_8235:
+ via_vlink_dev_lo = 16;
+ break;
+ case PCI_DEVICE_ID_VIA_8231:
+ case PCI_DEVICE_ID_VIA_8233_0:
+ case PCI_DEVICE_ID_VIA_8233A:
+ case PCI_DEVICE_ID_VIA_8233C_0:
+ via_vlink_dev_lo = 17;
+ break;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233C_0, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A, quirk_via_bridge);
+
+/**
+ * quirk_via_vlink - VIA VLink IRQ number update
+ * @dev: PCI device
+ *
+ * If the device we are dealing with is on a PIC IRQ we need to
+ * ensure that the IRQ line register which usually is not relevant
+ * for PCI cards, is actually written so that interrupts get sent
+ * to the right place.
+ * We only do this on systems where a VIA south bridge was detected,
+ * and only for VIA devices on the motherboard (see quirk_via_bridge
+ * above).
*/
-static const struct pci_device_id via_irq_fixup_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = PCI_CLASS_BRIDGE_ISA << 8,
- .class_mask = 0xffff00,
- },
- { 0, },
-};
-
-static void quirk_via_irq(struct pci_dev *dev)
+
+static void quirk_via_vlink(struct pci_dev *dev)
{
u8 irq, new_irq;
- if (via_irq_fixup_needed == -1)
- via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl);
-
- if (!via_irq_fixup_needed)
+ /* Check if we have VLink at all */
+ if (via_vlink_dev_lo == -1)
return;
new_irq = dev->irq;
@@ -691,15 +718,23 @@ static void quirk_via_irq(struct pci_dev *dev)
if (!new_irq || new_irq > 15)
return;
+ /* Internal device ? */
+ if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) > via_vlink_dev_hi ||
+ PCI_SLOT(dev->devfn) < via_vlink_dev_lo)
+ return;
+
+ /* This is an internal VLink device on a PIC interrupt. The BIOS
+ ought to have set this but may not have, so we redo it */
+
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq) {
- printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
+ printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n",
pci_name(dev), irq, new_irq);
udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
}
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink);
/*
* VIA VT82C598 has its device ID settable and many BIOSes
@@ -720,13 +755,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt
* do this even if the Linux CardBus driver is not loaded, because
* the Linux i82365 driver does not (and should not) handle CardBus.
*/
-static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
+static void quirk_cardbus_legacy(struct pci_dev *dev)
{
if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
return;
pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
+DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
/*
* Following the PCI ordering rules is optional on the AMD762. I'm not
@@ -735,7 +771,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
* To be fair to AMD, it follows the spec by default, its BIOS people
* who turn it off!
*/
-static void __devinit quirk_amd_ordering(struct pci_dev *dev)
+static void quirk_amd_ordering(struct pci_dev *dev)
{
u32 pcic;
pci_read_config_dword(dev, 0x4C, &pcic);
@@ -749,6 +785,7 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
/*
* DreamWorks provided workaround for Dunord I-3000 problem
@@ -784,7 +821,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge
* datasheets found at http://www.national.com/ds/GX for info on what
* these bits do. <christer@weinigel.se>
*/
-static void __init quirk_mediagx_master(struct pci_dev *dev)
+static void quirk_mediagx_master(struct pci_dev *dev)
{
u8 reg;
pci_read_config_byte(dev, 0x41, &reg);
@@ -795,13 +832,14 @@ static void __init quirk_mediagx_master(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
/*
* Ensure C0 rev restreaming is off. This is normally done by
* the BIOS but in the odd case it is not the results are corruption
* hence the presence of a Linux check
*/
-static void __init quirk_disable_pxb(struct pci_dev *pdev)
+static void quirk_disable_pxb(struct pci_dev *pdev)
{
u16 config;
u8 rev;
@@ -817,7 +855,25 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
+
+
+static void __devinit quirk_sb600_sata(struct pci_dev *pdev)
+{
+ /* set sb600 sata to ahci mode */
+ if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+ u8 tmp;
+
+ pci_read_config_byte(pdev, 0x40, &tmp);
+ pci_write_config_byte(pdev, 0x40, tmp|1);
+ pci_write_config_byte(pdev, 0x9, 1);
+ pci_write_config_byte(pdev, 0xa, 6);
+ pci_write_config_byte(pdev, 0x40, tmp);
+ pdev->class = 0x010601;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata);
/*
* Serverworks CSB5 IDE does not fully support native mode
@@ -874,7 +930,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e
* runs everywhere at present we suppress the printk output in most
* irrelevant cases.
*/
-static void __init k8t_sound_hostbridge(struct pci_dev *dev)
+static void k8t_sound_hostbridge(struct pci_dev *dev)
{
unsigned char val;
@@ -893,8 +949,8 @@ static void __init k8t_sound_hostbridge(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
-#ifndef CONFIG_ACPI_SLEEP
/*
* On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
* is not activated. The myth is that Asus said that they do not want the
@@ -906,12 +962,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_ho
* bridge. Unfortunately, this device has no subvendor/subdevice ID. So it
* becomes necessary to do this tweak in two steps -- I've chosen the Host
* bridge as trigger.
- *
- * Actually, leaving it unhidden and not redoing the quirk over suspend2ram
- * will cause thermal management to break down, and causing machine to
- * overheat.
*/
-static int __initdata asus_hides_smbus;
+static int asus_hides_smbus;
static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
{
@@ -958,6 +1010,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x186a: /* M6Ne notebook */
asus_hides_smbus = 1;
}
+ if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
+ switch (dev->subsystem_device) {
+ case 0x80f2: /* P4P800-X */
+ asus_hides_smbus = 1;
+ }
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
switch (dev->subsystem_device) {
case 0x1882: /* M6V notebook */
@@ -1019,7 +1076,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, as
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
-static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
+static void asus_hides_smbus_lpc(struct pci_dev *dev)
{
u16 val;
@@ -1042,8 +1099,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asu
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
-static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
+static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
{
u32 val, rcba;
void __iomem *base;
@@ -1059,19 +1122,19 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
-
-#endif
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
*/
-static void __init quirk_sis_96x_smbus(struct pci_dev *dev)
+static void quirk_sis_96x_smbus(struct pci_dev *dev)
{
u8 val = 0;
- printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
- pci_read_config_byte(dev, 0x77, &val);
- pci_write_config_byte(dev, 0x77, val & ~0x10);
pci_read_config_byte(dev, 0x77, &val);
+ if (val & 0x10) {
+ printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
+ pci_write_config_byte(dev, 0x77, val & ~0x10);
+ }
}
/*
@@ -1086,7 +1149,7 @@ static int __devinitdata sis_96x_compatible = 0;
#define SIS_DETECT_REGISTER 0x40
-static void __init quirk_sis_503(struct pci_dev *dev)
+static void quirk_sis_503(struct pci_dev *dev)
{
u8 reg;
u16 devid;
@@ -1103,11 +1166,12 @@ static void __init quirk_sis_503(struct pci_dev *dev)
printk(KERN_WARNING "Uncovering SIS%x that hid as a SIS503 (compatible=%d)\n", devid, sis_96x_compatible);
/*
- * Ok, it now shows up as a 96x.. The 96x quirks are after
- * the 503 quirk in the quirk table, so they'll automatically
- * run and enable things like the SMBus device
+ * Ok, it now shows up as a 96x.. run the 96x quirk by
+ * hand in case it has already been processed.
+ * (depends on link order, which is apparently not guaranteed)
*/
dev->device = devid;
+ quirk_sis_96x_smbus(dev);
}
static void __init quirk_sis_96x_compatible(struct pci_dev *dev)
@@ -1122,13 +1186,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
/*
* On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller
* and MC97 modem controller are disabled when a second PCI soundcard is
* present. This patch, tweaking the VT8237 ISA bridge, enables them.
* -- bjd
*/
-static void __init asus_hides_ac97_lpc(struct pci_dev *dev)
+static void asus_hides_ac97_lpc(struct pci_dev *dev)
{
u8 val;
int asus_hides_ac97 = 0;
@@ -1159,6 +1224,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
+
+
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
+
#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
/*
@@ -1167,7 +1240,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_
* the PCI scanning.
*/
-static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
+static void quirk_jmicron_dualfn(struct pci_dev *pdev)
{
u32 conf;
u8 hdr;
@@ -1189,8 +1262,8 @@ static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
pci_read_config_dword(pdev, 0x40, &conf);
/* Enable dual function mode, AHCI on fn 0, IDE fn1 */
/* Set the class codes correctly and then direct IDE 0 */
- conf &= ~0x000F0200; /* Clear bit 9 and 16-19 */
- conf |= 0x00C20002; /* Set bit 1, 17, 22, 23 */
+ conf &= ~0x000FF200; /* Clear bit 9 and 12-19 */
+ conf |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
pci_write_config_dword(pdev, 0x40, conf);
/* Reconfigure so that the PCI scanner discovers the
@@ -1205,6 +1278,7 @@ static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
#endif
@@ -1532,6 +1606,8 @@ extern struct pci_fixup __start_pci_fixups_final[];
extern struct pci_fixup __end_pci_fixups_final[];
extern struct pci_fixup __start_pci_fixups_enable[];
extern struct pci_fixup __end_pci_fixups_enable[];
+extern struct pci_fixup __start_pci_fixups_resume[];
+extern struct pci_fixup __end_pci_fixups_resume[];
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
@@ -1559,6 +1635,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
end = __end_pci_fixups_enable;
break;
+ case pci_fixup_resume:
+ start = __start_pci_fixups_resume;
+ end = __end_pci_fixups_resume;
+ break;
+
default:
/* stupid compiler warning, you would think with an enum... */
return;
@@ -1596,7 +1677,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
* Force it to be linked by setting the corresponding control bit in the
* config space.
*/
-static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
+static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
{
uint8_t b;
if (pci_read_config_byte(dev, 0xf41, &b) == 0) {
@@ -1610,6 +1691,8 @@ static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_pcie_aer_ext_cap);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
+ quirk_nvidia_ck804_pcie_aer_ext_cap);
#ifdef CONFIG_PCI_MSI
/* To disable MSI globally */
@@ -1644,19 +1727,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
* return 1 if a HT MSI capability is found and enabled */
static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
{
- u8 pos;
- int ttl;
- for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48;
- pos && ttl;
- pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) {
- u32 cap_hdr;
- /* MSI mapping section according to Hypertransport spec */
- if (pci_read_config_dword(dev, pos, &cap_hdr) == 0
- && (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) {
- printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n",
- pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled");
- return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */
+ int pos, ttl = 48;
+
+ pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+ while (pos && ttl--) {
+ u8 flags;
+
+ if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
+ &flags) == 0)
+ {
+ printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n",
+ flags & HT_MSI_FLAGS_ENABLE ?
+ "enabled" : "disabled", pci_name(dev));
+ return (flags & HT_MSI_FLAGS_ENABLE) != 0;
}
+
+ pos = pci_find_next_ht_capability(dev, pos,
+ HT_CAPTYPE_MSI_MAPPING);
}
return 0;
}
@@ -1688,8 +1775,9 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
* a single one having MSI is enough to be sure that MSI are supported.
*/
pdev = pci_get_slot(dev->bus, 0);
- if (dev->subordinate && !msi_ht_cap_enabled(dev)
- && !msi_ht_cap_enabled(pdev)) {
+ if (!pdev)
+ return;
+ if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
printk(KERN_WARNING "PCI: MSI quirk detected. "
"MSI disabled on chipset %s.\n",
pci_name(dev));
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 2f13eba5d5a..b2653c4afe9 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -193,6 +193,15 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor,
struct pci_dev *dev;
WARN_ON(in_interrupt());
+
+ /*
+ * pci_find_subsys() can be called on the ide_setup() path, super-early
+ * in boot. But the down_read() will enable local interrupts, which
+ * can cause some machines to crash. So here we detect and flag that
+ * situation and bail out early.
+ */
+ if (unlikely(list_empty(&pci_devices)))
+ return NULL;
down_read(&pci_bus_sem);
n = from ? from->global_list.next : pci_devices.next;
@@ -259,6 +268,15 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
struct pci_dev *dev;
WARN_ON(in_interrupt());
+
+ /*
+ * pci_get_subsys() can potentially be called by drivers super-early
+ * in boot. But the down_read() will enable local interrupts, which
+ * can cause some machines to crash. So here we detect and flag that
+ * situation and bail out early.
+ */
+ if (unlikely(list_empty(&pci_devices)))
+ return NULL;
down_read(&pci_bus_sem);
n = from ? from->global_list.next : pci_devices.next;
@@ -413,6 +431,24 @@ exit:
return dev;
}
+const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
+{
+ struct pci_dev *dev;
+ const struct pci_device_id *found = NULL;
+
+ WARN_ON(in_interrupt());
+ down_read(&pci_bus_sem);
+ while (ids->vendor || ids->subvendor || ids->class_mask) {
+ list_for_each_entry(dev, &pci_devices, global_list) {
+ if ((found = pci_match_one_device(ids, dev)) != NULL)
+ break;
+ }
+ ids++;
+ }
+ up_read(&pci_bus_sem);
+ return found;
+}
+
/**
* pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
* @ids: A pointer to a null terminated list of struct pci_device_id structures
@@ -426,25 +462,11 @@ exit:
*/
int pci_dev_present(const struct pci_device_id *ids)
{
- struct pci_dev *dev;
- int found = 0;
-
- WARN_ON(in_interrupt());
- down_read(&pci_bus_sem);
- while (ids->vendor || ids->subvendor || ids->class_mask) {
- list_for_each_entry(dev, &pci_devices, global_list) {
- if (pci_match_one_device(ids, dev)) {
- found = 1;
- goto exit;
- }
- }
- ids++;
- }
-exit:
- up_read(&pci_bus_sem);
- return found;
+ return pci_find_present(ids) == NULL ? 0 : 1;
}
+
EXPORT_SYMBOL(pci_dev_present);
+EXPORT_SYMBOL(pci_find_present);
EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_device_reverse);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 8f7bcf56f14..89f3036f0de 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -41,7 +41,7 @@
* have a P2P bridge below a cardbus bridge, we need 4K.
*/
#define CARDBUS_IO_SIZE (256)
-#define CARDBUS_MEM_SIZE (32*1024*1024)
+#define CARDBUS_MEM_SIZE (64*1024*1024)
static void __devinit
pbus_assign_resources_sorted(struct pci_bus *bus)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index ab78e4bbdd8..cb4ced3560e 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -33,11 +33,22 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
u32 new, check, mask;
int reg;
- /* Ignore resources for unimplemented BARs and unused resource slots
- for 64 bit BARs. */
+ /*
+ * Ignore resources for unimplemented BARs and unused resource slots
+ * for 64 bit BARs.
+ */
if (!res->flags)
return;
+ /*
+ * Ignore non-moveable resources. This might be legacy resources for
+ * which no functional BAR register exists or another important
+ * system resource we should better not move around in system address
+ * space.
+ */
+ if (res->flags & IORESOURCE_PCI_FIXED)
+ return;
+
pcibios_resource_to_bus(dev, &region, res);
pr_debug(" got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
@@ -212,6 +223,10 @@ pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
resource_size_t r_align;
r = &dev->resource[i];
+
+ if (r->flags & IORESOURCE_PCI_FIXED)
+ continue;
+
r_align = r->end - r->start;
if (!(r->flags) || r->parent)
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 52d4a38b366..3334f22a86c 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -230,7 +230,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
if (!io)
return -ENODEV;
- cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ cf = kzalloc(sizeof *cf, GFP_KERNEL);
if (!cf)
return -ENOMEM;
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 06bf7f48836..e65a6b8188f 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -220,7 +220,7 @@ static int __devinit omap_cf_probe(struct device *dev)
if (irq < 0)
return -EINVAL;
- cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+ cf = kzalloc(sizeof *cf, GFP_KERNEL);
if (!cf)
return -ENOMEM;
init_timer(&cf->timer);
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index d077870c673..327372b7a54 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -486,7 +486,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,
user_info_t *user;
int ret;
- ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode));
+ ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));
if (count < 4)
return -EINVAL;
@@ -511,7 +511,7 @@ 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)
{
- ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
+ ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));
if (count != 4)
return -EINVAL;
@@ -529,7 +529,7 @@ static u_int ds_poll(struct file *file, poll_table *wait)
struct pcmcia_socket *s;
user_info_t *user;
- ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));
+ ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));
user = file->private_data;
if (CHECK_USER(user))
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 3ac5b123215..a0b158704ca 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -395,7 +395,7 @@ static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigne
struct pnp_id * id;
if (!dev)
return;
- id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -419,7 +419,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
struct pnp_dev *dev;
isapnp_peek(tmp, size);
- dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev)
return NULL;
dev->number = number;
@@ -450,7 +450,7 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option,
unsigned long bits;
isapnp_peek(tmp, size);
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (tmp[1] << 8) | tmp[0];
@@ -474,7 +474,7 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option,
struct pnp_dma *dma;
isapnp_peek(tmp, size);
- dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = tmp[0];
@@ -494,7 +494,7 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option,
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (tmp[2] << 8) | tmp[1];
@@ -517,7 +517,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option,
struct pnp_port *port;
isapnp_peek(tmp, size);
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (tmp[1] << 8) | tmp[0];
@@ -539,7 +539,7 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
@@ -562,7 +562,7 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -584,7 +584,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option,
struct pnp_mem *mem;
isapnp_peek(tmp, size);
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1];
@@ -829,7 +829,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data)
static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device)
{
- struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ struct pnp_id * id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!id)
return;
sprintf(id->id, "%c%c%c%x%x%x%x",
@@ -865,7 +865,7 @@ static int __init isapnp_build_device_list(void)
header[4], header[5], header[6], header[7], header[8]);
printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
#endif
- if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
+ if ((card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL)
continue;
card->number = csn;
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 958c11bedd0..d21f3c1e72f 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -56,7 +56,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
- struct inode *ino = file->f_dentry->d_inode;
+ struct inode *ino = file->f_path.dentry->d_inode;
struct proc_dir_entry *dp = PDE(ino);
struct pnp_dev *dev = dp->data;
int pos = *ppos;
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 6cf34a63c79..62eda5d5902 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -139,7 +139,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
return 0;
pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
- dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
if (!dev) {
pnp_err("Out of memory");
return -ENOMEM;
@@ -169,7 +169,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
dev->number = num;
/* set the initial values for the PnP device */
- dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
goto err;
pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
@@ -201,7 +201,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
for (i = 0; i < cid_list->count; i++) {
if (!ispnpidacpi(cid_list->id[i].value))
continue;
- dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
continue;
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 379048fdf05..7a535542fe9 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -298,7 +298,7 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso
if (p->channel_count == 0)
return;
- dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
@@ -354,7 +354,7 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option,
if (p->interrupt_count == 0)
return;
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
@@ -375,7 +375,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
if (p->interrupt_count == 0)
return;
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
@@ -396,7 +396,7 @@ pnpacpi_parse_port_option(struct pnp_option *option,
if (io->address_length == 0)
return;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = io->minimum;
@@ -417,7 +417,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option,
if (io->address_length == 0)
return;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = io->address;
@@ -436,7 +436,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option,
if (p->address_length == 0)
return;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->minimum;
@@ -459,7 +459,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option,
if (p->address_length == 0)
return;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = p->minimum;
@@ -482,7 +482,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
if (p->address_length == 0)
return;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = p->address;
@@ -514,7 +514,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
return;
if (p->resource_type == ACPI_MEMORY_RANGE) {
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = p->minimum;
@@ -524,7 +524,7 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
pnp_register_mem_resource(option, mem);
} else if (p->resource_type == ACPI_IO_RANGE) {
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = p->minimum;
@@ -721,7 +721,7 @@ int pnpacpi_build_resource_template(acpi_handle handle,
if (!res_cnt)
return -EINVAL;
buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
- buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
+ buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
if (!buffer->pointer)
return -ENOMEM;
pnp_dbg("Res cnt %d", res_cnt);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 33adeba1a31..95738dbd5d4 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -109,10 +109,10 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
if (!current->fs->root) {
return -EAGAIN;
}
- if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) {
+ if (!(envp = kcalloc(20, sizeof (char *), GFP_KERNEL))) {
return -ENOMEM;
}
- if (!(buf = kcalloc (1, 256, GFP_KERNEL))) {
+ if (!(buf = kzalloc(256, GFP_KERNEL))) {
kfree (envp);
return -ENOMEM;
}
@@ -220,7 +220,7 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table
if(!pnpbios_is_dynamic(dev))
return -EPERM;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -243,7 +243,7 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table
if (!pnpbios_is_dynamic(dev))
return -EPERM;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -1;
if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
@@ -294,7 +294,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev)
if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev))
return -EPERM;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
@@ -336,7 +336,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
}
/* set the initial values for the PnP device */
- dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
if (!dev_id)
return -1;
pnpid32_to_pnpid(node->eisa_id,id);
@@ -374,7 +374,7 @@ static void __init build_devlist(void)
struct pnp_bios_node *node;
struct pnp_dev *dev;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return;
@@ -391,7 +391,7 @@ static void __init build_devlist(void)
break;
}
nodes_got++;
- dev = kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof (struct pnp_dev), GFP_KERNEL);
if (!dev)
break;
if(insert_device(dev,node)<0)
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 5a3dfc97f5e..8027073f791 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -87,7 +87,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
return -EFBIG;
}
- tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL);
+ tmpbuf = kzalloc(escd.escd_size, GFP_KERNEL);
if (!tmpbuf) return -ENOMEM;
if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
@@ -133,7 +133,7 @@ static int proc_read_devices(char *buf, char **start, off_t pos,
if (pos >= 0xff)
return 0;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
for (nodenum=pos; nodenum<0xff; ) {
@@ -168,7 +168,7 @@ static int proc_read_node(char *buf, char **start, off_t pos,
u8 nodenum = (long)data;
int len;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
kfree(node);
@@ -188,7 +188,7 @@ static int proc_write_node(struct file *file, const char __user *buf,
u8 nodenum = (long)data;
int ret = count;
- node = kcalloc(1, node_info.max_node_size, GFP_KERNEL);
+ node = kzalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return -ENOMEM;
if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index ef508a4de55..95b79685a9d 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -248,7 +248,7 @@ static void
pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = ((p[5] << 8) | p[4]) << 8;
@@ -264,7 +264,7 @@ static void
pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -280,7 +280,7 @@ static void
pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_mem * mem;
- mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
+ mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
if (!mem)
return;
mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
@@ -297,7 +297,7 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option)
struct pnp_irq * irq;
unsigned long bits;
- irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
+ irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
if (!irq)
return;
bits = (p[2] << 8) | p[1];
@@ -314,7 +314,7 @@ static void
pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_dma * dma;
- dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
+ dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
if (!dma)
return;
dma->map = p[1];
@@ -327,7 +327,7 @@ static void
pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = (p[3] << 8) | p[2];
@@ -343,7 +343,7 @@ static void
pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option)
{
struct pnp_port * port;
- port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
if (!port)
return;
port->min = port->max = (p[2] << 8) | p[1];
@@ -527,7 +527,7 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de
case SMALL_TAG_COMPATDEVID: /* compatible ID */
if (len != 4)
goto len_err;
- dev_id = kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL);
+ dev_id = kzalloc(sizeof (struct pnp_id), GFP_KERNEL);
if (!dev_id)
return NULL;
memset(dev_id, 0, sizeof(struct pnp_id));
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index b52d547b7a7..8433eb7562c 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1 +1,2 @@
obj-y += system-bus.o
+obj-$(CONFIG_PS3_VUART) += vuart.o
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
new file mode 100644
index 00000000000..6974f65bcda
--- /dev/null
+++ b/drivers/ps3/vuart.c
@@ -0,0 +1,965 @@
+/*
+ * PS3 virtual uart
+ *
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <asm/ps3.h>
+
+#include <asm/lv1call.h>
+#include <asm/bitops.h>
+
+#include "vuart.h"
+
+MODULE_AUTHOR("Sony Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ps3 vuart");
+
+/**
+ * vuart - An inter-partition data link service.
+ * port 0: PS3 AV Settings.
+ * port 2: PS3 System Manager.
+ *
+ * The vuart provides a bi-directional byte stream data link between logical
+ * partitions. Its primary role is as a communications link between the guest
+ * OS and the system policy module. The current HV does not support any
+ * connections other than those listed.
+ */
+
+enum {PORT_COUNT = 3,};
+
+enum vuart_param {
+ PARAM_TX_TRIGGER = 0,
+ PARAM_RX_TRIGGER = 1,
+ PARAM_INTERRUPT_MASK = 2,
+ PARAM_RX_BUF_SIZE = 3, /* read only */
+ PARAM_RX_BYTES = 4, /* read only */
+ PARAM_TX_BUF_SIZE = 5, /* read only */
+ PARAM_TX_BYTES = 6, /* read only */
+ PARAM_INTERRUPT_STATUS = 7, /* read only */
+};
+
+enum vuart_interrupt_bit {
+ INTERRUPT_BIT_TX = 0,
+ INTERRUPT_BIT_RX = 1,
+ INTERRUPT_BIT_DISCONNECT = 2,
+};
+
+enum vuart_interrupt_mask {
+ INTERRUPT_MASK_TX = 1,
+ INTERRUPT_MASK_RX = 2,
+ INTERRUPT_MASK_DISCONNECT = 4,
+};
+
+/**
+ * struct ports_bmp - bitmap indicating ports needing service.
+ *
+ * A 256 bit read only bitmap indicating ports needing service. Do not write
+ * to these bits. Must not cross a page boundary.
+ */
+
+struct ports_bmp {
+ u64 status;
+ u64 unused[3];
+} __attribute__ ((aligned (32)));
+
+/* redefine dev_dbg to do a syntax check */
+
+#if !defined(DEBUG)
+#undef dev_dbg
+static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg(
+ const struct device *_dev, const char *fmt, ...) {return 0;}
+#endif
+
+#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
+static void __attribute__ ((unused)) _dump_ports_bmp(
+ const struct ports_bmp* bmp, const char* func, int line)
+{
+ pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
+}
+
+static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
+ unsigned int *port_number)
+{
+ switch(match_id) {
+ case PS3_MATCH_ID_AV_SETTINGS:
+ *port_number = 0;
+ return 0;
+ case PS3_MATCH_ID_SYSTEM_MANAGER:
+ *port_number = 2;
+ return 0;
+ default:
+ WARN_ON(1);
+ *port_number = UINT_MAX;
+ return -EINVAL;
+ };
+}
+
+#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
+static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number,
+ const char* func, int line)
+{
+#if defined(DEBUG)
+ static const char *strings[] = {
+ "tx_trigger ",
+ "rx_trigger ",
+ "interrupt_mask ",
+ "rx_buf_size ",
+ "rx_bytes ",
+ "tx_buf_size ",
+ "tx_bytes ",
+ "interrupt_status",
+ };
+ int result;
+ unsigned int i;
+ u64 value;
+
+ for (i = 0; i < ARRAY_SIZE(strings); i++) {
+ result = lv1_get_virtual_uart_param(port_number, i, &value);
+
+ if (result) {
+ pr_debug("%s:%d: port_%u: %s failed: %s\n", func, line,
+ port_number, strings[i], ps3_result(result));
+ continue;
+ }
+ pr_debug("%s:%d: port_%u: %s = %lxh\n",
+ func, line, port_number, strings[i], value);
+ }
+#endif
+}
+
+struct vuart_triggers {
+ unsigned long rx;
+ unsigned long tx;
+};
+
+int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
+ struct vuart_triggers *trig)
+{
+ int result;
+ unsigned long size;
+ unsigned long val;
+
+ result = lv1_get_virtual_uart_param(dev->port_number,
+ PARAM_TX_TRIGGER, &trig->tx);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ result = lv1_get_virtual_uart_param(dev->port_number,
+ PARAM_RX_BUF_SIZE, &size);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ result = lv1_get_virtual_uart_param(dev->port_number,
+ PARAM_RX_TRIGGER, &val);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ trig->rx = size - val;
+
+ dev_dbg(&dev->core, "%s:%d: tx %lxh, rx %lxh\n", __func__, __LINE__,
+ trig->tx, trig->rx);
+
+ return result;
+}
+
+int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
+ unsigned int rx)
+{
+ int result;
+ unsigned long size;
+
+ result = lv1_set_virtual_uart_param(dev->port_number,
+ PARAM_TX_TRIGGER, tx);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ result = lv1_get_virtual_uart_param(dev->port_number,
+ PARAM_RX_BUF_SIZE, &size);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ result = lv1_set_virtual_uart_param(dev->port_number,
+ PARAM_RX_TRIGGER, size - rx);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ dev_dbg(&dev->core, "%s:%d: tx %xh, rx %xh\n", __func__, __LINE__,
+ tx, rx);
+
+ return result;
+}
+
+static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
+ unsigned long *bytes_waiting)
+{
+ int result = lv1_get_virtual_uart_param(dev->port_number,
+ PARAM_RX_BYTES, bytes_waiting);
+
+ if (result)
+ dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
+ dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__,
+ *bytes_waiting);
+ return result;
+}
+
+static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
+ unsigned long mask)
+{
+ int result;
+
+ dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
+
+ dev->interrupt_mask = mask;
+
+ result = lv1_set_virtual_uart_param(dev->port_number,
+ PARAM_INTERRUPT_MASK, dev->interrupt_mask);
+
+ if (result)
+ dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
+ return result;
+}
+
+static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev,
+ unsigned long *status)
+{
+ int result = lv1_get_virtual_uart_param(dev->port_number,
+ PARAM_INTERRUPT_STATUS, status);
+
+ if (result)
+ dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+
+ dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
+ __func__, __LINE__, dev->interrupt_mask, *status,
+ dev->interrupt_mask & *status);
+
+ return result;
+}
+
+int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+ return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ | INTERRUPT_MASK_TX);
+}
+
+int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+ return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ | INTERRUPT_MASK_RX);
+}
+
+int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+{
+ return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ | INTERRUPT_MASK_DISCONNECT);
+}
+
+int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+ return (dev->interrupt_mask & INTERRUPT_MASK_TX)
+ ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ & ~INTERRUPT_MASK_TX) : 0;
+}
+
+int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+ return (dev->interrupt_mask & INTERRUPT_MASK_RX)
+ ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ & ~INTERRUPT_MASK_RX) : 0;
+}
+
+int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
+{
+ return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+ ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ & ~INTERRUPT_MASK_DISCONNECT) : 0;
+}
+
+/**
+ * ps3_vuart_raw_write - Low level write helper.
+ *
+ * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
+ */
+
+static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
+ const void* buf, unsigned int bytes, unsigned long *bytes_written)
+{
+ int result;
+
+ dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
+
+ result = lv1_write_virtual_uart(dev->port_number,
+ ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: lv1_write_virtual_uart failed: "
+ "%s\n", __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ dev->stats.bytes_written += *bytes_written;
+
+ dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__,
+ __LINE__, *bytes_written, bytes, dev->stats.bytes_written);
+
+ return result;
+}
+
+/**
+ * ps3_vuart_raw_read - Low level read helper.
+ *
+ * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
+ */
+
+static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
+ unsigned int bytes, unsigned long *bytes_read)
+{
+ int result;
+
+ dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
+
+ result = lv1_read_virtual_uart(dev->port_number,
+ ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: lv1_read_virtual_uart failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ return result;
+ }
+
+ dev->stats.bytes_read += *bytes_read;
+
+ dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
+ *bytes_read, bytes, dev->stats.bytes_read);
+
+ return result;
+}
+
+/**
+ * struct list_buffer - An element for a port device fifo buffer list.
+ */
+
+struct list_buffer {
+ struct list_head link;
+ const unsigned char *head;
+ const unsigned char *tail;
+ unsigned long dbg_number;
+ unsigned char data[];
+};
+
+/**
+ * ps3_vuart_write - the entry point for writing data to a port
+ *
+ * If the port is idle on entry as much of the incoming data is written to
+ * the port as the port will accept. Otherwise a list buffer is created
+ * and any remaning incoming data is copied to that buffer. The buffer is
+ * then enqueued for transmision via the transmit interrupt.
+ */
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+ unsigned int bytes)
+{
+ static unsigned long dbg_number;
+ int result;
+ unsigned long flags;
+ struct list_buffer *lb;
+
+ dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
+ bytes, bytes);
+
+ spin_lock_irqsave(&dev->tx_list.lock, flags);
+
+ if (list_empty(&dev->tx_list.head)) {
+ unsigned long bytes_written;
+
+ result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
+
+ spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+ if (result) {
+ dev_dbg(&dev->core,
+ "%s:%d: ps3_vuart_raw_write failed\n",
+ __func__, __LINE__);
+ return result;
+ }
+
+ if (bytes_written == bytes) {
+ dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n",
+ __func__, __LINE__, bytes);
+ return 0;
+ }
+
+ bytes -= bytes_written;
+ buf += bytes_written;
+ } else
+ spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+ lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
+
+ if (!lb) {
+ return -ENOMEM;
+ }
+
+ memcpy(lb->data, buf, bytes);
+ lb->head = lb->data;
+ lb->tail = lb->data + bytes;
+ lb->dbg_number = ++dbg_number;
+
+ spin_lock_irqsave(&dev->tx_list.lock, flags);
+ list_add_tail(&lb->link, &dev->tx_list.head);
+ ps3_vuart_enable_interrupt_tx(dev);
+ spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+
+ dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
+ __func__, __LINE__, lb->dbg_number, bytes);
+
+ return 0;
+}
+
+/**
+ * ps3_vuart_read - the entry point for reading data from a port
+ *
+ * If enough bytes to satisfy the request are held in the buffer list those
+ * bytes are dequeued and copied to the caller's buffer. Emptied list buffers
+ * are retiered. If the request cannot be statified by bytes held in the list
+ * buffers -EAGAIN is returned.
+ */
+
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+ unsigned int bytes)
+{
+ unsigned long flags;
+ struct list_buffer *lb, *n;
+ unsigned long bytes_read;
+
+ dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
+ bytes, bytes);
+
+ spin_lock_irqsave(&dev->rx_list.lock, flags);
+
+ if (dev->rx_list.bytes_held < bytes) {
+ spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+ dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
+ __func__, __LINE__, bytes - dev->rx_list.bytes_held);
+ return -EAGAIN;
+ }
+
+ list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) {
+ bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
+
+ memcpy(buf, lb->head, bytes_read);
+ buf += bytes_read;
+ bytes -= bytes_read;
+ dev->rx_list.bytes_held -= bytes_read;
+
+ if (bytes_read < lb->tail - lb->head) {
+ lb->head += bytes_read;
+ spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+
+ dev_dbg(&dev->core,
+ "%s:%d: dequeued buf_%lu, %lxh bytes\n",
+ __func__, __LINE__, lb->dbg_number, bytes_read);
+ return 0;
+ }
+
+ dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
+ lb->dbg_number);
+
+ list_del(&lb->link);
+ kfree(lb);
+ }
+ spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+
+ dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n",
+ __func__, __LINE__, lb->dbg_number, bytes);
+
+ return 0;
+}
+
+/**
+ * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
+ *
+ * Services the transmit interrupt for the port. Writes as much data from the
+ * buffer list as the port will accept. Retires any emptied list buffers and
+ * adjusts the final list buffer state for a partial write.
+ */
+
+static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
+{
+ int result = 0;
+ unsigned long flags;
+ struct list_buffer *lb, *n;
+ unsigned long bytes_total = 0;
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ spin_lock_irqsave(&dev->tx_list.lock, flags);
+
+ list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) {
+
+ unsigned long bytes_written;
+
+ result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head,
+ &bytes_written);
+
+ if (result) {
+ dev_dbg(&dev->core,
+ "%s:%d: ps3_vuart_raw_write failed\n",
+ __func__, __LINE__);
+ break;
+ }
+
+ bytes_total += bytes_written;
+
+ if (bytes_written < lb->tail - lb->head) {
+ lb->head += bytes_written;
+ dev_dbg(&dev->core,
+ "%s:%d cleared buf_%lu, %lxh bytes\n",
+ __func__, __LINE__, lb->dbg_number,
+ bytes_written);
+ goto port_full;
+ }
+
+ dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
+ lb->dbg_number);
+
+ list_del(&lb->link);
+ kfree(lb);
+ }
+
+ ps3_vuart_disable_interrupt_tx(dev);
+port_full:
+ spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+ dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
+ __func__, __LINE__, bytes_total);
+ return result;
+}
+
+/**
+ * ps3_vuart_handle_interrupt_rx - third stage receive interrupt handler
+ *
+ * Services the receive interrupt for the port. Creates a list buffer and
+ * copies all waiting port data to that buffer and enqueues the buffer in the
+ * buffer list. Buffer list data is dequeued via ps3_vuart_read.
+ */
+
+static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
+{
+ static unsigned long dbg_number;
+ int result = 0;
+ unsigned long flags;
+ struct list_buffer *lb;
+ unsigned long bytes;
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
+
+ if (result)
+ return -EIO;
+
+ BUG_ON(!bytes);
+
+ /* add some extra space for recently arrived data */
+
+ bytes += 128;
+
+ lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
+
+ if (!lb)
+ return -ENOMEM;
+
+ ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
+
+ lb->head = lb->data;
+ lb->tail = lb->data + bytes;
+ lb->dbg_number = ++dbg_number;
+
+ spin_lock_irqsave(&dev->rx_list.lock, flags);
+ list_add_tail(&lb->link, &dev->rx_list.head);
+ dev->rx_list.bytes_held += bytes;
+ spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+
+ dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n",
+ __func__, __LINE__, lb->dbg_number, bytes);
+
+ return 0;
+}
+
+static int ps3_vuart_handle_interrupt_disconnect(
+ struct ps3_vuart_port_device *dev)
+{
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+ BUG_ON("no support");
+ return -1;
+}
+
+/**
+ * ps3_vuart_handle_port_interrupt - second stage interrupt handler
+ *
+ * Services any pending interrupt types for the port. Passes control to the
+ * third stage type specific interrupt handler. Returns control to the first
+ * stage handler after one iteration.
+ */
+
+static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
+{
+ int result;
+ unsigned long status;
+
+ result = ps3_vuart_get_interrupt_mask(dev, &status);
+
+ if (result)
+ return result;
+
+ dev_dbg(&dev->core, "%s:%d: status: %lxh\n", __func__, __LINE__,
+ status);
+
+ if (status & INTERRUPT_MASK_DISCONNECT) {
+ dev->stats.disconnect_interrupts++;
+ result = ps3_vuart_handle_interrupt_disconnect(dev);
+ if (result)
+ ps3_vuart_disable_interrupt_disconnect(dev);
+ }
+
+ if (status & INTERRUPT_MASK_TX) {
+ dev->stats.tx_interrupts++;
+ result = ps3_vuart_handle_interrupt_tx(dev);
+ if (result)
+ ps3_vuart_disable_interrupt_tx(dev);
+ }
+
+ if (status & INTERRUPT_MASK_RX) {
+ dev->stats.rx_interrupts++;
+ result = ps3_vuart_handle_interrupt_rx(dev);
+ if (result)
+ ps3_vuart_disable_interrupt_rx(dev);
+ }
+
+ return 0;
+}
+
+struct vuart_private {
+ unsigned int in_use;
+ unsigned int virq;
+ struct ps3_vuart_port_device *devices[PORT_COUNT];
+ const struct ports_bmp bmp;
+};
+
+/**
+ * ps3_vuart_irq_handler - first stage interrupt handler
+ *
+ * Loops finding any interrupting port and its associated instance data.
+ * Passes control to the second stage port specific interrupt handler. Loops
+ * until all outstanding interrupts are serviced.
+ */
+
+static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
+{
+ struct vuart_private *private;
+
+ BUG_ON(!_private);
+ private = (struct vuart_private *)_private;
+
+ while (1) {
+ unsigned int port;
+
+ dump_ports_bmp(&private->bmp);
+
+ port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status);
+
+ if (port == BITS_PER_LONG)
+ break;
+
+ BUG_ON(port >= PORT_COUNT);
+ BUG_ON(!private->devices[port]);
+
+ ps3_vuart_handle_port_interrupt(private->devices[port]);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
+{
+ int result;
+ struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
+ struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+
+ result = dev->match_id == drv->match_id;
+
+ dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__,
+ __LINE__, dev->match_id, dev->core.bus_id, drv->match_id,
+ drv->core.name, (result ? "match" : "miss"));
+
+ return result;
+}
+
+static struct vuart_private vuart_private;
+
+static int ps3_vuart_probe(struct device *_dev)
+{
+ int result;
+ unsigned long tmp;
+ struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+ struct ps3_vuart_port_driver *drv =
+ to_ps3_vuart_port_driver(_dev->driver);
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ BUG_ON(!drv);
+
+ result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
+ __func__, __LINE__, dev->match_id);
+ result = -EINVAL;
+ goto fail_match;
+ }
+
+ if (vuart_private.devices[dev->port_number]) {
+ dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
+ __LINE__, dev->port_number);
+ result = -EBUSY;
+ goto fail_match;
+ }
+
+ vuart_private.devices[dev->port_number] = dev;
+
+ INIT_LIST_HEAD(&dev->tx_list.head);
+ spin_lock_init(&dev->tx_list.lock);
+ INIT_LIST_HEAD(&dev->rx_list.head);
+ spin_lock_init(&dev->rx_list.lock);
+
+ vuart_private.in_use++;
+ if (vuart_private.in_use == 1) {
+ result = ps3_alloc_vuart_irq((void*)&vuart_private.bmp.status,
+ &vuart_private.virq);
+
+ if (result) {
+ dev_dbg(&dev->core,
+ "%s:%d: ps3_alloc_vuart_irq failed (%d)\n",
+ __func__, __LINE__, result);
+ result = -EPERM;
+ goto fail_alloc_irq;
+ }
+
+ result = request_irq(vuart_private.virq, ps3_vuart_irq_handler,
+ IRQF_DISABLED, "vuart", &vuart_private);
+
+ if (result) {
+ dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
+ __func__, __LINE__, result);
+ goto fail_request_irq;
+ }
+ }
+
+ ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
+
+ /* clear stale pending interrupts */
+ ps3_vuart_get_interrupt_mask(dev, &tmp);
+
+ ps3_vuart_set_triggers(dev, 1, 1);
+
+ if (drv->probe)
+ result = drv->probe(dev);
+ else {
+ result = 0;
+ dev_info(&dev->core, "%s:%d: no probe method\n", __func__,
+ __LINE__);
+ }
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
+ __func__, __LINE__);
+ goto fail_probe;
+ }
+
+ return result;
+
+fail_probe:
+fail_request_irq:
+ vuart_private.in_use--;
+ if (!vuart_private.in_use) {
+ ps3_free_vuart_irq(vuart_private.virq);
+ vuart_private.virq = NO_IRQ;
+ }
+fail_alloc_irq:
+fail_match:
+ dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
+ return result;
+}
+
+static int ps3_vuart_remove(struct device *_dev)
+{
+ struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+ struct ps3_vuart_port_driver *drv =
+ to_ps3_vuart_port_driver(_dev->driver);
+
+ dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
+ dev->core.bus_id);
+
+ BUG_ON(vuart_private.in_use < 1);
+
+ if (drv->remove)
+ drv->remove(dev);
+ else
+ dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
+ __LINE__, dev->core.bus_id);
+
+ vuart_private.in_use--;
+
+ if (!vuart_private.in_use) {
+ free_irq(vuart_private.virq, &vuart_private);
+ ps3_free_vuart_irq(vuart_private.virq);
+ vuart_private.virq = NO_IRQ;
+ }
+ return 0;
+}
+
+/**
+ * ps3_vuart - The vuart instance.
+ *
+ * The vuart is managed as a bus that port devices connect to.
+ */
+
+struct bus_type ps3_vuart = {
+ .name = "ps3_vuart",
+ .match = ps3_vuart_match,
+ .probe = ps3_vuart_probe,
+ .remove = ps3_vuart_remove,
+};
+
+int __init ps3_vuart_init(void)
+{
+ int result;
+
+ pr_debug("%s:%d:\n", __func__, __LINE__);
+ result = bus_register(&ps3_vuart);
+ BUG_ON(result);
+ return result;
+}
+
+void __exit ps3_vuart_exit(void)
+{
+ pr_debug("%s:%d:\n", __func__, __LINE__);
+ bus_unregister(&ps3_vuart);
+}
+
+core_initcall(ps3_vuart_init);
+module_exit(ps3_vuart_exit);
+
+/**
+ * ps3_vuart_port_release_device - Remove a vuart port device.
+ */
+
+static void ps3_vuart_port_release_device(struct device *_dev)
+{
+ struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+#if defined(DEBUG)
+ memset(dev, 0xad, sizeof(struct ps3_vuart_port_device));
+#endif
+ kfree(dev);
+}
+
+/**
+ * ps3_vuart_port_device_register - Add a vuart port device.
+ */
+
+int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
+{
+ int result;
+ static unsigned int dev_count = 1;
+
+ dev->core.parent = NULL;
+ dev->core.bus = &ps3_vuart;
+ dev->core.release = ps3_vuart_port_release_device;
+
+ snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
+ dev_count++);
+
+ dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
+
+ result = device_register(&dev->core);
+
+ return result;
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
+
+/**
+ * ps3_vuart_port_driver_register - Add a vuart port device driver.
+ */
+
+int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
+{
+ int result;
+
+ pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
+ drv->core.bus = &ps3_vuart;
+ result = driver_register(&drv->core);
+ return result;
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
+
+/**
+ * ps3_vuart_port_driver_unregister - Remove a vuart port device driver.
+ */
+
+void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
+{
+ driver_unregister(&drv->core);
+}
+
+EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
new file mode 100644
index 00000000000..28fd89f0c8a
--- /dev/null
+++ b/drivers/ps3/vuart.h
@@ -0,0 +1,94 @@
+/*
+ * PS3 virtual uart
+ *
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if !defined(_PS3_VUART_H)
+#define _PS3_VUART_H
+
+struct ps3_vuart_stats {
+ unsigned long bytes_written;
+ unsigned long bytes_read;
+ unsigned long tx_interrupts;
+ unsigned long rx_interrupts;
+ unsigned long disconnect_interrupts;
+};
+
+/**
+ * struct ps3_vuart_port_device - a device on a vuart port
+ */
+
+struct ps3_vuart_port_device {
+ enum ps3_match_id match_id;
+ struct device core;
+
+ /* private driver variables */
+ unsigned int port_number;
+ unsigned long interrupt_mask;
+ struct {
+ spinlock_t lock;
+ struct list_head head;
+ } tx_list;
+ struct {
+ unsigned long bytes_held;
+ spinlock_t lock;
+ struct list_head head;
+ } rx_list;
+ struct ps3_vuart_stats stats;
+};
+
+/**
+ * struct ps3_vuart_port_driver - a driver for a device on a vuart port
+ */
+
+struct ps3_vuart_port_driver {
+ enum ps3_match_id match_id;
+ struct device_driver core;
+ int (*probe)(struct ps3_vuart_port_device *);
+ int (*remove)(struct ps3_vuart_port_device *);
+ int (*tx_event)(struct ps3_vuart_port_device *dev);
+ int (*rx_event)(struct ps3_vuart_port_device *dev);
+ int (*disconnect_event)(struct ps3_vuart_port_device *dev);
+ /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */
+ /* int (*resume)(struct ps3_vuart_port_device *); */
+};
+
+int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
+int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
+void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
+int ps3_vuart_write(struct ps3_vuart_port_device *dev,
+ const void* buf, unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+ unsigned int bytes);
+static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
+ struct device_driver *_drv)
+{
+ return container_of(_drv, struct ps3_vuart_port_driver, core);
+}
+static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
+ struct device *_dev)
+{
+ return container_of(_dev, struct ps3_vuart_port_device, core);
+}
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+ unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+ unsigned int bytes);
+
+#endif
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2a63ab2b47f..09660e2ab05 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -288,7 +288,7 @@ config RTC_DRV_PL031
To compile this driver as a module, choose M here: the
module will be called rtc-pl031.
-config RTC_DRV_AT91
+config RTC_DRV_AT91RM9200
tristate "AT91RM9200"
depends on RTC_CLASS && ARCH_AT91RM9200
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index bd4c45d333f..e6beedacc96 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -35,5 +35,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
-obj-$(CONFIG_RTC_DRV_AT91) += rtc-at91.o
+obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91rm9200.c
index 5c8addcaf1f..a724ab49a79 100644
--- a/drivers/rtc/rtc-at91.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -33,6 +33,8 @@
#include <asm/mach/time.h>
+#include <asm/arch/at91_rtc.h>
+
#define AT91_RTC_FREQ 1
#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */
@@ -137,6 +139,9 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
tm->tm_year = at91_alarm_year - 1900;
+ alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
+ ? 1 : 0;
+
pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
@@ -223,8 +228,6 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned long imr = at91_sys_read(AT91_RTC_IMR);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (imr & AT91_RTC_ALARM) ? "yes" : "no");
seq_printf(seq, "update_IRQ\t: %s\n",
(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
seq_printf(seq, "periodic_IRQ\t: %s\n",
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 828b329e08e..94d3df62a5f 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -435,7 +435,7 @@ static int rtc_dev_add_device(struct class_device *class_dev,
goto err_cdev_del;
}
- dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n",
+ dev_dbg(class_dev->dev, "rtc intf: dev (%d:%d)\n",
MAJOR(rtc->rtc_dev->devt),
MINOR(rtc->rtc_dev->devt));
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index dfef1637bfb..205fa28593b 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -199,7 +199,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *client;
struct rtc_device *rtc;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index ba795a4db1e..7bbc26a34bd 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -117,4 +117,85 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
}
EXPORT_SYMBOL(rtc_tm_to_time);
+
+/* Merge the valid (i.e. non-negative) fields of alarm into the current
+ * time. If the valid alarm fields are earlier than the equivalent
+ * fields in the time, carry one into the least significant invalid
+ * field, so that the alarm expiry is in the future. It assumes that the
+ * least significant invalid field is more significant than the most
+ * significant valid field, and that the seconds field is valid.
+ *
+ * This is used by alarms that take relative (rather than absolute)
+ * times, and/or have a simple binary second counter instead of
+ * day/hour/minute/sec registers.
+ */
+void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm)
+{
+ int *alarmp = &alarm->tm_sec;
+ int *timep = &now->tm_sec;
+ int carry_into, i;
+
+ /* Ignore everything past the 6th element (tm_year). */
+ for (i = 5; i > 0; i--) {
+ if (alarmp[i] < 0)
+ alarmp[i] = timep[i];
+ else
+ break;
+ }
+
+ /* No carry needed if all fields are valid. */
+ if (i == 5)
+ return;
+
+ for (carry_into = i + 1; i >= 0; i--) {
+ if (alarmp[i] < timep[i])
+ break;
+
+ if (alarmp[i] > timep[i])
+ return;
+ }
+
+ switch (carry_into) {
+ case 1:
+ alarm->tm_min++;
+
+ if (alarm->tm_min < 60)
+ return;
+
+ alarm->tm_min = 0;
+ /* fall-through */
+
+ case 2:
+ alarm->tm_hour++;
+
+ if (alarm->tm_hour < 60)
+ return;
+
+ alarm->tm_hour = 0;
+ /* fall-through */
+
+ case 3:
+ alarm->tm_mday++;
+
+ if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon])
+ return;
+
+ alarm->tm_mday = 1;
+ /* fall-through */
+
+ case 4:
+ alarm->tm_mon++;
+
+ if (alarm->tm_mon <= 12)
+ return;
+
+ alarm->tm_mon = 1;
+ /* fall-through */
+
+ case 5:
+ alarm->tm_year++;
+ }
+}
+EXPORT_SYMBOL(rtc_merge_alarm);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index eac5fb1fc02..d59880d44fb 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -279,9 +279,8 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
local_irq_enable();
bcd2tm(&alm->time);
- alm->pending = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
+ alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
& OMAP_RTC_INTERRUPTS_IT_ALARM);
- alm->enabled = alm->pending && device_may_wakeup(dev);
return 0;
}
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index a760cf69af9..4b72b8ef5d6 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -192,7 +192,7 @@ static int pcf8563_validate_client(struct i2c_client *client)
xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (xfer != ARRAY_SIZE(msgs)) {
- dev_err(&client->adapter->dev,
+ dev_err(&client->dev,
"%s: could not read register 0x%02X\n",
__FUNCTION__, pattern[i].reg);
@@ -203,7 +203,7 @@ static int pcf8563_validate_client(struct i2c_client *client)
if (value > pattern[i].max ||
value < pattern[i].min) {
- dev_dbg(&client->adapter->dev,
+ dev_dbg(&client->dev,
"%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
"max=%d, value=%d, raw=0x%02X\n",
__FUNCTION__, i, pattern[i].reg, pattern[i].mask,
@@ -253,7 +253,7 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
int err = 0;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index d51d8f20e63..c272afd6217 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -65,7 +65,7 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
seq_printf(seq, "%02d\n", alrm.time.tm_mday);
else
seq_printf(seq, "**\n");
- seq_printf(seq, "alrm_wakeup\t: %s\n",
+ seq_printf(seq, "alarm_IRQ\t: %s\n",
alrm.enabled ? "yes" : "no");
seq_printf(seq, "alrm_pending\t: %s\n",
alrm.pending ? "yes" : "no");
@@ -120,7 +120,7 @@ static int rtc_proc_add_device(struct class_device *class_dev,
ent->owner = rtc->owner;
ent->data = class_dev;
- dev_info(class_dev->dev, "rtc intf: proc\n");
+ dev_dbg(class_dev->dev, "rtc intf: proc\n");
}
else
rtc_dev = NULL;
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index e2c7698fdba..e7851e3739a 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -1,5 +1,5 @@
/*
- * An I2C driver for the Ricoh RS5C372 RTC
+ * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs
*
* Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net>
* Copyright (C) 2006 Tower Technologies
@@ -13,7 +13,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
-#define DRV_VERSION "0.3"
+#define DRV_VERSION "0.4"
/* Addresses to scan */
static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
@@ -21,6 +21,13 @@ static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD;
+
+/*
+ * Ricoh has a family of I2C based RTCs, which differ only slightly from
+ * each other. Differences center on pinout (e.g. how many interrupts,
+ * output clock, etc) and how the control registers are used. The '372
+ * is significant only because that's the one this driver first supported.
+ */
#define RS5C372_REG_SECS 0
#define RS5C372_REG_MINS 1
#define RS5C372_REG_HOURS 2
@@ -29,59 +36,142 @@ I2C_CLIENT_INSMOD;
#define RS5C372_REG_MONTH 5
#define RS5C372_REG_YEAR 6
#define RS5C372_REG_TRIM 7
+# define RS5C372_TRIM_XSL 0x80
+# define RS5C372_TRIM_MASK 0x7F
+
+#define RS5C_REG_ALARM_A_MIN 8 /* or ALARM_W */
+#define RS5C_REG_ALARM_A_HOURS 9
+#define RS5C_REG_ALARM_A_WDAY 10
+
+#define RS5C_REG_ALARM_B_MIN 11 /* or ALARM_D */
+#define RS5C_REG_ALARM_B_HOURS 12
+#define RS5C_REG_ALARM_B_WDAY 13 /* (ALARM_B only) */
+
+#define RS5C_REG_CTRL1 14
+# define RS5C_CTRL1_AALE (1 << 7) /* or WALE */
+# define RS5C_CTRL1_BALE (1 << 6) /* or DALE */
+# define RV5C387_CTRL1_24 (1 << 5)
+# define RS5C372A_CTRL1_SL1 (1 << 5)
+# define RS5C_CTRL1_CT_MASK (7 << 0)
+# define RS5C_CTRL1_CT0 (0 << 0) /* no periodic irq */
+# define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */
+#define RS5C_REG_CTRL2 15
+# define RS5C372_CTRL2_24 (1 << 5)
+# define RS5C_CTRL2_XSTP (1 << 4)
+# define RS5C_CTRL2_CTFG (1 << 2)
+# define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */
+# define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */
+
+
+/* to read (style 1) or write registers starting at R */
+#define RS5C_ADDR(R) (((R) << 4) | 0)
+
+
+enum rtc_type {
+ rtc_undef = 0,
+ rtc_rs5c372a,
+ rtc_rs5c372b,
+ rtc_rv5c386,
+ rtc_rv5c387a,
+};
-#define RS5C372_TRIM_XSL 0x80
-#define RS5C372_TRIM_MASK 0x7F
+/* REVISIT: this assumes that:
+ * - we're in the 21st century, so it's safe to ignore the century
+ * bit for rv5c38[67] (REG_MONTH bit 7);
+ * - we should use ALARM_A not ALARM_B (may be wrong on some boards)
+ */
+struct rs5c372 {
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+ enum rtc_type type;
+ unsigned time24:1;
+ unsigned has_irq:1;
+ char buf[17];
+ char *regs;
+
+ /* on conversion to a "new style" i2c driver, this vanishes */
+ struct i2c_client dev;
+};
-#define RS5C372_REG_BASE 0
+static int rs5c_get_regs(struct rs5c372 *rs5c)
+{
+ struct i2c_client *client = rs5c->client;
+ struct i2c_msg msgs[] = {
+ { client->addr, I2C_M_RD, sizeof rs5c->buf, rs5c->buf },
+ };
+
+ /* This implements the third reading method from the datasheet, using
+ * an internal address that's reset after each transaction (by STOP)
+ * to 0x0f ... so we read extra registers, and skip the first one.
+ *
+ * The first method doesn't work with the iop3xx adapter driver, on at
+ * least 80219 chips; this works around that bug.
+ */
+ if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
+ pr_debug("%s: can't read registers\n", rs5c->rtc->name);
+ return -EIO;
+ }
-static int rs5c372_attach(struct i2c_adapter *adapter);
-static int rs5c372_detach(struct i2c_client *client);
-static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind);
+ dev_dbg(&client->dev,
+ "%02x %02x %02x (%02x) %02x %02x %02x (%02x), "
+ "%02x %02x %02x, %02x %02x %02x; %02x %02x\n",
+ rs5c->regs[0], rs5c->regs[1], rs5c->regs[2], rs5c->regs[3],
+ rs5c->regs[4], rs5c->regs[5], rs5c->regs[6], rs5c->regs[7],
+ rs5c->regs[8], rs5c->regs[9], rs5c->regs[10], rs5c->regs[11],
+ rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);
-struct rs5c372 {
- u8 reg_addr;
- u8 regs[17];
- struct i2c_msg msg[1];
- struct i2c_client client;
- struct rtc_device *rtc;
-};
+ return 0;
+}
-static struct i2c_driver rs5c372_driver = {
- .driver = {
- .name = "rs5c372",
- },
- .attach_adapter = &rs5c372_attach,
- .detach_client = &rs5c372_detach,
-};
+static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg)
+{
+ unsigned hour;
-static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+ if (rs5c->time24)
+ return BCD2BIN(reg & 0x3f);
+
+ hour = BCD2BIN(reg & 0x1f);
+ if (hour == 12)
+ hour = 0;
+ if (reg & 0x20)
+ hour += 12;
+ return hour;
+}
+
+static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour)
{
+ if (rs5c->time24)
+ return BIN2BCD(hour);
+
+ if (hour > 12)
+ return 0x20 | BIN2BCD(hour - 12);
+ if (hour == 12)
+ return 0x20 | BIN2BCD(12);
+ if (hour == 0)
+ return BIN2BCD(12);
+ return BIN2BCD(hour);
+}
- struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
- u8 *buf = &(rs5c372->regs[1]);
+static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+ int status = rs5c_get_regs(rs5c);
- /* this implements the 3rd reading method, according
- * to the datasheet. rs5c372 defaults to internal
- * address 0xF, so 0x0 is in regs[1]
- */
+ if (status < 0)
+ return status;
- if ((i2c_transfer(client->adapter, rs5c372->msg, 1)) != 1) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
+ tm->tm_sec = BCD2BIN(rs5c->regs[RS5C372_REG_SECS] & 0x7f);
+ tm->tm_min = BCD2BIN(rs5c->regs[RS5C372_REG_MINS] & 0x7f);
+ tm->tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C372_REG_HOURS]);
- tm->tm_sec = BCD2BIN(buf[RS5C372_REG_SECS] & 0x7f);
- tm->tm_min = BCD2BIN(buf[RS5C372_REG_MINS] & 0x7f);
- tm->tm_hour = BCD2BIN(buf[RS5C372_REG_HOURS] & 0x3f);
- tm->tm_wday = BCD2BIN(buf[RS5C372_REG_WDAY] & 0x07);
- tm->tm_mday = BCD2BIN(buf[RS5C372_REG_DAY] & 0x3f);
+ tm->tm_wday = BCD2BIN(rs5c->regs[RS5C372_REG_WDAY] & 0x07);
+ tm->tm_mday = BCD2BIN(rs5c->regs[RS5C372_REG_DAY] & 0x3f);
/* tm->tm_mon is zero-based */
- tm->tm_mon = BCD2BIN(buf[RS5C372_REG_MONTH] & 0x1f) - 1;
+ tm->tm_mon = BCD2BIN(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1;
/* year is 1900 + tm->tm_year */
- tm->tm_year = BCD2BIN(buf[RS5C372_REG_YEAR]) + 100;
+ tm->tm_year = BCD2BIN(rs5c->regs[RS5C372_REG_YEAR]) + 100;
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -89,22 +179,25 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- return 0;
+ /* rtc might need initialization */
+ return rtc_valid_tm(tm);
}
static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
- unsigned char buf[8] = { RS5C372_REG_BASE };
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+ unsigned char buf[8];
- dev_dbg(&client->dev,
- "%s: secs=%d, mins=%d, hours=%d "
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
"mday=%d, mon=%d, year=%d, wday=%d\n",
- __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ buf[0] = RS5C_ADDR(RS5C372_REG_SECS);
buf[1] = BIN2BCD(tm->tm_sec);
buf[2] = BIN2BCD(tm->tm_min);
- buf[3] = BIN2BCD(tm->tm_hour);
+ buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour);
buf[4] = BIN2BCD(tm->tm_wday);
buf[5] = BIN2BCD(tm->tm_mday);
buf[6] = BIN2BCD(tm->tm_mon + 1);
@@ -118,21 +211,43 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0;
}
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+#define NEED_TRIM
+#endif
+
+#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
+#define NEED_TRIM
+#endif
+
+#ifdef NEED_TRIM
static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
{
struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
- u8 tmp = rs5c372->regs[RS5C372_REG_TRIM + 1];
+ u8 tmp = rs5c372->regs[RS5C372_REG_TRIM];
if (osc)
*osc = (tmp & RS5C372_TRIM_XSL) ? 32000 : 32768;
if (trim) {
- *trim = tmp & RS5C372_TRIM_MASK;
- dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim);
+ dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, tmp);
+ tmp &= RS5C372_TRIM_MASK;
+ if (tmp & 0x3e) {
+ int t = tmp & 0x3f;
+
+ if (tmp & 0x40)
+ t = (~t | (s8)0xc0) + 1;
+ else
+ t = t - 1;
+
+ tmp = t * 2;
+ } else
+ tmp = 0;
+ *trim = tmp;
}
return 0;
}
+#endif
static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
@@ -144,25 +259,190 @@ static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
return rs5c372_set_datetime(to_i2c_client(dev), tm);
}
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+
+static int
+rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+ unsigned char buf[2];
+ int status;
+
+ buf[1] = rs5c->regs[RS5C_REG_CTRL1];
+ switch (cmd) {
+ case RTC_UIE_OFF:
+ case RTC_UIE_ON:
+ /* some 327a modes use a different IRQ pin for 1Hz irqs */
+ if (rs5c->type == rtc_rs5c372a
+ && (buf[1] & RS5C372A_CTRL1_SL1))
+ return -ENOIOCTLCMD;
+ case RTC_AIE_OFF:
+ case RTC_AIE_ON:
+ /* these irq management calls only make sense for chips
+ * which are wired up to an IRQ.
+ */
+ if (!rs5c->has_irq)
+ return -ENOIOCTLCMD;
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ status = rs5c_get_regs(rs5c);
+ if (status < 0)
+ return status;
+
+ buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
+ switch (cmd) {
+ case RTC_AIE_OFF: /* alarm off */
+ buf[1] &= ~RS5C_CTRL1_AALE;
+ break;
+ case RTC_AIE_ON: /* alarm on */
+ buf[1] |= RS5C_CTRL1_AALE;
+ break;
+ case RTC_UIE_OFF: /* update off */
+ buf[1] &= ~RS5C_CTRL1_CT_MASK;
+ break;
+ case RTC_UIE_ON: /* update on */
+ buf[1] &= ~RS5C_CTRL1_CT_MASK;
+ buf[1] |= RS5C_CTRL1_CT4;
+ break;
+ }
+ if ((i2c_master_send(client, buf, 2)) != 2) {
+ printk(KERN_WARNING "%s: can't update alarm\n",
+ rs5c->rtc->name);
+ status = -EIO;
+ } else
+ rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+ return status;
+}
+
+#else
+#define rs5c_rtc_ioctl NULL
+#endif
+
+
+/* NOTE: Since RTC_WKALM_{RD,SET} were originally defined for EFI,
+ * which only exposes a polled programming interface; and since
+ * these calls map directly to those EFI requests; we don't demand
+ * we have an IRQ for this chip when we go through this API.
+ *
+ * The older x86_pc derived RTC_ALM_{READ,SET} calls require irqs
+ * though, managed through RTC_AIE_{ON,OFF} requests.
+ */
+
+static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+ int status;
+
+ status = rs5c_get_regs(rs5c);
+ if (status < 0)
+ return status;
+
+ /* report alarm time */
+ t->time.tm_sec = 0;
+ t->time.tm_min = BCD2BIN(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
+ t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
+ t->time.tm_mday = -1;
+ t->time.tm_mon = -1;
+ t->time.tm_year = -1;
+ t->time.tm_wday = -1;
+ t->time.tm_yday = -1;
+ t->time.tm_isdst = -1;
+
+ /* ... and status */
+ t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
+ t->pending = !!(rs5c->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_AAFG);
+
+ return 0;
+}
+
+static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+ int status;
+ unsigned char buf[4];
+
+ /* only handle up to 24 hours in the future, like RTC_ALM_SET */
+ if (t->time.tm_mday != -1
+ || t->time.tm_mon != -1
+ || t->time.tm_year != -1)
+ return -EINVAL;
+
+ /* REVISIT: round up tm_sec */
+
+ /* if needed, disable irq (clears pending status) */
+ status = rs5c_get_regs(rs5c);
+ if (status < 0)
+ return status;
+ if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) {
+ buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
+ buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
+ if (i2c_master_send(client, buf, 2) != 2) {
+ pr_debug("%s: can't disable alarm\n", rs5c->rtc->name);
+ return -EIO;
+ }
+ rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+ }
+
+ /* set alarm */
+ buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN);
+ buf[1] = BIN2BCD(t->time.tm_min);
+ buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour);
+ buf[3] = 0x7f; /* any/all days */
+ if ((i2c_master_send(client, buf, 4)) != 4) {
+ pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
+ return -EIO;
+ }
+
+ /* ... and maybe enable its irq */
+ if (t->enabled) {
+ buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
+ buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
+ if ((i2c_master_send(client, buf, 2)) != 2)
+ printk(KERN_WARNING "%s: can't enable alarm\n",
+ rs5c->rtc->name);
+ rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+
static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
{
int err, osc, trim;
err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim);
if (err == 0) {
- seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000);
- seq_printf(seq, "trim\t: %d\n", trim);
+ seq_printf(seq, "crystal\t\t: %d.%03d KHz\n",
+ osc / 1000, osc % 1000);
+ seq_printf(seq, "trim\t\t: %d\n", trim);
}
return 0;
}
+#else
+#define rs5c372_rtc_proc NULL
+#endif
+
static const struct rtc_class_ops rs5c372_rtc_ops = {
.proc = rs5c372_rtc_proc,
+ .ioctl = rs5c_rtc_ioctl,
.read_time = rs5c372_rtc_read_time,
.set_time = rs5c372_rtc_set_time,
+ .read_alarm = rs5c_read_alarm,
+ .set_alarm = rs5c_set_alarm,
};
+#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
+
static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -172,7 +452,7 @@ static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
if (err)
return err;
- return sprintf(buf, "0x%2x\n", trim);
+ return sprintf(buf, "%d\n", trim);
}
static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL);
@@ -189,18 +469,37 @@ static ssize_t rs5c372_sysfs_show_osc(struct device *dev,
}
static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL);
-static int rs5c372_attach(struct i2c_adapter *adapter)
+static int rs5c_sysfs_register(struct device *dev)
{
- return i2c_probe(adapter, &addr_data, rs5c372_probe);
+ int err;
+
+ err = device_create_file(dev, &dev_attr_trim);
+ if (err)
+ return err;
+ err = device_create_file(dev, &dev_attr_osc);
+ if (err)
+ device_remove_file(dev, &dev_attr_trim);
+
+ return err;
+}
+
+#else
+static int rs5c_sysfs_register(struct device *dev)
+{
+ return 0;
}
+#endif /* SYSFS */
+
+static struct i2c_driver rs5c372_driver;
static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
{
int err = 0;
struct i2c_client *client;
struct rs5c372 *rs5c372;
+ struct rtc_time tm;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
@@ -211,7 +510,15 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
err = -ENOMEM;
goto exit;
}
- client = &rs5c372->client;
+
+ /* we read registers 0x0f then 0x00-0x0f; skip the first one */
+ rs5c372->regs=&rs5c372->buf[1];
+
+ /* On conversion to a "new style" i2c driver, we'll be handed
+ * the i2c_client (we won't create it)
+ */
+ client = &rs5c372->dev;
+ rs5c372->client = client;
/* I2C client */
client->addr = address;
@@ -222,16 +529,99 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
i2c_set_clientdata(client, rs5c372);
- rs5c372->msg[0].addr = address;
- rs5c372->msg[0].flags = I2C_M_RD;
- rs5c372->msg[0].len = sizeof(rs5c372->regs);
- rs5c372->msg[0].buf = rs5c372->regs;
-
/* Inform the i2c layer */
if ((err = i2c_attach_client(client)))
goto exit_kfree;
- dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+ err = rs5c_get_regs(rs5c372);
+ if (err < 0)
+ goto exit_detach;
+
+ /* For "new style" drivers, irq is in i2c_client and chip type
+ * info comes from i2c_client.dev.platform_data. Meanwhile:
+ *
+ * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE
+ */
+ if (rs5c372->type == rtc_undef) {
+ rs5c372->type = rtc_rs5c372b;
+ dev_warn(&client->dev, "assuming rs5c372b\n");
+ }
+
+ /* clock may be set for am/pm or 24 hr time */
+ switch (rs5c372->type) {
+ case rtc_rs5c372a:
+ case rtc_rs5c372b:
+ /* alarm uses ALARM_A; and nINTRA on 372a, nINTR on 372b.
+ * so does periodic irq, except some 327a modes.
+ */
+ if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24)
+ rs5c372->time24 = 1;
+ break;
+ case rtc_rv5c386:
+ case rtc_rv5c387a:
+ if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24)
+ rs5c372->time24 = 1;
+ /* alarm uses ALARM_W; and nINTRB for alarm and periodic
+ * irq, on both 386 and 387
+ */
+ break;
+ default:
+ dev_err(&client->dev, "unknown RTC type\n");
+ goto exit_detach;
+ }
+
+ /* if the oscillator lost power and no other software (like
+ * the bootloader) set it up, do it here.
+ */
+ if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) {
+ unsigned char buf[3];
+
+ rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;
+
+ buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
+ buf[1] = rs5c372->regs[RS5C_REG_CTRL1];
+ buf[2] = rs5c372->regs[RS5C_REG_CTRL2];
+
+ /* use 24hr mode */
+ switch (rs5c372->type) {
+ case rtc_rs5c372a:
+ case rtc_rs5c372b:
+ buf[2] |= RS5C372_CTRL2_24;
+ rs5c372->time24 = 1;
+ break;
+ case rtc_rv5c386:
+ case rtc_rv5c387a:
+ buf[1] |= RV5C387_CTRL1_24;
+ rs5c372->time24 = 1;
+ break;
+ default:
+ /* impossible */
+ break;
+ }
+
+ if ((i2c_master_send(client, buf, 3)) != 3) {
+ dev_err(&client->dev, "setup error\n");
+ goto exit_detach;
+ }
+ rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
+ rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
+ }
+
+ if (rs5c372_get_datetime(client, &tm) < 0)
+ dev_warn(&client->dev, "clock needs to be set\n");
+
+ dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",
+ ({ char *s; switch (rs5c372->type) {
+ case rtc_rs5c372a: s = "rs5c372a"; break;
+ case rtc_rs5c372b: s = "rs5c372b"; break;
+ case rtc_rv5c386: s = "rv5c386"; break;
+ case rtc_rv5c387a: s = "rv5c387a"; break;
+ default: s = "chip"; break;
+ }; s;}),
+ rs5c372->time24 ? "24hr" : "am/pm"
+ );
+
+ /* FIXME when client->irq exists, use it to register alarm irq */
rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
&client->dev, &rs5c372_rtc_ops, THIS_MODULE);
@@ -241,18 +631,12 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
goto exit_detach;
}
- err = device_create_file(&client->dev, &dev_attr_trim);
+ err = rs5c_sysfs_register(&client->dev);
if (err)
goto exit_devreg;
- err = device_create_file(&client->dev, &dev_attr_osc);
- if (err)
- goto exit_trim;
return 0;
-exit_trim:
- device_remove_file(&client->dev, &dev_attr_trim);
-
exit_devreg:
rtc_device_unregister(rs5c372->rtc);
@@ -266,6 +650,11 @@ exit:
return err;
}
+static int rs5c372_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, rs5c372_probe);
+}
+
static int rs5c372_detach(struct i2c_client *client)
{
int err;
@@ -274,6 +663,8 @@ static int rs5c372_detach(struct i2c_client *client)
if (rs5c372->rtc)
rtc_device_unregister(rs5c372->rtc);
+ /* REVISIT properly destroy the sysfs files ... */
+
if ((err = i2c_detach_client(client)))
return err;
@@ -281,6 +672,14 @@ static int rs5c372_detach(struct i2c_client *client)
return 0;
}
+static struct i2c_driver rs5c372_driver = {
+ .driver = {
+ .name = "rtc-rs5c372",
+ },
+ .attach_adapter = &rs5c372_attach,
+ .detach_client = &rs5c372_detach,
+};
+
static __init int rs5c372_init(void)
{
return i2c_add_driver(&rs5c372_driver);
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e301dea57bb..f406a2b55ae 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -191,6 +191,8 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
alm_en = readb(base + S3C2410_RTCALM);
+ alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0;
+
pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
alm_en,
alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
@@ -331,12 +333,8 @@ static int s3c_rtc_ioctl(struct device *dev,
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
- unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM);
unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
-
seq_printf(seq, "periodic_IRQ\t: %s\n",
(ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index bd4d7d174ef..9c8ead43a59 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -289,9 +289,7 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
- seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (RTSR & RTSR_ALE) ? "yes" : "no" );
+ seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
seq_printf(seq, "update_IRQ\t: %s\n",
(RTSR & RTSR_HZE) ? "yes" : "no");
seq_printf(seq, "periodic_IRQ\t: %s\n",
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 143302a8e79..198b9f22fbf 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -2,6 +2,7 @@
* SuperH On-Chip RTC Support
*
* Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2006 Jamie Lenehan
*
* Based on the old arch/sh/kernel/cpu/rtc.c by:
*
@@ -21,7 +22,10 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
+
+#define DRV_NAME "sh-rtc"
+#define DRV_VERSION "0.1.2"
#ifdef CONFIG_CPU_SH3
#define rtc_reg_size sizeof(u16)
@@ -33,22 +37,26 @@
#define RTC_REG(r) ((r) * rtc_reg_size)
-#define R64CNT RTC_REG(0)
-#define RSECCNT RTC_REG(1)
-#define RMINCNT RTC_REG(2)
-#define RHRCNT RTC_REG(3)
-#define RWKCNT RTC_REG(4)
-#define RDAYCNT RTC_REG(5)
-#define RMONCNT RTC_REG(6)
-#define RYRCNT RTC_REG(7)
-#define RSECAR RTC_REG(8)
-#define RMINAR RTC_REG(9)
-#define RHRAR RTC_REG(10)
-#define RWKAR RTC_REG(11)
-#define RDAYAR RTC_REG(12)
-#define RMONAR RTC_REG(13)
-#define RCR1 RTC_REG(14)
-#define RCR2 RTC_REG(15)
+#define R64CNT RTC_REG(0)
+
+#define RSECCNT RTC_REG(1) /* RTC sec */
+#define RMINCNT RTC_REG(2) /* RTC min */
+#define RHRCNT RTC_REG(3) /* RTC hour */
+#define RWKCNT RTC_REG(4) /* RTC week */
+#define RDAYCNT RTC_REG(5) /* RTC day */
+#define RMONCNT RTC_REG(6) /* RTC month */
+#define RYRCNT RTC_REG(7) /* RTC year */
+#define RSECAR RTC_REG(8) /* ALARM sec */
+#define RMINAR RTC_REG(9) /* ALARM min */
+#define RHRAR RTC_REG(10) /* ALARM hour */
+#define RWKAR RTC_REG(11) /* ALARM week */
+#define RDAYAR RTC_REG(12) /* ALARM day */
+#define RMONAR RTC_REG(13) /* ALARM month */
+#define RCR1 RTC_REG(14) /* Control */
+#define RCR2 RTC_REG(15) /* Control */
+
+/* ALARM Bits - or with BCD encoded value */
+#define AR_ENB 0x80 /* Enable for alarm cmp */
/* RCR1 Bits */
#define RCR1_CF 0x80 /* Carry Flag */
@@ -71,22 +79,28 @@ struct sh_rtc {
unsigned int alarm_irq, periodic_irq, carry_irq;
struct rtc_device *rtc_dev;
spinlock_t lock;
+ int rearm_aie;
};
-static irqreturn_t sh_rtc_interrupt(int irq, void *id)
+static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
{
- struct platform_device *pdev = id;
+ struct platform_device *pdev = to_platform_device(dev_id);
struct sh_rtc *rtc = platform_get_drvdata(pdev);
unsigned int tmp, events = 0;
spin_lock(&rtc->lock);
tmp = readb(rtc->regbase + RCR1);
+ tmp &= ~RCR1_CF;
- if (tmp & RCR1_AF)
- events |= RTC_AF | RTC_IRQF;
-
- tmp &= ~(RCR1_CF | RCR1_AF);
+ if (rtc->rearm_aie) {
+ if (tmp & RCR1_AF)
+ tmp &= ~RCR1_AF; /* try to clear AF again */
+ else {
+ tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */
+ rtc->rearm_aie = 0;
+ }
+ }
writeb(tmp, rtc->regbase + RCR1);
@@ -97,9 +111,45 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *id)
return IRQ_HANDLED;
}
-static irqreturn_t sh_rtc_periodic(int irq, void *id)
+static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
+{
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ unsigned int tmp, events = 0;
+
+ spin_lock(&rtc->lock);
+
+ tmp = readb(rtc->regbase + RCR1);
+
+ /*
+ * If AF is set then the alarm has triggered. If we clear AF while
+ * the alarm time still matches the RTC time then AF will
+ * immediately be set again, and if AIE is enabled then the alarm
+ * interrupt will immediately be retrigger. So we clear AIE here
+ * and use rtc->rearm_aie so that the carry interrupt will keep
+ * trying to clear AF and once it stays cleared it'll re-enable
+ * AIE.
+ */
+ if (tmp & RCR1_AF) {
+ events |= RTC_AF | RTC_IRQF;
+
+ tmp &= ~(RCR1_AF|RCR1_AIE);
+
+ writeb(tmp, rtc->regbase + RCR1);
+
+ rtc->rearm_aie = 1;
+
+ rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
+ }
+
+ spin_unlock(&rtc->lock);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
{
- struct sh_rtc *rtc = dev_get_drvdata(id);
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
spin_lock(&rtc->lock);
@@ -139,10 +189,11 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
tmp = readb(rtc->regbase + RCR1);
- if (enable)
- tmp |= RCR1_AIE;
- else
+ if (!enable) {
tmp &= ~RCR1_AIE;
+ rtc->rearm_aie = 0;
+ } else if (rtc->rearm_aie == 0)
+ tmp |= RCR1_AIE;
writeb(tmp, rtc->regbase + RCR1);
@@ -177,7 +228,7 @@ static int sh_rtc_open(struct device *dev)
goto err_bad_carry;
}
- ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED,
+ ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
"sh-rtc alarm", dev);
if (unlikely(ret)) {
dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
@@ -200,6 +251,7 @@ static void sh_rtc_release(struct device *dev)
struct sh_rtc *rtc = dev_get_drvdata(dev);
sh_rtc_setpie(dev, 0);
+ sh_rtc_setaie(dev, 0);
free_irq(rtc->periodic_irq, dev);
free_irq(rtc->carry_irq, dev);
@@ -212,8 +264,6 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
unsigned int tmp;
tmp = readb(rtc->regbase + RCR1);
- seq_printf(seq, "alarm_IRQ\t: %s\n",
- (tmp & RCR1_AIE) ? "yes" : "no");
seq_printf(seq, "carry_IRQ\t: %s\n",
(tmp & RCR1_CIE) ? "yes" : "no");
@@ -267,7 +317,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_hour = BCD2BIN(readb(rtc->regbase + RHRCNT));
tm->tm_wday = BCD2BIN(readb(rtc->regbase + RWKCNT));
tm->tm_mday = BCD2BIN(readb(rtc->regbase + RDAYCNT));
- tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT));
+ tm->tm_mon = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1;
#if defined(CONFIG_CPU_SH4)
yr = readw(rtc->regbase + RYRCNT);
@@ -295,7 +345,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
"mday=%d, mon=%d, year=%d, wday=%d\n",
__FUNCTION__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
if (rtc_valid_tm(tm) < 0)
dev_err(dev, "invalid date\n");
@@ -322,7 +372,7 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
- writeb(BIN2BCD(tm->tm_mon), rtc->regbase + RMONCNT);
+ writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT);
#ifdef CONFIG_CPU_SH3
year = tm->tm_year % 100;
@@ -344,12 +394,140 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0;
}
+static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off)
+{
+ unsigned int byte;
+ int value = 0xff; /* return 0xff for ignored values */
+
+ byte = readb(rtc->regbase + reg_off);
+ if (byte & AR_ENB) {
+ byte &= ~AR_ENB; /* strip the enable bit */
+ value = BCD2BIN(byte);
+ }
+
+ return value;
+}
+
+static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct rtc_time* tm = &wkalrm->time;
+
+ spin_lock_irq(&rtc->lock);
+
+ tm->tm_sec = sh_rtc_read_alarm_value(rtc, RSECAR);
+ tm->tm_min = sh_rtc_read_alarm_value(rtc, RMINAR);
+ tm->tm_hour = sh_rtc_read_alarm_value(rtc, RHRAR);
+ tm->tm_wday = sh_rtc_read_alarm_value(rtc, RWKAR);
+ tm->tm_mday = sh_rtc_read_alarm_value(rtc, RDAYAR);
+ tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR);
+ if (tm->tm_mon > 0)
+ tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
+ tm->tm_year = 0xffff;
+
+ wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0;
+
+ spin_unlock_irq(&rtc->lock);
+
+ return 0;
+}
+
+static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
+ int value, int reg_off)
+{
+ /* < 0 for a value that is ignored */
+ if (value < 0)
+ writeb(0, rtc->regbase + reg_off);
+ else
+ writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off);
+}
+
+static int sh_rtc_check_alarm(struct rtc_time* tm)
+{
+ /*
+ * The original rtc says anything > 0xc0 is "don't care" or "match
+ * all" - most users use 0xff but rtc-dev uses -1 for the same thing.
+ * The original rtc doesn't support years - some things use -1 and
+ * some 0xffff. We use -1 to make out tests easier.
+ */
+ if (tm->tm_year == 0xffff)
+ tm->tm_year = -1;
+ if (tm->tm_mon >= 0xff)
+ tm->tm_mon = -1;
+ if (tm->tm_mday >= 0xff)
+ tm->tm_mday = -1;
+ if (tm->tm_wday >= 0xff)
+ tm->tm_wday = -1;
+ if (tm->tm_hour >= 0xff)
+ tm->tm_hour = -1;
+ if (tm->tm_min >= 0xff)
+ tm->tm_min = -1;
+ if (tm->tm_sec >= 0xff)
+ tm->tm_sec = -1;
+
+ if (tm->tm_year > 9999 ||
+ tm->tm_mon >= 12 ||
+ tm->tm_mday == 0 || tm->tm_mday >= 32 ||
+ tm->tm_wday >= 7 ||
+ tm->tm_hour >= 24 ||
+ tm->tm_min >= 60 ||
+ tm->tm_sec >= 60)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ unsigned int rcr1;
+ struct rtc_time *tm = &wkalrm->time;
+ int mon, err;
+
+ err = sh_rtc_check_alarm(tm);
+ if (unlikely(err < 0))
+ return err;
+
+ spin_lock_irq(&rtc->lock);
+
+ /* disable alarm interrupt and clear the alarm flag */
+ rcr1 = readb(rtc->regbase + RCR1);
+ rcr1 &= ~(RCR1_AF|RCR1_AIE);
+ writeb(rcr1, rtc->regbase + RCR1);
+
+ rtc->rearm_aie = 0;
+
+ /* set alarm time */
+ sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR);
+ sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR);
+ sh_rtc_write_alarm_value(rtc, tm->tm_hour, RHRAR);
+ sh_rtc_write_alarm_value(rtc, tm->tm_wday, RWKAR);
+ sh_rtc_write_alarm_value(rtc, tm->tm_mday, RDAYAR);
+ mon = tm->tm_mon;
+ if (mon >= 0)
+ mon += 1;
+ sh_rtc_write_alarm_value(rtc, mon, RMONAR);
+
+ if (wkalrm->enabled) {
+ rcr1 |= RCR1_AIE;
+ writeb(rcr1, rtc->regbase + RCR1);
+ }
+
+ spin_unlock_irq(&rtc->lock);
+
+ return 0;
+}
+
static struct rtc_class_ops sh_rtc_ops = {
.open = sh_rtc_open,
.release = sh_rtc_release,
.ioctl = sh_rtc_ioctl,
.read_time = sh_rtc_read_time,
.set_time = sh_rtc_set_time,
+ .read_alarm = sh_rtc_read_alarm,
+ .set_alarm = sh_rtc_set_alarm,
.proc = sh_rtc_proc,
};
@@ -442,7 +620,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
}
static struct platform_driver sh_rtc_platform_driver = {
.driver = {
- .name = "sh-rtc",
+ .name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = sh_rtc_probe,
@@ -463,5 +641,6 @@ module_init(sh_rtc_init);
module_exit(sh_rtc_exit);
MODULE_DESCRIPTION("SuperH on-chip RTC driver");
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, Jamie Lenehan <lenehan@twibble.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 625637b84d3..2ddd0cf0714 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -78,12 +78,12 @@ static struct attribute_group rtc_attr_group = {
.attrs = rtc_attrs,
};
-static int __devinit rtc_sysfs_add_device(struct class_device *class_dev,
+static int rtc_sysfs_add_device(struct class_device *class_dev,
struct class_interface *class_intf)
{
int err;
- dev_info(class_dev->dev, "rtc intf: sysfs\n");
+ dev_dbg(class_dev->dev, "rtc intf: sysfs\n");
err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
if (err)
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 9a67487d086..019ae255b0c 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -372,7 +372,7 @@ static int x1205_validate_client(struct i2c_client *client)
};
if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
- dev_err(&client->adapter->dev,
+ dev_err(&client->dev,
"%s: could not read register %x\n",
__FUNCTION__, probe_zero_pattern[i]);
@@ -380,7 +380,7 @@ static int x1205_validate_client(struct i2c_client *client)
}
if ((buf & probe_zero_pattern[i+1]) != 0) {
- dev_err(&client->adapter->dev,
+ dev_err(&client->dev,
"%s: register=%02x, zero pattern=%d, value=%x\n",
__FUNCTION__, probe_zero_pattern[i], i, buf);
@@ -400,7 +400,7 @@ static int x1205_validate_client(struct i2c_client *client)
};
if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
- dev_err(&client->adapter->dev,
+ dev_err(&client->dev,
"%s: could not read register %x\n",
__FUNCTION__, probe_limits_pattern[i].reg);
@@ -411,7 +411,7 @@ static int x1205_validate_client(struct i2c_client *client)
if (value > probe_limits_pattern[i].max ||
value < probe_limits_pattern[i].min) {
- dev_dbg(&client->adapter->dev,
+ dev_dbg(&client->dev,
"%s: register=%x, lim pattern=%d, value=%d\n",
__FUNCTION__, probe_limits_pattern[i].reg,
i, value);
@@ -506,7 +506,7 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
struct i2c_client *client;
struct rtc_device *rtc;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 2af2d9b53d1..492b68bcd7c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1050,10 +1050,10 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
}
} else { /* error */
memcpy(&cqr->irb, irb, sizeof (struct irb));
-#ifdef ERP_DEBUG
- /* dump sense data */
- dasd_log_sense(cqr, irb);
-#endif
+ if (device->features & DASD_FEATURE_ERPLOG) {
+ /* dump sense data */
+ dasd_log_sense(cqr, irb);
+ }
switch (era) {
case dasd_era_fatal:
cqr->status = DASD_CQR_FAILED;
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 669805d4402..4d01040c2c6 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -2641,14 +2641,12 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
struct dasd_ccw_req *erp = NULL;
struct dasd_device *device = cqr->device;
__u32 cpa = cqr->irb.scsw.cpa;
+ struct dasd_ccw_req *temp_erp = NULL;
-#ifdef ERP_DEBUG
- /* print current erp_chain */
- DEV_MESSAGE(KERN_ERR, device, "%s",
- "ERP chain at BEGINNING of ERP-ACTION");
- {
- struct dasd_ccw_req *temp_erp = NULL;
-
+ if (device->features & DASD_FEATURE_ERPLOG) {
+ /* print current erp_chain */
+ DEV_MESSAGE(KERN_ERR, device, "%s",
+ "ERP chain at BEGINNING of ERP-ACTION");
for (temp_erp = cqr;
temp_erp != NULL; temp_erp = temp_erp->refers) {
@@ -2658,7 +2656,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
temp_erp->refers);
}
}
-#endif /* ERP_DEBUG */
/* double-check if current erp/cqr was successfull */
if ((cqr->irb.scsw.cstat == 0x00) &&
@@ -2695,11 +2692,10 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
erp = dasd_3990_erp_handle_match_erp(cqr, erp);
}
-#ifdef ERP_DEBUG
- /* print current erp_chain */
- DEV_MESSAGE(KERN_ERR, device, "%s", "ERP chain at END of ERP-ACTION");
- {
- struct dasd_ccw_req *temp_erp = NULL;
+ if (device->features & DASD_FEATURE_ERPLOG) {
+ /* print current erp_chain */
+ DEV_MESSAGE(KERN_ERR, device, "%s",
+ "ERP chain at END of ERP-ACTION");
for (temp_erp = erp;
temp_erp != NULL; temp_erp = temp_erp->refers) {
@@ -2709,7 +2705,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
temp_erp->refers);
}
}
-#endif /* ERP_DEBUG */
if (erp->status == DASD_CQR_FAILED)
dasd_log_ccw(erp, 1, cpa);
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index cf28ccc5794..5943266152f 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -202,6 +202,8 @@ dasd_feature_list(char *str, char **endp)
features |= DASD_FEATURE_READONLY;
else if (len == 4 && !strncmp(str, "diag", 4))
features |= DASD_FEATURE_USEDIAG;
+ else if (len == 6 && !strncmp(str, "erplog", 6))
+ features |= DASD_FEATURE_ERPLOG;
else {
MESSAGE(KERN_WARNING,
"unsupported feature: %*s, "
@@ -709,6 +711,52 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
+/*
+ * erplog controls the logging of ERP related data
+ * (e.g. failing channel programs).
+ */
+static ssize_t
+dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct dasd_devmap *devmap;
+ int erplog;
+
+ devmap = dasd_find_busid(dev->bus_id);
+ if (!IS_ERR(devmap))
+ erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
+ else
+ erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
+ return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
+}
+
+static ssize_t
+dasd_erplog_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dasd_devmap *devmap;
+ int val;
+ char *endp;
+
+ devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
+ if (IS_ERR(devmap))
+ return PTR_ERR(devmap);
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (((endp + 1) < (buf + count)) || (val > 1))
+ return -EINVAL;
+
+ spin_lock(&dasd_devmap_lock);
+ if (val)
+ devmap->features |= DASD_FEATURE_ERPLOG;
+ else
+ devmap->features &= ~DASD_FEATURE_ERPLOG;
+ if (devmap->device)
+ devmap->device->features = devmap->features;
+ spin_unlock(&dasd_devmap_lock);
+ return count;
+}
+
+static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
/*
* use_diag controls whether the driver should use diag rather than ssch
@@ -896,6 +944,7 @@ static struct attribute * dasd_attrs[] = {
&dev_attr_uid.attr,
&dev_attr_use_diag.attr,
&dev_attr_eer_enabled.attr,
+ &dev_attr_erplog.attr,
NULL,
};
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index dc5dd509434..fb725e3b08f 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -13,10 +13,6 @@
#ifdef __KERNEL__
-/* erp debugging in dasd.c and dasd_3990_erp.c */
-#define ERP_DEBUG
-
-
/* we keep old device allocation scheme; IOW, minors are still in 0..255 */
#define DASD_PER_MAJOR (1U << (MINORBITS - DASD_PARTN_BITS))
#define DASD_PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 8fed3603e9e..758cfb54286 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -430,7 +430,7 @@ dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
int rval;
lock_kernel();
- rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ rval = dasd_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index c9321b920e9..25b5d7a6641 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -688,7 +688,7 @@ raw3215_probe (struct ccw_device *cdev)
raw->cdev = cdev;
raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
memset(raw, 0, sizeof(struct raw3215_info));
- raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE,
+ raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
GFP_KERNEL|GFP_DMA);
if (raw->buffer == NULL) {
spin_lock(&raw3215_device_lock);
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index 49e9628d929..c6cbcb3f925 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -16,14 +16,15 @@
#ifdef CONFIG_MAGIC_SYSRQ
static int ctrlchar_sysrq_key;
+static struct tty_struct *sysrq_tty;
static void
-ctrlchar_handle_sysrq(void *tty)
+ctrlchar_handle_sysrq(struct work_struct *work)
{
- handle_sysrq(ctrlchar_sysrq_key, (struct tty_struct *) tty);
+ handle_sysrq(ctrlchar_sysrq_key, sysrq_tty);
}
-static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq, NULL);
+static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq);
#endif
@@ -53,7 +54,7 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
/* racy */
if (len == 3 && buf[1] == '-') {
ctrlchar_sysrq_key = buf[2];
- ctrlchar_work.data = tty;
+ sysrq_tty = tty;
schedule_work(&ctrlchar_work);
return CTRLCHAR_SYSRQ;
}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 78f8bda81da..0893d306ae8 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -419,16 +419,20 @@ fs3270_open(struct inode *inode, struct file *filp)
struct idal_buffer *ib;
int minor, rc;
- if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
+ if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR)
return -ENODEV;
- minor = iminor(filp->f_dentry->d_inode);
+ minor = iminor(filp->f_path.dentry->d_inode);
/* Check for minor 0 multiplexer. */
if (minor == 0) {
- if (!current->signal->tty)
+ struct tty_struct *tty;
+ mutex_lock(&tty_mutex);
+ tty = get_current_tty();
+ if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) {
+ mutex_unlock(&tty_mutex);
return -ENODEV;
- if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
- return -ENODEV;
- minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
+ }
+ minor = tty->index + RAW3270_FIRSTMINOR;
+ mutex_unlock(&tty_mutex);
}
/* Check if some other program is already using fullscreen mode. */
fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index e3491a5f521..3e86fd1756e 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -377,7 +377,7 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe,
if (!(key_map = kbd->key_maps[tmp.kb_table])) {
int j;
- key_map = (ushort *) kmalloc(sizeof(plain_map),
+ key_map = kmalloc(sizeof(plain_map),
GFP_KERNEL);
if (!key_map)
return -ENOMEM;
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index b9b0fc3f812..cdb24f52811 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -23,7 +23,7 @@
#include <asm/appldata.h>
#include <asm/monwriter.h>
-#define MONWRITE_MAX_DATALEN 4024
+#define MONWRITE_MAX_DATALEN 4010
static int mon_max_bufs = 255;
static int mon_buf_count;
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 732dfbdb85c..4f873ae148b 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -49,6 +49,8 @@ static struct sclp_register sclp_cpi_event =
.send_mask = EvTyp_CtlProgIdent_Mask
};
+MODULE_LICENSE("GPL");
+
MODULE_AUTHOR(
"Martin Peschke, IBM Deutschland Entwicklung GmbH "
"<mpeschke@de.ibm.com>");
@@ -127,7 +129,7 @@ cpi_prepare_req(void)
struct cpi_sccb *sccb;
struct cpi_evbuf *evb;
- req = (struct sclp_req *) kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
+ req = kmalloc(sizeof(struct sclp_req), GFP_KERNEL);
if (req == NULL)
return ERR_PTR(-ENOMEM);
sccb = (struct cpi_sccb *) __get_free_page(GFP_KERNEL | GFP_DMA);
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 6f43e04dbef..2d173e5c8a0 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -60,8 +60,6 @@ static unsigned short int sclp_tty_chars_count;
struct tty_driver *sclp_tty_driver;
-extern struct termios tty_std_termios;
-
static struct sclp_ioctls sclp_ioctls;
static struct sclp_ioctls sclp_ioctls_init =
{
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index 1f4c89967be..c9f1c4c8bb1 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -179,6 +179,7 @@ struct tape_char_data {
/* Block Frontend Data */
struct tape_blk_data
{
+ struct tape_device * device;
/* Block device request queue. */
request_queue_t * request_queue;
spinlock_t request_queue_lock;
@@ -240,7 +241,7 @@ struct tape_device {
#endif
/* Function to start or stop the next request later. */
- struct work_struct tape_dnr;
+ struct delayed_work tape_dnr;
};
/* Externals from tape_core.c */
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 7b95dab913d..e765875e8db 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -95,6 +95,12 @@ tape_34xx_medium_sense(struct tape_device *device)
return rc;
}
+struct tape_34xx_work {
+ struct tape_device *device;
+ enum tape_op op;
+ struct work_struct work;
+};
+
/*
* These functions are currently used only to schedule a medium_sense for
* later execution. This is because we get an interrupt whenever a medium
@@ -103,13 +109,10 @@ tape_34xx_medium_sense(struct tape_device *device)
* interrupt handler.
*/
static void
-tape_34xx_work_handler(void *data)
+tape_34xx_work_handler(struct work_struct *work)
{
- struct {
- struct tape_device *device;
- enum tape_op op;
- struct work_struct work;
- } *p = data;
+ struct tape_34xx_work *p =
+ container_of(work, struct tape_34xx_work, work);
switch(p->op) {
case TO_MSEN:
@@ -126,17 +129,13 @@ tape_34xx_work_handler(void *data)
static int
tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
{
- struct {
- struct tape_device *device;
- enum tape_op op;
- struct work_struct work;
- } *p;
+ struct tape_34xx_work *p;
if ((p = kmalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;
memset(p, 0, sizeof(*p));
- INIT_WORK(&p->work, tape_34xx_work_handler, p);
+ INIT_WORK(&p->work, tape_34xx_work_handler);
p->device = tape_get_device_reference(device);
p->op = op;
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 928cbefc49d..9df912f6318 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -236,9 +236,10 @@ struct work_handler_data {
};
static void
-tape_3590_work_handler(void *data)
+tape_3590_work_handler(struct work_struct *work)
{
- struct work_handler_data *p = data;
+ struct work_handler_data *p =
+ container_of(work, struct work_handler_data, work);
switch (p->op) {
case TO_MSEN:
@@ -263,7 +264,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- INIT_WORK(&p->work, tape_3590_work_handler, p);
+ INIT_WORK(&p->work, tape_3590_work_handler);
p->device = tape_get_device_reference(device);
p->op = op;
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 3225fcd1dcb..c8a89b3b87d 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -15,6 +15,7 @@
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/buffer_head.h>
+#include <linux/kernel.h>
#include <asm/debug.h>
@@ -143,7 +144,8 @@ tapeblock_start_request(struct tape_device *device, struct request *req)
* queue.
*/
static void
-tapeblock_requeue(void *data) {
+tapeblock_requeue(struct work_struct *work) {
+ struct tape_blk_data * blkdat;
struct tape_device * device;
request_queue_t * queue;
int nr_queued;
@@ -151,7 +153,8 @@ tapeblock_requeue(void *data) {
struct list_head * l;
int rc;
- device = (struct tape_device *) data;
+ blkdat = container_of(work, struct tape_blk_data, requeue_task);
+ device = blkdat->device;
if (!device)
return;
@@ -212,6 +215,7 @@ tapeblock_setup_device(struct tape_device * device)
int rc;
blkdat = &device->blk_data;
+ blkdat->device = device;
spin_lock_init(&blkdat->request_queue_lock);
atomic_set(&blkdat->requeue_scheduled, 0);
@@ -255,8 +259,8 @@ tapeblock_setup_device(struct tape_device * device)
add_disk(disk);
- INIT_WORK(&blkdat->requeue_task, tapeblock_requeue,
- tape_get_device_reference(device));
+ tape_get_device_reference(device);
+ INIT_WORK(&blkdat->requeue_task, tapeblock_requeue);
return 0;
@@ -271,7 +275,7 @@ void
tapeblock_cleanup_device(struct tape_device *device)
{
flush_scheduled_work();
- device->blk_data.requeue_task.data = tape_put_device(device);
+ tape_put_device(device);
if (!device->blk_data.disk) {
PRINT_ERR("(%s): No gendisk to clean up!\n",
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 97f75237bed..31198c8f271 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -298,13 +298,13 @@ tapechar_open (struct inode *inode, struct file *filp)
int minor, rc;
DBF_EVENT(6, "TCHAR:open: %i:%i\n",
- imajor(filp->f_dentry->d_inode),
- iminor(filp->f_dentry->d_inode));
+ imajor(filp->f_path.dentry->d_inode),
+ iminor(filp->f_path.dentry->d_inode));
- if (imajor(filp->f_dentry->d_inode) != tapechar_major)
+ if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
return -ENODEV;
- minor = iminor(filp->f_dentry->d_inode);
+ minor = iminor(filp->f_path.dentry->d_inode);
device = tape_get_device(minor / TAPE_MINORS_PER_DEV);
if (IS_ERR(device)) {
DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n");
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 2826aed9104..c6c2e918b99 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -28,7 +28,7 @@
#define PRINTK_HEADER "TAPE_CORE: "
static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
-static void tape_delayed_next_request(void * data);
+static void tape_delayed_next_request(struct work_struct *);
/*
* One list to contain all tape devices of all disciplines, so
@@ -272,7 +272,7 @@ __tape_cancel_io(struct tape_device *device, struct tape_request *request)
return 0;
case -EBUSY:
request->status = TAPE_REQUEST_CANCEL;
- schedule_work(&device->tape_dnr);
+ schedule_delayed_work(&device->tape_dnr, 0);
return 0;
case -ENODEV:
DBF_EXCEPTION(2, "device gone, retry\n");
@@ -470,7 +470,7 @@ tape_alloc_device(void)
*device->modeset_byte = 0;
device->first_minor = -1;
atomic_set(&device->ref_count, 1);
- INIT_WORK(&device->tape_dnr, tape_delayed_next_request, device);
+ INIT_DELAYED_WORK(&device->tape_dnr, tape_delayed_next_request);
return device;
}
@@ -724,7 +724,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
} else if (rc == -EBUSY) {
/* The common I/O subsystem is currently busy. Retry later. */
request->status = TAPE_REQUEST_QUEUED;
- schedule_work(&device->tape_dnr);
+ schedule_delayed_work(&device->tape_dnr, 0);
rc = 0;
} else {
/* Start failed. Remove request and indicate failure. */
@@ -790,11 +790,11 @@ __tape_start_next_request(struct tape_device *device)
}
static void
-tape_delayed_next_request(void *data)
+tape_delayed_next_request(struct work_struct *work)
{
- struct tape_device * device;
+ struct tape_device *device =
+ container_of(work, struct tape_device, tape_dnr.work);
- device = (struct tape_device *) data;
DBF_LH(6, "tape_delayed_next_request(%p)\n", device);
spin_lock_irq(get_ccwdev_lock(device->cdev));
__tape_start_next_request(device);
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 4717c361160..09844621edc 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -1659,7 +1659,7 @@ tty3270_flush_buffer(struct tty_struct *tty)
* Check for visible/invisible input switches
*/
static void
-tty3270_set_termios(struct tty_struct *tty, struct termios *old)
+tty3270_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct tty3270 *tp;
int new;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 1678b6c757e..a420cd09904 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -117,7 +117,7 @@ vmcp_write(struct file *file, const char __user * buff, size_t count,
return -ENOMEM;
}
debug_text_event(vmcp_debug, 1, cmd);
- session->resp_size = __cpcmd(cmd, session->response,
+ session->resp_size = cpcmd(cmd, session->response,
session->bufsize,
&session->resp_code);
up(&session->mutex);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index dbfb77b0392..cbab8d2ce5c 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -183,7 +183,7 @@ css_get_ssd_info(struct subchannel *sch)
page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!page)
return -ENOMEM;
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
ret = chsc_get_sch_desc_irq(sch, page);
if (ret) {
static int cio_chsc_err_msg;
@@ -197,7 +197,7 @@ css_get_ssd_info(struct subchannel *sch)
cio_chsc_err_msg = 1;
}
}
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
free_page((unsigned long)page);
if (!ret) {
int j, chpid, mask;
@@ -233,7 +233,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
if (j >= 8)
return 0;
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
stsch(sch->schid, &schib);
if (!schib.pmcw.dnv)
@@ -265,10 +265,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
else if (sch->lpm == mask)
goto out_unreg;
out_unlock:
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
return 0;
out_unreg:
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
sch->lpm = 0;
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
@@ -378,12 +378,12 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
/* Check if a subchannel is newly available. */
return s390_process_res_acc_new_sch(schid);
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
chp_mask = s390_process_res_acc_sch(res_data, sch);
if (chp_mask == 0) {
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
put_device(&sch->dev);
return 0;
}
@@ -397,7 +397,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
else if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
put_device(&sch->dev);
return 0;
}
@@ -635,21 +635,21 @@ __chp_add(struct subchannel_id schid, void *data)
if (!sch)
/* Check if the subchannel is now available. */
return __chp_add_new_sch(schid);
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
for (i=0; i<8; i++) {
mask = 0x80 >> i;
if ((sch->schib.pmcw.pim & mask) &&
(sch->schib.pmcw.chpid[i] == chp->id)) {
if (stsch(sch->schid, &sch->schib) != 0) {
/* Endgame. */
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
return -ENXIO;
}
break;
}
}
if (i==8) {
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
return 0;
}
sch->lpm = ((sch->schib.pmcw.pim &
@@ -660,7 +660,7 @@ __chp_add(struct subchannel_id schid, void *data)
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
put_device(&sch->dev);
return 0;
}
@@ -750,7 +750,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
if (!sch->ssd_info.valid)
return;
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
old_lpm = sch->lpm;
for (chp = 0; chp < 8; chp++) {
if (sch->ssd_info.chpid[chp] != chpid)
@@ -785,7 +785,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
sch->driver->verify(&sch->dev);
break;
}
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
}
static int
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 20aee278384..ae1bf231d08 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -2,8 +2,7 @@
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
*
- * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
- * IBM Corporation
+ * Copyright (C) IBM Corp. 1999,2006
* Author(s): Ingo Adlung (adlung@de.ibm.com)
* Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
@@ -143,11 +142,11 @@ cio_tpi(void)
return 1;
local_bh_disable();
irq_enter ();
- spin_lock(&sch->lock);
+ spin_lock(sch->lock);
memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
if (sch->driver && sch->driver->irq)
sch->driver->irq(&sch->dev);
- spin_unlock(&sch->lock);
+ spin_unlock(sch->lock);
irq_exit ();
_local_bh_enable();
return 1;
@@ -415,6 +414,8 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
CIO_TRACE_EVENT (2, "ensch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ if (sch_is_pseudo_sch(sch))
+ return -EINVAL;
ccode = stsch (sch->schid, &sch->schib);
if (ccode)
return -ENODEV;
@@ -462,6 +463,8 @@ cio_disable_subchannel (struct subchannel *sch)
CIO_TRACE_EVENT (2, "dissch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
+ if (sch_is_pseudo_sch(sch))
+ return 0;
ccode = stsch (sch->schid, &sch->schib);
if (ccode == 3) /* Not operational. */
return -ENODEV;
@@ -496,6 +499,15 @@ cio_disable_subchannel (struct subchannel *sch)
return ret;
}
+int cio_create_sch_lock(struct subchannel *sch)
+{
+ sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+ if (!sch->lock)
+ return -ENOMEM;
+ spin_lock_init(sch->lock);
+ return 0;
+}
+
/*
* cio_validate_subchannel()
*
@@ -513,6 +525,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
{
char dbf_txt[15];
int ccode;
+ int err;
sprintf (dbf_txt, "valsch%x", schid.sch_no);
CIO_TRACE_EVENT (4, dbf_txt);
@@ -520,9 +533,15 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
/* Nuke all fields. */
memset(sch, 0, sizeof(struct subchannel));
- spin_lock_init(&sch->lock);
+ sch->schid = schid;
+ if (cio_is_console(schid)) {
+ sch->lock = cio_get_console_lock();
+ } else {
+ err = cio_create_sch_lock(sch);
+ if (err)
+ goto out;
+ }
mutex_init(&sch->reg_mutex);
-
/* Set a name for the subchannel */
snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
schid.sch_no);
@@ -534,10 +553,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
* is not valid.
*/
ccode = stsch_err (schid, &sch->schib);
- if (ccode)
- return (ccode == 3) ? -ENXIO : ccode;
-
- sch->schid = schid;
+ if (ccode) {
+ err = (ccode == 3) ? -ENXIO : ccode;
+ goto out;
+ }
/* Copy subchannel type from path management control word. */
sch->st = sch->schib.pmcw.st;
@@ -550,14 +569,16 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
"non-I/O subchannel type %04X\n",
sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */
- return sch->st;
+ err = sch->st;
+ goto out;
}
/* Initialization for io subchannels. */
- if (!sch->schib.pmcw.dnv)
+ if (!sch->schib.pmcw.dnv) {
/* io subchannel but device number is invalid. */
- return -ENODEV;
-
+ err = -ENODEV;
+ goto out;
+ }
/* Devno is valid. */
if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
/*
@@ -567,7 +588,8 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
CIO_MSG_EVENT(0, "Blacklisted device detected "
"at devno %04X, subchannel set %x\n",
sch->schib.pmcw.dev, sch->schid.ssid);
- return -ENODEV;
+ err = -ENODEV;
+ goto out;
}
sch->opm = 0xff;
if (!cio_is_console(sch->schid))
@@ -595,6 +617,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
if ((sch->lpm & (sch->lpm - 1)) != 0)
sch->schib.pmcw.mp = 1; /* multipath mode */
return 0;
+out:
+ if (!cio_is_console(schid))
+ kfree(sch->lock);
+ sch->lock = NULL;
+ return err;
}
/*
@@ -637,7 +664,7 @@ do_IRQ (struct pt_regs *regs)
}
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
if (sch)
- spin_lock(&sch->lock);
+ spin_lock(sch->lock);
/* Store interrupt response block to lowcore. */
if (tsch (tpi_info->schid, irb) == 0 && sch) {
/* Keep subchannel information word up to date. */
@@ -648,7 +675,7 @@ do_IRQ (struct pt_regs *regs)
sch->driver->irq(&sch->dev);
}
if (sch)
- spin_unlock(&sch->lock);
+ spin_unlock(sch->lock);
/*
* Are more interrupts pending?
* If so, the tpi instruction will update the lowcore
@@ -687,10 +714,10 @@ wait_cons_dev (void)
__ctl_load (cr6, 6, 6);
do {
- spin_unlock(&console_subchannel.lock);
+ spin_unlock(console_subchannel.lock);
if (!cio_tpi())
cpu_relax();
- spin_lock(&console_subchannel.lock);
+ spin_lock(console_subchannel.lock);
} while (console_subchannel.schib.scsw.actl != 0);
/*
* restore previous isc value
@@ -843,11 +870,36 @@ __clear_subchannel_easy(struct subchannel_id schid)
return -EBUSY;
}
+static int pgm_check_occured;
+
+static void cio_reset_pgm_check_handler(void)
+{
+ pgm_check_occured = 1;
+}
+
+static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
+{
+ int rc;
+
+ pgm_check_occured = 0;
+ s390_reset_pgm_handler = cio_reset_pgm_check_handler;
+ rc = stsch(schid, addr);
+ s390_reset_pgm_handler = NULL;
+
+ /* The program check handler could have changed pgm_check_occured */
+ barrier();
+
+ if (pgm_check_occured)
+ return -EIO;
+ else
+ return rc;
+}
+
static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
{
struct schib schib;
- if (stsch_err(schid, &schib))
+ if (stsch_reset(schid, &schib))
return -ENXIO;
if (!schib.pmcw.ena)
return 0;
@@ -944,7 +996,7 @@ static int __reipl_subchannel_match(struct subchannel_id schid, void *data)
struct schib schib;
struct sch_match_id *match_id = data;
- if (stsch_err(schid, &schib))
+ if (stsch_reset(schid, &schib))
return -ENXIO;
if (schib.pmcw.dnv &&
(schib.pmcw.dev == match_id->devid.devno) &&
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 4541c1af4b6..35154a21035 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -87,7 +87,7 @@ struct orb {
/* subchannel data structure used by I/O subroutines */
struct subchannel {
struct subchannel_id schid;
- spinlock_t lock; /* subchannel lock */
+ spinlock_t *lock; /* subchannel lock */
struct mutex reg_mutex;
enum {
SUBCHANNEL_TYPE_IO = 0,
@@ -131,15 +131,19 @@ extern int cio_set_options (struct subchannel *, int);
extern int cio_get_options (struct subchannel *);
extern int cio_modify (struct subchannel *);
+int cio_create_sch_lock(struct subchannel *);
+
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
extern struct subchannel *cio_probe_console(void);
extern void cio_release_console(void);
extern int cio_is_console(struct subchannel_id);
extern struct subchannel *cio_get_console_subchannel(void);
+extern spinlock_t * cio_get_console_lock(void);
#else
#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
+#define cio_get_console_lock() NULL;
#endif
extern int cio_show_msg;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 26cf2f5ae2e..9d6c0244686 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -91,9 +91,9 @@ css_free_subchannel(struct subchannel *sch)
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
+ kfree(sch->lock);
kfree(sch);
}
-
}
static void
@@ -102,8 +102,10 @@ css_subchannel_release(struct device *dev)
struct subchannel *sch;
sch = to_subchannel(dev);
- if (!cio_is_console(sch->schid))
+ if (!cio_is_console(sch->schid)) {
+ kfree(sch->lock);
kfree(sch);
+ }
}
extern int css_get_ssd_info(struct subchannel *sch);
@@ -135,14 +137,17 @@ css_register_subchannel(struct subchannel *sch)
sch->dev.parent = &css[0]->device;
sch->dev.bus = &css_bus_type;
sch->dev.release = &css_subchannel_release;
-
+ sch->dev.groups = subch_attr_groups;
+
+ css_get_ssd_info(sch);
+
/* make it known to the system */
ret = css_sch_device_register(sch);
- if (ret)
+ if (ret) {
printk (KERN_WARNING "%s: could not register %s\n",
__func__, sch->dev.bus_id);
- else
- css_get_ssd_info(sch);
+ return ret;
+ }
return ret;
}
@@ -201,18 +206,18 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
unsigned long flags;
enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action;
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
disc = device_is_disconnected(sch);
if (disc && slow) {
/* Disconnected devices are evaluated directly only.*/
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
return 0;
}
/* No interrupt after machine check - kill pending timers. */
device_kill_pending_timer(sch);
if (!disc && !slow) {
/* Non-disconnected devices are evaluated on the slow path. */
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
return -EAGAIN;
}
event = css_get_subchannel_status(sch);
@@ -237,9 +242,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
/* Ask driver what to do with device. */
action = UNREGISTER;
if (sch->driver && sch->driver->notify) {
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
ret = sch->driver->notify(&sch->dev, event);
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
if (ret)
action = NONE;
}
@@ -264,9 +269,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
case UNREGISTER:
case UNREGISTER_PROBE:
/* Unregister device (will use subchannel lock). */
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
css_sch_device_unregister(sch);
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
/* Reset intparm to zeroes. */
sch->schib.pmcw.intparm = 0;
@@ -278,7 +283,7 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
default:
break;
}
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
/* Probe if necessary. */
if (action == UNREGISTER_PROBE)
ret = css_probe_device(sch->schid);
@@ -573,12 +578,24 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store);
-static inline void __init
-setup_css(int nr)
+static inline int __init setup_css(int nr)
{
u32 tod_high;
+ int ret;
memset(css[nr], 0, sizeof(struct channel_subsystem));
+ css[nr]->pseudo_subchannel =
+ kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL);
+ if (!css[nr]->pseudo_subchannel)
+ return -ENOMEM;
+ css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device;
+ css[nr]->pseudo_subchannel->dev.release = css_subchannel_release;
+ sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct");
+ ret = cio_create_sch_lock(css[nr]->pseudo_subchannel);
+ if (ret) {
+ kfree(css[nr]->pseudo_subchannel);
+ return ret;
+ }
mutex_init(&css[nr]->mutex);
css[nr]->valid = 1;
css[nr]->cssid = nr;
@@ -586,6 +603,7 @@ setup_css(int nr)
css[nr]->device.release = channel_subsystem_release;
tod_high = (u32) (get_clock() >> 32);
css_generate_pgid(css[nr], tod_high);
+ return 0;
}
/*
@@ -622,10 +640,12 @@ init_channel_subsystem (void)
ret = -ENOMEM;
goto out_unregister;
}
- setup_css(i);
- ret = device_register(&css[i]->device);
+ ret = setup_css(i);
if (ret)
goto out_free;
+ ret = device_register(&css[i]->device);
+ if (ret)
+ goto out_free_all;
if (css_characteristics_avail &&
css_chsc_characteristics.secm) {
ret = device_create_file(&css[i]->device,
@@ -633,6 +653,9 @@ init_channel_subsystem (void)
if (ret)
goto out_device;
}
+ ret = device_register(&css[i]->pseudo_subchannel->dev);
+ if (ret)
+ goto out_file;
}
css_init_done = 1;
@@ -640,13 +663,19 @@ init_channel_subsystem (void)
for_each_subchannel(__init_channel_subsystem, NULL);
return 0;
+out_file:
+ device_remove_file(&css[i]->device, &dev_attr_cm_enable);
out_device:
device_unregister(&css[i]->device);
+out_free_all:
+ kfree(css[i]->pseudo_subchannel->lock);
+ kfree(css[i]->pseudo_subchannel);
out_free:
kfree(css[i]);
out_unregister:
while (i > 0) {
i--;
+ device_unregister(&css[i]->pseudo_subchannel->dev);
if (css_characteristics_avail && css_chsc_characteristics.secm)
device_remove_file(&css[i]->device,
&dev_attr_cm_enable);
@@ -658,6 +687,11 @@ out:
return ret;
}
+int sch_is_pseudo_sch(struct subchannel *sch)
+{
+ return sch == to_css(sch->dev.parent)->pseudo_subchannel;
+}
+
/*
* find a driver for a subchannel. They identify by the subchannel
* type with the exception that the console subchannel driver has its own
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 9ff064e7176..3464c5b875c 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -73,6 +73,8 @@ struct senseid {
} __attribute__ ((packed,aligned(4)));
struct ccw_device_private {
+ struct ccw_device *cdev;
+ struct subchannel *sch;
int state; /* device state */
atomic_t onoff;
unsigned long registered;
@@ -158,6 +160,8 @@ struct channel_subsystem {
int cm_enabled;
void *cub_addr1;
void *cub_addr2;
+ /* for orphaned ccw devices */
+ struct subchannel *pseudo_subchannel;
};
#define to_css(dev) container_of(dev, struct channel_subsystem, device)
@@ -185,6 +189,11 @@ void css_clear_subchannel_slow_list(void);
int css_slow_subchannels_exist(void);
extern int need_rescan;
+int sch_is_pseudo_sch(struct subchannel *);
+
extern struct workqueue_struct *slow_path_wq;
extern struct work_struct slow_path_work;
+
+int subchannel_add_files (struct device *);
+extern struct attribute_group *subch_attr_groups[];
#endif
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index d3d3716ff84..803579053c2 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -23,6 +23,7 @@
#include <asm/param.h> /* HZ */
#include "cio.h"
+#include "cio_debug.h"
#include "css.h"
#include "device.h"
#include "ioasm.h"
@@ -234,9 +235,11 @@ chpids_show (struct device * dev, struct device_attribute *attr, char * buf)
ssize_t ret = 0;
int chp;
- for (chp = 0; chp < 8; chp++)
- ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
-
+ if (ssd)
+ for (chp = 0; chp < 8; chp++)
+ ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
+ else
+ ret += sprintf (buf, "n/a");
ret += sprintf (buf+ret, "\n");
return min((ssize_t)PAGE_SIZE, ret);
}
@@ -294,14 +297,44 @@ online_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, cdev->online ? "1\n" : "0\n");
}
+int ccw_device_is_orphan(struct ccw_device *cdev)
+{
+ return sch_is_pseudo_sch(to_subchannel(cdev->dev.parent));
+}
+
+static void ccw_device_unregister(struct work_struct *work)
+{
+ struct ccw_device_private *priv;
+ struct ccw_device *cdev;
+
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
+ if (test_and_clear_bit(1, &cdev->private->registered))
+ device_unregister(&cdev->dev);
+ put_device(&cdev->dev);
+}
+
static void
ccw_device_remove_disconnected(struct ccw_device *cdev)
{
struct subchannel *sch;
+ unsigned long flags;
/*
* Forced offline in disconnected state means
* 'throw away device'.
*/
+ if (ccw_device_is_orphan(cdev)) {
+ /* Deregister ccw device. */
+ spin_lock_irqsave(cdev->ccwlock, flags);
+ cdev->private->state = DEV_STATE_NOT_OPER;
+ spin_unlock_irqrestore(cdev->ccwlock, flags);
+ if (get_device(&cdev->dev)) {
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_unregister);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ }
+ return ;
+ }
sch = to_subchannel(cdev->dev.parent);
css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
@@ -462,6 +495,8 @@ available_show (struct device *dev, struct device_attribute *attr, char *buf)
struct ccw_device *cdev = to_ccwdev(dev);
struct subchannel *sch;
+ if (ccw_device_is_orphan(cdev))
+ return sprintf(buf, "no device\n");
switch (cdev->private->state) {
case DEV_STATE_BOXED:
return sprintf(buf, "boxed\n");
@@ -498,11 +533,10 @@ static struct attribute_group subch_attr_group = {
.attrs = subch_attrs,
};
-static inline int
-subchannel_add_files (struct device *dev)
-{
- return sysfs_create_group(&dev->kobj, &subch_attr_group);
-}
+struct attribute_group *subch_attr_groups[] = {
+ &subch_attr_group,
+ NULL,
+};
static struct attribute * ccwdev_attrs[] = {
&dev_attr_devtype.attr,
@@ -563,11 +597,10 @@ match_devno(struct device * dev, void * data)
cdev = to_ccwdev(dev);
if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
+ !ccw_device_is_orphan(cdev) &&
ccw_dev_id_is_equal(&cdev->private->dev_id, &d->dev_id) &&
- (cdev != d->sibling)) {
- cdev->private->state = DEV_STATE_NOT_OPER;
+ (cdev != d->sibling))
return 1;
- }
return 0;
}
@@ -584,13 +617,36 @@ static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
return dev ? to_ccwdev(dev) : NULL;
}
-static void
-ccw_device_add_changed(void *data)
+static int match_orphan(struct device *dev, void *data)
+{
+ struct ccw_dev_id *dev_id;
+ struct ccw_device *cdev;
+
+ dev_id = data;
+ cdev = to_ccwdev(dev);
+ return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
+}
+
+static struct ccw_device *
+get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
+ struct ccw_dev_id *dev_id)
{
+ struct device *dev;
+ dev = device_find_child(&css->pseudo_subchannel->dev, dev_id,
+ match_orphan);
+
+ return dev ? to_ccwdev(dev) : NULL;
+}
+
+static void
+ccw_device_add_changed(struct work_struct *work)
+{
+ struct ccw_device_private *priv;
struct ccw_device *cdev;
- cdev = data;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
if (device_add(&cdev->dev)) {
put_device(&cdev->dev);
return;
@@ -602,64 +658,21 @@ ccw_device_add_changed(void *data)
}
}
-extern int css_get_ssd_info(struct subchannel *sch);
-
-void
-ccw_device_do_unreg_rereg(void *data)
+void ccw_device_do_unreg_rereg(struct work_struct *work)
{
+ struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;
- int need_rename;
- cdev = data;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
- if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
- /*
- * The device number has changed. This is usually only when
- * a device has been detached under VM and then re-appeared
- * on another subchannel because of a different attachment
- * order than before. Ideally, we should should just switch
- * subchannels, but unfortunately, this is not possible with
- * the current implementation.
- * Instead, we search for the old subchannel for this device
- * number and deregister so there are no collisions with the
- * newly registered ccw_device.
- * FIXME: Find another solution so the block layer doesn't
- * get possibly sick...
- */
- struct ccw_device *other_cdev;
- struct ccw_dev_id dev_id;
-
- need_rename = 1;
- dev_id.devno = sch->schib.pmcw.dev;
- dev_id.ssid = sch->schid.ssid;
- other_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
- if (other_cdev) {
- struct subchannel *other_sch;
-
- other_sch = to_subchannel(other_cdev->dev.parent);
- if (get_device(&other_sch->dev)) {
- stsch(other_sch->schid, &other_sch->schib);
- if (other_sch->schib.pmcw.dnv) {
- other_sch->schib.pmcw.intparm = 0;
- cio_modify(other_sch);
- }
- css_sch_device_unregister(other_sch);
- }
- }
- /* Update ssd info here. */
- css_get_ssd_info(sch);
- cdev->private->dev_id.devno = sch->schib.pmcw.dev;
- } else
- need_rename = 0;
+
device_remove_files(&cdev->dev);
if (test_and_clear_bit(1, &cdev->private->registered))
device_del(&cdev->dev);
- if (need_rename)
- snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
- sch->schid.ssid, sch->schib.pmcw.dev);
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_add_changed, cdev);
+ ccw_device_add_changed);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
@@ -673,18 +686,194 @@ ccw_device_release(struct device *dev)
kfree(cdev);
}
+static struct ccw_device * io_subchannel_allocate_dev(struct subchannel *sch)
+{
+ struct ccw_device *cdev;
+
+ cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ if (cdev) {
+ cdev->private = kzalloc(sizeof(struct ccw_device_private),
+ GFP_KERNEL | GFP_DMA);
+ if (cdev->private)
+ return cdev;
+ }
+ kfree(cdev);
+ return ERR_PTR(-ENOMEM);
+}
+
+static int io_subchannel_initialize_dev(struct subchannel *sch,
+ struct ccw_device *cdev)
+{
+ cdev->private->cdev = cdev;
+ atomic_set(&cdev->private->onoff, 0);
+ cdev->dev.parent = &sch->dev;
+ cdev->dev.release = ccw_device_release;
+ INIT_LIST_HEAD(&cdev->private->kick_work.entry);
+ /* Do first half of device_register. */
+ device_initialize(&cdev->dev);
+ if (!get_device(&sch->dev)) {
+ if (cdev->dev.release)
+ cdev->dev.release(&cdev->dev);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
+{
+ struct ccw_device *cdev;
+ int ret;
+
+ cdev = io_subchannel_allocate_dev(sch);
+ if (!IS_ERR(cdev)) {
+ ret = io_subchannel_initialize_dev(sch, cdev);
+ if (ret) {
+ kfree(cdev);
+ cdev = ERR_PTR(ret);
+ }
+ }
+ return cdev;
+}
+
+static int io_subchannel_recog(struct ccw_device *, struct subchannel *);
+
+static void sch_attach_device(struct subchannel *sch,
+ struct ccw_device *cdev)
+{
+ spin_lock_irq(sch->lock);
+ sch->dev.driver_data = cdev;
+ cdev->private->schid = sch->schid;
+ cdev->ccwlock = sch->lock;
+ device_trigger_reprobe(sch);
+ spin_unlock_irq(sch->lock);
+}
+
+static void sch_attach_disconnected_device(struct subchannel *sch,
+ struct ccw_device *cdev)
+{
+ struct subchannel *other_sch;
+ int ret;
+
+ other_sch = to_subchannel(get_device(cdev->dev.parent));
+ ret = device_move(&cdev->dev, &sch->dev);
+ if (ret) {
+ CIO_MSG_EVENT(2, "Moving disconnected device 0.%x.%04x failed "
+ "(ret=%d)!\n", cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
+ put_device(&other_sch->dev);
+ return;
+ }
+ other_sch->dev.driver_data = NULL;
+ /* No need to keep a subchannel without ccw device around. */
+ css_sch_device_unregister(other_sch);
+ put_device(&other_sch->dev);
+ sch_attach_device(sch, cdev);
+}
+
+static void sch_attach_orphaned_device(struct subchannel *sch,
+ struct ccw_device *cdev)
+{
+ int ret;
+
+ /* Try to move the ccw device to its new subchannel. */
+ ret = device_move(&cdev->dev, &sch->dev);
+ if (ret) {
+ CIO_MSG_EVENT(0, "Moving device 0.%x.%04x from orphanage "
+ "failed (ret=%d)!\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
+ return;
+ }
+ sch_attach_device(sch, cdev);
+}
+
+static void sch_create_and_recog_new_device(struct subchannel *sch)
+{
+ struct ccw_device *cdev;
+
+ /* Need to allocate a new ccw device. */
+ cdev = io_subchannel_create_ccwdev(sch);
+ if (IS_ERR(cdev)) {
+ /* OK, we did everything we could... */
+ css_sch_device_unregister(sch);
+ return;
+ }
+ spin_lock_irq(sch->lock);
+ sch->dev.driver_data = cdev;
+ spin_unlock_irq(sch->lock);
+ /* Start recognition for the new ccw device. */
+ if (io_subchannel_recog(cdev, sch)) {
+ spin_lock_irq(sch->lock);
+ sch->dev.driver_data = NULL;
+ spin_unlock_irq(sch->lock);
+ if (cdev->dev.release)
+ cdev->dev.release(&cdev->dev);
+ css_sch_device_unregister(sch);
+ }
+}
+
+
+void ccw_device_move_to_orphanage(struct work_struct *work)
+{
+ struct ccw_device_private *priv;
+ struct ccw_device *cdev;
+ struct ccw_device *replacing_cdev;
+ struct subchannel *sch;
+ int ret;
+ struct channel_subsystem *css;
+ struct ccw_dev_id dev_id;
+
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
+ sch = to_subchannel(cdev->dev.parent);
+ css = to_css(sch->dev.parent);
+ dev_id.devno = sch->schib.pmcw.dev;
+ dev_id.ssid = sch->schid.ssid;
+
+ /*
+ * Move the orphaned ccw device to the orphanage so the replacing
+ * ccw device can take its place on the subchannel.
+ */
+ ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev);
+ if (ret) {
+ CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to orphanage failed "
+ "(ret=%d)!\n", cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, ret);
+ return;
+ }
+ cdev->ccwlock = css->pseudo_subchannel->lock;
+ /*
+ * Search for the replacing ccw device
+ * - among the disconnected devices
+ * - in the orphanage
+ */
+ replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
+ if (replacing_cdev) {
+ sch_attach_disconnected_device(sch, replacing_cdev);
+ return;
+ }
+ replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id);
+ if (replacing_cdev) {
+ sch_attach_orphaned_device(sch, replacing_cdev);
+ return;
+ }
+ sch_create_and_recog_new_device(sch);
+}
+
/*
* Register recognized device.
*/
static void
-io_subchannel_register(void *data)
+io_subchannel_register(struct work_struct *work)
{
+ struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;
int ret;
unsigned long flags;
- cdev = data;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
/*
@@ -709,9 +898,9 @@ io_subchannel_register(void *data)
printk (KERN_WARNING "%s: could not register %s\n",
__func__, cdev->dev.bus_id);
put_device(&cdev->dev);
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
sch->dev.driver_data = NULL;
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
kfree (cdev->private);
kfree (cdev);
put_device(&sch->dev);
@@ -719,11 +908,6 @@ io_subchannel_register(void *data)
wake_up(&ccw_device_init_wq);
return;
}
-
- ret = subchannel_add_files(cdev->dev.parent);
- if (ret)
- printk(KERN_WARNING "%s: could not add attributes to %s\n",
- __func__, sch->dev.bus_id);
put_device(&cdev->dev);
out:
cdev->private->flags.recog_done = 1;
@@ -734,11 +918,14 @@ out:
}
void
-ccw_device_call_sch_unregister(void *data)
+ccw_device_call_sch_unregister(struct work_struct *work)
{
- struct ccw_device *cdev = data;
+ struct ccw_device_private *priv;
+ struct ccw_device *cdev;
struct subchannel *sch;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
css_sch_device_unregister(sch);
/* Reset intparm to zeroes. */
@@ -768,7 +955,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
break;
sch = to_subchannel(cdev->dev.parent);
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister, cdev);
+ ccw_device_call_sch_unregister);
queue_work(slow_path_wq, &cdev->private->kick_work);
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
@@ -783,7 +970,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
if (!get_device(&cdev->dev))
break;
PREPARE_WORK(&cdev->private->kick_work,
- io_subchannel_register, cdev);
+ io_subchannel_register);
queue_work(slow_path_wq, &cdev->private->kick_work);
break;
}
@@ -797,7 +984,7 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
sch->dev.driver_data = cdev;
sch->driver = &io_subchannel_driver;
- cdev->ccwlock = &sch->lock;
+ cdev->ccwlock = sch->lock;
/* Init private data. */
priv = cdev->private;
@@ -817,9 +1004,9 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
atomic_inc(&ccw_device_init_count);
/* Start async. device sensing. */
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
rc = ccw_device_recognition(cdev);
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
if (rc) {
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
@@ -827,12 +1014,55 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
return rc;
}
+static void ccw_device_move_to_sch(struct work_struct *work)
+{
+ struct ccw_device_private *priv;
+ int rc;
+ struct subchannel *sch;
+ struct ccw_device *cdev;
+ struct subchannel *former_parent;
+
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ sch = priv->sch;
+ cdev = priv->cdev;
+ former_parent = ccw_device_is_orphan(cdev) ?
+ NULL : to_subchannel(get_device(cdev->dev.parent));
+ mutex_lock(&sch->reg_mutex);
+ /* Try to move the ccw device to its new subchannel. */
+ rc = device_move(&cdev->dev, &sch->dev);
+ mutex_unlock(&sch->reg_mutex);
+ if (rc) {
+ CIO_MSG_EVENT(2, "Moving device 0.%x.%04x to subchannel "
+ "0.%x.%04x failed (ret=%d)!\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
+ sch->schid.sch_no, rc);
+ css_sch_device_unregister(sch);
+ goto out;
+ }
+ if (former_parent) {
+ spin_lock_irq(former_parent->lock);
+ former_parent->dev.driver_data = NULL;
+ spin_unlock_irq(former_parent->lock);
+ css_sch_device_unregister(former_parent);
+ /* Reset intparm to zeroes. */
+ former_parent->schib.pmcw.intparm = 0;
+ cio_modify(former_parent);
+ }
+ sch_attach_device(sch, cdev);
+out:
+ if (former_parent)
+ put_device(&former_parent->dev);
+ put_device(&cdev->dev);
+}
+
static int
io_subchannel_probe (struct subchannel *sch)
{
struct ccw_device *cdev;
int rc;
unsigned long flags;
+ struct ccw_dev_id dev_id;
if (sch->dev.driver_data) {
/*
@@ -843,7 +1073,6 @@ io_subchannel_probe (struct subchannel *sch)
cdev = sch->dev.driver_data;
device_initialize(&cdev->dev);
ccw_device_register(cdev);
- subchannel_add_files(&sch->dev);
/*
* Check if the device is already online. If it is
* the reference count needs to be corrected
@@ -856,33 +1085,37 @@ io_subchannel_probe (struct subchannel *sch)
get_device(&cdev->dev);
return 0;
}
- cdev = kzalloc (sizeof(*cdev), GFP_KERNEL);
+ /*
+ * First check if a fitting device may be found amongst the
+ * disconnected devices or in the orphanage.
+ */
+ dev_id.devno = sch->schib.pmcw.dev;
+ dev_id.ssid = sch->schid.ssid;
+ cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL);
if (!cdev)
- return -ENOMEM;
- cdev->private = kzalloc(sizeof(struct ccw_device_private),
- GFP_KERNEL | GFP_DMA);
- if (!cdev->private) {
- kfree(cdev);
- return -ENOMEM;
- }
- atomic_set(&cdev->private->onoff, 0);
- cdev->dev.parent = &sch->dev;
- cdev->dev.release = ccw_device_release;
- INIT_LIST_HEAD(&cdev->private->kick_work.entry);
- /* Do first half of device_register. */
- device_initialize(&cdev->dev);
-
- if (!get_device(&sch->dev)) {
- if (cdev->dev.release)
- cdev->dev.release(&cdev->dev);
- return -ENODEV;
+ cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent),
+ &dev_id);
+ if (cdev) {
+ /*
+ * Schedule moving the device until when we have a registered
+ * subchannel to move to and succeed the probe. We can
+ * unregister later again, when the probe is through.
+ */
+ cdev->private->sch = sch;
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_move_to_sch);
+ queue_work(slow_path_wq, &cdev->private->kick_work);
+ return 0;
}
+ cdev = io_subchannel_create_ccwdev(sch);
+ if (IS_ERR(cdev))
+ return PTR_ERR(cdev);
rc = io_subchannel_recog(cdev, sch);
if (rc) {
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
sch->dev.driver_data = NULL;
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
if (cdev->dev.release)
cdev->dev.release(&cdev->dev);
}
@@ -890,17 +1123,6 @@ io_subchannel_probe (struct subchannel *sch)
return rc;
}
-static void
-ccw_device_unregister(void *data)
-{
- struct ccw_device *cdev;
-
- cdev = (struct ccw_device *)data;
- if (test_and_clear_bit(1, &cdev->private->registered))
- device_unregister(&cdev->dev);
- put_device(&cdev->dev);
-}
-
static int
io_subchannel_remove (struct subchannel *sch)
{
@@ -921,7 +1143,7 @@ io_subchannel_remove (struct subchannel *sch)
*/
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_unregister, cdev);
+ ccw_device_unregister);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
return 0;
@@ -1003,6 +1225,13 @@ static struct ccw_device console_cdev;
static struct ccw_device_private console_private;
static int console_cdev_in_use;
+static DEFINE_SPINLOCK(ccw_console_lock);
+
+spinlock_t * cio_get_console_lock(void)
+{
+ return &ccw_console_lock;
+}
+
static int
ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
{
@@ -1048,6 +1277,7 @@ ccw_device_probe_console(void)
memset(&console_cdev, 0, sizeof(struct ccw_device));
memset(&console_private, 0, sizeof(struct ccw_device_private));
console_cdev.private = &console_private;
+ console_private.cdev = &console_cdev;
ret = ccw_device_console_enable(&console_cdev, sch);
if (ret) {
cio_release_console();
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 9233b5c0bcc..29db6341d63 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -78,8 +78,10 @@ void io_subchannel_recog_done(struct ccw_device *cdev);
int ccw_device_cancel_halt_clear(struct ccw_device *);
-void ccw_device_do_unreg_rereg(void *);
-void ccw_device_call_sch_unregister(void *);
+void ccw_device_do_unreg_rereg(struct work_struct *);
+void ccw_device_call_sch_unregister(struct work_struct *);
+void ccw_device_move_to_orphanage(struct work_struct *);
+int ccw_device_is_orphan(struct ccw_device *);
int ccw_device_recognition(struct ccw_device *);
int ccw_device_online(struct ccw_device *);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 09c7672eb3f..eed14572fc3 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -186,15 +186,14 @@ ccw_device_handle_oper(struct ccw_device *cdev)
/*
* Check if cu type and device type still match. If
* not, it is certainly another device and we have to
- * de- and re-register. Also check here for non-matching devno.
+ * de- and re-register.
*/
if (cdev->id.cu_type != cdev->private->senseid.cu_type ||
cdev->id.cu_model != cdev->private->senseid.cu_model ||
cdev->id.dev_type != cdev->private->senseid.dev_type ||
- cdev->id.dev_model != cdev->private->senseid.dev_model ||
- cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
+ cdev->id.dev_model != cdev->private->senseid.dev_model) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_do_unreg_rereg, cdev);
+ ccw_device_do_unreg_rereg);
queue_work(ccw_device_work, &cdev->private->kick_work);
return 0;
}
@@ -329,19 +328,21 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
}
static void
-ccw_device_oper_notify(void *data)
+ccw_device_oper_notify(struct work_struct *work)
{
+ struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;
int ret;
- cdev = data;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
ret = (sch->driver && sch->driver->notify) ?
sch->driver->notify(&sch->dev, CIO_OPER) : 0;
if (!ret)
/* Driver doesn't want device back. */
- ccw_device_do_unreg_rereg(cdev);
+ ccw_device_do_unreg_rereg(work);
else {
/* Reenable channel measurements, if needed. */
cmf_reenable(cdev);
@@ -377,8 +378,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
- PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify,
- cdev);
+ PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
}
wake_up(&cdev->private->wait_q);
@@ -528,13 +528,15 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event)
static void
-ccw_device_nopath_notify(void *data)
+ccw_device_nopath_notify(struct work_struct *work)
{
+ struct ccw_device_private *priv;
struct ccw_device *cdev;
struct subchannel *sch;
int ret;
- cdev = data;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent);
/* Extra sanity. */
if (sch->lpm)
@@ -547,8 +549,7 @@ ccw_device_nopath_notify(void *data)
cio_disable_subchannel(sch);
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister,
- cdev);
+ ccw_device_call_sch_unregister);
queue_work(ccw_device_work,
&cdev->private->kick_work);
} else
@@ -607,7 +608,7 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
/* Reset oper notify indication after verify error. */
cdev->private->flags.donotify = 0;
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, cdev);
+ ccw_device_nopath_notify);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
break;
@@ -674,6 +675,10 @@ ccw_device_offline(struct ccw_device *cdev)
{
struct subchannel *sch;
+ if (ccw_device_is_orphan(cdev)) {
+ ccw_device_done(cdev, DEV_STATE_OFFLINE);
+ return 0;
+ }
sch = to_subchannel(cdev->dev.parent);
if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
return -ENODEV;
@@ -738,7 +743,7 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent);
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister, cdev);
+ ccw_device_call_sch_unregister);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
wake_up(&cdev->private->wait_q);
@@ -769,7 +774,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
}
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister, cdev);
+ ccw_device_call_sch_unregister);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
wake_up(&cdev->private->wait_q);
@@ -874,7 +879,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent);
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, cdev);
+ ccw_device_nopath_notify);
queue_work(ccw_device_notify_work,
&cdev->private->kick_work);
} else
@@ -969,7 +974,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
ERR_PTR(-EIO));
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, cdev);
+ ccw_device_nopath_notify);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
} else if (cdev->private->flags.doverify)
/* Start delayed path verification. */
@@ -992,7 +997,7 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent);
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, cdev);
+ ccw_device_nopath_notify);
queue_work(ccw_device_notify_work,
&cdev->private->kick_work);
} else
@@ -1021,7 +1026,7 @@ void device_kill_io(struct subchannel *sch)
if (ret == -ENODEV) {
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, cdev);
+ ccw_device_nopath_notify);
queue_work(ccw_device_notify_work,
&cdev->private->kick_work);
} else
@@ -1033,7 +1038,7 @@ void device_kill_io(struct subchannel *sch)
ERR_PTR(-EIO));
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, cdev);
+ ccw_device_nopath_notify);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
} else
/* Start delayed path verification. */
@@ -1104,7 +1109,8 @@ device_trigger_reprobe(struct subchannel *sch)
/* Update some values. */
if (stsch(sch->schid, &sch->schib))
return;
-
+ if (!sch->schib.pmcw.dnv)
+ return;
/*
* The pim, pam, pom values may not be accurate, but they are the best
* we have before performing device selection :/
@@ -1118,7 +1124,13 @@ device_trigger_reprobe(struct subchannel *sch)
sch->schib.pmcw.mp = 1;
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);
+ /* Check if this is another device which appeared on the same sch. */
+ if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_move_to_orphanage);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ } else
+ ccw_device_start_id(cdev, 0);
}
static void
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index b39c1fa48ac..d269607336e 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -316,9 +316,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
ccw_device_set_timeout(cdev, 0);
if (ret == -EBUSY) {
/* Try again later. */
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
msleep(10);
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
continue;
}
if (ret != 0)
@@ -326,12 +326,12 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
break;
/* Wait for end of request. */
cdev->private->intparm = magic;
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
wait_event(cdev->private->wait_q,
(cdev->private->intparm == -EIO) ||
(cdev->private->intparm == -EAGAIN) ||
(cdev->private->intparm == 0));
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
/* Check at least for channel end / device end */
if (cdev->private->intparm == -EIO) {
/* Non-retryable error. */
@@ -342,9 +342,9 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
/* Success. */
break;
/* Try again later. */
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
msleep(10);
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
} while (1);
return ret;
@@ -389,7 +389,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
return ret;
}
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
/* Save interrupt handler. */
handler = cdev->handler;
/* Temporarily install own handler. */
@@ -406,7 +406,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
/* Restore interrupt handler. */
cdev->handler = handler;
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
clear_normalized_cda (rdc_ccw);
kfree(rdc_ccw);
@@ -463,7 +463,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp
rcd_ccw->count = ciw->count;
rcd_ccw->flags = CCW_FLAG_SLI;
- spin_lock_irq(&sch->lock);
+ spin_lock_irq(sch->lock);
/* Save interrupt handler. */
handler = cdev->handler;
/* Temporarily install own handler. */
@@ -480,7 +480,7 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp
/* Restore interrupt handler. */
cdev->handler = handler;
- spin_unlock_irq(&sch->lock);
+ spin_unlock_irq(sch->lock);
/*
* on success we update the user input parms
@@ -537,7 +537,7 @@ ccw_device_stlck(struct ccw_device *cdev)
kfree(buf);
return -ENOMEM;
}
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
ret = cio_enable_subchannel(sch, 3);
if (ret)
goto out_unlock;
@@ -559,9 +559,9 @@ ccw_device_stlck(struct ccw_device *cdev)
goto out_unlock;
}
cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
- spin_lock_irqsave(&sch->lock, flags);
+ spin_lock_irqsave(sch->lock, flags);
cio_disable_subchannel(sch); //FIXME: return code?
if ((cdev->private->irb.scsw.dstat !=
(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
@@ -572,7 +572,7 @@ ccw_device_stlck(struct ccw_device *cdev)
out_unlock:
kfree(buf);
kfree(buf2);
- spin_unlock_irqrestore(&sch->lock, flags);
+ spin_unlock_irqrestore(sch->lock, flags);
return ret;
}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 8d5fa1b4d11..6fd1940842e 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -46,6 +46,7 @@
#include <asm/timex.h>
#include <asm/debug.h>
+#include <asm/s390_rdev.h>
#include <asm/qdio.h>
#include "cio.h"
@@ -65,12 +66,12 @@ MODULE_LICENSE("GPL");
/******************** HERE WE GO ***********************************/
static const char version[] = "QDIO base support version 2";
+extern struct bus_type ccw_bus_type;
-#ifdef QDIO_PERFORMANCE_STATS
+static int qdio_performance_stats = 0;
static int proc_perf_file_registration;
static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc;
static struct qdio_perf_stats perf_stats;
-#endif /* QDIO_PERFORMANCE_STATS */
static int hydra_thinints;
static int is_passthrough = 0;
@@ -275,9 +276,8 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
QDIO_DBF_TEXT4(0,trace,"sigasync");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.siga_syncs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.siga_syncs++;
cc = do_siga_sync(q->schid, gpr2, gpr3);
if (cc)
@@ -322,9 +322,8 @@ qdio_siga_output(struct qdio_q *q)
__u32 busy_bit;
__u64 start_time=0;
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.siga_outs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.siga_outs++;
QDIO_DBF_TEXT4(0,trace,"sigaout");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -358,9 +357,8 @@ qdio_siga_input(struct qdio_q *q)
QDIO_DBF_TEXT4(0,trace,"sigain");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.siga_ins++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.siga_ins++;
cc = do_siga_input(q->schid, q->mask);
@@ -954,9 +952,8 @@ __qdio_outbound_processing(struct qdio_q *q)
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
- o_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ o_p_c++;
/* as we're sissies, we'll check next time */
if (likely(!atomic_read(&q->is_in_shutdown))) {
qdio_mark_q(q);
@@ -964,10 +961,10 @@ __qdio_outbound_processing(struct qdio_q *q)
}
return;
}
-#ifdef QDIO_PERFORMANCE_STATS
- o_p_nc++;
- perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ o_p_nc++;
+ perf_stats.tl_runs++;
+ }
/* see comment in qdio_kick_outbound_q */
siga_attempts=atomic_read(&q->busy_siga_counter);
@@ -982,12 +979,11 @@ __qdio_outbound_processing(struct qdio_q *q)
if (q->is_iqdio_q) {
/*
- * for asynchronous queues, we better check, if the fill
- * level is too high. for synchronous queues, the fill
- * level will never be that high.
+ * for asynchronous queues, we better check, if the sent
+ * buffer is already switched from PRIMED to EMPTY.
*/
- if (atomic_read(&q->number_of_buffers_used)>
- IQDIO_FILL_LEVEL_TO_POLL)
+ if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) &&
+ !qdio_is_outbound_q_done(q))
qdio_mark_q(q);
} else if (!q->hydra_gives_outbound_pcis)
@@ -1142,15 +1138,16 @@ qdio_has_inbound_q_moved(struct qdio_q *q)
{
int i;
-#ifdef QDIO_PERFORMANCE_STATS
static int old_pcis=0;
static int old_thinints=0;
- if ((old_pcis==perf_stats.pcis)&&(old_thinints==perf_stats.thinints))
- perf_stats.start_time_inbound=NOW;
- else
- old_pcis=perf_stats.pcis;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ if ((old_pcis==perf_stats.pcis)&&
+ (old_thinints==perf_stats.thinints))
+ perf_stats.start_time_inbound=NOW;
+ else
+ old_pcis=perf_stats.pcis;
+ }
i=qdio_get_inbound_buffer_frontier(q);
if ( (i!=GET_SAVED_FRONTIER(q)) ||
@@ -1340,10 +1337,10 @@ qdio_kick_inbound_handler(struct qdio_q *q)
q->siga_error=0;
q->error_status_flags=0;
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
- perf_stats.inbound_cnt++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
+ perf_stats.inbound_cnt++;
+ }
}
static inline void
@@ -1363,9 +1360,8 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
*/
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
- ii_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ ii_p_c++;
/*
* as we might just be about to stop polling, we make
* sure that we check again at least once more
@@ -1373,9 +1369,8 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
tiqdio_sched_tl();
return;
}
-#ifdef QDIO_PERFORMANCE_STATS
- ii_p_nc++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ ii_p_nc++;
if (unlikely(atomic_read(&q->is_in_shutdown))) {
qdio_unmark_q(q);
goto out;
@@ -1416,11 +1411,11 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
irq_ptr = (struct qdio_irq*)q->irq_ptr;
for (i=0;i<irq_ptr->no_output_qs;i++) {
oq = irq_ptr->output_qs[i];
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.tl_runs--;
-#endif /* QDIO_PERFORMANCE_STATS */
- if (!qdio_is_outbound_q_done(oq))
+ if (!qdio_is_outbound_q_done(oq)) {
+ if (qdio_performance_stats)
+ perf_stats.tl_runs--;
__qdio_outbound_processing(oq);
+ }
}
}
@@ -1457,9 +1452,8 @@ __qdio_inbound_processing(struct qdio_q *q)
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
- i_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ i_p_c++;
/* as we're sissies, we'll check next time */
if (likely(!atomic_read(&q->is_in_shutdown))) {
qdio_mark_q(q);
@@ -1467,10 +1461,10 @@ __qdio_inbound_processing(struct qdio_q *q)
}
return;
}
-#ifdef QDIO_PERFORMANCE_STATS
- i_p_nc++;
- perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ i_p_nc++;
+ perf_stats.tl_runs++;
+ }
again:
if (qdio_has_inbound_q_moved(q)) {
@@ -1516,9 +1510,8 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
if (unlikely(qdio_reserve_q(q))) {
qdio_release_q(q);
-#ifdef QDIO_PERFORMANCE_STATS
- ii_p_c++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ ii_p_c++;
/*
* as we might just be about to stop polling, we make
* sure that we check again at least once more
@@ -1609,9 +1602,8 @@ tiqdio_tl(unsigned long data)
{
QDIO_DBF_TEXT4(0,trace,"iqdio_tl");
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.tl_runs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.tl_runs++;
tiqdio_inbound_checks();
}
@@ -1832,6 +1824,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->sbal[j]=*(outbound_sbals_array++);
q->queue_type=q_format;
+ if ((q->queue_type == QDIO_IQDIO_QFMT) &&
+ (no_output_qs > 1) &&
+ (i == no_output_qs-1))
+ q->queue_type = QDIO_IQDIO_QFMT_ASYNCH;
q->int_parm=int_parm;
q->is_input_q=0;
q->schid = irq_ptr->schid;
@@ -1918,10 +1914,10 @@ tiqdio_thinint_handler(void)
{
QDIO_DBF_TEXT4(0,trace,"thin_int");
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.thinints++;
- perf_stats.start_time_inbound=NOW;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ perf_stats.thinints++;
+ perf_stats.start_time_inbound=NOW;
+ }
/* SVS only when needed:
* issue SVS to benefit from iqdio interrupt avoidance
@@ -1976,18 +1972,17 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
int i;
struct qdio_q *q;
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.pcis++;
- perf_stats.start_time_inbound=NOW;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ perf_stats.pcis++;
+ perf_stats.start_time_inbound=NOW;
+ }
for (i=0;i<irq_ptr->no_input_qs;i++) {
q=irq_ptr->input_qs[i];
if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
qdio_mark_q(q);
else {
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.tl_runs--;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.tl_runs--;
__qdio_inbound_processing(q);
}
}
@@ -1995,11 +1990,10 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
return;
for (i=0;i<irq_ptr->no_output_qs;i++) {
q=irq_ptr->output_qs[i];
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.tl_runs--;
-#endif /* QDIO_PERFORMANCE_STATS */
if (qdio_is_outbound_q_done(q))
continue;
+ if (qdio_performance_stats)
+ perf_stats.tl_runs--;
if (!irq_ptr->sync_done_on_outb_pcis)
SYNC_MEMORY;
__qdio_outbound_processing(q);
@@ -2045,11 +2039,13 @@ omit_handler_call:
}
static void
-qdio_call_shutdown(void *data)
+qdio_call_shutdown(struct work_struct *work)
{
+ struct ccw_device_private *priv;
struct ccw_device *cdev;
- cdev = (struct ccw_device *)data;
+ priv = container_of(work, struct ccw_device_private, kick_work);
+ cdev = priv->cdev;
qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
put_device(&cdev->dev);
}
@@ -2091,7 +2087,7 @@ qdio_timeout_handler(struct ccw_device *cdev)
if (get_device(&cdev->dev)) {
/* Can't call shutdown from interrupt context. */
PREPARE_WORK(&cdev->private->kick_work,
- qdio_call_shutdown, (void *)cdev);
+ qdio_call_shutdown);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
break;
@@ -3458,19 +3454,18 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
/* This is the outbound handling of queues */
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.start_time_outbound=NOW;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.start_time_outbound=NOW;
qdio_do_qdio_fill_output(q,qidx,count,buffers);
used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count;
if (callflags&QDIO_FLAG_DONT_SIGA) {
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
- perf_stats.outbound_cnt++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
+ perf_stats.outbound_cnt++;
+ }
return;
}
if (q->is_iqdio_q) {
@@ -3500,9 +3495,8 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
qdio_kick_outbound_q(q);
} else {
QDIO_DBF_TEXT3(0,trace, "fast-req");
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.fast_reqs++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats)
+ perf_stats.fast_reqs++;
}
}
/*
@@ -3513,10 +3507,10 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
__qdio_outbound_processing(q);
}
-#ifdef QDIO_PERFORMANCE_STATS
- perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
- perf_stats.outbound_cnt++;
-#endif /* QDIO_PERFORMANCE_STATS */
+ if (qdio_performance_stats) {
+ perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
+ perf_stats.outbound_cnt++;
+ }
}
/* count must be 1 in iqdio */
@@ -3574,7 +3568,6 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags,
return 0;
}
-#ifdef QDIO_PERFORMANCE_STATS
static int
qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
int buffer_length, int *eof, void *data)
@@ -3590,29 +3583,29 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
_OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c);
_OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c);
_OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c);
- _OUTP_IT("Number of tasklet runs (total) : %u\n",
+ _OUTP_IT("Number of tasklet runs (total) : %lu\n",
perf_stats.tl_runs);
_OUTP_IT("\n");
- _OUTP_IT("Number of SIGA sync's issued : %u\n",
+ _OUTP_IT("Number of SIGA sync's issued : %lu\n",
perf_stats.siga_syncs);
- _OUTP_IT("Number of SIGA in's issued : %u\n",
+ _OUTP_IT("Number of SIGA in's issued : %lu\n",
perf_stats.siga_ins);
- _OUTP_IT("Number of SIGA out's issued : %u\n",
+ _OUTP_IT("Number of SIGA out's issued : %lu\n",
perf_stats.siga_outs);
- _OUTP_IT("Number of PCIs caught : %u\n",
+ _OUTP_IT("Number of PCIs caught : %lu\n",
perf_stats.pcis);
- _OUTP_IT("Number of adapter interrupts caught : %u\n",
+ _OUTP_IT("Number of adapter interrupts caught : %lu\n",
perf_stats.thinints);
- _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %u\n",
+ _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %lu\n",
perf_stats.fast_reqs);
_OUTP_IT("\n");
- _OUTP_IT("Total time of all inbound actions (us) incl. UL : %u\n",
+ _OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n",
perf_stats.inbound_time);
- _OUTP_IT("Number of inbound transfers : %u\n",
+ _OUTP_IT("Number of inbound transfers : %lu\n",
perf_stats.inbound_cnt);
- _OUTP_IT("Total time of all outbound do_QDIOs (us) : %u\n",
+ _OUTP_IT("Total time of all outbound do_QDIOs (us) : %lu\n",
perf_stats.outbound_time);
- _OUTP_IT("Number of do_QDIOs outbound : %u\n",
+ _OUTP_IT("Number of do_QDIOs outbound : %lu\n",
perf_stats.outbound_cnt);
_OUTP_IT("\n");
@@ -3620,12 +3613,10 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
}
static struct proc_dir_entry *qdio_perf_proc_file;
-#endif /* QDIO_PERFORMANCE_STATS */
static void
qdio_add_procfs_entry(void)
{
-#ifdef QDIO_PERFORMANCE_STATS
proc_perf_file_registration=0;
qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
S_IFREG|0444,&proc_root);
@@ -3637,20 +3628,58 @@ qdio_add_procfs_entry(void)
QDIO_PRINT_WARN("was not able to register perf. " \
"proc-file (%i).\n",
proc_perf_file_registration);
-#endif /* QDIO_PERFORMANCE_STATS */
}
static void
qdio_remove_procfs_entry(void)
{
-#ifdef QDIO_PERFORMANCE_STATS
perf_stats.tl_runs=0;
if (!proc_perf_file_registration) /* means if it went ok earlier */
remove_proc_entry(QDIO_PERF,&proc_root);
-#endif /* QDIO_PERFORMANCE_STATS */
}
+/**
+ * attributes in sysfs
+ *****************************************************************************/
+
+static ssize_t
+qdio_performance_stats_show(struct bus_type *bus, char *buf)
+{
+ return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0);
+}
+
+static ssize_t
+qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count)
+{
+ char *tmp;
+ int i;
+
+ i = simple_strtoul(buf, &tmp, 16);
+ if ((i == 0) || (i == 1)) {
+ if (i == qdio_performance_stats)
+ return count;
+ qdio_performance_stats = i;
+ if (i==0) {
+ /* reset perf. stat. info */
+ i_p_nc = 0;
+ i_p_c = 0;
+ ii_p_nc = 0;
+ ii_p_c = 0;
+ o_p_nc = 0;
+ o_p_c = 0;
+ memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
+ }
+ } else {
+ QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n");
+ return -EINVAL;
+ }
+ return count;
+}
+
+static BUS_ATTR(qdio_performance_stats, 0644, qdio_performance_stats_show,
+ qdio_performance_stats_store);
+
static void
tiqdio_register_thinints(void)
{
@@ -3695,6 +3724,7 @@ qdio_release_qdio_memory(void)
kfree(indicators);
}
+
static void
qdio_unregister_dbf_views(void)
{
@@ -3796,9 +3826,7 @@ static int __init
init_QDIO(void)
{
int res;
-#ifdef QDIO_PERFORMANCE_STATS
void *ptr;
-#endif /* QDIO_PERFORMANCE_STATS */
printk("qdio: loading %s\n",version);
@@ -3811,13 +3839,12 @@ init_QDIO(void)
return res;
QDIO_DBF_TEXT0(0,setup,"initQDIO");
+ res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
-#ifdef QDIO_PERFORMANCE_STATS
- memset((void*)&perf_stats,0,sizeof(perf_stats));
+ memset((void*)&perf_stats,0,sizeof(perf_stats));
QDIO_DBF_TEXT0(0,setup,"perfstat");
ptr=&perf_stats;
QDIO_DBF_HEX0(0,setup,&ptr,sizeof(void*));
-#endif /* QDIO_PERFORMANCE_STATS */
qdio_add_procfs_entry();
@@ -3841,7 +3868,7 @@ cleanup_QDIO(void)
qdio_release_qdio_memory();
qdio_unregister_dbf_views();
mempool_destroy(qdio_mempool_scssc);
-
+ bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
printk("qdio: %s: module removed\n",version);
}
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 42927c1b745..ec9af72b2af 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -12,10 +12,6 @@
#endif /* CONFIG_QDIO_DEBUG */
#define QDIO_USE_PROCESSING_STATE
-#ifdef CONFIG_QDIO_PERF_STATS
-#define QDIO_PERFORMANCE_STATS
-#endif /* CONFIG_QDIO_PERF_STATS */
-
#define QDIO_MINIMAL_BH_RELIEF_TIME 16
#define QDIO_TIMER_POLL_VALUE 1
#define IQDIO_TIMER_POLL_VALUE 1
@@ -409,25 +405,23 @@ do_clear_global_summary(void)
#define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
#define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
-#ifdef QDIO_PERFORMANCE_STATS
struct qdio_perf_stats {
- unsigned int tl_runs;
+ unsigned long tl_runs;
- unsigned int siga_outs;
- unsigned int siga_ins;
- unsigned int siga_syncs;
- unsigned int pcis;
- unsigned int thinints;
- unsigned int fast_reqs;
+ unsigned long siga_outs;
+ unsigned long siga_ins;
+ unsigned long siga_syncs;
+ unsigned long pcis;
+ unsigned long thinints;
+ unsigned long fast_reqs;
__u64 start_time_outbound;
- unsigned int outbound_cnt;
- unsigned int outbound_time;
+ unsigned long outbound_cnt;
+ unsigned long outbound_time;
__u64 start_time_inbound;
- unsigned int inbound_cnt;
- unsigned int inbound_time;
+ unsigned long inbound_cnt;
+ unsigned long inbound_time;
};
-#endif /* QDIO_PERFORMANCE_STATS */
/* unlikely as the later the better */
#define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index e4dc947e74e..81b5899f401 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -33,6 +33,7 @@
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <asm/s390_rdev.h>
+#include <asm/reset.h>
#include "ap_bus.h"
@@ -1128,6 +1129,27 @@ static void ap_poll_thread_stop(void)
mutex_unlock(&ap_poll_thread_mutex);
}
+static void ap_reset_domain(void)
+{
+ int i;
+
+ for (i = 0; i < AP_DEVICES; i++)
+ ap_reset_queue(AP_MKQID(i, ap_domain_index));
+}
+
+static void ap_reset_all(void)
+{
+ int i, j;
+
+ for (i = 0; i < AP_DOMAINS; i++)
+ for (j = 0; j < AP_DEVICES; j++)
+ ap_reset_queue(AP_MKQID(j, i));
+}
+
+static struct reset_call ap_reset_call = {
+ .fn = ap_reset_all,
+};
+
/**
* The module initialization code.
*/
@@ -1144,6 +1166,7 @@ int __init ap_module_init(void)
printk(KERN_WARNING "AP instructions not installed.\n");
return -ENODEV;
}
+ register_reset_call(&ap_reset_call);
/* Create /sys/bus/ap. */
rc = bus_register(&ap_bus_type);
@@ -1197,6 +1220,7 @@ out_bus:
bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
bus_unregister(&ap_bus_type);
out:
+ unregister_reset_call(&ap_reset_call);
return rc;
}
@@ -1213,10 +1237,12 @@ void ap_module_exit(void)
int i;
struct device *dev;
+ ap_reset_domain();
ap_poll_thread_stop();
del_timer_sync(&ap_config_timer);
del_timer_sync(&ap_poll_timer);
destroy_workqueue(ap_work_queue);
+ tasklet_kill(&ap_tasklet);
s390_root_dev_unregister(ap_root_device);
while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
__ap_match_all)))
@@ -1227,6 +1253,7 @@ void ap_module_exit(void)
for (i = 0; ap_bus_attrs[i]; i++)
bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
bus_unregister(&ap_bus_type);
+ unregister_reset_call(&ap_reset_call);
}
#ifndef CONFIG_ZCRYPT_MONOLITHIC
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index a62b00083d0..5bb13a9d089 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -295,7 +295,7 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
@@ -337,7 +337,7 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index b6a4ecdc802..32e37014345 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -279,7 +279,7 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
@@ -321,7 +321,7 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
struct completion work;
int rc;
- ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 2da8b938140..b7153c1e15c 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -717,7 +717,7 @@ long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB)
};
int rc;
- ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
+ ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
if (!ap_msg.message)
return -ENOMEM;
ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 1a93fa684e9..52625153a4f 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -27,10 +27,7 @@ config IUCV
help
Select this option if you want to use inter-user communication
under VM or VIF. If unsure, say "Y" to enable a fast communication
- link between VM guests. At boot time the user ID of the guest needs
- to be passed to the kernel. Note that both kernels need to be
- compiled with this option and both need to be booted with the user ID
- of the other VM guest.
+ link between VM guests.
config NETIUCV
tristate "IUCV network device support (VM only)"
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 3257c22dd79..03cc263fe0d 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1646,7 +1646,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
return -1;
}
memset(ch, 0, sizeof (struct channel));
- if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1),
+ if ((ch->ccw = kmalloc(8*sizeof(struct ccw1),
GFP_KERNEL | GFP_DMA)) == NULL) {
kfree(ch);
ctc_pr_warn("ctc: Out of memory in add_channel\n");
@@ -1693,7 +1693,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
return -1;
}
fsm_newstate(ch->fsm, CH_STATE_IDLE);
- if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb),
+ if ((ch->irb = kmalloc(sizeof (struct irb),
GFP_KERNEL)) == NULL) {
ctc_pr_warn("ctc: Out of memory in add_channel\n");
kfree_fsm(ch->fsm);
@@ -2535,7 +2535,7 @@ ctc_print_statistics(struct ctc_priv *priv)
DBF_TEXT(trace, 4, __FUNCTION__);
if (!priv)
return;
- sbuf = (char *)kmalloc(2048, GFP_KERNEL);
+ sbuf = kmalloc(2048, GFP_KERNEL);
if (sbuf == NULL)
return;
p = sbuf;
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 1476ce2b437..229aeb5fc39 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -772,7 +772,7 @@ iucv_register_program (__u8 pgmname[16],
}
/* Allocate handler entry */
- new_handler = (handler *)kmalloc(sizeof(handler), GFP_ATOMIC);
+ new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
if (new_handler == NULL) {
printk(KERN_WARNING "%s: storage allocation for new handler "
"failed.\n", __FUNCTION__);
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 53c358c7d36..e95c281f1e3 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -710,7 +710,7 @@ struct qeth_reply {
int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
u32 seqno;
unsigned long offset;
- int received;
+ atomic_t received;
int rc;
void *param;
struct qeth_card *card;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 2bde4f1fb9c..d2efa5ff125 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -471,7 +471,7 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
channel->state == CH_STATE_UP)
qeth_issue_next_read(card);
- tasklet_schedule(&channel->irq_tasklet);
+ qeth_irq_tasklet((unsigned long)channel);
return;
out:
wake_up(&card->wait_q);
@@ -951,40 +951,6 @@ qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
}
static int
-qeth_register_ip_addresses(void *ptr)
-{
- struct qeth_card *card;
-
- card = (struct qeth_card *) ptr;
- daemonize("qeth_reg_ip");
- QETH_DBF_TEXT(trace,4,"regipth1");
- if (!qeth_do_run_thread(card, QETH_SET_IP_THREAD))
- return 0;
- QETH_DBF_TEXT(trace,4,"regipth2");
- qeth_set_ip_addr_list(card);
- qeth_clear_thread_running_bit(card, QETH_SET_IP_THREAD);
- return 0;
-}
-
-/*
- * Drive the SET_PROMISC_MODE thread
- */
-static int
-qeth_set_promisc_mode(void *ptr)
-{
- struct qeth_card *card = (struct qeth_card *) ptr;
-
- daemonize("qeth_setprm");
- QETH_DBF_TEXT(trace,4,"setprm1");
- if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
- return 0;
- QETH_DBF_TEXT(trace,4,"setprm2");
- qeth_setadp_promisc_mode(card);
- qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
- return 0;
-}
-
-static int
qeth_recover(void *ptr)
{
struct qeth_card *card;
@@ -1047,11 +1013,6 @@ qeth_start_kernel_thread(struct work_struct *work)
if (card->read.state != CH_STATE_UP &&
card->write.state != CH_STATE_UP)
return;
-
- if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
- kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
- if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
- kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
kernel_thread(qeth_recover, (void *) card, SIGCHLD);
}
@@ -1074,7 +1035,7 @@ qeth_set_intial_options(struct qeth_card *card)
card->options.layer2 = 1;
else
card->options.layer2 = 0;
- card->options.performance_stats = 1;
+ card->options.performance_stats = 0;
}
/**
@@ -1613,8 +1574,6 @@ qeth_issue_next_read(struct qeth_card *card)
return -ENOMEM;
}
qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
- wait_event(card->wait_q,
- atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(trace, 6, "noirqpnd");
rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
(addr_t) iob, 0, 0);
@@ -1635,6 +1594,7 @@ qeth_alloc_reply(struct qeth_card *card)
reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
if (reply){
atomic_set(&reply->refcnt, 1);
+ atomic_set(&reply->received, 0);
reply->card = card;
};
return reply;
@@ -1655,31 +1615,6 @@ qeth_put_reply(struct qeth_reply *reply)
kfree(reply);
}
-static void
-qeth_cmd_timeout(unsigned long data)
-{
- struct qeth_reply *reply, *list_reply, *r;
- unsigned long flags;
-
- reply = (struct qeth_reply *) data;
- spin_lock_irqsave(&reply->card->lock, flags);
- list_for_each_entry_safe(list_reply, r,
- &reply->card->cmd_waiter_list, list) {
- if (reply == list_reply){
- qeth_get_reply(reply);
- list_del_init(&reply->list);
- spin_unlock_irqrestore(&reply->card->lock, flags);
- reply->rc = -ETIME;
- reply->received = 1;
- wake_up(&reply->wait_q);
- qeth_put_reply(reply);
- return;
- }
- }
- spin_unlock_irqrestore(&reply->card->lock, flags);
-}
-
-
static struct qeth_ipa_cmd *
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
@@ -1745,7 +1680,7 @@ qeth_clear_ipacmd_list(struct qeth_card *card)
list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
qeth_get_reply(reply);
reply->rc = -EIO;
- reply->received = 1;
+ atomic_inc(&reply->received);
list_del_init(&reply->list);
wake_up(&reply->wait_q);
qeth_put_reply(reply);
@@ -1814,7 +1749,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
&card->cmd_waiter_list);
spin_unlock_irqrestore(&card->lock, flags);
} else {
- reply->received = 1;
+ atomic_inc(&reply->received);
wake_up(&reply->wait_q);
}
qeth_put_reply(reply);
@@ -1858,7 +1793,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
int rc;
unsigned long flags;
struct qeth_reply *reply = NULL;
- struct timer_list timer;
+ unsigned long timeout;
QETH_DBF_TEXT(trace, 2, "sendctl");
@@ -1873,21 +1808,20 @@ qeth_send_control_data(struct qeth_card *card, int len,
reply->seqno = QETH_IDX_COMMAND_SEQNO;
else
reply->seqno = card->seqno.ipa++;
- init_timer(&timer);
- timer.function = qeth_cmd_timeout;
- timer.data = (unsigned long) reply;
init_waitqueue_head(&reply->wait_q);
spin_lock_irqsave(&card->lock, flags);
list_add_tail(&reply->list, &card->cmd_waiter_list);
spin_unlock_irqrestore(&card->lock, flags);
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
- wait_event(card->wait_q,
- atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+
+ while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
qeth_prepare_control_data(card, len, iob);
+
if (IS_IPA(iob->data))
- timer.expires = jiffies + QETH_IPA_TIMEOUT;
+ timeout = jiffies + QETH_IPA_TIMEOUT;
else
- timer.expires = jiffies + QETH_TIMEOUT;
+ timeout = jiffies + QETH_TIMEOUT;
+
QETH_DBF_TEXT(trace, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1906,9 +1840,16 @@ qeth_send_control_data(struct qeth_card *card, int len,
wake_up(&card->wait_q);
return rc;
}
- add_timer(&timer);
- wait_event(reply->wait_q, reply->received);
- del_timer_sync(&timer);
+ while (!atomic_read(&reply->received)) {
+ if (time_after(jiffies, timeout)) {
+ spin_lock_irqsave(&reply->card->lock, flags);
+ list_del_init(&reply->list);
+ spin_unlock_irqrestore(&reply->card->lock, flags);
+ reply->rc = -ETIME;
+ atomic_inc(&reply->received);
+ wake_up(&reply->wait_q);
+ }
+ };
rc = reply->rc;
qeth_put_reply(reply);
return rc;
@@ -2466,32 +2407,17 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
}
-static inline __u16
+static inline void
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
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
- return vlan_id;
}
static inline __u16
@@ -2560,7 +2486,6 @@ qeth_process_inbound_buffer(struct qeth_card *card,
int offset;
int rxrc;
__u16 vlan_tag = 0;
- __u16 *vlan_addr;
/* get first element of current buffer */
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
@@ -2571,7 +2496,7 @@ qeth_process_inbound_buffer(struct qeth_card *card,
&offset, &hdr))) {
skb->dev = card->dev;
if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
- vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
+ qeth_layer2_rebuild_skb(card, skb, hdr);
else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
vlan_tag = qeth_rebuild_skb(card, skb, hdr);
else { /*in case of OSN*/
@@ -3968,13 +3893,22 @@ static inline struct sk_buff *
qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr **hdr, int ipv)
{
- struct sk_buff *new_skb;
+ struct sk_buff *new_skb, *new_skb2;
QETH_DBF_TEXT(trace, 6, "prepskb");
-
- new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
- if (new_skb == NULL)
+ new_skb = skb;
+ new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+ if (!new_skb)
+ return NULL;
+ new_skb2 = qeth_realloc_headroom(card, new_skb,
+ sizeof(struct qeth_hdr));
+ if (!new_skb2) {
+ __qeth_free_new_skb(skb, new_skb);
return NULL;
+ }
+ if (new_skb != skb)
+ __qeth_free_new_skb(new_skb2, new_skb);
+ new_skb = new_skb2;
*hdr = __qeth_prepare_skb(card, new_skb, ipv);
if (*hdr == NULL) {
__qeth_free_new_skb(skb, new_skb);
@@ -4844,9 +4778,11 @@ qeth_arp_query(struct qeth_card *card, char __user *udata)
"(0x%x/%d)\n",
QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
tmp, tmp);
- copy_to_user(udata, qinfo.udata, 4);
+ if (copy_to_user(udata, qinfo.udata, 4))
+ rc = -EFAULT;
} else {
- copy_to_user(udata, qinfo.udata, qinfo.udata_len);
+ if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+ rc = -EFAULT;
}
kfree(qinfo.udata);
return rc;
@@ -4992,8 +4928,10 @@ qeth_snmp_command(struct qeth_card *card, char __user *udata)
if (rc)
PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
QETH_CARD_IFNAME(card), rc);
- else
- copy_to_user(udata, qinfo.udata, qinfo.udata_len);
+ else {
+ if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+ rc = -EFAULT;
+ }
kfree(ureq);
kfree(qinfo.udata);
@@ -5544,12 +5482,10 @@ qeth_set_multicast_list(struct net_device *dev)
qeth_add_multicast_ipv6(card);
#endif
out:
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
return;
- if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_setadp_promisc_mode(card);
}
static int
@@ -6351,6 +6287,42 @@ static struct ethtool_ops qeth_ethtool_ops = {
};
static int
+qeth_hard_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ struct qeth_card *card;
+ struct ethhdr *eth;
+
+ card = qeth_get_card_from_dev(skb->dev);
+ if (card->options.layer2)
+ goto haveheader;
+#ifdef CONFIG_QETH_IPV6
+ /* cause of the manipulated arp constructor and the ARP
+ flag for OSAE devices we have some nasty exceptions */
+ if (card->info.type == QETH_CARD_TYPE_OSAE) {
+ if (!card->options.fake_ll) {
+ if ((skb->pkt_type==PACKET_OUTGOING) &&
+ (skb->protocol==ETH_P_IPV6))
+ goto haveheader;
+ else
+ return 0;
+ } else {
+ if ((skb->pkt_type==PACKET_OUTGOING) &&
+ (skb->protocol==ETH_P_IP))
+ return 0;
+ else
+ goto haveheader;
+ }
+ }
+#endif
+ if (!card->options.fake_ll)
+ return 0;
+haveheader:
+ eth = eth_hdr(skb);
+ memcpy(haddr, eth->h_source, ETH_ALEN);
+ return ETH_ALEN;
+}
+
+static int
qeth_netdev_init(struct net_device *dev)
{
struct qeth_card *card;
@@ -6388,7 +6360,10 @@ qeth_netdev_init(struct net_device *dev)
if (card->options.fake_ll &&
(qeth_get_netdev_flags(card) & IFF_NOARP))
dev->hard_header = qeth_fake_header;
- dev->hard_header_parse = NULL;
+ if (dev->type == ARPHRD_IEEE802_TR)
+ dev->hard_header_parse = NULL;
+ else
+ dev->hard_header_parse = qeth_hard_header_parse;
dev->set_mac_address = qeth_layer2_set_mac_address;
dev->flags |= qeth_get_netdev_flags(card);
if ((card->options.fake_broadcast) ||
@@ -8235,8 +8210,7 @@ qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
}
if (!qeth_add_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
return rc;
}
@@ -8264,8 +8238,7 @@ qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
return;
if (!qeth_delete_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
}
/*
@@ -8308,8 +8281,7 @@ qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
}
if (!qeth_add_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
return 0;
}
@@ -8337,8 +8309,7 @@ qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
return;
if (!qeth_delete_ip(card, ipaddr))
kfree(ipaddr);
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
}
/**
@@ -8380,8 +8351,7 @@ qeth_ip_event(struct notifier_block *this,
default:
break;
}
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
out:
return NOTIFY_DONE;
}
@@ -8433,8 +8403,7 @@ qeth_ip6_event(struct notifier_block *this,
default:
break;
}
- if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
- schedule_work(&card->kernel_thread_starter);
+ qeth_set_ip_addr_list(card);
out:
return NOTIFY_DONE;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 5d39b2df0cc..85093b71f9f 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -237,7 +237,7 @@ zfcp_device_setup(char *devstr)
return 0;
len = strlen(devstr) + 1;
- str = (char *) kmalloc(len, GFP_KERNEL);
+ str = kmalloc(len, GFP_KERNEL);
if (!str)
goto err_out;
memcpy(str, devstr, len);
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index 385f4f76831..ac7d1258efe 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -621,7 +621,7 @@ static long read_ecp(unsigned minor, char __user *c, unsigned long cnt)
static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos)
{
long rc;
- unsigned minor = iminor(f->f_dentry->d_inode);
+ unsigned minor = iminor(f->f_path.dentry->d_inode);
if (minor >= BPP_NO) return -ENODEV;
if (!instances[minor].present) return -ENODEV;
@@ -774,7 +774,7 @@ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt)
static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos)
{
long errno = 0;
- unsigned minor = iminor(f->f_dentry->d_inode);
+ unsigned minor = iminor(f->f_path.dentry->d_inode);
if (minor >= BPP_NO) return -ENODEV;
if (!instances[minor].present) return -ENODEV;
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index f5803ecb199..ad1c7db96cb 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -404,7 +404,7 @@ static long wd_compat_ioctl(struct file *file, unsigned int cmd,
case WIOCSTOP:
case WIOCGSTAT:
lock_kernel();
- rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+ rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
unlock_kernel();
break;
/* everything else is handled by the generic compat layer */
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index d92bc8827a9..a4909e0c7f8 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -121,7 +121,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
__u8 ireg = 0;
int error = 0;
- if (D7S_MINOR != iminor(file->f_dentry->d_inode))
+ if (D7S_MINOR != iminor(file->f_path.dentry->d_inode))
return -ENODEV;
lock_kernel();
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 81ba2d71cee..4e2a0e2dcc2 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -676,7 +676,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
case OPROMSETCUR:
case OPROMPCI2NODE:
case OPROMPATH2NODE:
- rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+ rval = openprom_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
break;
}
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 55b2b31bd7a..386e7de0b7e 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -610,7 +610,7 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
unsigned int map_size, ret, map_offset;
struct vfc_dev *dev;
- dev = vfc_get_dev_ptr(iminor(file->f_dentry->d_inode));
+ dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode));
if(dev == NULL)
return -ENODEV;
@@ -659,7 +659,7 @@ static int vfc_probe(void)
if (!cards)
return -ENODEV;
- vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) *
+ vfc_dev_lst = kmalloc(sizeof(struct vfc_dev *) *
(cards+1),
GFP_KERNEL);
if (vfc_dev_lst == NULL)
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 99a259c5a0c..e1b44d6c0c3 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-2005 3ware Inc.
+ Copyright (C) 1999-2007 3ware Inc.
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
@@ -191,6 +191,9 @@
before shutting down card.
Change to new 'change_queue_depth' api.
Fix 'handled=1' ISR usage, remove bogus IRQ check.
+ 1.26.02.002 - Free irq handler in __tw_shutdown().
+ Turn on RCD bit for caching mode page.
+ Serialize reset code.
*/
#include <linux/module.h>
@@ -214,7 +217,7 @@
#include "3w-xxxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "1.26.02.001"
+#define TW_DRIVER_VERSION "1.26.02.002"
static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
static int tw_device_extension_count = 0;
static int twe_major = -1;
@@ -226,7 +229,7 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(TW_DRIVER_VERSION);
/* Function prototypes */
-static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
+static int tw_reset_device_extension(TW_Device_Extension *tw_dev);
/* Functions */
@@ -984,24 +987,12 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
/* Now wait for the command to complete */
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 = -ERESTARTSYS;
- goto out2;
- }
-
/* 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 */
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);
- tw_dev->posted_request_count--;
- spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
- if (tw_reset_device_extension(tw_dev, 1)) {
+ if (tw_reset_device_extension(tw_dev)) {
printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
}
goto out2;
@@ -1336,7 +1327,7 @@ static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
} /* End tw_unmap_scsi_data() */
/* This function will reset a device extension */
-static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
+static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
{
int i = 0;
struct scsi_cmnd *srb;
@@ -1382,15 +1373,10 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_rese
printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
return 1;
}
- 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);
- }
+ TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ clear_bit(TW_IN_RESET, &tw_dev->flags);
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
return 0;
} /* End tw_reset_device_extension() */
@@ -1437,14 +1423,18 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
"WARNING: Command (0x%x) timed out, resetting card.\n",
SCpnt->cmnd[0]);
+ /* Make sure we are not issuing an ioctl or resetting from ioctl */
+ mutex_lock(&tw_dev->ioctl_lock);
+
/* Now reset the card and some of the device extension data */
- if (tw_reset_device_extension(tw_dev, 0)) {
+ if (tw_reset_device_extension(tw_dev)) {
printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
goto out;
}
retval = SUCCESS;
out:
+ mutex_unlock(&tw_dev->ioctl_lock);
return retval;
} /* End tw_scsi_eh_reset() */
@@ -1660,9 +1650,9 @@ static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int reques
request_buffer[4] = 0x8; /* caching page */
request_buffer[5] = 0xa; /* page length */
if (*flags & 0x1)
- request_buffer[6] = 0x4; /* WCE on */
+ request_buffer[6] = 0x5; /* WCE on, RCD on */
else
- request_buffer[6] = 0x0; /* WCE off */
+ request_buffer[6] = 0x1; /* WCE off, RCD on */
tw_transfer_internal(tw_dev, request_id, request_buffer,
sizeof(request_buffer));
@@ -2012,6 +2002,10 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
int retval = 1;
TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+ /* If we are resetting due to timed out ioctl, report as busy */
+ if (test_bit(TW_IN_RESET, &tw_dev->flags))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
/* Save done function into Scsi_Cmnd struct */
SCpnt->scsi_done = done;
@@ -2100,6 +2094,10 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
handled = 1;
+ /* If we are resetting, bail */
+ if (test_bit(TW_IN_RESET, &tw_dev->flags))
+ 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");
@@ -2276,6 +2274,9 @@ static void __tw_shutdown(TW_Device_Extension *tw_dev)
/* Disable interrupts */
TW_DISABLE_INTERRUPTS(tw_dev);
+ /* Free up the IRQ */
+ free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no);
/* Tell the card we are shutting down */
@@ -2444,9 +2445,6 @@ static void tw_remove(struct pci_dev *pdev)
twe_major = -1;
}
- /* Free up the IRQ */
- free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
-
/* Shutdown the card */
__tw_shutdown(tw_dev);
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index bbd654a2b9b..0742e684665 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-2005 3ware Inc.
+ Copyright (C) 1999-2007 3ware Inc.
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 69569096dae..7869c34a4a3 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1303,7 +1303,7 @@ config SCSI_LPFC
config SCSI_SEAGATE
tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support"
- depends on X86 && ISA && SCSI && BROKEN
+ depends on X86 && ISA && SCSI
---help---
These are 8-bit SCSI controllers; the ST-01 is also supported by
this driver. It is explained in section 3.9 of the SCSI-HOWTO,
@@ -1737,7 +1737,7 @@ config SCSI_NCR53C7xx_FAST
config SUN3_SCSI
tristate "Sun3 NCR5380 SCSI"
- depends on SUN3 && SCSI && BROKEN
+ depends on SUN3 && SCSI
select SCSI_SPI_ATTRS
help
This option will enable support for the OBIO (onboard io) NCR5380
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index ac108f9e267..426cd6f49f5 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -288,7 +288,7 @@ int aac_get_containers(struct aac_dev *dev)
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
- fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(
+ fsa_dev_ptr = kmalloc(
sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
if (!fsa_dev_ptr) {
aac_fib_free(fibptr);
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index d5cf8b91a0e..6d305b2f854 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -386,7 +386,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
* Ok now init the communication subsystem
*/
- dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
+ dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
if (dev->queues == NULL) {
printk(KERN_ERR "Error could not allocate comm region.\n");
return NULL;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 359e7ddfdb4..d2cf875af59 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -117,8 +117,8 @@ static struct pci_device_id aac_pci_tbl[] = {
{ 0x9005, 0x0286, 0x9005, 0x029b, 0, 0, 22 }, /* AAR-2820SA (Intruder) */
{ 0x9005, 0x0286, 0x9005, 0x029c, 0, 0, 23 }, /* AAR-2620SA (Intruder) */
{ 0x9005, 0x0286, 0x9005, 0x029d, 0, 0, 24 }, /* AAR-2420SA (Intruder) */
- { 0x9005, 0x0286, 0x9005, 0x029e, 0, 0, 25 }, /* ICP9024R0 (Lancer) */
- { 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */
+ { 0x9005, 0x0286, 0x9005, 0x029e, 0, 0, 25 }, /* ICP9024RO (Lancer) */
+ { 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014RO (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */
{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */
@@ -137,15 +137,15 @@ static struct pci_device_id aac_pci_tbl[] = {
{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
{ 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */
{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */
- { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005SAS */
+ { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005 */
{ 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */
{ 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */
{ 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */
{ 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */
- { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
+ { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000 (BlackBird) */
{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
- { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800SAS (Hurricane44) */
+ { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800 (Hurricane44) */
{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
@@ -193,8 +193,8 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2820SA ", 1 }, /* AAR-2820SA (Intruder) */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2620SA ", 1 }, /* AAR-2620SA (Intruder) */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2420SA ", 1 }, /* AAR-2420SA (Intruder) */
- { aac_rkt_init, "aacraid", "ICP ", "ICP9024R0 ", 2 }, /* ICP9024R0 (Lancer) */
- { aac_rkt_init, "aacraid", "ICP ", "ICP9014R0 ", 1 }, /* ICP9014R0 (Lancer) */
+ { aac_rkt_init, "aacraid", "ICP ", "ICP9024RO ", 2 }, /* ICP9024RO (Lancer) */
+ { aac_rkt_init, "aacraid", "ICP ", "ICP9014RO ", 1 }, /* ICP9014RO (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */
{ aac_rkt_init, "aacraid", "ICP ", "ICP5445AU ", 1 }, /* ICP5445AU (Hurricane44) */
@@ -212,14 +212,14 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005 ", 1 }, /* ASR-4005 */
{ aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */
{ aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */
{ aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000 ", 1 }, /* ASR-4000 (BlackBird & AvonPark) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */
- { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-3800SAS ", 1 }, /* ASR-3800SAS (Hurricane44) */
+ { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-3800 ", 1 }, /* ASR-3800 (Hurricane44) */
{ aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
{ aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 2b344356a29..306bec355e4 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -18215,6 +18215,7 @@ AdvInquiryHandling(
}
MODULE_LICENSE("Dual BSD/GPL");
+#ifdef CONFIG_PCI
/* PCI Devices supported by this driver */
static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
@@ -18232,4 +18233,4 @@ static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
{ }
};
MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
-
+#endif /* CONFIG_PCI */
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index d7a61a6bdaa..1d239f6c010 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -699,7 +699,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
#endif
int i;
ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */
- SCpnt->host_scribble = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+ SCpnt->host_scribble = kmalloc(512, GFP_KERNEL | GFP_DMA);
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
cptr = (struct chain *) SCpnt->host_scribble;
if (cptr == NULL) {
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 46eed10b25d..7d1fec62094 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2565,7 +2565,7 @@ aic7xxx_allocate_scb(struct aic7xxx_host *p)
}
}
scb_count = min( (i-1), p->scb_data->maxscbs - p->scb_data->numscbs);
- scb_ap = (struct aic7xxx_scb *)kmalloc(sizeof (struct aic7xxx_scb) * scb_count
+ scb_ap = kmalloc(sizeof (struct aic7xxx_scb) * scb_count
+ sizeof(struct aic7xxx_scb_dma), GFP_ATOMIC);
if (scb_ap == NULL)
return(0);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index e95b367d09e..a965ed3548d 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4319,7 +4319,7 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
- ptr = (struct SGentry *)kmalloc(PAGE_SIZE, GFP_KERNEL);
+ ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!ptr) {
adapter_sg_tables_free(acb);
return 1;
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 60b1b434eba..365db537a28 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -297,7 +297,7 @@ static void adpt_inquiry(adpt_hba* pHba)
s32 rcode;
memset(msg, 0, sizeof(msg));
- buf = (u8*)kmalloc(80,GFP_KERNEL|ADDR32);
+ buf = kmalloc(80,GFP_KERNEL|ADDR32);
if(!buf){
printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);
return;
@@ -1311,7 +1311,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
schedule_timeout_uninterruptible(1);
} while (m == EMPTY_QUEUE);
- status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32);
+ status = kmalloc(4, GFP_KERNEL|ADDR32);
if(status == NULL) {
adpt_send_nop(pHba, m);
printk(KERN_ERR"IOP reset failed - no free memory.\n");
@@ -1444,7 +1444,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
}
continue;
}
- d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
+ d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
if(d==NULL)
{
printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name);
@@ -2425,7 +2425,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
pDev = pDev->next_lun;
}
if(!pDev ) { // Something new add it
- d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
+ d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
if(d==NULL)
{
printk(KERN_CRIT "Out of memory for I2O device data.\n");
@@ -2728,7 +2728,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
kfree(pHba->reply_pool);
- pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
+ pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
if(!pHba->reply_pool){
printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name);
return -1;
diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
index 6ac0633d545..f67d9efc7a9 100644
--- a/drivers/scsi/ibmvscsi/Makefile
+++ b/drivers/scsi/ibmvscsi/Makefile
@@ -1,7 +1,9 @@
obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o
ibmvscsic-y += ibmvscsi.o
+ifndef CONFIG_PPC_PSERIES
ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o
+endif
ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o
obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index f160357e37a..d561663fb4e 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2828,7 +2828,7 @@ static int i91u_detect(struct scsi_host_template * tpnt)
for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
i = tul_num_ch * tul_num_scb * sizeof(SCB);
- if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
+ if ((tul_scb = kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
break;
}
if (tul_scb == NULL) {
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index d0b139cccbb..43768408437 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -749,7 +749,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
if (!offset)
crypto_hash_update(
&tcp_conn->rx_hash,
- &sg[i], 1);
+ &sg[i], sg[i].length);
else
partial_sg_digest_update(
&tcp_conn->rx_hash,
@@ -1777,13 +1777,13 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
CRYPTO_ALG_ASYNC);
tcp_conn->tx_hash.flags = 0;
- if (!tcp_conn->tx_hash.tfm)
+ if (IS_ERR(tcp_conn->tx_hash.tfm))
goto free_tcp_conn;
tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
CRYPTO_ALG_ASYNC);
tcp_conn->rx_hash.flags = 0;
- if (!tcp_conn->rx_hash.tfm)
+ if (IS_ERR(tcp_conn->rx_hash.tfm))
goto free_tx_tfm;
return cls_conn;
@@ -2044,13 +2044,11 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
sk = tcp_conn->sock->sk;
if (sk->sk_family == PF_INET) {
inet = inet_sk(sk);
- len = sprintf(buf, "%u.%u.%u.%u\n",
+ len = sprintf(buf, NIPQUAD_FMT "\n",
NIPQUAD(inet->daddr));
} else {
np = inet6_sk(sk);
- len = sprintf(buf,
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
- NIP6(np->daddr));
+ len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr));
}
mutex_unlock(&conn->xmitmutex);
break;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index e11b23c641e..d37048c96ea 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -260,7 +260,7 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
}
if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) {
- int senselen;
+ uint16_t senselen;
if (datalen < 2) {
invalid_datalen:
@@ -270,12 +270,12 @@ invalid_datalen:
goto out;
}
- senselen = (data[0] << 8) | data[1];
+ senselen = be16_to_cpu(*(uint16_t *)data);
if (datalen < senselen)
goto invalid_datalen;
memcpy(sc->sense_buffer, data + 2,
- min(senselen, SCSI_SENSE_BUFFERSIZE));
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
debug_scsi("copied %d bytes of sense\n",
min(senselen, SCSI_SENSE_BUFFERSIZE));
}
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 066292d3995..ec3bbbde6f7 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -56,6 +56,9 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) *
LPFC_MBUF_POOL_SIZE, GFP_KERNEL);
+ if (!pool->elements)
+ goto fail_free_lpfc_mbuf_pool;
+
pool->max_count = 0;
pool->current_count = 0;
for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) {
@@ -82,10 +85,11 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
fail_free_mbox_pool:
mempool_destroy(phba->mbox_mem_pool);
fail_free_mbuf_pool:
- while (--i)
+ while (i--)
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
pool->elements[i].phys);
kfree(pool->elements);
+ fail_free_lpfc_mbuf_pool:
pci_pool_destroy(phba->lpfc_mbuf_pool);
fail_free_dma_buf_pool:
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 046223b4ae5..b5bdd0d7a8b 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -13,8 +13,8 @@
* Version : v00.00.03.05
*
* Authors:
- * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
- * Sumant Patro <Sumant.Patro@lsil.com>
+ * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsi.com>
+ * Sumant Patro <Sumant.Patro@lsi.com>
*
* List of supported controllers
*
@@ -45,7 +45,7 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(MEGASAS_VERSION);
-MODULE_AUTHOR("sreenivas.bagalkote@lsil.com");
+MODULE_AUTHOR("megaraidlinux@lsi.com");
MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver");
/*
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 824fe080d1d..7d231106790 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5777,7 +5777,7 @@ static int osst_probe(struct device *dev)
dev_num = i;
/* allocate a struct osst_tape for this device */
- tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
+ tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index d72df5dae4e..e16fe361436 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1629,7 +1629,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
ret = nsp_cs_config(link);
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index fb7acea6028..5b458d2478f 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -545,8 +545,6 @@ SYM53C500_release(struct pcmcia_device *link)
*/
if (shost->irq)
free_irq(shost->irq, shost);
- if (shost->dma_channel != 0xff)
- free_dma(shost->dma_channel);
if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port);
@@ -895,7 +893,6 @@ SYM53C500_probe(struct pcmcia_device *link)
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
return SYM53C500_config(link);
} /* SYM53C500_attach */
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index aa60a5f1fbc..3b2e1a53e6e 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -117,7 +117,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
#endif
return 0;
}
- fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
+ fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
if (!fcs) {
printk ("PLUTO: Not enough memory to probe\n");
return 0;
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 16af5b79e58..1548d42a3b4 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1341,7 +1341,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
int host_status = DID_ERROR;
uint16_t comp_status = le16_to_cpu(sts->comp_status);
uint16_t state_flags = le16_to_cpu(sts->state_flags);
- uint16_t residual_length = le32_to_cpu(sts->residual_length);
+ uint32_t residual_length = le32_to_cpu(sts->residual_length);
uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
#if DEBUG_QLA1280_INTR
static char *reason[] = {
@@ -1413,8 +1413,10 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
"scsi: Underflow detected - retrying "
"command.\n");
host_status = DID_ERROR;
- } else
+ } else {
+ cp->resid = residual_length;
host_status = DID_OK;
+ }
break;
default:
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index c4fc40f8e8c..2c10130d9e0 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1602,6 +1602,7 @@ typedef struct fc_port {
#define CT_REJECT_RESPONSE 0x8001
#define CT_ACCEPT_RESPONSE 0x8002
+#define CT_REASON_INVALID_COMMAND_CODE 0x01
#define CT_REASON_CANNOT_PERFORM 0x09
#define CT_EXPL_ALREADY_REGISTERED 0x10
@@ -2079,6 +2080,7 @@ typedef struct scsi_qla_host {
uint32_t msi_enabled :1;
uint32_t msix_enabled :1;
uint32_t disable_serdes :1;
+ uint32_t gpsc_supported :1;
} flags;
atomic_t loop_state;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 32ebeec45ff..e4dd12f4b80 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -45,7 +45,6 @@ extern void qla2x00_update_fcports(scsi_qla_host_t *);
extern int qla2x00_abort_isp(scsi_qla_host_t *);
extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
-extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 97fbc62ec66..ec5b2dd90d6 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -127,8 +127,8 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,
ha->host_no, routine, ms_pkt->entry_status));
} else {
if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
- comp_status =
- ((struct ct_entry_24xx *)ms_pkt)->comp_status;
+ comp_status = le16_to_cpu(
+ ((struct ct_entry_24xx *)ms_pkt)->comp_status);
else
comp_status = le16_to_cpu(ms_pkt->status);
switch (comp_status) {
@@ -143,6 +143,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,
DEBUG2_3(qla2x00_dump_buffer(
(uint8_t *)&ct_rsp->header,
sizeof(struct ct_rsp_hdr)));
+ rval = QLA_INVALID_COMMAND;
} else
rval = QLA_SUCCESS;
break;
@@ -1683,7 +1684,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list)
memset(list[i].fabric_port_name, 0, WWN_SIZE);
/* Prepare common MS IOCB */
- ms_pkt = qla2x00_prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
+ ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GFPN_ID_REQ_SIZE,
GFPN_ID_RSP_SIZE);
/* Prepare CT request */
@@ -1784,6 +1785,8 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
return QLA_FUNCTION_FAILED;
+ if (!ha->flags.gpsc_supported)
+ return QLA_FUNCTION_FAILED;
rval = qla2x00_mgmt_svr_login(ha);
if (rval)
@@ -1813,8 +1816,19 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
/*EMPTY*/
DEBUG2_3(printk("scsi(%ld): GPSC issue IOCB "
"failed (%d).\n", ha->host_no, rval));
- } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
- "GPSC") != QLA_SUCCESS) {
+ } else if ((rval = qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
+ "GPSC")) != QLA_SUCCESS) {
+ /* FM command unsupported? */
+ if (rval == QLA_INVALID_COMMAND &&
+ ct_rsp->header.reason_code ==
+ CT_REASON_INVALID_COMMAND_CODE) {
+ DEBUG2(printk("scsi(%ld): GPSC command "
+ "unsupported, disabling query...\n",
+ ha->host_no));
+ ha->flags.gpsc_supported = 0;
+ rval = QLA_FUNCTION_FAILED;
+ break;
+ }
rval = QLA_FUNCTION_FAILED;
} else {
/* Save portname */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a823f0bc519..b3dac26ddba 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2103,40 +2103,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
}
}
-/*
- * qla2x00_update_fcport
- * Updates device on list.
- *
- * Input:
- * ha = adapter block pointer.
- * fcport = port structure pointer.
- *
- * Return:
- * 0 - Success
- * BIT_0 - error
- *
- * Context:
- * Kernel context.
- */
-void
-qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
-{
- fcport->ha = ha;
- fcport->login_retry = 0;
- fcport->port_login_retry_count = ha->port_down_retry_count *
- PORT_RETRY_TIME;
- atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
- PORT_RETRY_TIME);
- fcport->flags &= ~FCF_LOGIN_NEEDED;
-
- qla2x00_iidma_fcport(ha, fcport);
-
- atomic_set(&fcport->state, FCS_ONLINE);
-
- qla2x00_reg_remote_port(ha, fcport);
-}
-
-void
+static void
qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
{
struct fc_rport_identifiers rport_ids;
@@ -2179,6 +2146,39 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
}
/*
+ * qla2x00_update_fcport
+ * Updates device on list.
+ *
+ * Input:
+ * ha = adapter block pointer.
+ * fcport = port structure pointer.
+ *
+ * Return:
+ * 0 - Success
+ * BIT_0 - error
+ *
+ * Context:
+ * Kernel context.
+ */
+void
+qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+{
+ fcport->ha = ha;
+ fcport->login_retry = 0;
+ fcport->port_login_retry_count = ha->port_down_retry_count *
+ PORT_RETRY_TIME;
+ atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
+ PORT_RETRY_TIME);
+ fcport->flags &= ~FCF_LOGIN_NEEDED;
+
+ qla2x00_iidma_fcport(ha, fcport);
+
+ atomic_set(&fcport->state, FCS_ONLINE);
+
+ qla2x00_reg_remote_port(ha, fcport);
+}
+
+/*
* qla2x00_configure_fabric
* Setup SNS devices with loop ID's.
*
@@ -3476,9 +3476,11 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
/* Set host adapter parameters. */
ha->flags.disable_risc_code_load = 0;
- ha->flags.enable_lip_reset = 1;
- ha->flags.enable_lip_full_login = 1;
- ha->flags.enable_target_reset = 1;
+ ha->flags.enable_lip_reset = 0;
+ ha->flags.enable_lip_full_login =
+ le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
+ ha->flags.enable_target_reset =
+ le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
ha->flags.enable_led_scheme = 0;
ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d3b6df4d55c..39fd17b05be 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -134,11 +134,11 @@ qla2300_intr_handler(int irq, void *dev_id)
if (stat & HSR_RISC_PAUSED) {
hccr = RD_REG_WORD(&reg->hccr);
if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
- qla_printk(KERN_INFO, ha,
- "Parity error -- HCCR=%x.\n", hccr);
+ qla_printk(KERN_INFO, ha, "Parity error -- "
+ "HCCR=%x, Dumping firmware!\n", hccr);
else
- qla_printk(KERN_INFO, ha,
- "RISC paused -- HCCR=%x.\n", hccr);
+ qla_printk(KERN_INFO, ha, "RISC paused -- "
+ "HCCR=%x, Dumping firmware!\n", hccr);
/*
* Issue a "HARD" reset in order for the RISC
@@ -147,6 +147,8 @@ qla2300_intr_handler(int irq, void *dev_id)
*/
WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);
RD_REG_WORD(&reg->hccr);
+
+ ha->isp_ops.fw_dump(ha, 1);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;
} else if ((stat & HSR_RISC_INT) == 0)
@@ -475,6 +477,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
}
set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+
+ ha->flags.gpsc_supported = 1;
break;
case MBA_CHG_IN_CONNECTION: /* Change in connection mode */
@@ -1440,8 +1444,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
"Dumping firmware!\n", hccr);
- qla24xx_fw_dump(ha, 1);
-
+ ha->isp_ops.fw_dump(ha, 1);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
break;
} else if ((stat & HSRX_RISC_INT) == 0)
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 4cde76c85cb..077e5789bee 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1339,9 +1339,9 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
- mcp->mb[1] = BIT_0;
- mcp->mb[2] = 0xff;
- mcp->mb[3] = 0;
+ mcp->mb[1] = BIT_6;
+ mcp->mb[2] = 0;
+ mcp->mb[3] = ha->loop_reset_delay;
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
} else {
mcp->mb[0] = MBC_LIP_RESET;
@@ -1823,8 +1823,8 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
ha->host_no));
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
- mcp->mb[1] = 0;
- mcp->mb[2] = 0xff;
+ mcp->mb[1] = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? BIT_3: 0;
+ mcp->mb[2] = 0;
mcp->mb[3] = 0;
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
@@ -2486,7 +2486,7 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma,
mcp->mb[4] = LSW(MSD(eft_dma));
mcp->mb[5] = MSW(MSD(eft_dma));
mcp->mb[6] = buffers;
- mcp->mb[7] = buffers;
+ mcp->mb[7] = 0;
mcp->out_mb |= MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2;
}
mcp->tov = 30;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d03523d3bf3..d6445ae841b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1037,48 +1037,49 @@ eh_host_reset_lock:
static int
qla2x00_loop_reset(scsi_qla_host_t *ha)
{
- int status = QLA_SUCCESS;
+ int ret;
struct fc_port *fcport;
+ if (ha->flags.enable_lip_full_login) {
+ ret = qla2x00_full_login_lip(ha);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+ "full_login_lip=%d.\n", __func__, ha->host_no,
+ ret));
+ }
+ atomic_set(&ha->loop_state, LOOP_DOWN);
+ atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
+ qla2x00_mark_all_devices_lost(ha, 0);
+ qla2x00_wait_for_loop_ready(ha);
+ }
+
if (ha->flags.enable_lip_reset) {
- status = qla2x00_lip_reset(ha);
+ ret = qla2x00_lip_reset(ha);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+ "lip_reset=%d.\n", __func__, ha->host_no, ret));
+ }
+ qla2x00_wait_for_loop_ready(ha);
}
- if (status == QLA_SUCCESS && ha->flags.enable_target_reset) {
+ if (ha->flags.enable_target_reset) {
list_for_each_entry(fcport, &ha->fcports, list) {
if (fcport->port_type != FCT_TARGET)
continue;
- status = qla2x00_device_reset(ha, fcport);
- if (status != QLA_SUCCESS)
- break;
+ ret = qla2x00_device_reset(ha, fcport);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+ "target_reset=%d d_id=%x.\n", __func__,
+ ha->host_no, ret, fcport->d_id.b24));
+ }
}
}
- if (status == QLA_SUCCESS &&
- ((!ha->flags.enable_target_reset &&
- !ha->flags.enable_lip_reset) ||
- ha->flags.enable_lip_full_login)) {
-
- status = qla2x00_full_login_lip(ha);
- }
-
/* Issue marker command only when we are going to start the I/O */
ha->marker_needed = 1;
- if (status) {
- /* Empty */
- DEBUG2_3(printk("%s(%ld): **** FAILED ****\n",
- __func__,
- ha->host_no));
- } else {
- /* Empty */
- DEBUG3(printk("%s(%ld): exiting normally.\n",
- __func__,
- ha->host_no));
- }
-
- return(status);
+ return QLA_SUCCESS;
}
/*
@@ -1413,7 +1414,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
sht = &qla2x00_driver_template;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
- pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432)
sht = &qla24xx_driver_template;
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) {
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 1fa0bce6b24..459e0d6bd2b 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.01.07-k3"
+#define QLA2XXX_VERSION "8.01.07-k4"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 1
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 4249e52a559..6f4cf2dd2f4 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -418,7 +418,6 @@ struct scsi_qla_host {
* concurrently.
*/
struct mutex mbox_sem;
- wait_queue_head_t mailbox_wait_queue;
/* temporary mailbox status registers */
volatile uint8_t mbox_status_count;
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 2122967bbf0..e021eb5db2b 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -76,4 +76,5 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
extern int ql4xextended_error_logging;
extern int ql4xdiscoverywait;
extern int ql4xdontresethba;
+extern int ql4_mod_unload;
#endif /* _QLA4x_GBL_H */
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index cc210f297a7..b907b06d72a 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -958,25 +958,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha)
return status;
}
-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
{
-#define QL4_LOCK_DRVR_WAIT 300
-#define QL4_LOCK_DRVR_SLEEP 100
+#define QL4_LOCK_DRVR_WAIT 30
+#define QL4_LOCK_DRVR_SLEEP 1
int drvr_wait = QL4_LOCK_DRVR_WAIT;
while (drvr_wait) {
- if (ql4xxx_lock_drvr(a) == 0) {
- msleep(QL4_LOCK_DRVR_SLEEP);
+ if (ql4xxx_lock_drvr(ha) == 0) {
+ ssleep(QL4_LOCK_DRVR_SLEEP);
if (drvr_wait) {
DEBUG2(printk("scsi%ld: %s: Waiting for "
- "Global Init Semaphore...n",
- a->host_no,
- __func__));
+ "Global Init Semaphore(%d)...n",
+ ha->host_no,
+ __func__, drvr_wait));
}
drvr_wait -= QL4_LOCK_DRVR_SLEEP;
} else {
DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
- "acquired.n", a->host_no, __func__));
+ "acquired.n", ha->host_no, __func__));
return QLA_SUCCESS;
}
}
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index ef975e0dc87..35b9e36a0e8 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -433,7 +433,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
readl(&ha->reg->mailbox[i]);
set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
- wake_up(&ha->mailbox_wait_queue);
}
} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
/* Immediately process the AENs that don't require much work.
@@ -686,7 +685,8 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
&ha->reg->ctrl_status);
readl(&ha->reg->ctrl_status);
- set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+ if (!ql4_mod_unload)
+ set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
break;
} else if (intr_status & INTR_PENDING) {
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index b721dc5dd71..7f28657eef3 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -29,18 +29,30 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
u_long wait_count;
uint32_t intr_status;
unsigned long flags = 0;
- DECLARE_WAITQUEUE(wait, current);
-
- mutex_lock(&ha->mbox_sem);
-
- /* Mailbox code active */
- set_bit(AF_MBOX_COMMAND, &ha->flags);
/* Make sure that pointers are valid */
if (!mbx_cmd || !mbx_sts) {
DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
"pointer\n", ha->host_no, __func__));
- goto mbox_exit;
+ return status;
+ }
+ /* Mailbox code active */
+ wait_count = MBOX_TOV * 100;
+
+ while (wait_count--) {
+ mutex_lock(&ha->mbox_sem);
+ if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
+ set_bit(AF_MBOX_COMMAND, &ha->flags);
+ mutex_unlock(&ha->mbox_sem);
+ break;
+ }
+ mutex_unlock(&ha->mbox_sem);
+ if (!wait_count) {
+ DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
+ ha->host_no, __func__));
+ return status;
+ }
+ msleep(10);
}
/* To prevent overwriting mailbox registers for a command that has
@@ -73,8 +85,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Wait for completion */
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&ha->mailbox_wait_queue, &wait);
/*
* If we don't want status, don't wait for the mailbox command to
@@ -83,8 +93,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
*/
if (outCount == 0) {
status = QLA_SUCCESS;
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ha->mailbox_wait_queue, &wait);
goto mbox_exit;
}
/* Wait for command to complete */
@@ -108,8 +116,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
spin_unlock_irqrestore(&ha->hardware_lock, flags);
msleep(10);
}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ha->mailbox_wait_queue, &wait);
/* Check for mailbox timeout. */
if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
@@ -155,9 +161,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
spin_unlock_irqrestore(&ha->hardware_lock, flags);
mbox_exit:
+ mutex_lock(&ha->mbox_sem);
clear_bit(AF_MBOX_COMMAND, &ha->flags);
- clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
mutex_unlock(&ha->mbox_sem);
+ clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
return status;
}
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 9ef693c8809..81fb7bd44f0 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -40,6 +40,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
"Option to enable extended error logging, "
"Default is 0 - no logging, 1 - debug logging");
+int ql4_mod_unload = 0;
+
/*
* SCSI host template entry points
*/
@@ -422,6 +424,9 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
goto qc_host_busy;
}
+ if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+ goto qc_host_busy;
+
spin_unlock_irq(ha->host->host_lock);
srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
@@ -707,16 +712,12 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
return stat;
}
-/**
- * qla4xxx_soft_reset - performs soft reset.
- * @ha: Pointer to host adapter structure.
- **/
-int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
{
- uint32_t max_wait_time;
- unsigned long flags = 0;
- int status = QLA_ERROR;
uint32_t ctrl_status;
+ unsigned long flags = 0;
+
+ DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -733,6 +734,20 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha)
readl(&ha->reg->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+/**
+ * qla4xxx_soft_reset - performs soft reset.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+{
+ uint32_t max_wait_time;
+ unsigned long flags = 0;
+ int status = QLA_ERROR;
+ uint32_t ctrl_status;
+
+ qla4xxx_hw_reset(ha);
/* Wait until the Network Reset Intr bit is cleared */
max_wait_time = RESET_INTR_TOV;
@@ -966,10 +981,12 @@ static void qla4xxx_do_dpc(struct work_struct *work)
struct scsi_qla_host *ha =
container_of(work, struct scsi_qla_host, dpc_work);
struct ddb_entry *ddb_entry, *dtemp;
+ int status = QLA_ERROR;
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
- "flags = 0x%08lx, dpc_flags = 0x%08lx\n",
- ha->host_no, __func__, ha->flags, ha->dpc_flags));
+ "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n",
+ ha->host_no, __func__, ha->flags, ha->dpc_flags,
+ readw(&ha->reg->ctrl_status)));
/* Initialization not yet finished. Don't do anything yet. */
if (!test_bit(AF_INIT_DONE, &ha->flags))
@@ -983,31 +1000,28 @@ static void qla4xxx_do_dpc(struct work_struct *work)
test_bit(DPC_RESET_HA, &ha->dpc_flags))
qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
- if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
+ if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
uint8_t wait_time = RESET_INTR_TOV;
- unsigned long flags = 0;
-
- qla4xxx_flush_active_srbs(ha);
- spin_lock_irqsave(&ha->hardware_lock, flags);
while ((readw(&ha->reg->ctrl_status) &
(CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
if (--wait_time == 0)
break;
-
- spin_unlock_irqrestore(&ha->hardware_lock,
- flags);
-
msleep(1000);
-
- spin_lock_irqsave(&ha->hardware_lock, flags);
}
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
if (wait_time == 0)
DEBUG2(printk("scsi%ld: %s: SR|FSR "
"bit not cleared-- resetting\n",
ha->host_no, __func__));
+ qla4xxx_flush_active_srbs(ha);
+ if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
+ qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+ status = qla4xxx_initialize_adapter(ha,
+ PRESERVE_DDB_LIST);
+ }
+ clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+ if (status == QLA_SUCCESS)
+ qla4xxx_enable_intrs(ha);
}
}
@@ -1062,7 +1076,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
/* Issue Soft Reset to put firmware in unknown state */
if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
- qla4xxx_soft_reset(ha);
+ qla4xxx_hw_reset(ha);
/* Remove timer thread, if present */
if (ha->timer_active)
@@ -1198,7 +1212,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
INIT_LIST_HEAD(&ha->free_srb_q);
mutex_init(&ha->mbox_sem);
- init_waitqueue_head(&ha->mailbox_wait_queue);
spin_lock_init(&ha->hardware_lock);
@@ -1665,6 +1678,7 @@ no_srp_cache:
static void __exit qla4xxx_module_exit(void)
{
+ ql4_mod_unload = 1;
pci_unregister_driver(&qla4xxx_pci_driver);
iscsi_unregister_transport(&qla4xxx_iscsi_transport);
kmem_cache_destroy(srb_cachep);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 454e19c8ad6..e5183a697d1 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.00.07-k"
+#define QLA4XXX_DRIVER_VERSION "5.00.07-k1"
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 1748e27501c..f02f48a882a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -265,13 +265,11 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio)
if (!rq->bio)
blk_rq_bio_prep(q, rq, bio);
- else if (!q->back_merge_fn(q, rq, bio))
+ else if (!ll_back_merge_fn(q, rq, bio))
return -EINVAL;
else {
rq->biotail->bi_next = bio;
rq->biotail = bio;
- rq->hard_nr_sectors += bio_sectors(bio);
- rq->nr_sectors = rq->hard_nr_sectors;
}
return 0;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 14e635aa44c..96b7cbd746a 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -133,12 +133,10 @@ struct async_scan_data {
/**
* scsi_complete_async_scans - Wait for asynchronous scans to complete
*
- * Asynchronous scans add themselves to the scanning_hosts list. Once
- * that list is empty, we know that the scans are complete. Rather than
- * waking up periodically to check the state of the list, we pretend to be
- * a scanning task by adding ourselves at the end of the list and going to
- * sleep. When the task before us wakes us up, we take ourselves off the
- * list and return.
+ * When this function returns, any host which started scanning before
+ * this function was called will have finished its scan. Hosts which
+ * started scanning after this function was called may or may not have
+ * finished.
*/
int scsi_complete_async_scans(void)
{
@@ -171,6 +169,11 @@ int scsi_complete_async_scans(void)
spin_lock(&async_scan_lock);
list_del(&data->list);
+ if (!list_empty(&scanning_hosts)) {
+ struct async_scan_data *next = list_entry(scanning_hosts.next,
+ struct async_scan_data, list);
+ complete(&next->prev_finished);
+ }
done:
spin_unlock(&async_scan_lock);
@@ -739,6 +742,14 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
sdev->no_uld_attach = 1;
switch (sdev->type = (inq_result[0] & 0x1f)) {
+ case TYPE_RBC:
+ /* RBC devices can return SCSI-3 compliance and yet
+ * still not support REPORT LUNS, so make them act as
+ * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
+ * specifically set */
+ if ((*bflags & BLIST_REPORTLUN2) == 0)
+ *bflags |= BLIST_NOREPORTLUN;
+ /* fall through */
case TYPE_TAPE:
case TYPE_DISK:
case TYPE_PRINTER:
@@ -749,11 +760,17 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
case TYPE_ENCLOSURE:
case TYPE_COMM:
case TYPE_RAID:
- case TYPE_RBC:
sdev->writeable = 1;
break;
- case TYPE_WORM:
case TYPE_ROM:
+ /* MMC devices can return SCSI-3 compliance and yet
+ * still not support REPORT LUNS, so make them act as
+ * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
+ * specifically set */
+ if ((*bflags & BLIST_REPORTLUN2) == 0)
+ *bflags |= BLIST_NOREPORTLUN;
+ /* fall through */
+ case TYPE_WORM:
sdev->writeable = 0;
break;
default:
@@ -1436,6 +1453,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
struct device *parent = &shost->shost_gendev;
struct scsi_target *starget;
+ if (strncmp(scsi_scan_type, "none", 4) == 0)
+ return ERR_PTR(-ENODEV);
+
+ if (!shost->async_scan)
+ scsi_complete_async_scans();
+
starget = scsi_alloc_target(parent, channel, id);
if (!starget)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 9c22f134271..ce0d14af33c 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1416,7 +1416,7 @@ static __init int iscsi_transport_init(void)
{
int err;
- printk(KERN_INFO "Loading iSCSI transport class v%s.",
+ printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
ISCSI_TRANSPORT_VERSION);
err = class_register(&iscsi_transport_class);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 3fded483146..014d7fea1ff 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -122,7 +122,7 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
if (!sshdr)
sshdr = &sshdr_tmp;
- if (scsi_normalize_sense(sense, sizeof(*sense),
+ if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE,
sshdr)
&& sshdr->sense_key == UNIT_ATTENTION)
continue;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f6a452846fa..b781a90d669 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -863,7 +863,7 @@ static void sd_rescan(struct device *dev)
*/
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 block_device *bdev = file->f_path.dentry->d_inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
struct scsi_device *sdev = scsi_disk(disk)->device;
@@ -1647,16 +1647,6 @@ static int sd_probe(struct device *dev)
if (error)
goto out_put;
- class_device_initialize(&sdkp->cdev);
- sdkp->cdev.dev = &sdp->sdev_gendev;
- sdkp->cdev.class = &sd_disk_class;
- strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
-
- if (class_device_add(&sdkp->cdev))
- goto out_put;
-
- get_device(&sdp->sdev_gendev);
-
sdkp->device = sdp;
sdkp->driver = &sd_template;
sdkp->disk = gd;
@@ -1670,6 +1660,16 @@ static int sd_probe(struct device *dev)
sdp->timeout = SD_MOD_TIMEOUT;
}
+ class_device_initialize(&sdkp->cdev);
+ sdkp->cdev.dev = &sdp->sdev_gendev;
+ sdkp->cdev.class = &sd_disk_class;
+ strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
+
+ if (class_device_add(&sdkp->cdev))
+ goto out_put;
+
+ get_device(&sdp->sdev_gendev);
+
gd->major = sd_major((index & 0xf0) >> 4);
gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
gd->minors = 16;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 5ffec2721b2..ff62e9708e1 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -114,6 +114,7 @@
#define DPRINTK( when, msg... ) do { if ( (DEBUG & (when)) == (when) ) printk( msg ); } while (0)
#else
#define DPRINTK( when, msg... ) do { } while (0)
+#define DEBUG 0
#endif
#define DANY( msg... ) DPRINTK( 0xffff, msg );
@@ -523,7 +524,7 @@ int __init seagate_st0x_detect (struct scsi_host_template * tpnt)
#ifdef ARBITRATE
" ARBITRATE"
#endif
-#ifdef DEBUG
+#if DEBUG
" DEBUG"
#endif
#ifdef FAST
@@ -733,7 +734,7 @@ static int internal_command (unsigned char target, unsigned char lun,
unsigned char *data = NULL;
struct scatterlist *buffer = NULL;
int clock, temp, nobuffs = 0, done = 0, len = 0;
-#ifdef DEBUG
+#if DEBUG
int transfered = 0, phase = 0, newphase;
#endif
register unsigned char status_read;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index fae6e95a629..89e9b36b178 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -468,7 +468,7 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
}
ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg);
- if (ret != ENOSYS)
+ if (ret != -ENOSYS)
return ret;
/*
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index d1268cb4683..0578ba42718 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -546,7 +546,7 @@ int sr_is_xa(Scsi_CD *cd)
if (!xa_test)
return 0;
- raw_sector = (unsigned char *) kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
+ raw_sector = kmalloc(2048, GFP_KERNEL | SR_GFP_DMA(cd));
if (!raw_sector)
return -ENOMEM;
if (0 == sr_read_sector(cd, cd->ms_offset + 16,
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index a3e9d0f2eb5..4eb3da996b3 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -117,7 +117,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
density = (blocklength > 2048) ? 0x81 : 0x83;
#endif
- buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
return -ENOMEM;
@@ -164,7 +164,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
if (cd->cdi.mask & CDC_MULTI_SESSION)
return 0;
- buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
return -ENOMEM;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 587274dd705..488ec7948a5 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -922,7 +922,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
struct st_modedef *STm;
struct st_partstat *STps;
char *name = tape_name(STp);
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int mode = TAPE_MODE(inode);
STp->ready = ST_READY;
@@ -2816,15 +2816,18 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
if (cmd_in == MTWEOF &&
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 successfully at EOM */
- if (fileno >= 0)
- fileno++;
+ (cmdstatp->flags & SENSE_EOM)) {
+ if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+ cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
+ ioctl_result = 0; /* EOF(s) written successfully at EOM */
+ STps->eof = ST_NOEOF;
+ } else { /* Writing EOF(s) failed */
+ if (fileno >= 0)
+ fileno -= undone;
+ if (undone < arg)
+ STps->eof = ST_NOEOF;
+ }
STps->drv_file = fileno;
- STps->eof = ST_NOEOF;
} else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
if (fileno >= 0)
STps->drv_file = fileno - undone;
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 3b3f3050a87..98e3fe10c1d 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -266,7 +266,7 @@ static struct scsi_host_template *the_template = NULL;
(struct NCR5380_hostdata *)(in)->hostdata
#define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
-#define NEXT(cmd) ((struct scsi_cmnd *)((cmd)->host_scribble))
+#define NEXT(cmd) (*(struct scsi_cmnd **)&((cmd)->host_scribble))
#define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble))
#define HOSTNO instance->host_no
@@ -650,7 +650,7 @@ __inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
#include <linux/interrupt.h>
static volatile int main_running = 0;
-static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
+static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
static __inline__ void queue_main(void)
{
@@ -1031,7 +1031,7 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd,
* reenable them. This prevents reentrancy and kernel stack overflow.
*/
-static void NCR5380_main (void *bl)
+static void NCR5380_main (struct work_struct *bl)
{
struct scsi_cmnd *tmp, *prev;
struct Scsi_Host *instance = first_instance;
@@ -1271,7 +1271,7 @@ static irqreturn_t NCR5380_intr (int irq, void *dev_id)
NCR_PRINT(NDEBUG_INTR);
if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
done = 0;
- ENABLE_IRQ();
+// ENABLE_IRQ();
INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
NCR5380_reselect(instance);
(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
@@ -1304,7 +1304,7 @@ static irqreturn_t NCR5380_intr (int irq, void *dev_id)
INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
NCR5380_dma_complete( instance );
done = 0;
- ENABLE_IRQ();
+// ENABLE_IRQ();
} else
#endif /* REAL_DMA */
{
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index d56d85dd9ba..69ee3e4a820 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -75,9 +75,9 @@
#define REAL_DMA
#include "scsi.h"
+#include "initio.h"
#include <scsi/scsi_host.h>
#include "sun3_scsi.h"
-#include "NCR5380.h"
static void NCR5380_print(struct Scsi_Host *instance);
diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h
index a1103b3e203..b29a9d661ca 100644
--- a/drivers/scsi/sun3_scsi.h
+++ b/drivers/scsi/sun3_scsi.h
@@ -221,7 +221,7 @@ struct sun3_udc_regs {
*
*/
-
+#include "NCR5380.h"
#if NDEBUG & NDEBUG_ARBITRATION
#define ARB_PRINTK(format, args...) \
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
index 92def310a84..bb0c9fd99e6 100644
--- a/drivers/scsi/sun3_scsi_vme.c
+++ b/drivers/scsi/sun3_scsi_vme.c
@@ -41,9 +41,9 @@
#define REAL_DMA
#include "scsi.h"
+#include "initio.h"
#include <scsi/scsi_host.h>
#include "sun3_scsi.h"
-#include "NCR5380.h"
extern int sun3_map_test(unsigned long, char *);
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 940fa1e6f99..21cd4c7f528 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -5545,7 +5545,7 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram
/*
* Allocate the array of lists of CCBs hashed by DSA.
*/
- np->ccbh = kcalloc(sizeof(struct sym_ccb **), CCB_HASH_SIZE, GFP_KERNEL);
+ np->ccbh = kcalloc(CCB_HASH_SIZE, sizeof(struct sym_ccb **), GFP_KERNEL);
if (!np->ccbh)
goto attach_failed;
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 6a1a568ca64..facb6785561 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -214,8 +214,8 @@ static void serial21285_shutdown(struct uart_port *port)
}
static void
-serial21285_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned long flags;
unsigned int baud, quot, h_lcr;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 9b8b585513e..cad426c9711 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -1061,7 +1061,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
return 0;
}
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 634ecca36a7..68817a7d8c0 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1523,7 +1523,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
/* FIX UP modem control here someday......
*/
-static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
ser_info_t *info = (ser_info_t *)tty->driver_data;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index e34bd03cfce..5261f0af8b1 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1763,8 +1763,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int
}
static void
-serial8250_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char cval, fcr = 0;
@@ -2296,7 +2296,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
local_irq_restore(flags);
}
-static int serial8250_console_setup(struct console *co, char *options)
+static int __init serial8250_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 9600;
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 4d0ff8f4a01..52e2e64c664 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -2239,6 +2239,30 @@ static struct pci_device_id serial_pci_tbl[] = {
pbn_b0_bt_1_460800 },
/*
+ * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408).
+ * Cards are identified by their subsystem vendor IDs, which
+ * (in hex) match the model number.
+ *
+ * Note that JC140x are RS422/485 cards which require ox950
+ * ACR = 0x10, and as such are not currently fully supported.
+ */
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1204, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1402, 0x0002, 0, 0,
+ pbn_b0_2_921600 }, */
+/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0,
+ 0x1404, 0x0004, 0, 0,
+ pbn_b0_4_921600 }, */
+ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1,
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+
+ /*
* Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
*/
{ PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4,
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index fc12d5df10e..2978c09860e 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -151,32 +151,6 @@ config SERIAL_8250_MANY_PORTS
say N here to save some memory. You can also say Y if you have an
"intelligent" multiport card such as Cyclades, Digiboards, etc.
-config SERIAL_8250_SHARE_IRQ
- bool "Support for sharing serial interrupts"
- depends on SERIAL_8250_EXTENDED
- help
- Some serial boards have hardware support which allows multiple dumb
- serial ports on the same board to share a single IRQ. To enable
- support for this in the serial driver, say Y here.
-
-config SERIAL_8250_DETECT_IRQ
- bool "Autodetect IRQ on standard ports (unsafe)"
- depends on SERIAL_8250_EXTENDED
- help
- Say Y here if you want the kernel to try to guess which IRQ
- to use for your serial port.
-
- This is considered unsafe; it is far better to configure the IRQ in
- a boot script using the setserial command.
-
- If unsure, say N.
-
-config SERIAL_8250_RSA
- bool "Support RSA serial ports"
- depends on SERIAL_8250_EXTENDED
- help
- ::: To be written :::
-
#
# Multi-port serial cards
#
@@ -199,7 +173,6 @@ config SERIAL_8250_ACCENT
To compile this driver as a module, choose M here: the module
will be called 8250_accent.
-
config SERIAL_8250_BOCA
tristate "Support Boca cards"
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@@ -230,6 +203,32 @@ config SERIAL_8250_HUB6
To compile this driver as a module, choose M here: the module
will be called 8250_hub6.
+config SERIAL_8250_SHARE_IRQ
+ bool "Support for sharing serial interrupts"
+ depends on SERIAL_8250_EXTENDED
+ help
+ Some serial boards have hardware support which allows multiple dumb
+ serial ports on the same board to share a single IRQ. To enable
+ support for this in the serial driver, say Y here.
+
+config SERIAL_8250_DETECT_IRQ
+ bool "Autodetect IRQ on standard ports (unsafe)"
+ depends on SERIAL_8250_EXTENDED
+ help
+ Say Y here if you want the kernel to try to guess which IRQ
+ to use for your serial port.
+
+ This is considered unsafe; it is far better to configure the IRQ in
+ a boot script using the setserial command.
+
+ If unsure, say N.
+
+config SERIAL_8250_RSA
+ bool "Support RSA serial ports"
+ depends on SERIAL_8250_EXTENDED
+ help
+ ::: To be written :::
+
config SERIAL_8250_MCA
tristate "Support 8250-type ports on MCA buses"
depends on SERIAL_8250 != n && MCA
@@ -664,7 +663,7 @@ config V850E_UART
config V850E_UARTB
bool
- depends V850E_UART && V850E_ME2
+ depends on V850E_UART && V850E_ME2
default y
config V850E_UART_CONSOLE
@@ -910,7 +909,7 @@ config SERIAL_M32R_PLDSIO
config SERIAL_TXX9
bool "TMPTX39XX/49XX SIO support"
- depends HAS_TXX9_SERIAL
+ depends on HAS_TXX9_SERIAL
select SERIAL_CORE
default y
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 4d3626ef464..f69bd097166 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -345,8 +345,8 @@ static void pl010_shutdown(struct uart_port *port)
}
static void
-pl010_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+pl010_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int lcr_h, old_cr;
unsigned long flags;
@@ -589,6 +589,8 @@ static int __init pl010_console_setup(struct console *co, char *options)
*/
if (co->index >= UART_NR)
co->index = 0;
+ if (!amba_ports[co->index])
+ return -ENODEV;
port = &amba_ports[co->index]->port;
if (options)
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index d503625730d..44639e71372 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -412,8 +412,8 @@ static void pl011_shutdown(struct uart_port *port)
}
static void
-pl011_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+pl011_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int lcr_h, old_cr;
unsigned long flags;
@@ -661,6 +661,8 @@ static int __init pl011_console_setup(struct console *co, char *options)
if (co->index >= UART_NR)
co->index = 0;
uap = amba_ports[co->index];
+ if (!uap)
+ return -ENODEV;
uap->port.uartclk = clk_get_rate(uap->clk);
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 9217ee6c786..881f886b91c 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -478,7 +478,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned
/*
* Change the port parameters
*/
-static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old)
+static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old)
{
unsigned long flags;
unsigned int mode, imr, quot, baud;
@@ -689,9 +689,9 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct
struct atmel_uart_data *data = pdev->dev.platform_data;
port->iotype = UPIO_MEM;
- port->flags = UPF_BOOT_AUTOCONF;
+ port->flags = UPF_BOOT_AUTOCONF;
port->ops = &atmel_pops;
- port->fifosize = 1;
+ port->fifosize = 1;
port->line = pdev->id;
port->dev = &pdev->dev;
@@ -890,7 +890,6 @@ static int atmel_serial_suspend(struct platform_device *pdev, pm_message_t state
if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
enable_irq_wake(port->irq);
else {
- disable_irq_wake(port->irq);
uart_suspend_port(&atmel_uart, port);
atmel_port->suspended = 1;
}
@@ -907,6 +906,8 @@ static int atmel_serial_resume(struct platform_device *pdev)
uart_resume_port(&atmel_uart, port);
atmel_port->suspended = 0;
}
+ else
+ disable_irq_wake(port->irq);
return 0;
}
diff --git a/drivers/serial/atmel_serial.h b/drivers/serial/atmel_serial.h
index fe1763b2a6d..11b44360e10 100644
--- a/drivers/serial/atmel_serial.h
+++ b/drivers/serial/atmel_serial.h
@@ -106,7 +106,7 @@
#define ATMEL_US_CSR 0x14 /* Channel Status Register */
#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
-#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [SAM9 only] */
+#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [AT91SAM9261 only] */
#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
#define ATMEL_US_CD (0xffff << 0) /* Clock Divider */
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 59801271488..23827189ec0 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -286,8 +286,8 @@ static void clps711xuart_shutdown(struct uart_port *port)
}
static void
-clps711xuart_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int ubrlcr, baud, quot;
unsigned long flags;
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 7a24e53546c..42b050c46ab 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -804,8 +804,8 @@ static struct e100_serial rs_table[] = {
#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
+static struct ktermios *serial_termios[NR_PORTS];
+static struct ktermios *serial_termios_locked[NR_PORTS];
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
static struct fast_timer fast_timers[NR_PORTS];
#endif
@@ -4223,7 +4223,7 @@ rs_ioctl(struct tty_struct *tty, struct file * file,
}
static void
-rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
@@ -4877,6 +4877,8 @@ rs_init(void)
driver->init_termios = tty_std_termios;
driver->init_termios.c_cflag =
B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
+ driver->init_termios.c_ispeed = 115200;
+ driver->init_termios.c_ospeed = 115200;
driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
driver->termios = serial_termios;
driver->termios_locked = serial_termios_locked;
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
index f30b93d6ef7..4a23340663a 100644
--- a/drivers/serial/crisv10.h
+++ b/drivers/serial/crisv10.h
@@ -93,8 +93,8 @@ struct e100_serial {
struct work_struct work;
struct async_icount icount; /* error-statistics etc.*/
- struct termios normal_termios;
- struct termios callout_termios;
+ struct ktermios normal_termios;
+ struct ktermios callout_termios;
#ifdef DECLARE_WAITQUEUE
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index af1544f3356..587d87b9eb3 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -461,8 +461,8 @@ static void dz_break_ctl(struct uart_port *uport, int break_state)
spin_unlock_irqrestore(&uport->lock, flags);
}
-static void dz_set_termios(struct uart_port *uport, struct termios *termios,
- struct termios *old_termios)
+static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
+ struct ktermios *old_termios)
{
struct dz_port *dport = (struct dz_port *)uport;
unsigned long flags;
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 8aa0f641866..71e6a24d8c2 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -1087,8 +1087,8 @@ static void icom_close(struct uart_port *port)
}
static void icom_set_termios(struct uart_port *port,
- struct termios *termios,
- struct termios *old_termios)
+ struct ktermios *termios,
+ struct ktermios *old_termios)
{
int baud;
unsigned cflag, iflag;
@@ -1510,7 +1510,7 @@ static int __devinit icom_probe(struct pci_dev *dev,
}
if ( (retval = pci_request_regions(dev, "icom"))) {
- dev_err(&dev->dev, "pci_request_region FAILED\n");
+ dev_err(&dev->dev, "pci_request_regions FAILED\n");
pci_disable_device(dev);
return retval;
}
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index ee5c782597d..e216dcf2937 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -459,8 +459,8 @@ static void imx_shutdown(struct uart_port *port)
}
static void
-imx_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+imx_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
index 2308d26c862..9cc0be93231 100644
--- a/drivers/serial/ioc3_serial.c
+++ b/drivers/serial/ioc3_serial.c
@@ -950,7 +950,7 @@ static void transmit_chars(struct uart_port *the_port)
*/
static void
ioc3_change_speed(struct uart_port *the_port,
- struct termios *new_termios, struct termios *old_termios)
+ struct ktermios *new_termios, struct ktermios *old_termios)
{
struct ioc3_port *port = get_ioc3_port(the_port);
unsigned int cflag;
@@ -1853,7 +1853,7 @@ static int ic3_startup(struct uart_port *the_port)
*/
static void
ic3_set_termios(struct uart_port *the_port,
- struct termios *termios, struct termios *old_termios)
+ struct ktermios *termios, struct ktermios *old_termios)
{
unsigned long port_flags;
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 711bd151143..c862f67c985 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -1681,7 +1681,7 @@ static void transmit_chars(struct uart_port *the_port)
*/
static void
ioc4_change_speed(struct uart_port *the_port,
- struct termios *new_termios, struct termios *old_termios)
+ struct ktermios *new_termios, struct ktermios *old_termios)
{
struct ioc4_port *port = get_ioc4_port(the_port, 0);
int baud, bits;
@@ -1802,7 +1802,7 @@ static inline int ic4_startup_local(struct uart_port *the_port)
ioc4_set_proto(port, the_port->mapbase);
/* set the speed of the serial port */
- ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
+ ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0);
return 0;
}
@@ -2570,7 +2570,7 @@ static int ic4_startup(struct uart_port *the_port)
*/
static void
ic4_set_termios(struct uart_port *the_port,
- struct termios *termios, struct termios *old_termios)
+ struct ktermios *termios, struct ktermios *old_termios)
{
unsigned long port_flags;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index dca6c1bde8f..0746c9446ae 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -840,8 +840,8 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
/* The port lock is not held. */
static void
-ip22zilog_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
unsigned long flags;
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index f8262e6ad8d..7cf1c60027f 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -142,7 +142,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch)
{
unsigned long lock_flags;
struct jsm_channel *channel = (struct jsm_channel *)port;
- struct termios *termios;
+ struct ktermios *termios;
spin_lock_irqsave(&port->lock, lock_flags);
termios = port->info->tty->termios;
@@ -180,7 +180,7 @@ static int jsm_tty_open(struct uart_port *port)
struct jsm_board *brd;
int rc = 0;
struct jsm_channel *channel = (struct jsm_channel *)port;
- struct termios *termios;
+ struct ktermios *termios;
/* Get board pointer from our array of majors we have allocated */
brd = channel->ch_bd;
@@ -269,7 +269,7 @@ static int jsm_tty_open(struct uart_port *port)
static void jsm_tty_close(struct uart_port *port)
{
struct jsm_board *bd;
- struct termios *ts;
+ struct ktermios *ts;
struct jsm_channel *channel = (struct jsm_channel *)port;
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
@@ -302,8 +302,8 @@ static void jsm_tty_close(struct uart_port *port)
}
static void jsm_tty_set_termios(struct uart_port *port,
- struct termios *termios,
- struct termios *old_termios)
+ struct ktermios *termios,
+ struct ktermios *old_termios)
{
unsigned long lock_flags;
struct jsm_channel *channel = (struct jsm_channel *)port;
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 7656a35f5e2..6e09c8b395e 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -699,7 +699,7 @@ static unsigned int m32r_sio_get_divisor(struct uart_port *port,
}
static void m32r_sio_set_termios(struct uart_port *port,
- struct termios *termios, struct termios *old)
+ struct ktermios *termios, struct ktermios *old)
{
struct uart_sio_port *up = (struct uart_sio_port *)port;
unsigned char cval = 0;
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 3db206d29b3..08430961a89 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -1132,7 +1132,7 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
return 0;
}
-static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 6dd579ed977..3c4b6c24371 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -270,8 +270,8 @@ mpc52xx_uart_shutdown(struct uart_port *port)
}
static void
-mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new,
- struct termios *old)
+mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
+ struct ktermios *old)
{
struct mpc52xx_psc __iomem *psc = PSC(port);
unsigned long flags;
@@ -789,7 +789,9 @@ static struct console mpc52xx_console = {
static int __init
mpc52xx_console_init(void)
{
+#if defined(CONFIG_PPC_MERGE)
mpc52xx_uart_of_enumerate();
+#endif
register_console(&mpc52xx_console);
return 0;
}
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 29823bd60fb..3d2fcc57b1c 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -1440,8 +1440,8 @@ mpsc_shutdown(struct uart_port *port)
}
static void
-mpsc_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+mpsc_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
u32 baud;
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index ea9cbda7796..83211013deb 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -307,8 +307,8 @@ static void mux_shutdown(struct uart_port *port)
* The Serial Mux does not support this function.
*/
static void
-mux_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+mux_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
}
diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c
index 062bad457b1..b56f7db4503 100644
--- a/drivers/serial/netx-serial.c
+++ b/drivers/serial/netx-serial.c
@@ -337,8 +337,8 @@ static void netx_shutdown(struct uart_port *port)
}
static void
-netx_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+netx_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int baud, quot;
unsigned char old_cr;
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index bf9809ed9c0..752ef07516b 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -1262,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud)
}
-static void __pmz_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_pmac_port *uap = to_pmz(port);
unsigned long baud;
@@ -1273,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios,
if (ZS_IS_ASLEEP(uap))
return;
- memcpy(&uap->termios_cache, termios, sizeof(struct termios));
+ memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
/* XXX Check which revs of machines actually allow 1 and 4Mb speeds
* on the IR dongle. Note that the IRTTY driver currently doesn't know
@@ -1313,8 +1313,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios,
}
/* The port lock is not held. */
-static void pmz_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+static void pmz_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_pmac_port *uap = to_pmz(port);
unsigned long flags;
diff --git a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h
index c03f9bfacdd..570b0d925e8 100644
--- a/drivers/serial/pmac_zilog.h
+++ b/drivers/serial/pmac_zilog.h
@@ -60,7 +60,7 @@ struct uart_pmac_port {
volatile struct dbdma_regs __iomem *tx_dma_regs;
volatile struct dbdma_regs __iomem *rx_dma_regs;
- struct termios termios_cache;
+ struct ktermios termios_cache;
};
#define to_pmz(p) ((struct uart_pmac_port *)(p))
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 415fe9633a9..d403aaa5509 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -433,8 +433,8 @@ static void serial_pxa_shutdown(struct uart_port *port)
}
static void
-serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
unsigned char cval, fcr = 0;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 8dfc2dd058c..3ba9208ebd0 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -738,8 +738,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
}
static void s3c24xx_serial_set_termios(struct uart_port *port,
- struct termios *termios,
- struct termios *old)
+ struct ktermios *termios,
+ struct ktermios *old)
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index d4065266b6f..58a83c27e14 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -408,8 +408,8 @@ static void sa1100_shutdown(struct uart_port *port)
}
static void
-sa1100_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+sa1100_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct sa1100_port *sport = (struct sa1100_port *)port;
unsigned long flags;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index c67b05e9a45..f84982e508c 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key;
#define uart_console(port) (0)
#endif
-static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
+static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios);
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
static void uart_change_pm(struct uart_state *state, int pm_state);
@@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout);
* we're actually going to be using.
*/
unsigned int
-uart_get_baud_rate(struct uart_port *port, struct termios *termios,
- struct termios *old, unsigned int min, unsigned int max)
+uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old, unsigned int min, unsigned int max)
{
unsigned int try, baud, altbaud = 38400;
upf_t flags = port->flags & UPF_SPD_MASK;
@@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
EXPORT_SYMBOL(uart_get_divisor);
static void
-uart_change_speed(struct uart_state *state, struct termios *old_termios)
+uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
{
struct tty_struct *tty = state->info->tty;
struct uart_port *port = state->port;
- struct termios *termios;
+ struct ktermios *termios;
/*
* If we have no tty, termios, or the port does not exist,
@@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
return ret;
}
-static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct uart_state *state = tty->driver_data;
unsigned long flags;
@@ -1866,7 +1866,7 @@ int __init
uart_set_options(struct uart_port *port, struct console *co,
int baud, int parity, int bits, int flow)
{
- struct termios termios;
+ struct ktermios termios;
int i;
/*
@@ -1876,7 +1876,7 @@ uart_set_options(struct uart_port *port, struct console *co,
spin_lock_init(&port->lock);
lockdep_set_class(&port->lock, &port_lock_key);
- memset(&termios, 0, sizeof(struct termios));
+ memset(&termios, 0, sizeof(struct ktermios));
termios.c_cflag = CREAD | HUPCL | CLOCAL;
@@ -1991,12 +1991,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
* Re-enable the console device after suspending.
*/
if (uart_console(port)) {
- struct termios termios;
+ struct ktermios termios;
/*
* First try to use the console cflag setting.
*/
- memset(&termios, 0, sizeof(struct termios));
+ memset(&termios, 0, sizeof(struct ktermios));
termios.c_cflag = port->cons->cflag;
/*
@@ -2189,6 +2189,7 @@ int uart_register_driver(struct uart_driver *drv)
normal->subtype = SERIAL_TYPE_NORMAL;
normal->init_termios = tty_std_termios;
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
normal->driver_state = drv;
tty_set_operations(normal, &uart_ops);
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 5e1ac356bbb..eb18d429752 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -348,8 +348,8 @@ static void lh7a40xuart_shutdown (struct uart_port* port)
}
static void lh7a40xuart_set_termios (struct uart_port* port,
- struct termios* termios,
- struct termios* old)
+ struct ktermios* termios,
+ struct ktermios* old)
{
unsigned int con;
unsigned int inten;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 2a48289ac72..7186a82c475 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -556,8 +556,8 @@ static void serial_txx9_shutdown(struct uart_port *port)
}
static void
-serial_txx9_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_txx9_port *up = (struct uart_txx9_port *)port;
unsigned int cval, fcr = 0;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 3b5f19ec212..c53b69610a5 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -319,6 +319,28 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
sci_out(port, SCFCR, fcr_val);
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+{
+ unsigned int fcr_val = 0;
+
+ if (cflag & CRTSCTS) {
+ fcr_val |= SCFCR_MCE;
+
+ ctrl_outw(0x0000, PORT_PSCR);
+ } else {
+ unsigned short data;
+
+ data = ctrl_inw(PORT_PSCR);
+ data &= 0x033f;
+ data |= 0x0400;
+ ctrl_outw(data, PORT_PSCR);
+
+ ctrl_outw(ctrl_inw(SCSPTR0) & 0x17, SCSPTR0);
+ }
+
+ sci_out(port, SCFCR, fcr_val);
+}
#else
/* For SH7750 */
static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
@@ -943,8 +965,8 @@ static void sci_shutdown(struct uart_port *port)
s->disable(port);
}
-static void sci_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct sci_port *s = &sci_ports[port->line];
unsigned int status, baud, smr_val;
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index e4557cc4f74..77f7d6351ab 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -90,6 +90,13 @@
# define SCSPTR3 0xffe30010 /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */
# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */
+# define SCSPTR0 SCPDR0
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
+# define PORT_PSCR 0xA405011E
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -495,6 +502,7 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xfe620000)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+ return 1;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
static inline int sci_rxd_in(struct uart_port *port)
@@ -521,6 +529,13 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
return 1;
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xffe00000)
+ return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
+ return 1;
+}
#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
static inline int sci_rxd_in(struct uart_port *port)
{
@@ -550,6 +565,7 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xff925000)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+ return 1;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
static inline int sci_rxd_in(struct uart_port *port)
@@ -558,6 +574,7 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xffe10000)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+ return 1;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
static inline int sci_rxd_in(struct uart_port *port)
@@ -570,6 +587,7 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xfffe9800)
return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+ return 1;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
static inline int sci_rxd_in(struct uart_port *port)
@@ -580,6 +598,7 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
if (port->mapbase == 0xf8420000)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+ return 1;
}
#endif
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 956b2cf08e1..253ceb895ca 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -361,8 +361,8 @@ static int snp_startup(struct uart_port *port)
*
*/
static void
-snp_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+snp_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
}
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 03941d27d15..40d48566215 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -281,8 +281,8 @@ static void sunhv_shutdown(struct uart_port *port)
}
/* port->lock is not held. */
-static void sunhv_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
unsigned int quot = uart_get_divisor(port, baud);
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 08a7cd6a3a0..145d6236954 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -786,8 +786,8 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
}
/* port->lock is not held. */
-static void sunsab_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
unsigned long flags;
@@ -1037,7 +1037,8 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
err = request_irq(up->port.irq, sunsab_interrupt,
IRQF_SHARED, "sab", up);
if (err) {
- of_iounmap(up->port.membase,
+ of_iounmap(&op->resource[0],
+ up->port.membase,
sizeof(union sab82532_async_regs));
return err;
}
@@ -1064,7 +1065,8 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
sizeof(union sab82532_async_regs),
(inst * 2) + 1);
if (err) {
- of_iounmap(up[0].port.membase,
+ of_iounmap(&op->resource[0],
+ up[0].port.membase,
sizeof(union sab82532_async_regs));
free_irq(up[0].port.irq, &up[0]);
return err;
@@ -1082,10 +1084,13 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
static void __devexit sab_remove_one(struct uart_sunsab_port *up)
{
+ struct of_device *op = to_of_device(up->port.dev);
+
uart_remove_one_port(&sunsab_reg, &up->port);
if (!(up->port.line & 1))
free_irq(up->port.irq, up);
- of_iounmap(up->port.membase,
+ of_iounmap(&op->resource[0],
+ up->port.membase,
sizeof(union sab82532_async_regs));
}
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index c577faea60e..3ec3df21816 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -893,8 +893,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag,
}
static void
-sunsu_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+sunsu_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int baud, quot;
@@ -1480,13 +1480,13 @@ static int __devinit su_probe(struct of_device *op, const struct of_device_id *m
return 0;
out_unmap:
- of_iounmap(up->port.membase, up->reg_size);
+ of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
return err;
}
-static int __devexit su_remove(struct of_device *dev)
+static int __devexit su_remove(struct of_device *op)
{
- struct uart_sunsu_port *up = dev_get_drvdata(&dev->dev);;
+ struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
if (up->su_type == SU_PORT_MS ||
up->su_type == SU_PORT_KBD) {
@@ -1499,9 +1499,9 @@ static int __devexit su_remove(struct of_device *dev)
}
if (up->port.membase)
- of_iounmap(up->port.membase, up->reg_size);
+ of_iounmap(&op->resource[0], up->port.membase, up->reg_size);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index b2cc703b2b9..244f796dc62 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -922,8 +922,8 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
/* The port lock is not held. */
static void
-sunzilog_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
unsigned long flags;
@@ -1379,13 +1379,15 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
if (!keyboard_mouse) {
err = uart_add_one_port(&sunzilog_reg, &up[0].port);
if (err) {
- of_iounmap(rp, sizeof(struct zilog_layout));
+ of_iounmap(&op->resource[0],
+ rp, sizeof(struct zilog_layout));
return err;
}
err = uart_add_one_port(&sunzilog_reg, &up[1].port);
if (err) {
uart_remove_one_port(&sunzilog_reg, &up[0].port);
- of_iounmap(rp, sizeof(struct zilog_layout));
+ of_iounmap(&op->resource[0],
+ rp, sizeof(struct zilog_layout));
return err;
}
} else {
@@ -1414,18 +1416,18 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
uart_remove_one_port(&sunzilog_reg, &up->port);
}
-static int __devexit zs_remove(struct of_device *dev)
+static int __devexit zs_remove(struct of_device *op)
{
- struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
+ struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev);
struct zilog_layout __iomem *regs;
zs_remove_one(&up[0]);
zs_remove_one(&up[1]);
regs = sunzilog_chip_regs[up[0].port.line / 2];
- of_iounmap(regs, sizeof(struct zilog_layout));
+ of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout));
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index 83690653b78..db8607e3d53 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -214,8 +214,8 @@ static void ulite_shutdown(struct uart_port *port)
free_irq(port->irq, port);
}
-static void ulite_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
+static void ulite_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned long flags;
unsigned int baud;
@@ -278,8 +278,8 @@ static int ulite_request_port(struct uart_port *port)
static void ulite_config_port(struct uart_port *port, int flags)
{
- ulite_request_port(port);
- port->type = PORT_UARTLITE;
+ if (!ulite_request_port(port))
+ port->type = PORT_UARTLITE;
}
static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index 28f3bbff87b..dd98aca6ed0 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -404,8 +404,8 @@ static void v850e_uart_shutdown (struct uart_port *port)
}
static void
-v850e_uart_set_termios (struct uart_port *port, struct termios *termios,
- struct termios *old)
+v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
{
unsigned cflags = termios->c_cflag;
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index fd51f8182de..cf0e663b42e 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -562,8 +562,8 @@ static void siu_shutdown(struct uart_port *port)
free_irq(port->irq, port);
}
-static void siu_set_termios(struct uart_port *port, struct termios *new,
- struct termios *old)
+static void siu_set_termios(struct uart_port *port, struct ktermios *new,
+ struct ktermios *old)
{
tcflag_t c_cflag, c_iflag;
uint8_t lcr, fcr, ier;
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 494d9b85648..8b41f9cc256 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -49,6 +49,14 @@ MODULE_LICENSE("GPL");
#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
+/* for testing SSCR1 changes that require SSP restart, basically
+ * everything except the service and interrupt enables */
+#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \
+ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
+ | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \
+ | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \
+ | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
+
#define DEFINE_SSP_REG(reg, off) \
static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); }
@@ -123,8 +131,8 @@ struct driver_data {
u8 n_bytes;
u32 dma_width;
int cs_change;
- void (*write)(struct driver_data *drv_data);
- void (*read)(struct driver_data *drv_data);
+ int (*write)(struct driver_data *drv_data);
+ int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
};
@@ -132,7 +140,6 @@ struct driver_data {
struct chip_data {
u32 cr0;
u32 cr1;
- u32 to;
u32 psp;
u32 timeout;
u8 n_bytes;
@@ -143,8 +150,8 @@ struct chip_data {
u8 enable_dma;
u8 bits_per_word;
u32 speed_hz;
- void (*write)(struct driver_data *drv_data);
- void (*read)(struct driver_data *drv_data);
+ int (*write)(struct driver_data *drv_data);
+ int (*read)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
};
@@ -166,114 +173,118 @@ static int flush(struct driver_data *drv_data)
return limit;
}
-static void restore_state(struct driver_data *drv_data)
-{
- void *reg = drv_data->ioaddr;
-
- /* Clear status and disable clock */
- write_SSSR(drv_data->clear_sr, reg);
- write_SSCR0(drv_data->cur_chip->cr0 & ~SSCR0_SSE, reg);
-
- /* Load the registers */
- write_SSCR1(drv_data->cur_chip->cr1, reg);
- write_SSCR0(drv_data->cur_chip->cr0, reg);
- if (drv_data->ssp_type != PXA25x_SSP) {
- write_SSTO(0, reg);
- write_SSPSP(drv_data->cur_chip->psp, reg);
- }
-}
-
static void null_cs_control(u32 command)
{
}
-static void null_writer(struct driver_data *drv_data)
+static int null_writer(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
u8 n_bytes = drv_data->n_bytes;
- while ((read_SSSR(reg) & SSSR_TNF)
- && (drv_data->tx < drv_data->tx_end)) {
- write_SSDR(0, reg);
- drv_data->tx += n_bytes;
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+ write_SSDR(0, reg);
+ drv_data->tx += n_bytes;
+
+ return 1;
}
-static void null_reader(struct driver_data *drv_data)
+static int null_reader(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
u8 n_bytes = drv_data->n_bytes;
while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ && (drv_data->rx < drv_data->rx_end)) {
read_SSDR(reg);
drv_data->rx += n_bytes;
}
+
+ return drv_data->rx == drv_data->rx_end;
}
-static void u8_writer(struct driver_data *drv_data)
+static int u8_writer(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
- while ((read_SSSR(reg) & SSSR_TNF)
- && (drv_data->tx < drv_data->tx_end)) {
- write_SSDR(*(u8 *)(drv_data->tx), reg);
- ++drv_data->tx;
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+ write_SSDR(*(u8 *)(drv_data->tx), reg);
+ ++drv_data->tx;
+
+ return 1;
}
-static void u8_reader(struct driver_data *drv_data)
+static int u8_reader(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ && (drv_data->rx < drv_data->rx_end)) {
*(u8 *)(drv_data->rx) = read_SSDR(reg);
++drv_data->rx;
}
+
+ return drv_data->rx == drv_data->rx_end;
}
-static void u16_writer(struct driver_data *drv_data)
+static int u16_writer(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
- while ((read_SSSR(reg) & SSSR_TNF)
- && (drv_data->tx < drv_data->tx_end)) {
- write_SSDR(*(u16 *)(drv_data->tx), reg);
- drv_data->tx += 2;
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+ write_SSDR(*(u16 *)(drv_data->tx), reg);
+ drv_data->tx += 2;
+
+ return 1;
}
-static void u16_reader(struct driver_data *drv_data)
+static int u16_reader(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ && (drv_data->rx < drv_data->rx_end)) {
*(u16 *)(drv_data->rx) = read_SSDR(reg);
drv_data->rx += 2;
}
+
+ return drv_data->rx == drv_data->rx_end;
}
-static void u32_writer(struct driver_data *drv_data)
+
+static int u32_writer(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
- while ((read_SSSR(reg) & SSSR_TNF)
- && (drv_data->tx < drv_data->tx_end)) {
- write_SSDR(*(u32 *)(drv_data->tx), reg);
- drv_data->tx += 4;
- }
+ if (((read_SSSR(reg) & 0x00000f00) == 0x00000f00)
+ || (drv_data->tx == drv_data->tx_end))
+ return 0;
+
+ write_SSDR(*(u32 *)(drv_data->tx), reg);
+ drv_data->tx += 4;
+
+ return 1;
}
-static void u32_reader(struct driver_data *drv_data)
+static int u32_reader(struct driver_data *drv_data)
{
void *reg = drv_data->ioaddr;
while ((read_SSSR(reg) & SSSR_RNE)
- && (drv_data->rx < drv_data->rx_end)) {
+ && (drv_data->rx < drv_data->rx_end)) {
*(u32 *)(drv_data->rx) = read_SSDR(reg);
drv_data->rx += 4;
}
+
+ return drv_data->rx == drv_data->rx_end;
}
static void *next_transfer(struct driver_data *drv_data)
@@ -409,166 +420,134 @@ static int wait_dma_channel_stop(int channel)
return limit;
}
-static void dma_handler(int channel, void *data)
+void dma_error_stop(struct driver_data *drv_data, const char *msg)
{
- struct driver_data *drv_data = data;
- struct spi_message *msg = drv_data->cur_msg;
void *reg = drv_data->ioaddr;
- u32 irq_status = DCSR(channel) & DMA_INT_MASK;
- u32 trailing_sssr = 0;
- if (irq_status & DCSR_BUSERR) {
+ /* Stop and reset */
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ write_SSSR(drv_data->clear_sr, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ flush(drv_data);
+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- /* Disable interrupts, clear status and reset DMA */
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
- if (drv_data->ssp_type != PXA25x_SSP)
- write_SSTO(0, reg);
- write_SSSR(drv_data->clear_sr, reg);
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ unmap_dma_buffers(drv_data);
- if (flush(drv_data) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_handler: flush fail\n");
+ dev_err(&drv_data->pdev->dev, "%s\n", msg);
- unmap_dma_buffers(drv_data);
+ drv_data->cur_msg->state = ERROR_STATE;
+ tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_transfer_complete(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
+ struct spi_message *msg = drv_data->cur_msg;
+
+ /* Clear and disable interrupts on SSP and DMA channels*/
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ write_SSSR(drv_data->clear_sr, reg);
+ DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
+ DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
+
+ if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_handler: dma rx channel stop failed\n");
+
+ if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "dma_transfer: ssp rx stall failed\n");
+
+ unmap_dma_buffers(drv_data);
+
+ /* update the buffer pointer for the amount completed in dma */
+ drv_data->rx += drv_data->len -
+ (DCMD(drv_data->rx_channel) & DCMD_LENGTH);
+
+ /* read trailing data from fifo, it does not matter how many
+ * bytes are in the fifo just read until buffer is full
+ * or fifo is empty, which ever occurs first */
+ drv_data->read(drv_data);
+
+ /* return count of what was actually read */
+ msg->actual_length += drv_data->len -
+ (drv_data->rx_end - drv_data->rx);
+
+ /* Release chip select if requested, transfer delays are
+ * handled in pump_transfers */
+ if (drv_data->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
+
+ /* Move to next transfer */
+ msg->state = next_transfer(drv_data);
+
+ /* Schedule transfer tasklet */
+ tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_handler(int channel, void *data)
+{
+ struct driver_data *drv_data = data;
+ u32 irq_status = DCSR(channel) & DMA_INT_MASK;
+
+ if (irq_status & DCSR_BUSERR) {
if (channel == drv_data->tx_channel)
- dev_err(&drv_data->pdev->dev,
- "dma_handler: bad bus address on "
- "tx channel %d, source %x target = %x\n",
- channel, DSADR(channel), DTADR(channel));
+ dma_error_stop(drv_data,
+ "dma_handler: "
+ "bad bus address on tx channel");
else
- dev_err(&drv_data->pdev->dev,
- "dma_handler: bad bus address on "
- "rx channel %d, source %x target = %x\n",
- channel, DSADR(channel), DTADR(channel));
-
- msg->state = ERROR_STATE;
- tasklet_schedule(&drv_data->pump_transfers);
+ dma_error_stop(drv_data,
+ "dma_handler: "
+ "bad bus address on rx channel");
+ return;
}
/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
- if ((drv_data->ssp_type == PXA25x_SSP)
- && (channel == drv_data->tx_channel)
- && (irq_status & DCSR_ENDINTR)) {
+ if ((channel == drv_data->tx_channel)
+ && (irq_status & DCSR_ENDINTR)
+ && (drv_data->ssp_type == PXA25x_SSP)) {
/* Wait for rx to stall */
if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
dev_err(&drv_data->pdev->dev,
"dma_handler: ssp rx stall failed\n");
- /* Clear and disable interrupts on SSP and DMA channels*/
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
- write_SSSR(drv_data->clear_sr, reg);
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
- if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_handler: dma rx channel stop failed\n");
-
- unmap_dma_buffers(drv_data);
-
- /* Read trailing bytes */
- /* Calculate number of trailing bytes, read them */
- trailing_sssr = read_SSSR(reg);
- if ((trailing_sssr & 0xf008) != 0xf000) {
- drv_data->rx = drv_data->rx_end -
- (((trailing_sssr >> 12) & 0x0f) + 1);
- drv_data->read(drv_data);
- }
- msg->actual_length += drv_data->len;
-
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
-
- /* Move to next transfer */
- msg->state = next_transfer(drv_data);
-
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
+ /* finish this transfer, start the next */
+ dma_transfer_complete(drv_data);
}
}
static irqreturn_t dma_transfer(struct driver_data *drv_data)
{
u32 irq_status;
- u32 trailing_sssr = 0;
- struct spi_message *msg = drv_data->cur_msg;
void *reg = drv_data->ioaddr;
irq_status = read_SSSR(reg) & drv_data->mask_sr;
if (irq_status & SSSR_ROR) {
- /* Clear and disable interrupts on SSP and DMA channels*/
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
- if (drv_data->ssp_type != PXA25x_SSP)
- write_SSTO(0, reg);
- write_SSSR(drv_data->clear_sr, reg);
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
- unmap_dma_buffers(drv_data);
-
- if (flush(drv_data) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_transfer: flush fail\n");
-
- dev_warn(&drv_data->pdev->dev, "dma_transfer: fifo overun\n");
-
- drv_data->cur_msg->state = ERROR_STATE;
- tasklet_schedule(&drv_data->pump_transfers);
-
+ dma_error_stop(drv_data, "dma_transfer: fifo overrun");
return IRQ_HANDLED;
}
/* Check for false positive timeout */
- if ((irq_status & SSSR_TINT) && DCSR(drv_data->tx_channel) & DCSR_RUN) {
+ if ((irq_status & SSSR_TINT)
+ && (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
write_SSSR(SSSR_TINT, reg);
return IRQ_HANDLED;
}
if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
- /* Clear and disable interrupts on SSP and DMA channels*/
- write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
+ /* Clear and disable timeout interrupt, do the rest in
+ * dma_transfer_complete */
if (drv_data->ssp_type != PXA25x_SSP)
write_SSTO(0, reg);
- write_SSSR(drv_data->clear_sr, reg);
- DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
- DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
- if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_transfer: dma rx channel stop failed\n");
-
- if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
- dev_err(&drv_data->pdev->dev,
- "dma_transfer: ssp rx stall failed\n");
-
- unmap_dma_buffers(drv_data);
-
- /* Calculate number of trailing bytes, read them */
- trailing_sssr = read_SSSR(reg);
- if ((trailing_sssr & 0xf008) != 0xf000) {
- drv_data->rx = drv_data->rx_end -
- (((trailing_sssr >> 12) & 0x0f) + 1);
- drv_data->read(drv_data);
- }
- msg->actual_length += drv_data->len;
-
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
-
- /* Move to next transfer */
- msg->state = next_transfer(drv_data);
-
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
+ /* finish this transfer, start the next */
+ dma_transfer_complete(drv_data);
return IRQ_HANDLED;
}
@@ -577,89 +556,103 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data)
return IRQ_NONE;
}
-static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+static void int_error_stop(struct driver_data *drv_data, const char* msg)
{
- struct spi_message *msg = drv_data->cur_msg;
void *reg = drv_data->ioaddr;
- unsigned long limit = loops_per_jiffy << 1;
- u32 irq_status;
- u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
- drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
-
- while ((irq_status = read_SSSR(reg) & irq_mask)) {
-
- if (irq_status & SSSR_ROR) {
- /* Clear and disable interrupts */
- write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
- if (drv_data->ssp_type != PXA25x_SSP)
- write_SSTO(0, reg);
- write_SSSR(drv_data->clear_sr, reg);
+ /* Stop and reset SSP */
+ write_SSSR(drv_data->clear_sr, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
+ flush(drv_data);
+ write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
- if (flush(drv_data) == 0)
- dev_err(&drv_data->pdev->dev,
- "interrupt_transfer: flush fail\n");
+ dev_err(&drv_data->pdev->dev, "%s\n", msg);
- /* Stop the SSP */
+ drv_data->cur_msg->state = ERROR_STATE;
+ tasklet_schedule(&drv_data->pump_transfers);
+}
- dev_warn(&drv_data->pdev->dev,
- "interrupt_transfer: fifo overun\n");
+static void int_transfer_complete(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
- msg->state = ERROR_STATE;
- tasklet_schedule(&drv_data->pump_transfers);
+ /* Stop SSP */
+ write_SSSR(drv_data->clear_sr, reg);
+ write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(0, reg);
- return IRQ_HANDLED;
- }
+ /* Update total byte transfered return count actual bytes read */
+ drv_data->cur_msg->actual_length += drv_data->len -
+ (drv_data->rx_end - drv_data->rx);
- /* Look for false positive timeout */
- if ((irq_status & SSSR_TINT)
- && (drv_data->rx < drv_data->rx_end))
- write_SSSR(SSSR_TINT, reg);
+ /* Release chip select if requested, transfer delays are
+ * handled in pump_transfers */
+ if (drv_data->cs_change)
+ drv_data->cs_control(PXA2XX_CS_DEASSERT);
- /* Pump data */
- drv_data->read(drv_data);
- drv_data->write(drv_data);
+ /* Move to next transfer */
+ drv_data->cur_msg->state = next_transfer(drv_data);
- if (drv_data->tx == drv_data->tx_end) {
- /* Disable tx interrupt */
- write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
- irq_mask = drv_data->mask_sr & ~SSSR_TFS;
+ /* Schedule transfer tasklet */
+ tasklet_schedule(&drv_data->pump_transfers);
+}
- /* PXA25x_SSP has no timeout, read trailing bytes */
- if (drv_data->ssp_type == PXA25x_SSP) {
- while ((read_SSSR(reg) & SSSR_BSY) && limit--)
- drv_data->read(drv_data);
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+ void *reg = drv_data->ioaddr;
- if (limit == 0)
- dev_err(&drv_data->pdev->dev,
- "interrupt_transfer: "
- "trailing byte read failed\n");
- }
- }
+ u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ?
+ drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS;
- if ((irq_status & SSSR_TINT)
- || (drv_data->rx == drv_data->rx_end)) {
+ u32 irq_status = read_SSSR(reg) & irq_mask;
- /* Clear timeout */
- write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
- if (drv_data->ssp_type != PXA25x_SSP)
- write_SSTO(0, reg);
- write_SSSR(drv_data->clear_sr, reg);
+ if (irq_status & SSSR_ROR) {
+ int_error_stop(drv_data, "interrupt_transfer: fifo overrun");
+ return IRQ_HANDLED;
+ }
- /* Update total byte transfered */
- msg->actual_length += drv_data->len;
+ if (irq_status & SSSR_TINT) {
+ write_SSSR(SSSR_TINT, reg);
+ if (drv_data->read(drv_data)) {
+ int_transfer_complete(drv_data);
+ return IRQ_HANDLED;
+ }
+ }
- /* Release chip select if requested, transfer delays are
- * handled in pump_transfers */
- if (drv_data->cs_change)
- drv_data->cs_control(PXA2XX_CS_DEASSERT);
+ /* Drain rx fifo, Fill tx fifo and prevent overruns */
+ do {
+ if (drv_data->read(drv_data)) {
+ int_transfer_complete(drv_data);
+ return IRQ_HANDLED;
+ }
+ } while (drv_data->write(drv_data));
- /* Move to next transfer */
- msg->state = next_transfer(drv_data);
+ if (drv_data->read(drv_data)) {
+ int_transfer_complete(drv_data);
+ return IRQ_HANDLED;
+ }
- /* Schedule transfer tasklet */
- tasklet_schedule(&drv_data->pump_transfers);
+ if (drv_data->tx == drv_data->tx_end) {
+ write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg);
+ /* PXA25x_SSP has no timeout, read trailing bytes */
+ if (drv_data->ssp_type == PXA25x_SSP) {
+ if (!wait_ssp_rx_stall(reg))
+ {
+ int_error_stop(drv_data, "interrupt_transfer: "
+ "rx stall failed");
+ return IRQ_HANDLED;
+ }
+ if (!drv_data->read(drv_data))
+ {
+ int_error_stop(drv_data,
+ "interrupt_transfer: "
+ "trailing byte read failed");
+ return IRQ_HANDLED;
+ }
+ int_transfer_complete(drv_data);
}
}
@@ -681,7 +674,7 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
write_SSSR(drv_data->clear_sr, reg);
dev_err(&drv_data->pdev->dev, "bad message state "
- "in interrupt handler");
+ "in interrupt handler\n");
/* Never fail */
return IRQ_HANDLED;
@@ -690,6 +683,102 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
return drv_data->transfer_handler(drv_data);
}
+int set_dma_burst_and_threshold(struct chip_data *chip, struct spi_device *spi,
+ u8 bits_per_word, u32 *burst_code,
+ u32 *threshold)
+{
+ struct pxa2xx_spi_chip *chip_info =
+ (struct pxa2xx_spi_chip *)spi->controller_data;
+ int bytes_per_word;
+ int burst_bytes;
+ int thresh_words;
+ int req_burst_size;
+ int retval = 0;
+
+ /* Set the threshold (in registers) to equal the same amount of data
+ * as represented by burst size (in bytes). The computation below
+ * is (burst_size rounded up to nearest 8 byte, word or long word)
+ * divided by (bytes/register); the tx threshold is the inverse of
+ * the rx, so that there will always be enough data in the rx fifo
+ * to satisfy a burst, and there will always be enough space in the
+ * tx fifo to accept a burst (a tx burst will overwrite the fifo if
+ * there is not enough space), there must always remain enough empty
+ * space in the rx fifo for any data loaded to the tx fifo.
+ * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
+ * will be 8, or half the fifo;
+ * The threshold can only be set to 2, 4 or 8, but not 16, because
+ * to burst 16 to the tx fifo, the fifo would have to be empty;
+ * however, the minimum fifo trigger level is 1, and the tx will
+ * request service when the fifo is at this level, with only 15 spaces.
+ */
+
+ /* find bytes/word */
+ if (bits_per_word <= 8)
+ bytes_per_word = 1;
+ else if (bits_per_word <= 16)
+ bytes_per_word = 2;
+ else
+ bytes_per_word = 4;
+
+ /* use struct pxa2xx_spi_chip->dma_burst_size if available */
+ if (chip_info)
+ req_burst_size = chip_info->dma_burst_size;
+ else {
+ switch (chip->dma_burst_size) {
+ default:
+ /* if the default burst size is not set,
+ * do it now */
+ chip->dma_burst_size = DCMD_BURST8;
+ case DCMD_BURST8:
+ req_burst_size = 8;
+ break;
+ case DCMD_BURST16:
+ req_burst_size = 16;
+ break;
+ case DCMD_BURST32:
+ req_burst_size = 32;
+ break;
+ }
+ }
+ if (req_burst_size <= 8) {
+ *burst_code = DCMD_BURST8;
+ burst_bytes = 8;
+ } else if (req_burst_size <= 16) {
+ if (bytes_per_word == 1) {
+ /* don't burst more than 1/2 the fifo */
+ *burst_code = DCMD_BURST8;
+ burst_bytes = 8;
+ retval = 1;
+ } else {
+ *burst_code = DCMD_BURST16;
+ burst_bytes = 16;
+ }
+ } else {
+ if (bytes_per_word == 1) {
+ /* don't burst more than 1/2 the fifo */
+ *burst_code = DCMD_BURST8;
+ burst_bytes = 8;
+ retval = 1;
+ } else if (bytes_per_word == 2) {
+ /* don't burst more than 1/2 the fifo */
+ *burst_code = DCMD_BURST16;
+ burst_bytes = 16;
+ retval = 1;
+ } else {
+ *burst_code = DCMD_BURST32;
+ burst_bytes = 32;
+ }
+ }
+
+ thresh_words = burst_bytes / bytes_per_word;
+
+ /* thresh_words will be between 2 and 8 */
+ *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
+ | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
+
+ return retval;
+}
+
static void pump_transfers(unsigned long data)
{
struct driver_data *drv_data = (struct driver_data *)data;
@@ -702,6 +791,9 @@ static void pump_transfers(unsigned long data)
u8 bits = 0;
u32 speed = 0;
u32 cr0;
+ u32 cr1;
+ u32 dma_thresh = drv_data->cur_chip->dma_threshold;
+ u32 dma_burst = drv_data->cur_chip->dma_burst_size;
/* Get current state information */
message = drv_data->cur_msg;
@@ -731,6 +823,16 @@ static void pump_transfers(unsigned long data)
udelay(previous->delay_usecs);
}
+ /* Check transfer length */
+ if (transfer->len > 8191)
+ {
+ dev_warn(&drv_data->pdev->dev, "pump_transfers: transfer "
+ "length greater than 8191\n");
+ message->status = -EINVAL;
+ giveback(drv_data);
+ return;
+ }
+
/* Setup the transfer state based on the type of transfer */
if (flush(drv_data) == 0) {
dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
@@ -747,17 +849,15 @@ static void pump_transfers(unsigned long data)
drv_data->rx_end = drv_data->rx + transfer->len;
drv_data->rx_dma = transfer->rx_dma;
drv_data->tx_dma = transfer->tx_dma;
- drv_data->len = transfer->len;
+ drv_data->len = transfer->len & DCMD_LENGTH;
drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader;
drv_data->cs_change = transfer->cs_change;
/* Change speed and bit per word on a per transfer */
+ cr0 = chip->cr0;
if (transfer->speed_hz || transfer->bits_per_word) {
- /* Disable clock */
- write_SSCR0(chip->cr0 & ~SSCR0_SSE, reg);
- cr0 = chip->cr0;
bits = chip->bits_per_word;
speed = chip->speed_hz;
@@ -796,15 +896,24 @@ static void pump_transfers(unsigned long data)
drv_data->write = drv_data->write != null_writer ?
u32_writer : null_writer;
}
+ /* if bits/word is changed in dma mode, then must check the
+ * thresholds and burst also */
+ if (chip->enable_dma) {
+ if (set_dma_burst_and_threshold(chip, message->spi,
+ bits, &dma_burst,
+ &dma_thresh))
+ if (printk_ratelimit())
+ dev_warn(&message->spi->dev,
+ "pump_transfer: "
+ "DMA burst size reduced to "
+ "match bits_per_word\n");
+ }
cr0 = clk_div
| SSCR0_Motorola
| SSCR0_DataSize(bits > 16 ? bits - 16 : bits)
| SSCR0_SSE
| (bits > 16 ? SSCR0_EDSS : 0);
-
- /* Start it back up */
- write_SSCR0(cr0, reg);
}
message->state = RUNNING_STATE;
@@ -823,13 +932,13 @@ static void pump_transfers(unsigned long data)
/* No target address increment */
DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
| drv_data->dma_width
- | chip->dma_burst_size
+ | dma_burst
| drv_data->len;
else
DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
| DCMD_FLOWSRC
| drv_data->dma_width
- | chip->dma_burst_size
+ | dma_burst
| drv_data->len;
/* Setup tx DMA Channel */
@@ -840,13 +949,13 @@ static void pump_transfers(unsigned long data)
/* No source address increment */
DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
| drv_data->dma_width
- | chip->dma_burst_size
+ | dma_burst
| drv_data->len;
else
DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
| DCMD_FLOWTRG
| drv_data->dma_width
- | chip->dma_burst_size
+ | dma_burst
| drv_data->len;
/* Enable dma end irqs on SSP to detect end of transfer */
@@ -856,16 +965,11 @@ static void pump_transfers(unsigned long data)
/* Fix me, need to handle cs polarity */
drv_data->cs_control(PXA2XX_CS_ASSERT);
- /* Go baby, go */
+ /* Clear status and start DMA engine */
+ cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
write_SSSR(drv_data->clear_sr, reg);
DCSR(drv_data->rx_channel) |= DCSR_RUN;
DCSR(drv_data->tx_channel) |= DCSR_RUN;
- if (drv_data->ssp_type != PXA25x_SSP)
- write_SSTO(chip->timeout, reg);
- write_SSCR1(chip->cr1
- | chip->dma_threshold
- | drv_data->dma_cr1,
- reg);
} else {
/* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = interrupt_transfer;
@@ -873,14 +977,25 @@ static void pump_transfers(unsigned long data)
/* Fix me, need to handle cs polarity */
drv_data->cs_control(PXA2XX_CS_ASSERT);
- /* Go baby, go */
+ /* Clear status */
+ cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
write_SSSR(drv_data->clear_sr, reg);
+ }
+
+ /* see if we need to reload the config registers */
+ if ((read_SSCR0(reg) != cr0)
+ || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
+ (cr1 & SSCR1_CHANGE_MASK)) {
+
+ write_SSCR0(cr0 & ~SSCR0_SSE, reg);
if (drv_data->ssp_type != PXA25x_SSP)
write_SSTO(chip->timeout, reg);
- write_SSCR1(chip->cr1
- | chip->threshold
- | drv_data->int_cr1,
- reg);
+ write_SSCR1(cr1, reg);
+ write_SSCR0(cr0, reg);
+ } else {
+ if (drv_data->ssp_type != PXA25x_SSP)
+ write_SSTO(chip->timeout, reg);
+ write_SSCR1(cr1, reg);
}
}
@@ -915,9 +1030,9 @@ static void pump_messages(struct work_struct *work)
struct spi_transfer,
transfer_list);
- /* Setup the SSP using the per chip configuration */
+ /* prepare to setup the SSP, in pump_transfers, using the per
+ * chip configuration */
drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
- restore_state(drv_data);
/* Mark as busy and launch transfers */
tasklet_schedule(&drv_data->pump_transfers);
@@ -963,63 +1078,77 @@ static int setup(struct spi_device *spi)
spi->bits_per_word = 8;
if (drv_data->ssp_type != PXA25x_SSP
- && (spi->bits_per_word < 4 || spi->bits_per_word > 32))
+ && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
+ dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+ "b/w not 4-32 for type non-PXA25x_SSP\n",
+ drv_data->ssp_type, spi->bits_per_word);
return -EINVAL;
- else if (spi->bits_per_word < 4 || spi->bits_per_word > 16)
+ }
+ else if (drv_data->ssp_type == PXA25x_SSP
+ && (spi->bits_per_word < 4
+ || spi->bits_per_word > 16)) {
+ dev_err(&spi->dev, "failed setup: ssp_type=%d, bits/wrd=%d "
+ "b/w not 4-16 for type PXA25x_SSP\n",
+ drv_data->ssp_type, spi->bits_per_word);
return -EINVAL;
+ }
- /* Only alloc (or use chip_info) on first setup */
+ /* Only alloc on first setup */
chip = spi_get_ctldata(spi);
- if (chip == NULL) {
+ if (!chip) {
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
- if (!chip)
+ if (!chip) {
+ dev_err(&spi->dev,
+ "failed setup: can't allocate chip data\n");
return -ENOMEM;
+ }
chip->cs_control = null_cs_control;
chip->enable_dma = 0;
- chip->timeout = SSP_TIMEOUT(1000);
+ chip->timeout = 1000;
chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
chip->dma_burst_size = drv_data->master_info->enable_dma ?
DCMD_BURST8 : 0;
-
- chip_info = spi->controller_data;
}
+ /* protocol drivers may change the chip settings, so...
+ * if chip_info exists, use it */
+ chip_info = spi->controller_data;
+
/* chip_info isn't always needed */
+ chip->cr1 = 0;
if (chip_info) {
if (chip_info->cs_control)
chip->cs_control = chip_info->cs_control;
- chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs);
+ chip->timeout = chip_info->timeout;
- chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold)
- | SSCR1_TxTresh(chip_info->tx_threshold);
+ chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) &
+ SSCR1_RFT) |
+ (SSCR1_TxTresh(chip_info->tx_threshold) &
+ SSCR1_TFT);
chip->enable_dma = chip_info->dma_burst_size != 0
&& drv_data->master_info->enable_dma;
chip->dma_threshold = 0;
- if (chip->enable_dma) {
- if (chip_info->dma_burst_size <= 8) {
- chip->dma_threshold = SSCR1_RxTresh(8)
- | SSCR1_TxTresh(8);
- chip->dma_burst_size = DCMD_BURST8;
- } else if (chip_info->dma_burst_size <= 16) {
- chip->dma_threshold = SSCR1_RxTresh(16)
- | SSCR1_TxTresh(16);
- chip->dma_burst_size = DCMD_BURST16;
- } else {
- chip->dma_threshold = SSCR1_RxTresh(32)
- | SSCR1_TxTresh(32);
- chip->dma_burst_size = DCMD_BURST32;
- }
- }
-
-
if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM;
}
+ /* set dma burst and threshold outside of chip_info path so that if
+ * chip_info goes away after setting chip->enable_dma, the
+ * burst and threshold can still respond to changes in bits_per_word */
+ if (chip->enable_dma) {
+ /* set up legal burst and threshold for dma */
+ if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word,
+ &chip->dma_burst_size,
+ &chip->dma_threshold)) {
+ dev_warn(&spi->dev, "in setup: DMA burst size reduced "
+ "to match bits_per_word\n");
+ }
+ }
+
if (drv_data->ioaddr == SSP1_VIRT)
clk_div = SSP1_SerClkDiv(spi->max_speed_hz);
else if (drv_data->ioaddr == SSP2_VIRT)
@@ -1027,7 +1156,11 @@ static int setup(struct spi_device *spi)
else if (drv_data->ioaddr == SSP3_VIRT)
clk_div = SSP3_SerClkDiv(spi->max_speed_hz);
else
+ {
+ dev_err(&spi->dev, "failed setup: unknown IO address=0x%p\n",
+ drv_data->ioaddr);
return -ENODEV;
+ }
chip->speed_hz = spi->max_speed_hz;
chip->cr0 = clk_div
@@ -1036,8 +1169,9 @@ static int setup(struct spi_device *spi)
spi->bits_per_word - 16 : spi->bits_per_word)
| SSCR0_SSE
| (spi->bits_per_word > 16 ? SSCR0_EDSS : 0);
- chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4)
- | (((spi->mode & SPI_CPOL) != 0) << 3);
+ chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
+ chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+ | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
/* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (drv_data->ssp_type != PXA25x_SSP)
@@ -1071,7 +1205,6 @@ static int setup(struct spi_device *spi)
chip->write = u32_writer;
} else {
dev_err(&spi->dev, "invalid wordsize\n");
- kfree(chip);
return -ENODEV;
}
chip->bits_per_word = spi->bits_per_word;
@@ -1162,6 +1295,12 @@ static int destroy_queue(struct driver_data *drv_data)
int status;
status = stop_queue(drv_data);
+ /* we are unloading the module or failing to load (only two calls
+ * to this routine), and neither call can handle a return value.
+ * However, destroy_workqueue calls flush_workqueue, and that will
+ * block until all work is done. If the reason that stop_queue
+ * timed out is that the work will never finish, then it does no
+ * good to call destroy_workqueue, so return anyway. */
if (status != 0)
return status;
@@ -1360,7 +1499,16 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
/* Remove the queue */
status = destroy_queue(drv_data);
if (status != 0)
- return status;
+ /* the kernel does not check the return status of this
+ * this routine (mod->exit, within the kernel). Therefore
+ * nothing is gained by returning from here, the module is
+ * going away regardless, and we should not leave any more
+ * resources allocated than necessary. We cannot free the
+ * message memory in drv_data->queue, but we can release the
+ * resources below. I think the kernel should honor -EBUSY
+ * returns but... */
+ dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
+ "complete, message memory not freed\n");
/* Disable the SSP at the peripheral and SOC level */
write_SSCR0(0, drv_data->ioaddr);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 270e6211c2e..6307428d2c9 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, unsigned size)
class_device_initialize(&master->cdev);
master->cdev.class = &spi_master_class;
- kobj_set_kset_s(&master->cdev, spi_master_class.subsys);
master->cdev.dev = get_device(dev);
spi_master_set_devdata(master, &master[1]);
@@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master);
*/
struct spi_master *spi_busnum_to_master(u16 bus_num)
{
- char name[9];
- struct kobject *bus;
-
- snprintf(name, sizeof name, "spi%u", bus_num);
- bus = kset_find_obj(&spi_master_class.subsys.kset, name);
- if (bus)
- return container_of(bus, struct spi_master, cdev.kobj);
- return NULL;
+ struct class_device *cdev;
+ struct spi_master *master = NULL;
+ struct spi_master *m;
+
+ down(&spi_master_class.sem);
+ list_for_each_entry(cdev, &spi_master_class.children, node) {
+ m = container_of(cdev, struct spi_master, cdev);
+ if (m->bus_num == bus_num) {
+ master = spi_master_get(m);
+ break;
+ }
+ }
+ up(&spi_master_class.sem);
+ return master;
}
EXPORT_SYMBOL_GPL(spi_busnum_to_master);
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index ff0b04895db..e9798bf7b8c 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -112,6 +112,8 @@ u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \
{ \
u32 data; \
const type * tx = mpc83xx_spi->tx; \
+ if (!tx) \
+ return 0; \
data = *tx++; \
mpc83xx_spi->tx = tx; \
return data; \
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 2ebe1fc4c39..651379c51ae 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -10,9 +10,6 @@
*
*/
-
-//#define DEBUG
-
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
@@ -44,6 +41,9 @@ struct s3c24xx_spi {
int len;
int count;
+ int (*set_cs)(struct s3c2410_spi_info *spi,
+ int cs, int pol);
+
/* data buffers */
const unsigned char *tx;
unsigned char *rx;
@@ -64,6 +64,11 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
return spi_master_get_devdata(sdev->master);
}
+static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
+{
+ s3c2410_gpio_setpin(spi->pin_cs, pol);
+}
+
static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
{
struct s3c24xx_spi *hw = to_hw(spi);
@@ -72,10 +77,7 @@ static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
switch (value) {
case BITBANG_CS_INACTIVE:
- if (hw->pdata->set_cs)
- hw->pdata->set_cs(hw->pdata, value, cspol);
- else
- s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1);
+ hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol^1);
break;
case BITBANG_CS_ACTIVE:
@@ -96,14 +98,9 @@ static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
/* write new configration */
writeb(spcon, hw->regs + S3C2410_SPCON);
-
- if (hw->pdata->set_cs)
- hw->pdata->set_cs(hw->pdata, value, cspol);
- else
- s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol);
+ hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol);
break;
-
}
}
@@ -174,7 +171,7 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
{
- return hw->tx ? hw->tx[count] : 0xff;
+ return hw->tx ? hw->tx[count] : 0;
}
static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
@@ -330,9 +327,12 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
/* setup any gpio we can */
if (!hw->pdata->set_cs) {
+ hw->set_cs = s3c24xx_spi_gpiocs;
+
s3c2410_gpio_setpin(hw->pdata->pin_cs, 1);
s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT);
- }
+ } else
+ hw->set_cs = hw->pdata->set_cs;
/* register our spi controller */
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index a5d2cdfff46..eda53ed04cb 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
+#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
@@ -22,7 +23,7 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/spi-gpio.h>
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
struct s3c2410_spigpio {
struct spi_bitbang bitbang;
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 792becdfe6f..fc319727366 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1238,7 +1238,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
return 0;
}
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
struct dec_serial *info = (struct dec_serial *)tty->driver_data;
int was_stopped;
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 1b601b6cf2a..df4cc1fb5f6 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -2747,7 +2747,7 @@ static void alaw2ulaw(unsigned char *buff, unsigned long len)
static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos)
{
unsigned long i = *ppos;
- IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode));
+ IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
DECLARE_WAITQUEUE(wait, current);
@@ -2804,7 +2804,7 @@ static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t
{
int pre_retval;
ssize_t read_retval = 0;
- IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+ IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
pre_retval = ixj_PreRead(j, 0L);
switch (pre_retval) {
@@ -2883,7 +2883,7 @@ static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf,
int pre_retval;
ssize_t write_retval = 0;
- IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+ IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
pre_retval = ixj_PreWrite(j, 0L);
switch (pre_retval) {
@@ -4582,7 +4582,7 @@ static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
{
unsigned int mask = 0;
- IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+ IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
poll_wait(file_p, &(j->poll_q), wait);
if (j->read_buffer_ready > 0)
@@ -6657,7 +6657,7 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
static int ixj_fasync(int fd, struct file *file_p, int mode)
{
- IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode));
+ IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
return fasync_helper(fd, file_p, mode, &j->async_queue);
}
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 7f1fa956dcd..98199628e39 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -677,10 +677,10 @@ static const __u8 acm_tty_size[] = {
5, 6, 7, 8
};
-static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
+static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old)
{
struct acm *acm = tty->driver_data;
- struct termios *termios = tty->termios;
+ struct ktermios *termios = tty->termios;
struct usb_cdc_line_coding newline;
int newctrl = acm->ctrlout;
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 6303970e93c..6377db1b446 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -130,7 +130,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
struct usblp {
struct usb_device *dev; /* USB device */
- struct semaphore sem; /* locks this struct, especially "dev" */
+ struct mutex mut; /* locks this struct, especially "dev" */
char *writebuf; /* write transfer_buffer */
char *readbuf; /* read transfer_buffer */
char *statusbuf; /* status transfer_buffer */
@@ -217,6 +217,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
+ { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
{ 0, 0 }
};
@@ -465,7 +466,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int twoints[2];
int retval = 0;
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
if (!usblp->present) {
retval = -ENODEV;
goto done;
@@ -644,14 +645,14 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
done:
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return retval;
}
static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- int timeout, rv, err = 0, transfer_length = 0;
+ int timeout, intr, rv, err = 0, transfer_length = 0;
size_t writecount = 0;
while (writecount < count) {
@@ -668,14 +669,16 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
if (rv < 0)
return writecount ? writecount : -EINTR;
}
- down (&usblp->sem);
+ intr = mutex_lock_interruptible (&usblp->mut);
+ if (intr)
+ return writecount ? writecount : -EINTR;
if (!usblp->present) {
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return -ENODEV;
}
if (usblp->sleeping) {
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return writecount ? writecount : -ENODEV;
}
@@ -687,10 +690,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
err = usblp->writeurb->status;
} else
err = usblp_check_status(usblp, err);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
/* if the fault was due to disconnect, let khubd's
- * call to usblp_disconnect() grab usblp->sem ...
+ * call to usblp_disconnect() grab usblp->mut ...
*/
schedule ();
continue;
@@ -702,7 +705,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
*/
writecount += transfer_length;
if (writecount == count) {
- up(&usblp->sem);
+ mutex_unlock(&usblp->mut);
break;
}
@@ -714,7 +717,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
if (copy_from_user(usblp->writeurb->transfer_buffer,
buffer + writecount, transfer_length)) {
- up(&usblp->sem);
+ mutex_unlock(&usblp->mut);
return writecount ? writecount : -EFAULT;
}
@@ -727,10 +730,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
count = -EIO;
else
count = writecount ? writecount : -ENOMEM;
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
break;
}
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
}
return count;
@@ -739,12 +742,14 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- int rv;
+ int rv, intr;
if (!usblp->bidir)
return -EINVAL;
- down (&usblp->sem);
+ intr = mutex_lock_interruptible (&usblp->mut);
+ if (intr)
+ return -EINTR;
if (!usblp->present) {
count = -ENODEV;
goto done;
@@ -757,9 +762,9 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
count = -EAGAIN;
goto done;
}
- up(&usblp->sem);
+ mutex_unlock(&usblp->mut);
rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
- down(&usblp->sem);
+ mutex_lock(&usblp->mut);
if (rv < 0) {
count = -EINTR;
goto done;
@@ -807,7 +812,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
}
done:
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return count;
}
@@ -886,7 +891,7 @@ static int usblp_probe(struct usb_interface *intf,
goto abort;
}
usblp->dev = dev;
- init_MUTEX (&usblp->sem);
+ mutex_init (&usblp->mut);
init_waitqueue_head(&usblp->wait);
usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usblp->intf = intf;
@@ -1178,7 +1183,7 @@ static void usblp_disconnect(struct usb_interface *intf)
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
mutex_lock (&usblp_mutex);
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
usblp->present = 0;
usb_set_intfdata (intf, NULL);
@@ -1187,7 +1192,7 @@ static void usblp_disconnect(struct usb_interface *intf)
usblp->writebuf, usblp->writeurb->transfer_dma);
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->readbuf, usblp->readurb->transfer_dma);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
if (!usblp->used)
usblp_cleanup (usblp);
@@ -1200,11 +1205,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
/* this races against normal access and open */
mutex_lock (&usblp_mutex);
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
/* we take no more IO */
usblp->sleeping = 1;
usblp_unlink_urbs(usblp);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
mutex_unlock (&usblp_mutex);
return 0;
@@ -1216,12 +1221,12 @@ static int usblp_resume (struct usb_interface *intf)
int r;
mutex_lock (&usblp_mutex);
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
usblp->sleeping = 0;
r = handle_bidir (usblp);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
mutex_unlock (&usblp_mutex);
return r;
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f8324d8d06a..3e66b2a9974 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -72,22 +72,6 @@ config USB_SUSPEND
If you are unsure about this, say N here.
-config USB_MULTITHREAD_PROBE
- bool "USB Multi-threaded probe (EXPERIMENTAL)"
- depends on USB && EXPERIMENTAL
- default n
- help
- Say Y here if you want the USB core to spawn a new thread for
- every USB device that is probed. This can cause a small speedup
- in boot times on systems with a lot of different USB devices.
-
- This option should be safe to enable, but if any odd probing
- problems are found, please disable it, or dynamically turn it
- off in the /sys/module/usbcore/parameters/multithread_probe
- file
-
- When in doubt, say N.
-
config USB_OTG
bool
depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 3ed4cb2d56d..4b3a6ab29bd 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -962,7 +962,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
kfree(dr);
return -EFAULT;
}
- snoop(&ps->dev->dev, "control urb\n");
+ snoop(&ps->dev->dev, "control urb: bRequest=%02x "
+ "bRrequestType=%02x wValue=%04x "
+ "wIndex=%04x wLength=%04x\n",
+ dr->bRequest, dr->bRequestType, dr->wValue,
+ dr->wIndex, dr->wLength);
break;
case USBDEVFS_URB_TYPE_BULK:
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index c505b767cee..5e628ae3aec 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -268,6 +268,7 @@ static void ep_device_release(struct device *dev)
struct ep_device *ep_dev = to_ep_device(dev);
dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
+ endpoint_free_minor(ep_dev);
kfree(ep_dev);
}
@@ -349,7 +350,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
- endpoint_free_minor(ep_dev);
device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL;
destroy_endpoint_class();
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 2651c2e2a89..1988224b362 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -88,14 +88,7 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static struct task_struct *khubd_task;
/* multithreaded probe logic */
-static int multithread_probe =
-#ifdef CONFIG_USB_MULTITHREAD_PROBE
- 1;
-#else
- 0;
-#endif
-module_param(multithread_probe, bool, S_IRUGO);
-MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");
+static int multithread_probe = 0;
/* cycle leds on hubs that aren't blinking for attention */
static int blinkenlights = 0;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index b5d6a79af0b..11dad22da41 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -379,7 +379,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
{
loff_t retval = -EINVAL;
- mutex_lock(&file->f_dentry->d_inode->i_mutex);
+ mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
switch(orig) {
case 0:
if (offset > 0) {
@@ -396,7 +396,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
default:
break;
}
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return retval;
}
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 72f3db99ff9..812c733ba8c 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -43,14 +43,16 @@
#include <linux/usb_gadget.h>
#include <asm/byteorder.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/at91sam9261_matrix.h>
#include "at91_udc.h"
@@ -78,27 +80,11 @@
static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0";
-/*-------------------------------------------------------------------------*/
-/*
- * Read from a UDP register.
- */
-static inline unsigned long at91_udp_read(unsigned int reg)
-{
- void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
-
- return __raw_readl(udp_base + reg);
-}
-
-/*
- * Write to a UDP register.
- */
-static inline void at91_udp_write(unsigned int reg, unsigned long value)
-{
- void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
-
- __raw_writel(value, udp_base + reg);
-}
+#define at91_udp_read(dev, reg) \
+ __raw_readl((dev)->udp_baseaddr + (reg))
+#define at91_udp_write(dev, reg, val) \
+ __raw_writel((val), (dev)->udp_baseaddr + (reg))
/*-------------------------------------------------------------------------*/
@@ -210,13 +196,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
return 0;
}
- tmp = at91_udp_read(AT91_UDP_FRM_NUM);
+ tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM);
seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp,
(tmp & AT91_UDP_FRM_OK) ? " ok" : "",
(tmp & AT91_UDP_FRM_ERR) ? " err" : "",
(tmp & AT91_UDP_NUM));
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp,
(tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "",
(tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "",
@@ -224,13 +210,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
(tmp & AT91_UDP_CONFG) ? " confg" : "",
(tmp & AT91_UDP_FADDEN) ? " fadden" : "");
- tmp = at91_udp_read(AT91_UDP_FADDR);
+ tmp = at91_udp_read(udc, AT91_UDP_FADDR);
seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp,
(tmp & AT91_UDP_FEN) ? " fen" : "",
(tmp & AT91_UDP_FADD));
- proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR));
- proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR));
+ proc_irq_show(s, "imr ", at91_udp_read(udc, AT91_UDP_IMR));
+ proc_irq_show(s, "isr ", at91_udp_read(udc, AT91_UDP_ISR));
if (udc->enabled && udc->vbus) {
proc_ep_show(s, &udc->ep[0]);
@@ -286,6 +272,7 @@ static inline void remove_debug_file(struct at91_udc *udc) {}
static void done(struct at91_ep *ep, struct at91_request *req, int status)
{
unsigned stopped = ep->stopped;
+ struct at91_udc *udc = ep->udc;
list_del_init(&req->queue);
if (req->req.status == -EINPROGRESS)
@@ -301,7 +288,7 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)
/* ep0 is always ready; other endpoints need a non-empty queue */
if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
- at91_udp_write(AT91_UDP_IDR, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
}
/*-------------------------------------------------------------------------*/
@@ -554,8 +541,8 @@ ok:
* reset/init endpoint fifo. NOTE: leaves fifo_bank alone,
* since endpoint resets don't reset hw pingpong state.
*/
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(dev, AT91_UDP_RST_EP, 0);
local_irq_restore(flags);
return 0;
@@ -564,6 +551,7 @@ ok:
static int at91_ep_disable (struct usb_ep * _ep)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
unsigned long flags;
if (ep == &ep->udc->ep[0])
@@ -579,8 +567,8 @@ static int at91_ep_disable (struct usb_ep * _ep)
/* reset fifos and endpoint */
if (ep->udc->clocked) {
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
__raw_writel(0, ep->creg);
}
@@ -598,7 +586,7 @@ at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags)
{
struct at91_request *req;
- req = kcalloc(1, sizeof (struct at91_request), gfp_flags);
+ req = kzalloc(sizeof (struct at91_request), gfp_flags);
if (!req)
return NULL;
@@ -695,10 +683,10 @@ static int at91_ep_queue(struct usb_ep *_ep,
* reconfigures the endpoints.
*/
if (dev->wait_for_config_ack) {
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT);
tmp ^= AT91_UDP_CONFG;
VDBG("toggle config\n");
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp);
}
if (req->req.length == 0) {
ep0_in_status:
@@ -727,7 +715,7 @@ ep0_in_status:
if (req && !status) {
list_add_tail (&req->queue, &ep->queue);
- at91_udp_write(AT91_UDP_IER, ep->int_mask);
+ at91_udp_write(dev, AT91_UDP_IER, ep->int_mask);
}
done:
local_irq_restore(flags);
@@ -758,6 +746,7 @@ static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int at91_ep_set_halt(struct usb_ep *_ep, int value)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
u32 __iomem *creg;
u32 csr;
unsigned long flags;
@@ -785,8 +774,8 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
csr |= AT91_UDP_FORCESTALL;
VDBG("halt %s\n", ep->ep.name);
} else {
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
csr &= ~AT91_UDP_FORCESTALL;
}
__raw_writel(csr, creg);
@@ -813,9 +802,11 @@ static struct usb_ep_ops at91_ep_ops = {
static int at91_get_frame(struct usb_gadget *gadget)
{
+ struct at91_udc *udc = to_udc(gadget);
+
if (!to_udc(gadget)->clocked)
return -EINVAL;
- return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
+ return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
}
static int at91_wakeup(struct usb_gadget *gadget)
@@ -833,11 +824,11 @@ static int at91_wakeup(struct usb_gadget *gadget)
/* NOTE: some "early versions" handle ESR differently ... */
- glbstate = at91_udp_read(AT91_UDP_GLB_STAT);
+ glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
if (!(glbstate & AT91_UDP_ESR))
goto done;
glbstate |= AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, glbstate);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
done:
local_irq_restore(flags);
@@ -861,6 +852,7 @@ static void udc_reinit(struct at91_udc *udc)
ep->stopped = 0;
ep->fifo_bank = 0;
ep->ep.maxpacket = ep->maxpacket;
+ ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
// initialiser une queue par endpoint
INIT_LIST_HEAD(&ep->queue);
}
@@ -915,14 +907,41 @@ static void pullup(struct at91_udc *udc, int is_on)
if (!udc->enabled || !udc->vbus)
is_on = 0;
DBG("%sactive\n", is_on ? "" : "in");
+
if (is_on) {
clk_on(udc);
- at91_udp_write(AT91_UDP_TXVC, 0);
- at91_set_gpio_value(udc->board.pullup_pin, 1);
- } else {
+ at91_udp_write(udc, AT91_UDP_TXVC, 0);
+ if (cpu_is_at91rm9200())
+ at91_set_gpio_value(udc->board.pullup_pin, 1);
+ else if (cpu_is_at91sam9260()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc |= AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261()) {
+ u32 usbpucr;
+
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr |= AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
+ } else {
stop_activity(udc);
- at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
- at91_set_gpio_value(udc->board.pullup_pin, 0);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ if (cpu_is_at91rm9200())
+ at91_set_gpio_value(udc->board.pullup_pin, 0);
+ else if (cpu_is_at91sam9260()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc &= ~AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261()) {
+ u32 usbpucr;
+
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
clk_off(udc);
}
}
@@ -936,7 +955,10 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
// VDBG("vbus %s\n", is_active ? "on" : "off");
local_irq_save(flags);
udc->vbus = (is_active != 0);
- pullup(udc, is_active);
+ if (udc->driver)
+ pullup(udc, is_active);
+ else
+ pullup(udc, 0);
local_irq_restore(flags);
return 0;
}
@@ -1086,7 +1108,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_SET_CONFIGURATION:
- tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
if (pkt.r.wValue)
udc->wait_for_config_ack = (tmp == 0);
else
@@ -1103,7 +1125,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_GET_STATUS:
tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
- if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
+ if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
PACKET("get device status\n");
__raw_writeb(tmp, dreg);
@@ -1114,17 +1136,17 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_SET_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp |= AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_CLEAR_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
/*
@@ -1206,8 +1228,8 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
} else if (ep->is_in)
goto stall;
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
tmp = __raw_readl(ep->creg);
tmp |= CLR_FX;
tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
@@ -1222,7 +1244,10 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
#undef w_length
/* pass request up to the gadget driver */
- status = udc->driver->setup(&udc->gadget, &pkt.r);
+ if (udc->driver)
+ status = udc->driver->setup(&udc->gadget, &pkt.r);
+ else
+ status = -ENODEV;
if (status < 0) {
stall:
VDBG("req %02x.%02x protocol STALL; stat %d\n",
@@ -1300,13 +1325,13 @@ static void handle_ep0(struct at91_udc *udc)
if (udc->wait_for_addr_ack) {
u32 tmp;
- at91_udp_write(AT91_UDP_FADDR,
+ at91_udp_write(udc, AT91_UDP_FADDR,
AT91_UDP_FEN | udc->addr);
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_FADDEN;
if (udc->addr)
tmp |= AT91_UDP_FADDEN;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
udc->wait_for_addr_ack = 0;
VDBG("address %d\n", udc->addr);
@@ -1374,28 +1399,28 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
while (rescans--) {
u32 status;
- status = at91_udp_read(AT91_UDP_ISR)
- & at91_udp_read(AT91_UDP_IMR);
+ status = at91_udp_read(udc, AT91_UDP_ISR)
+ & at91_udp_read(udc, AT91_UDP_IMR);
if (!status)
break;
/* USB reset irq: not maskable */
if (status & AT91_UDP_ENDBUSRES) {
- at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
- at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS);
+ at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
+ at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
/* Atmel code clears this irq twice */
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
VDBG("end bus reset\n");
udc->addr = 0;
stop_activity(udc);
/* enable ep0 */
- at91_udp_write(AT91_UDP_CSR(0),
+ at91_udp_write(udc, AT91_UDP_CSR(0),
AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
udc->gadget.speed = USB_SPEED_FULL;
udc->suspended = 0;
- at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0));
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
/*
* NOTE: this driver keeps clocks off unless the
@@ -1406,9 +1431,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated suspend (3+ms bus idle) */
} else if (status & AT91_UDP_RXSUSP) {
- at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP);
- at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
// VDBG("bus suspend\n");
if (udc->suspended)
continue;
@@ -1425,9 +1450,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated resume */
} else if (status & AT91_UDP_RXRSM) {
- at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM);
- at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
// VDBG("bus resume\n");
if (!udc->suspended)
continue;
@@ -1485,8 +1510,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(0)),
.int_mask = 1 << 0,
},
.ep[1] = {
@@ -1497,8 +1520,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(1)),
.int_mask = 1 << 1,
},
.ep[2] = {
@@ -1509,8 +1530,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(2)),
.int_mask = 1 << 2,
},
.ep[3] = {
@@ -1521,8 +1540,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(3)),
.int_mask = 1 << 3,
},
.ep[4] = {
@@ -1533,8 +1550,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(4)),
.int_mask = 1 << 4,
},
.ep[5] = {
@@ -1545,8 +1560,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(5)),
.int_mask = 1 << 5,
},
/* ep6 and ep7 are also reserved (custom silicon might use them) */
@@ -1572,9 +1585,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
int retval;
if (!driver
- || driver->speed != USB_SPEED_FULL
+ || driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->setup) {
DBG("bad parameter.\n");
return -EINVAL;
@@ -1595,6 +1607,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (retval) {
DBG("driver->bind() returned %d\n", retval);
udc->driver = NULL;
+ udc->gadget.dev.driver = NULL;
+ udc->gadget.dev.driver_data = NULL;
+ udc->enabled = 0;
+ udc->selfpowered = 0;
return retval;
}
@@ -1611,12 +1627,12 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
- if (!driver || driver != udc->driver)
+ if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
udc->enabled = 0;
- at91_udp_write(AT91_UDP_IDR, ~0);
+ at91_udp_write(udc, AT91_UDP_IDR, ~0);
pullup(udc, 0);
local_irq_enable();
@@ -1641,6 +1657,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct at91_udc *udc;
int retval;
+ struct resource *res;
if (!dev->platform_data) {
/* small (so we copy it) but critical! */
@@ -1658,7 +1675,13 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!request_mem_region(res->start,
+ res->end - res->start + 1,
+ driver_name)) {
DBG("someone's using UDC memory\n");
return -EBUSY;
}
@@ -1668,15 +1691,23 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
udc->gadget.dev.parent = dev;
udc->board = *(struct at91_udc_data *) dev->platform_data;
udc->pdev = pdev;
- udc_reinit(udc);
udc->enabled = 0;
+ udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
+ if (!udc->udp_baseaddr) {
+ release_mem_region(res->start, res->end - res->start + 1);
+ return -ENOMEM;
+ }
+
+ udc_reinit(udc);
+
/* get interface and function clocks */
udc->iclk = clk_get(dev, "udc_clk");
udc->fclk = clk_get(dev, "udpck");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
DBG("clocks missing\n");
- return -ENODEV;
+ retval = -ENODEV;
+ goto fail0;
}
retval = device_register(&udc->gadget.dev);
@@ -1685,8 +1716,10 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
/* don't do anything until we have both gadget driver and VBUS */
clk_enable(udc->iclk);
- at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
- at91_udp_write(AT91_UDP_IDR, 0xffffffff);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
+ /* Clear all pending interrupts - UDP may be used by bootloader. */
+ at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
clk_disable(udc->iclk);
/* request UDC and maybe VBUS irqs */
@@ -1698,6 +1731,11 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
goto fail1;
}
if (udc->board.vbus_pin > 0) {
+ /*
+ * Get the initial state of VBUS - we cannot expect
+ * a pending interrupt.
+ */
+ udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
IRQF_DISABLED, driver_name, udc)) {
DBG("request vbus irq %d failed\n",
@@ -1720,7 +1758,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
fail1:
device_unregister(&udc->gadget.dev);
fail0:
- release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
+ release_mem_region(res->start, res->end - res->start + 1);
DBG("%s probe failed, %d\n", driver_name, retval);
return retval;
}
@@ -1728,13 +1766,14 @@ fail0:
static int __devexit at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
+ struct resource *res;
DBG("remove\n");
- pullup(udc, 0);
+ if (udc->driver)
+ return -EBUSY;
- if (udc->driver != 0)
- usb_gadget_unregister_driver(udc->driver);
+ pullup(udc, 0);
device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc);
@@ -1742,7 +1781,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev)
free_irq(udc->board.vbus_pin, udc);
free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
- release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
+
+ iounmap(udc->udp_baseaddr);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
clk_put(udc->iclk);
clk_put(udc->fclk);
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 882af42e86c..677089baa59 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -51,10 +51,10 @@
#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */
#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */
#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */
-#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */
+#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */
#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */
-#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */
+#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */
#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */
@@ -84,7 +84,7 @@
#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */
#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */
-
+#define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */
/*-------------------------------------------------------------------------*/
@@ -141,6 +141,7 @@ struct at91_udc {
struct clk *iclk, *fclk;
struct platform_device *pdev;
struct proc_dir_entry *pde;
+ void __iomem *udp_baseaddr;
int udp_irq;
};
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index f1f32d7be5f..3c2bc075ef4 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -779,7 +779,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
return -EINVAL;
if (dum->driver)
return -EBUSY;
- if (!driver->bind || !driver->unbind || !driver->setup
+ if (!driver->bind || !driver->setup
|| driver->speed == USB_SPEED_UNKNOWN)
return -EINVAL;
@@ -837,7 +837,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
err_bind_driver:
driver_unregister (&driver->driver);
err_register:
- driver->unbind (&dum->gadget);
+ if (driver->unbind)
+ driver->unbind (&dum->gadget);
spin_lock_irq (&dum->lock);
dum->pullup = 0;
set_link_state (dum);
@@ -857,7 +858,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dum)
return -ENODEV;
- if (!driver || driver != dum->driver)
+ if (!driver || driver != dum->driver || !driver->unbind)
return -EINVAL;
dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index c98316ce838..72f2ae96fbf 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun)
if (!filp->f_op->fsync)
return -EINVAL;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
mutex_lock(&inode->i_mutex);
rc = filemap_fdatawrite(inode->i_mapping);
- err = filp->f_op->fsync(filp, filp->f_dentry, 1);
+ err = filp->f_op->fsync(filp, filp->f_path.dentry, 1);
if (!rc)
rc = err;
err = filemap_fdatawait(inode->i_mapping);
@@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg)
static void invalidate_sub(struct lun *curlun)
{
struct file *filp = curlun->filp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
unsigned long rc;
rc = invalidate_inode_pages(inode->i_mapping);
@@ -3526,8 +3526,8 @@ static int open_backing_file(struct lun *curlun, const char *filename)
if (!(filp->f_mode & FMODE_WRITE))
ro = 1;
- if (filp->f_dentry)
- inode = filp->f_dentry->d_inode;
+ if (filp->f_path.dentry)
+ inode = filp->f_path.dentry->d_inode;
if (inode && S_ISBLK(inode->i_mode)) {
if (bdev_read_only(inode->i_bdev))
ro = 1;
@@ -3606,7 +3606,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
down_read(&fsg->filesem);
if (backing_file_is_open(curlun)) { // Get the complete pathname
- p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt,
+ p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt,
buf, PAGE_SIZE - 1);
if (IS_ERR(p))
rc = PTR_ERR(p);
@@ -4030,8 +4030,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
if (backing_file_is_open(curlun)) {
p = NULL;
if (pathbuf) {
- p = d_path(curlun->filp->f_dentry,
- curlun->filp->f_vfsmnt,
+ p = d_path(curlun->filp->f_path.dentry,
+ curlun->filp->f_path.mnt,
pathbuf, PATH_MAX);
if (IS_ERR(p))
p = NULL;
@@ -4100,7 +4100,7 @@ static struct usb_gadget_driver fsg_driver = {
#endif
.function = (char *) longname,
.bind = fsg_bind,
- .unbind = __exit_p(fsg_unbind),
+ .unbind = fsg_unbind,
.disconnect = fsg_disconnect,
.setup = fsg_setup,
.suspend = fsg_suspend,
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 31351826f2b..f1a679656c9 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -123,7 +123,7 @@ struct gmidi_device {
struct usb_request *req; /* for control responses */
u8 config;
struct usb_ep *in_ep, *out_ep;
- struct snd_card *card;
+ struct snd_card *card;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *in_substream;
struct snd_rawmidi_substream *out_substream;
@@ -490,7 +490,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
int status = req->status;
switch (status) {
- case 0: /* normal completion */
+ case 0: /* normal completion */
if (ep == dev->out_ep) {
/* we received stuff.
req is queued again, below */
@@ -505,7 +505,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
break;
/* this endpoint is normally active while we're configured */
- case -ECONNABORTED: /* hardware forced ep reset */
+ case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
@@ -656,7 +656,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
case USB_SPEED_LOW: speed = "low"; break;
case USB_SPEED_FULL: speed = "full"; break;
case USB_SPEED_HIGH: speed = "high"; break;
- default: speed = "?"; break;
+ default: speed = "?"; break;
}
dev->config = number;
@@ -1308,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = {
.speed = USB_SPEED_FULL,
.function = (char *)longname,
.bind = gmidi_bind,
- .unbind = __exit_p(gmidi_unbind),
+ .unbind = gmidi_unbind,
.setup = gmidi_setup,
.disconnect = gmidi_disconnect,
@@ -1316,7 +1316,7 @@ static struct usb_gadget_driver gmidi_driver = {
.suspend = gmidi_suspend,
.resume = gmidi_resume,
- .driver = {
+ .driver = {
.name = (char *)shortname,
.owner = THIS_MODULE,
},
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 805a9826842..d0ef1d6b3fa 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1432,7 +1432,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@@ -1495,7 +1494,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@@ -1808,13 +1807,8 @@ static void goku_remove(struct pci_dev *pdev)
struct goku_udc *dev = pci_get_drvdata(pdev);
DBG(dev, "%s\n", __FUNCTION__);
- /* start with the driver above us */
- if (dev->driver) {
- /* should have been done already by driver model core */
- WARN(dev, "pci remove, driver '%s' is still registered\n",
- dev->driver->driver.name);
- usb_gadget_unregister_driver(dev->driver);
- }
+
+ BUG_ON(dev->driver);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
remove_proc_entry(proc_node_name, NULL);
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 4a991564a03..a0a73c08a34 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -422,9 +422,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
if (!driver
- || driver->speed != USB_SPEED_FULL
- || !driver->bind
- || !driver->unbind || !driver->disconnect || !driver->setup)
+ || driver->speed != USB_SPEED_FULL
+ || !driver->bind
+ || !driver->disconnect
+ || !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
@@ -471,7 +472,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@@ -2125,9 +2126,11 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
DEBUG("%s: %p\n", __FUNCTION__, pdev);
+ if (dev->driver)
+ return -EBUSY;
+
udc_disable(dev);
remove_proc_files();
- usb_gadget_unregister_driver(dev->driver);
free_irq(IRQ_USBINTR, dev);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3024c679e38..569eb8ccf23 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2020,7 +2020,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
if (!dev)
@@ -2107,7 +2106,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave (&dev->lock, flags);
@@ -2803,13 +2802,7 @@ static void net2280_remove (struct pci_dev *pdev)
{
struct net2280 *dev = pci_get_drvdata (pdev);
- /* start with the driver above us */
- if (dev->driver) {
- /* should have been done already by driver model core */
- WARN (dev, "pci remove, driver '%s' is still registered\n",
- dev->driver->driver.name);
- usb_gadget_unregister_driver (dev->driver);
- }
+ BUG_ON(dev->driver);
/* then clean up the resources we allocated during probe() */
net2280_led_shutdown (dev);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 030d87c28c2..cdcfd42843d 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -42,6 +42,7 @@
#include <linux/usb_gadget.h>
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
+#include <linux/clk.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -60,6 +61,11 @@
/* bulk DMA seems to be behaving for both IN and OUT */
#define USE_DMA
+/* FIXME: OMAP2 currently has some problem in DMA mode */
+#ifdef CONFIG_ARCH_OMAP2
+#undef USE_DMA
+#endif
+
/* ISO too */
#define USE_ISO
@@ -99,7 +105,7 @@ static unsigned fifo_mode = 0;
* boot parameter "omap_udc:fifo_mode=42"
*/
module_param (fifo_mode, uint, 0);
-MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
+MODULE_PARM_DESC (fifo_mode, "endpoint configuration");
#ifdef USE_DMA
static unsigned use_dma = 1;
@@ -122,7 +128,7 @@ static const char driver_desc [] = DRIVER_DESC;
/*-------------------------------------------------------------------------*/
/* there's a notion of "current endpoint" for modifying endpoint
- * state, and PIO access to its FIFO.
+ * state, and PIO access to its FIFO.
*/
static void use_ep(struct omap_ep *ep, u16 select)
@@ -391,7 +397,7 @@ done(struct omap_ep *ep, struct omap_req *req, int status)
#define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
-static inline int
+static inline int
write_packet(u8 *buf, struct omap_req *req, unsigned max)
{
unsigned len;
@@ -456,7 +462,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req)
return is_last;
}
-static inline int
+static inline int
read_packet(u8 *buf, struct omap_req *req, unsigned avail)
{
unsigned len;
@@ -542,9 +548,9 @@ static inline dma_addr_t dma_csac(unsigned lch)
/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
- csac = omap_readw(OMAP_DMA_CSAC(lch));
+ csac = OMAP_DMA_CSAC_REG(lch);
if (csac == 0)
- csac = omap_readw(OMAP_DMA_CSAC(lch));
+ csac = OMAP_DMA_CSAC_REG(lch);
return csac;
}
@@ -555,9 +561,9 @@ static inline dma_addr_t dma_cdac(unsigned lch)
/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
- cdac = omap_readw(OMAP_DMA_CDAC(lch));
+ cdac = OMAP_DMA_CDAC_REG(lch);
if (cdac == 0)
- cdac = omap_readw(OMAP_DMA_CDAC(lch));
+ cdac = OMAP_DMA_CDAC_REG(lch);
return cdac;
}
@@ -582,7 +588,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
}
#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
- ? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \
+ ? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \
: dma_cdac(x))
static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
@@ -620,17 +626,19 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
txdma_ctrl = UDC_TXN_EOT | length;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
- length, 1, sync_mode);
+ length, 1, sync_mode, 0, 0);
} else {
length = min(length / ep->maxpacket,
(unsigned) UDC_TXN_TSC + 1);
- txdma_ctrl = length;
+ txdma_ctrl = length;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
- ep->ep.maxpacket >> 1, length, sync_mode);
+ ep->ep.maxpacket >> 1, length, sync_mode,
+ 0, 0);
length *= ep->maxpacket;
}
omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
- OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+ OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+ 0, 0);
omap_start_dma(ep->lch);
ep->dma_counter = dma_csac(ep->lch);
@@ -675,9 +683,11 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
req->dma_bytes = packets * ep->ep.maxpacket;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
ep->ep.maxpacket >> 1, packets,
- OMAP_DMA_SYNC_ELEMENT);
+ OMAP_DMA_SYNC_ELEMENT,
+ 0, 0);
omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
- OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+ OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+ 0, 0);
ep->dma_counter = DMA_DEST_LAST(ep->lch);
UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
@@ -820,7 +830,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
omap_set_dma_dest_params(ep->lch,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
- (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+ (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+ 0, 0);
}
} else {
status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
@@ -831,7 +842,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
omap_set_dma_src_params(ep->lch,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
- (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+ (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+ 0, 0);
/* EMIFF */
omap_set_dma_dest_burst_mode(ep->lch,
OMAP_DMA_DATA_BURST_4);
@@ -846,7 +858,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
/* channel type P: hw synch (fifo) */
if (!cpu_is_omap15xx())
- omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+ OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
}
just_restart:
@@ -893,7 +905,7 @@ static void dma_channel_release(struct omap_ep *ep)
else
req = NULL;
- active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0;
+ active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0;
DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
active ? "active" : "idle",
@@ -1117,7 +1129,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
*/
dma_channel_release(ep);
dma_channel_claim(ep, channel);
- } else
+ } else
done(ep, req, -ECONNRESET);
spin_unlock_irqrestore(&ep->udc->lock, flags);
return 0;
@@ -1153,7 +1165,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
/* IN endpoints must already be idle */
if ((ep->bEndpointAddress & USB_DIR_IN)
- && !list_empty(&ep->queue)) {
+ && !list_empty(&ep->queue)) {
status = -EAGAIN;
goto done;
}
@@ -1298,6 +1310,23 @@ static void pullup_disable(struct omap_udc *udc)
UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
}
+static struct omap_udc *udc;
+
+static void omap_udc_enable_clock(int enable)
+{
+ if (udc == NULL || udc->dc_clk == NULL || udc->hhc_clk == NULL)
+ return;
+
+ if (enable) {
+ clk_enable(udc->dc_clk);
+ clk_enable(udc->hhc_clk);
+ udelay(100);
+ } else {
+ clk_disable(udc->hhc_clk);
+ clk_disable(udc->dc_clk);
+ }
+}
+
/*
* Called by whatever detects VBUS sessions: external transceiver
* driver, or maybe GPIO0 VBUS IRQ. May request 48 MHz clock.
@@ -1318,10 +1347,22 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
else
FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
}
+ if (udc->dc_clk != NULL && is_active) {
+ if (!udc->clk_requested) {
+ omap_udc_enable_clock(1);
+ udc->clk_requested = 1;
+ }
+ }
if (can_pullup(udc))
pullup_enable(udc);
else
pullup_disable(udc);
+ if (udc->dc_clk != NULL && !is_active) {
+ if (udc->clk_requested) {
+ omap_udc_enable_clock(0);
+ udc->clk_requested = 0;
+ }
+ }
spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -1441,7 +1482,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
}
}
- /* IN/OUT packets mean we're in the DATA or STATUS stage.
+ /* IN/OUT packets mean we're in the DATA or STATUS stage.
* This driver uses only uses protocol stalls (ep0 never halts),
* and if we got this far the gadget driver already had a
* chance to stall. Tries to be forgiving of host oddities.
@@ -1509,7 +1550,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
} else if (stat == 0)
UDC_CTRL_REG = UDC_SET_FIFO_EN;
UDC_EP_NUM_REG = 0;
-
+
/* activate status stage */
if (stat == 1) {
done(ep0, req, 0);
@@ -1866,7 +1907,7 @@ static void pio_out_timer(unsigned long _ep)
spin_lock_irqsave(&ep->udc->lock, flags);
if (!list_empty(&ep->queue) && ep->ackwait) {
- use_ep(ep, 0);
+ use_ep(ep, UDC_EP_SEL);
stat_flg = UDC_STAT_FLG_REG;
if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
@@ -1876,12 +1917,12 @@ static void pio_out_timer(unsigned long _ep)
VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
req = container_of(ep->queue.next,
struct omap_req, queue);
- UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL;
(void) read_fifo(ep, req);
UDC_EP_NUM_REG = ep->bEndpointAddress;
UDC_CTRL_REG = UDC_SET_FIFO_EN;
ep->ackwait = 1 + ep->double_buf;
- }
+ } else
+ deselect_ep();
}
mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
spin_unlock_irqrestore(&ep->udc->lock, flags);
@@ -2028,7 +2069,17 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
/*-------------------------------------------------------------------------*/
-static struct omap_udc *udc;
+static inline int machine_needs_vbus_session(void)
+{
+ return (machine_is_omap_innovator()
+ || machine_is_omap_osk()
+ || machine_is_omap_apollon()
+#ifndef CONFIG_MACH_OMAP_H4_OTG
+ || machine_is_omap_h4()
+#endif
+ || machine_is_sx1()
+ );
+}
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
{
@@ -2043,7 +2094,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
// FIXME if otg, check: driver->is_otg
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
@@ -2071,6 +2121,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags);
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(1);
+
status = driver->bind (&udc->gadget);
if (status) {
DBG("bind to %s --> %d\n", driver->driver.name, status);
@@ -2087,9 +2140,11 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
status = otg_set_peripheral(udc->transceiver, &udc->gadget);
if (status < 0) {
ERR("can't bind to transceiver\n");
- driver->unbind (&udc->gadget);
- udc->gadget.dev.driver = NULL;
- udc->driver = NULL;
+ if (driver->unbind) {
+ driver->unbind (&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+ udc->driver = NULL;
+ }
goto done;
}
} else {
@@ -2102,10 +2157,12 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
/* 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())
+ if (machine_needs_vbus_session())
omap_vbus_session(&udc->gadget, 1);
done:
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(0);
return status;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
@@ -2117,10 +2174,13 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!udc)
return -ENODEV;
- if (!driver || driver != udc->driver)
+ if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
- if (machine_is_omap_innovator() || machine_is_omap_osk())
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(1);
+
+ if (machine_needs_vbus_session())
omap_vbus_session(&udc->gadget, 0);
if (udc->transceiver)
@@ -2136,6 +2196,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(0);
DBG("unregistered driver '%s'\n", driver->driver.name);
return status;
}
@@ -2218,7 +2280,7 @@ static char *trx_mode(unsigned m, int enabled)
case 0: return enabled ? "*6wire" : "unused";
case 1: return "4wire";
case 2: return "3wire";
- case 3: return "6wire";
+ case 3: return "6wire";
default: return "unknown";
}
}
@@ -2227,11 +2289,18 @@ static int proc_otg_show(struct seq_file *s)
{
u32 tmp;
u32 trans;
+ char *ctrl_name;
tmp = OTG_REV_REG;
- trans = USB_TRANSCEIVER_CTRL_REG;
- seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n",
- tmp >> 4, tmp & 0xf, trans);
+ if (cpu_is_omap24xx()) {
+ ctrl_name = "control_devconf";
+ trans = CONTROL_DEVCONF_REG;
+ } else {
+ ctrl_name = "tranceiver_ctrl";
+ trans = USB_TRANSCEIVER_CTRL_REG;
+ }
+ seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
+ tmp >> 4, tmp & 0xf, ctrl_name, trans);
tmp = OTG_SYSCON_1_REG;
seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
FOURBITS "\n", tmp,
@@ -2306,7 +2375,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
driver_desc,
use_dma ? " (dma)" : "");
- tmp = UDC_REV_REG & 0xff;
+ tmp = UDC_REV_REG & 0xff;
seq_printf(s,
"UDC rev %d.%d, fifo mode %d, gadget %s\n"
"hmc %d, transceiver %s\n",
@@ -2314,11 +2383,16 @@ static int proc_udc_show(struct seq_file *s, void *_)
fifo_mode,
udc->driver ? udc->driver->driver.name : "(none)",
HMC,
- udc->transceiver ? udc->transceiver->label : "(none)");
- seq_printf(s, "ULPD control %04x req %04x status %04x\n",
- __REG16(ULPD_CLOCK_CTRL),
- __REG16(ULPD_SOFT_REQ),
- __REG16(ULPD_STATUS_REQ));
+ udc->transceiver
+ ? udc->transceiver->label
+ : ((cpu_is_omap1710() || cpu_is_omap24xx())
+ ? "external" : "(none)"));
+ if (cpu_class_is_omap1()) {
+ seq_printf(s, "ULPD control %04x req %04x status %04x\n",
+ __REG16(ULPD_CLOCK_CTRL),
+ __REG16(ULPD_SOFT_REQ),
+ __REG16(ULPD_STATUS_REQ));
+ }
/* OTG controller registers */
if (!cpu_is_omap15xx())
@@ -2503,9 +2577,10 @@ omap_ep_setup(char *name, u8 addr, u8 type,
dbuf = 1;
} else {
/* double-buffering "not supported" on 15xx,
- * and ignored for PIO-IN on 16xx
+ * and ignored for PIO-IN on newer chips
+ * (for more reliable behavior)
*/
- if (!use_dma || cpu_is_omap15xx())
+ if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx())
dbuf = 0;
switch (maxp) {
@@ -2548,7 +2623,7 @@ omap_ep_setup(char *name, u8 addr, u8 type,
ep->bEndpointAddress = addr;
ep->bmAttributes = type;
ep->double_buf = dbuf;
- ep->udc = udc;
+ ep->udc = udc;
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
@@ -2708,15 +2783,37 @@ static int __init omap_udc_probe(struct platform_device *pdev)
struct otg_transceiver *xceiv = NULL;
const char *type = NULL;
struct omap_usb_config *config = pdev->dev.platform_data;
+ struct clk *dc_clk;
+ struct clk *hhc_clk;
/* NOTE: "knows" the order of the resources! */
- if (!request_mem_region(pdev->resource[0].start,
+ if (!request_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1,
driver_name)) {
DBG("request_mem_region failed\n");
return -EBUSY;
}
+ if (cpu_is_omap16xx()) {
+ dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
+ hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
+ BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
+ /* can't use omap_udc_enable_clock yet */
+ clk_enable(dc_clk);
+ clk_enable(hhc_clk);
+ udelay(100);
+ }
+
+ if (cpu_is_omap24xx()) {
+ dc_clk = clk_get(&pdev->dev, "usb_fck");
+ hhc_clk = clk_get(&pdev->dev, "usb_l4_ick");
+ BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
+ /* can't use omap_udc_enable_clock yet */
+ clk_enable(dc_clk);
+ clk_enable(hhc_clk);
+ udelay(100);
+ }
+
INFO("OMAP UDC rev %d.%d%s\n",
UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
config->otg ? ", Mini-AB" : "");
@@ -2726,7 +2823,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
hmc = HMC_1510;
type = "(unknown)";
- if (machine_is_omap_innovator()) {
+ if (machine_is_omap_innovator() || machine_is_sx1()) {
/* just set up software VBUS detect, and then
* later rig it so we always report VBUS.
* FIXME without really sensing VBUS, we can't
@@ -2755,6 +2852,15 @@ static int __init omap_udc_probe(struct platform_device *pdev)
}
hmc = HMC_1610;
+
+ if (cpu_is_omap24xx()) {
+ /* this could be transceiverless in one of the
+ * "we don't need to know" modes.
+ */
+ type = "external";
+ goto known;
+ }
+
switch (hmc) {
case 0: /* POWERUP DEFAULT == 0 */
case 4:
@@ -2793,6 +2899,7 @@ bad_on_1710:
goto cleanup0;
}
}
+known:
INFO("hmc mode %d, %s transceiver\n", hmc, type);
/* a "gadget" abstracts/virtualizes the controller */
@@ -2817,8 +2924,8 @@ bad_on_1710:
status = request_irq(pdev->resource[1].start, omap_udc_irq,
IRQF_SAMPLE_RANDOM, driver_name, udc);
if (status != 0) {
- ERR( "can't get irq %ld, err %d\n",
- pdev->resource[1].start, status);
+ ERR("can't get irq %d, err %d\n",
+ (int) pdev->resource[1].start, status);
goto cleanup1;
}
@@ -2826,24 +2933,41 @@ bad_on_1710:
status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
if (status != 0) {
- ERR( "can't get irq %ld, err %d\n",
- pdev->resource[2].start, status);
+ ERR("can't get irq %d, err %d\n",
+ (int) pdev->resource[2].start, status);
goto cleanup2;
}
#ifdef USE_ISO
status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
IRQF_DISABLED, "omap_udc iso", udc);
if (status != 0) {
- ERR("can't get irq %ld, err %d\n",
- pdev->resource[3].start, status);
+ ERR("can't get irq %d, err %d\n",
+ (int) pdev->resource[3].start, status);
goto cleanup3;
}
#endif
+ if (cpu_is_omap16xx()) {
+ udc->dc_clk = dc_clk;
+ udc->hhc_clk = hhc_clk;
+ clk_disable(hhc_clk);
+ clk_disable(dc_clk);
+ }
+
+ if (cpu_is_omap24xx()) {
+ udc->dc_clk = dc_clk;
+ udc->hhc_clk = hhc_clk;
+ /* FIXME OMAP2 don't release hhc & dc clock */
+#if 0
+ clk_disable(hhc_clk);
+ clk_disable(dc_clk);
+#endif
+ }
create_proc_file();
- device_add(&udc->gadget.dev);
- return 0;
-
+ status = device_add(&udc->gadget.dev);
+ if (!status)
+ return status;
+ /* If fail, fall through */
#ifdef USE_ISO
cleanup3:
free_irq(pdev->resource[2].start, udc);
@@ -2859,8 +2983,17 @@ cleanup1:
cleanup0:
if (xceiv)
put_device(xceiv->dev);
+
+ if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ clk_disable(hhc_clk);
+ clk_disable(dc_clk);
+ clk_put(hhc_clk);
+ clk_put(dc_clk);
+ }
+
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
+
return status;
}
@@ -2870,6 +3003,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
if (!udc)
return -ENODEV;
+ if (udc->driver)
+ return -EBUSY;
udc->done = &done;
@@ -2888,6 +3023,13 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
free_irq(pdev->resource[2].start, udc);
free_irq(pdev->resource[1].start, udc);
+ if (udc->dc_clk) {
+ if (udc->clk_requested)
+ omap_udc_enable_clock(0);
+ clk_put(udc->hhc_clk);
+ clk_put(udc->dc_clk);
+ }
+
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 652ee462734..1dc398bb9ab 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -175,6 +175,9 @@ struct omap_udc {
unsigned ep0_reset_config:1;
unsigned ep0_setup:1;
struct completion *done;
+ struct clk *dc_clk;
+ struct clk *hhc_clk;
+ unsigned clk_requested:1;
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 1ed506e9598..b78de969466 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -1623,7 +1623,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@@ -1694,7 +1693,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
@@ -2638,9 +2637,11 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
{
struct pxa2xx_udc *dev = platform_get_drvdata(pdev);
+ if (dev->driver)
+ return -EBUSY;
+
udc_disable(dev);
remove_proc_files();
- usb_gadget_unregister_driver(dev->driver);
if (dev->got_irq) {
free_irq(IRQ_USB, dev);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 208e55a667a..f8a3ec64635 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty);
static void gs_break(struct tty_struct *tty, int break_state);
static int gs_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
-static void gs_set_termios(struct tty_struct *tty, struct termios *old);
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old);
static int gs_send(struct gs_dev *dev);
static int gs_send_packet(struct gs_dev *dev, char *packet,
@@ -296,7 +296,7 @@ static struct usb_gadget_driver gs_gadget_driver = {
#endif /* CONFIG_USB_GADGET_DUALSPEED */
.function = GS_LONG_NAME,
.bind = gs_bind,
- .unbind = __exit_p(gs_unbind),
+ .unbind = gs_unbind,
.setup = gs_setup,
.disconnect = gs_disconnect,
.driver = {
@@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
/*
* gs_set_termios
*/
-static void gs_set_termios(struct tty_struct *tty, struct termios *old)
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
{
}
@@ -2195,7 +2195,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
if (size == 0)
return NULL;
- gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags);
+ gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
if (gb == NULL)
return NULL;
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 9325e46a68c..282d82efc0b 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -365,7 +365,7 @@ static inline struct urb *urb_list_first(int epid)
/* Adds an urb_entry last in the list for this epid. */
static inline void urb_list_add(struct urb *urb, int epid)
{
- urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
+ urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
assert(urb_entry);
urb_entry->urb = urb;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index b466581beb4..cc405512fa1 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -187,7 +187,6 @@ ohci_at91_start (struct usb_hcd *hcd)
{
struct at91_usbh_data *board = hcd->self.controller->platform_data;
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- struct usb_device *root = hcd->self.root_hub;
int ret;
if ((ret = ohci_init(ohci)) < 0)
@@ -221,7 +220,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
*/
.start = ohci_at91_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 24e23c5783d..e70b2430e2a 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -269,7 +269,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
*/
.start = ohci_au1xxx_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -336,7 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_au1xxx_driver = {
.probe = ohci_hcd_au1xxx_drv_probe,
.remove = ohci_hcd_au1xxx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_au1xxx_drv_suspend, */
/*.resume = ohci_hcd_au1xxx_drv_resume, */
.driver = {
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 0f47a57dac2..273d5ddb72b 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -16,7 +16,7 @@
case PIPE_CONTROL: temp = "ctrl"; break; \
case PIPE_BULK: temp = "bulk"; break; \
case PIPE_INTERRUPT: temp = "intr"; break; \
- default: temp = "isoc"; break; \
+ default: temp = "isoc"; break; \
}; temp;})
#define pipestring(pipe) edstring(usb_pipetype(pipe))
@@ -205,13 +205,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
- \
+ \
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
- \
+ \
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
@@ -563,7 +563,7 @@ show_periodic (struct class_device *class_dev, char *buf)
(info & ED_SKIP) ? " K" : "",
(ed->hwHeadP &
cpu_to_hc32(ohci, ED_H)) ?
- " H" : "");
+ " H" : "");
size -= temp;
next += temp;
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 1bf5e7a4e73..3348b07f0fe 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -169,7 +169,7 @@ static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev)
static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct ochi_hcd *ohci = hcd_to_ohci(hcd);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
@@ -204,7 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
static struct platform_driver ohci_hcd_ep93xx_driver = {
.probe = ohci_hcd_ep93xx_drv_probe,
.remove = ohci_hcd_ep93xx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_hcd_ep93xx_drv_suspend,
.resume = ohci_hcd_ep93xx_drv_resume,
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index b28a9b60206..c1c1d871aba 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -3,77 +3,21 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* [ Initialisation is based on Linus' ]
* [ uhci code and gregs ohci fragments ]
* [ (C) Copyright 1999 Linus Torvalds ]
* [ (C) Copyright 1999 Gregory P. Smith]
- *
- *
+ *
+ *
* OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller
* interfaces (though some non-x86 Intel chips use it). It supports
* smarter hardware than UHCI. A download link for the spec available
* through the http://www.usb.org website.
*
- * History:
- *
- * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
- * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
- * 2003/02/24 show registers in sysfs (Kevin Brosius)
- *
- * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
- * bandwidth accounting; if debugging, show schedules in driverfs
- * 2002/07/19 fixes to management of ED and schedule state.
- * 2002/06/09 SA-1111 support (Christopher Hoover)
- * 2002/06/01 remember frame when HC won't see EDs any more; use that info
- * to fix urb unlink races caused by interrupt latency assumptions;
- * minor ED field and function naming updates
- * 2002/01/18 package as a patch for 2.5.3; this should match the
- * 2.4.17 kernel modulo some bugs being fixed.
- *
- * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes
- * from post-2.4.5 patches.
- * 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning
- * 2001/09/07 match PCI PM changes, errnos from Linus' tree
- * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify;
- * pbook pci quirks gone (please fix pbook pci sw!) (db)
- *
- * 2001/04/08 Identify version on module load (gb)
- * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
- pci_map_single (db)
- * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
- * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
- *
- * 2000/09/26 fixed races in removing the private portion of the urb
- * 2000/09/07 disable bulk and control lists when unlinking the last
- * endpoint descriptor in order to avoid unrecoverable errors on
- * the Lucent chips. (rwc@sgi)
- * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
- * urb unlink probs, indentation fixes
- * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
- * device unplugs.
- * 2000/06/28 use PCI hotplug framework, for better power management
- * and for Cardbus support (David Brownell)
- * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling
- * when the controller loses power; handle UE; cleanup; ...
- *
- * v5.2 1999/12/07 URB 3rd preview,
- * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
- * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume
- * i386: HUB, Keyboard, Mouse, Printer
- *
- * v4.3 1999/10/27 multiple HCs, bulk_request
- * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
- * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
- * v4.0 1999/08/18
- * v3.0 1999/06/25
- * v2.1 1999/05/09 code clean up
- * v2.0 1999/05/04
- * v1.0 1999/04/27 initial release
- *
* This file is licenced under the GPL.
*/
-
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
@@ -89,7 +33,7 @@
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/usb/otg.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/reboot.h>
@@ -183,11 +127,11 @@ static int ohci_urb_enqueue (
int i, size = 0;
unsigned long flags;
int retval = 0;
-
+
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "SUB", usb_pipein (pipe));
#endif
-
+
/* every endpoint has a ed, locate and maybe (re)initialize it */
if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval)))
return -ENOMEM;
@@ -232,7 +176,7 @@ static int ohci_urb_enqueue (
memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
INIT_LIST_HEAD (&urb_priv->pending);
urb_priv->length = size;
- urb_priv->ed = ed;
+ urb_priv->ed = ed;
/* allocate the TDs (deferring hash chain updates) */
for (i = 0; i < size; i++) {
@@ -242,7 +186,7 @@ static int ohci_urb_enqueue (
urb_free_priv (ohci, urb_priv);
return -ENOMEM;
}
- }
+ }
spin_lock_irqsave (&ohci->lock, flags);
@@ -313,13 +257,13 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
unsigned long flags;
-
+
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "UNLINK", 1);
-#endif
+#endif
spin_lock_irqsave (&ohci->lock, flags);
- if (HC_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
@@ -512,11 +456,11 @@ static int ohci_init (struct ohci_hcd *ohci)
/* Start an OHCI controller, set the BUS operational
* resets USB and controller
- * enable interrupts
+ * enable interrupts
*/
static int ohci_run (struct ohci_hcd *ohci)
{
- u32 mask, temp;
+ u32 mask, temp;
int first = ohci->fminterval == 0;
struct usb_hcd *hcd = ohci_to_hcd(ohci);
@@ -534,7 +478,7 @@ static int ohci_run (struct ohci_hcd *ohci)
/* also: power/overcurrent flags in roothub.a */
}
- /* Reset USB nearly "by the book". RemoteWakeupConnected was
+ /* Reset USB nearly "by the book". RemoteWakeupConnected was
* saved if boot firmware (BIOS/SMM/...) told us it's connected,
* or if bus glue did the same (e.g. for PCI add-in cards with
* PCI PM support).
@@ -765,9 +709,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
dl_done_list (ohci);
spin_unlock (&ohci->lock);
if (HC_IS_RUNNING(hcd->state))
- ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
+ ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
}
-
+
/* could track INTR_SO to reduce available PCI/... bandwidth */
/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
@@ -778,12 +722,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
finish_unlinks (ohci, ohci_frame_no(ohci));
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
&& HC_IS_RUNNING(hcd->state))
- ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
+ ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
if (HC_IS_RUNNING(hcd->state)) {
ohci_writel (ohci, ints, &regs->intrstatus);
- ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
+ ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);
}
@@ -794,7 +738,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
static void ohci_stop (struct usb_hcd *hcd)
-{
+{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n",
@@ -812,8 +756,8 @@ static void ohci_stop (struct usb_hcd *hcd)
remove_debug_files (ohci);
ohci_mem_cleanup (ohci);
if (ohci->hcca) {
- dma_free_coherent (hcd->self.controller,
- sizeof *ohci->hcca,
+ dma_free_coherent (hcd->self.controller,
+ sizeof *ohci->hcca,
ohci->hcca, ohci->hcca_dma);
ohci->hcca = NULL;
ohci->hcca_dma = 0;
@@ -836,7 +780,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
* recycle any "live" eds/tds (and urbs) right away.
* later, khubd disconnect processing will recycle the other state,
* (either as disconnect/reconnect, or maybe someday as a reset).
- */
+ */
spin_lock_irq(&ohci->lock);
disable (ohci);
usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
@@ -875,11 +819,11 @@ static int ohci_restart (struct ohci_hcd *ohci)
/* empty the interrupt branches */
for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
-
+
/* no EDs to remove */
ohci->ed_rm_list = NULL;
- /* empty control and bulk lists */
+ /* empty control and bulk lists */
ohci->ed_controltail = NULL;
ohci->ed_bulktail = NULL;
@@ -941,6 +885,10 @@ MODULE_LICENSE ("GPL");
#include "ohci-au1xxx.c"
#endif
+#ifdef CONFIG_PNX8550
+#include "ohci-pnx8550.c"
+#endif
+
#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
#include "ohci-ppc-soc.c"
#endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 2441642cb7b..216c9c9d4d6 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -1,9 +1,9 @@
/*
* 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>
- *
+ *
* This file is licenced under GPL
*/
@@ -23,13 +23,13 @@
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
- \
+ \
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
- \
+ \
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
@@ -484,7 +484,7 @@ ohci_hub_descriptor (
temp = 0;
if (rh & RH_A_NPS) /* no power switching? */
temp |= 0x0002;
- if (rh & RH_A_PSM) /* per-port power switching? */
+ if (rh & RH_A_PSM) /* per-port power switching? */
temp |= 0x0001;
if (rh & RH_A_NOCP) /* no overcurrent reporting? */
temp |= 0x0010;
@@ -555,7 +555,7 @@ static void start_hnp(struct ohci_hcd *ohci);
#define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
/* called from some task, normally khubd */
-static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
+static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
@@ -570,10 +570,13 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
/* spin until any current reset finishes */
for (;;) {
temp = ohci_readl (ohci, portstat);
+ /* handle e.g. CardBus eject */
+ if (temp == ~(u32)0)
+ return -ESHUTDOWN;
if (!(temp & RH_PS_PRS))
break;
udelay (500);
- }
+ }
if (!(temp & RH_PS_CCS))
break;
@@ -586,6 +589,8 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
now = ohci_readl(ohci, &ohci->regs->fmnumber);
} while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */
+
+ return 0;
}
static int ohci_hub_control (
@@ -702,7 +707,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_RESET:
- root_port_reset (ohci, wIndex);
+ retval = root_port_reset (ohci, wIndex);
break;
default:
goto error;
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index e121d97ed91..e9807cf73a2 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -38,7 +38,7 @@ static void lh7a404_start_hc(struct platform_device *dev)
CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
udelay(1000);
USBH_CMDSTATUS = OHCI_HCR;
-
+
printk(KERN_DEBUG __FILE__
": Clock to USB host has been enabled \n");
}
@@ -89,7 +89,7 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
retval = -EBUSY;
goto err1;
}
-
+
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
pr_debug("ioremap failed");
@@ -174,7 +174,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
*/
.start = ohci_lh7a404_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -242,7 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_lh7a404_driver = {
.probe = ohci_hcd_lh7a404_drv_probe,
.remove = ohci_hcd_lh7a404_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_lh7a404_drv_suspend, */
/*.resume = ohci_hcd_lh7a404_drv_resume, */
.driver = {
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index d976614eebd..2f20d3dc895 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -1,24 +1,24 @@
/*
* 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>
- *
+ *
* This file is licenced under the GPL.
*/
/*-------------------------------------------------------------------------*/
/*
- * There's basically three types of memory:
+ * OHCI deals with three types of memory:
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use dma_pool or dma_alloc_coherent
* - driver buffers, read/written by HC ... the hcd glue or the
* device driver provides us with dma addresses
*
- * There's also PCI "register" data, which is memory mapped.
- * No memory seen by this driver is pagable.
+ * There's also "register" data, which is memory mapped.
+ * No memory seen by this driver (or any HCD) may be paged out.
*/
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 9c02177de50..27be1f93688 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -447,7 +447,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
.reset = ohci_omap_init,
.start = ohci_omap_start,
.stop = ohci_omap_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -533,7 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_omap_driver = {
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
.resume = ohci_omap_resume,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 87441855278..596e0b41e60 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -3,17 +3,17 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* [ Initialisation is based on Linus' ]
* [ uhci code and gregs ohci fragments ]
* [ (C) Copyright 1999 Linus Torvalds ]
* [ (C) Copyright 1999 Gregory P. Smith]
- *
+ *
* PCI Bus Glue
*
* This file is licenced under the GPL.
*/
-
+
#ifndef CONFIG_PCI
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
#endif
@@ -83,7 +83,7 @@ ohci_pci_start (struct usb_hcd *hcd)
pci_dev_put(b);
}
- /* Check for Compaq's ZFMicro chipset, which needs short
+ /* Check for Compaq's ZFMicro chipset, which needs short
* delays before control or bulk queues get re-activated
* in finish_unlinks()
*/
@@ -238,8 +238,8 @@ static struct pci_driver ohci_pci_driver = {
.shutdown = usb_hcd_pci_shutdown,
};
-
-static int __init ohci_hcd_pci_init (void)
+
+static int __init ohci_hcd_pci_init (void)
{
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
if (usb_disabled())
@@ -253,8 +253,8 @@ module_init (ohci_hcd_pci_init);
/*-------------------------------------------------------------------------*/
-static void __exit ohci_hcd_pci_cleanup (void)
-{
+static void __exit ohci_hcd_pci_cleanup (void)
+{
pci_unregister_driver (&ohci_pci_driver);
}
module_exit (ohci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 7f26f9bdbaf..3a8cbfb6905 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -4,7 +4,7 @@
* driver for Philips PNX4008 USB Host
*
* Authors: Dmitry Chigirev <source@mvista.com>
- * Vitaly Wool <vitalywool@gmail.com>
+ * Vitaly Wool <vitalywool@gmail.com>
*
* register initialization is based on code examples provided by Philips
* Copyright (c) 2005 Koninklijke Philips Electronics N.V.
@@ -29,7 +29,7 @@
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
-#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
+#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
/* USB_CTRL bit defines */
#define USB_SLAVE_HCLK_EN (1 << 24)
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
new file mode 100644
index 00000000000..6922b91b170
--- /dev/null
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -0,0 +1,258 @@
+/*
+ * 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 2005 Embedded Alley Solutions, Inc.
+ *
+ * Bus Glue for PNX8550
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ * Based on fragments of previous driver by Russell King et al.
+ *
+ * Modified for LH7A404 from ohci-sa1111.c
+ * by Durgesh Pattamatta <pattamattad@sharpsec.com>
+ *
+ * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
+ * by Vitaly Wool <vitalywool@gmail.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/mach-pnx8550/usb.h>
+#include <asm/mach-pnx8550/int.h>
+#include <asm/mach-pnx8550/pci.h>
+
+#ifndef CONFIG_PNX8550
+#error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined."
+#endif
+
+extern int usb_disabled(void);
+
+/*-------------------------------------------------------------------------*/
+
+static void pnx8550_start_hc(struct platform_device *dev)
+{
+ /*
+ * Set register CLK48CTL to enable and 48MHz
+ */
+ outl(0x00000003, PCI_BASE | 0x0004770c);
+
+ /*
+ * Set register CLK12CTL to enable and 48MHz
+ */
+ outl(0x00000003, PCI_BASE | 0x00047710);
+
+ udelay(100);
+}
+
+static void pnx8550_stop_hc(struct platform_device *dev)
+{
+ udelay(10);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+
+/**
+ * usb_hcd_pnx8550_probe - initialize pnx8550-based 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.
+ *
+ */
+int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
+ struct platform_device *dev)
+{
+ int retval;
+ struct usb_hcd *hcd;
+
+ if (dev->resource[0].flags != IORESOURCE_MEM ||
+ dev->resource[1].flags != IORESOURCE_IRQ) {
+ dev_err (&dev->dev,"invalid resource type\n");
+ return -ENOMEM;
+ }
+
+ hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
+ 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)) {
+ dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
+ "failed\n", hcd->rsrc_start, hcd->rsrc_len);
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
+ hcd->rsrc_start, hcd->rsrc_len);
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ pnx8550_start_hc(dev);
+
+ ohci_hcd_init(hcd_to_ohci(hcd));
+
+ retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ if (retval == 0)
+ return retval;
+
+ pnx8550_stop_hc(dev);
+ 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_pnx8550_remove - shutdown processing for pnx8550-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
+ * the HCD's stop() method. It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
+{
+ usb_remove_hcd(hcd);
+ pnx8550_stop_hc(dev);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit
+ohci_pnx8550_start (struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret;
+
+ ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
+
+ if ((ret = ohci_init(ohci)) < 0)
+ return ret;
+
+ if ((ret = ohci_run (ohci)) < 0) {
+ err ("can't start %s", hcd->self.bus_name);
+ ohci_stop (hcd);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_pnx8550_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "PNX8550 OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ohci_irq,
+ .flags = HCD_USB11 | HCD_MEMORY,
+
+ /*
+ * basic lifecycle operations
+ */
+ .start = ohci_pnx8550_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,
+ .hub_irq_enable = ohci_rhsc_enable,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
+ return ret;
+}
+
+static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_hcd_pnx8550_remove(hcd, pdev);
+ return 0;
+}
+
+MODULE_ALIAS("pnx8550-ohci");
+
+static struct platform_driver ohci_hcd_pnx8550_driver = {
+ .driver = {
+ .name = "pnx8550-ohci",
+ },
+ .probe = ohci_hcd_pnx8550_drv_probe,
+ .remove = ohci_hcd_pnx8550_drv_remove,
+};
+
+static int __init ohci_hcd_pnx8550_init (void)
+{
+ pr_debug (DRIVER_INFO " (pnx8550)");
+ pr_debug ("block sizes: ed %d td %d\n",
+ sizeof (struct ed), sizeof (struct td));
+
+ return platform_driver_register(&ohci_hcd_pnx8550_driver);
+}
+
+static void __exit ohci_hcd_pnx8550_cleanup (void)
+{
+ platform_driver_unregister(&ohci_hcd_pnx8550_driver);
+}
+
+module_init (ohci_hcd_pnx8550_init);
+module_exit (ohci_hcd_pnx8550_cleanup);
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index d9d1ae236bd..e1a7eb81731 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -5,7 +5,7 @@
* (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
*
@@ -85,7 +85,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
- usb_put_hcd(hcd);
+ usb_put_hcd(hcd);
return retval;
}
@@ -148,7 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
*/
.start = ohci_ppc_soc_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -197,7 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_ppc_soc_driver = {
.probe = ohci_hcd_ppc_soc_drv_probe,
.remove = ohci_hcd_ppc_soc_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
/*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
/*.resume = ohci_hcd_ppc_soc_drv_resume,*/
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e176b04d7ae..3bbea844a9e 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -47,7 +47,7 @@ static int pxa27x_ohci_select_pmm( int mode )
switch ( mode ) {
case PMM_NPS_MODE:
UHCRHDA |= RH_A_NPS;
- break;
+ break;
case PMM_GLOBAL_MODE:
UHCRHDA &= ~(RH_A_NPS & RH_A_PSM);
break;
@@ -60,7 +60,7 @@ static int pxa27x_ohci_select_pmm( int mode )
break;
default:
printk( KERN_ERR
- "Invalid mode %d, set to non-power switch mode.\n",
+ "Invalid mode %d, set to non-power switch mode.\n",
mode );
UHCRHDA |= RH_A_NPS;
@@ -270,7 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
*/
.start = ohci_pxa27x_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -359,9 +359,9 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
- .suspend = ohci_hcd_pxa27x_drv_suspend,
+ .suspend = ohci_hcd_pxa27x_drv_suspend,
.resume = ohci_hcd_pxa27x_drv_resume,
#endif
.driver = {
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index fe1fe2f97cb..830a3fe8615 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -1,9 +1,9 @@
/*
* 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>
- *
+ *
* This file is licenced under the GPL.
*/
@@ -89,7 +89,7 @@ __acquires(ohci->lock)
/*-------------------------------------------------------------------------*
* ED handling functions
- *-------------------------------------------------------------------------*/
+ *-------------------------------------------------------------------------*/
/* search for the right schedule branch to use for a periodic ed.
* does some load balancing; returns the branch, or negative errno.
@@ -107,7 +107,6 @@ static int balance (struct ohci_hcd *ohci, int interval, int load)
*/
for (i = 0; i < interval ; i++) {
if (branch < 0 || ohci->load [branch] > ohci->load [i]) {
-#if 1 /* CONFIG_USB_BANDWIDTH */
int j;
/* usb 1.1 says 90% of one frame */
@@ -117,8 +116,7 @@ static int balance (struct ohci_hcd *ohci, int interval, int load)
}
if (j < NUM_INTS)
continue;
-#endif
- branch = i;
+ branch = i;
}
}
return branch;
@@ -171,7 +169,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
/* link an ed into one of the HC chains */
static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
-{
+{
int branch;
if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
@@ -248,7 +246,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
}
ed->branch = branch;
periodic_link (ohci, ed);
- }
+ }
/* the HC may not see the schedule updates yet, but if it does
* then they'll be properly ordered.
@@ -277,7 +275,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
*prev = ed->ed_next;
}
ohci->load [i] -= ed->load;
- }
+ }
ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval;
ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
@@ -285,7 +283,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
ed, ed->branch, ed->load, ed->interval);
}
-/* unlink an ed from one of the HC chains.
+/* unlink an ed from one of the HC chains.
* just the link to the ed is unlinked.
* the link from the ed still points to another operational ed or 0
* so the HC can eventually finish the processing of the unlinked ed
@@ -307,7 +305,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
* When finish_unlinks() runs later, after SOF interrupt, it will often
* complete one or more URB unlinks before making that state change.
*/
-static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
+static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
{
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
@@ -397,7 +395,7 @@ static struct ed *ed_get (
unsigned int pipe,
int interval
) {
- struct ed *ed;
+ struct ed *ed;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@@ -413,9 +411,9 @@ static struct ed *ed_get (
goto done;
}
- /* dummy td; end of td list for ed */
+ /* dummy td; end of td list for ed */
td = td_alloc (ohci, GFP_ATOMIC);
- if (!td) {
+ if (!td) {
/* out of memory */
ed_free (ohci, ed);
ed = NULL;
@@ -462,7 +460,7 @@ static struct ed *ed_get (
done:
spin_unlock_irqrestore (&ohci->lock, flags);
- return ed;
+ return ed;
}
/*-------------------------------------------------------------------------*/
@@ -474,7 +472,7 @@ done:
* and that ed->state is ED_OPER
*/
static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
-{
+{
ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE);
ed_deschedule (ohci, ed);
@@ -541,7 +539,7 @@ td_fill (struct ohci_hcd *ohci, u32 info,
td->ed = urb_priv->ed;
td->next_dl_td = NULL;
td->index = index;
- td->urb = urb;
+ td->urb = urb;
td->data_dma = data;
if (!len)
data = 0;
@@ -553,8 +551,8 @@ td_fill (struct ohci_hcd *ohci, u32 info,
(data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff;
} else {
- td->hwCBP = cpu_to_hc32 (ohci, data);
- }
+ td->hwCBP = cpu_to_hc32 (ohci, data);
+ }
if (data)
td->hwBE = cpu_to_hc32 (ohci, data + len - 1);
else
@@ -597,7 +595,7 @@ static void td_submit_urb (
* use the device toggle bits for resetting, and rely on the fact
* that resetting toggle is meaningless if the endpoint is active.
*/
- if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
+ if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
is_out, 1);
urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
@@ -721,16 +719,16 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
list_del (&td->td_list);
/* ISO ... drivers see per-TD length/status */
- if (tdINFO & TD_ISO) {
- u16 tdPSW = ohci_hwPSW (ohci, td, 0);
+ if (tdINFO & TD_ISO) {
+ u16 tdPSW = ohci_hwPSW (ohci, td, 0);
int dlen = 0;
/* 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? */
+ cc = (tdPSW >> 12) & 0xF;
+ if (tdINFO & TD_CC) /* hc didn't touch? */
return;
if (usb_pipeout (urb->pipe))
@@ -758,7 +756,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
int type = usb_pipetype (urb->pipe);
u32 tdBE = hc32_to_cpup (ohci, &td->hwBE);
- cc = TD_CC_GET (tdINFO);
+ cc = TD_CC_GET (tdINFO);
/* update packet status if needed (short is normally ok) */
if (cc == TD_DATAUNDERRUN
@@ -787,7 +785,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
urb, td, 1 + td->index, cc,
urb->actual_length,
urb->transfer_buffer_length);
- }
+ }
}
/*-------------------------------------------------------------------------*/
@@ -795,7 +793,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
static inline struct td *
ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
{
- struct urb *urb = td->urb;
+ struct urb *urb = td->urb;
struct ed *ed = td->ed;
struct list_head *tmp = td->td_list.next;
__hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C);
@@ -805,7 +803,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
*/
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
- ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
+ ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
/* put any later tds from this urb onto the donelist, after 'td',
* order won't matter here: no errors, and nothing was transferred.
@@ -833,7 +831,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
info &= ~cpu_to_hc32 (ohci, TD_CC);
next->hwINFO = info;
- next->next_dl_td = rev;
+ next->next_dl_td = rev;
rev = next;
ed->hwHeadP = next->hwNextTD | toggle;
@@ -881,8 +879,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
/* get TD from hc's singly linked list, and
* prepend to ours. ed->td_list changes later.
*/
- while (td_dma) {
- int cc;
+ while (td_dma) {
+ int cc;
td = dma_to_td (ohci, td_dma);
if (!td) {
@@ -901,10 +899,10 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
&& (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
td_rev = ed_halted (ohci, td, cc, td_rev);
- td->next_dl_td = td_rev;
+ td->next_dl_td = td_rev;
td_rev = td;
td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
- }
+ }
return td_rev;
}
@@ -1013,9 +1011,9 @@ rescan_this:
if (modified)
goto rescan_all;
- }
+ }
- /* maybe reenable control and bulk lists */
+ /* maybe reenable control and bulk lists */
if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
&& ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
&& !ohci->ed_rm_list) {
@@ -1041,20 +1039,20 @@ rescan_this:
&ohci->regs->ed_bulkcurrent);
}
}
-
+
/* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
if (control) {
ohci->hc_control |= control;
if (ohci->flags & OHCI_QUIRK_ZFMICRO)
mdelay(1);
- ohci_writel (ohci, ohci->hc_control,
- &ohci->regs->control);
- }
+ ohci_writel (ohci, ohci->hc_control,
+ &ohci->regs->control);
+ }
if (command) {
if (ohci->flags & OHCI_QUIRK_ZFMICRO)
mdelay(1);
- ohci_writel (ohci, command, &ohci->regs->cmdstatus);
- }
+ ohci_writel (ohci, command, &ohci->regs->cmdstatus);
+ }
}
}
@@ -1074,19 +1072,19 @@ dl_done_list (struct ohci_hcd *ohci)
{
struct td *td = dl_reverse_done_list (ohci);
- while (td) {
+ while (td) {
struct td *td_next = td->next_dl_td;
struct urb *urb = td->urb;
urb_priv_t *urb_priv = urb->hcpriv;
struct ed *ed = td->ed;
/* update URB's length and status from TD */
- td_done (ohci, urb, td);
- urb_priv->td_cnt++;
+ td_done (ohci, urb, td);
+ urb_priv->td_cnt++;
/* If all this urb's TDs are done, call complete() */
- if (urb_priv->td_cnt == urb_priv->length)
- finish_urb (ohci, urb);
+ if (urb_priv->td_cnt == urb_priv->length)
+ finish_urb (ohci, urb);
/* clean schedule: unlink EDs that are no longer busy */
if (list_empty (&ed->td_list)) {
@@ -1094,25 +1092,26 @@ dl_done_list (struct ohci_hcd *ohci)
start_ed_unlink (ohci, ed);
/* ... reenabling halted EDs only after fault cleanup */
- } else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
+ } else if ((ed->hwINFO & cpu_to_hc32 (ohci,
+ ED_SKIP | ED_DEQUEUE))
== cpu_to_hc32 (ohci, ED_SKIP)) {
td = list_entry (ed->td_list.next, struct td, td_list);
- if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
+ if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
/* ... hc may need waking-up */
switch (ed->type) {
case PIPE_CONTROL:
ohci_writel (ohci, OHCI_CLF,
- &ohci->regs->cmdstatus);
+ &ohci->regs->cmdstatus);
break;
case PIPE_BULK:
ohci_writel (ohci, OHCI_BLF,
- &ohci->regs->cmdstatus);
+ &ohci->regs->cmdstatus);
break;
}
}
}
- td = td_next;
- }
+ td = td_next;
+ }
}
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 59e436424d4..b350d45033e 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -447,7 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
*/
.start = ohci_s3c2410_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -492,7 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,
.remove = ohci_hcd_s3c2410_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_s3c2410_drv_suspend, */
/*.resume = ohci_hcd_s3c2410_drv_resume, */
.driver = {
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 71371de32ad..fe0090e3367 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -4,7 +4,7 @@
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
- *
+ *
* SA1111 Bus Glue
*
* Written by Christopher Hoover <ch@hpl.hp.com>
@@ -12,7 +12,7 @@
*
* This file is licenced under the GPL.
*/
-
+
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/assabet.h>
@@ -31,7 +31,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst = 0;
- printk(KERN_DEBUG __FILE__
+ printk(KERN_DEBUG __FILE__
": starting SA-1111 OHCI USB Controller\n");
#ifdef CONFIG_SA1100_BADGE4
@@ -65,7 +65,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
static void sa1111_stop_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst;
- printk(KERN_DEBUG __FILE__
+ printk(KERN_DEBUG __FILE__
": stopping SA-1111 OHCI USB Controller\n");
/*
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index a2f42a2f47c..405257f3e85 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -1,9 +1,9 @@
/*
* 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>
- *
+ *
* This file is licenced under the GPL.
*/
@@ -14,7 +14,7 @@
*/
typedef __u32 __bitwise __hc32;
typedef __u16 __bitwise __hc16;
-
+
/*
* OHCI Endpoint Descriptor (ED) ... holds TD queue
* See OHCI spec, section 4.2
@@ -24,7 +24,7 @@ typedef __u16 __bitwise __hc16;
*/
struct ed {
/* first fields are hardware-specified */
- __hc32 hwINFO; /* endpoint config bitmap */
+ __hc32 hwINFO; /* endpoint config bitmap */
/* info bits defined by hcd */
#define ED_DEQUEUE (1 << 27)
/* info bits defined by the hardware */
@@ -52,11 +52,11 @@ struct ed {
* usually: OPER --> UNLINK --> (IDLE | OPER) --> ...
*/
u8 state; /* ED_{IDLE,UNLINK,OPER} */
-#define ED_IDLE 0x00 /* NOT linked to HC */
-#define ED_UNLINK 0x01 /* being unlinked from hc */
+#define ED_IDLE 0x00 /* NOT linked to HC */
+#define ED_UNLINK 0x01 /* being unlinked from hc */
#define ED_OPER 0x02 /* IS linked to hc */
- u8 type; /* PIPE_{BULK,...} */
+ u8 type; /* PIPE_{BULK,...} */
/* periodic scheduling params (for intr and iso) */
u8 branch;
@@ -70,7 +70,7 @@ struct ed {
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
-
+
/*
* OHCI Transfer Descriptor (TD) ... one per transfer segment
* See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
@@ -107,22 +107,22 @@ struct td {
/* (no hwINFO #defines yet for iso tds) */
- __hc32 hwCBP; /* Current Buffer Pointer (or 0) */
- __hc32 hwNextTD; /* Next TD Pointer */
- __hc32 hwBE; /* Memory Buffer End Pointer */
+ __hc32 hwCBP; /* Current Buffer Pointer (or 0) */
+ __hc32 hwNextTD; /* Next TD Pointer */
+ __hc32 hwBE; /* Memory Buffer End Pointer */
/* 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];
+ __hc16 hwPSW [MAXPSW];
/* rest are purely for the driver's use */
- __u8 index;
- struct ed *ed;
- struct td *td_hash; /* dma-->td hashtable */
- struct td *next_dl_td;
- struct urb *urb;
+ __u8 index;
+ struct ed *ed;
+ struct td *td_hash; /* dma-->td hashtable */
+ struct td *next_dl_td;
+ struct urb *urb;
dma_addr_t td_dma; /* addr of this TD */
dma_addr_t data_dma; /* addr of data it points to */
@@ -152,8 +152,8 @@ struct td {
#define TD_NOTACCESSED 0x0F
-/* map OHCI TD status codes (CC) to errno values */
-static const int cc_to_error [16] = {
+/* map OHCI TD status codes (CC) to errno values */
+static const int cc_to_error [16] = {
/* No Error */ 0,
/* CRC Error */ -EILSEQ,
/* Bit Stuff */ -EPROTO,
@@ -169,7 +169,7 @@ static const int cc_to_error [16] = {
/* BufferOver */ -ECOMM,
/* BuffUnder */ -ENOSR,
/* (for HCD) */ -EALREADY,
- /* (for HCD) */ -EALREADY
+ /* (for HCD) */ -EALREADY
};
@@ -182,7 +182,7 @@ struct ohci_hcca {
#define NUM_INTS 32
__hc32 int_table [NUM_INTS]; /* periodic schedule */
- /*
+ /*
* 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 bits wide.
@@ -262,10 +262,10 @@ struct ohci_regs {
* HcCommandStatus (cmdstatus) register masks
*/
#define OHCI_HCR (1 << 0) /* host controller reset */
-#define OHCI_CLF (1 << 1) /* control list filled */
-#define OHCI_BLF (1 << 2) /* bulk list filled */
-#define OHCI_OCR (1 << 3) /* ownership change request */
-#define OHCI_SOC (3 << 16) /* scheduling overrun count */
+#define OHCI_CLF (1 << 1) /* control list filled */
+#define OHCI_BLF (1 << 2) /* bulk list filled */
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_SOC (3 << 16) /* scheduling overrun count */
/*
* masks used with interrupt registers:
@@ -285,20 +285,20 @@ struct ohci_regs {
/* OHCI ROOT HUB REGISTER MASKS */
-
+
/* roothub.portstatus [i] bits */
-#define RH_PS_CCS 0x00000001 /* current connect status */
-#define RH_PS_PES 0x00000002 /* port enable status*/
-#define RH_PS_PSS 0x00000004 /* port suspend status */
-#define RH_PS_POCI 0x00000008 /* port over current indicator */
-#define RH_PS_PRS 0x00000010 /* port reset status */
-#define RH_PS_PPS 0x00000100 /* port power status */
-#define RH_PS_LSDA 0x00000200 /* low speed device attached */
-#define RH_PS_CSC 0x00010000 /* connect status change */
-#define RH_PS_PESC 0x00020000 /* port enable status change */
-#define RH_PS_PSSC 0x00040000 /* port suspend status change */
-#define RH_PS_OCIC 0x00080000 /* over current indicator change */
-#define RH_PS_PRSC 0x00100000 /* port reset status change */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status*/
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
/* roothub.status bits */
#define RH_HS_LPS 0x00000001 /* local power status */
@@ -333,7 +333,7 @@ typedef struct urb_priv {
} urb_priv_t;
#define TD_HASH_SIZE 64 /* power'o'two */
-// sizeof (struct td) ~= 64 == 2^6 ...
+// sizeof (struct td) ~= 64 == 2^6 ...
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
@@ -364,11 +364,11 @@ struct ohci_hcd {
struct ed *ed_bulktail; /* last in bulk list */
struct ed *ed_controltail; /* last in ctrl list */
- struct ed *periodic [NUM_INTS]; /* shadow int_table */
+ struct ed *periodic [NUM_INTS]; /* shadow int_table */
/*
* OTG controllers and transceivers need software interaction;
- * other external transceivers should be software-transparent
+ * other external transceivers should be software-transparent
*/
struct otg_transceiver *transceiver;
@@ -385,7 +385,7 @@ struct ohci_hcd {
*/
int num_ports;
int load [NUM_INTS];
- u32 hc_control; /* copy of hc control reg */
+ u32 hc_control; /* copy of hc control reg */
unsigned long next_statechange; /* suspend/resume */
u32 fminterval; /* saved register */
unsigned autostop:1; /* rh auto stopping/stopped */
@@ -598,11 +598,11 @@ static inline void disable (struct ohci_hcd *ohci)
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
-#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
+#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
#define FIT (1 << 31)
#define LSTHRESH 0x628 /* lowspeed bit threshold */
-static void periodic_reinit (struct ohci_hcd *ohci)
+static inline void periodic_reinit (struct ohci_hcd *ohci)
{
u32 fi = ohci->fminterval & 0x03fff;
u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT;
@@ -626,11 +626,11 @@ static void periodic_reinit (struct ohci_hcd *ohci)
temp = ohci_readl (hc, &hc->regs->roothub.register); \
temp; })
-static u32 roothub_a (struct ohci_hcd *hc)
+static inline u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); }
static inline u32 roothub_b (struct ohci_hcd *hc)
{ return ohci_readl (hc, &hc->regs->roothub.b); }
static inline u32 roothub_status (struct ohci_hcd *hc)
{ return ohci_readl (hc, &hc->regs->roothub.status); }
-static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
+static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i)
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index a9d7119e317..a7fa0d75567 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -40,6 +40,7 @@
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/pci_ids.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
@@ -210,15 +211,16 @@ struct u132 {
* these cannot be inlines because we need the structure offset!!
* Does anyone have a better way?????
*/
+#define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
+ offsetof(struct ohci_regs, member), 0, data);
+#define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
+ offsetof(struct ohci_regs, member), 0, data);
#define u132_read_pcimem(u132, member, data) \
usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0, data);
#define u132_write_pcimem(u132, member, data) \
usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0, data);
-#define u132_write_pcimem_byte(u132, member, data) \
- usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
- ohci_regs, member), 0x0e, data);
static inline struct u132 *udev_to_u132(struct u132_udev *udev)
{
u8 udev_number = udev->udev_number;
@@ -1574,59 +1576,12 @@ static char *hcfs2string(int state)
return "?";
}
-static int u132_usb_reset(struct u132 *u132)
-{
- int retval;
- retval = u132_read_pcimem(u132, control, &u132->hc_control);
- if (retval)
- return retval;
- u132->hc_control &= OHCI_CTRL_RWC;
- retval = u132_write_pcimem(u132, control, u132->hc_control);
- if (retval)
- return retval;
- return 0;
-}
-
static int u132_init(struct u132 *u132)
{
int retval;
u32 control;
u132_disable(u132);
- u132->next_statechange =
- jiffies; /* SMM owns the HC? not for long! */ {
- u32 control;
- retval = u132_read_pcimem(u132, control, &control);
- if (retval)
- return retval;
- if (control & OHCI_CTRL_IR) {
- u32 temp = 50;
- retval = u132_write_pcimem(u132, intrenable,
- OHCI_INTR_OC);
- if (retval)
- return retval;
- retval = u132_write_pcimem_byte(u132, cmdstatus,
- OHCI_OCR);
- if (retval)
- return retval;
- check:{
- retval = u132_read_pcimem(u132, control,
- &control);
- if (retval)
- return retval;
- }
- if (control & OHCI_CTRL_IR) {
- msleep(10);
- if (--temp == 0) {
- dev_err(&u132->platform_dev->dev, "USB "
- "HC takeover failed!(BIOS/SMM b"
- "ug) control=%08X\n", control);
- return -EBUSY;
- }
- goto check;
- }
- u132_usb_reset(u132);
- }
- }
+ u132->next_statechange = jiffies;
retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
if (retval)
return retval;
@@ -1725,7 +1680,7 @@ static int u132_run(struct u132 *u132)
retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
if (retval)
return retval;
- retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR);
+ retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
if (retval)
return retval;
extra:{
@@ -1782,7 +1737,7 @@ static int u132_run(struct u132 *u132)
retval = u132_write_pcimem(u132, control, u132->hc_control);
if (retval)
return retval;
- retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF);
+ retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
if (retval)
return retval;
retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
@@ -1839,8 +1794,8 @@ static void u132_hcd_stop(struct usb_hcd *hcd)
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 1) {
- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
- , u132->going);
+ dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
+ "een removed %d\n", u132, hcd, u132->going);
} else if (u132->going > 0) {
dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
"ed\n", hcd);
@@ -2545,8 +2500,9 @@ static void u132_endpoint_disable(struct usb_hcd *hcd,
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 2) {
- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
- , u132->going);
+ dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
+ ") has been removed %d\n", u132, hcd, hep,
+ u132->going);
} else {
struct u132_endp *endp = hep->hcpriv;
if (endp)
@@ -2790,7 +2746,6 @@ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
} else if (u132->going > 0) {
dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
"ed\n", hcd);
- dump_stack();
return -ESHUTDOWN;
} else {
int i, changed = 0, length = 1;
@@ -3034,12 +2989,15 @@ static int __devexit u132_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
if (hcd) {
struct u132 *u132 = hcd_to_u132(hcd);
- dump_stack();
if (u132->going++ > 1) {
+ dev_err(&u132->platform_dev->dev, "already being remove"
+ "d\n");
return -ENODEV;
} else {
int rings = MAX_U132_RINGS;
int endps = MAX_U132_ENDPS;
+ dev_err(&u132->platform_dev->dev, "removing device u132"
+ ".%d\n", u132->sequence_num);
msleep(100);
down(&u132->sw_lock);
u132_monitor_cancel_work(u132);
@@ -3121,10 +3079,24 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
static int __devinit u132_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
+ int retval;
+ u32 control;
+ u32 rh_a = -1;
+ u32 num_ports;
msleep(100);
if (u132_exiting > 0) {
return -ENODEV;
- } /* refuse to confuse usbcore */
+ }
+ retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(pdev, control, &control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
+ if (retval)
+ return retval;
+ num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
if (pdev->dev.dma_mask) {
return -EINVAL;
}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index e87692c31be..e0d4c2358b3 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
Alan Stern"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+/* for flakey hardware, ignore overcurrent indicators */
+static int ignore_oc;
+module_param(ignore_oc, bool, S_IRUGO);
+MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
+
/*
* debug = 0, no debugging messages
* debug = 1, dump failed URBs except for stalls
@@ -169,6 +174,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
{
int port;
+ /* If we have to ignore overcurrent events then almost by definition
+ * we can't depend on resume-detect interrupts. */
+ if (ignore_oc)
+ return 1;
+
switch (to_pci_dev(uhci_dev(uhci))->vendor) {
default:
break;
@@ -199,24 +209,16 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
{
- static struct dmi_system_id broken_wakeup_table[] = {
- {
- .ident = "Asus A7V8X",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
- DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
- DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
- }
- },
- { }
- };
int port;
+ char *sys_info;
+ static char bad_Asus_board[] = "A7V8X";
/* One of Asus's motherboards has a bug which causes it to
* wake up immediately from suspend-to-RAM if any of the ports
* are connected. In such cases we will not set EGSM.
*/
- if (dmi_check_system(broken_wakeup_table)) {
+ sys_info = dmi_get_system_info(DMI_BOARD_NAME);
+ if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
for (port = 0; port < uhci->rh_numports; ++port) {
if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
USBPORTSC_CCS)
@@ -255,7 +257,9 @@ __acquires(uhci->lock)
int_enable = USBINTR_RESUME;
if (remote_wakeup_is_broken(uhci))
egsm_enable = 0;
- if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable)
+ if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
+ !device_may_wakeup(
+ &uhci_to_hcd(uhci)->self.root_hub->dev))
uhci->working_RD = int_enable = 0;
outw(int_enable, uhci->io_addr + USBINTR);
@@ -921,7 +925,8 @@ static int __init uhci_hcd_init(void)
{
int retval = -ENOMEM;
- printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");
+ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
+ ignore_oc ? ", overcurrent ignored" : "");
if (usb_disabled())
return -ENODEV;
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index f8347f1a10b..bacc25c53ba 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -52,10 +52,20 @@ static int any_ports_active(struct uhci_hcd *uhci)
static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
{
int port;
+ int mask = RWC_BITS;
+
+ /* Some boards (both VIA and Intel apparently) report bogus
+ * overcurrent indications, causing massive log spam unless
+ * we completely ignore them. This doesn't seem to be a problem
+ * with the chipset so much as with the way it is connected on
+ * the motherboard; if the overcurrent input is left to float
+ * then it may constantly register false positives. */
+ if (ignore_oc)
+ mask &= ~USBPORTSC_OCC;
*buf = 0;
for (port = 0; port < uhci->rh_numports; ++port) {
- if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
+ if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
test_bit(port, &uhci->port_c_suspend))
*buf |= (1 << (port + 1));
}
@@ -263,7 +273,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortChange |= USB_PORT_STAT_C_CONNECTION;
if (status & USBPORTSC_PEC)
wPortChange |= USB_PORT_STAT_C_ENABLE;
- if (status & USBPORTSC_OCC)
+ if ((status & USBPORTSC_OCC) && !ignore_oc)
wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
if (test_bit(port, &uhci->port_c_suspend)) {
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 661af7aa623..c7d887540d8 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -6,14 +6,14 @@ comment "USB Input Devices"
config USB_HID
tristate "USB Human Interface Device (full HID) support"
- depends on USB
+ default y
+ depends on USB && INPUT
+ select HID
---help---
- Say Y here if you want full HID support to connect keyboards,
+ Say Y here if you want full HID support to connect USB keyboards,
mice, joysticks, graphic tablets, or any other HID based devices
- to your computer via USB. You also need to select HID Input layer
- support (below) if you want to use keyboards, mice, joysticks and
- the like ... as well as Uninterruptible Power Supply (UPS) and
- monitor control devices.
+ to your computer via USB, as well as Uninterruptible Power Supply
+ (UPS) and monitor control devices.
You can't use this driver and the HIDBP (Boot Protocol) keyboard
and mouse drivers at the same time. More information is available:
@@ -27,20 +27,10 @@ config USB_HID
comment "Input core support is needed for USB HID input layer or HIDBP support"
depends on USB_HID && INPUT=n
-config USB_HIDINPUT
- bool "HID input layer support"
- default y
- depends on INPUT && USB_HID
- help
- Say Y here if you want to use a USB keyboard, mouse or joystick,
- or any other HID input device.
-
- If unsure, say Y.
-
config USB_HIDINPUT_POWERBOOK
bool "Enable support for iBook/PowerBook special keys"
default n
- depends on USB_HIDINPUT
+ depends on USB_HID
help
Say Y here if you want support for the special keys (Fn, Numlock) on
Apple iBooks and PowerBooks.
@@ -49,7 +39,7 @@ config USB_HIDINPUT_POWERBOOK
config HID_FF
bool "Force feedback support (EXPERIMENTAL)"
- depends on USB_HIDINPUT && EXPERIMENTAL
+ depends on USB_HID && EXPERIMENTAL
help
Say Y here is you want force feedback support for a few HID devices.
See below for a list of supported devices.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index d946d5213b3..1a24b5bfa05 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -11,9 +11,6 @@ usbhid-objs := hid-core.o
ifeq ($(CONFIG_USB_HIDDEV),y)
usbhid-objs += hiddev.o
endif
-ifeq ($(CONFIG_USB_HIDINPUT),y)
- usbhid-objs += hid-input.o
-endif
ifeq ($(CONFIG_HID_PID),y)
usbhid-objs += hid-pidff.o
endif
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 4c213513484..c77291d3d06 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -38,14 +38,29 @@
#define APPLE_VENDOR_ID 0x05AC
/* These names come from Info.plist in AppleUSBTrackpad.kext */
-#define GEYSER_ANSI_PRODUCT_ID 0x0214
-#define GEYSER_ISO_PRODUCT_ID 0x0215
-#define GEYSER_JIS_PRODUCT_ID 0x0216
+#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E
+#define FOUNTAIN_ISO_PRODUCT_ID 0x020F
+
+#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A
+
+#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B
+
+#define GEYSER_ANSI_PRODUCT_ID 0x0214
+#define GEYSER_ISO_PRODUCT_ID 0x0215
+#define GEYSER_JIS_PRODUCT_ID 0x0216
/* MacBook devices */
-#define GEYSER3_ANSI_PRODUCT_ID 0x0217
-#define GEYSER3_ISO_PRODUCT_ID 0x0218
-#define GEYSER3_JIS_PRODUCT_ID 0x0219
+#define GEYSER3_ANSI_PRODUCT_ID 0x0217
+#define GEYSER3_ISO_PRODUCT_ID 0x0218
+#define GEYSER3_JIS_PRODUCT_ID 0x0219
+
+/*
+ * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
+ * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
+ */
+#define GEYSER4_ANSI_PRODUCT_ID 0x021A
+#define GEYSER4_ISO_PRODUCT_ID 0x021B
+#define GEYSER4_JIS_PRODUCT_ID 0x021C
#define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
@@ -58,20 +73,26 @@
/* table of devices that work with this driver */
static struct usb_device_id atp_table [] = {
- { ATP_DEVICE(0x020E) },
- { ATP_DEVICE(0x020F) },
- { ATP_DEVICE(0x030A) },
- { ATP_DEVICE(0x030B) },
+ { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
/* PowerBooks Oct 2005 */
{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+ /* Core Duo MacBook & MacBook Pro */
{ ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+ /* Core2 Duo MacBook & MacBook Pro */
+ { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+
/* Terminating entry */
{ }
};
@@ -108,7 +129,7 @@ MODULE_DEVICE_TABLE (usb, atp_table);
*/
#define ATP_THRESHOLD 5
-/* MacBook Pro (Geyser 3) initialization constants */
+/* MacBook Pro (Geyser 3 & 4) initialization constants */
#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1
#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9
#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300
@@ -154,6 +175,13 @@ MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
MODULE_LICENSE("GPL");
+/*
+ * Make the threshold a module parameter
+ */
+static int threshold = ATP_THRESHOLD;
+module_param(threshold, int, 0644);
+MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
@@ -174,7 +202,10 @@ static inline int atp_is_geyser_3(struct atp *dev)
return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
(productId == GEYSER3_ISO_PRODUCT_ID) ||
- (productId == GEYSER3_JIS_PRODUCT_ID);
+ (productId == GEYSER3_JIS_PRODUCT_ID) ||
+ (productId == GEYSER4_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER4_ISO_PRODUCT_ID) ||
+ (productId == GEYSER4_JIS_PRODUCT_ID);
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -183,16 +214,48 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
int i;
/* values to calculate mean */
int pcum = 0, psum = 0;
+ int is_increasing = 0;
*fingers = 0;
for (i = 0; i < nb_sensors; i++) {
- if (xy_sensors[i] < ATP_THRESHOLD)
+ if (xy_sensors[i] < threshold) {
+ if (is_increasing)
+ is_increasing = 0;
+
continue;
- if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+ }
+
+ /*
+ * Makes the finger detection more versatile. For example,
+ * two fingers with no gap will be detected. Also, my
+ * tests show it less likely to have intermittent loss
+ * of multiple finger readings while moving around (scrolling).
+ *
+ * Changes the multiple finger detection to counting humps on
+ * sensors (transitions from nonincreasing to increasing)
+ * instead of counting transitions from low sensors (no
+ * finger reading) to high sensors (finger above
+ * sensor)
+ *
+ * - Jason Parekh <jasonparekh@gmail.com>
+ */
+ if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
(*fingers)++;
- pcum += xy_sensors[i] * i;
- psum += xy_sensors[i];
+ is_increasing = 1;
+ } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
+ is_increasing = 0;
+ }
+
+ /*
+ * Subtracts threshold so a high sensor that just passes the threshold
+ * won't skew the calculated absolute coordinate. Fixes an issue
+ * where slowly moving the mouse would occassionaly jump a number of
+ * pixels (let me restate--slowly moving the mouse makes this issue
+ * most apparent).
+ */
+ pcum += (xy_sensors[i] - threshold) * i;
+ psum += (xy_sensors[i] - threshold);
}
if (psum > 0) {
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index f1d0e1d6982..c6c9e72e5fd 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -4,6 +4,7 @@
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006 Jiri Kosina
*/
/*
@@ -32,8 +33,9 @@
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
#include <linux/hiddev.h>
+#include "usbhid.h"
/*
* Version Information
@@ -55,887 +57,6 @@ module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
/*
- * Register a new report for a device.
- */
-
-static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
-{
- struct hid_report_enum *report_enum = device->report_enum + type;
- struct hid_report *report;
-
- if (report_enum->report_id_hash[id])
- return report_enum->report_id_hash[id];
-
- if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
- return NULL;
-
- if (id != 0)
- report_enum->numbered = 1;
-
- report->id = id;
- report->type = type;
- report->size = 0;
- report->device = device;
- report_enum->report_id_hash[id] = report;
-
- list_add_tail(&report->list, &report_enum->report_list);
-
- return report;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
-{
- struct hid_field *field;
-
- if (report->maxfield == HID_MAX_FIELDS) {
- dbg("too many fields in report");
- return NULL;
- }
-
- if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
- + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
-
- field->index = report->maxfield++;
- report->field[field->index] = field;
- field->usage = (struct hid_usage *)(field + 1);
- field->value = (unsigned *)(field->usage + usages);
- field->report = report;
-
- return field;
-}
-
-/*
- * Open a collection. The type/usage is pushed on the stack.
- */
-
-static int open_collection(struct hid_parser *parser, unsigned type)
-{
- struct hid_collection *collection;
- unsigned usage;
-
- usage = parser->local.usage[0];
-
- if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- dbg("collection stack overflow");
- return -1;
- }
-
- if (parser->device->maxcollection == parser->device->collection_size) {
- collection = kmalloc(sizeof(struct hid_collection) *
- 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);
- memset(collection + parser->device->collection_size, 0,
- sizeof(struct hid_collection) *
- parser->device->collection_size);
- kfree(parser->device->collection);
- parser->device->collection = collection;
- parser->device->collection_size *= 2;
- }
-
- parser->collection_stack[parser->collection_stack_ptr++] =
- parser->device->maxcollection;
-
- 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++;
-
- return 0;
-}
-
-/*
- * Close a collection.
- */
-
-static int close_collection(struct hid_parser *parser)
-{
- if (!parser->collection_stack_ptr) {
- dbg("collection stack underflow");
- return -1;
- }
- parser->collection_stack_ptr--;
- return 0;
-}
-
-/*
- * Climb up the stack, search for the specified collection type
- * and return the usage.
- */
-
-static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
-{
- int n;
- for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
- if (parser->device->collection[parser->collection_stack[n]].type == type)
- return parser->device->collection[parser->collection_stack[n]].usage;
- return 0; /* we know nothing about this usage type */
-}
-
-/*
- * Add a usage to the temporary parser table.
- */
-
-static int hid_add_usage(struct hid_parser *parser, unsigned usage)
-{
- if (parser->local.usage_index >= HID_MAX_USAGES) {
- dbg("usage index exceeded");
- return -1;
- }
- parser->local.usage[parser->local.usage_index] = usage;
- parser->local.collection_index[parser->local.usage_index] =
- parser->collection_stack_ptr ?
- parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
- parser->local.usage_index++;
- return 0;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
-{
- struct hid_report *report;
- struct hid_field *field;
- int usages;
- unsigned offset;
- int i;
-
- if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
- dbg("hid_register_report failed");
- return -1;
- }
-
- if (parser->global.logical_maximum < parser->global.logical_minimum) {
- dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
- return -1;
- }
-
- 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;
-
- field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
- field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
- field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
-
- for (i = 0; i < usages; i++) {
- int j = i;
- /* Duplicate the last usage we parsed if we have excess values */
- if (i >= parser->local.usage_index)
- j = parser->local.usage_index - 1;
- field->usage[i].hid = parser->local.usage[j];
- field->usage[i].collection_index =
- parser->local.collection_index[j];
- }
-
- field->maxusage = usages;
- field->flags = flags;
- field->report_offset = offset;
- field->report_type = report_type;
- field->report_size = parser->global.report_size;
- field->report_count = parser->global.report_count;
- field->logical_minimum = parser->global.logical_minimum;
- field->logical_maximum = parser->global.logical_maximum;
- field->physical_minimum = parser->global.physical_minimum;
- field->physical_maximum = parser->global.physical_maximum;
- field->unit_exponent = parser->global.unit_exponent;
- field->unit = parser->global.unit;
-
- return 0;
-}
-
-/*
- * Read data value from item.
- */
-
-static u32 item_udata(struct hid_item *item)
-{
- switch (item->size) {
- case 1: return item->data.u8;
- case 2: return item->data.u16;
- case 4: return item->data.u32;
- }
- return 0;
-}
-
-static s32 item_sdata(struct hid_item *item)
-{
- switch (item->size) {
- case 1: return item->data.s8;
- case 2: return item->data.s16;
- case 4: return item->data.s32;
- }
- return 0;
-}
-
-/*
- * Process a global item.
- */
-
-static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
-{
- switch (item->tag) {
-
- case HID_GLOBAL_ITEM_TAG_PUSH:
-
- if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg("global enviroment stack overflow");
- return -1;
- }
-
- memcpy(parser->global_stack + parser->global_stack_ptr++,
- &parser->global, sizeof(struct hid_global));
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_POP:
-
- if (!parser->global_stack_ptr) {
- dbg("global enviroment stack underflow");
- return -1;
- }
-
- memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
- sizeof(struct hid_global));
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
- parser->global.usage_page = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
- parser->global.logical_minimum = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
- if (parser->global.logical_minimum < 0)
- parser->global.logical_maximum = item_sdata(item);
- else
- parser->global.logical_maximum = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
- parser->global.physical_minimum = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
- if (parser->global.physical_minimum < 0)
- parser->global.physical_maximum = item_sdata(item);
- else
- parser->global.physical_maximum = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
- parser->global.unit_exponent = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_UNIT:
- parser->global.unit = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
- if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg("invalid report_size %d", parser->global.report_size);
- return -1;
- }
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
- if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg("invalid report_count %d", parser->global.report_count);
- return -1;
- }
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_ID:
- if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg("report_id 0 is invalid");
- return -1;
- }
- return 0;
-
- default:
- dbg("unknown global tag 0x%x", item->tag);
- return -1;
- }
-}
-
-/*
- * Process a local item.
- */
-
-static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
-{
- __u32 data;
- unsigned n;
-
- if (item->size == 0) {
- dbg("item data expected for local item");
- return -1;
- }
-
- data = item_udata(item);
-
- switch (item->tag) {
-
- case HID_LOCAL_ITEM_TAG_DELIMITER:
-
- if (data) {
- /*
- * We treat items before the first delimiter
- * as global to all usage sets (branch 0).
- * In the moment we process only these global
- * items and the first delimiter set.
- */
- if (parser->local.delimiter_depth != 0) {
- dbg("nested delimiters");
- return -1;
- }
- parser->local.delimiter_depth++;
- parser->local.delimiter_branch++;
- } else {
- if (parser->local.delimiter_depth < 1) {
- dbg("bogus close delimiter");
- return -1;
- }
- parser->local.delimiter_depth--;
- }
- return 1;
-
- case HID_LOCAL_ITEM_TAG_USAGE:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- return hid_add_usage(parser, data);
-
- case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- parser->local.usage_minimum = data;
- return 0;
-
- case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- for (n = parser->local.usage_minimum; n <= data; n++)
- if (hid_add_usage(parser, n)) {
- dbg("hid_add_usage failed\n");
- return -1;
- }
- return 0;
-
- default:
-
- dbg("unknown local item tag 0x%x", item->tag);
- return 0;
- }
- return 0;
-}
-
-/*
- * Process a main item.
- */
-
-static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
-{
- __u32 data;
- int ret;
-
- data = item_udata(item);
-
- switch (item->tag) {
- case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
- ret = open_collection(parser, data & 0xff);
- break;
- case HID_MAIN_ITEM_TAG_END_COLLECTION:
- ret = close_collection(parser);
- break;
- case HID_MAIN_ITEM_TAG_INPUT:
- ret = hid_add_field(parser, HID_INPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_OUTPUT:
- ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_FEATURE:
- ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
- break;
- default:
- dbg("unknown main item tag 0x%x", item->tag);
- ret = 0;
- }
-
- memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */
-
- return ret;
-}
-
-/*
- * Process a reserved item.
- */
-
-static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
-{
- dbg("reserved item type, tag 0x%x", item->tag);
- return 0;
-}
-
-/*
- * Free a report and all registered fields. The field->usage and
- * field->value table's are allocated behind the field, so we need
- * only to free(field) itself.
- */
-
-static void hid_free_report(struct hid_report *report)
-{
- unsigned n;
-
- for (n = 0; n < report->maxfield; n++)
- kfree(report->field[n]);
- kfree(report);
-}
-
-/*
- * Free a device structure, all reports, and all fields.
- */
-
-static void hid_free_device(struct hid_device *device)
-{
- unsigned i,j;
-
- for (i = 0; i < HID_REPORT_TYPES; i++) {
- struct hid_report_enum *report_enum = device->report_enum + i;
-
- for (j = 0; j < 256; j++) {
- struct hid_report *report = report_enum->report_id_hash[j];
- if (report)
- hid_free_report(report);
- }
- }
-
- kfree(device->rdesc);
- kfree(device);
-}
-
-/*
- * Fetch a report description item from the data stream. We support long
- * items, though they are not used yet.
- */
-
-static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
-{
- u8 b;
-
- if ((end - start) <= 0)
- return NULL;
-
- b = *start++;
-
- item->type = (b >> 2) & 3;
- item->tag = (b >> 4) & 15;
-
- if (item->tag == HID_ITEM_TAG_LONG) {
-
- item->format = HID_ITEM_FORMAT_LONG;
-
- if ((end - start) < 2)
- return NULL;
-
- item->size = *start++;
- item->tag = *start++;
-
- 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;
-
- switch (item->size) {
-
- case 0:
- return start;
-
- case 1:
- if ((end - start) < 1)
- return NULL;
- item->data.u8 = *start++;
- return start;
-
- case 2:
- if ((end - start) < 2)
- return NULL;
- item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
- start = (__u8 *)((__le16 *)start + 1);
- return start;
-
- case 3:
- item->size++;
- if ((end - start) < 4)
- return NULL;
- item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
- start = (__u8 *)((__le32 *)start + 1);
- return start;
- }
-
- return NULL;
-}
-
-/*
- * Parse a report description into a hid_device structure. Reports are
- * enumerated, fields are attached to these reports.
- */
-
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
-{
- struct hid_device *device;
- struct hid_parser *parser;
- struct hid_item item;
- __u8 *end;
- unsigned i;
- static int (*dispatch_type[])(struct hid_parser *parser,
- struct hid_item *item) = {
- hid_parser_main,
- hid_parser_global,
- hid_parser_local,
- hid_parser_reserved
- };
-
- if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
- return NULL;
-
- if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
- HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
- kfree(device);
- return NULL;
- }
- device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
- for (i = 0; i < HID_REPORT_TYPES; i++)
- INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
- if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
- kfree(device->collection);
- kfree(device);
- return NULL;
- }
- memcpy(device->rdesc, start, size);
- device->rsize = size;
-
- if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
- kfree(device->rdesc);
- kfree(device->collection);
- kfree(device);
- return NULL;
- }
- parser->device = device;
-
- end = start + size;
- while ((start = fetch_item(start, end, &item)) != NULL) {
-
- if (item.format != HID_ITEM_FORMAT_SHORT) {
- dbg("unexpected long global item");
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
-
- if (dispatch_type[item.type](parser, &item)) {
- dbg("item %u %u %u %u parsing failed\n",
- item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
-
- if (start == end) {
- if (parser->collection_stack_ptr) {
- dbg("unbalanced collection at end of report description");
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
- if (parser->local.delimiter_depth) {
- dbg("unbalanced delimiter at end of report description");
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
- kfree(parser);
- return device;
- }
- }
-
- dbg("item fetching failed at offset %d\n", (int)(end - start));
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
-}
-
-/*
- * Convert a signed n-bit integer to signed 32-bit integer. Common
- * cases are done through the compiler, the screwed things has to be
- * done by hand.
- */
-
-static s32 snto32(__u32 value, unsigned n)
-{
- switch (n) {
- case 8: return ((__s8)value);
- case 16: return ((__s16)value);
- case 32: return ((__s32)value);
- }
- return value & (1 << (n - 1)) ? value | (-1 << n) : value;
-}
-
-/*
- * Convert a signed 32-bit integer to a signed n-bit integer.
- */
-
-static u32 s32ton(__s32 value, unsigned n)
-{
- s32 a = value >> (n - 1);
- if (a && a != -1)
- return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
- return value & ((1 << n) - 1);
-}
-
-/*
- * Extract/implement a data field from/to a little endian report (bit array).
- *
- * Code sort-of follows HID spec:
- * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
- *
- * While the USB HID spec allows unlimited length bit fields in "report
- * descriptors", most devices never use more than 16 bits.
- * One model of UPS is claimed to report "LINEV" as a 32-bit field.
- * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
- */
-
-static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
-{
- u64 x;
-
- WARN_ON(n > 32);
-
- report += offset >> 3; /* adjust byte index */
- offset &= 7; /* now only need bit offset into one byte */
- x = get_unaligned((u64 *) report);
- x = le64_to_cpu(x);
- x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
- return (u32) x;
-}
-
-/*
- * "implement" : set bits in a little endian bit stream.
- * Same concepts as "extract" (see comments above).
- * The data mangled in the bit stream remains in little endian
- * order the whole time. It make more sense to talk about
- * endianness of register values by considering a register
- * a "cached" copy of the little endiad bit stream.
- */
-static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
-{
- u64 x;
- u64 m = (1ULL << n) - 1;
-
- WARN_ON(n > 32);
-
- WARN_ON(value > m);
- value &= m;
-
- report += offset >> 3;
- offset &= 7;
-
- x = get_unaligned((u64 *)report);
- x &= cpu_to_le64(~(m << offset));
- x |= cpu_to_le64(((u64) value) << offset);
- put_unaligned(x, (u64 *) report);
-}
-
-/*
- * Search an array for a value.
- */
-
-static __inline__ int search(__s32 *array, __s32 value, unsigned n)
-{
- while (n--) {
- if (*array++ == value)
- return 0;
- }
- return -1;
-}
-
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
-{
- hid_dump_input(usage, value);
- if (hid->claimed & HID_CLAIMED_INPUT)
- hidinput_hid_event(hid, field, usage, value);
- if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
- hiddev_hid_event(hid, field, usage, value);
-}
-
-/*
- * Analyse a received field, and fetch the data from it. The field
- * content is stored for next report processing (we do differential
- * reporting to the layer).
- */
-
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
-{
- unsigned n;
- unsigned count = field->report_count;
- unsigned offset = field->report_offset;
- unsigned size = field->report_size;
- __s32 min = field->logical_minimum;
- __s32 max = field->logical_maximum;
- __s32 *value;
-
- if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
- return;
-
- for (n = 0; n < count; n++) {
-
- value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
- extract(data, offset + n * size, size);
-
- if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
- && value[n] >= min && value[n] <= max
- && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
- goto exit;
- }
-
- for (n = 0; n < count; n++) {
-
- if (HID_MAIN_ITEM_VARIABLE & field->flags) {
- hid_process_event(hid, field, &field->usage[n], value[n], interrupt);
- continue;
- }
-
- if (field->value[n] >= min && field->value[n] <= max
- && field->usage[field->value[n] - min].hid
- && search(value, field->value[n], count))
- hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
-
- if (value[n] >= min && value[n] <= max
- && field->usage[value[n] - min].hid
- && search(field->value, value[n], count))
- hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
- }
-
- memcpy(field->value, value, count * sizeof(__s32));
-exit:
- kfree(value);
-}
-
-static int hid_input_report(int type, struct urb *urb, int interrupt)
-{
- struct hid_device *hid = urb->context;
- struct hid_report_enum *report_enum = hid->report_enum + type;
- u8 *data = urb->transfer_buffer;
- int len = urb->actual_length;
- struct hid_report *report;
- int n, size;
-
- if (!len) {
- dbg("empty report");
- return -1;
- }
-
-#ifdef DEBUG_DATA
- printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
-#endif
-
- n = 0; /* Normally report number is 0 */
- if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
- n = *data++;
- len--;
- }
-
-#ifdef DEBUG_DATA
- {
- int i;
- printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len);
- for (i = 0; i < len; i++)
- printk(" %02x", data[i]);
- printk("\n");
- }
-#endif
-
- if (!(report = report_enum->report_id_hash[n])) {
- dbg("undefined report_id %d received", n);
- return -1;
- }
-
- size = ((report->size - 1) >> 3) + 1;
-
- if (len < size) {
- dbg("report %d is too short, (%d < %d)", report->id, len, size);
- memset(data + len, 0, size - len);
- }
-
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- hiddev_report_event(hid, report);
-
- for (n = 0; n < report->maxfield; n++)
- hid_input_field(hid, report->field[n], data, interrupt);
-
- if (hid->claimed & HID_CLAIMED_INPUT)
- hidinput_report_event(hid, report);
-
- return 0;
-}
-
-/*
* Input submission and I/O error handler.
*/
@@ -946,15 +67,16 @@ static int hid_start_in(struct hid_device *hid)
{
unsigned long flags;
int rc = 0;
+ struct usbhid_device *usbhid = hid->driver_data;
- spin_lock_irqsave(&hid->inlock, flags);
- if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
- !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
- rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
+ spin_lock_irqsave(&usbhid->inlock, flags);
+ if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
+ !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+ rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
if (rc != 0)
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
}
- spin_unlock_irqrestore(&hid->inlock, flags);
+ spin_unlock_irqrestore(&usbhid->inlock, flags);
return rc;
}
@@ -962,8 +84,9 @@ static int hid_start_in(struct hid_device *hid)
static void hid_retry_timeout(unsigned long _hid)
{
struct hid_device *hid = (struct hid_device *) _hid;
+ struct usbhid_device *usbhid = hid->driver_data;
- dev_dbg(&hid->intf->dev, "retrying intr urb\n");
+ dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
if (hid_start_in(hid))
hid_io_error(hid);
}
@@ -971,38 +94,39 @@ static void hid_retry_timeout(unsigned long _hid)
/* Workqueue routine to reset the device or clear a halt */
static void hid_reset(struct work_struct *work)
{
- struct hid_device *hid =
- container_of(work, struct hid_device, reset_work);
+ struct usbhid_device *usbhid =
+ container_of(work, struct usbhid_device, reset_work);
+ struct hid_device *hid = usbhid->hid;
int rc_lock, rc = 0;
- if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
- dev_dbg(&hid->intf->dev, "clear halt\n");
- rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
- clear_bit(HID_CLEAR_HALT, &hid->iofl);
+ if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
+ dev_dbg(&usbhid->intf->dev, "clear halt\n");
+ rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe);
+ clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
hid_start_in(hid);
}
- else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
- dev_dbg(&hid->intf->dev, "resetting device\n");
- rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+ else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+ dev_dbg(&usbhid->intf->dev, "resetting device\n");
+ rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
if (rc_lock >= 0) {
- rc = usb_reset_composite_device(hid->dev, hid->intf);
+ rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf);
if (rc_lock)
- usb_unlock_device(hid->dev);
+ usb_unlock_device(hid_to_usb_dev(hid));
}
- clear_bit(HID_RESET_PENDING, &hid->iofl);
+ clear_bit(HID_RESET_PENDING, &usbhid->iofl);
}
switch (rc) {
case 0:
- if (!test_bit(HID_IN_RUNNING, &hid->iofl))
+ if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
hid_io_error(hid);
break;
default:
err("can't reset device, %s-%s/input%d, status %d",
- hid->dev->bus->bus_name,
- hid->dev->devpath,
- hid->ifnum, rc);
+ hid_to_usb_dev(hid)->bus->bus_name,
+ hid_to_usb_dev(hid)->devpath,
+ usbhid->ifnum, rc);
/* FALLTHROUGH */
case -EHOSTUNREACH:
case -ENODEV:
@@ -1015,33 +139,34 @@ static void hid_reset(struct work_struct *work)
static void hid_io_error(struct hid_device *hid)
{
unsigned long flags;
+ struct usbhid_device *usbhid = hid->driver_data;
- spin_lock_irqsave(&hid->inlock, flags);
+ spin_lock_irqsave(&usbhid->inlock, flags);
/* Stop when disconnected */
- if (usb_get_intfdata(hid->intf) == NULL)
+ if (usb_get_intfdata(usbhid->intf) == NULL)
goto done;
/* When an error occurs, retry at increasing intervals */
- if (hid->retry_delay == 0) {
- hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
- hid->stop_retry = jiffies + msecs_to_jiffies(1000);
- } else if (hid->retry_delay < 100)
- hid->retry_delay *= 2;
+ if (usbhid->retry_delay == 0) {
+ usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
+ usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
+ } else if (usbhid->retry_delay < 100)
+ usbhid->retry_delay *= 2;
- if (time_after(jiffies, hid->stop_retry)) {
+ if (time_after(jiffies, usbhid->stop_retry)) {
/* Retries failed, so do a port reset */
- if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
- schedule_work(&hid->reset_work);
+ if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+ schedule_work(&usbhid->reset_work);
goto done;
}
}
- mod_timer(&hid->io_retry,
- jiffies + msecs_to_jiffies(hid->retry_delay));
+ mod_timer(&usbhid->io_retry,
+ jiffies + msecs_to_jiffies(usbhid->retry_delay));
done:
- spin_unlock_irqrestore(&hid->inlock, flags);
+ spin_unlock_irqrestore(&usbhid->inlock, flags);
}
/*
@@ -1051,28 +176,31 @@ done:
static void hid_irq_in(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct usbhid_device *usbhid = hid->driver_data;
int status;
switch (urb->status) {
case 0: /* success */
- hid->retry_delay = 0;
- hid_input_report(HID_INPUT_REPORT, urb, 1);
+ usbhid->retry_delay = 0;
+ hid_input_report(urb->context, HID_INPUT_REPORT,
+ urb->transfer_buffer,
+ urb->actual_length, 1);
break;
case -EPIPE: /* stall */
- clear_bit(HID_IN_RUNNING, &hid->iofl);
- set_bit(HID_CLEAR_HALT, &hid->iofl);
- schedule_work(&hid->reset_work);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ set_bit(HID_CLEAR_HALT, &usbhid->iofl);
+ schedule_work(&usbhid->reset_work);
return;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN: /* unplug */
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
return;
case -EILSEQ: /* protocol error or unplug */
case -EPROTO: /* protocol error or unplug */
case -ETIME: /* protocol error or unplug */
case -ETIMEDOUT: /* Should never happen, but... */
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
hid_io_error(hid);
return;
default: /* error */
@@ -1081,79 +209,18 @@ static void hid_irq_in(struct urb *urb)
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
if (status != -EPERM) {
err("can't resubmit intr, %s-%s/input%d, status %d",
- hid->dev->bus->bus_name,
- hid->dev->devpath,
- hid->ifnum, status);
+ hid_to_usb_dev(hid)->bus->bus_name,
+ hid_to_usb_dev(hid)->devpath,
+ usbhid->ifnum, status);
hid_io_error(hid);
}
}
}
/*
- * Output the field into the report.
- */
-
-static void hid_output_field(struct hid_field *field, __u8 *data)
-{
- unsigned count = field->report_count;
- unsigned offset = field->report_offset;
- unsigned size = field->report_size;
- unsigned n;
-
- 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 */
- implement(data, offset + n * size, size, field->value[n]);
- }
-}
-
-/*
- * Create a report.
- */
-
-static void hid_output_report(struct hid_report *report, __u8 *data)
-{
- unsigned n;
-
- if (report->id > 0)
- *data++ = report->id;
-
- for (n = 0; n < report->maxfield; n++)
- hid_output_field(report->field[n], data);
-}
-
-/*
- * Set a field value. The report this field belongs to has to be
- * created and transferred to the device, to set this value in the
- * device.
- */
-
-int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
-{
- unsigned size = field->report_size;
-
- hid_dump_input(field->usage + offset, value);
-
- if (offset >= field->report_count) {
- dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
- hid_dump_field(field, 8);
- return -1;
- }
- if (field->logical_minimum < 0) {
- if (value != snto32(s32ton(value, size), size)) {
- dbg("value %d is out of range", value);
- return -1;
- }
- }
- field->value[offset] = value;
- return 0;
-}
-
-/*
* Find a report field with a specified HID usage.
*/
#if 0
@@ -1173,16 +240,17 @@ struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_u
static int hid_submit_out(struct hid_device *hid)
{
struct hid_report *report;
+ struct usbhid_device *usbhid = hid->driver_data;
- report = hid->out[hid->outtail];
+ report = usbhid->out[usbhid->outtail];
- hid_output_report(report, hid->outbuf);
- hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
- hid->urbout->dev = hid->dev;
+ hid_output_report(report, usbhid->outbuf);
+ usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+ usbhid->urbout->dev = hid_to_usb_dev(hid);
dbg("submitting out urb");
- if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
+ if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
err("usb_submit_urb(out) failed");
return -1;
}
@@ -1195,42 +263,43 @@ static int hid_submit_ctrl(struct hid_device *hid)
struct hid_report *report;
unsigned char dir;
int len;
+ struct usbhid_device *usbhid = hid->driver_data;
- report = hid->ctrl[hid->ctrltail].report;
- dir = hid->ctrl[hid->ctrltail].dir;
+ report = usbhid->ctrl[usbhid->ctrltail].report;
+ dir = usbhid->ctrl[usbhid->ctrltail].dir;
len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
if (dir == USB_DIR_OUT) {
- hid_output_report(report, hid->ctrlbuf);
- hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0);
- hid->urbctrl->transfer_buffer_length = len;
+ hid_output_report(report, usbhid->ctrlbuf);
+ usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
+ usbhid->urbctrl->transfer_buffer_length = len;
} else {
int maxpacket, padlen;
- hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0);
- maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0);
+ usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
+ maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0);
if (maxpacket > 0) {
padlen = (len + maxpacket - 1) / maxpacket;
padlen *= maxpacket;
- if (padlen > hid->bufsize)
- padlen = hid->bufsize;
+ if (padlen > usbhid->bufsize)
+ padlen = usbhid->bufsize;
} else
padlen = 0;
- hid->urbctrl->transfer_buffer_length = padlen;
+ usbhid->urbctrl->transfer_buffer_length = padlen;
}
- hid->urbctrl->dev = hid->dev;
+ usbhid->urbctrl->dev = hid_to_usb_dev(hid);
- hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
- hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
- hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
- hid->cr->wIndex = cpu_to_le16(hid->ifnum);
- hid->cr->wLength = cpu_to_le16(len);
+ usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
+ usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
+ usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
+ usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
+ usbhid->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);
+ usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+ usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
- if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
+ if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
err("usb_submit_urb(ctrl) failed");
return -1;
}
@@ -1245,6 +314,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
static void hid_irq_out(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct usbhid_device *usbhid = hid->driver_data;
unsigned long flags;
int unplug = 0;
@@ -1262,24 +332,24 @@ static void hid_irq_out(struct urb *urb)
warn("output irq status %d received", urb->status);
}
- spin_lock_irqsave(&hid->outlock, flags);
+ spin_lock_irqsave(&usbhid->outlock, flags);
if (unplug)
- hid->outtail = hid->outhead;
+ usbhid->outtail = usbhid->outhead;
else
- hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+ usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
- if (hid->outhead != hid->outtail) {
+ if (usbhid->outhead != usbhid->outtail) {
if (hid_submit_out(hid)) {
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
wake_up(&hid->wait);
}
- spin_unlock_irqrestore(&hid->outlock, flags);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
return;
}
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
- spin_unlock_irqrestore(&hid->outlock, flags);
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
wake_up(&hid->wait);
}
@@ -1290,15 +360,17 @@ static void hid_irq_out(struct urb *urb)
static void hid_ctrl(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct usbhid_device *usbhid = hid->driver_data;
unsigned long flags;
int unplug = 0;
- spin_lock_irqsave(&hid->ctrllock, flags);
+ spin_lock_irqsave(&usbhid->ctrllock, flags);
switch (urb->status) {
case 0: /* success */
- if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
- hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0);
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+ hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
+ urb->transfer_buffer, urb->actual_length, 0);
break;
case -ESHUTDOWN: /* unplug */
unplug = 1;
@@ -1313,76 +385,102 @@ static void hid_ctrl(struct urb *urb)
}
if (unplug)
- hid->ctrltail = hid->ctrlhead;
+ usbhid->ctrltail = usbhid->ctrlhead;
else
- hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
- if (hid->ctrlhead != hid->ctrltail) {
+ if (usbhid->ctrlhead != usbhid->ctrltail) {
if (hid_submit_ctrl(hid)) {
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
wake_up(&hid->wait);
}
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
return;
}
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
wake_up(&hid->wait);
}
-void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
{
int head;
unsigned long flags;
+ struct usbhid_device *usbhid = hid->driver_data;
if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
return;
- if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
+ if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
- spin_lock_irqsave(&hid->outlock, flags);
+ spin_lock_irqsave(&usbhid->outlock, flags);
- if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
- spin_unlock_irqrestore(&hid->outlock, flags);
+ if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
warn("output queue full");
return;
}
- hid->out[hid->outhead] = report;
- hid->outhead = head;
+ usbhid->out[usbhid->outhead] = report;
+ usbhid->outhead = head;
- if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
+ if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
if (hid_submit_out(hid))
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
- spin_unlock_irqrestore(&hid->outlock, flags);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
return;
}
- spin_lock_irqsave(&hid->ctrllock, flags);
+ spin_lock_irqsave(&usbhid->ctrllock, flags);
- if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
warn("control queue full");
return;
}
- hid->ctrl[hid->ctrlhead].report = report;
- hid->ctrl[hid->ctrlhead].dir = dir;
- hid->ctrlhead = head;
+ usbhid->ctrl[usbhid->ctrlhead].report = report;
+ usbhid->ctrl[usbhid->ctrlhead].dir = dir;
+ usbhid->ctrlhead = head;
- if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
+ if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
if (hid_submit_ctrl(hid))
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+}
+
+static int usb_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;
+ int offset;
+
+ if (type == EV_FF)
+ return input_ff_event(dev, type, code, value);
+
+ if (type != EV_LED)
+ return -1;
+
+ if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
+ warn("event field not found");
+ return -1;
+ }
+
+ hid_set_field(field, offset, value);
+ usbhid_submit_report(hid, field->report, USB_DIR_OUT);
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ return 0;
}
-int hid_wait_io(struct hid_device *hid)
+int usbhid_wait_io(struct hid_device *hid)
{
- if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
- !test_bit(HID_OUT_RUNNING, &hid->iofl)),
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
+ !test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
10*HZ)) {
dbg("timeout waiting for ctrl or out queue to clear");
return -1;
@@ -1414,7 +512,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
return result;
}
-int hid_open(struct hid_device *hid)
+int usbhid_open(struct hid_device *hid)
{
++hid->open;
if (hid_start_in(hid))
@@ -1422,10 +520,24 @@ int hid_open(struct hid_device *hid)
return 0;
}
-void hid_close(struct hid_device *hid)
+void usbhid_close(struct hid_device *hid)
{
+ struct usbhid_device *usbhid = hid->driver_data;
+
if (!--hid->open)
- usb_kill_urb(hid->urbin);
+ usb_kill_urb(usbhid->urbin);
+}
+
+static int hidinput_open(struct input_dev *dev)
+{
+ struct hid_device *hid = dev->private;
+ return usbhid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+ struct hid_device *hid = dev->private;
+ usbhid_close(hid);
}
#define USB_VENDOR_ID_PANJIT 0x134c
@@ -1437,26 +549,27 @@ void hid_close(struct hid_device *hid)
* Initialize all reports
*/
-void hid_init_reports(struct hid_device *hid)
+void usbhid_init_reports(struct hid_device *hid)
{
struct hid_report *report;
+ struct usbhid_device *usbhid = hid->driver_data;
int err, ret;
list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
- hid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_submit_report(hid, report, USB_DIR_IN);
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
- hid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_submit_report(hid, report, USB_DIR_IN);
err = 0;
- ret = hid_wait_io(hid);
+ ret = usbhid_wait_io(hid);
while (ret) {
err |= ret;
- if (test_bit(HID_CTRL_RUNNING, &hid->iofl))
- usb_kill_urb(hid->urbctrl);
- if (test_bit(HID_OUT_RUNNING, &hid->iofl))
- usb_kill_urb(hid->urbout);
- ret = hid_wait_io(hid);
+ if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+ usb_kill_urb(usbhid->urbctrl);
+ if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+ usb_kill_urb(usbhid->urbout);
+ ret = usbhid_wait_io(hid);
}
if (err)
@@ -1464,6 +577,7 @@ void hid_init_reports(struct hid_device *hid)
}
#define USB_VENDOR_ID_GTCO 0x078c
+#define USB_VENDOR_ID_GTCO_IPANEL_2 0x5543
#define USB_DEVICE_ID_GTCO_90 0x0090
#define USB_DEVICE_ID_GTCO_100 0x0100
#define USB_DEVICE_ID_GTCO_101 0x0101
@@ -1509,6 +623,8 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_GTCO_1004 0x1004
#define USB_DEVICE_ID_GTCO_1005 0x1005
#define USB_DEVICE_ID_GTCO_1006 0x1006
+#define USB_DEVICE_ID_GTCO_8 0x0008
+#define USB_DEVICE_ID_GTCO_d 0x000d
#define USB_VENDOR_ID_WACOM 0x056a
@@ -1670,6 +786,12 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_AIRCABLE 0x16CA
#define USB_DEVICE_ID_AIRCABLE1 0x1502
+#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101
+
+#define USB_VENDOR_ID_IMATION 0x0718
+#define USB_DEVICE_ID_DISC_STAKKA 0xd000
+
/*
* Alphabetically sorted blacklist by quirk type.
*/
@@ -1754,6 +876,9 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
@@ -1830,7 +955,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
@@ -1841,7 +966,9 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
-
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
+
{ 0, 0 }
};
@@ -1864,13 +991,15 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *
static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
- if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->inbuf_dma)))
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
return -1;
- if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->outbuf_dma)))
+ if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
return -1;
- if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), GFP_ATOMIC, &hid->cr_dma)))
+ if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
return -1;
- if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->ctrlbuf_dma)))
+ if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
return -1;
return 0;
@@ -1878,14 +1007,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
- if (hid->inbuf)
- usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
- if (hid->outbuf)
- usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
- if (hid->cr)
- usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
- if (hid->ctrlbuf)
- usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (usbhid->inbuf)
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+ if (usbhid->outbuf)
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+ if (usbhid->cr)
+ usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
+ if (usbhid->ctrlbuf)
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
/*
@@ -1911,6 +1042,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
unsigned quirks = 0, rsize = 0;
char *rdesc;
int n, len, insize = 0;
+ struct usbhid_device *usbhid;
/* Ignore all Wacom devices */
if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
@@ -1980,13 +1112,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
kfree(rdesc);
hid->quirks = quirks;
- hid->bufsize = HID_MIN_BUFFER_SIZE;
- hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
- hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
- hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+ if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
+ goto fail;
+
+ hid->driver_data = usbhid;
+ usbhid->hid = hid;
- if (hid->bufsize > HID_MAX_BUFFER_SIZE)
- hid->bufsize = HID_MAX_BUFFER_SIZE;
+ usbhid->bufsize = HID_MIN_BUFFER_SIZE;
+ hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
+ hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
+ hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize);
+
+ if (usbhid->bufsize > HID_MAX_BUFFER_SIZE)
+ usbhid->bufsize = HID_MAX_BUFFER_SIZE;
hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
@@ -2015,47 +1153,47 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
interval = hid_mousepoll_interval;
if (usb_endpoint_dir_in(endpoint)) {
- if (hid->urbin)
+ if (usbhid->urbin)
continue;
- if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
+ if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
+ usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize,
hid_irq_in, hid, interval);
- hid->urbin->transfer_dma = hid->inbuf_dma;
- hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
+ usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
} else {
- if (hid->urbout)
+ if (usbhid->urbout)
continue;
- if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
+ if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
- usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
+ usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0,
hid_irq_out, hid, interval);
- hid->urbout->transfer_dma = hid->outbuf_dma;
- hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usbhid->urbout->transfer_dma = usbhid->outbuf_dma;
+ usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
}
- if (!hid->urbin) {
+ if (!usbhid->urbin) {
err("couldn't find an input interrupt endpoint");
goto fail;
}
init_waitqueue_head(&hid->wait);
- INIT_WORK(&hid->reset_work, hid_reset);
- setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
+ INIT_WORK(&usbhid->reset_work, hid_reset);
+ setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
- spin_lock_init(&hid->inlock);
- spin_lock_init(&hid->outlock);
- spin_lock_init(&hid->ctrllock);
+ spin_lock_init(&usbhid->inlock);
+ spin_lock_init(&usbhid->outlock);
+ spin_lock_init(&usbhid->ctrllock);
hid->version = le16_to_cpu(hdesc->bcdHID);
hid->country = hdesc->bCountryCode;
- hid->dev = dev;
- hid->intf = intf;
- hid->ifnum = interface->desc.bInterfaceNumber;
+ hid->dev = &intf->dev;
+ usbhid->intf = intf;
+ usbhid->ifnum = interface->desc.bInterfaceNumber;
hid->name[0] = 0;
@@ -2073,6 +1211,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
+ hid->bus = BUS_USB;
+ hid->vendor = dev->descriptor.idVendor;
+ hid->product = dev->descriptor.idProduct;
+
usb_make_path(dev, hid->phys, sizeof(hid->phys));
strlcat(hid->phys, "/input", sizeof(hid->phys));
len = strlen(hid->phys);
@@ -2083,22 +1225,28 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
hid->uniq[0] = 0;
- hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
- if (!hid->urbctrl)
+ usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+ if (!usbhid->urbctrl)
goto fail;
- usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
- hid->ctrlbuf, 1, hid_ctrl, hid);
- hid->urbctrl->setup_dma = hid->cr_dma;
- hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
- hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
-
+ usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
+ usbhid->ctrlbuf, 1, hid_ctrl, hid);
+ usbhid->urbctrl->setup_dma = usbhid->cr_dma;
+ usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
+ usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+ hid->hidinput_input_event = usb_hidinput_input_event;
+ hid->hidinput_open = hidinput_open;
+ hid->hidinput_close = hidinput_close;
+#ifdef CONFIG_USB_HIDDEV
+ hid->hiddev_hid_event = hiddev_hid_event;
+ hid->hiddev_report_event = hiddev_report_event;
+#endif
return hid;
fail:
- usb_free_urb(hid->urbin);
- usb_free_urb(hid->urbout);
- usb_free_urb(hid->urbctrl);
+ usb_free_urb(usbhid->urbin);
+ usb_free_urb(usbhid->urbout);
+ usb_free_urb(usbhid->urbctrl);
hid_free_buffers(dev, hid);
hid_free_device(hid);
@@ -2108,18 +1256,21 @@ fail:
static void hid_disconnect(struct usb_interface *intf)
{
struct hid_device *hid = usb_get_intfdata (intf);
+ struct usbhid_device *usbhid;
if (!hid)
return;
- spin_lock_irq(&hid->inlock); /* Sync with error handler */
+ usbhid = hid->driver_data;
+
+ spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
usb_set_intfdata(intf, NULL);
- spin_unlock_irq(&hid->inlock);
- usb_kill_urb(hid->urbin);
- usb_kill_urb(hid->urbout);
- usb_kill_urb(hid->urbctrl);
+ spin_unlock_irq(&usbhid->inlock);
+ usb_kill_urb(usbhid->urbin);
+ usb_kill_urb(usbhid->urbout);
+ usb_kill_urb(usbhid->urbctrl);
- del_timer_sync(&hid->io_retry);
+ del_timer_sync(&usbhid->io_retry);
flush_scheduled_work();
if (hid->claimed & HID_CLAIMED_INPUT)
@@ -2127,11 +1278,11 @@ static void hid_disconnect(struct usb_interface *intf)
if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_disconnect(hid);
- usb_free_urb(hid->urbin);
- usb_free_urb(hid->urbctrl);
- usb_free_urb(hid->urbout);
+ usb_free_urb(usbhid->urbin);
+ usb_free_urb(usbhid->urbctrl);
+ usb_free_urb(usbhid->urbout);
- hid_free_buffers(hid->dev, hid);
+ hid_free_buffers(hid_to_usb_dev(hid), hid);
hid_free_device(hid);
}
@@ -2148,7 +1299,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (!(hid = usb_hid_configure(intf)))
return -ENODEV;
- hid_init_reports(hid);
+ usbhid_init_reports(hid);
hid_dump_device(hid);
if (!hidinput_connect(hid))
@@ -2164,6 +1315,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
return -ENODEV;
}
+ /* 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
+ * only useful in this case, and not for multi-input quirks. */
+ if ((hid->claimed & HID_CLAIMED_INPUT) &&
+ !(hid->quirks & HID_QUIRK_MULTI_INPUT))
+ hid_ff_init(hid);
+
printk(KERN_INFO);
if (hid->claimed & HID_CLAIMED_INPUT)
@@ -2194,12 +1352,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
static int hid_suspend(struct usb_interface *intf, pm_message_t message)
{
struct hid_device *hid = usb_get_intfdata (intf);
+ struct usbhid_device *usbhid = hid->driver_data;
- spin_lock_irq(&hid->inlock); /* Sync with error handler */
- set_bit(HID_SUSPENDED, &hid->iofl);
- spin_unlock_irq(&hid->inlock);
- del_timer(&hid->io_retry);
- usb_kill_urb(hid->urbin);
+ spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
+ set_bit(HID_SUSPENDED, &usbhid->iofl);
+ spin_unlock_irq(&usbhid->inlock);
+ del_timer(&usbhid->io_retry);
+ usb_kill_urb(usbhid->urbin);
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
@@ -2207,10 +1366,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
static int hid_resume(struct usb_interface *intf)
{
struct hid_device *hid = usb_get_intfdata (intf);
+ struct usbhid_device *usbhid = hid->driver_data;
int status;
- clear_bit(HID_SUSPENDED, &hid->iofl);
- hid->retry_delay = 0;
+ clear_bit(HID_SUSPENDED, &usbhid->iofl);
+ usbhid->retry_delay = 0;
status = hid_start_in(hid);
dev_dbg(&intf->dev, "resume status %d\n", status);
return status;
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index a8fc46c721c..59ed65e7a62 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -32,7 +32,8 @@
#undef DEBUG
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
/*
* This table contains pointers to initializers. To add support for new
@@ -70,8 +71,8 @@ static struct hid_ff_initializer inits[] = {
int hid_ff_init(struct hid_device* hid)
{
struct hid_ff_initializer *init;
- int vendor = le16_to_cpu(hid->dev->descriptor.idVendor);
- int product = le16_to_cpu(hid->dev->descriptor.idProduct);
+ int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
+ int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);
for (init = inits; init->idVendor; init++)
if (init->idVendor == vendor && init->idProduct == product)
@@ -79,3 +80,5 @@ int hid_ff_init(struct hid_device* hid)
return init->init(hid);
}
+EXPORT_SYMBOL_GPL(hid_ff_init);
+
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 93da222b6da..e4746626856 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -29,7 +29,8 @@
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
struct device_type {
u16 idVendor;
@@ -75,7 +76,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[2] = x;
report->field[0]->value[3] = y;
dbg("(x, y)=(%04x, %04x)", x, y);
- hid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
case FF_RUMBLE:
@@ -90,7 +91,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[2] = left;
report->field[0]->value[3] = right;
dbg("(left, right)=(%04x, %04x)", left, right);
- hid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
}
return 0;
diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c
index 5420c13eb8e..cbd2d53feff 100644
--- a/drivers/usb/input/hid-pidff.c
+++ b/drivers/usb/input/hid-pidff.c
@@ -28,7 +28,9 @@
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+
+#include "usbhid.h"
#define PID_EFFECTS_MAX 64
@@ -260,7 +262,7 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
debug("attack %u => %d", envelope->attack_level,
pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
USB_DIR_OUT);
}
@@ -287,7 +289,7 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
effect->u.constant.level);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
USB_DIR_OUT);
}
@@ -322,7 +324,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
pidff->effect_direction);
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
USB_DIR_OUT);
}
@@ -354,7 +356,7 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
USB_DIR_OUT);
}
@@ -396,8 +398,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
effect->u.condition[i].left_saturation);
pidff_set(&pidff->set_condition[PID_DEAD_BAND],
effect->u.condition[i].deadband);
- hid_wait_io(pidff->hid);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
+ usbhid_wait_io(pidff->hid);
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
USB_DIR_OUT);
}
}
@@ -438,7 +440,7 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
effect->u.ramp.start_level);
pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
effect->u.ramp.end_level);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
USB_DIR_OUT);
}
@@ -463,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
int j;
pidff->create_new_effect_type->value[0] = efnum;
- hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
USB_DIR_OUT);
debug("create_new_effect sent, type: %d", efnum);
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
pidff->block_load_status->value[0] = 0;
- hid_wait_io(pidff->hid);
+ usbhid_wait_io(pidff->hid);
for (j = 0; j < 60; j++) {
debug("pid_block_load requested");
- hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
USB_DIR_IN);
- hid_wait_io(pidff->hid);
+ usbhid_wait_io(pidff->hid);
if (pidff->block_load_status->value[0] ==
pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
debug("device reported free memory: %d bytes",
@@ -511,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
}
- hid_wait_io(pidff->hid);
- hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+ usbhid_wait_io(pidff->hid);
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
USB_DIR_OUT);
}
@@ -534,7 +536,7 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
{
pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
- hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
USB_DIR_OUT);
}
@@ -714,7 +716,7 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
struct pidff_device *pidff = dev->ff->private;
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
- hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
USB_DIR_OUT);
}
@@ -739,7 +741,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
pidff->set_effect[PID_START_DELAY].value[0] = 0;
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
USB_DIR_OUT);
}
@@ -1163,19 +1165,19 @@ static void pidff_reset(struct pidff_device *pidff)
pidff->device_control->value[0] = pidff->control_id[PID_RESET];
/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
- hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
- hid_wait_io(hid);
- hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+ usbhid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+ usbhid_wait_io(hid);
pidff->device_control->value[0] =
pidff->control_id[PID_ENABLE_ACTUATORS];
- hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+ usbhid_wait_io(hid);
/* pool report is sometimes messed up, refetch it */
- hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
+ usbhid_wait_io(hid);
if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0];
@@ -1187,9 +1189,9 @@ static void pidff_reset(struct pidff_device *pidff)
break;
}
debug("pid_pool requested again");
- hid_submit_report(hid, pidff->reports[PID_POOL],
+ usbhid_submit_report(hid, pidff->reports[PID_POOL],
USB_DIR_IN);
- hid_wait_io(hid);
+ usbhid_wait_io(hid);
}
}
}
@@ -1275,7 +1277,7 @@ int hid_pidff_init(struct hid_device *hid)
if (test_bit(FF_GAIN, dev->ffbit)) {
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
- hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
USB_DIR_OUT);
}
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c
index 2d5be4c318a..ab67331620d 100644
--- a/drivers/usb/input/hid-tmff.c
+++ b/drivers/usb/input/hid-tmff.c
@@ -32,7 +32,8 @@
#undef DEBUG
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
/* Usages for thrustmaster devices I know about */
#define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb)
@@ -70,7 +71,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
tmff->rumble->value[0] = left;
tmff->rumble->value[1] = right;
dbg("(left,right)=(%08x, %08x)", left, right);
- hid_submit_report(hid, tmff->report, USB_DIR_OUT);
+ usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
return 0;
}
diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c
index d2ce3214572..7bd8238ca21 100644
--- a/drivers/usb/input/hid-zpff.c
+++ b/drivers/usb/input/hid-zpff.c
@@ -27,7 +27,8 @@
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
struct zpff_device {
struct hid_report *report;
@@ -56,7 +57,7 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right;
debug("running with 0x%02x 0x%02x", left, right);
- hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+ usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
return 0;
}
@@ -101,7 +102,7 @@ int hid_zpff_init(struct hid_device *hid)
zpff->report->field[1]->value[0] = 0x02;
zpff->report->field[2]->value[0] = 0x00;
zpff->report->field[3]->value[0] = 0x00;
- hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+ usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
printk(KERN_INFO "Force feedback for Zeroplus based devices by "
"Anssi Hannula <anssi.hannula@gmail.com>\n");
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 7dc14d0cacc..a8b3d66cd49 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -32,8 +32,9 @@
#include <linux/smp_lock.h>
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
#include <linux/hiddev.h>
+#include "usbhid.h"
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define HIDDEV_MINOR_BASE 0
@@ -196,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
hiddev_send_event(hid, &uref);
}
-
+EXPORT_SYMBOL_GPL(hiddev_hid_event);
void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
{
@@ -213,6 +214,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
hiddev_send_event(hid, &uref);
}
+
/*
* fasync file op
*/
@@ -239,7 +241,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
if (!--list->hiddev->open) {
if (list->hiddev->exist)
- hid_close(list->hiddev->hid);
+ usbhid_close(list->hiddev->hid);
else
kfree(list->hiddev);
}
@@ -270,7 +272,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
if (!list->hiddev->open++)
if (list->hiddev->exist)
- hid_open(hiddev_table[i]->hid);
+ usbhid_open(hiddev_table[i]->hid);
return 0;
}
@@ -382,7 +384,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct hiddev_list *list = file->private_data;
struct hiddev *hiddev = list->hiddev;
struct hid_device *hid = hiddev->hid;
- struct usb_device *dev = hid->dev;
+ struct usb_device *dev = hid_to_usb_dev(hid);
struct hiddev_collection_info cinfo;
struct hiddev_report_info rinfo;
struct hiddev_field_info finfo;
@@ -391,6 +393,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct hiddev_devinfo dinfo;
struct hid_report *report;
struct hid_field *field;
+ struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg;
int i;
@@ -420,7 +423,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dinfo.bustype = BUS_USB;
dinfo.busnum = dev->bus->busnum;
dinfo.devnum = dev->devnum;
- dinfo.ifnum = hid->ifnum;
+ dinfo.ifnum = usbhid->ifnum;
dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
@@ -479,7 +482,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
}
case HIDIOCINITREPORT:
- hid_init_reports(hid);
+ usbhid_init_reports(hid);
return 0;
@@ -493,8 +496,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- hid_submit_report(hid, report, USB_DIR_IN);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_wait_io(hid);
return 0;
@@ -508,8 +511,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- hid_submit_report(hid, report, USB_DIR_OUT);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_wait_io(hid);
return 0;
@@ -745,6 +748,7 @@ static struct usb_class_driver hiddev_class = {
int hiddev_connect(struct hid_device *hid)
{
struct hiddev *hiddev;
+ struct usbhid_device *usbhid = hid->driver_data;
int i;
int retval;
@@ -760,7 +764,7 @@ int hiddev_connect(struct hid_device *hid)
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1;
- retval = usb_register_dev(hid->intf, &hiddev_class);
+ retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
err("Not able to get a minor for this device.");
kfree(hiddev);
@@ -772,10 +776,10 @@ int hiddev_connect(struct hid_device *hid)
hiddev->hid = hid;
hiddev->exist = 1;
- hid->minor = hid->intf->minor;
+ hid->minor = usbhid->intf->minor;
hid->hiddev = hiddev;
- hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+ hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
return 0;
}
@@ -788,14 +792,15 @@ static struct usb_class_driver hiddev_class;
void hiddev_disconnect(struct hid_device *hid)
{
struct hiddev *hiddev = hid->hiddev;
+ struct usbhid_device *usbhid = hid->driver_data;
hiddev->exist = 0;
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
- usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+ usb_deregister_dev(usbhid->intf, &hiddev_class);
if (hiddev->open) {
- hid_close(hiddev->hid);
+ usbhid_close(hiddev->hid);
wake_up_interruptible(&hiddev->wait);
} else {
kfree(hiddev);
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h
new file mode 100644
index 00000000000..0023f96d429
--- /dev/null
+++ b/drivers/usb/input/usbhid.h
@@ -0,0 +1,87 @@
+#ifndef __USBHID_H
+#define __USBHID_H
+
+/*
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2001 Vojtech Pavlik
+ * Copyright (c) 2006 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+
+/* API provided by hid-core.c for USB HID drivers */
+int usbhid_wait_io(struct hid_device* hid);
+void usbhid_close(struct hid_device *hid);
+int usbhid_open(struct hid_device *hid);
+void usbhid_init_reports(struct hid_device *hid);
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
+
+/*
+ * USB-specific HID struct, to be pointed to
+ * from struct hid_device->driver_data
+ */
+
+struct usbhid_device {
+ struct hid_device *hid; /* pointer to corresponding HID dev */
+
+ struct usb_interface *intf; /* USB interface */
+ int ifnum; /* USB interface number */
+
+ unsigned int bufsize; /* URB buffer size */
+
+ struct urb *urbin; /* Input URB */
+ char *inbuf; /* Input buffer */
+ dma_addr_t inbuf_dma; /* Input buffer dma */
+ spinlock_t inlock; /* Input fifo spinlock */
+
+ struct urb *urbctrl; /* Control URB */
+ struct usb_ctrlrequest *cr; /* Control request struct */
+ dma_addr_t cr_dma; /* Control request struct dma */
+ struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
+ unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
+ char *ctrlbuf; /* Control buffer */
+ dma_addr_t ctrlbuf_dma; /* Control buffer dma */
+ spinlock_t ctrllock; /* Control fifo spinlock */
+
+ struct urb *urbout; /* Output URB */
+ struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
+ unsigned char outhead, outtail; /* Output pipe fifo head & tail */
+ char *outbuf; /* Output buffer */
+ dma_addr_t outbuf_dma; /* Output buffer dma */
+ spinlock_t outlock; /* Output fifo spinlock */
+
+ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+ struct timer_list io_retry; /* Retry timer */
+ unsigned long stop_retry; /* Time to give up, in jiffies */
+ unsigned int retry_delay; /* Delay length in ms */
+ struct work_struct reset_work; /* Task context for resets */
+
+};
+
+#define hid_to_usb_dev(hid_dev) \
+ container_of(hid_dev->dev->parent, struct usb_device, dev)
+
+#endif
+
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 7f3c57da9bc..86e37a20f8e 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -66,7 +66,7 @@ struct usbtouch_device_info {
void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
int (*get_pkt_len) (unsigned char *pkt, int len);
- int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press);
+ int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
int (*init) (struct usbtouch_usb *usbtouch);
};
@@ -85,6 +85,9 @@ struct usbtouch_usb {
struct usbtouch_device_info *type;
char name[128];
char phys[64];
+
+ int x, y;
+ int touch, press;
};
@@ -161,14 +164,14 @@ static struct usb_device_id usbtouch_devices[] = {
#define EGALAX_PKT_TYPE_REPT 0x80
#define EGALAX_PKT_TYPE_DIAG 0x0A
-static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
return 0;
- *x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
- *y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
- *touch = pkt[0] & 0x01;
+ dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
+ dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
+ dev->touch = pkt[0] & 0x01;
return 1;
}
@@ -195,11 +198,11 @@ static int egalax_get_pkt_len(unsigned char *buf, int len)
* PanJit Part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
-static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = ((pkt[2] & 0x0F) << 8) | pkt[1];
- *y = ((pkt[4] & 0x0F) << 8) | pkt[3];
- *touch = pkt[0] & 0x01;
+ dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
+ dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3];
+ dev->touch = pkt[0] & 0x01;
return 1;
}
@@ -215,11 +218,11 @@ static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
#define MTOUCHUSB_RESET 7
#define MTOUCHUSB_REQ_CTRLLR_ID 10
-static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = (pkt[8] << 8) | pkt[7];
- *y = (pkt[10] << 8) | pkt[9];
- *touch = (pkt[2] & 0x40) ? 1 : 0;
+ dev->x = (pkt[8] << 8) | pkt[7];
+ dev->y = (pkt[10] << 8) | pkt[9];
+ dev->touch = (pkt[2] & 0x40) ? 1 : 0;
return 1;
}
@@ -260,14 +263,32 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
* ITM Part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_ITM
-static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
- *y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
- *press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
- *touch = ~pkt[7] & 0x20;
+ int touch;
+ /*
+ * ITM devices report invalid x/y data if not touched.
+ * if the screen was touched before but is not touched any more
+ * report touch as 0 with the last valid x/y data once. then stop
+ * reporting data until touched again.
+ */
+ dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
+
+ touch = ~pkt[7] & 0x20;
+ if (!touch) {
+ if (dev->touch) {
+ dev->touch = 0;
+ return 1;
+ }
- return *touch;
+ return 0;
+ }
+
+ dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
+ dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+ dev->touch = touch;
+
+ return 1;
}
#endif
@@ -276,7 +297,7 @@ static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *pr
* eTurboTouch part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
-static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
unsigned int shift;
@@ -285,9 +306,9 @@ static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
return 0;
shift = (6 - (pkt[0] & 0x03));
- *x = ((pkt[3] << 7) | pkt[4]) >> shift;
- *y = ((pkt[1] << 7) | pkt[2]) >> shift;
- *touch = (pkt[0] & 0x10) ? 1 : 0;
+ dev->x = ((pkt[3] << 7) | pkt[4]) >> shift;
+ dev->y = ((pkt[1] << 7) | pkt[2]) >> shift;
+ dev->touch = (pkt[0] & 0x10) ? 1 : 0;
return 1;
}
@@ -307,14 +328,14 @@ static int eturbo_get_pkt_len(unsigned char *buf, int len)
* Gunze part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
-static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
return 0;
- *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
- *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
- *touch = pkt[0] & 0x20;
+ dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
+ dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
+ dev->touch = pkt[0] & 0x20;
return 1;
}
@@ -383,11 +404,11 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
}
-static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = ((pkt[2] & 0x03) << 8) | pkt[1];
- *y = ((pkt[4] & 0x03) << 8) | pkt[3];
- *touch = pkt[0] & 0x01;
+ dev->x = ((pkt[2] & 0x03) << 8) | pkt[1];
+ dev->y = ((pkt[4] & 0x03) << 8) | pkt[3];
+ dev->touch = pkt[0] & 0x01;
return 1;
}
@@ -492,23 +513,22 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
unsigned char *pkt, int len)
{
- int x, y, touch, press;
struct usbtouch_device_info *type = usbtouch->type;
- if (!type->read_data(pkt, &x, &y, &touch, &press))
+ if (!type->read_data(usbtouch, pkt))
return;
- input_report_key(usbtouch->input, BTN_TOUCH, touch);
+ input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
if (swap_xy) {
- input_report_abs(usbtouch->input, ABS_X, y);
- input_report_abs(usbtouch->input, ABS_Y, x);
+ input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
+ input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
} else {
- input_report_abs(usbtouch->input, ABS_X, x);
- input_report_abs(usbtouch->input, ABS_Y, y);
+ input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
+ input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
}
if (type->max_press)
- input_report_abs(usbtouch->input, ABS_PRESSURE, press);
+ input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
input_sync(usbtouch->input);
}
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index e7cc20ab815..12b42746ded 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -159,13 +159,13 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3);
- input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+ input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
}
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
- input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
index 92726fe8937..4142e36730f 100644
--- a/drivers/usb/input/wacom_wac.c
+++ b/drivers/usb/input/wacom_wac.c
@@ -209,13 +209,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
}
- }
-
- if (data[1] & 0x10)
wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+ }
else
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
- wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10);
+
+ if (data[1] & 0x10) /* only report prox-in when in area */
+ wacom_report_key(wcombo, wacom->tool[0], 1);
+ if (!(data[1] & 0x90)) /* report prox-out when physically out */
+ wacom_report_key(wcombo, wacom->tool[0], 0);
wacom_input_sync(wcombo);
/* send pad data */
@@ -405,7 +407,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
return 0;
- if (wacom->features->type >= INTUOS3) {
+ if (wacom->features->type >= INTUOS3S) {
wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
@@ -423,7 +425,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if (data[1] & 0x02) {
/* Rotation packet */
- if (wacom->features->type >= INTUOS3) {
+ if (wacom->features->type >= INTUOS3S) {
/* I3 marker pen rotation reported as wheel
* due to valuator limitation
*/
@@ -547,11 +549,11 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE },
{ "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 },
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 },
- { "Wacom Volito", 8, 5104, 3712, 511, 0, GRAPHIRE },
- { "Wacom PenStation2", 8, 3250, 2320, 255, 0, GRAPHIRE },
- { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 0, GRAPHIRE },
- { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 0, GRAPHIRE },
- { "Wacom PenPartner2", 8, 3250, 2320, 255, 0, GRAPHIRE },
+ { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE },
+ { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE },
+ { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
+ { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
+ { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS },
@@ -580,7 +582,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 },
- { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 15, INTUOS3S },
+ { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS },
{ }
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 02cbb7fff24..a7932a72d29 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -281,7 +281,7 @@ static int appledisplay_probe(struct usb_interface *iface,
/* Register backlight device */
snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
atomic_inc_return(&count_displays) - 1);
- pdata->bd = backlight_device_register(bl_name, pdata,
+ pdata->bd = backlight_device_register(bl_name, NULL, NULL,
&appledisplay_bl_data);
if (IS_ERR(pdata->bd)) {
err("appledisplay: Backlight registration failed");
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index c703f73e165..b5332e679c4 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -766,7 +766,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned
bep->bufp = kmalloc (bufsize, GFP_KERNEL);
if (!bep->bufp)
goto bl_fail;
- bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
+ bep->dr = kmalloc(sizeof (struct usb_ctrlrequest), GFP_KERNEL);
if (!bep->dr)
goto bl_fail;
bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
@@ -1376,7 +1376,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
}
/* we have access to the device. Now lets allocate memory */
- ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
+ ccp = kzalloc(sizeof(auerchar_t), GFP_KERNEL);
if (ccp == NULL) {
err ("out of memory");
ret = -ENOMEM;
@@ -1384,7 +1384,6 @@ static int auerchar_open (struct inode *inode, struct file *file)
}
/* Initialize device descriptor */
- memset( ccp, 0, sizeof(auerchar_t));
init_MUTEX( &ccp->mutex);
init_MUTEX( &ccp->readmutex);
auerbuf_init (&ccp->bufctl);
@@ -1912,14 +1911,13 @@ static int auerswald_probe (struct usb_interface *intf,
return -ENODEV;
/* allocate memory for our device and initialize it */
- cp = kmalloc (sizeof(auerswald_t), GFP_KERNEL);
+ cp = kzalloc (sizeof(auerswald_t), GFP_KERNEL);
if (cp == NULL) {
err ("out of memory");
goto pfail;
}
/* Initialize device descriptor */
- memset (cp, 0, sizeof(auerswald_t));
init_MUTEX (&cp->mutex);
cp->usbdev = usbdev;
auerchain_init (&cp->controlchain);
@@ -1969,7 +1967,7 @@ static int auerswald_probe (struct usb_interface *intf,
info("device is a %s", cp->dev_desc);
/* get the maximum allowed control transfer length */
- pbuf = (__le16 *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */
+ pbuf = kmalloc(2, GFP_KERNEL); /* use an allocated buffer because of urb target */
if (!pbuf) {
err( "out of memory");
goto pfail;
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 18b1925032a..41c0161abdb 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -40,6 +40,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/ioctl.h>
+#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
@@ -51,6 +52,10 @@ MODULE_AUTHOR("Tony Olech");
MODULE_DESCRIPTION("FTDI ELAN driver");
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+static int distrust_firmware = 1;
+module_param(distrust_firmware, bool, 0);
+MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+ "t setup");
extern struct platform_driver u132_platform_driver;
static struct workqueue_struct *status_queue;
static struct workqueue_struct *command_queue;
@@ -66,7 +71,9 @@ static struct list_head ftdi_static_list;
* end of the global variables protected by ftdi_module_lock
*/
#include "usb_u132.h"
-#define TD_DEVNOTRESP 5
+#include <asm/io.h>
+#include "../core/hcd.h"
+#include "../host/ohci.h"
/* Define these values to match your devices*/
#define USB_FTDI_ELAN_VENDOR_ID 0x0403
#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
@@ -551,7 +558,7 @@ static void ftdi_elan_status_work(struct work_struct *work)
} else {
dev_err(&ftdi->udev->dev, "initialized failed - trying "
"again in 10 seconds\n");
- work_delay_in_msec = 10 *1000;
+ work_delay_in_msec = 1 *1000;
}
} else if (ftdi->registered == 0) {
work_delay_in_msec = 10;
@@ -2288,82 +2295,288 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
}
}
-static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+
+#define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \
+ offsetof(struct ohci_regs, member), 0, data);
+#define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
+ offsetof(struct ohci_regs, member), 0, data);
+#define OHCI_QUIRK_AMD756 0x01
+#define OHCI_QUIRK_SUPERIO 0x02
+#define OHCI_QUIRK_INITRESET 0x04
+#define OHCI_BIG_ENDIAN 0x08
+#define OHCI_QUIRK_ZFMICRO 0x10
+#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+ OHCI_INTR_WDH)
+static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk)
+{
+ int devices = 0;
+ int retval;
+ u32 hc_control;
+ int num_ports;
+ u32 control;
+ u32 rh_a = -1;
+ u32 status;
+ u32 fminterval;
+ u32 hc_fminterval;
+ u32 periodicstart;
+ u32 cmdstatus;
+ u32 roothub_a;
+ int mask = OHCI_INTR_INIT;
+ int sleep_time = 0;
+ int reset_timeout = 30; /* ... allow extra time */
+ int temp;
+ retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a);
+ if (retval)
+ return retval;
+ num_ports = rh_a & RH_A_NDP;
+ retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval);
+ if (retval)
+ return retval;
+ hc_fminterval &= 0x3fff;
+ if (hc_fminterval != FI) {
+ }
+ hc_fminterval |= FSMP(hc_fminterval) << 16;
+ retval = ftdi_read_pcimem(ftdi, control, &hc_control);
+ if (retval)
+ return retval;
+ switch (hc_control & OHCI_CTRL_HCFS) {
+ case OHCI_USB_OPER:
+ sleep_time = 0;
+ break;
+ case OHCI_USB_SUSPEND:
+ case OHCI_USB_RESUME:
+ hc_control &= OHCI_CTRL_RWC;
+ hc_control |= OHCI_USB_RESUME;
+ sleep_time = 10;
+ break;
+ default:
+ hc_control &= OHCI_CTRL_RWC;
+ hc_control |= OHCI_USB_RESET;
+ sleep_time = 50;
+ break;
+ }
+ retval = ftdi_write_pcimem(ftdi, control, hc_control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ msleep(sleep_time);
+ retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
+ if (retval)
+ return retval;
+ if (!(roothub_a & RH_A_NPS)) { /* power down each port */
+ for (temp = 0; temp < num_ports; temp++) {
+ retval = ftdi_write_pcimem(ftdi,
+ roothub.portstatus[temp], RH_PS_LSDA);
+ if (retval)
+ return retval;
+ }
+ }
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR);
+ if (retval)
+ return retval;
+ extra:{
+ retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
+ if (retval)
+ return retval;
+ if (0 != (status & OHCI_HCR)) {
+ if (--reset_timeout == 0) {
+ dev_err(&ftdi->udev->dev, "USB HC reset timed o"
+ "ut!\n");
+ return -ENODEV;
+ } else {
+ msleep(5);
+ goto extra;
+ }
+ }
+ }
+ if (quirk & OHCI_QUIRK_INITRESET) {
+ retval = ftdi_write_pcimem(ftdi, control, hc_control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ }
+ retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, fminterval,
+ ((fminterval & FIT) ^ FIT) | hc_fminterval);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, periodicstart,
+ ((9 *hc_fminterval) / 10) & 0x3fff);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart);
+ if (retval)
+ return retval;
+ if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+ if (!(quirk & OHCI_QUIRK_INITRESET)) {
+ quirk |= OHCI_QUIRK_INITRESET;
+ goto retry;
+ } else
+ dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n",
+ fminterval, periodicstart);
+ } /* start controller operations */
+ hc_control &= OHCI_CTRL_RWC;
+ hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+ retval = ftdi_write_pcimem(ftdi, control, hc_control);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, intrstatus, mask);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, intrdisable,
+ OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+ OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+ OHCI_INTR_SO);
+ if (retval)
+ return retval; /* handle root hub init quirks ... */
+ retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
+ if (retval)
+ return retval;
+ roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+ if (quirk & OHCI_QUIRK_SUPERIO) {
+ roothub_a |= RH_A_NOCP;
+ roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+ retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
+ if (retval)
+ return retval;
+ } else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) {
+ roothub_a |= RH_A_NPS;
+ retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
+ if (retval)
+ return retval;
+ }
+ retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, roothub.b,
+ (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ mdelay((roothub_a >> 23) & 0x1fe);
+ for (temp = 0; temp < num_ports; temp++) {
+ u32 portstatus;
+ retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp],
+ &portstatus);
+ if (retval)
+ return retval;
+ if (1 & portstatus)
+ devices += 1;
+ }
+ return devices;
+}
+
+static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn)
{
u32 latence_timer;
- u32 controlreg;
int UxxxStatus;
u32 pcidata;
int reg = 0;
- int foundOHCI = 0;
- u8 fn;
- int activePCIfn = 0;
- u32 pciVID = 0;
- u32 pciPID = 0;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
- if (UxxxStatus)
- return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
- if (UxxxStatus)
- return UxxxStatus;
- msleep(750);
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+ int activePCIfn = fn << 8;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+ reg = 16;
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+ 0xFFFFFFFF);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+ 0xF0000000);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- msleep(250);
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+ reg = 12;
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &latence_timer);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ latence_timer &= 0xFFFF00FF;
+ latence_timer |= 0x00001600;
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+ latence_timer);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ reg = 4;
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+ 0x06);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- msleep(1000);
- for (fn = 0; (fn < 4) && (!foundOHCI); fn++) {
- activePCIfn = fn << 8;
- ftdi->function = fn + 1;
- UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
- &pcidata);
+ for (reg = 0; reg <= 0x54; reg += 4) {
+ UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (UxxxStatus)
return UxxxStatus;
- pciVID = pcidata & 0xFFFF;
- pciPID = (pcidata >> 16) & 0xFFFF;
- if ((pciVID == 0x1045) && (pciPID == 0xc861)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) {
- }
- }
- if (foundOHCI == 0) {
- return -ENXIO;
}
- ftdi->platform_data.vendor = pciVID;
- ftdi->platform_data.device = pciPID;
+ return 0;
+}
+
+static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn)
+{
+ u32 latence_timer;
+ int UxxxStatus;
+ u32 pcidata;
+ int reg = 0;
+ int activePCIfn = fn << 8;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
if (UxxxStatus)
return UxxxStatus;
@@ -2377,7 +2590,7 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
- 0xF0000000);
+ 0x00000000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
@@ -2401,7 +2614,7 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
return UxxxStatus;
reg = 4;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
- 0x06);
+ 0x00);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
@@ -2411,159 +2624,139 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
return 0;
}
+static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
+{
+ int result;
+ int UxxxStatus;
+ UxxxStatus = ftdi_elan_setup_controller(ftdi, fn);
+ if (UxxxStatus)
+ return UxxxStatus;
+ result = ftdi_elan_check_controller(ftdi, quirk);
+ UxxxStatus = ftdi_elan_close_controller(ftdi, fn);
+ if (UxxxStatus)
+ return UxxxStatus;
+ return result;
+}
+
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+{
+ u32 controlreg;
+ u8 sensebits;
+ int UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
+ if (UxxxStatus)
+ return UxxxStatus;
+ msleep(750);
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+ if (UxxxStatus)
+ return UxxxStatus;
+ msleep(250);
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ msleep(1000);
+ sensebits = (controlreg >> 16) & 0x000F;
+ if (0x0D == sensebits)
+ return 0;
+ else
+ return - ENXIO;
+}
+
static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
{
+ int UxxxStatus;
u32 pcidata;
- int U132Status;
- int reg;
- int reset_repeat = 0;
- do_reset:reg = 8;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01);
- if (U132Status)
- return U132Status;
- reset_check:{
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- if (pcidata & 1) {
- msleep(500);
- if (reset_repeat++ > 100) {
- reset_repeat = 0;
- goto do_reset;
- } else
- goto reset_check;
+ int reg = 0;
+ u8 fn;
+ int activePCIfn = 0;
+ int max_devices = 0;
+ int controllers = 0;
+ int unrecognized = 0;
+ ftdi->function = 0;
+ for (fn = 0; (fn < 4); fn++) {
+ u32 pciVID = 0;
+ u32 pciPID = 0;
+ int devices = 0;
+ activePCIfn = fn << 8;
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
+ if (UxxxStatus)
+ return UxxxStatus;
+ pciVID = pcidata & 0xFFFF;
+ pciPID = (pcidata >> 16) & 0xFFFF;
+ if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035))
+ {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802))
+ {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) {
+ devices = ftdi_elan_found_controller(ftdi, fn,
+ OHCI_QUIRK_AMD756);
+ controllers += 1;
+ } else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) {
+ devices = ftdi_elan_found_controller(ftdi, fn,
+ OHCI_QUIRK_ZFMICRO);
+ controllers += 1;
+ } else if (0 == pcidata) {
+ } else
+ unrecognized += 1;
+ if (devices > max_devices) {
+ max_devices = devices;
+ ftdi->function = fn + 1;
+ ftdi->platform_data.vendor = pciVID;
+ ftdi->platform_data.device = pciPID;
}
}
- goto dump_regs;
- msleep(500);
- reg = 0x28;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x40;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x34;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 4;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- msleep(250);
- reg = 8;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x28;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 8;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x48;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x58;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x34;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- msleep(100);
- reg = 0x50;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- if (!(pcidata & 1)) {
- msleep(500);
- goto power_check;
- }
- msleep(3000);
- reg = 0x54;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x58;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- msleep(750);
- reg = 0x54;
- if (0) {
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
- if (U132Status)
- return U132Status;
- }
- if (0) {
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- }
- reg = 0x54;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x58;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- dump_regs:for (reg = 0; reg <= 0x54; reg += 4) {
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
+ if (ftdi->function > 0) {
+ UxxxStatus = ftdi_elan_setup_controller(ftdi,
+ ftdi->function - 1);
+ if (UxxxStatus)
+ return UxxxStatus;
+ return 0;
+ } else if (controllers > 0) {
+ return -ENXIO;
+ } else if (unrecognized > 0) {
+ return -ENXIO;
+ } else {
+ ftdi->enumerated = 0;
+ return -ENXIO;
}
- return 0;
}
@@ -2688,6 +2881,7 @@ static void ftdi_elan_disconnect(struct usb_interface *interface)
platform_device_unregister(&ftdi->platform_dev);
ftdi->synchronized = 0;
ftdi->enumerated = 0;
+ ftdi->initialized = 0;
ftdi->registered = 0;
}
flush_workqueue(status_queue);
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 7163f05c5b2..0d9de2f7393 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -282,6 +282,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
dev->dev = NULL;
goto out;
}
+ dev_set_drvdata(dev->dev, dev);
servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index b99ca9c7982..0398908b15d 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3168,7 +3168,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
case SISUSB_GET_CONFIG:
case SISUSB_COMMAND:
lock_kernel();
- retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+ retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
unlock_kernel();
return retval;
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index bf26c3c5699..9148694627d 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -403,7 +403,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
- (u32)SISUSB_HADDR(x, y), 2, &written);
+ (long)SISUSB_HADDR(x, y), 2, &written);
mutex_unlock(&sisusb->lock);
}
@@ -438,7 +438,7 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
}
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
- (u32)SISUSB_HADDR(x, y), count * 2, &written);
+ (long)SISUSB_HADDR(x, y), count * 2, &written);
mutex_unlock(&sisusb->lock);
}
@@ -492,7 +492,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
- (u32)SISUSB_HADDR(x, y), length, &written);
+ (long)SISUSB_HADDR(x, y), length, &written);
mutex_unlock(&sisusb->lock);
}
@@ -564,7 +564,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx,
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
- (u32)SISUSB_HADDR(dx, dy), length, &written);
+ (long)SISUSB_HADDR(dx, dy), length, &written);
mutex_unlock(&sisusb->lock);
}
@@ -612,7 +612,7 @@ sisusbcon_switch(struct vc_data *c)
length);
sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
- (u32)SISUSB_HADDR(0, 0),
+ (long)SISUSB_HADDR(0, 0),
length, &written);
mutex_unlock(&sisusb->lock);
@@ -939,7 +939,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
}
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
- (u32)SISUSB_HADDR(0, t), length, &written);
+ (long)SISUSB_HADDR(0, t), length, &written);
mutex_unlock(&sisusb->lock);
diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c
index 33cd91d11ec..67e2fc20eee 100644
--- a/drivers/usb/misc/trancevibrator.c
+++ b/drivers/usb/misc/trancevibrator.c
@@ -120,8 +120,8 @@ static void tv_disconnect(struct usb_interface *interface)
struct trancevibrator *dev;
dev = usb_get_intfdata (interface);
- usb_set_intfdata(interface, NULL);
device_remove_file(&interface->dev, &dev_attr_speed);
+ usb_set_intfdata(interface, NULL);
usb_put_dev(dev->udev);
kfree(dev);
}
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 7e8a0acd52e..70250252ae2 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -705,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf,
/*
* Allocate parport interface
*/
- if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+ if (!(priv = kzalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) {
usb_put_dev(usbdev);
return -ENOMEM;
}
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 95e682e2c9d..896449f0cf8 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -898,7 +898,7 @@ static int ax88772_link_reset(struct usbnet *dev)
static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
{
- int ret;
+ int ret, embd_phy;
void *buf;
u16 rx_ctl;
struct asix_data *data = (struct asix_data *)&dev->data;
@@ -919,13 +919,15 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
goto out2;
+ /* 0x10 is the phy id of the embedded 10/100 ethernet phy */
+ embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
- 0x0000, 0, 0, buf)) < 0) {
+ embd_phy, 0, 0, buf)) < 0) {
dbg("Select PHY #1 failed: %d", ret);
goto out2;
}
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD)) < 0)
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0)
goto out2;
msleep(150);
@@ -933,8 +935,14 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
msleep(150);
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
- goto out2;
+ if (embd_phy) {
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0)
+ goto out2;
+ }
+ else {
+ if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0)
+ goto out2;
+ }
msleep(150);
rx_ctl = asix_read_rx_ctl(dev);
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index a3242be2195..a6f0f4d934d 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -79,160 +79,6 @@ struct gl_header {
struct gl_packet packets;
};
-#ifdef GENELINK_ACK
-
-// FIXME: this code is incomplete, not debugged; it doesn't
-// handle interrupts correctly; it should use the generic
-// status IRQ code (which didn't exist back in 2001).
-
-struct gl_priv {
- struct urb *irq_urb;
- char irq_buf [INTERRUPT_BUFSIZE];
-};
-
-static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value)
-{
- int retval;
-
- retval = usb_control_msg(dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- request,
- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- value,
- 0, // index
- 0, // data buffer
- 0, // size
- USB_CTRL_SET_TIMEOUT);
- return retval;
-}
-
-static void gl_interrupt_complete(struct urb *urb)
-{
- int status = urb->status;
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
- }
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status)
- err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
-}
-
-static int gl_interrupt_read(struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
- int retval;
-
- // issue usb interrupt read
- if (priv && priv->irq_urb) {
- // submit urb
- if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0)
- dbg("gl_interrupt_read: submit fail - %X...", retval);
- else
- dbg("gl_interrupt_read: submit success...");
- }
-
- return 0;
-}
-
-// check whether another side is connected
-static int genelink_check_connect(struct usbnet *dev)
-{
- int retval;
-
- dbg("genelink_check_connect...");
-
- // detect whether another side is connected
- if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
- dbg("%s: genelink_check_connect write fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- // usb interrupt read to ack another side
- if ((retval = gl_interrupt_read(dev)) != 0) {
- dbg("%s: genelink_check_connect read fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- dbg("%s: genelink_check_connect read success", dev->net->name);
- return 0;
-}
-
-// allocate and initialize the private data for genelink
-static int genelink_init(struct usbnet *dev)
-{
- struct gl_priv *priv;
-
- // allocate the private data structure
- if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) {
- dbg("%s: cannot allocate private data per device",
- dev->net->name);
- return -ENOMEM;
- }
-
- // allocate irq urb
- if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) {
- dbg("%s: cannot allocate private irq urb per device",
- dev->net->name);
- kfree(priv);
- return -ENOMEM;
- }
-
- // fill irq urb
- usb_fill_int_urb(priv->irq_urb, dev->udev,
- usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE),
- priv->irq_buf, INTERRUPT_BUFSIZE,
- gl_interrupt_complete, 0,
- GENELINK_INTERRUPT_INTERVAL);
-
- // set private data pointer
- dev->priv_data = priv;
-
- return 0;
-}
-
-// release the private data
-static int genelink_free(struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
-
- if (!priv)
- return 0;
-
-// FIXME: can't cancel here; it's synchronous, and
-// should have happened earlier in any case (interrupt
-// handling needs to be generic)
-
- // cancel irq urb first
- usb_kill_urb(priv->irq_urb);
-
- // free irq urb
- usb_free_urb(priv->irq_urb);
-
- // free the private data structure
- kfree(priv);
-
- return 0;
-}
-
-#endif
-
static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
struct gl_header *header;
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 99f26b3e502..a322a16d9cf 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -379,6 +379,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
{
int retval;
struct net_device *net = dev->net;
+ struct cdc_state *info = (void *) &dev->data;
union {
void *buf;
struct rndis_msg_hdr *header;
@@ -397,7 +398,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
return -ENOMEM;
retval = usbnet_generic_cdc_bind(dev, intf);
if (retval < 0)
- goto done;
+ goto fail;
net->hard_header_len += sizeof (struct rndis_data_hdr);
@@ -412,10 +413,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
if (unlikely(retval < 0)) {
/* it might not even be an RNDIS device!! */
dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
-fail:
- usb_driver_release_interface(driver_of(intf),
- ((struct cdc_state *)&(dev->data))->data);
- goto done;
+ goto fail_and_release;
}
dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size);
/* REVISIT: peripheral "alignment" request is ignored ... */
@@ -431,7 +429,7 @@ fail:
retval = rndis_command(dev, u.header);
if (unlikely(retval < 0)) {
dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
- goto fail;
+ goto fail_and_release;
}
tmp = le32_to_cpu(u.get_c->offset);
if (unlikely((tmp + 8) > (1024 - ETH_ALEN)
@@ -439,7 +437,7 @@ fail:
dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n",
tmp, le32_to_cpu(u.get_c->len));
retval = -EDOM;
- goto fail;
+ goto fail_and_release;
}
memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN);
@@ -455,11 +453,18 @@ fail:
retval = rndis_command(dev, u.header);
if (unlikely(retval < 0)) {
dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
- goto fail;
+ goto fail_and_release;
}
retval = 0;
-done:
+
+ kfree(u.buf);
+ return retval;
+
+fail_and_release:
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface(driver_of(intf), info->data);
+fail:
kfree(u.buf);
return retval;
}
@@ -469,7 +474,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
struct rndis_halt *halt;
/* try to clear any rndis state/activity (no i/o from stack!) */
- halt = kcalloc(1, sizeof *halt, GFP_KERNEL);
+ halt = kzalloc(sizeof *halt, GFP_KERNEL);
if (halt) {
halt->msg_type = RNDIS_MSG_HALT;
halt->msg_len = ccpu2(sizeof *halt);
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index c54235f73cb..670262a38a0 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -124,10 +124,11 @@
#define RX_URB_FAIL 3
/* Define these values to match your device */
-#define VENDOR_ID_REALTEK 0x0bda
+#define VENDOR_ID_REALTEK 0x0bda
#define VENDOR_ID_MELCO 0x0411
-#define VENDOR_ID_MICRONET 0x3980
+#define VENDOR_ID_MICRONET 0x3980
#define VENDOR_ID_LONGSHINE 0x07b8
+#define VENDOR_ID_OQO 0x1557
#define VENDOR_ID_ZYXEL 0x0586
#define PRODUCT_ID_RTL8150 0x8150
@@ -144,6 +145,7 @@ static struct usb_device_id rtl8150_table[] = {
{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
{USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},
{USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},
+ {USB_DEVICE(VENDOR_ID_OQO, PRODUCT_ID_RTL8150)},
{USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)},
{}
};
@@ -282,7 +284,8 @@ static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg)
u8 data[3], tmp;
data[0] = phy;
- *(data + 1) = cpu_to_le16p(&reg);
+ data[1] = reg & 0xff;
+ data[2] = (reg >> 8) & 0xff;
tmp = indx | PHY_WRITE | PHY_GO;
i = 0;
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 96c73726d74..f2ca76a9cba 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -19,8 +19,11 @@
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+ { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */
+ { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */
{ USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
+ { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 863966c1c5a..5261cd22ee6 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -156,7 +156,7 @@ cleanup:
}
static void ark3116_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
@@ -326,7 +326,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
static int ark3116_open(struct usb_serial_port *port, struct file *filp)
{
- struct termios tmp_termios;
+ struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
char *buf;
int result = 0;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 8835bb58ca9..38b4dae319e 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -92,7 +92,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial);
static int belkin_sa_open (struct usb_serial_port *port, struct file *filp);
static void belkin_sa_close (struct usb_serial_port *port, struct file *filp);
static void belkin_sa_read_int_callback (struct urb *urb);
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old);
+static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file);
@@ -333,7 +333,7 @@ exit:
__FUNCTION__, retval);
}
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 7167728d764..9386e216d68 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -65,7 +65,7 @@ static int usb_console_setup(struct console *co, char *options)
struct usb_serial_port *port;
int retval = 0;
struct tty_struct *tty;
- struct termios *termios;
+ struct ktermios *termios;
dbg ("%s", __FUNCTION__);
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index f95d42c0d16..7ebaffd6ed8 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -41,7 +41,7 @@ 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_set_termios(struct usb_serial_port*, struct ktermios*);
static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
unsigned int, unsigned int);
@@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ } /* Terminating Entry */
};
@@ -506,7 +507,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
}
static void cp2101_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
unsigned int cflag, old_cflag=0;
int baud=0, bits;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 093f303b318..6bc1f404e18 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -143,7 +143,7 @@ struct cypress_private {
wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
char prev_status, diff_status; /* used for TIOCMIWAIT */
/* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
- struct termios tmp_termios; /* stores the old termios settings */
+ struct ktermios tmp_termios; /* stores the old termios settings */
};
/* write buffer structure */
@@ -165,7 +165,7 @@ static int cypress_write (struct usb_serial_port *port, const unsigned char *b
static void cypress_send (struct usb_serial_port *port);
static int cypress_write_room (struct usb_serial_port *port);
static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void cypress_set_termios (struct usb_serial_port *port, struct termios * old);
+static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int cypress_tiocmget (struct usb_serial_port *port, struct file *file);
static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static int cypress_chars_in_buffer (struct usb_serial_port *port);
@@ -949,28 +949,13 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
switch (cmd) {
case TIOCGSERIAL:
- if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
+ if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) {
return -EFAULT;
}
return (0);
break;
case TIOCSSERIAL:
- if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
- return -EFAULT;
- }
- /* here we need to call cypress_set_termios to invoke the new settings */
- cypress_set_termios(port, &priv->tmp_termios);
- return (0);
- break;
- /* these are called when setting baud rate from gpsd */
- case TCGETS:
- if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
- return -EFAULT;
- }
- return (0);
- break;
- case TCSETS:
- if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
+ if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) {
return -EFAULT;
}
/* here we need to call cypress_set_termios to invoke the new settings */
@@ -1019,7 +1004,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
static void cypress_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
@@ -1493,7 +1478,7 @@ static struct cypress_buf *cypress_buf_alloc(unsigned int size)
if (size == 0)
return NULL;
- cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
+ cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 83d0e21145b..efd9ce3f931 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -449,7 +449,7 @@ static int digi_transmit_idle( struct usb_serial_port *port,
static void digi_rx_throttle (struct usb_serial_port *port);
static void digi_rx_unthrottle (struct usb_serial_port *port);
static void digi_set_termios( struct usb_serial_port *port,
- struct termios *old_termios );
+ struct ktermios *old_termios );
static void digi_break_ctl( struct usb_serial_port *port, int break_state );
static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg );
@@ -976,7 +976,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
static void digi_set_termios( struct usb_serial_port *port,
- struct termios *old_termios )
+ struct ktermios *old_termios )
{
struct digi_port *priv = usb_get_serial_port_data(port);
@@ -1463,7 +1463,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp )
int ret;
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
- struct termios not_termios;
+ struct ktermios not_termios;
unsigned long flags = 0;
@@ -1681,7 +1681,7 @@ dbg( "digi_startup: TOP" );
for( i=0; i<serial->type->num_ports+1; i++ ) {
/* allocate port private structure */
- priv = (struct digi_port *)kmalloc( sizeof(struct digi_port),
+ priv = kmalloc( sizeof(struct digi_port),
GFP_KERNEL );
if( priv == (struct digi_port *)0 ) {
while( --i >= 0 )
@@ -1714,7 +1714,7 @@ dbg( "digi_startup: TOP" );
}
/* allocate serial private structure */
- serial_priv = (struct digi_serial *)kmalloc( sizeof(struct digi_serial),
+ serial_priv = kmalloc( sizeof(struct digi_serial),
GFP_KERNEL );
if( serial_priv == (struct digi_serial *)0 ) {
for( i=0; i<serial->type->num_ports+1; i++ )
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 4ce10a83195..92beeb19795 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -92,7 +92,7 @@ static int empeg_ioctl (struct usb_serial_port *port,
struct file * file,
unsigned int cmd,
unsigned long arg);
-static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void empeg_write_bulk_callback (struct urb *urb);
static void empeg_read_bulk_callback (struct urb *urb);
@@ -442,7 +442,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
}
-static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s - port %d", __FUNCTION__, port->number);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 72e4d48f51e..6986e756f7c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -452,6 +452,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
@@ -595,7 +596,7 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port);
static void ftdi_write_bulk_callback (struct urb *urb);
static void ftdi_read_bulk_callback (struct urb *urb);
static void ftdi_process_read (struct work_struct *work);
-static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old);
+static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file);
static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
@@ -1880,7 +1881,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
* WARNING: set_termios calls this with old_termios in kernel space
*/
-static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{ /* ftdi_termios */
struct usb_device *dev = port->serial->dev;
unsigned int cflag = port->tty->termios->c_cflag;
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index bae117d359a..40dd394de58 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -312,8 +312,9 @@
/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
/* unit for PIC16's/PIC18's */
-#define FTDI_CCSICDU20_0_PID 0xF9D0
-#define FTDI_CCSICDU40_1_PID 0xF9D1
+#define FTDI_CCSICDU20_0_PID 0xF9D0
+#define FTDI_CCSICDU40_1_PID 0xF9D1
+#define FTDI_CCSMACHX_2_PID 0xF9D2
/* Inside Accesso contactless reader (http://www.insidefr.com) */
#define INSIDE_ACCESSO 0xFAD0
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 77b977206a8..2bebd63d5ed 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -14,6 +14,9 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+
+static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1404, 0xcddc) },
@@ -21,6 +24,26 @@ static struct usb_device_id id_table [] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
+static int funsoft_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ktermios t;
+
+ dbg("%s - port %d, cmd 0x%04x", __FUNCTION__, port->number, cmd);
+
+ if (cmd == TCSETSF) {
+ if (user_termios_to_kernel_termios(&t, (struct termios __user *)arg))
+ return -EFAULT;
+
+ dbg("%s - iflag:%x oflag:%x cflag:%x lflag:%x", __FUNCTION__,
+ t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag);
+
+ if (!(t.c_lflag & ICANON))
+ return -EINVAL;
+ }
+ return -ENOIOCTLCMD;
+}
+
static struct usb_driver funsoft_driver = {
.name = "funsoft",
.probe = usb_serial_probe,
@@ -39,6 +62,7 @@ static struct usb_serial_driver funsoft_device = {
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
+ .ioctl = funsoft_ioctl,
};
static int __init funsoft_init(void)
@@ -63,3 +87,6 @@ static void __exit funsoft_exit(void)
module_init(funsoft_init);
module_exit(funsoft_exit);
MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index d06547a13f2..f623d58370a 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -229,7 +229,7 @@ static int edge_write_room (struct usb_serial_port *port);
static int edge_chars_in_buffer (struct usb_serial_port *port);
static void edge_throttle (struct usb_serial_port *port);
static void edge_unthrottle (struct usb_serial_port *port);
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
static void edge_break (struct usb_serial_port *port, int break_state);
static int edge_tiocmget (struct usb_serial_port *port, struct file *file);
@@ -257,7 +257,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8
static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param);
static int calc_baud_rate_divisor (int baud_rate, int *divisor);
static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate);
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios);
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios);
static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
@@ -1431,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
* SerialSetTermios
* this function is called by the tty driver when it wants to change the termios structure
*****************************************************************************/
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -2412,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
#ifndef CMSPAR
#define CMSPAR 0
#endif
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
{
struct tty_struct *tty;
int baud;
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index ee0c921e152..980285c0233 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -238,7 +238,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
static void stop_read(struct edgeport_port *edge_port);
static int restart_read(struct edgeport_port *edge_port);
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void edge_send(struct usb_serial_port *port);
/* circular buffer */
@@ -2361,7 +2361,7 @@ static int restart_read(struct edgeport_port *edge_port)
return status;
}
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
{
struct ump_uart_config *config;
struct tty_struct *tty;
@@ -2512,7 +2512,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio
return;
}
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -2811,7 +2811,7 @@ static struct edge_buf *edge_buf_alloc(unsigned int size)
if (size == 0)
return NULL;
- eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
+ eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
if (eb == NULL)
return NULL;
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d72cf8bc7f7..42f757a5b87 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -595,7 +595,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
bytes_in = 0;
bytes_out = 0;
- priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
if (priv == NULL) {
err("%s - Out of memory", __FUNCTION__);
return -ENOMEM;
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 331bf81556f..8fdf486e346 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -107,7 +107,7 @@ static void ir_close (struct usb_serial_port *port, struct file *filep);
static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static void ir_write_bulk_callback (struct urb *urb);
static void ir_read_bulk_callback (struct urb *urb);
-static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static u8 ir_baud = 0;
static u8 ir_xbof = 0;
@@ -497,7 +497,7 @@ static void ir_read_bulk_callback (struct urb *urb)
return;
}
-static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned char *transfer_buffer;
unsigned int cflag;
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 7639652cec4..9d2fdfd6865 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -264,7 +264,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
static void keyspan_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int baud_rate, device_port;
struct keyspan_port_private *p_priv;
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 7472ed6bf62..6413d73c139 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -59,7 +59,7 @@ static int keyspan_ioctl (struct usb_serial_port *port,
unsigned int cmd,
unsigned long arg);
static void keyspan_set_termios (struct usb_serial_port *port,
- struct termios *old);
+ struct ktermios *old);
static void keyspan_break_ctl (struct usb_serial_port *port,
int break_state);
static int keyspan_tiocmget (struct usb_serial_port *port,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index e09a0bfe623..126b9703bba 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -365,7 +365,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
static void keyspan_pda_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
unsigned int cflag = port->tty->termios->c_cflag;
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 17e205699c2..5c4b06a99ac 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -86,11 +86,7 @@ static int klsi_105_write_room (struct usb_serial_port *port);
static void klsi_105_read_bulk_callback (struct urb *urb);
static void klsi_105_set_termios (struct usb_serial_port *port,
- struct termios * old);
-static int klsi_105_ioctl (struct usb_serial_port *port,
- struct file * file,
- unsigned int cmd,
- unsigned long arg);
+ struct ktermios *old);
static void klsi_105_throttle (struct usb_serial_port *port);
static void klsi_105_unthrottle (struct usb_serial_port *port);
/*
@@ -140,7 +136,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
.chars_in_buffer = klsi_105_chars_in_buffer,
.write_room = klsi_105_write_room,
.read_bulk_callback =klsi_105_read_bulk_callback,
- .ioctl = klsi_105_ioctl,
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
@@ -164,7 +159,7 @@ struct klsi_105_port_settings {
#define URB_TRANSFER_BUFFER_SIZE 64
struct klsi_105_private {
struct klsi_105_port_settings cfg;
- struct termios termios;
+ struct ktermios termios;
unsigned long line_state; /* modem line settings */
/* write pool */
struct urb * write_urb_pool[NUM_URBS];
@@ -688,7 +683,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
static void klsi_105_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag;
@@ -899,69 +894,6 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
*/
return retval;
}
-
-static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct klsi_105_private *priv = usb_get_serial_port_data(port);
- void __user *user_arg = (void __user *)arg;
-
- dbg("%scmd=0x%x", __FUNCTION__, cmd);
-
- /* Based on code from acm.c and others */
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* 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 */
- 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__);
-
- if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios)))
- return -EFAULT;
-
- if (user_termios_to_kernel_termios(&priv->termios,
- (struct termios __user *)arg))
- return -EFAULT;
- klsi_105_set_termios(port, &priv->termios);
- return 0;
- case TCSETSW: {
- /* set port termios and try to wait for completion of last
- * write operation */
- /* We guess here. If there are not too many write urbs
- * outstanding, we lie. */
- /* what is the right way to wait here? schedule() ? */
- /*
- while (klsi_105_chars_in_buffer(port) > (NUM_URBS / 4 ) * URB_TRANSFER_BUFFER_SIZE)
- schedule();
- */
- return -ENOIOCTLCMD;
- }
- default:
- dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
- return(-ENOIOCTLCMD);
- break;
- }
- return 0;
-} /* klsi_105_ioctl */
static void klsi_105_throttle (struct usb_serial_port *port)
{
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 237289920f0..62bea0c923b 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -136,7 +136,7 @@ struct kobil_private {
int cur_pos; // index of the next char to send in buf
__u16 device_type;
int line_state;
- struct termios internal_termios;
+ struct ktermios internal_termios;
};
@@ -269,7 +269,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
}
// allocate memory for write_urb transfer buffer
- port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+ port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
if (! port->write_urb->transfer_buffer) {
kfree(transfer_buffer);
usb_free_urb(port->write_urb);
@@ -624,11 +624,11 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
switch (cmd) {
case TCGETS: // 0x5401
- if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) {
+ if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) {
dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
return -EFAULT;
}
- if (kernel_termios_to_user_termios((struct termios __user *)arg,
+ if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
&priv->internal_termios))
return -EFAULT;
return 0;
@@ -638,12 +638,12 @@ 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;
}
- if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) {
+ if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) {
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))
+ (struct ktermios __user *)arg))
return -EFAULT;
settings = kzalloc(50, GFP_KERNEL);
@@ -696,7 +696,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
return 0;
case TCFLSH: // 0x540B
- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
+ transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
return -ENOBUFS;
}
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index a906e500a02..38b1d17e06e 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -98,7 +98,7 @@ static void mct_u232_close (struct usb_serial_port *port,
struct file *filp);
static void mct_u232_read_int_callback (struct urb *urb);
static void mct_u232_set_termios (struct usb_serial_port *port,
- struct termios * old);
+ struct ktermios * old);
static int mct_u232_ioctl (struct usb_serial_port *port,
struct file * file,
unsigned int cmd,
@@ -556,7 +556,7 @@ exit:
} /* mct_u232_read_int_callback */
static void mct_u232_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 70f93b18292..e55f4ed81d7 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1014,7 +1014,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
* the specified new settings.
*/
static void change_port_settings(struct moschip_port *mos7720_port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial_port *port;
struct usb_serial *serial;
@@ -1203,7 +1203,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
* termios structure.
*/
static void mos7720_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int status;
unsigned int cflag;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 5432c634008..83f661403ba 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1931,7 +1931,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
*****************************************************************************/
static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct tty_struct *tty;
int baud;
@@ -2118,7 +2118,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
*****************************************************************************/
static void mos7840_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int status;
unsigned int cflag;
@@ -2460,12 +2460,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
tty_ldisc_deref(ld);
return 0;
- case TCGETS:
- if (kernel_termios_to_user_termios
- ((struct termios __user *)argp, tty->termios))
- return -EFAULT;
- return 0;
-
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
return mos7840_get_lsr_info(mos7840_port, argp);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 130afbbd3fc..0fed43a9687 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -59,7 +59,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port);
static int option_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg);
static void option_set_termios(struct usb_serial_port *port,
- struct termios *old);
+ struct ktermios *old);
static void option_break_ctl(struct usb_serial_port *port, int break_state);
static int option_tiocmget(struct usb_serial_port *port, struct file *file);
static int option_tiocmset(struct usb_serial_port *port, struct file *file,
@@ -78,7 +78,9 @@ static int option_send_setup(struct usb_serial_port *port);
#define OPTION_PRODUCT_FUSION2 0x6300
#define OPTION_PRODUCT_COBRA 0x6500
#define OPTION_PRODUCT_COBRA2 0x6600
+#define OPTION_PRODUCT_GTMAX36 0x6701
#define HUAWEI_PRODUCT_E600 0x1001
+#define HUAWEI_PRODUCT_E220 0x1003
#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
#define NOVATELWIRELESS_PRODUCT_U740 0x1400
#define ANYDATA_PRODUCT_ID 0x6501
@@ -89,7 +91,9 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
@@ -102,7 +106,9 @@ static struct usb_device_id option_ids1[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
@@ -230,7 +236,7 @@ static void option_break_ctl(struct usb_serial_port *port, int break_state)
}
static void option_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
dbg("%s", __FUNCTION__);
@@ -622,6 +628,9 @@ static int option_send_setup(struct usb_serial_port *port)
dbg("%s", __FUNCTION__);
+ if (port->number != 0)
+ return 0;
+
portdata = usb_get_serial_port_data(port);
if (port->tty) {
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index bc800c8787a..5dc2ac9afa9 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -159,7 +159,7 @@ static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
if (size == 0)
return NULL;
- pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+ pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
if (pb == NULL)
return NULL;
@@ -455,7 +455,7 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
}
static void pl2303_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -687,7 +687,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
static int pl2303_open(struct usb_serial_port *port, struct file *filp)
{
- struct termios tmp_termios;
+ struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned char *buf;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 4b5097fa48d..6d8e91e00ec 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -145,7 +145,7 @@ static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
}
static void sierra_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
dbg("%s", __FUNCTION__);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index ae98d8cbdbb..83189005c6f 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -161,7 +161,7 @@ static void ti_throttle(struct usb_serial_port *port);
static void ti_unthrottle(struct usb_serial_port *port);
static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
static void ti_set_termios(struct usb_serial_port *port,
- struct termios *old_termios);
+ struct ktermios *old_termios);
static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear);
@@ -881,7 +881,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
static void ti_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct ti_port *tport = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -1710,7 +1710,7 @@ static struct circ_buf *ti_buf_alloc(void)
{
struct circ_buf *cb;
- cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+ cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 3d5072f14b8..716f6806cc8 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -397,7 +397,7 @@ exit:
return retval;
}
-static void serial_set_termios (struct tty_struct *tty, struct termios * old)
+static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
{
struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index eef5eaa5fa0..b09f0609605 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -46,7 +46,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id
static int visor_calc_num_ports(struct usb_serial *serial);
static void visor_shutdown (struct usb_serial *serial);
static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void visor_write_bulk_callback (struct urb *urb);
static void visor_read_bulk_callback (struct urb *urb);
static void visor_read_int_callback (struct urb *urb);
@@ -916,7 +916,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign
/* This function is all nice and good, but we don't change anything based on it :) */
-static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 154c7d29059..5483d8564c1 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -145,7 +145,7 @@ static void whiteheat_close (struct usb_serial_port *port, struct file *filp);
static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static int whiteheat_write_room (struct usb_serial_port *port);
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old);
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file);
static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
@@ -416,7 +416,7 @@ static int whiteheat_attach (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
+ info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
err("%s: Out of memory for port structures\n", serial->type->description);
goto no_private;
@@ -487,7 +487,7 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_set_serial_port_data(port, info);
}
- command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+ command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
if (command_info == NULL) {
err("%s: Out of memory for port structures\n", serial->type->description);
goto no_command_private;
@@ -597,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
- struct termios old_term;
+ struct ktermios old_term;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -870,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
}
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s -port %d", __FUNCTION__, port->number);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index fb8bacaae27..e3528eca29a 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -646,7 +646,7 @@ sddr09_read_sg_test_only(struct us_data *us) {
return result;
}
- buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
+ buf = kmalloc(bulklen, GFP_NOIO);
if (!buf)
return -ENOMEM;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index db8b26012c7..b49f2a78189 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -153,6 +153,13 @@ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+/* Reported by <honkkis@gmail.com> */
+UNUSUAL_DEV( 0x0421, 0x0433, 0x0100, 0x0100,
+ "Nokia",
+ "E70",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+
/* Reported by Jon Hart <Jon.Hart@web.de> */
UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100,
"Nokia",
@@ -190,6 +197,13 @@ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0370,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 ),
+/* Reported by Manuel Osdoba <manuel.osdoba@tu-ilmenau.de> */
+UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452,
+ "Nokia",
+ "Nokia 6233",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64 ),
+
/* Reported by Alex Corcoles <alex@corcoles.net> */
UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370,
"Nokia",
@@ -247,6 +261,18 @@ UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101,
US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
#endif
+/*
+ * This virtual floppy is found in Sun equipment (x4600, x4200m2, etc.)
+ * Reported by Pete Zaitcev <zaitcev@redhat.com>
+ * This device chokes on both version of MODE SENSE which we have, so
+ * use_10_for_ms is not effective, and we use US_FL_NO_WP_DETECT.
+ */
+UNUSUAL_DEV( 0x046b, 0xff40, 0x0100, 0x0100,
+ "AMI",
+ "Virtual Floppy",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NO_WP_DETECT),
+
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
"Kyocera",
@@ -721,7 +747,7 @@ UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
"Apple",
"iPod",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
"Apple",
@@ -1328,6 +1354,15 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* This prevents the kernel from detecting the virtual cd-drive with the
+ * Windows drivers. <johann.wilhelm@student.tugraz.at>
+*/
+UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0xffff,
+ "HUAWEI",
+ "E220 USB-UMTS Install",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_DEVICE),
+
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
"Minolta",
@@ -1342,6 +1377,21 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Francesco Foresti <frafore@tiscali.it> */
+UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
+ "Super Top",
+ "IDE DEVICE",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Robert Schedel <r.schedel@yahoo.de>
+ * Note: this is a 'super top' device like the above 14cd/6600 device */
+UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
+ "Teac",
+ "HD-35PUK-B",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
* and Renato Perini <rperini@email.it>
*/
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 7a43020fa58..4e83f01e894 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -541,6 +541,7 @@ config FB_TGA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select BITREVERSE
help
This is the frame buffer device driver for generic TGA graphic
cards. Say Y if you have one of those.
@@ -551,6 +552,7 @@ config FB_VESA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select VIDEO_SELECT
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.
@@ -705,6 +707,7 @@ config FB_NVIDIA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select BITREVERSE
help
This driver supports graphics boards with the nVidia chips, TNT
and newer. For very old chipsets, such as the RIVA128, then use
@@ -744,6 +747,7 @@ config FB_RIVA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select BITREVERSE
help
This driver supports graphics boards with the nVidia Riva/Geforce
chips.
@@ -1611,6 +1615,16 @@ config FB_PNX4008_DUM_RGB
---help---
Say Y here to enable support for PNX4008 RGB Framebuffer
+config FB_IBM_GXT4500
+ tristate "Framebuffer support for IBM GXT4500P adaptor"
+ depends on PPC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Say Y here to enable support for the IBM GXT4500P display
+ adaptor, found on some IBM System P (pSeries) machines.
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index a6980e9a248..309a26dd164 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_FB_IMX) += imxfb.o
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
+obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c
index 397005eb392..b3717c8f1bc 100644
--- a/drivers/video/S3triofb.c
+++ b/drivers/video/S3triofb.c
@@ -535,8 +535,11 @@ static void __init s3triofb_of_init(struct device_node *dp)
#endif
fb_info.flags = FBINFO_FLAG_DEFAULT;
- if (register_framebuffer(&fb_info) < 0)
- return;
+ if (register_framebuffer(&fb_info) < 0) {
+ iounmap(fb_info.screen_base);
+ fb_info.screen_base = NULL;
+ return;
+ }
printk("fb%d: S3 Trio frame buffer device on %s\n",
fb_info.node, dp->full_name);
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 6761b68c35e..6c9dc2e69c8 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -447,7 +447,7 @@ static int clcdfb_probe(struct amba_device *dev, void *id)
goto out;
}
- fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+ fb = kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
if (!fb) {
printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
ret = -ENOMEM;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index a4e3fca0589..1a849b870bc 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -2407,10 +2407,10 @@ default_chipset:
fb_info.fix.smem_len);
if (!videomemory) {
printk("amifb: WARNING! unable to map videomem cached writethrough\n");
- videomemory = ZTWO_VADDR(fb_info.fix.smem_start);
- }
+ fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start);
+ } else
+ fb_info.screen_base = (char *)videomemory;
- fb_info.screen_base = (char *)videomemory;
memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
/*
@@ -2453,6 +2453,8 @@ static void amifb_deinit(void)
{
fb_dealloc_cmap(&fb_info.cmap);
chipfree();
+ if (videomemory)
+ iounmap((void*)videomemory);
release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
custom.dmacon = DMAF_ALL | DMAF_MASTER;
}
@@ -2904,14 +2906,6 @@ static int ami_decode_var(struct fb_var_screeninfo *var,
par->crsr.spot_x = par->crsr.spot_y = 0;
par->crsr.height = par->crsr.width = 0;
-#if 0 /* fbmon not done. uncomment for 2.5.x -brad */
- if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal,
- &fb_info)) {
- DPRINTK("mode doesn't fit for monitor\n");
- return -EINVAL;
- }
-#endif
-
return 0;
}
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index ab34b96acc3..30a8369757e 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -454,7 +454,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou
unsigned int xres;
p = *ppos;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
fbidx = iminor(inode);
info = registered_fb[fbidx];
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 02c41a626fa..602db660bc7 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2804,8 +2804,19 @@ int __init atafb_init(void)
atafb_set_disp(-1, &fb_info);
do_install_cmap(0, &fb_info);
- if (register_framebuffer(&fb_info) < 0)
+ if (register_framebuffer(&fb_info) < 0) {
+#ifdef ATAFB_EXT
+ if (external_addr) {
+ iounmap(external_addr);
+ external_addr = NULL;
+ }
+ if (external_vgaiobase) {
+ iounmap((void*)external_vgaiobase);
+ external_vgaiobase = 0;
+ }
+#endif
return -EINVAL;
+ }
printk("Determined %dx%d, depth %d\n",
disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 276a21530b9..2e976ffcde0 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1333,6 +1333,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
if (vclk * 12 < c.ppll_min)
vclk = c.ppll_min/12;
+ pll->post_divider = -1;
+
/* now, find an acceptable divider */
for (i = 0; i < sizeof(post_dividers); i++) {
output_freq = post_dividers[i] * vclk;
@@ -1342,6 +1344,9 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
}
}
+ if (pll->post_divider < 0)
+ return -EINVAL;
+
/* calculate feedback divider */
n = c.ref_divider * output_freq;
d = c.ref_clk;
@@ -1829,7 +1834,7 @@ static void aty128_bl_init(struct aty128fb_par *par)
snprintf(name, sizeof(name), "aty128bl%d", info->node);
- bd = backlight_device_register(name, par, &aty128_bl_data);
+ bd = backlight_device_register(name, info->dev, par, &aty128_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
printk(KERN_WARNING "aty128: Backlight registration failed\n");
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index b04f49fb976..f72faff33c0 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -126,7 +126,6 @@ union aty_pll {
*/
struct atyfb_par {
- struct aty_cmap_regs __iomem *aty_cmap_regs;
struct { u8 red, green, blue; } palette[256];
const struct aty_dac_ops *dac_ops;
const struct aty_pll_ops *pll_ops;
@@ -186,6 +185,7 @@ struct atyfb_par {
int mtrr_aper;
int mtrr_reg;
#endif
+ u32 mem_cntl;
};
/*
@@ -227,7 +227,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par)
regindex -= 0x800;
#ifdef CONFIG_ATARI
- return in_le32((volatile u32 *)(par->ati_regbase + regindex));
+ return in_le32(par->ati_regbase + regindex);
#else
return readl(par->ati_regbase + regindex);
#endif
@@ -240,7 +240,7 @@ static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *pa
regindex -= 0x800;
#ifdef CONFIG_ATARI
- out_le32((volatile u32 *)(par->ati_regbase + regindex), val);
+ out_le32(par->ati_regbase + regindex, val);
#else
writel(val, par->ati_regbase + regindex);
#endif
@@ -253,7 +253,7 @@ static inline void aty_st_le16(int regindex, u16 val,
if (regindex >= 0x400)
regindex -= 0x800;
#ifdef CONFIG_ATARI
- out_le16((volatile u16 *)(par->ati_regbase + regindex), val);
+ out_le16(par->ati_regbase + regindex, val);
#else
writel(val, par->ati_regbase + regindex);
#endif
@@ -315,6 +315,7 @@ struct aty_pll_ops {
void (*set_pll) (const struct fb_info * info, const union aty_pll * pll);
void (*get_pll) (const struct fb_info *info, union aty_pll * pll);
int (*init_pll) (const struct fb_info * info, union aty_pll * pll);
+ void (*resume_pll)(const struct fb_info *info, union aty_pll *pll);
};
extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index e815b354c09..f2ebdd88008 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -203,14 +203,6 @@ static void ATIReduceRatio(int *Numerator, int *Denominator)
* The Hardware parameters for each card
*/
-struct aty_cmap_regs {
- u8 windex;
- u8 lut;
- u8 mask;
- u8 rindex;
- u8 cntl;
-};
-
struct pci_mmap_map {
unsigned long voff;
unsigned long poff;
@@ -249,7 +241,8 @@ static int atyfb_sync(struct fb_info *info);
* Internal routines
*/
-static int aty_init(struct fb_info *info, const char *name);
+static int aty_init(struct fb_info *info);
+static void aty_resume_chip(struct fb_info *info);
#ifdef CONFIG_ATARI
static int store_video_par(char *videopar, unsigned char m64_num);
#endif
@@ -1495,10 +1488,6 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
else
info->var.accel_flags = 0;
-#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
- if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
- return -EINVAL;
-#endif
aty_crtc_to_var(&crtc, var);
var->pixclock = par->pll_ops->pll_to_var(info, &pll);
return 0;
@@ -1937,17 +1926,14 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter)
aty_st_8(DAC_CNTL, tmp, par);
aty_st_8(DAC_MASK, 0xff, par);
- writeb(i, &par->aty_cmap_regs->rindex);
- atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut);
- atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut);
- atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut);
- writeb(i, &par->aty_cmap_regs->windex);
- writeb(atyfb_save.r[1 - enter][i],
- &par->aty_cmap_regs->lut);
- writeb(atyfb_save.g[1 - enter][i],
- &par->aty_cmap_regs->lut);
- writeb(atyfb_save.b[1 - enter][i],
- &par->aty_cmap_regs->lut);
+ aty_st_8(DAC_R_INDEX, i, par);
+ atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par);
+ atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par);
+ atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par);
+ aty_st_8(DAC_W_INDEX, i, par);
+ aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par);
+ aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par);
+ aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par);
}
}
@@ -1982,6 +1968,7 @@ static void atyfb_palette(int enter)
#if defined(CONFIG_PM) && defined(CONFIG_PCI)
+#ifdef CONFIG_PPC_PMAC
/* Power management routines. Those are used for PowerBook sleep.
*/
static int aty_power_mgmt(int sleep, struct atyfb_par *par)
@@ -2038,21 +2025,13 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
return timeout ? 0 : -EIO;
}
+#endif
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;
-#ifndef CONFIG_PPC_PMAC
- /* HACK ALERT ! Once I find a proper way to say to each driver
- * individually what will happen with it's PCI slot, I'll change
- * that. On laptops, the AGP slot is just unclocked, so D2 is
- * expected, while on desktops, the card is powered off
- */
- return 0;
-#endif /* CONFIG_PPC_PMAC */
-
if (state.event == pdev->dev.power.power_state.event)
return 0;
@@ -2070,6 +2049,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
par->asleep = 1;
par->lock_blank = 1;
+#ifdef CONFIG_PPC_PMAC
/* Set chip to "suspend" mode */
if (aty_power_mgmt(1, par)) {
par->asleep = 0;
@@ -2079,6 +2059,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
release_console_sem();
return -EIO;
}
+#else
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+#endif
release_console_sem();
@@ -2097,8 +2080,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
acquire_console_sem();
+#ifdef CONFIG_PPC_PMAC
if (pdev->dev.power.power_state.event == 2)
aty_power_mgmt(0, par);
+#else
+ pci_set_power_state(pdev, PCI_D0);
+#endif
+
+ aty_resume_chip(info);
+
par->asleep = 0;
/* Restore display */
@@ -2221,7 +2211,7 @@ static void aty_bl_init(struct atyfb_par *par)
snprintf(name, sizeof(name), "atybl%d", info->node);
- bd = backlight_device_register(name, par, &aty_bl_data);
+ bd = backlight_device_register(name, info->dev, par, &aty_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
printk(KERN_WARNING "aty: Backlight registration failed\n");
@@ -2344,24 +2334,16 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
}
#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
-static int __devinit aty_init(struct fb_info *info, const char *name)
+static int __devinit aty_init(struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
const char *ramname = NULL, *xtal;
int gtb_memsize, has_var = 0;
struct fb_var_screeninfo var;
- u8 pll_ref_div;
- u32 i;
-#if defined(CONFIG_PPC)
- int sense;
-#endif
init_waitqueue_head(&par->vblank.wait);
spin_lock_init(&par->int_lock);
- par->aty_cmap_regs =
- (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0);
-
#ifdef CONFIG_PPC_PMAC
/* The Apple iBook1 uses non-standard memory frequencies. We detect it
* and set the frequency manually. */
@@ -2464,18 +2446,21 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
par->pll_limits.mclk = 63;
}
- if (M64_HAS(GTB_DSP)
- && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) {
- int diff1, diff2;
- diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
- diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
- if (diff1 < 0)
- diff1 = -diff1;
- if (diff2 < 0)
- diff2 = -diff2;
- if (diff2 < diff1) {
- par->ref_clk_per = 1000000000000ULL / 29498928;
- xtal = "29.498928";
+ if (M64_HAS(GTB_DSP)) {
+ u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+
+ if (pll_ref_div) {
+ int diff1, diff2;
+ diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
+ diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
+ if (diff1 < 0)
+ diff1 = -diff1;
+ if (diff2 < 0)
+ diff2 = -diff2;
+ if (diff2 < diff1) {
+ par->ref_clk_per = 1000000000000ULL / 29498928;
+ xtal = "29.498928";
+ }
}
}
#endif /* CONFIG_FB_ATY_CT */
@@ -2485,10 +2470,10 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
if(par->pll_ops->get_pll)
par->pll_ops->get_pll(info, &saved_pll);
- i = aty_ld_le32(MEM_CNTL, par);
+ par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
gtb_memsize = M64_HAS(GTB_DSP);
if (gtb_memsize)
- switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
+ switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
case MEM_SIZE_512K:
info->fix.smem_len = 0x80000;
break;
@@ -2510,7 +2495,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
default:
info->fix.smem_len = 0x80000;
} else
- switch (i & MEM_SIZE_ALIAS) {
+ switch (par->mem_cntl & MEM_SIZE_ALIAS) {
case MEM_SIZE_512K:
info->fix.smem_len = 0x80000;
break;
@@ -2540,20 +2525,20 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
if (vram) {
info->fix.smem_len = vram * 1024;
- i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
+ par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
if (info->fix.smem_len <= 0x80000)
- i |= MEM_SIZE_512K;
+ par->mem_cntl |= MEM_SIZE_512K;
else if (info->fix.smem_len <= 0x100000)
- i |= MEM_SIZE_1M;
+ par->mem_cntl |= MEM_SIZE_1M;
else if (info->fix.smem_len <= 0x200000)
- i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
+ par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
else if (info->fix.smem_len <= 0x400000)
- i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
+ par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
else if (info->fix.smem_len <= 0x600000)
- i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
+ par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
else
- i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
- aty_st_le32(MEM_CNTL, i, par);
+ par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
+ aty_st_le32(MEM_CNTL, par->mem_cntl, par);
}
/*
@@ -2599,11 +2584,12 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
#endif
if(par->pll_ops->init_pll)
par->pll_ops->init_pll(info, &par->pll);
+ if (par->pll_ops->resume_pll)
+ par->pll_ops->resume_pll(info, &par->pll);
/*
- * Last page of 8 MB (4 MB on ISA) aperture is MMIO
- * FIXME: we should use the auxiliary aperture instead so we can access
- * the full 8 MB of video RAM on 8 MB boards
+ * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
+ * unless the auxiliary register aperture is used.
*/
if (!par->aux_start &&
@@ -2669,6 +2655,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
has_var = 1;
} else {
if (default_vmode == VMODE_CHOOSE) {
+ int sense;
if (M64_HAS(G3_PB_1024x768))
/* G3 PowerBook with 1024x768 LCD */
default_vmode = VMODE_1024_768_60;
@@ -2749,7 +2736,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name)
fb_list = info;
PRINTKI("fb%d: %s frame buffer device on %s\n",
- info->node, info->fix.id, name);
+ info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
return 0;
aty_init_exit:
@@ -2770,6 +2757,19 @@ aty_init_exit:
return -1;
}
+static void aty_resume_chip(struct fb_info *info)
+{
+ struct atyfb_par *par = info->par;
+
+ aty_st_le32(MEM_CNTL, par->mem_cntl, par);
+
+ if (par->pll_ops->resume_pll)
+ par->pll_ops->resume_pll(info, &par->pll);
+
+ if (par->aux_start)
+ aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
+}
+
#ifdef CONFIG_ATARI
static int __devinit store_video_par(char *video_str, unsigned char m64_num)
{
@@ -2826,9 +2826,9 @@ static int atyfb_blank(int blank, struct fb_info *info)
#endif
gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+ gen_cntl &= ~0x400004c;
switch (blank) {
- case FB_BLANK_UNBLANK:
- gen_cntl &= ~0x400004c;
+ case FB_BLANK_UNBLANK:
break;
case FB_BLANK_NORMAL:
gen_cntl |= 0x4000040;
@@ -2863,17 +2863,10 @@ static int atyfb_blank(int blank, struct fb_info *info)
static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
const struct atyfb_par *par)
{
-#ifdef CONFIG_ATARI
- out_8(&par->aty_cmap_regs->windex, regno);
- out_8(&par->aty_cmap_regs->lut, red);
- out_8(&par->aty_cmap_regs->lut, green);
- out_8(&par->aty_cmap_regs->lut, blue);
-#else
- writeb(regno, &par->aty_cmap_regs->windex);
- writeb(red, &par->aty_cmap_regs->lut);
- writeb(green, &par->aty_cmap_regs->lut);
- writeb(blue, &par->aty_cmap_regs->lut);
-#endif
+ aty_st_8(DAC_W_INDEX, regno, par);
+ aty_st_8(DAC_DATA, red, par);
+ aty_st_8(DAC_DATA, green, par);
+ aty_st_8(DAC_DATA, blue, par);
}
/*
@@ -3182,7 +3175,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
#ifdef __i386__
#ifdef CONFIG_FB_ATY_GENERIC_LCD
-static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
{
u32 driv_inf_tab, sig;
u16 lcd_ofs;
@@ -3527,6 +3520,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i
atyfb_setup_generic_fail:
iounmap(par->ati_regbase);
par->ati_regbase = NULL;
+ if (info->screen_base) {
+ iounmap(info->screen_base);
+ info->screen_base = NULL;
+ }
return ret;
}
@@ -3594,7 +3591,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
pci_set_drvdata(pdev, info);
/* Init chip & register framebuffer */
- if (aty_init(info, "PCI"))
+ if (aty_init(info))
goto err_release_io;
#ifdef __sparc__
@@ -3641,12 +3638,13 @@ err_release_mem:
#ifdef CONFIG_ATARI
-static int __devinit atyfb_atari_probe(void)
+static int __init atyfb_atari_probe(void)
{
struct atyfb_par *par;
struct fb_info *info;
int m64_num;
u32 clock_r;
+ int num_found = 0;
for (m64_num = 0; m64_num < mach64_count; m64_num++) {
if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
@@ -3694,16 +3692,34 @@ static int __devinit atyfb_atari_probe(void)
break;
}
- if (aty_init(info, "ISA bus")) {
+ /* Fake pci_id for correct_chipset() */
+ switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
+ case 0x00d7:
+ par->pci_id = PCI_CHIP_MACH64GX;
+ break;
+ case 0x0057:
+ par->pci_id = PCI_CHIP_MACH64CX;
+ break;
+ default:
+ break;
+ }
+
+ if (correct_chipset(par) || aty_init(info)) {
+ iounmap(info->screen_base);
+ iounmap(par->ati_regbase);
framebuffer_release(info);
- /* This is insufficient! kernel_map has added two large chunks!! */
- return -ENXIO;
+ } else {
+ num_found++;
}
}
+
+ return num_found ? 0 : -ENXIO;
}
#endif /* CONFIG_ATARI */
+#ifdef CONFIG_PCI
+
static void __devexit atyfb_remove(struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -3751,7 +3767,6 @@ static void __devexit atyfb_remove(struct fb_info *info)
framebuffer_release(info);
}
-#ifdef CONFIG_PCI
static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
{
@@ -3786,7 +3801,7 @@ static struct pci_driver atyfb_driver = {
#endif /* CONFIG_PCI */
#ifndef MODULE
-static int __devinit atyfb_setup(char *options)
+static int __init atyfb_setup(char *options)
{
char *this_opt;
@@ -3858,7 +3873,7 @@ static int __devinit atyfb_setup(char *options)
}
#endif /* MODULE */
-static int __devinit atyfb_init(void)
+static int __init atyfb_init(void)
{
int err1 = 1, err2 = 1;
#ifndef MODULE
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
index 5080816be65..f3b487b8710 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/aty/mach64_ct.c
@@ -370,8 +370,8 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
#endif
}
-static void __init aty_get_pll_ct(const struct fb_info *info,
- union aty_pll *pll)
+static void __devinit 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;
@@ -394,12 +394,12 @@ static void __init aty_get_pll_ct(const struct fb_info *info,
}
}
-static int __init aty_init_pll_ct(const struct fb_info *info,
- union aty_pll *pll)
+static int __devinit 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;
+ u8 mpost_div, xpost_div, sclk_post_div_real;
+ u32 q, memcntl, trp;
u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
#ifdef DEBUG
int pllmclk, pllsclk;
@@ -575,14 +575,30 @@ static int __init aty_init_pll_ct(const struct fb_info *info,
mpost_div += (q < 32*8);
}
sclk_post_div_real = postdividers[mpost_div];
- sclk_fb_div = q * sclk_post_div_real / 8;
- spll_cntl2 = mpost_div << 4;
+ pll->ct.sclk_fb_div = q * sclk_post_div_real / 8;
+ pll->ct.spll_cntl2 = mpost_div << 4;
#ifdef DEBUG
- pllsclk = (1000000 * 2 * sclk_fb_div) /
+ pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) /
(par->ref_clk_per * pll->ct.pll_ref_div);
printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
__FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);
#endif
+ }
+
+ /* Disable the extra precision pixel clock controls since we do not use them. */
+ pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par);
+ pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC);
+
+ return 0;
+}
+
+static void aty_resume_pll_ct(const struct fb_info *info,
+ union aty_pll *pll)
+{
+ struct atyfb_par *par = info->par;
+
+ if (par->mclk_per != par->xclk_per) {
+ int i;
/*
* This disables the sclk, crashes the computer as reported:
* aty_st_pll_ct(SPLL_CNTL2, 3, info);
@@ -590,8 +606,8 @@ static int __init aty_init_pll_ct(const struct fb_info *info,
* So it seems the sclk must be enabled before it is used;
* so PLL_GEN_CNTL must be programmed *after* the sclk.
*/
- aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par);
- aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par);
+ aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par);
+ aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par);
/*
* The sclk has been started. However, I believe the first clock
* ticks it generates are not very stable. Hope this primitive loop
@@ -605,11 +621,7 @@ static int __init aty_init_pll_ct(const struct fb_info *info,
aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
- /* Disable the extra precision pixel clock controls since we do not use them. */
- aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) &
- ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par);
-
- return 0;
+ aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par);
}
static int dummy(void)
@@ -626,5 +638,6 @@ const struct aty_pll_ops aty_pll_ct = {
.pll_to_var = aty_pll_to_var_ct,
.set_pll = aty_set_pll_ct,
.get_pll = aty_get_pll_ct,
- .init_pll = aty_init_pll_ct
+ .init_pll = aty_init_pll_ct,
+ .resume_pll = aty_resume_pll_ct,
};
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 585eb7b9e63..3abfd4a380c 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -163,7 +163,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
- bd = backlight_device_register(name, pdata, &radeon_bl_data);
+ bd = backlight_device_register(name, rinfo->info->dev, pdata, &radeon_bl_data);
if (IS_ERR(bd)) {
rinfo->info->bl_dev = NULL;
printk("radeonfb: Backlight registration failed\n");
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 869725a13c2..e7c5b219ad1 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -120,19 +120,19 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
{
if (rinfo->i2c[0].rinfo)
- i2c_bit_del_bus(&rinfo->i2c[0].adapter);
+ i2c_del_adapter(&rinfo->i2c[0].adapter);
rinfo->i2c[0].rinfo = NULL;
if (rinfo->i2c[1].rinfo)
- i2c_bit_del_bus(&rinfo->i2c[1].adapter);
+ i2c_del_adapter(&rinfo->i2c[1].adapter);
rinfo->i2c[1].rinfo = NULL;
if (rinfo->i2c[2].rinfo)
- i2c_bit_del_bus(&rinfo->i2c[2].adapter);
+ i2c_del_adapter(&rinfo->i2c[2].adapter);
rinfo->i2c[2].rinfo = NULL;
if (rinfo->i2c[3].rinfo)
- i2c_bit_del_bus(&rinfo->i2c[3].adapter);
+ i2c_del_adapter(&rinfo->i2c[3].adapter);
rinfo->i2c[3].rinfo = NULL;
}
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index ea531a6f45d..38c7dbf8c15 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -104,10 +104,9 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
if (pedid == NULL)
return mt;
- tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL);
+ tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
if (!tmp)
return mt;
- memcpy(tmp, pedid, EDID_LENGTH);
*out_EDID = tmp;
return mt;
}
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h
index 2855534dc23..164fe2f231e 100644
--- a/drivers/video/au1100fb.h
+++ b/drivers/video/au1100fb.h
@@ -274,7 +274,7 @@ static struct au1100fb_panel known_lcd_panels[] =
.bpp = 16,
.control_base = 0x0004886A |
LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF |
- LCD_CONTROL_BPP_16,
+ LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4,
.clkcontrol_base = 0x00020000,
.horztiming = 0x005aff1f,
.verttiming = 0x16000e57,
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 27597c576ef..9601bfe309a 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -14,6 +14,59 @@
#include <linux/err.h>
#include <linux/fb.h>
+
+#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
+ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
+/* This callback gets called when something important happens inside a
+ * framebuffer driver. We're looking if that important event is blanking,
+ * and if it is, we're switching backlight power as well ...
+ */
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct backlight_device *bd;
+ struct fb_event *evdata = data;
+
+ /* If we aren't interested in this event, skip it immediately ... */
+ if (event != FB_EVENT_BLANK)
+ return 0;
+
+ bd = container_of(self, struct backlight_device, fb_notif);
+ down(&bd->sem);
+ if (bd->props)
+ if (!bd->props->check_fb ||
+ bd->props->check_fb(evdata->info)) {
+ bd->props->fb_blank = *(int *)evdata->data;
+ if (likely(bd->props && bd->props->update_status))
+ bd->props->update_status(bd);
+ }
+ up(&bd->sem);
+ return 0;
+}
+
+static int backlight_register_fb(struct backlight_device *bd)
+{
+ memset(&bd->fb_notif, 0, sizeof(bd->fb_notif));
+ bd->fb_notif.notifier_call = fb_notifier_callback;
+
+ return fb_register_client(&bd->fb_notif);
+}
+
+static void backlight_unregister_fb(struct backlight_device *bd)
+{
+ fb_unregister_client(&bd->fb_notif);
+}
+#else
+static inline int backlight_register_fb(struct backlight_device *bd)
+{
+ return 0;
+}
+
+static inline void backlight_unregister_fb(struct backlight_device *bd)
+{
+}
+#endif /* CONFIG_FB */
+
static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
{
int rc = -ENXIO;
@@ -142,7 +195,7 @@ static struct class backlight_class = {
.store = _store, \
}
-static struct class_device_attribute bl_class_device_attributes[] = {
+static const struct class_device_attribute bl_class_device_attributes[] = {
DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power),
DECLARE_ATTR(brightness, 0644, backlight_show_brightness,
backlight_store_brightness),
@@ -151,33 +204,6 @@ static struct class_device_attribute bl_class_device_attributes[] = {
DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
};
-/* This callback gets called when something important happens inside a
- * framebuffer driver. We're looking if that important event is blanking,
- * and if it is, we're switching backlight power as well ...
- */
-static int fb_notifier_callback(struct notifier_block *self,
- unsigned long event, void *data)
-{
- struct backlight_device *bd;
- struct fb_event *evdata =(struct fb_event *)data;
-
- /* If we aren't interested in this event, skip it immediately ... */
- if (event != FB_EVENT_BLANK)
- return 0;
-
- bd = container_of(self, struct backlight_device, fb_notif);
- down(&bd->sem);
- if (bd->props)
- if (!bd->props->check_fb ||
- bd->props->check_fb(evdata->info)) {
- bd->props->fb_blank = *(int *)evdata->data;
- if (likely(bd->props && bd->props->update_status))
- bd->props->update_status(bd);
- }
- up(&bd->sem);
- return 0;
-}
-
/**
* backlight_device_register - create and register a new object of
* backlight_device class.
@@ -190,8 +216,10 @@ static int fb_notifier_callback(struct notifier_block *self,
* Creates and registers new backlight class_device. Returns either an
* ERR_PTR() or a pointer to the newly allocated device.
*/
-struct backlight_device *backlight_device_register(const char *name, void *devdata,
- struct backlight_properties *bp)
+struct backlight_device *backlight_device_register(const char *name,
+ struct device *dev,
+ void *devdata,
+ struct backlight_properties *bp)
{
int i, rc;
struct backlight_device *new_bd;
@@ -206,6 +234,7 @@ struct backlight_device *backlight_device_register(const char *name, void *devda
new_bd->props = bp;
memset(&new_bd->class_dev, 0, sizeof(new_bd->class_dev));
new_bd->class_dev.class = &backlight_class;
+ new_bd->class_dev.dev = dev;
strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
class_set_devdata(&new_bd->class_dev, devdata);
@@ -215,10 +244,7 @@ error: kfree(new_bd);
return ERR_PTR(rc);
}
- memset(&new_bd->fb_notif, 0, sizeof(new_bd->fb_notif));
- new_bd->fb_notif.notifier_call = fb_notifier_callback;
-
- rc = fb_register_client(&new_bd->fb_notif);
+ rc = backlight_register_fb(new_bd);
if (unlikely(rc))
goto error;
@@ -259,16 +285,10 @@ void backlight_device_unregister(struct backlight_device *bd)
&bl_class_device_attributes[i]);
down(&bd->sem);
- if (likely(bd->props && bd->props->update_status)) {
- bd->props->brightness = 0;
- bd->props->power = 0;
- bd->props->update_status(bd);
- }
-
bd->props = NULL;
up(&bd->sem);
- fb_unregister_client(&bd->fb_notif);
+ backlight_unregister_fb(bd);
class_device_unregister(&bd->class_dev);
}
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index d07ecb53c68..fde1d951812 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -121,7 +121,7 @@ static int corgibl_probe(struct platform_device *pdev)
machinfo->limit_mask = -1;
corgi_backlight_device = backlight_device_register ("corgi-bl",
- NULL, &corgibl_data);
+ &pdev->dev, NULL, &corgibl_data);
if (IS_ERR (corgi_backlight_device))
return PTR_ERR (corgi_backlight_device);
@@ -135,6 +135,10 @@ static int corgibl_probe(struct platform_device *pdev)
static int corgibl_remove(struct platform_device *dev)
{
+ corgibl_data.power = 0;
+ corgibl_data.brightness = 0;
+ corgibl_send_intensity(corgi_backlight_device);
+
backlight_device_unregister(corgi_backlight_device);
printk("Corgi Backlight Driver Unloaded\n");
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index e3993213d10..c07d8207fb5 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -105,7 +105,7 @@ static struct backlight_properties hp680bl_data = {
static int __init hp680bl_probe(struct platform_device *dev)
{
hp680_backlight_device = backlight_device_register ("hp680-bl",
- NULL, &hp680bl_data);
+ &dev->dev, NULL, &hp680bl_data);
if (IS_ERR (hp680_backlight_device))
return PTR_ERR (hp680_backlight_device);
@@ -117,6 +117,10 @@ static int __init hp680bl_probe(struct platform_device *dev)
static int hp680bl_remove(struct platform_device *dev)
{
+ hp680bl_data.brightness = 0;
+ hp680bl_data.power = 0;
+ hp680bl_send_intensity(hp680_backlight_device);
+
backlight_device_unregister(hp680_backlight_device);
return 0;
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index bc8ab005a3f..f6e041627ed 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -14,6 +14,53 @@
#include <linux/err.h>
#include <linux/fb.h>
+#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
+ defined(CONFIG_LCD_CLASS_DEVICE_MODULE))
+/* This callback gets called when something important happens inside a
+ * framebuffer driver. We're looking if that important event is blanking,
+ * and if it is, we're switching lcd power as well ...
+ */
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct lcd_device *ld;
+ struct fb_event *evdata = data;
+
+ /* If we aren't interested in this event, skip it immediately ... */
+ if (event != FB_EVENT_BLANK)
+ return 0;
+
+ ld = container_of(self, struct lcd_device, fb_notif);
+ down(&ld->sem);
+ if (ld->props)
+ if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
+ ld->props->set_power(ld, *(int *)evdata->data);
+ up(&ld->sem);
+ return 0;
+}
+
+static int lcd_register_fb(struct lcd_device *ld)
+{
+ memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif));
+ ld->fb_notif.notifier_call = fb_notifier_callback;
+ return fb_register_client(&ld->fb_notif);
+}
+
+static void lcd_unregister_fb(struct lcd_device *ld)
+{
+ fb_unregister_client(&ld->fb_notif);
+}
+#else
+static int lcd_register_fb(struct lcd_device *ld)
+{
+ return 0;
+}
+
+static inline void lcd_unregister_fb(struct lcd_device *ld)
+{
+}
+#endif /* CONFIG_FB */
+
static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
{
int rc;
@@ -121,35 +168,12 @@ static struct class lcd_class = {
.store = _store, \
}
-static struct class_device_attribute lcd_class_device_attributes[] = {
+static const struct class_device_attribute lcd_class_device_attributes[] = {
DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power),
DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast),
DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL),
};
-/* This callback gets called when something important happens inside a
- * framebuffer driver. We're looking if that important event is blanking,
- * and if it is, we're switching lcd power as well ...
- */
-static int fb_notifier_callback(struct notifier_block *self,
- unsigned long event, void *data)
-{
- struct lcd_device *ld;
- struct fb_event *evdata =(struct fb_event *)data;
-
- /* If we aren't interested in this event, skip it immediately ... */
- if (event != FB_EVENT_BLANK)
- return 0;
-
- ld = container_of(self, struct lcd_device, fb_notif);
- down(&ld->sem);
- if (ld->props)
- if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
- ld->props->set_power(ld, *(int *)evdata->data);
- up(&ld->sem);
- return 0;
-}
-
/**
* lcd_device_register - register a new object of lcd_device class.
* @name: the name of the new object(must be the same as the name of the
@@ -186,10 +210,8 @@ error: kfree(new_ld);
return ERR_PTR(rc);
}
- memset(&new_ld->fb_notif, 0, sizeof(new_ld->fb_notif));
- new_ld->fb_notif.notifier_call = fb_notifier_callback;
+ rc = lcd_register_fb(new_ld);
- rc = fb_register_client(&new_ld->fb_notif);
if (unlikely(rc))
goto error;
@@ -232,9 +254,7 @@ void lcd_device_unregister(struct lcd_device *ld)
down(&ld->sem);
ld->props = NULL;
up(&ld->sem);
-
- fb_unregister_client(&ld->fb_notif);
-
+ lcd_unregister_fb(ld);
class_device_unregister(&ld->class_dev);
}
EXPORT_SYMBOL(lcd_device_unregister);
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 628571c63ba..fc812d96c31 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -184,7 +184,7 @@ static int locomolcd_probe(struct locomo_dev *ldev)
local_irq_restore(flags);
- locomolcd_bl_device = backlight_device_register("locomo-bl", NULL, &locomobl_data);
+ locomolcd_bl_device = backlight_device_register("locomo-bl", &ldev->dev, NULL, &locomobl_data);
if (IS_ERR (locomolcd_bl_device))
return PTR_ERR (locomolcd_bl_device);
@@ -200,6 +200,10 @@ static int locomolcd_remove(struct locomo_dev *dev)
{
unsigned long flags;
+ locomobl_data.brightness = 0;
+ locomobl_data.power = 0;
+ locomolcd_set_intensity(locomolcd_bl_device);
+
backlight_device_unregister(locomolcd_bl_device);
local_irq_save(flags);
locomolcd_dev = NULL;
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index c66e3d52cbf..9bb6257d691 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -320,7 +320,7 @@ static int __devinit bw2_init_one(struct of_device *op)
all->info.fbops = &bw2_ops;
all->info.screen_base =
- sbus_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram");
+ of_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram");
all->info.par = &all->par;
bw2_blank(0, &all->info);
@@ -329,8 +329,10 @@ static int __devinit bw2_init_one(struct of_device *op)
err= register_framebuffer(&all->info);
if (err < 0) {
- of_iounmap(all->par.regs, sizeof(struct bw2_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct bw2_regs));
+ of_iounmap(&op->resource[0],
+ all->info.screen_base, all->par.fbsize);
kfree(all);
return err;
}
@@ -351,18 +353,18 @@ static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id
return bw2_init_one(op);
}
-static int __devexit bw2_remove(struct of_device *dev)
+static int __devexit bw2_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
- of_iounmap(all->par.regs, sizeof(struct bw2_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0], all->par.regs, sizeof(struct bw2_regs));
+ of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 51d35386a94..261004473c8 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -42,7 +42,7 @@
#define DPRINTK(fmt, args...)
#endif
-static u32 cfb_tab8[] = {
+static const u32 cfb_tab8[] = {
#if defined(__BIG_ENDIAN)
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
@@ -58,7 +58,7 @@ static u32 cfb_tab8[] = {
#endif
};
-static u32 cfb_tab16[] = {
+static const u32 cfb_tab16[] = {
#if defined(__BIG_ENDIAN)
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
#elif defined(__LITTLE_ENDIAN)
@@ -68,7 +68,7 @@ static u32 cfb_tab16[] = {
#endif
};
-static u32 cfb_tab32[] = {
+static const u32 cfb_tab32[] = {
0x00000000, 0xffffffff
};
@@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
u32 bit_mask, end_mask, eorx, shift;
const char *s = image->data, *src;
u32 __iomem *dst;
- u32 *tab = NULL;
+ const u32 *tab = NULL;
int i, j, k;
switch (bpp) {
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 7f926c619b6..ec6a51a5822 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -452,16 +452,20 @@ struct all_info {
struct cg14_par par;
};
-static void cg14_unmap_regs(struct all_info *all)
+static void cg14_unmap_regs(struct of_device *op, struct all_info *all)
{
if (all->par.regs)
- of_iounmap(all->par.regs, sizeof(struct cg14_regs));
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct cg14_regs));
if (all->par.clut)
- of_iounmap(all->par.clut, sizeof(struct cg14_clut));
+ of_iounmap(&op->resource[0],
+ all->par.clut, sizeof(struct cg14_clut));
if (all->par.cursor)
- of_iounmap(all->par.cursor, sizeof(struct cg14_cursor));
+ of_iounmap(&op->resource[0],
+ all->par.cursor, sizeof(struct cg14_cursor));
if (all->info.screen_base)
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[1],
+ all->info.screen_base, all->par.fbsize);
}
static int __devinit cg14_init_one(struct of_device *op)
@@ -506,7 +510,7 @@ static int __devinit cg14_init_one(struct of_device *op)
if (!all->par.regs || !all->par.clut || !all->par.cursor ||
!all->info.screen_base)
- cg14_unmap_regs(all);
+ cg14_unmap_regs(op, all);
is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
(8 * 1024 * 1024));
@@ -541,7 +545,7 @@ static int __devinit cg14_init_one(struct of_device *op)
__cg14_reset(&all->par);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- cg14_unmap_regs(all);
+ cg14_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -552,7 +556,7 @@ static int __devinit cg14_init_one(struct of_device *op)
err = register_framebuffer(&all->info);
if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
- cg14_unmap_regs(all);
+ cg14_unmap_regs(op, all);
kfree(all);
return err;
}
@@ -574,18 +578,18 @@ static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id
return cg14_init_one(op);
}
-static int __devexit cg14_remove(struct of_device *dev)
+static int __devexit cg14_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- cg14_unmap_regs(all);
+ cg14_unmap_regs(op, all);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 9c8c753ef45..ada6f7e3a89 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -403,8 +403,10 @@ static int __devinit cg3_init_one(struct of_device *op)
cg3_do_default_mode(&all->par);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- of_iounmap(all->par.regs, sizeof(struct cg3_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct cg3_regs));
+ of_iounmap(&op->resource[0],
+ all->info.screen_base, all->par.fbsize);
kfree(all);
return -ENOMEM;
}
@@ -415,8 +417,10 @@ static int __devinit cg3_init_one(struct of_device *op)
err = register_framebuffer(&all->info);
if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
- of_iounmap(all->par.regs, sizeof(struct cg3_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct cg3_regs));
+ of_iounmap(&op->resource[0],
+ all->info.screen_base, all->par.fbsize);
kfree(all);
return err;
}
@@ -436,19 +440,19 @@ static int __devinit cg3_probe(struct of_device *dev, const struct of_device_id
return cg3_init_one(op);
}
-static int __devexit cg3_remove(struct of_device *dev)
+static int __devexit cg3_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- of_iounmap(all->par.regs, sizeof(struct cg3_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0], all->par.regs, sizeof(struct cg3_regs));
+ of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 64146be2eeb..4dad23a28f5 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -658,21 +658,26 @@ struct all_info {
struct cg6_par par;
};
-static void cg6_unmap_regs(struct all_info *all)
+static void cg6_unmap_regs(struct of_device *op, struct all_info *all)
{
if (all->par.fbc)
- of_iounmap(all->par.fbc, 4096);
+ of_iounmap(&op->resource[0], all->par.fbc, 4096);
if (all->par.tec)
- of_iounmap(all->par.tec, sizeof(struct cg6_tec));
+ of_iounmap(&op->resource[0],
+ all->par.tec, sizeof(struct cg6_tec));
if (all->par.thc)
- of_iounmap(all->par.thc, sizeof(struct cg6_thc));
+ of_iounmap(&op->resource[0],
+ all->par.thc, sizeof(struct cg6_thc));
if (all->par.bt)
- of_iounmap(all->par.bt, sizeof(struct bt_regs));
+ of_iounmap(&op->resource[0],
+ all->par.bt, sizeof(struct bt_regs));
if (all->par.fhc)
- of_iounmap(all->par.fhc, sizeof(u32));
+ of_iounmap(&op->resource[0],
+ all->par.fhc, sizeof(u32));
if (all->info.screen_base)
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->info.screen_base, all->par.fbsize);
}
static int __devinit cg6_init_one(struct of_device *op)
@@ -720,7 +725,7 @@ static int __devinit cg6_init_one(struct of_device *op)
all->par.fbsize, "cgsix ram");
if (!all->par.fbc || !all->par.tec || !all->par.thc ||
!all->par.bt || !all->par.fhc || !all->info.screen_base) {
- cg6_unmap_regs(all);
+ cg6_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -734,7 +739,7 @@ static int __devinit cg6_init_one(struct of_device *op)
cg6_blank(0, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- cg6_unmap_regs(all);
+ cg6_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -744,7 +749,7 @@ static int __devinit cg6_init_one(struct of_device *op)
err = register_framebuffer(&all->info);
if (err < 0) {
- cg6_unmap_regs(all);
+ cg6_unmap_regs(op, all);
fb_dealloc_cmap(&all->info.cmap);
kfree(all);
return err;
@@ -767,18 +772,18 @@ static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id
return cg6_init_one(op);
}
-static int __devexit cg6_remove(struct of_device *dev)
+static int __devexit cg6_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- cg6_unmap_regs(all);
+ cg6_unmap_regs(op, all);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index daf43f535a0..2c4bc620573 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -2442,7 +2442,10 @@ static int cirrusfb_pci_register (struct pci_dev *pdev,
printk ("Cirrus Logic chipset on PCI bus\n");
pci_set_drvdata(pdev, info);
- return cirrusfb_register(cinfo);
+ ret = cirrusfb_register(cinfo);
+ if (ret)
+ iounmap(cinfo->fbmem);
+ return ret;
err_release_legacy:
if (release_io_ports)
@@ -2574,7 +2577,15 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
zorro_set_drvdata(z, info);
- return cirrusfb_register(cinfo);
+ ret = cirrusfb_register(cinfo);
+ if (ret) {
+ if (btype == BT_PICASSO4) {
+ iounmap(cinfo->fbmem);
+ iounmap(cinfo->regbase - 0x600000);
+ } else if (board_addr > 0x01000000)
+ iounmap(cinfo->fbmem);
+ }
+ return ret;
err_unmap_regbase:
/* Parental advisory: explicit hack */
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 7d07d838356..f577bd80e02 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -1,11 +1,13 @@
/*
- * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices
+ * linux/drivers/video/softcursor.c
+ *
+ * Generic software cursor for frame buffer devices
*
* Created 14 Nov 2002 by James Simmons
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
*/
#include <linux/module.h>
@@ -25,7 +27,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
unsigned int buf_align = info->pixmap.buf_align - 1;
unsigned int i, size, dsize, s_pitch, d_pitch;
struct fb_image *image;
- u8 *dst;
+ u8 *src, *dst;
if (info->state != FBINFO_STATE_RUNNING)
return 0;
@@ -45,7 +47,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
}
}
- image = (struct fb_image *) (ops->cursor_src + dsize);
+ src = ops->cursor_src + sizeof(struct fb_image);
+ image = (struct fb_image *)ops->cursor_src;
*image = cursor->image;
d_pitch = (s_pitch + scan_align) & ~scan_align;
@@ -57,21 +60,18 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
switch (cursor->rop) {
case ROP_XOR:
for (i = 0; i < dsize; i++)
- ops->cursor_src[i] = image->data[i] ^
- cursor->mask[i];
+ src[i] = image->data[i] ^ cursor->mask[i];
break;
case ROP_COPY:
default:
for (i = 0; i < dsize; i++)
- ops->cursor_src[i] = image->data[i] &
- cursor->mask[i];
+ src[i] = image->data[i] & cursor->mask[i];
break;
}
} else
- memcpy(ops->cursor_src, image->data, dsize);
+ memcpy(src, image->data, dsize);
- fb_pad_aligned_buffer(dst, d_pitch, ops->cursor_src, s_pitch,
- image->height);
+ fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
image->data = dst;
info->fbops->fb_imageblit(info, image);
return 0;
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 45586aaabd1..57b21e53303 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -345,7 +345,7 @@ static void sticon_save_screen(struct vc_data *conp)
{
}
-static struct consw sti_con = {
+static const struct consw sti_con = {
.owner = THIS_MODULE,
.con_startup = sticon_startup,
.con_init = sticon_init,
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 0a2c10a1abf..4a9bde2c839 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -93,27 +93,27 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
static unsigned long vgacon_uni_pagedir[2];
/* Description of the hardware situation */
-static unsigned long vga_vram_base; /* Base of video memory */
-static unsigned long vga_vram_end; /* End of video memory */
-static int vga_vram_size; /* Size of video memory */
-static u16 vga_video_port_reg; /* Video register select port */
-static u16 vga_video_port_val; /* Video register value port */
-static unsigned int vga_video_num_columns; /* Number of text columns */
-static unsigned int vga_video_num_lines; /* Number of text lines */
-static int vga_can_do_color = 0; /* Do we support colors? */
-static unsigned int vga_default_font_height;/* Height of default screen font */
-static unsigned char vga_video_type; /* Card type */
-static unsigned char vga_hardscroll_enabled;
-static unsigned char vga_hardscroll_user_enable = 1;
+static int vga_init_done __read_mostly;
+static unsigned long vga_vram_base __read_mostly; /* Base of video memory */
+static unsigned long vga_vram_end __read_mostly; /* End of video memory */
+static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
+static u16 vga_video_port_reg __read_mostly; /* Video register select port */
+static u16 vga_video_port_val __read_mostly; /* Video register value port */
+static unsigned int vga_video_num_columns; /* Number of text columns */
+static unsigned int vga_video_num_lines; /* Number of text lines */
+static int vga_can_do_color __read_mostly; /* Do we support colors? */
+static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */
+static unsigned char vga_video_type __read_mostly; /* Card type */
+static unsigned char vga_hardscroll_enabled __read_mostly;
+static unsigned char vga_hardscroll_user_enable __read_mostly = 1;
static unsigned char vga_font_is_default = 1;
static int vga_vesa_blanked;
static int vga_palette_blanked;
static int vga_is_gfx;
static int vga_512_chars;
static int vga_video_font_height;
-static int vga_scan_lines;
-static unsigned int vga_rolled_over = 0;
-static int vga_init_done;
+static int vga_scan_lines __read_mostly;
+static unsigned int vga_rolled_over;
static int __init no_scroll(char *str)
{
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
index c40e72dafb0..0b8d5b12115 100644
--- a/drivers/video/cyberfb.c
+++ b/drivers/video/cyberfb.c
@@ -109,8 +109,6 @@ static void cv64_dump(void);
#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
-#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
-
struct cyberfb_par {
struct fb_var_screeninfo var;
__u32 type;
@@ -1055,6 +1053,8 @@ int __init cyberfb_init(void)
if (register_framebuffer(&fb_info) < 0) {
DPRINTK("EXIT - register_framebuffer failed\n");
+ if (CyberBase)
+ iounmap(CyberBase);
release_mem_region(CyberMem_phys, 0x400000);
release_mem_region(CyberRegs_phys, 0x10000);
return -EINVAL;
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 737257d278f..29e07c10988 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -405,7 +405,7 @@ static inline unsigned long copy_to_user16(void *to, const void *from,
static ssize_t
epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
unsigned long p = *ppos;
@@ -437,7 +437,7 @@ static ssize_t
epson1355fb_write(struct file *file, const char *buf,
size_t count, loff_t * ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
unsigned long p = *ppos;
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index e8b135f3d80..148108afdd5 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -18,63 +18,64 @@
#include <asm/uaccess.h>
-static u16 red2[] = {
+static u16 red2[] __read_mostly = {
0x0000, 0xaaaa
};
-static u16 green2[] = {
+static u16 green2[] __read_mostly = {
0x0000, 0xaaaa
};
-static u16 blue2[] = {
+static u16 blue2[] __read_mostly = {
0x0000, 0xaaaa
};
-static u16 red4[] = {
+static u16 red4[] __read_mostly = {
0x0000, 0xaaaa, 0x5555, 0xffff
};
-static u16 green4[] = {
+static u16 green4[] __read_mostly = {
0x0000, 0xaaaa, 0x5555, 0xffff
};
-static u16 blue4[] = {
+static u16 blue4[] __read_mostly = {
0x0000, 0xaaaa, 0x5555, 0xffff
};
-static u16 red8[] = {
+static u16 red8[] __read_mostly = {
0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa
};
-static u16 green8[] = {
+static u16 green8[] __read_mostly = {
0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa
};
-static u16 blue8[] = {
+static u16 blue8[] __read_mostly = {
0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa
};
-static u16 red16[] = {
+static u16 red16[] __read_mostly = {
0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
};
-static u16 green16[] = {
+static u16 green16[] __read_mostly = {
0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
};
-static u16 blue16[] = {
+static u16 blue16[] __read_mostly = {
0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
};
-static struct fb_cmap default_2_colors = {
- 0, 2, red2, green2, blue2, NULL
+static const struct fb_cmap default_2_colors = {
+ .len=2, .red=red2, .green=green2, .blue=blue2
};
-static struct fb_cmap default_8_colors = {
- 0, 8, red8, green8, blue8, NULL
+static const struct fb_cmap default_8_colors = {
+ .len=8, .red=red8, .green=green8, .blue=blue8
};
-static struct fb_cmap default_4_colors = {
- 0, 4, red4, green4, blue4, NULL
+static const struct fb_cmap default_4_colors = {
+ .len=4, .red=red4, .green=green4, .blue=blue4
};
-static struct fb_cmap default_16_colors = {
- 0, 16, red16, green16, blue16, NULL
+static const struct fb_cmap default_16_colors = {
+ .len=16, .red=red16, .green=green16, .blue=blue16
};
+
/**
* fb_alloc_cmap - allocate a colormap
* @cmap: frame buffer colormap structure
@@ -146,7 +147,7 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)
* Copy contents of colormap from @from to @to.
*/
-int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to)
+int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
{
int tooff = 0, fromoff = 0;
int size;
@@ -170,7 +171,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to)
return 0;
}
-int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to)
+int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
{
int tooff = 0, fromoff = 0;
int size;
@@ -282,7 +283,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
*
*/
-struct fb_cmap *fb_default_cmap(int len)
+const struct fb_cmap *fb_default_cmap(int len)
{
if (len <= 2)
return &default_2_colors;
@@ -305,22 +306,22 @@ void fb_invert_cmaps(void)
{
u_int i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(red2); i++) {
red2[i] = ~red2[i];
green2[i] = ~green2[i];
blue2[i] = ~blue2[i];
}
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(red4); i++) {
red4[i] = ~red4[i];
green4[i] = ~green4[i];
blue4[i] = ~blue4[i];
}
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < ARRAY_SIZE(red8); i++) {
red8[i] = ~red8[i];
green8[i] = ~green8[i];
blue8[i] = ~blue8[i];
}
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < ARRAY_SIZE(red16); i++) {
red16[i] = ~red16[i];
green16[i] = ~green16[i];
blue16[i] = ~blue16[i];
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index b5498999c4e..0847c5e72cb 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -57,7 +57,7 @@ struct fb_cvt_data {
u32 status;
};
-static int fb_cvt_vbi_tab[] = {
+static const unsigned char fb_cvt_vbi_tab[] = {
4, /* 4:3 */
5, /* 16:9 */
6, /* 16:10 */
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index e973a87fbb0..3cfea315a48 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -52,8 +52,8 @@
#define FBPIXMAPSIZE (1024 * 8)
-struct fb_info *registered_fb[FB_MAX];
-int num_registered_fb;
+struct fb_info *registered_fb[FB_MAX] __read_mostly;
+int num_registered_fb __read_mostly;
/*
* Helpers
@@ -202,7 +202,7 @@ static void fb_set_logo_truepalette(struct fb_info *info,
const struct linux_logo *logo,
u32 *palette)
{
- unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
+ static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
unsigned char redmask, greenmask, bluemask;
int redshift, greenshift, blueshift;
int i;
@@ -317,7 +317,7 @@ static struct logo_data {
int needs_truepalette;
int needs_cmapreset;
const struct linux_logo *logo;
-} fb_logo;
+} fb_logo __read_mostly;
static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
{
@@ -572,7 +572,7 @@ static ssize_t
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
u32 *buffer, *dst;
@@ -647,7 +647,7 @@ static ssize_t
fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
u32 *buffer, *src;
@@ -1081,7 +1081,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
static long
fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int fbidx = iminor(inode);
struct fb_info *info = registered_fb[fbidx];
struct fb_ops *fb = info->fbops;
@@ -1121,7 +1121,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static int
fb_mmap(struct file *file, struct vm_area_struct * vma)
{
- int fbidx = iminor(file->f_dentry->d_inode);
+ int fbidx = iminor(file->f_path.dentry->d_inode);
struct fb_info *info = registered_fb[fbidx];
struct fb_ops *fb = info->fbops;
unsigned long off;
@@ -1253,7 +1253,7 @@ fb_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations fb_fops = {
+static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
@@ -1459,8 +1459,8 @@ int fb_new_modelist(struct fb_info *info)
return err;
}
-static char *video_options[FB_MAX];
-static int ofonly;
+static char *video_options[FB_MAX] __read_mostly;
+static int ofonly __read_mostly;
extern const char *global_mode_option;
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index de93139ccbb..6b385c39b8b 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -58,7 +58,7 @@ struct broken_edid {
u32 fix;
};
-static struct broken_edid brokendb[] = {
+static const struct broken_edid brokendb[] = {
/* DEC FR-PCXAV-YZ */
{
.manufacturer = "DEC",
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 2a0e8210d39..15854aec318 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -910,7 +910,8 @@ static int ffb_init_one(struct of_device *op)
all->par.dac = of_ioremap(&op->resource[1], 0,
sizeof(struct ffb_dac), "ffb dac");
if (!all->par.dac) {
- of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
+ of_iounmap(&op->resource[2],
+ all->par.fbc, sizeof(struct ffb_fbc));
kfree(all);
return -ENOMEM;
}
@@ -968,6 +969,10 @@ static int ffb_init_one(struct of_device *op)
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
printk(KERN_ERR "ffb: Could not allocate color map.\n");
+ of_iounmap(&op->resource[2],
+ all->par.fbc, sizeof(struct ffb_fbc));
+ of_iounmap(&op->resource[1],
+ all->par.dac, sizeof(struct ffb_dac));
kfree(all);
return -ENOMEM;
}
@@ -978,6 +983,10 @@ static int ffb_init_one(struct of_device *op)
if (err < 0) {
printk(KERN_ERR "ffb: Could not register framebuffer.\n");
fb_dealloc_cmap(&all->info.cmap);
+ of_iounmap(&op->resource[2],
+ all->par.fbc, sizeof(struct ffb_fbc));
+ of_iounmap(&op->resource[1],
+ all->par.dac, sizeof(struct ffb_dac));
kfree(all);
return err;
}
@@ -999,19 +1008,19 @@ static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id
return ffb_init_one(op);
}
-static int __devexit ffb_remove(struct of_device *dev)
+static int __devexit ffb_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- of_iounmap(all->par.fbc, sizeof(struct ffb_fbc));
- of_iounmap(all->par.dac, sizeof(struct ffb_dac));
+ of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc));
+ of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac));
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 998374cfae6..70ff55b1459 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -283,6 +283,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
if (register_framebuffer(info) < 0) {
fb_dealloc_cmap(&info->cmap);
+ iounmap(info->screen_base);
framebuffer_release(info);
zorro_release_device(z);
return -EINVAL;
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
index 4e173ef20a7..a814b6c2605 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -23,6 +23,26 @@ config FB_GEODE_GX
If unsure, say N.
+config FB_GEODE_GX_SET_FBSIZE
+ bool "Manually specify the Geode GX framebuffer size"
+ depends on FB_GEODE_GX
+ default n
+ ---help---
+ If you want to manually specify the size of your GX framebuffer,
+ say Y here, otherwise say N to dynamically probe it.
+
+ Say N unless you know what you are doing.
+
+config FB_GEODE_GX_FBSIZE
+ hex "Size of the GX framebuffer, in bytes"
+ depends on FB_GEODE_GX_SET_FBSIZE
+ default "0x1600000"
+ ---help---
+ Specify the size of the GX framebuffer. Normally, you will
+ want this to be MB aligned. Common values are 0x80000 (8MB)
+ and 0x1600000 (16MB). Don't change this unless you know what
+ you are doing
+
config FB_GEODE_GX1
tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
depends on FB && FB_GEODE && EXPERIMENTAL
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
index 825c3405f5c..0f16e4bffc6 100644
--- a/drivers/video/geode/display_gx.c
+++ b/drivers/video/geode/display_gx.c
@@ -21,11 +21,27 @@
#include "geodefb.h"
#include "display_gx.h"
-int gx_frame_buffer_size(void)
+#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
+unsigned int gx_frame_buffer_size(void)
{
- /* Assuming 16 MiB. */
- return 16*1024*1024;
+ return CONFIG_FB_GEODE_GX_FBSIZE;
}
+#else
+unsigned int gx_frame_buffer_size(void)
+{
+ unsigned int val;
+
+ /* FB size is reported by a virtual register */
+ /* Virtual register class = 0x02 */
+ /* VG_MEM_SIZE(512Kb units) = 0x00 */
+
+ outw(0xFC53, 0xAC1C);
+ outw(0x0200, 0xAC1C);
+
+ val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
+ return (val << 19);
+}
+#endif
int gx_line_delta(int xres, int bpp)
{
@@ -81,6 +97,7 @@ static void gx_set_mode(struct fb_info *info)
writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
par->dc_regs + DC_LINE_SIZE);
+
/* Enable graphics and video data and unmask address lines. */
dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M;
diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h
index 86c62336130..0af33f329e8 100644
--- a/drivers/video/geode/display_gx.h
+++ b/drivers/video/geode/display_gx.h
@@ -11,11 +11,15 @@
#ifndef __DISPLAY_GX_H__
#define __DISPLAY_GX_H__
-int gx_frame_buffer_size(void);
+unsigned int gx_frame_buffer_size(void);
int gx_line_delta(int xres, int bpp);
extern struct geode_dc_ops gx_dc_ops;
+/* MSR that tells us if a TFT or CRT is attached */
+#define GLD_MSR_CONFIG 0xC0002001
+#define GLD_MSR_CONFIG_DM_FP 0x40
+
/* Display controller registers */
#define DC_UNLOCK 0x00
@@ -93,4 +97,5 @@ extern struct geode_dc_ops gx_dc_ops;
#define DC_PAL_ADDRESS 0x70
#define DC_PAL_DATA 0x74
+#define DC_GLIU0_MEM_OFFSET 0x84
#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index a454dcb8e21..cf841efa229 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -35,10 +35,10 @@
#include "display_gx.h"
#include "video_gx.h"
-static char mode_option[32] = "640x480-16@60";
+static char *mode_option;
/* Modes relevant to the GX (taken from modedb.c) */
-static const struct fb_videomode __initdata gx_modedb[] = {
+static const struct fb_videomode gx_modedb[] __initdata = {
/* 640x480-60 VESA */
{ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -240,6 +240,12 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de
if (!info->screen_base)
return -ENOMEM;
+ /* Set the 16MB aligned base address of the graphics memory region
+ * in the display controller */
+
+ writel(info->fix.smem_start & 0xFF000000,
+ par->dc_regs + DC_GLIU0_MEM_OFFSET);
+
dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
info->fix.smem_len / 1024, info->fix.smem_start);
@@ -302,6 +308,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
struct geodefb_par *par;
struct fb_info *info;
int ret;
+ unsigned long val;
info = gxfb_init_fbinfo(&pdev->dev);
if (!info)
@@ -317,6 +324,15 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
goto err;
}
+ /* Figure out if this is a TFT or CRT part */
+
+ rdmsrl(GLD_MSR_CONFIG, val);
+
+ if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP)
+ par->enable_crt = 0;
+ else
+ par->enable_crt = 1;
+
ret = fb_find_mode(&info->var, info, mode_option,
gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
if (ret == 0 || ret == 4) {
@@ -325,7 +341,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
goto err;
}
- /* Clear the frame buffer of garbage. */
+
+ /* Clear the frame buffer of garbage. */
memset_io(info->screen_base, 0, info->fix.smem_len);
gxfb_check_var(&info->var, info);
@@ -395,11 +412,35 @@ static struct pci_driver gxfb_driver = {
.remove = gxfb_remove,
};
+#ifndef MODULE
+static int __init gxfb_setup(char *options)
+{
+
+ char *opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+
+ mode_option = opt;
+ }
+
+ return 0;
+}
+#endif
+
static int __init gxfb_init(void)
{
#ifndef MODULE
- if (fb_get_options("gxfb", NULL))
+ char *option = NULL;
+
+ if (fb_get_options("gxfb", &option))
return -ENODEV;
+
+ gxfb_setup(option);
#endif
return pci_register_driver(&gxfb_driver);
}
@@ -412,8 +453,8 @@ static void __exit gxfb_cleanup(void)
module_init(gxfb_init);
module_exit(gxfb_cleanup);
-module_param_string(mode, mode_option, sizeof(mode_option), 0444);
-MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
index 2b2a7880ea7..7f3f18d0671 100644
--- a/drivers/video/geode/video_gx.c
+++ b/drivers/video/geode/video_gx.c
@@ -175,13 +175,88 @@ static void gx_set_dclk_frequency(struct fb_info *info)
} while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
}
+static void
+gx_configure_tft(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ unsigned long val;
+ unsigned long fp;
+
+ /* Set up the DF pad select MSR */
+
+ rdmsrl(GX_VP_MSR_PAD_SELECT, val);
+ val &= ~GX_VP_PAD_SELECT_MASK;
+ val |= GX_VP_PAD_SELECT_TFT;
+ wrmsrl(GX_VP_MSR_PAD_SELECT, val);
+
+ /* Turn off the panel */
+
+ fp = readl(par->vid_regs + GX_FP_PM);
+ fp &= ~GX_FP_PM_P;
+ writel(fp, par->vid_regs + GX_FP_PM);
+
+ /* Set timing 1 */
+
+ fp = readl(par->vid_regs + GX_FP_PT1);
+ fp &= GX_FP_PT1_VSIZE_MASK;
+ fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
+ writel(fp, par->vid_regs + GX_FP_PT1);
+
+ /* Timing 2 */
+ /* Set bits that are always on for TFT */
+
+ fp = 0x0F100000;
+
+ /* Add sync polarity */
+
+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+ fp |= GX_FP_PT2_VSP;
+
+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+ fp |= GX_FP_PT2_HSP;
+
+ writel(fp, par->vid_regs + GX_FP_PT2);
+
+ /* Set the dither control */
+ writel(0x70, par->vid_regs + GX_FP_DFC);
+
+ /* Enable the FP data and power (in case the BIOS didn't) */
+
+ fp = readl(par->vid_regs + GX_DCFG);
+ fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
+ writel(fp, par->vid_regs + GX_DCFG);
+
+ /* Unblank the panel */
+
+ fp = readl(par->vid_regs + GX_FP_PM);
+ fp |= GX_FP_PM_P;
+ writel(fp, par->vid_regs + GX_FP_PM);
+}
+
static void gx_configure_display(struct fb_info *info)
{
struct geodefb_par *par = info->par;
- u32 dcfg, fp_pm;
+ u32 dcfg, misc;
+
+ /* Set up the MISC register */
+
+ misc = readl(par->vid_regs + GX_MISC);
+
+ /* Power up the DAC */
+ misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
+
+ /* Disable gamma correction */
+ misc |= GX_MISC_GAM_EN;
+
+ writel(misc, par->vid_regs + GX_MISC);
+ /* Write the display configuration */
dcfg = readl(par->vid_regs + GX_DCFG);
+ /* Disable hsync and vsync */
+ dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
+ writel(dcfg, par->vid_regs + GX_DCFG);
+
/* Clear bits from existing mode. */
dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
| GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
@@ -199,12 +274,19 @@ static void gx_configure_display(struct fb_info *info)
if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
dcfg |= GX_DCFG_CRT_VSYNC_POL;
+ /* Enable the display logic */
+ /* Set up the DACS to blank normally */
+
+ dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
+
+ /* Enable the external DAC VREF? */
+
writel(dcfg, par->vid_regs + GX_DCFG);
- /* Power on flat panel. */
- fp_pm = readl(par->vid_regs + GX_FP_PM);
- fp_pm |= GX_FP_PM_P;
- writel(fp_pm, par->vid_regs + GX_FP_PM);
+ /* Set up the flat panel (if it is enabled) */
+
+ if (par->enable_crt == 0)
+ gx_configure_tft(info);
}
static int gx_blank_display(struct fb_info *info, int blank_mode)
@@ -245,12 +327,15 @@ static int gx_blank_display(struct fb_info *info, int blank_mode)
writel(dcfg, par->vid_regs + GX_DCFG);
/* Power on/off flat panel. */
- fp_pm = readl(par->vid_regs + GX_FP_PM);
- if (blank_mode == FB_BLANK_POWERDOWN)
- fp_pm &= ~GX_FP_PM_P;
- else
- fp_pm |= GX_FP_PM_P;
- writel(fp_pm, par->vid_regs + GX_FP_PM);
+
+ if (par->enable_crt == 0) {
+ fp_pm = readl(par->vid_regs + GX_FP_PM);
+ if (blank_mode == FB_BLANK_POWERDOWN)
+ fp_pm &= ~GX_FP_PM_P;
+ else
+ fp_pm |= GX_FP_PM_P;
+ writel(fp_pm, par->vid_regs + GX_FP_PM);
+ }
return 0;
}
diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h
index 2d9211f3ed8..ce28d8f382d 100644
--- a/drivers/video/geode/video_gx.h
+++ b/drivers/video/geode/video_gx.h
@@ -13,6 +13,11 @@
extern struct geode_vid_ops gx_vid_ops;
+/* GX Flatpanel control MSR */
+#define GX_VP_MSR_PAD_SELECT 0xC0002011
+#define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF
+#define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF
+
/* Geode GX video processor registers */
#define GX_DCFG 0x0008
@@ -20,6 +25,8 @@ extern struct geode_vid_ops gx_vid_ops;
# define GX_DCFG_HSYNC_EN 0x00000002
# define GX_DCFG_VSYNC_EN 0x00000004
# define GX_DCFG_DAC_BL_EN 0x00000008
+# define GX_DCFG_FP_PWR_EN 0x00000040
+# define GX_DCFG_FP_DATA_EN 0x00000080
# define GX_DCFG_CRT_HSYNC_POL 0x00000100
# define GX_DCFG_CRT_VSYNC_POL 0x00000200
# define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
@@ -28,10 +35,28 @@ extern struct geode_vid_ops gx_vid_ops;
# define GX_DCFG_GV_GAM 0x00200000
# define GX_DCFG_DAC_VREF 0x04000000
+/* Geode GX MISC video configuration */
+
+#define GX_MISC 0x50
+#define GX_MISC_GAM_EN 0x00000001
+#define GX_MISC_DAC_PWRDN 0x00000400
+#define GX_MISC_A_PWRDN 0x00000800
+
/* Geode GX flat panel display control registers */
+
+#define GX_FP_PT1 0x0400
+#define GX_FP_PT1_VSIZE_MASK 0x7FF0000
+#define GX_FP_PT1_VSIZE_SHIFT 16
+
+#define GX_FP_PT2 0x408
+#define GX_FP_PT2_VSP (1 << 23)
+#define GX_FP_PT2_HSP (1 << 22)
+
#define GX_FP_PM 0x410
# define GX_FP_PM_P 0x01000000
+#define GX_FP_DFC 0x418
+
/* Geode GX clock control MSRs */
#define MSR_GLCP_SYS_RSTPLL 0x4c000014
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
new file mode 100644
index 00000000000..23a6bcc3e3c
--- /dev/null
+++ b/drivers/video/gxt4500.c
@@ -0,0 +1,774 @@
+/*
+ * Frame buffer device for IBM GXT4500P and GXT6000P display adaptors
+ *
+ * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+#define PCI_DEVICE_ID_IBM_GXT4500P 0x21c
+#define PCI_DEVICE_ID_IBM_GXT6000P 0x170
+
+/* GXT4500P registers */
+
+/* Registers in PCI config space */
+#define CFG_ENDIAN0 0x40
+
+/* Misc control/status registers */
+#define STATUS 0x1000
+#define CTRL_REG0 0x1004
+#define CR0_HALT_DMA 0x4
+#define CR0_RASTER_RESET 0x8
+#define CR0_GEOM_RESET 0x10
+#define CR0_MEM_CTRLER_RESET 0x20
+
+/* Framebuffer control registers */
+#define FB_AB_CTRL 0x1100
+#define FB_CD_CTRL 0x1104
+#define FB_WID_CTRL 0x1108
+#define FB_Z_CTRL 0x110c
+#define FB_VGA_CTRL 0x1110
+#define REFRESH_AB_CTRL 0x1114
+#define REFRESH_CD_CTRL 0x1118
+#define FB_OVL_CTRL 0x111c
+#define FB_CTRL_TYPE 0x80000000
+#define FB_CTRL_WIDTH_MASK 0x007f0000
+#define FB_CTRL_WIDTH_SHIFT 16
+#define FB_CTRL_START_SEG_MASK 0x00003fff
+
+#define REFRESH_START 0x1098
+#define REFRESH_SIZE 0x109c
+
+/* "Direct" framebuffer access registers */
+#define DFA_FB_A 0x11e0
+#define DFA_FB_B 0x11e4
+#define DFA_FB_C 0x11e8
+#define DFA_FB_D 0x11ec
+#define DFA_FB_ENABLE 0x80000000
+#define DFA_FB_BASE_MASK 0x03f00000
+#define DFA_FB_STRIDE_1k 0x00000000
+#define DFA_FB_STRIDE_2k 0x00000010
+#define DFA_FB_STRIDE_4k 0x00000020
+#define DFA_PIX_8BIT 0x00000000
+#define DFA_PIX_16BIT_565 0x00000001
+#define DFA_PIX_16BIT_1555 0x00000002
+#define DFA_PIX_24BIT 0x00000004
+#define DFA_PIX_32BIT 0x00000005
+
+/* maps DFA_PIX_* to pixel size in bytes */
+static const unsigned char pixsize[] = {
+ 1, 2, 2, 2, 4, 4
+};
+
+/* Display timing generator registers */
+#define DTG_CONTROL 0x1900
+#define DTG_CTL_SCREEN_REFRESH 2
+#define DTG_CTL_ENABLE 1
+#define DTG_HORIZ_EXTENT 0x1904
+#define DTG_HORIZ_DISPLAY 0x1908
+#define DTG_HSYNC_START 0x190c
+#define DTG_HSYNC_END 0x1910
+#define DTG_HSYNC_END_COMP 0x1914
+#define DTG_VERT_EXTENT 0x1918
+#define DTG_VERT_DISPLAY 0x191c
+#define DTG_VSYNC_START 0x1920
+#define DTG_VSYNC_END 0x1924
+#define DTG_VERT_SHORT 0x1928
+
+/* PLL/RAMDAC registers */
+#define DISP_CTL 0x402c
+#define DISP_CTL_OFF 2
+#define SYNC_CTL 0x4034
+#define SYNC_CTL_SYNC_ON_RGB 1
+#define SYNC_CTL_SYNC_OFF 2
+#define SYNC_CTL_HSYNC_INV 8
+#define SYNC_CTL_VSYNC_INV 0x10
+#define SYNC_CTL_HSYNC_OFF 0x20
+#define SYNC_CTL_VSYNC_OFF 0x40
+
+#define PLL_M 0x4040
+#define PLL_N 0x4044
+#define PLL_POSTDIV 0x4048
+#define PLL_C 0x404c
+
+/* Hardware cursor */
+#define CURSOR_X 0x4078
+#define CURSOR_Y 0x407c
+#define CURSOR_HOTSPOT 0x4080
+#define CURSOR_MODE 0x4084
+#define CURSOR_MODE_OFF 0
+#define CURSOR_MODE_4BPP 1
+#define CURSOR_PIXMAP 0x5000
+#define CURSOR_CMAP 0x7400
+
+/* Window attribute table */
+#define WAT_FMT 0x4100
+#define WAT_FMT_24BIT 0
+#define WAT_FMT_16BIT_565 1
+#define WAT_FMT_16BIT_1555 2
+#define WAT_FMT_32BIT 3 /* 0 vs. 3 is a guess */
+#define WAT_FMT_8BIT_332 9
+#define WAT_FMT_8BIT 0xa
+#define WAT_FMT_NO_CMAP 4 /* ORd in to other values */
+#define WAT_CMAP_OFFSET 0x4104 /* 4-bit value gets << 6 */
+#define WAT_CTRL 0x4108
+#define WAT_CTRL_SEL_B 1 /* select B buffer if 1 */
+#define WAT_CTRL_NO_INC 2
+#define WAT_GAMMA_CTRL 0x410c
+#define WAT_GAMMA_DISABLE 1 /* disables gamma cmap */
+#define WAT_OVL_CTRL 0x430c /* controls overlay */
+
+/* Indexed by DFA_PIX_* values */
+static const unsigned char watfmt[] = {
+ WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0,
+ WAT_FMT_24BIT, WAT_FMT_32BIT
+};
+
+/* Colormap array; 1k entries of 4 bytes each */
+#define CMAP 0x6000
+
+#define readreg(par, reg) readl((par)->regs + (reg))
+#define writereg(par, reg, val) writel((val), (par)->regs + (reg))
+
+struct gxt4500_par {
+ void __iomem *regs;
+
+ int pixfmt; /* pixel format, see DFA_PIX_* values */
+
+ /* PLL parameters */
+ int refclk_ps; /* ref clock period in picoseconds */
+ int pll_m; /* ref clock divisor */
+ int pll_n; /* VCO divisor */
+ int pll_pd1; /* first post-divisor */
+ int pll_pd2; /* second post-divisor */
+
+ u32 pseudo_palette[16]; /* used in color blits */
+};
+
+/* mode requested by user */
+static char *mode_option;
+
+/* default mode: 1280x1024 @ 60 Hz, 8 bpp */
+static const struct fb_videomode defaultmode __devinitdata = {
+ .refresh = 60,
+ .xres = 1280,
+ .yres = 1024,
+ .pixclock = 9295,
+ .left_margin = 248,
+ .right_margin = 48,
+ .upper_margin = 38,
+ .lower_margin = 1,
+ .hsync_len = 112,
+ .vsync_len = 3,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+/* List of supported cards */
+enum gxt_cards {
+ GXT4500P,
+ GXT6000P
+};
+
+/* Card-specific information */
+static const struct cardinfo {
+ int refclk_ps; /* period of PLL reference clock in ps */
+ const char *cardname;
+} cardinfo[] = {
+ [GXT4500P] = { .refclk_ps = 9259, .cardname = "IBM GXT4500P" },
+ [GXT6000P] = { .refclk_ps = 40000, .cardname = "IBM GXT6000P" },
+};
+
+/*
+ * The refclk and VCO dividers appear to use a linear feedback shift
+ * register, which gets reloaded when it reaches a terminal value, at
+ * which point the divider output is toggled. Thus one can obtain
+ * whatever divisor is required by putting the appropriate value into
+ * the reload register. For a divisor of N, one puts the value from
+ * the LFSR sequence that comes N-1 places before the terminal value
+ * into the reload register.
+ */
+
+static const unsigned char mdivtab[] = {
+/* 1 */ 0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a,
+/* 10 */ 0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11,
+/* 20 */ 0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d,
+/* 30 */ 0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02,
+/* 40 */ 0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e,
+/* 50 */ 0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e,
+/* 60 */ 0x1f, 0x0f, 0x07, 0x03, 0x01,
+};
+
+static const unsigned char ndivtab[] = {
+/* 2 */ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e,
+/* 10 */ 0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e,
+/* 20 */ 0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf,
+/* 30 */ 0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc,
+/* 40 */ 0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8,
+/* 50 */ 0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6,
+/* 60 */ 0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62,
+/* 70 */ 0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57,
+/* 80 */ 0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94,
+/* 90 */ 0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79,
+/* 100 */ 0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24,
+/* 110 */ 0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45,
+/* 120 */ 0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d,
+/* 130 */ 0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e,
+/* 140 */ 0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98,
+/* 150 */ 0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2,
+/* 160 */ 0x69,
+};
+
+static int calc_pll(int period_ps, struct gxt4500_par *par)
+{
+ int m, n, pdiv1, pdiv2, postdiv;
+ int pll_period, best_error, t, intf;
+
+ /* only deal with range 5MHz - 300MHz */
+ if (period_ps < 3333 || period_ps > 200000)
+ return -1;
+
+ best_error = 1000000;
+ for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) {
+ for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) {
+ postdiv = pdiv1 * pdiv2;
+ pll_period = (period_ps + postdiv - 1) / postdiv;
+ /* keep pll in range 350..600 MHz */
+ if (pll_period < 1666 || pll_period > 2857)
+ continue;
+ for (m = 1; m <= 64; ++m) {
+ intf = m * par->refclk_ps;
+ if (intf > 500000)
+ break;
+ n = intf * postdiv / period_ps;
+ if (n < 3 || n > 160)
+ continue;
+ t = par->refclk_ps * m * postdiv / n;
+ t -= period_ps;
+ if (t >= 0 && t < best_error) {
+ par->pll_m = m;
+ par->pll_n = n;
+ par->pll_pd1 = pdiv1;
+ par->pll_pd2 = pdiv2;
+ best_error = t;
+ }
+ }
+ }
+ }
+ if (best_error == 1000000)
+ return -1;
+ return 0;
+}
+
+static int calc_pixclock(struct gxt4500_par *par)
+{
+ return par->refclk_ps * par->pll_m * par->pll_pd1 * par->pll_pd2
+ / par->pll_n;
+}
+
+static int gxt4500_var_to_par(struct fb_var_screeninfo *var,
+ struct gxt4500_par *par)
+{
+ if (var->xres + var->xoffset > var->xres_virtual ||
+ var->yres + var->yoffset > var->yres_virtual ||
+ var->xres_virtual > 4096)
+ return -EINVAL;
+ if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+ return -EINVAL;
+
+ if (calc_pll(var->pixclock, par) < 0)
+ return -EINVAL;
+
+ switch (var->bits_per_pixel) {
+ case 32:
+ if (var->transp.length)
+ par->pixfmt = DFA_PIX_32BIT;
+ else
+ par->pixfmt = DFA_PIX_24BIT;
+ break;
+ case 24:
+ par->pixfmt = DFA_PIX_24BIT;
+ break;
+ case 16:
+ if (var->green.length == 5)
+ par->pixfmt = DFA_PIX_16BIT_1555;
+ else
+ par->pixfmt = DFA_PIX_16BIT_565;
+ break;
+ case 8:
+ par->pixfmt = DFA_PIX_8BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct fb_bitfield eightbits = {0, 8};
+static const struct fb_bitfield nobits = {0, 0};
+
+static void gxt4500_unpack_pixfmt(struct fb_var_screeninfo *var,
+ int pixfmt)
+{
+ var->bits_per_pixel = pixsize[pixfmt] * 8;
+ var->red = eightbits;
+ var->green = eightbits;
+ var->blue = eightbits;
+ var->transp = nobits;
+
+ switch (pixfmt) {
+ case DFA_PIX_16BIT_565:
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ break;
+ case DFA_PIX_16BIT_1555:
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ var->transp.length = 1;
+ break;
+ case DFA_PIX_32BIT:
+ var->transp.length = 8;
+ break;
+ }
+ if (pixfmt != DFA_PIX_8BIT) {
+ var->green.offset = var->red.length;
+ var->blue.offset = var->green.offset + var->green.length;
+ if (var->transp.length)
+ var->transp.offset =
+ var->blue.offset + var->blue.length;
+ }
+}
+
+static int gxt4500_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct gxt4500_par par;
+ int err;
+
+ par = *(struct gxt4500_par *)info->par;
+ err = gxt4500_var_to_par(var, &par);
+ if (!err) {
+ var->pixclock = calc_pixclock(&par);
+ gxt4500_unpack_pixfmt(var, par.pixfmt);
+ }
+ return err;
+}
+
+static int gxt4500_set_par(struct fb_info *info)
+{
+ struct gxt4500_par *par = info->par;
+ struct fb_var_screeninfo *var = &info->var;
+ int err;
+ u32 ctrlreg, tmp;
+ unsigned int dfa_ctl, pixfmt, stride;
+ unsigned int wid_tiles, i;
+ unsigned int prefetch_pix, htot;
+ struct gxt4500_par save_par;
+
+ save_par = *par;
+ err = gxt4500_var_to_par(var, par);
+ if (err) {
+ *par = save_par;
+ return err;
+ }
+
+ /* turn off DTG for now */
+ ctrlreg = readreg(par, DTG_CONTROL);
+ ctrlreg &= ~(DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH);
+ writereg(par, DTG_CONTROL, ctrlreg);
+
+ /* set PLL registers */
+ tmp = readreg(par, PLL_C) & ~0x7f;
+ if (par->pll_n < 38)
+ tmp |= 0x29;
+ if (par->pll_n < 69)
+ tmp |= 0x35;
+ else if (par->pll_n < 100)
+ tmp |= 0x76;
+ else
+ tmp |= 0x7e;
+ writereg(par, PLL_C, tmp);
+ writereg(par, PLL_M, mdivtab[par->pll_m - 1]);
+ writereg(par, PLL_N, ndivtab[par->pll_n - 2]);
+ tmp = ((8 - par->pll_pd2) << 3) | (8 - par->pll_pd1);
+ if (par->pll_pd1 == 8 || par->pll_pd2 == 8) {
+ /* work around erratum */
+ writereg(par, PLL_POSTDIV, tmp | 0x9);
+ udelay(1);
+ }
+ writereg(par, PLL_POSTDIV, tmp);
+ msleep(20);
+
+ /* turn off hardware cursor */
+ writereg(par, CURSOR_MODE, CURSOR_MODE_OFF);
+
+ /* reset raster engine */
+ writereg(par, CTRL_REG0, CR0_RASTER_RESET | (CR0_RASTER_RESET << 16));
+ udelay(10);
+ writereg(par, CTRL_REG0, CR0_RASTER_RESET << 16);
+
+ /* set display timing generator registers */
+ htot = var->xres + var->left_margin + var->right_margin +
+ var->hsync_len;
+ writereg(par, DTG_HORIZ_EXTENT, htot - 1);
+ writereg(par, DTG_HORIZ_DISPLAY, var->xres - 1);
+ writereg(par, DTG_HSYNC_START, var->xres + var->right_margin - 1);
+ writereg(par, DTG_HSYNC_END,
+ var->xres + var->right_margin + var->hsync_len - 1);
+ writereg(par, DTG_HSYNC_END_COMP,
+ var->xres + var->right_margin + var->hsync_len - 1);
+ writereg(par, DTG_VERT_EXTENT,
+ var->yres + var->upper_margin + var->lower_margin +
+ var->vsync_len - 1);
+ writereg(par, DTG_VERT_DISPLAY, var->yres - 1);
+ writereg(par, DTG_VSYNC_START, var->yres + var->lower_margin - 1);
+ writereg(par, DTG_VSYNC_END,
+ var->yres + var->lower_margin + var->vsync_len - 1);
+ prefetch_pix = 3300000 / var->pixclock;
+ if (prefetch_pix >= htot)
+ prefetch_pix = htot - 1;
+ writereg(par, DTG_VERT_SHORT, htot - prefetch_pix - 1);
+ ctrlreg |= DTG_CTL_ENABLE | DTG_CTL_SCREEN_REFRESH;
+ writereg(par, DTG_CONTROL, ctrlreg);
+
+ /* calculate stride in DFA aperture */
+ if (var->xres_virtual > 2048) {
+ stride = 4096;
+ dfa_ctl = DFA_FB_STRIDE_4k;
+ } else if (var->xres_virtual > 1024) {
+ stride = 2048;
+ dfa_ctl = DFA_FB_STRIDE_2k;
+ } else {
+ stride = 1024;
+ dfa_ctl = DFA_FB_STRIDE_1k;
+ }
+
+ /* Set up framebuffer definition */
+ wid_tiles = (var->xres_virtual + 63) >> 6;
+
+ /* XXX add proper FB allocation here someday */
+ writereg(par, FB_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+ writereg(par, REFRESH_AB_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+ writereg(par, FB_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+ writereg(par, REFRESH_CD_CTRL, FB_CTRL_TYPE | (wid_tiles << 16) | 0);
+ writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
+ writereg(par, REFRESH_SIZE, (var->xres << 16) | var->yres);
+
+ /* Set up framebuffer access by CPU */
+
+ pixfmt = par->pixfmt;
+ dfa_ctl |= DFA_FB_ENABLE | pixfmt;
+ writereg(par, DFA_FB_A, dfa_ctl);
+
+ /*
+ * Set up window attribute table.
+ * We set all WAT entries the same so it doesn't matter what the
+ * window ID (WID) plane contains.
+ */
+ for (i = 0; i < 32; ++i) {
+ writereg(par, WAT_FMT + (i << 4), watfmt[pixfmt]);
+ writereg(par, WAT_CMAP_OFFSET + (i << 4), 0);
+ writereg(par, WAT_CTRL + (i << 4), 0);
+ writereg(par, WAT_GAMMA_CTRL + (i << 4), WAT_GAMMA_DISABLE);
+ }
+
+ /* Set sync polarity etc. */
+ ctrlreg = readreg(par, SYNC_CTL) &
+ ~(SYNC_CTL_SYNC_ON_RGB | SYNC_CTL_HSYNC_INV |
+ SYNC_CTL_VSYNC_INV);
+ if (var->sync & FB_SYNC_ON_GREEN)
+ ctrlreg |= SYNC_CTL_SYNC_ON_RGB;
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+ ctrlreg |= SYNC_CTL_HSYNC_INV;
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+ ctrlreg |= SYNC_CTL_VSYNC_INV;
+ writereg(par, SYNC_CTL, ctrlreg);
+
+ info->fix.line_length = stride * pixsize[pixfmt];
+ info->fix.visual = (pixfmt == DFA_PIX_8BIT)? FB_VISUAL_PSEUDOCOLOR:
+ FB_VISUAL_DIRECTCOLOR;
+
+ return 0;
+}
+
+static int gxt4500_setcolreg(unsigned int reg, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
+{
+ u32 cmap_entry;
+ struct gxt4500_par *par = info->par;
+
+ if (reg > 1023)
+ return 1;
+ cmap_entry = ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
+ (green & 0xff00) | (blue >> 8);
+ writereg(par, CMAP + reg * 4, cmap_entry);
+
+ if (reg < 16 && par->pixfmt != DFA_PIX_8BIT) {
+ u32 *pal = info->pseudo_palette;
+ u32 val = reg;
+ switch (par->pixfmt) {
+ case DFA_PIX_16BIT_565:
+ val |= (reg << 11) | (reg << 6);
+ break;
+ case DFA_PIX_16BIT_1555:
+ val |= (reg << 10) | (reg << 5);
+ break;
+ case DFA_PIX_32BIT:
+ val |= (reg << 24);
+ /* fall through */
+ case DFA_PIX_24BIT:
+ val |= (reg << 16) | (reg << 8);
+ break;
+ }
+ pal[reg] = val;
+ }
+
+ return 0;
+}
+
+static int gxt4500_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct gxt4500_par *par = info->par;
+
+ if (var->xoffset & 7)
+ return -EINVAL;
+ if (var->xoffset + var->xres > var->xres_virtual ||
+ var->yoffset + var->yres > var->yres_virtual)
+ return -EINVAL;
+
+ writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
+ return 0;
+}
+
+static int gxt4500_blank(int blank, struct fb_info *info)
+{
+ struct gxt4500_par *par = info->par;
+ int ctrl, dctl;
+
+ ctrl = readreg(par, SYNC_CTL);
+ ctrl &= ~(SYNC_CTL_SYNC_OFF | SYNC_CTL_HSYNC_OFF | SYNC_CTL_VSYNC_OFF);
+ dctl = readreg(par, DISP_CTL);
+ dctl |= DISP_CTL_OFF;
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ dctl &= ~DISP_CTL_OFF;
+ break;
+ case FB_BLANK_POWERDOWN:
+ ctrl |= SYNC_CTL_SYNC_OFF;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ ctrl |= SYNC_CTL_HSYNC_OFF;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ ctrl |= SYNC_CTL_VSYNC_OFF;
+ break;
+ default: ;
+ }
+ writereg(par, SYNC_CTL, ctrl);
+ writereg(par, DISP_CTL, dctl);
+
+ return 0;
+}
+
+static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = {
+ .id = "IBM GXT4500P",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .xpanstep = 8,
+ .ypanstep = 1,
+ .mmio_len = 0x20000,
+};
+
+static struct fb_ops gxt4500_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = gxt4500_check_var,
+ .fb_set_par = gxt4500_set_par,
+ .fb_setcolreg = gxt4500_setcolreg,
+ .fb_pan_display = gxt4500_pan_display,
+ .fb_blank = gxt4500_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+/* PCI functions */
+static int __devinit gxt4500_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int err;
+ unsigned long reg_phys, fb_phys;
+ struct gxt4500_par *par;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ enum gxt_cards cardtype;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n",
+ err);
+ return err;
+ }
+
+ reg_phys = pci_resource_start(pdev, 0);
+ if (!request_mem_region(reg_phys, pci_resource_len(pdev, 0),
+ "gxt4500 regs")) {
+ dev_err(&pdev->dev, "gxt4500: cannot get registers\n");
+ goto err_nodev;
+ }
+
+ fb_phys = pci_resource_start(pdev, 1);
+ if (!request_mem_region(fb_phys, pci_resource_len(pdev, 1),
+ "gxt4500 FB")) {
+ dev_err(&pdev->dev, "gxt4500: cannot get framebuffer\n");
+ goto err_free_regs;
+ }
+
+ info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev);
+ if (!info) {
+ dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record");
+ goto err_free_fb;
+ }
+ par = info->par;
+ cardtype = ent->driver_data;
+ par->refclk_ps = cardinfo[cardtype].refclk_ps;
+ info->fix = gxt4500_fix;
+ strlcpy(info->fix.id, cardinfo[cardtype].cardname,
+ sizeof(info->fix.id));
+ info->pseudo_palette = par->pseudo_palette;
+
+ info->fix.mmio_start = reg_phys;
+ par->regs = ioremap(reg_phys, pci_resource_len(pdev, 0));
+ if (!par->regs) {
+ dev_err(&pdev->dev, "gxt4500: cannot map registers\n");
+ goto err_free_all;
+ }
+
+ info->fix.smem_start = fb_phys;
+ info->fix.smem_len = pci_resource_len(pdev, 1);
+ info->screen_base = ioremap(fb_phys, pci_resource_len(pdev, 1));
+ if (!info->screen_base) {
+ dev_err(&pdev->dev, "gxt4500: cannot map framebuffer\n");
+ goto err_unmap_regs;
+ }
+
+ pci_set_drvdata(pdev, info);
+
+ /* Set byte-swapping for DFA aperture for all pixel sizes */
+ pci_write_config_dword(pdev, CFG_ENDIAN0, 0x333300);
+
+ info->fbops = &gxt4500_ops;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ err = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (err) {
+ dev_err(&pdev->dev, "gxt4500: cannot allocate cmap\n");
+ goto err_unmap_all;
+ }
+
+ gxt4500_blank(FB_BLANK_UNBLANK, info);
+
+ if (!fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8)) {
+ dev_err(&pdev->dev, "gxt4500: cannot find valid video mode\n");
+ goto err_free_cmap;
+ }
+ info->var = var;
+ if (gxt4500_set_par(info)) {
+ printk(KERN_ERR "gxt4500: cannot set video mode\n");
+ goto err_free_cmap;
+ }
+
+ if (register_framebuffer(info) < 0) {
+ dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n");
+ goto err_free_cmap;
+ }
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ return 0;
+
+ err_free_cmap:
+ fb_dealloc_cmap(&info->cmap);
+ err_unmap_all:
+ iounmap(info->screen_base);
+ err_unmap_regs:
+ iounmap(par->regs);
+ err_free_all:
+ framebuffer_release(info);
+ err_free_fb:
+ release_mem_region(fb_phys, pci_resource_len(pdev, 1));
+ err_free_regs:
+ release_mem_region(reg_phys, pci_resource_len(pdev, 0));
+ err_nodev:
+ return -ENODEV;
+}
+
+static void __devexit gxt4500_remove(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct gxt4500_par *par;
+
+ if (!info)
+ return;
+ par = info->par;
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ iounmap(par->regs);
+ iounmap(info->screen_base);
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ release_mem_region(pci_resource_start(pdev, 1),
+ pci_resource_len(pdev, 1));
+ framebuffer_release(info);
+}
+
+/* supported chipsets */
+static const struct pci_device_id gxt4500_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT4500P),
+ .driver_data = GXT4500P },
+ { PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_GXT6000P),
+ .driver_data = GXT6000P },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, gxt4500_pci_tbl);
+
+static struct pci_driver gxt4500_driver = {
+ .name = "gxt4500",
+ .id_table = gxt4500_pci_tbl,
+ .probe = gxt4500_probe,
+ .remove = __devexit_p(gxt4500_remove),
+};
+
+static int __devinit gxt4500_init(void)
+{
+#ifndef MODULE
+ if (fb_get_options("gxt4500", &mode_option))
+ return -ENODEV;
+#endif
+
+ return pci_register_driver(&gxt4500_driver);
+}
+module_init(gxt4500_init);
+
+static void __exit gxt4500_exit(void)
+{
+ pci_unregister_driver(&gxt4500_driver);
+}
+module_exit(gxt4500_exit);
+
+MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
+MODULE_DESCRIPTION("FBDev driver for IBM GXT4500P/6000P");
+MODULE_LICENSE("GPL");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index 91cf3b577d1..9ab9b839a0f 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -295,6 +295,8 @@ static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base
if (register_framebuffer(&fb_info) < 0) {
fb_dealloc_cmap(&fb_info.cmap);
+ iounmap(fb_info.screen_base);
+ fb_info.screen_base = NULL;
return 1;
}
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index b38d805db31..961f4d40446 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -137,15 +137,15 @@ void i810_create_i2c_busses(struct i810fb_par *par)
void i810_delete_i2c_busses(struct i810fb_par *par)
{
if (par->chan[0].par)
- i2c_bit_del_bus(&par->chan[0].adapter);
+ i2c_del_adapter(&par->chan[0].adapter);
par->chan[0].par = NULL;
if (par->chan[1].par)
- i2c_bit_del_bus(&par->chan[1].adapter);
+ i2c_del_adapter(&par->chan[1].adapter);
par->chan[1].par = NULL;
if (par->chan[2].par)
- i2c_bit_del_bus(&par->chan[2].adapter);
+ i2c_del_adapter(&par->chan[2].adapter);
par->chan[2].par = NULL;
}
@@ -162,9 +162,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
if (e != NULL) {
DPRINTK("i810-i2c: Getting EDID from BIOS\n");
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, e, EDID_LENGTH);
+ edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
}
}
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index e6df492c22a..655ae0fa99c 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -384,19 +384,21 @@ int __init igafb_init(void)
if (!con_is_present())
return -ENXIO;
- pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
+ pdev = pci_get_device(PCI_VENDOR_ID_INTERG,
PCI_DEVICE_ID_INTERG_1682, 0);
if (pdev == NULL) {
/*
* XXX We tried to use cyber2000fb.c for IGS 2000.
* But it does not initialize the chip in JavaStation-E, alas.
*/
- pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
+ pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
if(pdev == NULL) {
return -ENXIO;
}
iga2000 = 1;
}
+ /* We leak a reference here but as it cannot be unloaded this is
+ fine. If you write unload code remember to free it in unload */
size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16;
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index 5686e2164e3..33bc41f5054 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -188,11 +188,11 @@ void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
for (i = 0; i < MAX_OUTPUTS; i++) {
if (dinfo->output[i].i2c_bus.dinfo) {
- i2c_bit_del_bus(&dinfo->output[i].i2c_bus.adapter);
+ i2c_del_adapter(&dinfo->output[i].i2c_bus.adapter);
dinfo->output[i].i2c_bus.dinfo = NULL;
}
if (dinfo->output[i].ddc_bus.dinfo) {
- i2c_bit_del_bus(&dinfo->output[i].ddc_bus.adapter);
+ i2c_del_adapter(&dinfo->output[i].ddc_bus.adapter);
dinfo->output[i].ddc_bus.dinfo = NULL;
}
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 6f9de04193d..664fc5cf962 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1058,10 +1058,9 @@ intelfb_init_var(struct intelfb_info *dinfo)
u8 *edid_d = NULL;
if (edid_s) {
- edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);
if (edid_d) {
- memcpy(edid_d, edid_s, EDID_LENGTH);
fb_edid_to_monspecs(edid_d,
&dinfo->info->monspecs);
kfree(edid_d);
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index f3a24338d9a..a038aa5a9e1 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -530,20 +530,21 @@ struct all_info {
struct leo_par par;
};
-static void leo_unmap_regs(struct all_info *all)
+static void leo_unmap_regs(struct of_device *op, struct all_info *all)
{
if (all->par.lc_ss0_usr)
- of_iounmap(all->par.lc_ss0_usr, 0x1000);
+ of_iounmap(&op->resource[0], all->par.lc_ss0_usr, 0x1000);
if (all->par.ld_ss0)
- of_iounmap(all->par.ld_ss0, 0x1000);
+ of_iounmap(&op->resource[0], all->par.ld_ss0, 0x1000);
if (all->par.ld_ss1)
- of_iounmap(all->par.ld_ss1, 0x1000);
+ of_iounmap(&op->resource[0], all->par.ld_ss1, 0x1000);
if (all->par.lx_krn)
- of_iounmap(all->par.lx_krn, 0x1000);
+ of_iounmap(&op->resource[0], all->par.lx_krn, 0x1000);
if (all->par.cursor)
- of_iounmap(all->par.cursor, sizeof(struct leo_cursor));
+ of_iounmap(&op->resource[0],
+ all->par.cursor, sizeof(struct leo_cursor));
if (all->info.screen_base)
- of_iounmap(all->info.screen_base, 0x800000);
+ of_iounmap(&op->resource[0], all->info.screen_base, 0x800000);
}
static int __devinit leo_init_one(struct of_device *op)
@@ -592,7 +593,7 @@ static int __devinit leo_init_one(struct of_device *op)
!all->par.lx_krn ||
!all->par.cursor ||
!all->info.screen_base) {
- leo_unmap_regs(all);
+ leo_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -607,7 +608,7 @@ static int __devinit leo_init_one(struct of_device *op)
leo_blank(0, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- leo_unmap_regs(all);
+ leo_unmap_regs(op, all);
kfree(all);
return -ENOMEM;;
}
@@ -617,7 +618,7 @@ static int __devinit leo_init_one(struct of_device *op)
err = register_framebuffer(&all->info);
if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
- leo_unmap_regs(all);
+ leo_unmap_regs(op, all);
kfree(all);
return err;
}
@@ -638,18 +639,18 @@ static int __devinit leo_probe(struct of_device *dev, const struct of_device_id
return leo_init_one(op);
}
-static int __devexit leo_remove(struct of_device *dev)
+static int __devexit leo_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- leo_unmap_regs(all);
+ leo_unmap_regs(op, all);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 80a04380716..180d94c2b4d 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -608,6 +608,22 @@ void __init macfb_setup(char *options)
}
}
+static void __init iounmap_macfb(void)
+{
+ if (valkyrie_cmap_regs)
+ iounmap(valkyrie_cmap_regs);
+ if (dafb_cmap_regs)
+ iounmap(dafb_cmap_regs);
+ if (v8_brazil_cmap_regs)
+ iounmap(v8_brazil_cmap_regs);
+ if (rbv_cmap_regs)
+ iounmap(rbv_cmap_regs);
+ if (civic_cmap_regs)
+ iounmap(civic_cmap_regs);
+ if (csc_cmap_regs)
+ iounmap(csc_cmap_regs);
+}
+
static int __init macfb_init(void)
{
int video_cmap_len, video_is_nubus = 0;
@@ -962,6 +978,10 @@ static int __init macfb_init(void)
if (!err)
printk("fb%d: %s frame buffer device\n",
fb_info.node, fb_info.fix.id);
+ else {
+ iounmap(fb_info.screen_base);
+ iounmap_macfb();
+ }
return err;
}
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 795c1a99a68..fe28848e7b5 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -124,7 +124,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
if (b->initialized) {
- i2c_bit_del_bus(&b->adapter);
+ i2c_del_adapter(&b->adapter);
b->initialized = 0;
}
}
@@ -146,7 +146,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
unsigned long flags;
struct matroxfb_dh_maven_info* m2info;
- m2info = (struct matroxfb_dh_maven_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
+ m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
if (!m2info)
return NULL;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index e9b4115fcad..cb2aa402ddf 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -2028,7 +2028,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
}
#ifdef CONFIG_FB_MATROX_MULTIHEAD
- minfo = (struct matrox_fb_info*)kmalloc(sizeof(*minfo), GFP_KERNEL);
+ minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
if (!minfo)
return -1;
#else
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 27eb4bb4f89..2c9801090fa 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -694,7 +694,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
/* hardware is CRTC2 incapable... */
if (!ACCESS_FBINFO(devflags.crtc2))
return NULL;
- m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
+ m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
if (!m2info) {
printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
return NULL;
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index 84aab3ad024..472a3ca3d92 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -10,6 +10,8 @@ struct mbxfb_debugfs_data {
struct dentry *clock;
struct dentry *display;
struct dentry *gsctl;
+ struct dentry *sdram;
+ struct dentry *misc;
};
static int open_file_generic(struct inode *inode, struct file *file)
@@ -29,11 +31,11 @@ static ssize_t sysconf_read_file(struct file *file, char __user *userbuf,
{
char * s = big_buffer;
- s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG);
- s += sprintf(s, "PFBASE = %08lx\n", PFBASE);
- s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL);
- s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG);
- s += sprintf(s, "SYSRST = %08lx\n", SYSRST);
+ s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG));
+ s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE));
+ s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL));
+ s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG));
+ s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST));
return simple_read_from_buffer(userbuf, count, ppos,
big_buffer, s-big_buffer);
@@ -45,24 +47,24 @@ static ssize_t gsctl_read_file(struct file *file, char __user *userbuf,
{
char * s = big_buffer;
- s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL);
- s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL);
- s += sprintf(s, "GBBASE = %08lx\n", GBBASE);
- s += sprintf(s, "VBBASE = %08lx\n", VBBASE);
- s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL);
- s += sprintf(s, "VCMSK = %08lx\n", VCMSK);
- s += sprintf(s, "GSCADR = %08lx\n", GSCADR);
- s += sprintf(s, "VSCADR = %08lx\n", VSCADR);
- s += sprintf(s, "VUBASE = %08lx\n", VUBASE);
- s += sprintf(s, "VVBASE = %08lx\n", VVBASE);
- s += sprintf(s, "GSADR = %08lx\n", GSADR);
- s += sprintf(s, "VSADR = %08lx\n", VSADR);
- s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL);
- s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE);
- s += sprintf(s, "HCPOS = %08lx\n", HCPOS);
- s += sprintf(s, "HCBADR = %08lx\n", HCBADR);
- s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK);
- s += sprintf(s, "GPLUT = %08lx\n", GPLUT);
+ s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL));
+ s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL));
+ s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE));
+ s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE));
+ s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL));
+ s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK));
+ s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR));
+ s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR));
+ s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE));
+ s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE));
+ s += sprintf(s, "GSADR = %08x\n", readl(GSADR));
+ s += sprintf(s, "VSADR = %08x\n", readl(VSADR));
+ s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL));
+ s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE));
+ s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS));
+ s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR));
+ s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK));
+ s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT));
return simple_read_from_buffer(userbuf, count, ppos,
big_buffer, s-big_buffer);
@@ -73,36 +75,36 @@ static ssize_t display_read_file(struct file *file, char __user *userbuf,
{
char * s = big_buffer;
- s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL);
- s += sprintf(s, "DHT01 = %08lx\n", DHT01);
- s += sprintf(s, "DHT02 = %08lx\n", DHT02);
- s += sprintf(s, "DHT03 = %08lx\n", DHT03);
- s += sprintf(s, "DVT01 = %08lx\n", DVT01);
- s += sprintf(s, "DVT02 = %08lx\n", DVT02);
- s += sprintf(s, "DVT03 = %08lx\n", DVT03);
- s += sprintf(s, "DBCOL = %08lx\n", DBCOL);
- s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR);
- s += sprintf(s, "DINTRS = %08lx\n", DINTRS);
- s += sprintf(s, "DINTRE = %08lx\n", DINTRE);
- s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT);
- s += sprintf(s, "DSIG = %08lx\n", DSIG);
- s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL);
- s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL);
- s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL);
- s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL);
- s += sprintf(s, "DLSTS = %08lx\n", DLSTS);
- s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL);
- s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM);
- s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL);
- s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL);
- s += sprintf(s, "DHDET = %08lx\n", DHDET);
- s += sprintf(s, "DVDET = %08lx\n", DVDET);
- s += sprintf(s, "DODMSK = %08lx\n", DODMSK);
- s += sprintf(s, "CSC01 = %08lx\n", CSC01);
- s += sprintf(s, "CSC02 = %08lx\n", CSC02);
- s += sprintf(s, "CSC03 = %08lx\n", CSC03);
- s += sprintf(s, "CSC04 = %08lx\n", CSC04);
- s += sprintf(s, "CSC05 = %08lx\n", CSC05);
+ s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL));
+ s += sprintf(s, "DHT01 = %08x\n", readl(DHT01));
+ s += sprintf(s, "DHT02 = %08x\n", readl(DHT02));
+ s += sprintf(s, "DHT03 = %08x\n", readl(DHT03));
+ s += sprintf(s, "DVT01 = %08x\n", readl(DVT01));
+ s += sprintf(s, "DVT02 = %08x\n", readl(DVT02));
+ s += sprintf(s, "DVT03 = %08x\n", readl(DVT03));
+ s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL));
+ s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR));
+ s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS));
+ s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE));
+ s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT));
+ s += sprintf(s, "DSIG = %08x\n", readl(DSIG));
+ s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL));
+ s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL));
+ s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL));
+ s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL));
+ s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS));
+ s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL));
+ s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM));
+ s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL));
+ s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL));
+ s += sprintf(s, "DHDET = %08x\n", readl(DHDET));
+ s += sprintf(s, "DVDET = %08x\n", readl(DVDET));
+ s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK));
+ s += sprintf(s, "CSC01 = %08x\n", readl(CSC01));
+ s += sprintf(s, "CSC02 = %08x\n", readl(CSC02));
+ s += sprintf(s, "CSC03 = %08x\n", readl(CSC03));
+ s += sprintf(s, "CSC04 = %08x\n", readl(CSC04));
+ s += sprintf(s, "CSC05 = %08x\n", readl(CSC05));
return simple_read_from_buffer(userbuf, count, ppos,
big_buffer, s-big_buffer);
@@ -113,24 +115,61 @@ static ssize_t clock_read_file(struct file *file, char __user *userbuf,
{
char * s = big_buffer;
- s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC);
- s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC);
- s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP);
- s += sprintf(s, "COREPLL = %08lx\n", COREPLL);
- s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL);
- s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT);
- s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK);
- s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK);
- s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK);
- s += sprintf(s, "M24CLK = %08lx\n", M24CLK);
- s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK);
- s += sprintf(s, "SDCLK = %08lx\n", SDCLK);
- s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV);
+ s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC));
+ s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC));
+ s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP));
+ s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL));
+ s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL));
+ s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT));
+ s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK));
+ s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK));
+ s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK));
+ s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK));
+ s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK));
+ s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK));
+ s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV));
return simple_read_from_buffer(userbuf, count, ppos,
big_buffer, s-big_buffer);
}
+static ssize_t sdram_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char * s = big_buffer;
+
+ s += sprintf(s, "LMRST = %08x\n", readl(LMRST));
+ s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG));
+ s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR));
+ s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT));
+ s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR));
+ s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE));
+ s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM));
+ s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH));
+ s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN));
+ s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX));
+ s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG));
+ s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR));
+
+ return simple_read_from_buffer(userbuf, count, ppos,
+ big_buffer, s-big_buffer);
+}
+
+static ssize_t misc_read_file(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char * s = big_buffer;
+
+ s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG));
+ s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR));
+ s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT));
+ s += sprintf(s, "ID = %08x\n", readl(ID));
+
+ return simple_read_from_buffer(userbuf, count, ppos,
+ big_buffer, s-big_buffer);
+}
+
+
static struct file_operations sysconf_fops = {
.read = sysconf_read_file,
.write = write_file_dummy,
@@ -155,6 +194,17 @@ static struct file_operations gsctl_fops = {
.open = open_file_generic,
};
+static struct file_operations sdram_fops = {
+ .read = sdram_read_file,
+ .write = write_file_dummy,
+ .open = open_file_generic,
+};
+
+static struct file_operations misc_fops = {
+ .read = misc_read_file,
+ .write = write_file_dummy,
+ .open = open_file_generic,
+};
static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
{
@@ -173,6 +223,10 @@ static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
fbi, &display_fops);
dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir,
fbi, &gsctl_fops);
+ dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir,
+ fbi, &sdram_fops);
+ dbg->misc = debugfs_create_file("misc", 0444, dbg->dir,
+ fbi, &misc_fops);
}
static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi)
@@ -180,6 +234,8 @@ static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi)
struct mbxfb_info *mfbi = fbi->par;
struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data;
+ debugfs_remove(dbg->misc);
+ debugfs_remove(dbg->sdram);
debugfs_remove(dbg->gsctl);
debugfs_remove(dbg->display);
debugfs_remove(dbg->clock);
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index a32d1af79e0..980d5f62390 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -1,8 +1,14 @@
/*
* linux/drivers/video/mbx/mbxfb.c
*
+ * Copyright (C) 2006 8D Technologies inc
+ * Raphael Assenat <raph@8d.com>
+ * - Added video overlay support
+ * - Various improvements
+ *
* Copyright (C) 2006 Compulab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
+ * - Creation of driver
*
* Based on pxafb.c
*
@@ -19,6 +25,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/uaccess.h>
#include <asm/io.h>
@@ -29,6 +36,14 @@
static unsigned long virt_base_2700;
+#define write_reg(val, reg) do { writel((val), (reg)); } while(0)
+
+/* Without this delay, the graphics appears somehow scaled and
+ * there is a lot of jitter in scanlines. This delay is probably
+ * needed only after setting some specific register(s) somewhere,
+ * not all over the place... */
+#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0)
+
#define MIN_XRES 16
#define MIN_YRES 16
#define MAX_XRES 2048
@@ -257,19 +272,17 @@ static int mbxfb_set_par(struct fb_info *info)
gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
gsctrl |= Gsctrl_Width(info->var.xres) |
Gsctrl_Height(info->var.yres);
- writel(gsctrl, GSCTRL);
- udelay(1000);
+ write_reg_dly(gsctrl, GSCTRL);
gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
(8 * 16) - 1);
- writel(gsadr, GSADR);
- udelay(1000);
+ write_reg_dly(gsadr, GSADR);
/* setup timings */
var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
- writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
+ write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
hbps = var->hsync_len;
@@ -282,18 +295,20 @@ static int mbxfb_set_par(struct fb_info *info)
vfps = vas + var->yres;
vt = vfps + var->lower_margin;
- writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
- writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
- writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
- writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
+ write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
+ write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
+ write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
+ write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
- writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
- writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
- writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
- writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
- writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
+ write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
+ write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
+ write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
+ write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
+ write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
- writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+ write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+
+ write_reg_dly(DINTRE_VEVENT0_EN, DINTRE);
return 0;
}
@@ -305,23 +320,203 @@ static int mbxfb_blank(int blank, struct fb_info *info)
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_NORMAL:
- writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
- udelay(1000);
- writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
- udelay(1000);
- writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
- udelay(1000);
+ write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
+ write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
+ write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
break;
case FB_BLANK_UNBLANK:
- writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
- udelay(1000);
- writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
- udelay(1000);
+ write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+ write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
break;
}
return 0;
}
+static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set)
+{
+ u32 vsctrl, vbbase, vscadr, vsadr;
+ u32 sssize, spoctrl, svctrl, shctrl;
+ u32 vubase, vvbase;
+ u32 vovrclk;
+
+ if (set->scaled_width==0 || set->scaled_height==0)
+ return -EINVAL;
+
+ /* read registers which have reserved bits
+ * so we can write them back as-is. */
+ vovrclk = readl(VOVRCLK);
+ vsctrl = readl(VSCTRL);
+ vscadr = readl(VSCADR);
+ vubase = readl(VUBASE);
+ vvbase = readl(VVBASE);
+
+ spoctrl = readl(SPOCTRL);
+ sssize = readl(SSSIZE);
+
+
+ vbbase = Vbbase_Glalpha(set->alpha);
+
+ vsctrl &= ~( FMsk(VSCTRL_VSWIDTH) |
+ FMsk(VSCTRL_VSHEIGHT) |
+ FMsk(VSCTRL_VPIXFMT) |
+ VSCTRL_GAMMA_EN | VSCTRL_CSC_EN |
+ VSCTRL_COSITED );
+ vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) |
+ VSCTRL_CSC_EN;
+
+ vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC |
+ FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) |
+ FMsk(VSCADR_VBASE_ADR) );
+ vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR));
+ vvbase &= ~(FMsk(VVBASE_VBASE_ADR));
+
+ switch (set->fmt)
+ {
+ case MBXFB_FMT_YUV12:
+ vsctrl |= VSCTRL_VPIXFMT_YUV12;
+
+ set->Y_stride = ((set->width) + 0xf ) & ~0xf;
+
+ break;
+ case MBXFB_FMT_UY0VY1:
+ vsctrl |= VSCTRL_VPIXFMT_UY0VY1;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_VY0UY1:
+ vsctrl |= VSCTRL_VPIXFMT_VY0UY1;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_Y0UY1V:
+ vsctrl |= VSCTRL_VPIXFMT_Y0UY1V;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ case MBXFB_FMT_Y0VY1U:
+ vsctrl |= VSCTRL_VPIXFMT_Y0VY1U;
+ set->Y_stride = (set->width*2 + 0xf ) & ~0xf;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* VSCTRL has the bits which sets the Video Pixel Format.
+ * When passing from a packed to planar format,
+ * if we write VSCTRL first, VVBASE and VUBASE would
+ * be zero if we would not set them here. (And then,
+ * the chips hangs and only a reset seems to fix it).
+ *
+ * If course, the values calculated here have no meaning
+ * for packed formats.
+ */
+ set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7;
+ set->U_offset = set->height * set->Y_stride;
+ set->V_offset = set->U_offset +
+ set->height * set->UV_stride;
+ vubase |= Vubase_Ubase_Adr(
+ (0x60000 + set->mem_offset + set->U_offset)>>3);
+ vvbase |= Vvbase_Vbase_Adr(
+ (0x60000 + set->mem_offset + set->V_offset)>>3);
+
+
+ vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB |
+ Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4);
+
+ if (set->enable)
+ vscadr |= VSCADR_STR_EN;
+
+
+ vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) |
+ Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y);
+
+ sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT));
+ sssize = Sssize_Sc_Width(set->scaled_width-1) |
+ Sssize_Sc_Height(set->scaled_height-1);
+
+ spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP |
+ SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C |
+ FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH));
+ spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height)
+ | SPOCTRL_VORDER_2TAP;
+
+ /* Bypass horiz/vert scaler when same size */
+ if (set->scaled_width == set->width)
+ spoctrl |= SPOCTRL_H_SC_BP;
+ if (set->scaled_height == set->height)
+ spoctrl |= SPOCTRL_V_SC_BP;
+
+ svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10);
+
+ shctrl = Shctrl_Hinitial(4<<11)
+ | Shctrl_Hpitch((set->width<<11)/set->scaled_width);
+
+ /* Video plane registers */
+ write_reg(vsctrl, VSCTRL);
+ write_reg(vbbase, VBBASE);
+ write_reg(vscadr, VSCADR);
+ write_reg(vubase, VUBASE);
+ write_reg(vvbase, VVBASE);
+ write_reg(vsadr, VSADR);
+
+ /* Video scaler registers */
+ write_reg(sssize, SSSIZE);
+ write_reg(spoctrl, SPOCTRL);
+ write_reg(svctrl, SVCTRL);
+ write_reg(shctrl, SHCTRL);
+
+ /* RAPH: Using those coefficients, the scaled
+ * image is quite blurry. I dont know how
+ * to improve them ; The chip documentation
+ * was not helpful.. */
+ write_reg(0x21212121, VSCOEFF0);
+ write_reg(0x21212121, VSCOEFF1);
+ write_reg(0x21212121, VSCOEFF2);
+ write_reg(0x21212121, VSCOEFF3);
+ write_reg(0x21212121, VSCOEFF4);
+ write_reg(0x00000000, HSCOEFF0);
+ write_reg(0x00000000, HSCOEFF1);
+ write_reg(0x00000000, HSCOEFF2);
+ write_reg(0x03020201, HSCOEFF3);
+ write_reg(0x09070604, HSCOEFF4);
+ write_reg(0x0f0e0c0a, HSCOEFF5);
+ write_reg(0x15141211, HSCOEFF6);
+ write_reg(0x19181716, HSCOEFF7);
+ write_reg(0x00000019, HSCOEFF8);
+
+ /* Clock */
+ if (set->enable)
+ vovrclk |= 1;
+ else
+ vovrclk &= ~1;
+
+ write_reg(vovrclk, VOVRCLK);
+
+ return 0;
+}
+
+static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ struct mbxfb_overlaySetup setup;
+ int res;
+
+ if (cmd == MBXFB_IOCX_OVERLAY)
+ {
+ if (copy_from_user(&setup, (void __user*)arg,
+ sizeof(struct mbxfb_overlaySetup)))
+ return -EFAULT;
+
+ res = mbxfb_setupOverlay(&setup);
+ if (res)
+ return res;
+
+ if (copy_to_user((void __user*)arg, &setup,
+ sizeof(struct mbxfb_overlaySetup)))
+ return -EFAULT;
+
+ return 0;
+ }
+ return -EINVAL;
+}
+
static struct fb_ops mbxfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = mbxfb_check_var,
@@ -331,6 +526,7 @@ static struct fb_ops mbxfb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = mbxfb_blank,
+ .fb_ioctl = mbxfb_ioctl,
};
/*
@@ -339,36 +535,29 @@ static struct fb_ops mbxfb_ops = {
*/
static void __devinit setup_memc(struct fb_info *fbi)
{
- struct mbxfb_info *mfbi = fbi->par;
unsigned long tmp;
int i;
/* FIXME: use platfrom specific parameters */
/* setup SDRAM controller */
- writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
+ write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
LMCFG_LMA_TS),
LMCFG);
- udelay(1000);
- writel(LMPWR_MC_PWR_ACT, LMPWR);
- udelay(1000);
+ write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
/* setup SDRAM timings */
- writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
+ write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
Lmtim_Trc(9) | Lmtim_Tdpl(2)),
LMTIM);
- udelay(1000);
/* setup SDRAM refresh rate */
- writel(0xc2b, LMREFRESH);
- udelay(1000);
+ write_reg_dly(0xc2b, LMREFRESH);
/* setup SDRAM type parameters */
- writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
+ write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
LMTYPE_COLSZ_8),
LMTYPE);
- udelay(1000);
/* enable memory controller */
- writel(LMPWR_MC_PWR_ACT, LMPWR);
- udelay(1000);
+ write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR);
/* perform dummy reads */
for ( i = 0; i < 16; i++ ) {
@@ -379,34 +568,30 @@ static void __devinit setup_memc(struct fb_info *fbi)
static void enable_clocks(struct fb_info *fbi)
{
/* enable clocks */
- writel(SYSCLKSRC_PLL_2, SYSCLKSRC);
- udelay(1000);
- writel(PIXCLKSRC_PLL_1, PIXCLKSRC);
- udelay(1000);
- writel(0x00000000, CLKSLEEP);
- udelay(1000);
- writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) |
+ write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC);
+ write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC);
+ write_reg_dly(0x00000000, CLKSLEEP);
+
+ /* PLL output = (Frefclk * M) / (N * 2^P )
+ *
+ * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz!
+ * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz
+ * */
+ write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) |
CORE_PLL_EN),
COREPLL);
- udelay(1000);
- writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
+
+ write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
DISP_PLL_EN),
DISPPLL);
- writel(0x00000000, VOVRCLK);
- udelay(1000);
- writel(PIXCLK_EN, PIXCLK);
- udelay(1000);
- writel(MEMCLK_EN, MEMCLK);
- udelay(1000);
- writel(0x00000006, M24CLK);
- udelay(1000);
- writel(0x00000006, MBXCLK);
- udelay(1000);
- writel(SDCLK_EN, SDCLK);
- udelay(1000);
- writel(0x00000001, PIXCLKDIV);
- udelay(1000);
+ write_reg_dly(0x00000000, VOVRCLK);
+ write_reg_dly(PIXCLK_EN, PIXCLK);
+ write_reg_dly(MEMCLK_EN, MEMCLK);
+ write_reg_dly(0x00000006, M24CLK);
+ write_reg_dly(0x00000006, MBXCLK);
+ write_reg_dly(SDCLK_EN, SDCLK);
+ write_reg_dly(0x00000001, PIXCLKDIV);
}
static void __devinit setup_graphics(struct fb_info *fbi)
@@ -430,16 +615,11 @@ static void __devinit setup_graphics(struct fb_info *fbi)
break;
}
- writel(gsctrl, GSCTRL);
- udelay(1000);
- writel(0x00000000, GBBASE);
- udelay(1000);
- writel(0x00ffffff, GDRCTRL);
- udelay(1000);
- writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
- udelay(1000);
- writel(0x00000000, GPLUT);
- udelay(1000);
+ write_reg_dly(gsctrl, GSCTRL);
+ write_reg_dly(0x00000000, GBBASE);
+ write_reg_dly(0x00ffffff, GDRCTRL);
+ write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
+ write_reg_dly(0x00000000, GPLUT);
}
static void __devinit setup_display(struct fb_info *fbi)
@@ -451,17 +631,14 @@ static void __devinit setup_display(struct fb_info *fbi)
dsctrl |= DSCTRL_HS_POL;
if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
dsctrl |= DSCTRL_VS_POL;
- writel(dsctrl, DSCTRL);
- udelay(1000);
- writel(0xd0303010, DMCTRL);
- udelay(1000);
- writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+ write_reg_dly(dsctrl, DSCTRL);
+ write_reg_dly(0xd0303010, DMCTRL);
+ write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
}
static void __devinit enable_controller(struct fb_info *fbi)
{
- writel(SYSRST_RST, SYSRST);
- udelay(1000);
+ write_reg_dly(SYSRST_RST, SYSRST);
enable_clocks(fbi);
@@ -478,12 +655,12 @@ static void __devinit enable_controller(struct fb_info *fbi)
static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
{
/* make frame buffer memory enter self-refresh mode */
- writel(LMPWR_MC_PWR_SRM, LMPWR);
+ write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
; /* empty statement */
/* reset the device, since it's initial state is 'mostly sleeping' */
- writel(SYSRST_RST, SYSRST);
+ write_reg_dly(SYSRST_RST, SYSRST);
return 0;
}
@@ -495,7 +672,7 @@ static int mbxfb_resume(struct platform_device *dev)
/* setup_graphics(fbi); */
/* setup_display(fbi); */
- writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+ write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
return 0;
}
#else
@@ -520,6 +697,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
dev_dbg(dev, "mbxfb_probe\n");
+ pdata = dev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&dev->dev, "platform data is required\n");
+ return -EINVAL;
+ }
+
fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
if (fbi == NULL) {
dev_err(&dev->dev, "framebuffer_alloc failed\n");
@@ -528,7 +711,8 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
mfbi = fbi->par;
fbi->pseudo_palette = mfbi->pseudo_palette;
- pdata = dev->dev.platform_data;
+
+
if (pdata->probe)
mfbi->platform_probe = pdata->probe;
if (pdata->remove)
@@ -578,16 +762,16 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
goto err4;
}
- /* FIXME: get from platform */
fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
- fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */
+ fbi->screen_size = pdata->memsize;
fbi->fbops = &mbxfb_ops;
fbi->var = mbxfb_default;
fbi->fix = mbxfb_fix;
fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
- fbi->fix.smem_len = 8 * 1024 * 1024;
- fbi->fix.line_length = 640 * 2;
+ fbi->fix.smem_len = pdata->memsize;
+ fbi->fix.line_length = mbxfb_default.xres_virtual *
+ mbxfb_default.bits_per_pixel / 8;
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret < 0) {
@@ -636,8 +820,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
{
struct fb_info *fbi = platform_get_drvdata(dev);
- writel(SYSRST_RST, SYSRST);
- udelay(1000);
+ write_reg_dly(SYSRST_RST, SYSRST);
mbxfb_debugfs_remove(fbi);
diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h
index c226a8e4531..9a24fb0c7d4 100644
--- a/drivers/video/mbx/reg_bits.h
+++ b/drivers/video/mbx/reg_bits.h
@@ -242,6 +242,67 @@
#define GPLUT_LUTDATA Fld(24,0)
#define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA))
+/* VSCTRL - Video Surface Control Register */
+#define VSCTRL_VPIXFMT Fld(4,27)
+#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT))
+#define VSCTRL_GAMMA_EN (1 << 26)
+#define VSCTRL_CSC_EN (1 << 25)
+#define VSCTRL_COSITED (1 << 22)
+#define VSCTRL_VSWIDTH Fld(11,11)
+#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \
+ (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH))
+#define VSCTRL_VSHEIGHT Fld(11,0)
+#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \
+ (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT))
+
+/* VBBASE - Video Blending Base Register */
+#define VBBASE_GLALPHA Fld(8,24)
+#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA))
+
+#define VBBASE_COLKEY Fld(24,0)
+#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY))
+
+/* VCMSK - Video Color Key Mask Register */
+#define VCMSK_COLKEY_M Fld(24,0)
+#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M))
+
+/* VSCADR - Video Stream Control Rddress Register */
+#define VSCADR_STR_EN (1 << 31)
+#define VSCADR_COLKEY_EN (1 << 30)
+#define VSCADR_COLKEYSRC (1 << 29)
+#define VSCADR_BLEND_M Fld(2,27)
+#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M))
+#define VSCADR_BLEND_POS Fld(2,24)
+#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS))
+#define VSCADR_VBASE_ADR Fld(23,0)
+#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR))
+
+/* VUBASE - Video U Base Register */
+#define VUBASE_UVHALFSTR (1 << 31)
+#define VUBASE_UBASE_ADR Fld(24,0)
+#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR))
+
+/* VVBASE - Video V Base Register */
+#define VVBASE_VBASE_ADR Fld(24,0)
+#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR))
+
+/* VSADR - Video Stride Address Register */
+#define VSADR_SRCSTRIDE Fld(10,22)
+#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE))
+#define VSADR_XSTART Fld(11,11)
+#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART))
+#define VSADR_YSTART Fld(11,0)
+#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART))
+
/* HCCTRL - Hardware Cursor Register fields */
#define HCCTRL_CUR_EN (1 << 31)
#define HCCTRL_COLKEY_EN (1 << 29)
@@ -394,6 +455,30 @@
#define DMCTRL_BURSTLEN Fld(6,0)
#define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN))
+/* DINTRS - Display Interrupt Status Register */
+#define DINTRS_CUR_OR_S (1 << 18)
+#define DINTRS_STR2_OR_S (1 << 17)
+#define DINTRS_STR1_OR_S (1 << 16)
+#define DINTRS_CUR_UR_S (1 << 6)
+#define DINTRS_STR2_UR_S (1 << 5)
+#define DINTRS_STR1_UR_S (1 << 4)
+#define DINTRS_VEVENT1_S (1 << 3)
+#define DINTRS_VEVENT0_S (1 << 2)
+#define DINTRS_HBLNK1_S (1 << 1)
+#define DINTRS_HBLNK0_S (1 << 0)
+
+/* DINTRE - Display Interrupt Enable Register */
+#define DINTRE_CUR_OR_EN (1 << 18)
+#define DINTRE_STR2_OR_EN (1 << 17)
+#define DINTRE_STR1_OR_EN (1 << 16)
+#define DINTRE_CUR_UR_EN (1 << 6)
+#define DINTRE_STR2_UR_EN (1 << 5)
+#define DINTRE_STR1_UR_EN (1 << 4)
+#define DINTRE_VEVENT1_EN (1 << 3)
+#define DINTRE_VEVENT0_EN (1 << 2)
+#define DINTRE_HBLNK1_EN (1 << 1)
+#define DINTRE_HBLNK0_EN (1 << 0)
+
/* DLSTS - display load status register */
#define DLSTS_RLD_ADONE (1 << 23)
@@ -403,16 +488,41 @@
#define DLLCTRL_RLD_ADRLN Fld(8,24)
#define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN))
+/* CLIPCTRL - Clipping Control Register */
+#define CLIPCTRL_HSKIP Fld(11,16)
+#define Clipctrl_Hskip ((x) << FShft(CLIPCTRL_HSKIP))
+#define CLIPCTRL_VSKIP Fld(11,0)
+#define Clipctrl_Vskip ((x) << FShft(CLIPCTRL_VSKIP))
+
/* SPOCTRL - Scale Pitch/Order Control Register */
#define SPOCTRL_H_SC_BP (1 << 31)
#define SPOCTRL_V_SC_BP (1 << 30)
#define SPOCTRL_HV_SC_OR (1 << 29)
#define SPOCTRL_VS_UR_C (1 << 27)
-#define SPOCTRL_VORDER Fld(2,16)
+#define SPOCTRL_VORDER Fld(2,16)
#define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER))
#define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER))
#define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER))
-#define SPOCTRL_VPITCH Fld(16,0)
+#define SPOCTRL_VPITCH Fld(16,0)
#define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH))
+/* SVCTRL - Scale Vertical Control Register */
+#define SVCTRL_INITIAL1 Fld(16,16)
+#define Svctrl_Initial1(x) ((x) << FShft(SVCTRL_INITIAL1))
+#define SVCTRL_INITIAL2 Fld(16,0)
+#define Svctrl_Initial2(x) ((x) << FShft(SVCTRL_INITIAL2))
+
+/* SHCTRL - Scale Horizontal Control Register */
+#define SHCTRL_HINITIAL Fld(16,16)
+#define Shctrl_Hinitial(x) ((x) << FShft(SHCTRL_HINITIAL))
+#define SHCTRL_HDECIM (1 << 15)
+#define SHCTRL_HPITCH Fld(15,0)
+#define Shctrl_Hpitch(x) ((x) << FShft(SHCTRL_HPITCH))
+
+/* SSSIZE - Scale Surface Size Register */
+#define SSSIZE_SC_WIDTH Fld(11,16)
+#define Sssize_Sc_Width(x) ((x) << FShft(SSSIZE_SC_WIDTH))
+#define SSSIZE_SC_HEIGHT Fld(11,0)
+#define Sssize_Sc_Height(x) ((x) << FShft(SSSIZE_SC_HEIGHT))
+
#endif /* __REG_BITS_2700G_ */
diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h
index ad20be07666..a7c63d865aa 100644
--- a/drivers/video/mbx/regs.h
+++ b/drivers/video/mbx/regs.h
@@ -127,7 +127,7 @@
#define HSCOEFF0 __REG_2700G(0x000021b4)
#define HSCOEFF1 __REG_2700G(0x000021b8)
#define HSCOEFF2 __REG_2700G(0x000021bc)
-#define HSCOEFF3 __REG_2700G(0x000021b0)
+#define HSCOEFF3 __REG_2700G(0x000021c0)
#define HSCOEFF4 __REG_2700G(0x000021c4)
#define HSCOEFF5 __REG_2700G(0x000021c8)
#define HSCOEFF6 __REG_2700G(0x000021cc)
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index d1267904c28..5df41f6f2b8 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -34,8 +34,6 @@ const char *global_mode_option;
* Standard video mode definitions (taken from XFree86)
*/
-#define DEFAULT_MODEDB_INDEX 0
-
static const struct fb_videomode modedb[] = {
{
/* 640x400 @ 70 Hz, 31.5 kHz hsync */
@@ -505,8 +503,10 @@ int fb_find_mode(struct fb_var_screeninfo *var,
db = modedb;
dbsize = ARRAY_SIZE(modedb);
}
+
if (!default_mode)
- default_mode = &modedb[DEFAULT_MODEDB_INDEX];
+ default_mode = &db[0];
+
if (!default_bpp)
default_bpp = 8;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 59a6f5fa5ae..deaf820cb38 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1932,7 +1932,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
printk(KERN_DEBUG "--- Neo extended register dump ---\n");
for (int w = 0; w < 0x85; w++)
printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
- (void *) vga_rcrt(NULL, w);
+ (void *) vga_rcrt(NULL, w));
for (int w = 0; w < 0xC7; w++)
printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
(void *) vga_rgfx(NULL, w));
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
index 4aefb8f4163..9efb8a3854e 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/nvidia/nv_accel.c
@@ -261,41 +261,6 @@ void NVResetGraphics(struct fb_info *info)
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;
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index 5b75ae4e945..df934bd2189 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -141,7 +141,7 @@ void nvidia_bl_init(struct nvidia_par *par)
snprintf(name, sizeof(name), "nvidiabl%d", info->node);
- bd = backlight_device_register(name, par, &nvidia_bl_data);
+ bd = backlight_device_register(name, info->dev, par, &nvidia_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
printk(KERN_WARNING "nvidia: Backlight registration failed\n");
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 19eef3a0902..8454adf2d17 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -147,15 +147,15 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
void nvidia_delete_i2c_busses(struct nvidia_par *par)
{
if (par->chan[0].par)
- i2c_bit_del_bus(&par->chan[0].adapter);
+ i2c_del_adapter(&par->chan[0].adapter);
par->chan[0].par = NULL;
if (par->chan[1].par)
- i2c_bit_del_bus(&par->chan[1].adapter);
+ i2c_del_adapter(&par->chan[1].adapter);
par->chan[1].par = NULL;
if (par->chan[2].par)
- i2c_bit_del_bus(&par->chan[2].adapter);
+ i2c_del_adapter(&par->chan[2].adapter);
par->chan[2].par = NULL;
}
@@ -210,11 +210,8 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
/* try to get from firmware */
const u8 *e = fb_firmware_edid(info->device);
- if (e != NULL) {
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, e, EDID_LENGTH);
- }
+ if (e != NULL)
+ edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
}
*out_edid = edid;
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
index 4243d7fae97..e009d242ea1 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/nvidia/nv_local.h
@@ -96,13 +96,16 @@
#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
#ifdef __LITTLE_ENDIAN
+
+#include <linux/bitrev.h>
+
#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]; \
+ a[0] = bitrev8(a[0]); \
+ a[1] = bitrev8(a[1]); \
+ a[2] = bitrev8(a[2]); \
+ a[3] = bitrev8(a[3]); \
} while(0)
#else
#define reverse_order(l) do { } while(0)
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index d9af88c2b58..181875fe35c 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -72,10 +72,9 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
}
}
if (pedid) {
- *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ *out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);
if (*out_edid == NULL)
return -1;
- memcpy(*out_edid, pedid, EDID_LENGTH);
printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
return 0;
}
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 86127101765..43058d0cf5b 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -62,7 +62,6 @@ extern void nvidiafb_fillrect(struct fb_info *info,
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];
/* in nv_backlight.h */
#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 9a40bbecf76..9576a55eaf1 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -402,6 +402,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
fb_alloc_cmap(&info->cmap, 256, 0);
if (register_framebuffer(info) < 0) {
+ iounmap(par->cmap_adr);
+ par->cmap_adr = NULL;
+ iounmap(info->screen_base);
kfree(info);
release_mem_region(res_start, res_size);
return;
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 56ac51d6a7f..637b78bb4bf 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -297,7 +297,8 @@ static int __devinit p9100_init_one(struct of_device *op)
all->info.screen_base = of_ioremap(&op->resource[2], 0,
all->par.fbsize, "p9100 ram");
if (!all->info.screen_base) {
- of_iounmap(all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct p9100_regs));
kfree(all);
return -ENOMEM;
}
@@ -306,8 +307,10 @@ static int __devinit p9100_init_one(struct of_device *op)
p9100_blank(0, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- of_iounmap(all->par.regs, sizeof(struct p9100_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(&op->resource[2],
+ all->info.screen_base, all->par.fbsize);
kfree(all);
return -ENOMEM;
}
@@ -317,8 +320,10 @@ static int __devinit p9100_init_one(struct of_device *op)
err = register_framebuffer(&all->info);
if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
- of_iounmap(all->par.regs, sizeof(struct p9100_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(&op->resource[2],
+ all->info.screen_base, all->par.fbsize);
kfree(all);
return err;
}
@@ -340,19 +345,19 @@ static int __devinit p9100_probe(struct of_device *dev, const struct of_device_i
return p9100_init_one(op);
}
-static int __devexit p9100_remove(struct of_device *dev)
+static int __devexit p9100_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- of_iounmap(all->par.regs, sizeof(struct p9100_regs));
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0], all->par.regs, sizeof(struct p9100_regs));
+ of_iounmap(&op->resource[2], all->info.screen_base, all->par.fbsize);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index cb26c6df058..23387165582 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -627,6 +627,9 @@ static int __devinit platinumfb_probe(struct of_device* odev,
rc = platinum_init_fb(info);
if (rc != 0) {
+ iounmap(pinfo->frame_buffer);
+ iounmap(pinfo->platinum_regs);
+ iounmap(pinfo->cmap_regs);
dev_set_drvdata(&odev->dev, NULL);
framebuffer_release(info);
}
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 73e2d7d1660..a06a064ad75 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -186,7 +186,7 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info)
static void __init pmagbbfb_osc_setup(struct fb_info *info)
{
static unsigned int pmagbbfb_freqs[] __initdata = {
- 130808, 119843, 104000, 92980, 74367, 72800,
+ 130808, 119843, 104000, 92980, 74370, 72800,
69197, 66000, 65000, 50350, 36000, 32000, 25175
};
struct pmagbbfb_par *par = info->par;
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index c7bc80921f1..a93618bc9d2 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -905,6 +905,15 @@ static int __init pvr2fb_dc_init(void)
static void pvr2fb_dc_exit(void)
{
+ if (fb_info->screen_base) {
+ iounmap(fb_info->screen_base);
+ fb_info->screen_base = NULL;
+ }
+ if (currentpar->mmio_base) {
+ iounmap((void *)currentpar->mmio_base);
+ currentpar->mmio_base = 0;
+ }
+
free_irq(HW_EVENT_VSYNC, 0);
#ifdef CONFIG_SH_DMA
free_dma(pvr2dma);
@@ -946,6 +955,15 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev,
static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev)
{
+ if (fb_info->screen_base) {
+ iounmap(fb_info->screen_base);
+ fb_info->screen_base = NULL;
+ }
+ if (currentpar->mmio_base) {
+ iounmap((void *)currentpar->mmio_base);
+ currentpar->mmio_base = 0;
+ }
+
pci_release_regions(pdev);
}
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 38eb0b69c2d..b4947c81070 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1216,7 +1216,7 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
done:
if (res_specified) {
dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
- inf->xres = xres; inf->yres = yres;
+ inf->modes[0].xres = xres; inf->modes[0].yres = yres;
}
if (bpp_specified)
switch (bpp) {
@@ -1225,48 +1225,48 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
case 4:
case 8:
case 16:
- inf->bpp = bpp;
+ inf->modes[0].bpp = bpp;
dev_info(dev, "overriding bit depth: %d\n", bpp);
break;
default:
dev_err(dev, "Depth %d is not valid\n", bpp);
}
} else if (!strncmp(this_opt, "pixclock:", 9)) {
- inf->pixclock = simple_strtoul(this_opt+9, NULL, 0);
- dev_info(dev, "override pixclock: %ld\n", inf->pixclock);
+ inf->modes[0].pixclock = simple_strtoul(this_opt+9, NULL, 0);
+ dev_info(dev, "override pixclock: %ld\n", inf->modes[0].pixclock);
} else if (!strncmp(this_opt, "left:", 5)) {
- inf->left_margin = simple_strtoul(this_opt+5, NULL, 0);
- dev_info(dev, "override left: %u\n", inf->left_margin);
+ inf->modes[0].left_margin = simple_strtoul(this_opt+5, NULL, 0);
+ dev_info(dev, "override left: %u\n", inf->modes[0].left_margin);
} else if (!strncmp(this_opt, "right:", 6)) {
- inf->right_margin = simple_strtoul(this_opt+6, NULL, 0);
- dev_info(dev, "override right: %u\n", inf->right_margin);
+ inf->modes[0].right_margin = simple_strtoul(this_opt+6, NULL, 0);
+ dev_info(dev, "override right: %u\n", inf->modes[0].right_margin);
} else if (!strncmp(this_opt, "upper:", 6)) {
- inf->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
- dev_info(dev, "override upper: %u\n", inf->upper_margin);
+ inf->modes[0].upper_margin = simple_strtoul(this_opt+6, NULL, 0);
+ dev_info(dev, "override upper: %u\n", inf->modes[0].upper_margin);
} else if (!strncmp(this_opt, "lower:", 6)) {
- inf->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
- dev_info(dev, "override lower: %u\n", inf->lower_margin);
+ inf->modes[0].lower_margin = simple_strtoul(this_opt+6, NULL, 0);
+ dev_info(dev, "override lower: %u\n", inf->modes[0].lower_margin);
} else if (!strncmp(this_opt, "hsynclen:", 9)) {
- inf->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
- dev_info(dev, "override hsynclen: %u\n", inf->hsync_len);
+ inf->modes[0].hsync_len = simple_strtoul(this_opt+9, NULL, 0);
+ dev_info(dev, "override hsynclen: %u\n", inf->modes[0].hsync_len);
} else if (!strncmp(this_opt, "vsynclen:", 9)) {
- inf->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
- dev_info(dev, "override vsynclen: %u\n", inf->vsync_len);
+ inf->modes[0].vsync_len = simple_strtoul(this_opt+9, NULL, 0);
+ dev_info(dev, "override vsynclen: %u\n", inf->modes[0].vsync_len);
} else if (!strncmp(this_opt, "hsync:", 6)) {
if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
dev_info(dev, "override hsync: Active Low\n");
- inf->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+ inf->modes[0].sync &= ~FB_SYNC_HOR_HIGH_ACT;
} else {
dev_info(dev, "override hsync: Active High\n");
- inf->sync |= FB_SYNC_HOR_HIGH_ACT;
+ inf->modes[0].sync |= FB_SYNC_HOR_HIGH_ACT;
}
} else if (!strncmp(this_opt, "vsync:", 6)) {
if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
dev_info(dev, "override vsync: Active Low\n");
- inf->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ inf->modes[0].sync &= ~FB_SYNC_VERT_HIGH_ACT;
} else {
dev_info(dev, "override vsync: Active High\n");
- inf->sync |= FB_SYNC_VERT_HIGH_ACT;
+ inf->modes[0].sync |= FB_SYNC_VERT_HIGH_ACT;
}
} else if (!strncmp(this_opt, "dpc:", 4)) {
if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
index cf41ff17764..bc7ffc84e18 100644
--- a/drivers/video/retz3fb.c
+++ b/drivers/video/retz3fb.c
@@ -1423,8 +1423,10 @@ int __init retz3fb_init(void)
do_install_cmap(0, fb_info);
- if (register_framebuffer(fb_info) < 0)
+ if (register_framebuffer(fb_info) < 0) {
+ iounmap(zinfo->base);
return -EINVAL;
+ }
printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of "
"video memory\n", fb_info->node,
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index a433cc78ef9..1a13966b7d5 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -40,6 +40,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/backlight.h>
+#include <linux/bitrev.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -383,7 +384,7 @@ static void riva_bl_init(struct riva_par *par)
snprintf(name, sizeof(name), "rivabl%d", info->node);
- bd = backlight_device_register(name, par, &riva_bl_data);
+ bd = backlight_device_register(name, info->dev, par, &riva_bl_data);
if (IS_ERR(bd)) {
info->bl_dev = NULL;
printk(KERN_WARNING "riva: Backlight registration failed\n");
@@ -521,48 +522,13 @@ static inline unsigned char MISCin(struct riva_par *par)
return (VGA_RD08(par->riva.PVIO, 0x3cc));
}
-static 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,
-};
-
static inline void reverse_order(u32 *l)
{
u8 *a = (u8 *)l;
- *a = byte_rev[*a], a++;
- *a = byte_rev[*a], a++;
- *a = byte_rev[*a], a++;
- *a = byte_rev[*a];
+ a[0] = bitrev8(a[0]);
+ a[1] = bitrev8(a[1]);
+ a[2] = bitrev8(a[2]);
+ a[3] = bitrev8(a[3]);
}
/* ------------------------------------------------------------------------- *
@@ -774,11 +740,12 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
* CALLED FROM:
* rivafb_set_par()
*/
-static void riva_load_video_mode(struct fb_info *info)
+static int riva_load_video_mode(struct fb_info *info)
{
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
+ int rc;
struct riva_par *par = info->par;
struct riva_regs newmode;
@@ -884,8 +851,10 @@ static void riva_load_video_mode(struct fb_info *info)
else
newmode.misc_output |= 0x80;
- par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
- hDisplaySize, height, dotClock);
+ rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width,
+ hDisplaySize, height, dotClock);
+ if (rc)
+ goto out;
newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) &
0xfff000ff;
@@ -917,8 +886,12 @@ static void riva_load_video_mode(struct fb_info *info)
par->current_state = newmode;
riva_load_state(par, &par->current_state);
par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
+
+out:
rivafb_blank(FB_BLANK_UNBLANK, info);
NVTRACE_LEAVE();
+
+ return rc;
}
static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
@@ -1286,12 +1259,15 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int rivafb_set_par(struct fb_info *info)
{
struct riva_par *par = info->par;
+ int rc = 0;
NVTRACE_ENTER();
/* vgaHWunlock() + riva unlock (0x7F) */
CRTCout(par, 0x11, 0xFF);
par->riva.LockUnlock(&par->riva, 0);
- riva_load_video_mode(info);
+ rc = riva_load_video_mode(info);
+ if (rc)
+ goto out;
if(!(info->flags & FBINFO_HWACCEL_DISABLED))
riva_setup_accel(info);
@@ -1304,8 +1280,10 @@ static int rivafb_set_par(struct fb_info *info)
info->pixmap.scan_align = 1;
else
info->pixmap.scan_align = 4;
+
+out:
NVTRACE_LEAVE();
- return 0;
+ return rc;
}
/**
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
index b6f8690b96c..e0b8c521cc9 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/riva/riva_hw.c
@@ -1227,7 +1227,7 @@ static int CalcVClock
* Calculate extended mode parameters (SVGA) and save in a
* mode state structure.
*/
-static void CalcStateExt
+int CalcStateExt
(
RIVA_HW_INST *chip,
RIVA_HW_STATE *state,
@@ -1249,7 +1249,8 @@ static void CalcStateExt
* Extended RIVA registers.
*/
pixelDepth = (bpp + 1)/8;
- CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
+ if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip))
+ return -EINVAL;
switch (chip->Architecture)
{
@@ -1327,6 +1328,8 @@ static void CalcStateExt
state->pitch1 =
state->pitch2 =
state->pitch3 = pixelDepth * width;
+
+ return 0;
}
/*
* Load fixed function state and pre-calculated/stored state.
@@ -2026,7 +2029,6 @@ static void nv3GetConfig
*/
chip->Busy = nv3Busy;
chip->ShowHideCursor = ShowHideCursor;
- chip->CalcStateExt = CalcStateExt;
chip->LoadStateExt = LoadStateExt;
chip->UnloadStateExt = UnloadStateExt;
chip->SetStartAddress = SetStartAddress3;
@@ -2084,7 +2086,6 @@ static void nv4GetConfig
*/
chip->Busy = nv4Busy;
chip->ShowHideCursor = ShowHideCursor;
- chip->CalcStateExt = CalcStateExt;
chip->LoadStateExt = LoadStateExt;
chip->UnloadStateExt = UnloadStateExt;
chip->SetStartAddress = SetStartAddress;
@@ -2186,7 +2187,6 @@ static void nv10GetConfig
*/
chip->Busy = nv10Busy;
chip->ShowHideCursor = ShowHideCursor;
- chip->CalcStateExt = CalcStateExt;
chip->LoadStateExt = LoadStateExt;
chip->UnloadStateExt = UnloadStateExt;
chip->SetStartAddress = SetStartAddress;
diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
index a1e71a626df..c2769f73e0b 100644
--- a/drivers/video/riva/riva_hw.h
+++ b/drivers/video/riva/riva_hw.h
@@ -463,7 +463,6 @@ typedef struct _riva_hw_inst
* Common chip functions.
*/
int (*Busy)(struct _riva_hw_inst *);
- void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int);
void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
void (*SetStartAddress)(struct _riva_hw_inst *,U032);
@@ -528,6 +527,22 @@ typedef struct _riva_hw_state
U032 pitch2;
U032 pitch3;
} RIVA_HW_STATE;
+
+/*
+ * function prototypes
+ */
+
+extern int CalcStateExt
+(
+ RIVA_HW_INST *chip,
+ RIVA_HW_STATE *state,
+ int bpp,
+ int width,
+ int hDisplaySize,
+ int height,
+ int dotClock
+);
+
/*
* External routines.
*/
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index c15b259af64..01b85e3b0ae 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -144,15 +144,15 @@ void riva_create_i2c_busses(struct riva_par *par)
void riva_delete_i2c_busses(struct riva_par *par)
{
if (par->chan[0].par)
- i2c_bit_del_bus(&par->chan[0].adapter);
+ i2c_del_adapter(&par->chan[0].adapter);
par->chan[0].par = NULL;
if (par->chan[1].par)
- i2c_bit_del_bus(&par->chan[1].adapter);
+ i2c_del_adapter(&par->chan[1].adapter);
par->chan[1].par = NULL;
if (par->chan[2].par)
- i2c_bit_del_bus(&par->chan[2].adapter);
+ i2c_del_adapter(&par->chan[2].adapter);
par->chan[2].par = NULL;
}
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 59407343cc7..ccef56d0c15 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -131,7 +131,7 @@ static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
saddr2>>= 1;
- saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres);
+ saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff);
dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
@@ -199,28 +199,86 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
var->bits_per_pixel = fbi->mach_info->bpp.min;
/* set r/g/b positions */
+ switch (var->bits_per_pixel) {
+ case 1:
+ case 2:
+ case 4:
+ var->red.offset = 0;
+ var->red.length = var->bits_per_pixel;
+ var->green = var->red;
+ var->blue = var->red;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 8:
+ if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) {
+ /* 8 bpp 332 */
+ var->red.length = 3;
+ var->red.offset = 5;
+ var->green.length = 3;
+ var->green.offset = 2;
+ var->blue.length = 2;
+ var->blue.offset = 0;
+ var->transp.length = 0;
+ } else {
+ var->red.offset = 0;
+ var->red.length = var->bits_per_pixel;
+ var->green = var->red;
+ var->blue = var->red;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ }
+ break;
+ case 12:
+ /* 12 bpp 444 */
+ var->red.length = 4;
+ var->red.offset = 8;
+ var->green.length = 4;
+ var->green.offset = 4;
+ var->blue.length = 4;
+ var->blue.offset = 0;
+ var->transp.length = 0;
+ break;
+
+ default:
+ case 16:
+ if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) {
+ /* 16 bpp, 565 format */
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ var->transp.length = 0;
+ } else {
+ /* 16 bpp, 5551 format */
+ var->red.offset = 11;
+ var->green.offset = 6;
+ var->blue.offset = 1;
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ var->transp.length = 0;
+ }
+ break;
+ case 24:
+ /* 24 bpp 888 */
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->transp.length = 0;
+ break;
- if (var->bits_per_pixel == 16) {
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
- var->transp.length = 0;
- } else {
- var->red.length = var->bits_per_pixel;
- var->red.offset = 0;
- var->green.length = var->bits_per_pixel;
- var->green.offset = 0;
- var->blue.length = var->bits_per_pixel;
- var->blue.offset = 0;
- var->transp.length = 0;
- }
+ }
return 0;
}
+
/* s3c2410fb_activate_var
*
* activate (set) the controller from the given framebuffer
@@ -230,29 +288,61 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
struct fb_var_screeninfo *var)
{
+ int hs;
+
fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
+ fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT;
dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
- switch (var->bits_per_pixel) {
- case 1:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
- break;
- case 2:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
- break;
- case 4:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
- break;
- case 8:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
- break;
- case 16:
- fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
- break;
- }
+ fbi->regs.lcdcon1 |= fbi->mach_info->type;
+
+ if (fbi->mach_info->type == S3C2410_LCDCON1_TFT)
+ switch (var->bits_per_pixel) {
+ case 1:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+ break;
+ case 2:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+ break;
+ case 4:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+ break;
+ case 8:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+ break;
+ case 16:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+ break;
+
+ default:
+ /* invalid pixel depth */
+ dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
+ }
+ else
+ switch (var->bits_per_pixel) {
+ case 1:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
+ break;
+ case 2:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
+ break;
+ case 4:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
+ break;
+ case 8:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
+ break;
+ case 12:
+ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
+ break;
+
+ default:
+ /* invalid pixel depth */
+ dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
+ }
/* check to see if we need to update sync/borders */
@@ -283,15 +373,44 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+ switch(fbi->mach_info->type) {
+ case S3C2410_LCDCON1_DSCAN4:
+ case S3C2410_LCDCON1_STN8:
+ hs = var->xres / 8;
+ break;
+ case S3C2410_LCDCON1_STN4:
+ hs = var->xres / 4;
+ break;
+ default:
+ case S3C2410_LCDCON1_TFT:
+ hs = var->xres;
+ break;
+
+ }
+
+ /* Special cases : STN color displays */
+ if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \
+ || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) {
+ hs = hs * 3;
+ }
+
+
fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
- fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+ fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(hs - 1);
if (var->pixclock > 0) {
int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
- clkdiv = (clkdiv / 2) -1;
- if (clkdiv < 0)
- clkdiv = 0;
+ if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) {
+ clkdiv = (clkdiv / 2) -1;
+ if (clkdiv < 0)
+ clkdiv = 0;
+ }
+ else {
+ clkdiv = (clkdiv / 2);
+ if (clkdiv < 2)
+ clkdiv = 2;
+ }
fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
@@ -329,10 +448,18 @@ static int s3c2410fb_set_par(struct fb_info *info)
struct s3c2410fb_info *fbi = info->par;
struct fb_var_screeninfo *var = &info->var;
- if (var->bits_per_pixel == 16)
- fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
- else
- fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ switch (var->bits_per_pixel)
+ {
+ case 16:
+ fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
+ break;
+ case 1:
+ fbi->fb->fix.visual = FB_VISUAL_MONO01;
+ break;
+ default:
+ fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ }
fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8;
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index cd10b18150b..5d2a4a4b731 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1200,9 +1200,9 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
* Our LCD controller task (which is called when we blank or unblank)
* via keventd.
*/
-static void sa1100fb_task(void *dummy)
+static void sa1100fb_task(struct work_struct *w)
{
- struct sa1100fb_info *fbi = dummy;
+ struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task);
u_int state = xchg(&fbi->task_state, -1);
set_ctrlr_state(fbi, state);
@@ -1444,7 +1444,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
fbi->max_bpp / 8;
init_waitqueue_head(&fbi->ctrlr_wait);
- INIT_WORK(&fbi->task, sa1100fb_task, fbi);
+ INIT_WORK(&fbi->task, sa1100fb_task);
init_MUTEX(&fbi->ctrlr_sem);
return fbi;
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 3f94223b7f0..1411f3b6a00 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -208,7 +208,7 @@ void savagefb_delete_i2c_busses(struct fb_info *info)
struct savagefb_par *par = info->par;
if (par->chan.par)
- i2c_bit_del_bus(&par->chan.adapter);
+ i2c_del_adapter(&par->chan.adapter);
par->chan.par = NULL;
}
@@ -227,11 +227,8 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
/* try to get from firmware */
const u8 *e = fb_firmware_edid(info->device);
- if (e) {
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, e, EDID_LENGTH);
- }
+ if (e)
+ edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
}
*out_edid = edid;
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index f13faddc618..47e1896cffe 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -445,11 +445,8 @@ SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
void
SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
{
- unsigned int i, j;
-
- for(i = 0; i < delaytime; i++) {
- j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
- }
+ while (delaytime-- > 0)
+ SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
}
#if defined(SIS300) || defined(SIS315H)
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 711cb11d6eb..59cd1e750f3 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -21,6 +21,11 @@
* Remove never finished and bogus 24/32bit support
* Clean up macro abuse
* Minor tidying for format.
+ * 12/2006 Helge Deller <deller@gmx.de>
+ * add /sys/class/graphics/fbX/vgapass sysfs-interface
+ * add module option "mode_option" to set initial screen mode
+ * use fbdev default videomode database
+ * remove debug functions from ioctl
*/
/*
@@ -65,19 +70,10 @@
*
* sstfb specific ioctls:
* toggle vga (0x46db) : toggle vga_pass_through
- * fill fb (0x46dc) : fills fb
- * test disp (0x46de) : draws a test image
*/
#undef SST_DEBUG
-/*
- Default video mode .
- 0 800x600@60 took from glide
- 1 640x480@75 took from glide
- 2 1024x768@76 std fb.mode
- 3 640x480@60 glide default */
-#define DEFAULT_MODE 3
/*
* Includes
@@ -92,20 +88,24 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/io.h>
-#include <asm/ioctl.h>
#include <asm/uaccess.h>
#include <video/sstfb.h>
/* initialized by setup */
-static int vgapass; /* enable Vga passthrough cable */
+static int vgapass; /* enable VGA passthrough cable */
static int mem; /* mem size in MB, 0 = autodetect */
static int clipping = 1; /* use clipping (slower, safer) */
static int gfxclk; /* force FBI freq in Mhz . Dangerous */
static int slowpci; /* slow PCI settings */
-static char *mode_option __devinitdata;
+/*
+ Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
+*/
+#define DEFAULT_VIDEO_MODE "640x480@60"
+
+static char *mode_option __devinitdata = DEFAULT_VIDEO_MODE;
enum {
ID_VOODOO1 = 0,
@@ -119,48 +119,11 @@ static struct sst_spec voodoo_spec[] __devinitdata = {
{ .name = "Voodoo2", .default_gfx_clock = 75000, .max_gfxclk = 85 },
};
-static struct fb_var_screeninfo sstfb_default =
-#if ( DEFAULT_MODE == 0 )
- { /* 800x600@60, 16 bpp .borowed from glide/sst1/include/sst1init.h */
- 800, 600, 800, 600, 0, 0, 16, 0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 25000, 86, 41, 23, 1, 127, 4,
- 0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 1 )
- {/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */
- 640, 480, 640, 480, 0, 0, 16, 0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 31746, 118, 17, 16, 1, 63, 3,
- 0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 2 )
- { /* 1024x768@76 took from my /etc/fb.modes */
- 1024, 768, 1024, 768,0, 0, 16,0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 11764, 208, 8, 36, 16, 120, 3 ,
- 0, FB_VMODE_NONINTERLACED };
-#elif ( DEFAULT_MODE == 3 )
- { /* 640x480@60 , 16bpp glide default ?*/
- 640, 480, 640, 480, 0, 0, 16, 0,
- {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0,
- 39721 , 38, 26 , 25 ,18 , 96 ,2,
- 0, FB_VMODE_NONINTERLACED };
-#elif
- #error "Invalid DEFAULT_MODE value !"
-#endif
-
/*
* debug functions
*/
-static void sstfb_drawdebugimage(struct fb_info *info);
-static int sstfb_dump_regs(struct fb_info *info);
-
-
#if (SST_DEBUG_REG > 0)
static void sst_dbg_print_read_reg(u32 reg, u32 val) {
const char *regname;
@@ -726,51 +689,77 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0;
}
-static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+static void sstfb_setvgapass( struct fb_info *info, int enable )
{
struct sstfb_par *par = info->par;
struct pci_dev *sst_dev = par->dev;
- u32 fbiinit0, tmp, val;
- u_long p;
+ u32 fbiinit0, tmp;
+
+ enable = enable ? 1:0;
+ if (par->vgapass == enable)
+ return;
+ par->vgapass = enable;
+
+ pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
+ tmp | PCI_EN_INIT_WR );
+ fbiinit0 = sst_read (FBIINIT0);
+ if (par->vgapass) {
+ sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
+ printk(KERN_INFO "fb%d: Enabling VGA pass-through\n", info->node );
+ } else {
+ sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
+ printk(KERN_INFO "fb%d: Disabling VGA pass-through\n", info->node );
+ }
+ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
+}
+
+static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *info = dev_get_drvdata(device);
+ char ** last = NULL;
+ int val;
+
+ val = simple_strtoul(buf, last, 0);
+ sstfb_setvgapass(info, val);
+
+ return count;
+}
+
+static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(device);
+ struct sstfb_par *par = info->par;
+ return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass);
+}
+
+static struct device_attribute device_attrs[] = {
+ __ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
+ };
+
+static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sstfb_par *par;
+ u32 val;
switch (cmd) {
-
- /* dump current FBIINIT values to system log */
- case _IO('F', 0xdb): /* 0x46db */
- return sstfb_dump_regs(info);
-
- /* fills lfb with #arg pixels */
- case _IOW('F', 0xdc, u32): /* 0x46dc */
+ /* set/get VGA pass_through mode */
+ case SSTFB_SET_VGAPASS:
if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
return -EFAULT;
- if (val > info->fix.smem_len)
- val = info->fix.smem_len;
- for (p = 0 ; p < val; p += 2)
- writew(p >> 6, info->screen_base + p);
+ sstfb_setvgapass(info, val);
return 0;
-
- /* change VGA pass_through mode */
- case _IOW('F', 0xdd, u32): /* 0x46dd */
- if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+ case SSTFB_GET_VGAPASS:
+ par = info->par;
+ val = par->vgapass;
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
return -EFAULT;
- pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
- tmp | PCI_EN_INIT_WR );
- fbiinit0 = sst_read (FBIINIT0);
- if (val)
- sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
- else
- sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);
- pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
- return 0;
-
- /* draw test image */
- case _IO('F', 0xde): /* 0x46de */
- f_dprintk("test color display at %d bpp\n",
- info->var.bits_per_pixel);
- sstfb_drawdebugimage(info);
return 0;
}
+
return -EINVAL;
}
@@ -804,6 +793,7 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
/*
* FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
*/
+#if 0
static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct sstfb_par *par = info->par;
@@ -825,6 +815,7 @@ static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
| (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
sst_wait_idle();
}
+#endif
@@ -1156,6 +1147,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
struct pll_timing gfx_timings;
struct sst_spec *spec;
int Fout;
+ int gfx_clock;
spec = &voodoo_spec[par->type];
f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
@@ -1196,15 +1188,15 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
}
/* set graphic clock */
- par->gfx_clock = spec->default_gfx_clock;
+ gfx_clock = spec->default_gfx_clock;
if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
- par->gfx_clock = gfxclk *1000;
+ gfx_clock = gfxclk *1000;
} else if (gfxclk) {
printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
}
- sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);
+ sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* disable fbiinit remap */
@@ -1215,10 +1207,11 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
fbiinit0 = FBIINIT0_DEFAULT;
fbiinit1 = FBIINIT1_DEFAULT;
fbiinit4 = FBIINIT4_DEFAULT;
- if (vgapass)
- fbiinit0 &= ~EN_VGA_PASSTHROUGH;
+ par->vgapass = vgapass;
+ if (par->vgapass)
+ fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
else
- fbiinit0 |= EN_VGA_PASSTHROUGH;
+ fbiinit0 |= DIS_VGA_PASSTHROUGH;
if (slowpci) {
fbiinit1 |= SLOW_PCI_WRITES;
fbiinit4 |= SLOW_PCI_READS;
@@ -1267,7 +1260,7 @@ static void __devexit sst_shutdown(struct fb_info *info)
/* TODO maybe shutdown the dac, vrefresh and so on... */
pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR);
- sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH);
+ sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
* from start ? */
@@ -1278,8 +1271,7 @@ static void __devexit sst_shutdown(struct fb_info *info)
/*
* Interface to the world
*/
-#ifndef MODULE
-static int __init sstfb_setup(char *options)
+static int __devinit sstfb_setup(char *options)
{
char *this_opt;
@@ -1312,7 +1304,7 @@ static int __init sstfb_setup(char *options)
}
return 0;
}
-#endif
+
static struct fb_ops sstfb_ops = {
.owner = THIS_MODULE,
@@ -1416,15 +1408,10 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
*/
fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
- if ( mode_option &&
- fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) {
- printk(KERN_ERR "sstfb: can't set supplied video mode. Using default\n");
- info->var = sstfb_default;
- } else
- info->var = sstfb_default;
+ fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
if (sstfb_check_var(&info->var, info)) {
- printk(KERN_ERR "sstfb: invalid default video mode.\n");
+ printk(KERN_ERR "sstfb: invalid video mode.\n");
goto fail;
}
@@ -1442,10 +1429,11 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
goto fail;
}
- if (1) /* set to 0 to see an initial bitmap instead */
- sstfb_clear_screen(info);
- else
- sstfb_drawdebugimage(info);
+ sstfb_clear_screen(info);
+
+ if (device_create_file(info->dev, &device_attrs[0]))
+ printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
+
printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n",
info->node, fix->id, info->screen_base);
@@ -1453,6 +1441,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
return 0;
fail:
+ fb_dealloc_cmap(&info->cmap);
iounmap(info->screen_base);
fail_fb_remap:
iounmap(par->mmio_vbase);
@@ -1473,21 +1462,23 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
info = pci_get_drvdata(pdev);
par = info->par;
+ device_remove_file(info->dev, &device_attrs[0]);
sst_shutdown(info);
- unregister_framebuffer(info);
iounmap(info->screen_base);
iounmap(par->mmio_vbase);
release_mem_region(info->fix.smem_start, 0x400000);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ fb_dealloc_cmap(&info->cmap);
+ unregister_framebuffer(info);
framebuffer_release(info);
}
-static struct pci_device_id sstfb_id_tbl[] = {
- { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
- { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
+static const struct pci_device_id sstfb_id_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
+ .driver_data = ID_VOODOO1, },
+ { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
+ .driver_data = ID_VOODOO2, },
{ 0 },
};
@@ -1501,142 +1492,23 @@ static struct pci_driver sstfb_driver = {
static int __devinit sstfb_init(void)
{
-#ifndef MODULE
char *option = NULL;
if (fb_get_options("sstfb", &option))
return -ENODEV;
sstfb_setup(option);
-#endif
+
return pci_register_driver(&sstfb_driver);
}
-#ifdef MODULE
static void __devexit sstfb_exit(void)
{
pci_unregister_driver(&sstfb_driver);
}
-#endif
-/*
- * testing and debugging functions
- */
-
-static int sstfb_dump_regs(struct fb_info *info)
-{
-#ifdef SST_DEBUG
- static struct { u32 reg ; const char *reg_name;} pci_regs[] = {
- { PCI_INIT_ENABLE, "initenable"},
- { PCI_VCLK_ENABLE, "enable vclk"},
- { PCI_VCLK_DISABLE, "disable vclk"},
- };
-
- static struct { u32 reg ; const char *reg_name;} sst_regs[] = {
- {FBIINIT0,"fbiinit0"},
- {FBIINIT1,"fbiinit1"},
- {FBIINIT2,"fbiinit2"},
- {FBIINIT3,"fbiinit3"},
- {FBIINIT4,"fbiinit4"},
- {FBIINIT5,"fbiinit5"},
- {FBIINIT6,"fbiinit6"},
- {FBIINIT7,"fbiinit7"},
- {LFBMODE,"lfbmode"},
- {FBZMODE,"fbzmode"},
- };
-
- const int pci_s = ARRAY_SIZE(pci_regs);
- const int sst_s = ARRAY_SIZE(sst_regs);
- struct sstfb_par *par = info->par;
- struct pci_dev *dev = par->dev;
- u32 pci_res[pci_s];
- u32 sst_res[sst_s];
- int i;
-
- for (i=0; i<pci_s; i++) {
- pci_read_config_dword(dev, pci_regs[i].reg, &pci_res[i]);
- }
- for (i=0; i<sst_s; i++) {
- sst_res[i] = sst_read(sst_regs[i].reg);
- }
-
- dprintk("hardware register dump:\n");
- for (i=0; i<pci_s; i++) {
- dprintk("%s %0#10x\n", pci_regs[i].reg_name, pci_res[i]);
- }
- for (i=0; i<sst_s; i++) {
- dprintk("%s %0#10x\n", sst_regs[i].reg_name, sst_res[i]);
- }
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
-static void sstfb_fillrect_softw( struct fb_info *info, const struct fb_fillrect *rect)
-{
- u8 __iomem *fbbase_virt = info->screen_base;
- int x, y, w = info->var.bits_per_pixel == 16 ? 2 : 4;
- u32 color = rect->color, height = rect->height;
- u8 __iomem *p;
-
- if (w==2) color |= color<<16;
- for (y=rect->dy; height; y++, height--) {
- p = fbbase_virt + y*info->fix.line_length + rect->dx*w;
- x = rect->width;
- if (w==2) x>>=1;
- while (x) {
- writel(color, p);
- p += 4;
- x--;
- }
- }
-}
-
-static void sstfb_drawrect_XY( struct fb_info *info, int x, int y,
- int w, int h, int color, int hwfunc)
-{
- struct fb_fillrect rect;
- rect.dx = x;
- rect.dy = y;
- rect.height = h;
- rect.width = w;
- rect.color = color;
- rect.rop = ROP_COPY;
- if (hwfunc)
- sstfb_fillrect(info, &rect);
- else
- sstfb_fillrect_softw(info, &rect);
-}
-
-/* print some squares on the fb */
-static void sstfb_drawdebugimage(struct fb_info *info)
-{
- static int idx;
-
- /* clear screen */
- sstfb_clear_screen(info);
-
- idx = (idx+1) & 1;
-
- /* white rect */
- sstfb_drawrect_XY(info, 0, 0, 50, 50, 0xffff, idx);
-
- /* blue rect */
- sstfb_drawrect_XY(info, 50, 50, 50, 50, 0x001f, idx);
-
- /* green rect */
- sstfb_drawrect_XY(info, 100, 100, 80, 80, 0x07e0, idx);
-
- /* red rect */
- sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);
-}
-
module_init(sstfb_init);
-
-#ifdef MODULE
module_exit(sstfb_exit);
-#endif
MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
@@ -1652,3 +1524,6 @@ module_param(gfxclk, int, 0);
MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
module_param(slowpci, bool, 0);
MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
+
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 3e16e2d9d55..69f3b264a22 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1291,6 +1291,7 @@ out_err3:
out_err2:
release_mem_region(fix->smem_start, fix->smem_len);
out_err1:
+ iounmap(info->screen_base);
fb_dealloc_cmap(&info->cmap);
out_err0:
kfree(fb);
@@ -1364,6 +1365,8 @@ stifb_cleanup(void)
unregister_framebuffer(sti->info);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
release_mem_region(info->fix.smem_start, info->fix.smem_len);
+ if (info->screen_base)
+ iounmap(info->screen_base);
fb_dealloc_cmap(&info->cmap);
kfree(info);
}
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 6990ab11cd0..5a99669232c 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -350,18 +350,23 @@ struct all_info {
struct tcx_par par;
};
-static void tcx_unmap_regs(struct all_info *all)
+static void tcx_unmap_regs(struct of_device *op, struct all_info *all)
{
if (all->par.tec)
- of_iounmap(all->par.tec, sizeof(struct tcx_tec));
+ of_iounmap(&op->resource[7],
+ all->par.tec, sizeof(struct tcx_tec));
if (all->par.thc)
- of_iounmap(all->par.thc, sizeof(struct tcx_thc));
+ of_iounmap(&op->resource[9],
+ all->par.thc, sizeof(struct tcx_thc));
if (all->par.bt)
- of_iounmap(all->par.bt, sizeof(struct bt_regs));
+ of_iounmap(&op->resource[8],
+ all->par.bt, sizeof(struct bt_regs));
if (all->par.cplane)
- of_iounmap(all->par.cplane, all->par.fbsize * sizeof(u32));
+ of_iounmap(&op->resource[4],
+ all->par.cplane, all->par.fbsize * sizeof(u32));
if (all->info.screen_base)
- of_iounmap(all->info.screen_base, all->par.fbsize);
+ of_iounmap(&op->resource[0],
+ all->info.screen_base, all->par.fbsize);
}
static int __devinit tcx_init_one(struct of_device *op)
@@ -398,7 +403,7 @@ static int __devinit tcx_init_one(struct of_device *op)
all->par.fbsize, "tcx ram");
if (!all->par.tec || !all->par.thc ||
!all->par.bt || !all->info.screen_base) {
- tcx_unmap_regs(all);
+ tcx_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -409,7 +414,7 @@ static int __devinit tcx_init_one(struct of_device *op)
all->par.fbsize * sizeof(u32),
"tcx cplane");
if (!all->par.cplane) {
- tcx_unmap_regs(all);
+ tcx_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -461,7 +466,7 @@ static int __devinit tcx_init_one(struct of_device *op)
tcx_blank(FB_BLANK_UNBLANK, &all->info);
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
- tcx_unmap_regs(all);
+ tcx_unmap_regs(op, all);
kfree(all);
return -ENOMEM;
}
@@ -472,7 +477,7 @@ static int __devinit tcx_init_one(struct of_device *op)
err = register_framebuffer(&all->info);
if (err < 0) {
fb_dealloc_cmap(&all->info.cmap);
- tcx_unmap_regs(all);
+ tcx_unmap_regs(op, all);
kfree(all);
return err;
}
@@ -495,18 +500,18 @@ static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id
return tcx_init_one(op);
}
-static int __devexit tcx_remove(struct of_device *dev)
+static int __devexit tcx_remove(struct of_device *op)
{
- struct all_info *all = dev_get_drvdata(&dev->dev);
+ struct all_info *all = dev_get_drvdata(&op->dev);
unregister_framebuffer(&all->info);
fb_dealloc_cmap(&all->info.cmap);
- tcx_unmap_regs(all);
+ tcx_unmap_regs(op, all);
kfree(all);
- dev_set_drvdata(&dev->dev, NULL);
+ dev_set_drvdata(&op->dev, NULL);
return 0;
}
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 94fde625a6c..4b88fab83b7 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -23,6 +23,7 @@
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/selection.h>
+#include <linux/bitrev.h>
#include <asm/io.h>
#include <video/tgafb.h>
@@ -517,41 +518,6 @@ tgafb_blank(int blank, struct fb_info *info)
static void
tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- static unsigned char const bitrev[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
- };
-
struct tga_par *par = (struct tga_par *) info->par;
u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask;
unsigned long rincr, line_length, shift, pos, is8bpp;
@@ -649,7 +615,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
/* The image data is bit big endian; we need
little endian. */
for (j = 0; j < bwidth; ++j)
- mask |= bitrev[data[j]] << (j * 8);
+ mask |= bitrev8(data[j]) << (j * 8);
__raw_writel(mask << shift, fb_base + pos);
@@ -676,10 +642,10 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
for (i = 0; i < height; ++i) {
for (j = 0; j < bwidth; j += 4) {
u32 mask = 0;
- mask |= bitrev[data[j+0]] << (0 * 8);
- mask |= bitrev[data[j+1]] << (1 * 8);
- mask |= bitrev[data[j+2]] << (2 * 8);
- mask |= bitrev[data[j+3]] << (3 * 8);
+ mask |= bitrev8(data[j+0]) << (0 * 8);
+ mask |= bitrev8(data[j+1]) << (1 * 8);
+ mask |= bitrev8(data[j+2]) << (2 * 8);
+ mask |= bitrev8(data[j+3]) << (3 * 8);
__raw_writel(mask, fb_base + pos + j*bincr);
}
pos += line_length;
@@ -699,7 +665,7 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
for (i = 0; i < height; ++i) {
u32 mask = 0;
for (j = 0; j < bwidth; ++j)
- mask |= bitrev[data[j]] << (j * 8);
+ mask |= bitrev8(data[j]) << (j * 8);
__raw_writel(mask, fb_base + pos);
pos += line_length;
data += rincr;
@@ -726,8 +692,8 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
for (i = 0; i < height; ++i) {
for (j = 0; j < bwidth; j += 2) {
u32 mask = 0;
- mask |= bitrev[data[j+0]] << (0 * 8);
- mask |= bitrev[data[j+1]] << (1 * 8);
+ mask |= bitrev8(data[j+0]) << (0 * 8);
+ mask |= bitrev8(data[j+1]) << (1 * 8);
mask <<= shift;
__raw_writel(mask, fb_base + pos + j*bincr);
}
@@ -746,9 +712,9 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
bwidth = (width & 15) > 8;
for (i = 0; i < height; ++i) {
- u32 mask = bitrev[data[0]];
+ u32 mask = bitrev8(data[0]);
if (bwidth)
- mask |= bitrev[data[1]] << 8;
+ mask |= bitrev8(data[1]) << 8;
mask <<= shift;
__raw_writel(mask, fb_base + pos);
pos += line_length;
@@ -1473,6 +1439,8 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err1:
+ if (mem_base)
+ iounmap(mem_base);
release_mem_region(bar0_start, bar0_len);
err0:
kfree(all);
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 14175cdb9c9..55e8aa450bf 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1130,7 +1130,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
debug("request_mem_region failed!\n");
- return -1;
+ err = -1;
+ goto out_unmap;
}
fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
@@ -1139,7 +1140,8 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
if (!fb_info.screen_base) {
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
debug("ioremap failed\n");
- return -1;
+ err = -1;
+ goto out_unmap;
}
output("%s board found\n", pci_name(dev));
@@ -1162,8 +1164,10 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
#endif
fb_info.pseudo_palette = pseudo_pal;
- if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp))
- return -EINVAL;
+ if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) {
+ err = -EINVAL;
+ goto out_unmap;
+ }
fb_alloc_cmap(&fb_info.cmap,256,0);
if (defaultaccel && acc)
default_var.accel_flags |= FB_ACCELF_TEXT;
@@ -1174,12 +1178,20 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
fb_info.device = &dev->dev;
if (register_framebuffer(&fb_info) < 0) {
printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto out_unmap;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
fb_info.node, fb_info.fix.id,default_var.xres,
default_var.yres,default_var.bits_per_pixel);
return 0;
+
+out_unmap:
+ if (default_par.io_virt)
+ iounmap(default_par.io_virt);
+ if (fb_info.screen_base)
+ iounmap(fb_info.screen_base);
+ return err;
}
static void __devexit trident_pci_remove(struct pci_dev * dev)
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 2196448396e..e16322d157d 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -47,17 +47,16 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = {
.accel = FB_ACCEL_NONE,
};
-static int inverse = 0;
-static int mtrr = 0; /* disable mtrr */
-static int vram_remap __initdata = 0; /* Set amount of memory to be used */
-static int vram_total __initdata = 0; /* Set total amount of memory */
-static int pmi_setpal = 1; /* pmi for palette changes ??? */
-static int ypan = 0; /* 0..nothing, 1..ypan, 2..ywrap */
-static unsigned short *pmi_base = NULL;
-static void (*pmi_start)(void);
-static void (*pmi_pal)(void);
-static int depth;
-static int vga_compat;
+static int inverse __read_mostly;
+static int mtrr __read_mostly; /* disable mtrr */
+static int vram_remap __initdata; /* Set amount of memory to be used */
+static int vram_total __initdata; /* Set total amount of memory */
+static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */
+static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */
+static void (*pmi_start)(void) __read_mostly;
+static void (*pmi_pal) (void) __read_mostly;
+static int depth __read_mostly;
+static int vga_compat __read_mostly;
/* --------------------------------------------------------------------- */
static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -312,6 +311,7 @@ static int __init vesafb_probe(struct platform_device *dev)
ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
if (ypan || pmi_setpal) {
+ unsigned short *pmi_base;
pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
@@ -456,6 +456,8 @@ static int __init vesafb_probe(struct platform_device *dev)
info->node, info->fix.id);
return 0;
err:
+ if (info->screen_base)
+ iounmap(info->screen_base);
framebuffer_release(info);
release_mem_region(vesafb_fix.smem_start, size_total);
return err;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 43d5a6d9c4a..6aff63d5b29 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -264,7 +264,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
const struct fb_info *info,
int mul, int div)
{
- static struct {
+ static const struct {
u32 pixclock;
u8 misc;
u8 seq_clock_mode;
@@ -652,7 +652,7 @@ static int vga16fb_set_par(struct fb_info *info)
static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
{
- static unsigned char map[] = { 000, 001, 010, 011 };
+ static const unsigned char map[] = { 000, 001, 010, 011 };
int val;
if (regno >= 16)
@@ -1139,23 +1139,19 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
}
}
-#ifdef __LITTLE_ENDIAN
-static unsigned int transl_l[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_h[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
-#else
-#ifdef __BIG_ENDIAN
-static unsigned int transl_h[] =
-{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
-static unsigned int transl_l[] =
-{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
+#define TRANS_MASK_LOW {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
+#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
+ 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
+
+#if defined(__LITTLE_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_LOW;
+static const u16 transl_h[] = TRANS_MASK_HIGH;
+#elif defined(__BIG_ENDIAN)
+static const u16 transl_l[] = TRANS_MASK_HIGH;
+static const u16 transl_h[] = TRANS_MASK_LOW;
#else
#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
#endif
-#endif
static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
{
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index 64378959dd7..b9fb6fb3600 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -1799,7 +1799,7 @@ int __init virgefb_init(void)
#warning release resources
printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
DPRINTK("EXIT\n");
- return -EINVAL;
+ goto out_unmap;
}
printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
@@ -1809,6 +1809,21 @@ int __init virgefb_init(void)
DPRINTK("EXIT\n");
return 0;
+
+out_unmap:
+ if (board_addr >= 0x01000000) {
+ if (v_ram)
+ iounmap((void*)v_ram);
+ if (vgaio_regs)
+ iounmap(vgaio_regs);
+ if (mmio_regs)
+ iounmap(mmio_regs);
+ if (vcode_switch_base)
+ iounmap((void*)vcode_switch_base);
+ v_ram = vcode_switch_base = 0;
+ vgaio_regs = mmio_regs = NULL;
+ }
+ return -EINVAL;
}
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index d18d6424cd2..904e5aeb696 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -9,7 +9,7 @@ config W1_SLAVE_THERM
tristate "Thermal family implementation"
depends on W1
help
- Say Y here if you want to connect 1-wire thermal sensors to you
+ Say Y here if you want to connect 1-wire thermal sensors to your
wire.
config W1_SLAVE_SMEM
@@ -17,7 +17,7 @@ config W1_SLAVE_SMEM
depends on W1
help
Say Y here if you want to connect 1-wire
- simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+ simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
config W1_SLAVE_DS2433
tristate "4kb EEPROM family support (DS2433)"
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 7aa2d3de6d3..60b05bc1564 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -47,7 +47,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
static ssize_t
proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
- struct inode *ino = file->f_dentry->d_inode;
+ struct inode *ino = file->f_path.dentry->d_inode;
struct proc_dir_entry *dp = PDE(ino);
struct zorro_dev *z = dp->data;
struct ConfigDev cd;
diff --git a/fs/9p/error.c b/fs/9p/error.c
index ae91555c155..0d7fa4e0881 100644
--- a/fs/9p/error.c
+++ b/fs/9p/error.c
@@ -83,6 +83,7 @@ int v9fs_errstr2errno(char *errstr, int len)
if (errno == 0) {
/* TODO: if error isn't found, add it dynamically */
+ errstr[len] = 0;
printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
errstr);
errno = 1;
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 27507201f9e..a9b6301a04f 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -25,6 +25,7 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/idr.h>
+#include <asm/semaphore.h>
#include "debug.h"
#include "v9fs.h"
@@ -84,6 +85,7 @@ struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
new->iounit = 0;
new->rdir_pos = 0;
new->rdir_fcall = NULL;
+ init_MUTEX(&new->lock);
INIT_LIST_HEAD(&new->list);
return new;
@@ -102,11 +104,11 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
}
/**
- * v9fs_fid_lookup - retrieve the right fid from a particular dentry
+ * v9fs_fid_lookup - return a locked fid from a dentry
* @dentry: dentry to look for fid in
- * @type: intent of lookup (operation or traversal)
*
- * find a fid in the dentry
+ * find a fid in the dentry, obtain its semaphore and return a reference to it.
+ * code calling lookup is responsible for releasing lock
*
* TODO: only match fids that have the same uid as current user
*
@@ -124,7 +126,68 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
if (!return_fid) {
dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");
+ return_fid = ERR_PTR(-EBADF);
}
+ if(down_interruptible(&return_fid->lock))
+ return ERR_PTR(-EINTR);
+
return return_fid;
}
+
+/**
+ * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it
+ * @dentry: dentry to look for fid in
+ *
+ * find a fid in the dentry and then clone to a new private fid
+ *
+ * TODO: only match fids that have the same uid as current user
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry)
+{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
+ struct v9fs_fcall *fcall = NULL;
+ int fid, err;
+
+ base_fid = v9fs_fid_lookup(dentry);
+
+ if(IS_ERR(base_fid))
+ return base_fid;
+
+ if(base_fid) { /* clone fid */
+ fid = v9fs_get_idpool(&v9ses->fidpool);
+ if (fid < 0) {
+ eprintk(KERN_WARNING, "newfid fails!\n");
+ new_fid = ERR_PTR(-ENOSPC);
+ goto Release_Fid;
+ }
+
+ err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
+ if (err < 0) {
+ dprintk(DEBUG_ERROR, "clone walk didn't work\n");
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ new_fid = ERR_PTR(err);
+ goto Free_Fcall;
+ }
+ new_fid = v9fs_fid_create(v9ses, fid);
+ if (new_fid == NULL) {
+ dprintk(DEBUG_ERROR, "out of memory\n");
+ new_fid = ERR_PTR(-ENOMEM);
+ }
+Free_Fcall:
+ kfree(fcall);
+ }
+
+Release_Fid:
+ up(&base_fid->lock);
+ return new_fid;
+}
+
+void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid)
+{
+ v9fs_t_clunk(v9ses, fid->fid);
+ v9fs_fid_destroy(fid);
+}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index aa974d6875c..48fc170c26c 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -30,6 +30,8 @@ struct v9fs_fid {
struct list_head list; /* list of fids associated with a dentry */
struct list_head active; /* XXX - debug */
+ struct semaphore lock;
+
u32 fid;
unsigned char fidopen; /* set when fid is opened */
unsigned char fidclunked; /* set when fid has already been clunked */
@@ -55,3 +57,6 @@ struct v9fs_fid *v9fs_fid_get_created(struct dentry *);
void v9fs_fid_destroy(struct v9fs_fid *fid);
struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid);
int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry);
+struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry);
+void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid);
+
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 944273c3dbf..147ceef8e53 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -132,8 +132,10 @@ int v9fs_mux_global_init(void)
v9fs_mux_poll_tasks[i].task = NULL;
v9fs_mux_wq = create_workqueue("v9fs");
- if (!v9fs_mux_wq)
+ if (!v9fs_mux_wq) {
+ printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
return -ENOMEM;
+ }
return 0;
}
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 0b96fae8b47..d9b561ba5e5 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -457,14 +457,19 @@ static int __init init_v9fs(void)
v9fs_error_init();
- printk(KERN_INFO "Installing v9fs 9P2000 file system support\n");
+ printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
ret = v9fs_mux_global_init();
- if (!ret)
+ if (ret) {
+ printk(KERN_WARNING "v9fs: starting mux failed\n");
return ret;
+ }
ret = register_filesystem(&v9fs_fs_type);
- if (!ret)
+ if (ret) {
+ printk(KERN_WARNING "v9fs: registering file system failed\n");
v9fs_mux_global_exit();
+ }
+
return ret;
}
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 9dfd259a70b..cc24abf232d 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -54,7 +54,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
int retval = -EIO;
loff_t offset = page_offset(page);
int count = PAGE_CACHE_SIZE;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
struct v9fs_fid *v9f = filp->private_data;
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 905c882f4e2..3129688143e 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -71,7 +71,7 @@ static inline int dt_type(struct v9fs_stat *mistat)
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct v9fs_fcall *fcall = NULL;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
struct v9fs_fid *file = filp->private_data;
unsigned int i, n, s;
@@ -80,7 +80,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct v9fs_stat stat;
int over = 0;
- dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name);
+ dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = file->fid;
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 79e6f9cd734..9f17b0cacdd 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -55,53 +55,22 @@ int v9fs_file_open(struct inode *inode, struct file *file)
struct v9fs_fid *vfid;
struct v9fs_fcall *fcall = NULL;
int omode;
- int fid = V9FS_NOFID;
int err;
dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
- vfid = v9fs_fid_lookup(file->f_dentry);
- if (!vfid) {
- dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
- return -EBADF;
- }
-
- fid = v9fs_get_idpool(&v9ses->fidpool);
- if (fid < 0) {
- eprintk(KERN_WARNING, "newfid fails!\n");
- return -ENOSPC;
- }
+ vfid = v9fs_fid_clone(file->f_path.dentry);
+ if (IS_ERR(vfid))
+ return PTR_ERR(vfid);
- err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall);
- if (err < 0) {
- dprintk(DEBUG_ERROR, "rewalk didn't work\n");
- if (fcall && fcall->id == RWALK)
- goto clunk_fid;
- else {
- v9fs_put_idpool(fid, &v9ses->fidpool);
- goto free_fcall;
- }
- }
- kfree(fcall);
-
- /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
- /* translate open mode appropriately */
omode = v9fs_uflags2omode(file->f_flags);
- err = v9fs_t_open(v9ses, fid, omode, &fcall);
+ err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("open failed", fcall);
- goto clunk_fid;
- }
-
- vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
- if (vfid == NULL) {
- dprintk(DEBUG_ERROR, "out of memory\n");
- err = -ENOMEM;
- goto clunk_fid;
+ goto Clunk_Fid;
}
file->private_data = vfid;
- vfid->fid = fid;
vfid->fidopen = 1;
vfid->fidclunked = 0;
vfid->iounit = fcall->params.ropen.iounit;
@@ -112,10 +81,8 @@ int v9fs_file_open(struct inode *inode, struct file *file)
return 0;
-clunk_fid:
- v9fs_t_clunk(v9ses, fid);
-
-free_fcall:
+Clunk_Fid:
+ v9fs_fid_clunk(v9ses, vfid);
kfree(fcall);
return err;
@@ -133,7 +100,7 @@ free_fcall:
static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
{
int res = 0;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
@@ -161,7 +128,7 @@ static ssize_t
v9fs_file_read(struct file *filp, char __user * data, size_t count,
loff_t * offset)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
struct v9fs_fid *v9f = filp->private_data;
struct v9fs_fcall *fcall = NULL;
@@ -225,7 +192,7 @@ static ssize_t
v9fs_file_write(struct file *filp, const char __user * data,
size_t count, loff_t * offset)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
struct v9fs_fid *v9fid = filp->private_data;
struct v9fs_fcall *fcall;
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 18f26cdfd88..9109ba1d696 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -416,12 +416,8 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
sb = file_inode->i_sb;
v9ses = v9fs_inode2v9ses(file_inode);
v9fid = v9fs_fid_lookup(file);
-
- if (!v9fid) {
- dprintk(DEBUG_ERROR,
- "no v9fs_fid\n");
- return -EBADF;
- }
+ if(IS_ERR(v9fid))
+ return PTR_ERR(v9fid);
fid = v9fid->fid;
if (fid < 0) {
@@ -433,11 +429,13 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
result = v9fs_t_remove(v9ses, fid, &fcall);
if (result < 0) {
PRINT_FCALL_ERROR("remove fails", fcall);
+ goto Error;
}
v9fs_put_idpool(fid, &v9ses->fidpool);
v9fs_fid_destroy(v9fid);
+Error:
kfree(fcall);
return result;
}
@@ -473,9 +471,13 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
inode = NULL;
vfid = NULL;
v9ses = v9fs_inode2v9ses(dir);
- dfid = v9fs_fid_lookup(dentry->d_parent);
- perm = unixmode2p9mode(v9ses, mode);
+ dfid = v9fs_fid_clone(dentry->d_parent);
+ if(IS_ERR(dfid)) {
+ err = PTR_ERR(dfid);
+ goto error;
+ }
+ perm = unixmode2p9mode(v9ses, mode);
if (nd && nd->flags & LOOKUP_OPEN)
flags = nd->intent.open.flags - 1;
else
@@ -485,9 +487,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
if (err)
- goto error;
+ goto clunk_dfid;
vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
+ v9fs_fid_clunk(v9ses, dfid);
if (IS_ERR(vfid)) {
err = PTR_ERR(vfid);
vfid = NULL;
@@ -525,6 +528,9 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
return 0;
+clunk_dfid:
+ v9fs_fid_clunk(v9ses, dfid);
+
error:
if (vfid)
v9fs_fid_destroy(vfid);
@@ -551,7 +557,12 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inode = NULL;
vfid = NULL;
v9ses = v9fs_inode2v9ses(dir);
- dfid = v9fs_fid_lookup(dentry->d_parent);
+ dfid = v9fs_fid_clone(dentry->d_parent);
+ if(IS_ERR(dfid)) {
+ err = PTR_ERR(dfid);
+ goto error;
+ }
+
perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
@@ -559,37 +570,36 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (err) {
dprintk(DEBUG_ERROR, "create error %d\n", err);
- goto error;
- }
-
- err = v9fs_t_clunk(v9ses, fid);
- if (err) {
- dprintk(DEBUG_ERROR, "clunk error %d\n", err);
- goto error;
+ goto clean_up_dfid;
}
vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
if (IS_ERR(vfid)) {
err = PTR_ERR(vfid);
vfid = NULL;
- goto error;
+ goto clean_up_dfid;
}
+ v9fs_fid_clunk(v9ses, dfid);
inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
- goto error;
+ goto clean_up_fids;
}
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
return 0;
-error:
+clean_up_fids:
if (vfid)
v9fs_fid_destroy(vfid);
+clean_up_dfid:
+ v9fs_fid_clunk(v9ses, dfid);
+
+error:
return err;
}
@@ -622,28 +632,23 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
dentry->d_op = &v9fs_dentry_operations;
dirfid = v9fs_fid_lookup(dentry->d_parent);
- if (!dirfid) {
- dprintk(DEBUG_ERROR, "no dirfid\n");
- return ERR_PTR(-EINVAL);
- }
+ if(IS_ERR(dirfid))
+ return ERR_PTR(PTR_ERR(dirfid));
dirfidnum = dirfid->fid;
- if (dirfidnum < 0) {
- dprintk(DEBUG_ERROR, "no dirfid for inode %p, #%lu\n",
- dir, dir->i_ino);
- return ERR_PTR(-EBADF);
- }
-
newfid = v9fs_get_idpool(&v9ses->fidpool);
if (newfid < 0) {
eprintk(KERN_WARNING, "newfid fails!\n");
- return ERR_PTR(-ENOSPC);
+ result = -ENOSPC;
+ goto Release_Dirfid;
}
result = v9fs_t_walk(v9ses, dirfidnum, newfid,
(char *)dentry->d_name.name, &fcall);
+ up(&dirfid->lock);
+
if (result < 0) {
if (fcall && fcall->id == RWALK)
v9fs_t_clunk(v9ses, newfid);
@@ -701,8 +706,12 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
return NULL;
- FreeFcall:
+Release_Dirfid:
+ up(&dirfid->lock);
+
+FreeFcall:
kfree(fcall);
+
return ERR_PTR(result);
}
@@ -746,10 +755,8 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *old_inode = old_dentry->d_inode;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
- struct v9fs_fid *olddirfid =
- v9fs_fid_lookup(old_dentry->d_parent);
- struct v9fs_fid *newdirfid =
- v9fs_fid_lookup(new_dentry->d_parent);
+ struct v9fs_fid *olddirfid;
+ struct v9fs_fid *newdirfid;
struct v9fs_wstat wstat;
struct v9fs_fcall *fcall = NULL;
int fid = -1;
@@ -759,16 +766,26 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
dprintk(DEBUG_VFS, "\n");
- if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
- dprintk(DEBUG_ERROR, "problem with arguments\n");
- return -EBADF;
+ if(IS_ERR(oldfid))
+ return PTR_ERR(oldfid);
+
+ olddirfid = v9fs_fid_clone(old_dentry->d_parent);
+ if(IS_ERR(olddirfid)) {
+ retval = PTR_ERR(olddirfid);
+ goto Release_lock;
+ }
+
+ newdirfid = v9fs_fid_clone(new_dentry->d_parent);
+ if(IS_ERR(newdirfid)) {
+ retval = PTR_ERR(newdirfid);
+ goto Clunk_olddir;
}
/* 9P can only handle file rename in the same directory */
if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
dprintk(DEBUG_ERROR, "old dir and new dir are different\n");
- retval = -EPERM;
- goto FreeFcallnBail;
+ retval = -EXDEV;
+ goto Clunk_newdir;
}
fid = oldfid->fid;
@@ -779,7 +796,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
old_inode->i_ino);
retval = -EBADF;
- goto FreeFcallnBail;
+ goto Clunk_newdir;
}
v9fs_blank_wstat(&wstat);
@@ -788,11 +805,20 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
- FreeFcallnBail:
if (retval < 0)
PRINT_FCALL_ERROR("wstat error", fcall);
kfree(fcall);
+
+Clunk_newdir:
+ v9fs_fid_clunk(v9ses, newdirfid);
+
+Clunk_olddir:
+ v9fs_fid_clunk(v9ses, olddirfid);
+
+Release_lock:
+ up(&oldfid->lock);
+
return retval;
}
@@ -810,15 +836,12 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
{
struct v9fs_fcall *fcall = NULL;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
+ struct v9fs_fid *fid = v9fs_fid_clone(dentry);
int err = -EPERM;
dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
- if (!fid) {
- dprintk(DEBUG_ERROR,
- "couldn't find fid associated with dentry\n");
- return -EBADF;
- }
+ if(IS_ERR(fid))
+ return PTR_ERR(fid);
err = v9fs_t_stat(v9ses, fid->fid, &fcall);
@@ -831,6 +854,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
}
kfree(fcall);
+ v9fs_fid_clunk(v9ses, fid);
return err;
}
@@ -844,18 +868,14 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
{
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
+ struct v9fs_fid *fid = v9fs_fid_clone(dentry);
struct v9fs_fcall *fcall = NULL;
struct v9fs_wstat wstat;
int res = -EPERM;
dprintk(DEBUG_VFS, "\n");
-
- if (!fid) {
- dprintk(DEBUG_ERROR,
- "Couldn't find fid associated with dentry\n");
- return -EBADF;
- }
+ if(IS_ERR(fid))
+ return PTR_ERR(fid);
v9fs_blank_wstat(&wstat);
if (iattr->ia_valid & ATTR_MODE)
@@ -887,6 +907,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (res >= 0)
res = inode_setattr(dentry->d_inode, iattr);
+ v9fs_fid_clunk(v9ses, fid);
return res;
}
@@ -987,18 +1008,15 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
struct v9fs_fcall *fcall = NULL;
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
+ struct v9fs_fid *fid = v9fs_fid_clone(dentry);
- if (!fid) {
- dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n");
- retval = -EBADF;
- goto FreeFcall;
- }
+ if(IS_ERR(fid))
+ return PTR_ERR(fid);
if (!v9ses->extended) {
retval = -EBADF;
dprintk(DEBUG_ERROR, "not extended\n");
- goto FreeFcall;
+ goto ClunkFid;
}
dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
@@ -1009,8 +1027,10 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
goto FreeFcall;
}
- if (!fcall)
- return -EIO;
+ if (!fcall) {
+ retval = -EIO;
+ goto ClunkFid;
+ }
if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) {
retval = -EINVAL;
@@ -1028,9 +1048,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
fcall->params.rstat.stat.extension.str, buffer);
retval = buflen;
- FreeFcall:
+FreeFcall:
kfree(fcall);
+ClunkFid:
+ v9fs_fid_clunk(v9ses, fid);
+
return retval;
}
@@ -1123,52 +1146,58 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
int err;
u32 fid, perm;
struct v9fs_session_info *v9ses;
- struct v9fs_fid *dfid, *vfid;
- struct inode *inode;
+ struct v9fs_fid *dfid, *vfid = NULL;
+ struct inode *inode = NULL;
- inode = NULL;
- vfid = NULL;
v9ses = v9fs_inode2v9ses(dir);
- dfid = v9fs_fid_lookup(dentry->d_parent);
- perm = unixmode2p9mode(v9ses, mode);
-
if (!v9ses->extended) {
dprintk(DEBUG_ERROR, "not extended\n");
return -EPERM;
}
+ dfid = v9fs_fid_clone(dentry->d_parent);
+ if(IS_ERR(dfid)) {
+ err = PTR_ERR(dfid);
+ goto error;
+ }
+
+ perm = unixmode2p9mode(v9ses, mode);
+
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
if (err)
- goto error;
+ goto clunk_dfid;
err = v9fs_t_clunk(v9ses, fid);
if (err)
- goto error;
+ goto clunk_dfid;
vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
if (IS_ERR(vfid)) {
err = PTR_ERR(vfid);
vfid = NULL;
- goto error;
+ goto clunk_dfid;
}
inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
inode = NULL;
- goto error;
+ goto free_vfid;
}
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
return 0;
-error:
- if (vfid)
- v9fs_fid_destroy(vfid);
+free_vfid:
+ v9fs_fid_destroy(vfid);
+
+clunk_dfid:
+ v9fs_fid_clunk(v9ses, dfid);
+error:
return err;
}
@@ -1209,26 +1238,29 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *dentry)
{
int retval;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
struct v9fs_fid *oldfid;
char *name;
dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
old_dentry->d_name.name);
- oldfid = v9fs_fid_lookup(old_dentry);
- if (!oldfid) {
- dprintk(DEBUG_ERROR, "can't find oldfid\n");
- return -EPERM;
- }
+ oldfid = v9fs_fid_clone(old_dentry);
+ if(IS_ERR(oldfid))
+ return PTR_ERR(oldfid);
name = __getname();
- if (unlikely(!name))
- return -ENOMEM;
+ if (unlikely(!name)) {
+ retval = -ENOMEM;
+ goto clunk_fid;
+ }
sprintf(name, "%d\n", oldfid->fid);
retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
__putname(name);
+clunk_fid:
+ v9fs_fid_clunk(v9ses, oldfid);
return retval;
}
diff --git a/fs/Kconfig b/fs/Kconfig
index b3b5aa0edff..8cd2417a14d 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -12,9 +12,7 @@ config EXT2_FS
Ext2 is a standard Linux file system for hard disks.
To compile this file system support as a module, choose M here: the
- module will be called ext2. Be aware however that the file system
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this could be dangerous.
+ module will be called ext2.
If unsure, say Y.
@@ -98,9 +96,7 @@ config EXT3_FS
(available at <http://sourceforge.net/projects/e2fsprogs/>).
To compile this file system support as a module, choose M here: the
- module will be called ext3. Be aware however that the file system
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
+ module will be called ext3.
config EXT3_FS_XATTR
bool "Ext3 extended attributes"
@@ -163,9 +159,7 @@ config EXT4DEV_FS
features will be added to ext4dev gradually.
To compile this file system support as a module, choose M here. The
- module will be called ext4dev. Be aware, however, that the filesystem
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this could be dangerous.
+ module will be called ext4dev.
If unsure, say N.
@@ -1008,7 +1002,7 @@ config TMPFS_POSIX_ACL
config HUGETLBFS
bool "HugeTLB file system support"
- depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+ depends on X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
help
hugetlbfs is a filesystem backing for HugeTLB pages, based on
ramfs. For architectures that support it, say Y here and read
@@ -1204,13 +1198,16 @@ config EFS_FS
config JFFS_FS
tristate "Journalling Flash File System (JFFS) support"
- depends on MTD && BLOCK
+ depends on MTD && BLOCK && BROKEN
help
JFFS is the Journalling Flash File System developed by Axis
Communications in Sweden, aimed at providing a crash/powerdown-safe
file system for disk-less embedded devices. Further information is
available at (<http://developer.axis.com/software/jffs/>).
+ NOTE: This filesystem is deprecated and is scheduled for removal in
+ 2.6.21. See Documentation/feature-removal-schedule.txt
+
config JFFS_FS_VERBOSE
int "JFFS debugging verbosity (0 = quiet, 3 = noisy)"
depends on JFFS_FS
diff --git a/fs/Makefile b/fs/Makefile
index 9a5ce9323bf..b9ffa63f77f 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -10,7 +10,8 @@ obj-y := open.o read_write.o file_table.o super.o \
ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
seq_file.o xattr.o libfs.o fs-writeback.o \
- pnode.o drop_caches.o splice.o sync.o utimes.o
+ pnode.o drop_caches.o splice.o sync.o utimes.o \
+ stack.o
ifeq ($(CONFIG_BLOCK),y)
obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index d3c7905b2dd..2b8903893d3 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -28,7 +28,7 @@ static DEFINE_RWLOCK(adfs_dir_lock);
static int
adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
struct object_info obj;
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
index bbfc8625927..b9b2b27b68c 100644
--- a/fs/adfs/dir_f.c
+++ b/fs/adfs/dir_f.c
@@ -53,7 +53,7 @@ static inline int adfs_readname(char *buf, char *ptr, int maxlen)
{
char *old_buf = buf;
- while (*ptr >= ' ' && maxlen--) {
+ while ((unsigned char)*ptr >= ' ' && maxlen--) {
if (*ptr == '/')
*buf++ = '.';
else
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index 5d9649fa181..cad3ee34006 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -41,7 +41,7 @@ struct inode_operations affs_dir_inode_operations = {
static int
affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
struct buffer_head *dir_bh;
struct buffer_head *fh_bh;
@@ -71,7 +71,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
stored++;
}
if (f_pos == 1) {
- if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_dentry), DT_DIR) < 0)
+ if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_path.dentry), DT_DIR) < 0)
return stored;
filp->f_pos = f_pos = 2;
stored++;
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index a6ec75c56fc..4acd0413405 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -392,10 +392,10 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
unsigned fpos;
int ret;
- _enter("{%Ld,{%lu}}", file->f_pos, file->f_dentry->d_inode->i_ino);
+ _enter("{%Ld,{%lu}}", file->f_pos, file->f_path.dentry->d_inode->i_ino);
fpos = file->f_pos;
- ret = afs_dir_iterate(file->f_dentry->d_inode, &fpos, cookie, filldir);
+ ret = afs_dir_iterate(file->f_path.dentry->d_inode, &fpos, cookie, filldir);
file->f_pos = fpos;
_leave(" = %d", ret);
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 99785a79d04..8f74e845082 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -18,7 +18,7 @@
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include "super.h"
#include "cell.h"
#include "volume.h"
@@ -136,11 +136,11 @@ static int afs_mntpt_open(struct inode *inode, struct file *file)
{
kenter("%p,%p{%p{%s},%s}",
inode, file,
- file->f_dentry->d_parent,
- file->f_dentry->d_parent ?
- file->f_dentry->d_parent->d_name.name :
+ file->f_path.dentry->d_parent,
+ file->f_path.dentry->d_parent ?
+ file->f_path.dentry->d_parent->d_name.name :
(const unsigned char *) "",
- file->f_dentry->d_name.name);
+ file->f_path.dentry->d_name.name);
return -EREMOTE;
} /* end afs_mntpt_open() */
diff --git a/fs/aio.c b/fs/aio.c
index d3a6ec2c962..55991e4132a 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -298,17 +298,23 @@ static void wait_for_all_aios(struct kioctx *ctx)
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
+ spin_lock_irq(&ctx->ctx_lock);
if (!ctx->reqs_active)
- return;
+ goto out;
add_wait_queue(&ctx->wait, &wait);
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
while (ctx->reqs_active) {
+ spin_unlock_irq(&ctx->ctx_lock);
schedule();
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ spin_lock_irq(&ctx->ctx_lock);
}
__set_task_state(tsk, TASK_RUNNING);
remove_wait_queue(&ctx->wait, &wait);
+
+out:
+ spin_unlock_irq(&ctx->ctx_lock);
}
/* wait_on_sync_kiocb:
@@ -424,7 +430,6 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
ring = kmap_atomic(ctx->ring_info.ring_pages[0], KM_USER0);
if (ctx->reqs_active < aio_ring_avail(&ctx->ring_info, ring)) {
list_add(&req->ki_list, &ctx->active_reqs);
- get_ioctx(ctx);
ctx->reqs_active++;
okay = 1;
}
@@ -536,8 +541,6 @@ int fastcall aio_put_req(struct kiocb *req)
spin_lock_irq(&ctx->ctx_lock);
ret = __aio_put_req(ctx, req);
spin_unlock_irq(&ctx->ctx_lock);
- if (ret)
- put_ioctx(ctx);
return ret;
}
@@ -586,7 +589,7 @@ static void use_mm(struct mm_struct *mm)
* Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
* it won't work. Update it accordingly if you change it here
*/
- activate_mm(active_mm, mm);
+ switch_mm(active_mm, mm, tsk);
task_unlock(tsk);
mmdrop(active_mm);
@@ -599,9 +602,6 @@ static void use_mm(struct mm_struct *mm)
* by the calling kernel thread
* (Note: this routine is intended to be called only
* from a kernel thread context)
- *
- * Comments: Called with ctx->ctx_lock held. This nests
- * task_lock instead ctx_lock.
*/
static void unuse_mm(struct mm_struct *mm)
{
@@ -782,8 +782,7 @@ static int __aio_run_iocbs(struct kioctx *ctx)
*/
iocb->ki_users++; /* grab extra reference */
aio_run_iocb(iocb);
- if (__aio_put_req(ctx, iocb)) /* drop extra ref */
- put_ioctx(ctx);
+ __aio_put_req(ctx, iocb);
}
if (!list_empty(&ctx->run_list))
return 1;
@@ -850,14 +849,16 @@ static void aio_kick_handler(struct work_struct *work)
{
struct kioctx *ctx = container_of(work, struct kioctx, wq.work);
mm_segment_t oldfs = get_fs();
+ struct mm_struct *mm;
int requeue;
set_fs(USER_DS);
use_mm(ctx->mm);
spin_lock_irq(&ctx->ctx_lock);
requeue =__aio_run_iocbs(ctx);
- unuse_mm(ctx->mm);
+ mm = ctx->mm;
spin_unlock_irq(&ctx->ctx_lock);
+ unuse_mm(mm);
set_fs(oldfs);
/*
* we're in a worker thread already, don't use queue_delayed_work,
@@ -998,14 +999,10 @@ put_rq:
/* everything turned out well, dispose of the aiocb. */
ret = __aio_put_req(ctx, iocb);
- spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-
if (waitqueue_active(&ctx->wait))
wake_up(&ctx->wait);
- if (ret)
- put_ioctx(ctx);
-
+ spin_unlock_irqrestore(&ctx->ctx_lock, flags);
return ret;
}
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 368a1c33a3c..e698c51d2b0 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -45,7 +45,7 @@ static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldi
struct autofs_dir_ent *ent = NULL;
struct autofs_dirhash *dirhash;
struct autofs_sb_info *sbi;
- struct inode * inode = filp->f_dentry->d_inode;
+ struct inode * inode = filp->f_path.dentry->d_inode;
off_t onr, nr;
lock_kernel();
@@ -557,7 +557,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
case AUTOFS_IOC_SETTIMEOUT:
return autofs_get_set_timeout(sbi, argp);
case AUTOFS_IOC_EXPIRE:
- return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
+ return autofs_expire_run(inode->i_sb, sbi, filp->f_path.mnt,
argp);
default:
return -ENOSYS;
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index b13f32c8aee..216b1a364cc 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -150,7 +150,8 @@ static inline int autofs4_ispending(struct dentry *dentry)
static inline void autofs4_copy_atime(struct file *src, struct file *dst)
{
- dst->f_dentry->d_inode->i_atime = src->f_dentry->d_inode->i_atime;
+ dst->f_path.dentry->d_inode->i_atime =
+ src->f_path.dentry->d_inode->i_atime;
return;
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 9c48250fd72..e8f6c5ad3e9 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -313,7 +313,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
struct autofs_sb_info *sbi;
struct autofs_info *ino;
- sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL);
+ sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
if ( !sbi )
goto fail_unlock;
DPRINTK("starting up, sbi = %p",sbi);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index c1493524da4..8d05b9f7578 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -74,7 +74,7 @@ struct inode_operations autofs4_dir_inode_operations = {
static int autofs4_root_readdir(struct file *file, void *dirent,
filldir_t filldir)
{
- struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
+ struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb);
int oz_mode = autofs4_oz_mode(sbi);
DPRINTK("called, filp->f_pos = %lld", file->f_pos);
@@ -95,8 +95,8 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
static int autofs4_dir_open(struct inode *inode, struct file *file)
{
- struct dentry *dentry = file->f_dentry;
- struct vfsmount *mnt = file->f_vfsmnt;
+ struct dentry *dentry = file->f_path.dentry;
+ struct vfsmount *mnt = file->f_path.mnt;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor;
int status;
@@ -172,7 +172,7 @@ out:
static int autofs4_dir_close(struct inode *inode, struct file *file)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor = file->private_data;
int status = 0;
@@ -204,7 +204,7 @@ out:
static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor = file->private_data;
int status;
@@ -858,14 +858,14 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
return autofs4_ask_reghost(sbi, p);
case AUTOFS_IOC_ASKUMOUNT:
- return autofs4_ask_umount(filp->f_vfsmnt, p);
+ return autofs4_ask_umount(filp->f_path.mnt, p);
/* return a single thing to expire */
case AUTOFS_IOC_EXPIRE:
- return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p);
+ return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p);
/* same as above, but can send multiple expires through pipe */
case AUTOFS_IOC_EXPIRE_MULTI:
- return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p);
+ return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p);
default:
return -ENOSYS;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 34e6d7b220c..869f5193ecc 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -14,59 +14,307 @@
#include <linux/time.h>
#include <linux/smp_lock.h>
#include <linux/namei.h>
+#include <linux/poll.h>
-static int return_EIO(void)
+
+static loff_t bad_file_llseek(struct file *file, loff_t offset, int origin)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_read(struct file *filp, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_write(struct file *filp, const char __user *buf,
+ size_t siz, loff_t *ppos)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ return -EIO;
+}
+
+static int bad_file_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ return -EIO;
+}
+
+static unsigned int bad_file_poll(struct file *filp, poll_table *wait)
+{
+ return POLLERR;
+}
+
+static int bad_file_ioctl (struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ return -EIO;
+}
+
+static long bad_file_unlocked_ioctl(struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ return -EIO;
+}
+
+static long bad_file_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return -EIO;
+}
+
+static int bad_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ return -EIO;
+}
+
+static int bad_file_open(struct inode *inode, struct file *filp)
+{
+ return -EIO;
+}
+
+static int bad_file_flush(struct file *file, fl_owner_t id)
+{
+ return -EIO;
+}
+
+static int bad_file_release(struct inode *inode, struct file *filp)
+{
+ return -EIO;
+}
+
+static int bad_file_fsync(struct file *file, struct dentry *dentry,
+ int datasync)
+{
+ return -EIO;
+}
+
+static int bad_file_aio_fsync(struct kiocb *iocb, int datasync)
+{
+ return -EIO;
+}
+
+static int bad_file_fasync(int fd, struct file *filp, int on)
+{
+ return -EIO;
+}
+
+static int bad_file_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_sendfile(struct file *in_file, loff_t *ppos,
+ size_t count, read_actor_t actor, void *target)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_sendpage(struct file *file, struct page *page,
+ int off, size_t len, loff_t *pos, int more)
+{
+ return -EIO;
+}
+
+static unsigned long bad_file_get_unmapped_area(struct file *file,
+ unsigned long addr, unsigned long len,
+ unsigned long pgoff, unsigned long flags)
+{
+ return -EIO;
+}
+
+static int bad_file_check_flags(int flags)
{
return -EIO;
}
-#define EIO_ERROR ((void *) (return_EIO))
+static int bad_file_dir_notify(struct file *file, unsigned long arg)
+{
+ return -EIO;
+}
+
+static int bad_file_flock(struct file *filp, int cmd, struct file_lock *fl)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_splice_write(struct pipe_inode_info *pipe,
+ struct file *out, loff_t *ppos, size_t len,
+ unsigned int flags)
+{
+ return -EIO;
+}
+
+static ssize_t bad_file_splice_read(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
+{
+ return -EIO;
+}
static const struct file_operations bad_file_ops =
{
- .llseek = EIO_ERROR,
- .aio_read = EIO_ERROR,
- .read = EIO_ERROR,
- .write = EIO_ERROR,
- .aio_write = EIO_ERROR,
- .readdir = EIO_ERROR,
- .poll = EIO_ERROR,
- .ioctl = EIO_ERROR,
- .mmap = EIO_ERROR,
- .open = EIO_ERROR,
- .flush = EIO_ERROR,
- .release = EIO_ERROR,
- .fsync = EIO_ERROR,
- .aio_fsync = EIO_ERROR,
- .fasync = EIO_ERROR,
- .lock = EIO_ERROR,
- .sendfile = EIO_ERROR,
- .sendpage = EIO_ERROR,
- .get_unmapped_area = EIO_ERROR,
+ .llseek = bad_file_llseek,
+ .read = bad_file_read,
+ .write = bad_file_write,
+ .aio_read = bad_file_aio_read,
+ .aio_write = bad_file_aio_write,
+ .readdir = bad_file_readdir,
+ .poll = bad_file_poll,
+ .ioctl = bad_file_ioctl,
+ .unlocked_ioctl = bad_file_unlocked_ioctl,
+ .compat_ioctl = bad_file_compat_ioctl,
+ .mmap = bad_file_mmap,
+ .open = bad_file_open,
+ .flush = bad_file_flush,
+ .release = bad_file_release,
+ .fsync = bad_file_fsync,
+ .aio_fsync = bad_file_aio_fsync,
+ .fasync = bad_file_fasync,
+ .lock = bad_file_lock,
+ .sendfile = bad_file_sendfile,
+ .sendpage = bad_file_sendpage,
+ .get_unmapped_area = bad_file_get_unmapped_area,
+ .check_flags = bad_file_check_flags,
+ .dir_notify = bad_file_dir_notify,
+ .flock = bad_file_flock,
+ .splice_write = bad_file_splice_write,
+ .splice_read = bad_file_splice_read,
};
+static int bad_inode_create (struct inode *dir, struct dentry *dentry,
+ int mode, struct nameidata *nd)
+{
+ return -EIO;
+}
+
+static struct dentry *bad_inode_lookup(struct inode *dir,
+ struct dentry *dentry, struct nameidata *nd)
+{
+ return ERR_PTR(-EIO);
+}
+
+static int bad_inode_link (struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+{
+ return -EIO;
+}
+
+static int bad_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+ return -EIO;
+}
+
+static int bad_inode_symlink (struct inode *dir, struct dentry *dentry,
+ const char *symname)
+{
+ return -EIO;
+}
+
+static int bad_inode_mkdir(struct inode *dir, struct dentry *dentry,
+ int mode)
+{
+ return -EIO;
+}
+
+static int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
+{
+ return -EIO;
+}
+
+static int bad_inode_mknod (struct inode *dir, struct dentry *dentry,
+ int mode, dev_t rdev)
+{
+ return -EIO;
+}
+
+static int bad_inode_rename (struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ return -EIO;
+}
+
+static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
+ int buflen)
+{
+ return -EIO;
+}
+
+static int bad_inode_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ return -EIO;
+}
+
+static int bad_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ return -EIO;
+}
+
+static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
+{
+ return -EIO;
+}
+
+static int bad_inode_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ return -EIO;
+}
+
+static ssize_t bad_inode_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size)
+{
+ return -EIO;
+}
+
+static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
+ size_t buffer_size)
+{
+ return -EIO;
+}
+
+static int bad_inode_removexattr(struct dentry *dentry, const char *name)
+{
+ return -EIO;
+}
+
static struct inode_operations bad_inode_ops =
{
- .create = EIO_ERROR,
- .lookup = EIO_ERROR,
- .link = EIO_ERROR,
- .unlink = EIO_ERROR,
- .symlink = EIO_ERROR,
- .mkdir = EIO_ERROR,
- .rmdir = EIO_ERROR,
- .mknod = EIO_ERROR,
- .rename = EIO_ERROR,
- .readlink = EIO_ERROR,
+ .create = bad_inode_create,
+ .lookup = bad_inode_lookup,
+ .link = bad_inode_link,
+ .unlink = bad_inode_unlink,
+ .symlink = bad_inode_symlink,
+ .mkdir = bad_inode_mkdir,
+ .rmdir = bad_inode_rmdir,
+ .mknod = bad_inode_mknod,
+ .rename = bad_inode_rename,
+ .readlink = bad_inode_readlink,
/* follow_link must be no-op, otherwise unmounting this inode
won't work */
- .truncate = EIO_ERROR,
- .permission = EIO_ERROR,
- .getattr = EIO_ERROR,
- .setattr = EIO_ERROR,
- .setxattr = EIO_ERROR,
- .getxattr = EIO_ERROR,
- .listxattr = EIO_ERROR,
- .removexattr = EIO_ERROR,
+ /* put_link returns void */
+ /* truncate returns void */
+ .permission = bad_inode_permission,
+ .getattr = bad_inode_getattr,
+ .setattr = bad_inode_setattr,
+ .setxattr = bad_inode_setxattr,
+ .getxattr = bad_inode_getxattr,
+ .listxattr = bad_inode_listxattr,
+ .removexattr = bad_inode_removexattr,
+ /* truncate_range returns void */
};
@@ -88,7 +336,7 @@ static struct inode_operations bad_inode_ops =
* on it to fail from this point on.
*/
-void make_bad_inode(struct inode * inode)
+void make_bad_inode(struct inode *inode)
{
remove_inode_hash(inode);
@@ -113,7 +361,7 @@ EXPORT_SYMBOL(make_bad_inode);
* Returns true if the inode in question has been marked as bad.
*/
-int is_bad_inode(struct inode * inode)
+int is_bad_inode(struct inode *inode)
{
return (inode->i_op == &bad_inode_ops);
}
diff --git a/fs/befs/btree.c b/fs/befs/btree.c
index 81b042ee24e..af5bb93276f 100644
--- a/fs/befs/btree.c
+++ b/fs/befs/btree.c
@@ -260,7 +260,7 @@ befs_btree_find(struct super_block *sb, befs_data_stream * ds,
goto error;
}
- this_node = (befs_btree_node *) kmalloc(sizeof (befs_btree_node),
+ this_node = kmalloc(sizeof (befs_btree_node),
GFP_NOFS);
if (!this_node) {
befs_error(sb, "befs_btree_find() failed to allocate %u "
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index e831a8f3084..b8e304a0661 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -28,7 +28,7 @@ void
befs_error(const struct super_block *sb, const char *fmt, ...)
{
va_list args;
- char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+ char *err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
if (err_buf == NULL) {
printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
return;
@@ -46,7 +46,7 @@ void
befs_warning(const struct super_block *sb, const char *fmt, ...)
{
va_list args;
- char *err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+ char *err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
if (err_buf == NULL) {
printk(KERN_ERR "could not allocate %d bytes\n", ERRBUFSIZE);
return;
@@ -70,7 +70,7 @@ befs_debug(const struct super_block *sb, const char *fmt, ...)
char *err_buf = NULL;
if (BEFS_SB(sb)->mount_opts.debug) {
- err_buf = (char *) kmalloc(ERRBUFSIZE, GFP_KERNEL);
+ err_buf = kmalloc(ERRBUFSIZE, GFP_KERNEL);
if (err_buf == NULL) {
printk(KERN_ERR "could not allocate %d bytes\n",
ERRBUFSIZE);
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index bce402eee55..481e59b9d91 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -212,7 +212,7 @@ befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
static int
befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
befs_off_t value;
@@ -222,7 +222,7 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
char keybuf[BEFS_NAME_LEN + 1];
char *nlsname;
int nlsnamelen;
- const char *dirname = filp->f_dentry->d_name.name;
+ const char *dirname = filp->f_path.dentry->d_name.name;
befs_debug(sb, "---> befs_readdir() "
"name %s, inode %ld, filp->f_pos %Ld",
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index a650f1d0b85..2a746e688df 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -27,7 +27,7 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
{
- struct inode * dir = f->f_dentry->d_inode;
+ struct inode * dir = f->f_path.dentry->d_inode;
struct buffer_head * bh;
struct bfs_dirent * de;
unsigned int offset;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index eac175ed9f4..134c99941a6 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -1,7 +1,7 @@
/*
* fs/bfs/inode.c
* BFS superblock and inode operations.
- * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ * Copyright (C) 1999-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
* From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
*
* Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
@@ -18,7 +18,7 @@
#include <asm/uaccess.h>
#include "bfs.h"
-MODULE_AUTHOR("Tigran A. Aivazian <tigran@veritas.com>");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
MODULE_LICENSE("GPL");
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 517e111bb7e..813a887cd2b 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -274,7 +274,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
N_TRSIZE(ex) || N_DRSIZE(ex) ||
- i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+ i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
return -ENOEXEC;
}
@@ -389,7 +389,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
printk(KERN_WARNING
"fd_offset is not page aligned. Please convert program: %s\n",
- bprm->file->f_dentry->d_name.name);
+ bprm->file->f_path.dentry->d_name.name);
error_time = jiffies;
}
@@ -469,7 +469,7 @@ static int load_aout_library(struct file *file)
int retval;
struct exec ex;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
retval = -ENOEXEC;
error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
@@ -506,7 +506,7 @@ static int load_aout_library(struct file *file)
{
printk(KERN_WARNING
"N_TXTOFF is not page aligned. Please convert library: %s\n",
- file->f_dentry->d_name.name);
+ file->f_path.dentry->d_name.name);
error_time = jiffies;
}
down_write(&current->mm->mmap_sem);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index be5869d3499..669dbe5b031 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -682,6 +682,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
retval = PTR_ERR(interpreter);
if (IS_ERR(interpreter))
goto out_free_interp;
+
+ /*
+ * If the binary is not readable then enforce
+ * mm->dumpable = 0 regardless of the interpreter's
+ * permissions.
+ */
+ if (file_permission(interpreter, MAY_READ) < 0)
+ bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
retval = kernel_read(interpreter, 0, bprm->buf,
BINPRM_BUF_SIZE);
if (retval != BINPRM_BUF_SIZE) {
@@ -854,13 +863,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
* default mmap base, as well as whatever program they
* might try to exec. This is because the brk will
* follow the loader, and is not movable. */
- if (current->flags & PF_RANDOMIZE)
- load_bias = randomize_range(0x10000,
- ELF_ET_DYN_BASE,
- 0);
- else
- load_bias = ELF_ET_DYN_BASE;
- load_bias = ELF_PAGESTART(load_bias - vaddr);
+ load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
}
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
@@ -1184,13 +1187,17 @@ static int dump_seek(struct file *file, loff_t off)
*/
static int maydump(struct vm_area_struct *vma)
{
+ /* The vma can be set up to tell us the answer directly. */
+ if (vma->vm_flags & VM_ALWAYSDUMP)
+ return 1;
+
/* 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;
+ return vma->vm_file->f_path.dentry->d_inode->i_nlink == 0;
/* If it hasn't been written to, don't write it out */
if (!vma->anon_vma)
@@ -1317,7 +1324,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_pid = p->pid;
prstatus->pr_ppid = p->parent->pid;
prstatus->pr_pgrp = process_group(p);
- prstatus->pr_sid = p->signal->session;
+ prstatus->pr_sid = process_session(p);
if (thread_group_leader(p)) {
/*
* This is the record for the group leader. Add in the
@@ -1363,7 +1370,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_pid = p->pid;
psinfo->pr_ppid = p->parent->pid;
psinfo->pr_pgrp = process_group(p);
- psinfo->pr_sid = p->signal->session;
+ psinfo->pr_sid = process_session(p);
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
@@ -1430,6 +1437,32 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
return sz;
}
+static struct vm_area_struct *first_vma(struct task_struct *tsk,
+ struct vm_area_struct *gate_vma)
+{
+ struct vm_area_struct *ret = tsk->mm->mmap;
+
+ if (ret)
+ return ret;
+ return gate_vma;
+}
+/*
+ * Helper function for iterating across a vma list. It ensures that the caller
+ * will visit `gate_vma' prior to terminating the search.
+ */
+static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
+ struct vm_area_struct *gate_vma)
+{
+ struct vm_area_struct *ret;
+
+ ret = this_vma->vm_next;
+ if (ret)
+ return ret;
+ if (this_vma == gate_vma)
+ return NULL;
+ return gate_vma;
+}
+
/*
* Actual dumper
*
@@ -1445,7 +1478,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
int segs;
size_t size = 0;
int i;
- struct vm_area_struct *vma;
+ struct vm_area_struct *vma, *gate_vma;
struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff, foffset;
unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
@@ -1531,6 +1564,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
segs += ELF_CORE_EXTRA_PHDRS;
#endif
+ gate_vma = get_gate_vma(current);
+ if (gate_vma != NULL)
+ segs++;
+
/* Set up header */
fill_elf_header(elf, segs + 1); /* including notes section */
@@ -1598,7 +1635,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
/* Write program headers for segments dump */
- for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+ for (vma = first_vma(current, gate_vma); vma != NULL;
+ vma = next_vma(vma, gate_vma)) {
struct elf_phdr phdr;
size_t sz;
@@ -1647,7 +1685,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
/* Align to page */
DUMP_SEEK(dataoff - foffset);
- for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+ for (vma = first_vma(current, gate_vma); vma != NULL;
+ vma = next_vma(vma, gate_vma)) {
unsigned long addr;
if (!maydump(vma))
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index ed9a61c6beb..a4d933a5120 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -234,6 +234,14 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
goto error;
}
+ /*
+ * If the binary is not readable then enforce
+ * mm->dumpable = 0 regardless of the interpreter's
+ * permissions.
+ */
+ if (file_permission(interpreter, MAY_READ) < 0)
+ bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
retval = kernel_read(interpreter, 0, bprm->buf,
BINPRM_BUF_SIZE);
if (retval < 0)
@@ -706,12 +714,11 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
return -ELIBBAD;
size = sizeof(*loadmap) + nloads * sizeof(*seg);
- loadmap = kmalloc(size, GFP_KERNEL);
+ loadmap = kzalloc(size, GFP_KERNEL);
if (!loadmap)
return -ENOMEM;
params->loadmap = loadmap;
- memset(loadmap, 0, size);
loadmap->version = ELF32_FDPIC_LOADMAP_VERSION;
loadmap->nsegs = nloads;
@@ -855,7 +862,7 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
dynamic_error:
printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
- what, file->f_dentry->d_inode->i_ino);
+ what, file->f_path.dentry->d_inode->i_ino);
return -ELIBBAD;
}
@@ -1186,7 +1193,7 @@ static int maydump(struct vm_area_struct *vma)
/* Dump shared memory only if mapped from an anonymous file. */
if (vma->vm_flags & VM_SHARED) {
- if (vma->vm_file->f_dentry->d_inode->i_nlink == 0) {
+ if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) {
kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
return 1;
}
@@ -1322,7 +1329,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_pid = p->pid;
prstatus->pr_ppid = p->parent->pid;
prstatus->pr_pgrp = process_group(p);
- prstatus->pr_sid = p->signal->session;
+ prstatus->pr_sid = process_session(p);
if (thread_group_leader(p)) {
/*
* This is the record for the group leader. Add in the
@@ -1371,7 +1378,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_pid = p->pid;
psinfo->pr_ppid = p->parent->pid;
psinfo->pr_pgrp = process_group(p);
- psinfo->pr_sid = p->signal->session;
+ psinfo->pr_sid = process_session(p);
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index a62fd4018a2..ae8595d4985 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -429,7 +429,7 @@ static int load_flat_file(struct linux_binprm * bprm,
int ret;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
- inode = bprm->file->f_dentry->d_inode;
+ inode = bprm->file->f_path.dentry->d_inode;
text_len = ntohl(hdr->data_start);
data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 1713c48fef5..c2e08252af3 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -311,7 +311,7 @@ static Node *create_entry(const char __user *buffer, size_t count)
err = -ENOMEM;
memsize = sizeof(Node) + count + 8;
- e = (Node *) kmalloc(memsize, GFP_USER);
+ e = kmalloc(memsize, GFP_USER);
if (!e)
goto out;
@@ -542,7 +542,7 @@ static void kill_node(Node *e)
static ssize_t
bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
{
- Node *e = file->f_dentry->d_inode->i_private;
+ Node *e = file->f_path.dentry->d_inode->i_private;
loff_t pos = *ppos;
ssize_t res;
char *page;
@@ -576,7 +576,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
struct dentry *root;
- Node *e = file->f_dentry->d_inode->i_private;
+ Node *e = file->f_path.dentry->d_inode->i_private;
int res = parse_command(buffer, count);
switch (res) {
@@ -584,7 +584,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
break;
case 2: set_bit(Enabled, &e->flags);
break;
- case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
+ case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
mutex_lock(&root->d_inode->i_mutex);
kill_node(e);
@@ -610,7 +610,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
Node *e;
struct inode *inode;
struct dentry *root, *dentry;
- struct super_block *sb = file->f_vfsmnt->mnt_sb;
+ struct super_block *sb = file->f_path.mnt->mnt_sb;
int err = 0;
e = create_entry(buffer, count);
@@ -699,7 +699,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
switch (res) {
case 1: enabled = 0; break;
case 2: enabled = 1; break;
- case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
+ case 3: root = dget(file->f_path.mnt->mnt_sb->s_root);
mutex_lock(&root->d_inode->i_mutex);
while (!list_empty(&entries))
diff --git a/fs/bio.c b/fs/bio.c
index 7ec737eda72..7618bcb1836 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -916,7 +916,7 @@ void bio_set_pages_dirty(struct bio *bio)
}
}
-static void bio_release_pages(struct bio *bio)
+void bio_release_pages(struct bio *bio)
{
struct bio_vec *bvec = bio->bi_io_vec;
int i;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 13816b4d76f..fc7028b685f 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -168,6 +168,203 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
iov, offset, nr_segs, blkdev_get_blocks, NULL);
}
+#if 0
+static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error)
+{
+ struct kiocb *iocb = bio->bi_private;
+ atomic_t *bio_count = &iocb->ki_bio_count;
+
+ if (bio_data_dir(bio) == READ)
+ bio_check_pages_dirty(bio);
+ else {
+ bio_release_pages(bio);
+ bio_put(bio);
+ }
+
+ /* iocb->ki_nbytes stores error code from LLDD */
+ if (error)
+ iocb->ki_nbytes = -EIO;
+
+ if (atomic_dec_and_test(bio_count)) {
+ if ((long)iocb->ki_nbytes < 0)
+ aio_complete(iocb, iocb->ki_nbytes, 0);
+ else
+ aio_complete(iocb, iocb->ki_left, 0);
+ }
+
+ return 0;
+}
+
+#define VEC_SIZE 16
+struct pvec {
+ unsigned short nr;
+ unsigned short idx;
+ struct page *page[VEC_SIZE];
+};
+
+#define PAGES_SPANNED(addr, len) \
+ (DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE);
+
+/*
+ * get page pointer for user addr, we internally cache struct page array for
+ * (addr, count) range in pvec to avoid frequent call to get_user_pages. If
+ * internal page list is exhausted, a batch count of up to VEC_SIZE is used
+ * to get next set of page struct.
+ */
+static struct page *blk_get_page(unsigned long addr, size_t count, int rw,
+ struct pvec *pvec)
+{
+ int ret, nr_pages;
+ if (pvec->idx == pvec->nr) {
+ nr_pages = PAGES_SPANNED(addr, count);
+ nr_pages = min(nr_pages, VEC_SIZE);
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, addr, nr_pages,
+ rw == READ, 0, pvec->page, NULL);
+ up_read(&current->mm->mmap_sem);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ pvec->nr = ret;
+ pvec->idx = 0;
+ }
+ return pvec->page[pvec->idx++];
+}
+
+/* return a page back to pvec array */
+static void blk_unget_page(struct page *page, struct pvec *pvec)
+{
+ pvec->page[--pvec->idx] = page;
+}
+
+static ssize_t
+blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+ loff_t pos, unsigned long nr_segs)
+{
+ struct inode *inode = iocb->ki_filp->f_mapping->host;
+ unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode)));
+ unsigned blocksize_mask = (1 << blkbits) - 1;
+ unsigned long seg = 0; /* iov segment iterator */
+ unsigned long nvec; /* number of bio vec needed */
+ unsigned long cur_off; /* offset into current page */
+ unsigned long cur_len; /* I/O len of current page, up to PAGE_SIZE */
+
+ unsigned long addr; /* user iovec address */
+ size_t count; /* user iovec len */
+ size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */
+ loff_t size; /* size of block device */
+ struct bio *bio;
+ atomic_t *bio_count = &iocb->ki_bio_count;
+ struct page *page;
+ struct pvec pvec;
+
+ pvec.nr = 0;
+ pvec.idx = 0;
+
+ if (pos & blocksize_mask)
+ return -EINVAL;
+
+ size = i_size_read(inode);
+ if (pos + nbytes > size) {
+ nbytes = size - pos;
+ iocb->ki_left = nbytes;
+ }
+
+ /*
+ * check first non-zero iov alignment, the remaining
+ * iov alignment is checked inside bio loop below.
+ */
+ do {
+ addr = (unsigned long) iov[seg].iov_base;
+ count = min(iov[seg].iov_len, nbytes);
+ if (addr & blocksize_mask || count & blocksize_mask)
+ return -EINVAL;
+ } while (!count && ++seg < nr_segs);
+ atomic_set(bio_count, 1);
+
+ while (nbytes) {
+ /* roughly estimate number of bio vec needed */
+ nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE;
+ nvec = max(nvec, nr_segs - seg);
+ nvec = min(nvec, (unsigned long) BIO_MAX_PAGES);
+
+ /* bio_alloc should not fail with GFP_KERNEL flag */
+ bio = bio_alloc(GFP_KERNEL, nvec);
+ bio->bi_bdev = I_BDEV(inode);
+ bio->bi_end_io = blk_end_aio;
+ bio->bi_private = iocb;
+ bio->bi_sector = pos >> blkbits;
+same_bio:
+ cur_off = addr & ~PAGE_MASK;
+ cur_len = PAGE_SIZE - cur_off;
+ if (count < cur_len)
+ cur_len = count;
+
+ page = blk_get_page(addr, count, rw, &pvec);
+ if (unlikely(IS_ERR(page)))
+ goto backout;
+
+ if (bio_add_page(bio, page, cur_len, cur_off)) {
+ pos += cur_len;
+ addr += cur_len;
+ count -= cur_len;
+ nbytes -= cur_len;
+
+ if (count)
+ goto same_bio;
+ while (++seg < nr_segs) {
+ addr = (unsigned long) iov[seg].iov_base;
+ count = iov[seg].iov_len;
+ if (!count)
+ continue;
+ if (unlikely(addr & blocksize_mask ||
+ count & blocksize_mask)) {
+ page = ERR_PTR(-EINVAL);
+ goto backout;
+ }
+ count = min(count, nbytes);
+ goto same_bio;
+ }
+ } else {
+ blk_unget_page(page, &pvec);
+ }
+
+ /* bio is ready, submit it */
+ if (rw == READ)
+ bio_set_pages_dirty(bio);
+ atomic_inc(bio_count);
+ submit_bio(rw, bio);
+ }
+
+completion:
+ iocb->ki_left -= nbytes;
+ nbytes = iocb->ki_left;
+ iocb->ki_pos += nbytes;
+
+ blk_run_address_space(inode->i_mapping);
+ if (atomic_dec_and_test(bio_count))
+ aio_complete(iocb, nbytes, 0);
+
+ return -EIOCBQUEUED;
+
+backout:
+ /*
+ * back out nbytes count constructed so far for this bio,
+ * we will throw away current bio.
+ */
+ nbytes += bio->bi_size;
+ bio_release_pages(bio);
+ bio_put(bio);
+
+ /*
+ * if no bio was submmitted, return the error code.
+ * otherwise, proceed with pending I/O completion.
+ */
+ if (atomic_read(bio_count) == 1)
+ return PTR_ERR(page);
+ goto completion;
+}
+#endif
+
static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, blkdev_get_block, wbc);
@@ -190,7 +387,7 @@ static int blkdev_commit_write(struct file *file, struct page *page, unsigned fr
/*
* private llseek:
- * for a block special file file->f_dentry->d_inode->i_size is zero
+ * for a block special file file->f_path.dentry->d_inode->i_size is zero
* so we compute the size by hand (just as in block_read/write above)
*/
static loff_t block_llseek(struct file *file, loff_t offset, int origin)
@@ -263,7 +460,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
{
memset(bdev, 0, sizeof(*bdev));
mutex_init(&bdev->bd_mutex);
- mutex_init(&bdev->bd_mount_mutex);
+ sema_init(&bdev->bd_mount_sem, 1);
INIT_LIST_HEAD(&bdev->bd_inodes);
INIT_LIST_HEAD(&bdev->bd_list);
#ifdef CONFIG_SYSFS
@@ -762,7 +959,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
if (!bo)
return -ENOMEM;
- mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
+ mutex_lock(&bdev->bd_mutex);
res = bd_claim(bdev, holder);
if (res == 0) {
found = find_bd_holder(bdev, bo);
@@ -796,7 +993,7 @@ static void bd_release_from_kobject(struct block_device *bdev,
if (!kobj)
return;
- mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION);
+ mutex_lock(&bdev->bd_mutex);
bd_release(bdev);
if ((bo = del_bd_holder(bdev, kobj)))
free_bd_holder(bo);
@@ -854,22 +1051,6 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode)
EXPORT_SYMBOL(open_by_devnum);
-static int
-blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags);
-
-struct block_device *open_partition_by_devnum(dev_t dev, unsigned mode)
-{
- struct block_device *bdev = bdget(dev);
- int err = -ENOMEM;
- int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY;
- if (bdev)
- err = blkdev_get_partition(bdev, mode, flags);
- return err ? ERR_PTR(err) : bdev;
-}
-
-EXPORT_SYMBOL(open_partition_by_devnum);
-
-
/*
* This routine checks whether a removable media has been changed,
* and invalidates all buffer-cache-entries in that case. This
@@ -916,66 +1097,11 @@ void bd_set_size(struct block_device *bdev, loff_t size)
}
EXPORT_SYMBOL(bd_set_size);
-static int __blkdev_put(struct block_device *bdev, unsigned int subclass)
-{
- int ret = 0;
- struct inode *bd_inode = bdev->bd_inode;
- struct gendisk *disk = bdev->bd_disk;
-
- mutex_lock_nested(&bdev->bd_mutex, subclass);
- lock_kernel();
- if (!--bdev->bd_openers) {
- sync_blockdev(bdev);
- kill_bdev(bdev);
- }
- if (bdev->bd_contains == bdev) {
- if (disk->fops->release)
- ret = disk->fops->release(bd_inode, NULL);
- } else {
- mutex_lock_nested(&bdev->bd_contains->bd_mutex,
- subclass + 1);
- bdev->bd_contains->bd_part_count--;
- mutex_unlock(&bdev->bd_contains->bd_mutex);
- }
- if (!bdev->bd_openers) {
- struct module *owner = disk->fops->owner;
-
- put_disk(disk);
- module_put(owner);
-
- if (bdev->bd_contains != bdev) {
- kobject_put(&bdev->bd_part->kobj);
- bdev->bd_part = NULL;
- }
- bdev->bd_disk = NULL;
- bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
- if (bdev != bdev->bd_contains)
- __blkdev_put(bdev->bd_contains, subclass + 1);
- bdev->bd_contains = NULL;
- }
- unlock_kernel();
- mutex_unlock(&bdev->bd_mutex);
- bdput(bdev);
- return ret;
-}
-
-int blkdev_put(struct block_device *bdev)
-{
- return __blkdev_put(bdev, BD_MUTEX_NORMAL);
-}
-EXPORT_SYMBOL(blkdev_put);
+static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+ int for_part);
+static int __blkdev_put(struct block_device *bdev, int for_part);
-int blkdev_put_partition(struct block_device *bdev)
-{
- return __blkdev_put(bdev, BD_MUTEX_PARTITION);
-}
-EXPORT_SYMBOL(blkdev_put_partition);
-
-static int
-blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags);
-
-static int
-do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
+static int do_open(struct block_device *bdev, struct file *file, int for_part)
{
struct module *owner = NULL;
struct gendisk *disk;
@@ -992,8 +1118,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
}
owner = disk->fops->owner;
- mutex_lock_nested(&bdev->bd_mutex, subclass);
-
+ mutex_lock_nested(&bdev->bd_mutex, for_part);
if (!bdev->bd_openers) {
bdev->bd_disk = disk;
bdev->bd_contains = bdev;
@@ -1020,25 +1145,21 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
ret = -ENOMEM;
if (!whole)
goto out_first;
- ret = blkdev_get_whole(whole, file->f_mode, file->f_flags);
+ BUG_ON(for_part);
+ ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1);
if (ret)
goto out_first;
bdev->bd_contains = whole;
- mutex_lock_nested(&whole->bd_mutex, BD_MUTEX_WHOLE);
- whole->bd_part_count++;
p = disk->part[part - 1];
bdev->bd_inode->i_data.backing_dev_info =
whole->bd_inode->i_data.backing_dev_info;
if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) {
- whole->bd_part_count--;
- mutex_unlock(&whole->bd_mutex);
ret = -ENXIO;
goto out_first;
}
kobject_get(&p->kobj);
bdev->bd_part = p;
bd_set_size(bdev, (loff_t) p->nr_sects << 9);
- mutex_unlock(&whole->bd_mutex);
}
} else {
put_disk(disk);
@@ -1051,14 +1172,11 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass)
}
if (bdev->bd_invalidated)
rescan_partitions(bdev->bd_disk, bdev);
- } else {
- mutex_lock_nested(&bdev->bd_contains->bd_mutex,
- BD_MUTEX_WHOLE);
- bdev->bd_contains->bd_part_count++;
- mutex_unlock(&bdev->bd_contains->bd_mutex);
}
}
bdev->bd_openers++;
+ if (for_part)
+ bdev->bd_part_count++;
mutex_unlock(&bdev->bd_mutex);
unlock_kernel();
return 0;
@@ -1067,7 +1185,7 @@ out_first:
bdev->bd_disk = NULL;
bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
if (bdev != bdev->bd_contains)
- __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE);
+ __blkdev_put(bdev->bd_contains, 1);
bdev->bd_contains = NULL;
put_disk(disk);
module_put(owner);
@@ -1079,7 +1197,8 @@ out:
return ret;
}
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
+static int __blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags,
+ int for_part)
{
/*
* This crockload is due to bad choice of ->open() type.
@@ -1091,51 +1210,17 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
struct dentry fake_dentry = {};
fake_file.f_mode = mode;
fake_file.f_flags = flags;
- fake_file.f_dentry = &fake_dentry;
+ fake_file.f_path.dentry = &fake_dentry;
fake_dentry.d_inode = bdev->bd_inode;
- return do_open(bdev, &fake_file, BD_MUTEX_NORMAL);
+ return do_open(bdev, &fake_file, for_part);
}
-EXPORT_SYMBOL(blkdev_get);
-
-static int
-blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags)
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags)
{
- /*
- * This crockload is due to bad choice of ->open() type.
- * It will go away.
- * For now, block device ->open() routine must _not_
- * examine anything in 'inode' argument except ->i_rdev.
- */
- struct file fake_file = {};
- struct dentry fake_dentry = {};
- fake_file.f_mode = mode;
- fake_file.f_flags = flags;
- fake_file.f_dentry = &fake_dentry;
- fake_dentry.d_inode = bdev->bd_inode;
-
- return do_open(bdev, &fake_file, BD_MUTEX_WHOLE);
-}
-
-static int
-blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags)
-{
- /*
- * This crockload is due to bad choice of ->open() type.
- * It will go away.
- * For now, block device ->open() routine must _not_
- * examine anything in 'inode' argument except ->i_rdev.
- */
- struct file fake_file = {};
- struct dentry fake_dentry = {};
- fake_file.f_mode = mode;
- fake_file.f_flags = flags;
- fake_file.f_dentry = &fake_dentry;
- fake_dentry.d_inode = bdev->bd_inode;
-
- return do_open(bdev, &fake_file, BD_MUTEX_PARTITION);
+ return __blkdev_get(bdev, mode, flags, 0);
}
+EXPORT_SYMBOL(blkdev_get);
static int blkdev_open(struct inode * inode, struct file * filp)
{
@@ -1154,7 +1239,7 @@ static int blkdev_open(struct inode * inode, struct file * filp)
if (bdev == NULL)
return -ENOMEM;
- res = do_open(bdev, filp, BD_MUTEX_NORMAL);
+ res = do_open(bdev, filp, 0);
if (res)
return res;
@@ -1168,6 +1253,56 @@ static int blkdev_open(struct inode * inode, struct file * filp)
return res;
}
+static int __blkdev_put(struct block_device *bdev, int for_part)
+{
+ int ret = 0;
+ struct inode *bd_inode = bdev->bd_inode;
+ struct gendisk *disk = bdev->bd_disk;
+ struct block_device *victim = NULL;
+
+ mutex_lock_nested(&bdev->bd_mutex, for_part);
+ lock_kernel();
+ if (for_part)
+ bdev->bd_part_count--;
+
+ if (!--bdev->bd_openers) {
+ sync_blockdev(bdev);
+ kill_bdev(bdev);
+ }
+ if (bdev->bd_contains == bdev) {
+ if (disk->fops->release)
+ ret = disk->fops->release(bd_inode, NULL);
+ }
+ if (!bdev->bd_openers) {
+ struct module *owner = disk->fops->owner;
+
+ put_disk(disk);
+ module_put(owner);
+
+ if (bdev->bd_contains != bdev) {
+ kobject_put(&bdev->bd_part->kobj);
+ bdev->bd_part = NULL;
+ }
+ bdev->bd_disk = NULL;
+ bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
+ if (bdev != bdev->bd_contains)
+ victim = bdev->bd_contains;
+ bdev->bd_contains = NULL;
+ }
+ unlock_kernel();
+ mutex_unlock(&bdev->bd_mutex);
+ bdput(bdev);
+ if (victim)
+ __blkdev_put(victim, 1);
+ return ret;
+}
+
+int blkdev_put(struct block_device *bdev)
+{
+ return __blkdev_put(bdev, 0);
+}
+EXPORT_SYMBOL(blkdev_put);
+
static int blkdev_close(struct inode * inode, struct file * filp)
{
struct block_device *bdev = I_BDEV(filp->f_mapping->host);
diff --git a/fs/buffer.c b/fs/buffer.c
index 517860f2d75..1ad674fd348 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -35,6 +35,7 @@
#include <linux/hash.h>
#include <linux/suspend.h>
#include <linux/buffer_head.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/bio.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
@@ -179,7 +180,7 @@ int fsync_bdev(struct block_device *bdev)
* freeze_bdev -- lock a filesystem and force it into a consistent state
* @bdev: blockdevice to lock
*
- * This takes the block device bd_mount_mutex to make sure no new mounts
+ * This takes the block device bd_mount_sem to make sure no new mounts
* happen on bdev until thaw_bdev() is called.
* If a superblock is found on this device, we take the s_umount semaphore
* on it to make sure nobody unmounts until the snapshot creation is done.
@@ -188,7 +189,7 @@ struct super_block *freeze_bdev(struct block_device *bdev)
{
struct super_block *sb;
- mutex_lock(&bdev->bd_mount_mutex);
+ down(&bdev->bd_mount_sem);
sb = get_super(bdev);
if (sb && !(sb->s_flags & MS_RDONLY)) {
sb->s_frozen = SB_FREEZE_WRITE;
@@ -230,7 +231,7 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb)
drop_super(sb);
}
- mutex_unlock(&bdev->bd_mount_mutex);
+ up(&bdev->bd_mount_sem);
}
EXPORT_SYMBOL(thaw_bdev);
@@ -724,20 +725,21 @@ int __set_page_dirty_buffers(struct page *page)
}
spin_unlock(&mapping->private_lock);
- if (!TestSetPageDirty(page)) {
- write_lock_irq(&mapping->tree_lock);
- if (page->mapping) { /* Race with truncate? */
- if (mapping_cap_account_dirty(mapping))
- __inc_zone_page_state(page, NR_FILE_DIRTY);
- radix_tree_tag_set(&mapping->page_tree,
- page_index(page),
- PAGECACHE_TAG_DIRTY);
+ if (TestSetPageDirty(page))
+ return 0;
+
+ write_lock_irq(&mapping->tree_lock);
+ if (page->mapping) { /* Race with truncate? */
+ if (mapping_cap_account_dirty(mapping)) {
+ __inc_zone_page_state(page, NR_FILE_DIRTY);
+ task_io_account_write(PAGE_CACHE_SIZE);
}
- write_unlock_irq(&mapping->tree_lock);
- __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
- return 1;
+ radix_tree_tag_set(&mapping->page_tree,
+ page_index(page), PAGECACHE_TAG_DIRTY);
}
- return 0;
+ write_unlock_irq(&mapping->tree_lock);
+ __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+ return 1;
}
EXPORT_SYMBOL(__set_page_dirty_buffers);
@@ -2842,18 +2844,24 @@ int try_to_free_buffers(struct page *page)
spin_lock(&mapping->private_lock);
ret = drop_buffers(page, &buffers_to_free);
+
+ /*
+ * If the filesystem writes its buffers by hand (eg ext3)
+ * then we can have clean buffers against a dirty page. We
+ * clean the page here; otherwise the VM will never notice
+ * that the filesystem did any IO at all.
+ *
+ * Also, during truncate, discard_buffer will have marked all
+ * the page's buffers clean. We discover that here and clean
+ * the page also.
+ *
+ * private_lock must be held over this entire operation in order
+ * to synchronise against __set_page_dirty_buffers and prevent the
+ * dirty bit from being lost.
+ */
+ if (ret)
+ cancel_dirty_page(page, PAGE_CACHE_SIZE);
spin_unlock(&mapping->private_lock);
- if (ret) {
- /*
- * If the filesystem writes its buffers by hand (eg ext3)
- * then we can have clean buffers against a dirty page. We
- * clean the page here; otherwise later reattachment of buffers
- * could encounter a non-uptodate page, which is unresolvable.
- * This only applies in the rare case where try_to_free_buffers
- * succeeds but the page is not freed.
- */
- clear_page_dirty(page);
- }
out:
if (buffers_to_free) {
struct buffer_head *bh = buffers_to_free;
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 0b3c37ef52e..d04d2f7448d 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,7 @@
+Version 1.47
+------------
+Fix oops in list_del during mount caused by unaligned string.
+
Version 1.46
------------
Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps.
@@ -5,7 +9,8 @@ Allow null user to be specified on mount ("username="). Do not return
EINVAL on readdir when filldir fails due to overwritten blocksize
(fixes FC problem). Return error in rename 2nd attempt retry (ie report
if rename by handle also fails, after rename by path fails, we were
-not reporting whether the retry worked or not).
+not reporting whether the retry worked or not). Fix NTLMv2 to
+work to Windows servers (mount with option "sec=ntlmv2").
Version 1.45
------------
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 96abeb73897..6017c465440 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -143,8 +143,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
(ses->serverNOS == NULL)) {
- buf += sprintf("\nentry for %s not fully displayed\n\t",
- ses->serverName);
+ buf += sprintf(buf, "\nentry for %s not fully "
+ "displayed\n\t", ses->serverName);
} else {
length =
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 4bc250b2d9f..fdeda519eac 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -372,8 +372,10 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
buf->reserved2 = 0;
- buf->names[0].type = 0;
+ buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
buf->names[0].length = 0;
+ buf->names[1].type = 0;
+ buf->names[1].length = 0;
/* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, nls_cp);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 71bc87a37fc..10c90294cd1 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -498,7 +498,7 @@ cifs_get_sb(struct file_system_type *fs_type,
static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
- struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+ struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
ssize_t written;
written = generic_file_aio_write(iocb, iov, nr_segs, pos);
@@ -511,7 +511,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
{
/* origin == SEEK_END => we must revalidate the cached file length */
if (origin == SEEK_END) {
- int retval = cifs_revalidate(file->f_dentry);
+ int retval = cifs_revalidate(file->f_path.dentry);
if (retval < 0)
return (loff_t)retval;
}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index a243f779b36..8aa66dcf13b 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg);
-#define CIFS_VERSION "1.46"
+#define CIFS_VERSION "1.47"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 6df9dadba64..068ef51edbf 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -580,6 +580,12 @@ typedef union smb_com_session_setup_andx {
/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
+#define NTLMSSP_SERVER_TYPE 1
+#define NTLMSSP_DOMAIN_TYPE 2
+#define NTLMSSP_FQ_DOMAIN_TYPE 3
+#define NTLMSSP_DNS_DOMAIN_TYPE 4
+#define NTLMSSP_DNS_PARENT_TYPE 5
+
struct ntlmssp2_name {
__le16 type;
__le16 length;
@@ -593,7 +599,7 @@ struct ntlmv2_resp {
__le64 time;
__u64 client_chal; /* random */
__u32 reserved2;
- struct ntlmssp2_name names[1];
+ struct ntlmssp2_name names[2];
/* array of name entries could follow ending in minimum 4 byte struct */
} __attribute__((packed));
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 098790eb2aa..472e33e0f3c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4876,7 +4876,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
} else {
/* Add file to outstanding requests */
/* BB change to kmem cache alloc */
- dnotify_req = (struct dir_notify_req *) kmalloc(
+ dnotify_req = kmalloc(
sizeof(struct dir_notify_req),
GFP_KERNEL);
if(dnotify_req) {
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index d91a3d44e9e..da12b482ebe 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -83,10 +83,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
return 0;
xid = GetXid();
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
- full_path = build_path_from_dentry(file->f_dentry);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if(full_path == NULL) {
rc = -ENOMEM;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 2436ed8fc84..8a49b2e77d3 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -29,6 +29,7 @@
#include <linux/pagevec.h>
#include <linux/smp_lock.h>
#include <linux/writeback.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/delay.h>
#include <asm/div64.h>
#include "cifsfs.h"
@@ -122,34 +123,34 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
/* 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 ==
+ if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
+ (file->f_path.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) {
+ if (file->f_path.dentry->d_inode->i_mapping) {
/* BB no need to lock inode until after invalidate
since namei code should already have it locked? */
- filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
+ filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
}
cFYI(1, ("invalidating remote inode since open detected it "
"changed"));
- invalidate_remote_inode(file->f_dentry->d_inode);
+ invalidate_remote_inode(file->f_path.dentry->d_inode);
}
client_can_cache:
if (pTcon->ses->capabilities & CAP_UNIX)
- rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+ rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
full_path, inode->i_sb, xid);
else
- rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+ rc = cifs_get_inode_info(&file->f_path.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));
+ file->f_path.dentry->d_inode));
} else if ((*oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
@@ -178,7 +179,7 @@ int cifs_open(struct inode *inode, struct file *file)
if (file->f_flags & O_CREAT) {
/* search inode for this file and fill in file->private_data */
- pCifsInode = CIFS_I(file->f_dentry->d_inode);
+ pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp, struct cifsFileInfo,
@@ -206,7 +207,7 @@ int cifs_open(struct inode *inode, struct file *file)
}
}
- full_path = build_path_from_dentry(file->f_dentry);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -291,7 +292,7 @@ int cifs_open(struct inode *inode, struct file *file)
write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist, &pTcon->openFileList);
- pCifsInode = CIFS_I(file->f_dentry->d_inode);
+ pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
if (pCifsInode) {
rc = cifs_open_inode_helper(inode, file, pCifsInode,
pCifsFile, pTcon,
@@ -366,7 +367,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
return 0;
}
- if (file->f_dentry == NULL) {
+ if (file->f_path.dentry == NULL) {
up(&pCifsFile->fh_sem);
cFYI(1, ("failed file reopen, no valid name if dentry freed"));
FreeXid(xid);
@@ -378,7 +379,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
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);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
@@ -444,7 +445,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1, ("Exclusive Oplock granted on inode %p",
- file->f_dentry->d_inode));
+ file->f_path.dentry->d_inode));
} else if ((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE;
pCifsInode->clientCanCacheAll = FALSE;
@@ -551,7 +552,7 @@ int 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_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
@@ -664,7 +665,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
} else
cFYI(1, ("Unknown type of lock"));
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
@@ -791,10 +792,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
int xid, long_op;
struct cifsFileInfo *open_file;
- if (file->f_dentry == NULL)
+ if (file->f_path.dentry == NULL)
return -EBADF;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
if (cifs_sb == NULL)
return -EBADF;
@@ -802,7 +803,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
/* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
- *poffset, file->f_dentry->d_name.name)); */
+ *poffset, file->f_path.dentry->d_name.name)); */
if (file->private_data == NULL)
return -EBADF;
@@ -810,12 +811,12 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
open_file = (struct cifsFileInfo *) file->private_data;
xid = GetXid();
- if (file->f_dentry->d_inode == NULL) {
+ if (file->f_path.dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
- if (*poffset > file->f_dentry->d_inode->i_size)
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
@@ -840,8 +841,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
return -EBADF;
}
if (open_file->invalidHandle) {
- if ((file->f_dentry == NULL) ||
- (file->f_dentry->d_inode == NULL)) {
+ if ((file->f_path.dentry == NULL) ||
+ (file->f_path.dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
@@ -849,7 +850,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
filemap_fdatawait from here so tell
reopen_file not to flush data to server
now */
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, FALSE);
if (rc != 0)
break;
@@ -878,17 +879,17 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
cifs_stats_bytes_written(pTcon, total_written);
/* since the write may have blocked check these pointers again */
- if (file->f_dentry) {
- if (file->f_dentry->d_inode) {
- struct inode *inode = file->f_dentry->d_inode;
+ if (file->f_path.dentry) {
+ if (file->f_path.dentry->d_inode) {
+ struct inode *inode = file->f_path.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,
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
+ i_size_write(file->f_path.dentry->d_inode,
*poffset);
}
- mark_inode_dirty_sync(file->f_dentry->d_inode);
+ mark_inode_dirty_sync(file->f_path.dentry->d_inode);
}
}
FreeXid(xid);
@@ -906,17 +907,17 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
int xid, long_op;
struct cifsFileInfo *open_file;
- if (file->f_dentry == NULL)
+ if (file->f_path.dentry == NULL)
return -EBADF;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
if (cifs_sb == NULL)
return -EBADF;
pTcon = cifs_sb->tcon;
cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
- *poffset, file->f_dentry->d_name.name));
+ *poffset, file->f_path.dentry->d_name.name));
if (file->private_data == NULL)
return -EBADF;
@@ -924,12 +925,12 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
open_file = (struct cifsFileInfo *)file->private_data;
xid = GetXid();
- if (file->f_dentry->d_inode == NULL) {
+ if (file->f_path.dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
- if (*poffset > file->f_dentry->d_inode->i_size)
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
@@ -955,8 +956,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
return -EBADF;
}
if (open_file->invalidHandle) {
- if ((file->f_dentry == NULL) ||
- (file->f_dentry->d_inode == NULL)) {
+ if ((file->f_path.dentry == NULL) ||
+ (file->f_path.dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
@@ -964,7 +965,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
filemap_fdatawait from here so tell
reopen_file not to flush data to
server now */
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, FALSE);
if (rc != 0)
break;
@@ -1011,16 +1012,16 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
cifs_stats_bytes_written(pTcon, total_written);
/* 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_path.dentry) {
+ if (file->f_path.dentry->d_inode) {
+ file->f_path.dentry->d_inode->i_ctime =
+ file->f_path.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,
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
+ i_size_write(file->f_path.dentry->d_inode,
*poffset);
}
- mark_inode_dirty_sync(file->f_dentry->d_inode);
+ mark_inode_dirty_sync(file->f_path.dentry->d_inode);
}
}
FreeXid(xid);
@@ -1244,14 +1245,21 @@ retry:
wait_on_page_writeback(page);
if (PageWriteback(page) ||
- !test_clear_page_dirty(page)) {
+ !clear_page_dirty_for_io(page)) {
unlock_page(page);
break;
}
+ /*
+ * This actually clears the dirty bit in the radix tree.
+ * See cifs_writepage() for more commentary.
+ */
+ set_page_writeback(page);
+
if (page_offset(page) >= mapping->host->i_size) {
done = 1;
unlock_page(page);
+ end_page_writeback(page);
break;
}
@@ -1315,6 +1323,7 @@ retry:
SetPageError(page);
kunmap(page);
unlock_page(page);
+ end_page_writeback(page);
page_cache_release(page);
}
if ((wbc->nr_to_write -= n_iov) <= 0)
@@ -1351,11 +1360,23 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc)
if (!PageUptodate(page)) {
cFYI(1, ("ppw - page not up to date"));
}
-
+
+ /*
+ * Set the "writeback" flag, and clear "dirty" in the radix tree.
+ *
+ * A writepage() implementation always needs to do either this,
+ * or re-dirty the page with "redirty_page_for_writepage()" in
+ * the case of a failure.
+ *
+ * Just unlocking the page will cause the radix tree tag-bits
+ * to fail to update with the state of the page correctly.
+ */
+ set_page_writeback(page);
rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
unlock_page(page);
- page_cache_release(page);
+ end_page_writeback(page);
+ page_cache_release(page);
FreeXid(xid);
return rc;
}
@@ -1384,7 +1405,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
rc = cifs_reopen_file(
- file->f_dentry->d_inode, file);
+ file->f_path.dentry->d_inode, file);
if (rc != 0)
break;
}
@@ -1434,7 +1455,7 @@ 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_path.dentry->d_inode;
xid = GetXid();
@@ -1482,7 +1503,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
*/
int cifs_flush(struct file *file, fl_owner_t id)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
int rc = 0;
/* Rather than do the steps manually:
@@ -1519,7 +1540,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
struct smb_com_read_rsp *pSMBr;
xid = GetXid();
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
@@ -1542,7 +1563,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
int buf_type = CIFS_NO_BUFFER;
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, TRUE);
if (rc != 0)
break;
@@ -1601,7 +1622,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
int buf_type = CIFS_NO_BUFFER;
xid = GetXid();
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
@@ -1629,7 +1650,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
while (rc == -EAGAIN) {
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, TRUE);
if (rc != 0)
break;
@@ -1658,7 +1679,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int rc, xid;
xid = GetXid();
@@ -1744,7 +1765,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
return -EBADF;
}
open_file = (struct cifsFileInfo *)file->private_data;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
pagevec_init(&lru_pvec, 0);
@@ -1786,7 +1807,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
while (rc == -EAGAIN) {
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, TRUE);
if (rc != 0)
break;
@@ -1812,6 +1833,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
cFYI(1, ("Read error in readpages: %d", rc));
break;
} else if (bytes_read > 0) {
+ task_io_account_read(bytes_read);
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
cifs_copy_cache_pages(mapping, page_list, bytes_read,
smb_read_data + 4 /* RFC1001 hdr */ +
@@ -1880,8 +1902,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
else
cFYI(1, ("Bytes read %d",rc));
- file->f_dentry->d_inode->i_atime =
- current_fs_time(file->f_dentry->d_inode->i_sb);
+ file->f_path.dentry->d_inode->i_atime =
+ current_fs_time(file->f_path.dentry->d_inode->i_sb);
if (PAGE_CACHE_SIZE > rc)
memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index aedf683f011..19cc294c7c7 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -71,9 +71,7 @@ sesInfoAlloc(void)
{
struct cifsSesInfo *ret_buf;
- ret_buf =
- (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
- GFP_KERNEL);
+ ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL);
if (ret_buf) {
write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
@@ -109,9 +107,7 @@ struct cifsTconInfo *
tconInfoAlloc(void)
{
struct cifsTconInfo *ret_buf;
- ret_buf =
- (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
- GFP_KERNEL);
+ ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL);
if (ret_buf) {
write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index ed18c3965f7..99dfb5337e3 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -68,30 +68,30 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
int rc = 0;
cFYI(1, ("For %s", qstring->name));
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
qstring->hash = full_name_hash(qstring->name, qstring->len);
- tmp_dentry = d_lookup(file->f_dentry, qstring);
+ tmp_dentry = d_lookup(file->f_path.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);
+ *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
if(*ptmp_inode == NULL)
return rc;
rc = 1;
}
} else {
- tmp_dentry = d_alloc(file->f_dentry, qstring);
+ tmp_dentry = d_alloc(file->f_path.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);
+ *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
if (pTcon->nocase)
tmp_dentry->d_op = &cifs_ci_dentry_ops;
else
@@ -432,10 +432,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifsFile->invalidHandle = TRUE;
cifsFile->srch_inf.endOfSearch = FALSE;
- if(file->f_dentry == NULL)
+ if(file->f_path.dentry == NULL)
return -ENOENT;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
if(cifs_sb == NULL)
return -EINVAL;
@@ -443,7 +443,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
if(pTcon == NULL)
return -EINVAL;
- full_path = build_path_from_dentry(file->f_dentry);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if(full_path == NULL) {
return -ENOMEM;
@@ -609,10 +609,10 @@ static int is_dir_changed(struct file * file)
struct inode * inode;
struct cifsInodeInfo *cifsInfo;
- if(file->f_dentry == NULL)
+ if(file->f_path.dentry == NULL)
return 0;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if(inode == NULL)
return 0;
@@ -839,7 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
return -ENOENT;
- if(file->f_dentry == NULL)
+ if(file->f_path.dentry == NULL)
return -ENOENT;
rc = cifs_entry_is_dot(pfindEntry,pCifsF);
@@ -847,7 +847,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if(rc != 0)
return 0;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
qstring.name = scratch_buf;
rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
@@ -985,12 +985,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
xid = GetXid();
- if(file->f_dentry == NULL) {
+ if(file->f_path.dentry == NULL) {
FreeXid(xid);
return -EIO;
}
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if(pTcon == NULL)
return -EINVAL;
@@ -998,7 +998,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
switch ((int) file->f_pos) {
case 0:
if (filldir(direntry, ".", 1, file->f_pos,
- file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
+ file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for current dir failed"));
rc = -ENOMEM;
break;
@@ -1006,7 +1006,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
file->f_pos++;
case 1:
if (filldir(direntry, "..", 2, file->f_pos,
- file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+ file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for parent dir failed"));
rc = -ENOMEM;
break;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index bbdda99dce6..75846463089 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -182,11 +182,14 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
cFYI(1,("bleft %d",bleft));
- /* word align, if bytes remaining is not even */
- if(bleft % 2) {
- bleft--;
- data++;
- }
+ /* SMB header is unaligned, so cifs servers word align start of
+ Unicode strings */
+ data++;
+ bleft--; /* Windows servers do not always double null terminate
+ their final Unicode string - in which case we
+ now will not attempt to decode the byte of junk
+ which follows it */
+
words_left = bleft / 2;
/* save off server operating system */
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 0102b28a15f..0c6f7f3b3dd 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -441,7 +441,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
/* file operations for directories */
int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
{
- struct dentry *coda_dentry = coda_file->f_dentry;
+ struct dentry *coda_dentry = coda_file->f_path.dentry;
struct coda_file_info *cfi;
struct file *host_file;
struct inode *host_inode;
@@ -453,7 +453,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
coda_vfs_stat.readdir++;
- host_inode = host_file->f_dentry->d_inode;
+ host_inode = host_file->f_path.dentry->d_inode;
mutex_lock(&host_inode->i_mutex);
host_file->f_pos = coda_file->f_pos;
@@ -544,14 +544,14 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
/* catch truncated reads */
if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
printk("coda_venus_readdir: short read: %ld\n",
- filp->f_dentry->d_inode->i_ino);
+ filp->f_path.dentry->d_inode->i_ino);
ret = -EBADF;
break;
}
/* validate whether the directory file actually makes sense */
if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
printk("coda_venus_readdir: Invalid dir: %ld\n",
- filp->f_dentry->d_inode->i_ino);
+ filp->f_path.dentry->d_inode->i_ino);
ret = -EBADF;
break;
}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index dbfbcfa5b3c..5ef2b609ec7 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -66,7 +66,7 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
static ssize_t
coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode;
+ struct inode *host_inode, *coda_inode = coda_file->f_path.dentry->d_inode;
struct coda_file_info *cfi;
struct file *host_file;
ssize_t ret;
@@ -78,7 +78,7 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
if (!host_file->f_op || !host_file->f_op->write)
return -EINVAL;
- host_inode = host_file->f_dentry->d_inode;
+ host_inode = host_file->f_path.dentry->d_inode;
mutex_lock(&coda_inode->i_mutex);
ret = host_file->f_op->write(host_file, buf, count, ppos);
@@ -106,8 +106,8 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
if (!host_file->f_op || !host_file->f_op->mmap)
return -ENODEV;
- coda_inode = coda_file->f_dentry->d_inode;
- host_inode = host_file->f_dentry->d_inode;
+ coda_inode = coda_file->f_path.dentry->d_inode;
+ host_inode = host_file->f_path.dentry->d_inode;
coda_file->f_mapping = host_file->f_mapping;
if (coda_inode->i_mapping == &coda_inode->i_data)
coda_inode->i_mapping = host_inode->i_mapping;
@@ -190,7 +190,7 @@ int coda_flush(struct file *coda_file, fl_owner_t id)
cfi = CODA_FTOC(coda_file);
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
- coda_inode = coda_file->f_dentry->d_inode;
+ coda_inode = coda_file->f_path.dentry->d_inode;
err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
coda_file->f_uid);
@@ -233,7 +233,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
coda_flags, coda_file->f_uid);
- host_inode = cfi->cfi_container->f_dentry->d_inode;
+ host_inode = cfi->cfi_container->f_path.dentry->d_inode;
cii = ITOC(coda_inode);
/* did we mmap this file? */
@@ -270,7 +270,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
coda_vfs_stat.fsync++;
if (host_file->f_op && host_file->f_op->fsync) {
- host_dentry = host_file->f_dentry;
+ host_dentry = host_file->f_path.dentry;
host_inode = host_dentry->d_inode;
mutex_lock(&host_inode->i_mutex);
err = host_file->f_op->fsync(host_file, host_dentry, datasync);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index b64659fa82d..01395defed8 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -119,7 +119,7 @@ static int get_device_index(struct coda_mount_data *data)
file = fget(data->fd);
inode = NULL;
if(file)
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if(!inode || !S_ISCHR(inode->i_mode) ||
imajor(inode) != CODA_PSDEV_MAJOR) {
diff --git a/fs/compat.c b/fs/compat.c
index a7e3f162fb1..0ec70e3cee0 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -232,7 +232,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs(file->f_dentry, &tmp);
+ error = vfs_statfs(file->f_path.dentry, &tmp);
if (!error)
error = put_compat_statfs(buf, &tmp);
fput(file);
@@ -303,7 +303,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs(file->f_dentry, &tmp);
+ error = vfs_statfs(file->f_path.dentry, &tmp);
if (!error)
error = put_compat_statfs64(buf, &tmp);
fput(file);
@@ -365,7 +365,7 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd,
/* find the name of the device. */
path = (char *)__get_free_page(GFP_KERNEL);
if (path) {
- fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE);
+ fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
if (IS_ERR(fn))
fn = "?";
}
@@ -416,7 +416,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
case FIBMAP:
case FIGETBSZ:
case FIONREAD:
- if (S_ISREG(filp->f_dentry->d_inode->i_mode))
+ if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
break;
/*FALL THROUGH*/
@@ -438,7 +438,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
goto found_handler;
}
- if (S_ISSOCK(filp->f_dentry->d_inode->i_mode) &&
+ if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
error = siocdevprivate_ioctl(fd, cmd, arg);
} else {
@@ -1259,7 +1259,7 @@ out:
if (iov != iovstack)
kfree(iov);
if ((ret + (type == READ)) > 0) {
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
if (type == READ)
fsnotify_access(dentry);
else
@@ -1679,19 +1679,19 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
{
fd_set_bits fds;
char *bits;
- int size, max_fdset, ret = -EINVAL;
+ int size, max_fds, ret = -EINVAL;
struct fdtable *fdt;
if (n < 0)
goto out_nofds;
- /* max_fdset can increase, so grab it once to avoid race */
+ /* max_fds can increase, so grab it once to avoid race */
rcu_read_lock();
fdt = files_fdtable(current->files);
- max_fdset = fdt->max_fdset;
+ max_fds = fdt->max_fds;
rcu_read_unlock();
- if (n > max_fdset)
- n = max_fdset;
+ if (n > max_fds)
+ n = max_fds;
/*
* We need 6 bitmaps (in/out/ex for both incoming and outgoing),
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index bcc3caf5d82..c81c958b3e1 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1177,7 +1177,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
static int vt_check(struct file *file)
{
struct tty_struct *tty;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
if (file->f_op->ioctl != tty_ioctl)
return -EINVAL;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index c398861f78a..1814ba44680 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -980,7 +980,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name)
static int configfs_dir_open(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
struct configfs_dirent * parent_sd = dentry->d_fsdata;
mutex_lock(&dentry->d_inode->i_mutex);
@@ -993,7 +993,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
static int configfs_dir_close(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
struct configfs_dirent * cursor = file->private_data;
mutex_lock(&dentry->d_inode->i_mutex);
@@ -1013,7 +1013,7 @@ static inline unsigned char dt_type(struct configfs_dirent *sd)
static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct configfs_dirent * parent_sd = dentry->d_fsdata;
struct configfs_dirent *cursor = filp->private_data;
struct list_head *p, *q = &cursor->s_sibling;
@@ -1070,7 +1070,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
mutex_lock(&dentry->d_inode->i_mutex);
switch (origin) {
@@ -1080,7 +1080,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index cf33fac68c8..2a7cb086e80 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -134,7 +134,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
down(&buffer->sem);
if (buffer->needs_read_fill) {
- if ((retval = fill_read_buffer(file->f_dentry,buffer)))
+ if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
goto out;
}
pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -222,7 +222,7 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
down(&buffer->sem);
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
- len = flush_write_buffer(file->f_dentry, buffer, count);
+ len = flush_write_buffer(file->f_path.dentry, buffer, count);
if (len > 0)
*ppos += len;
up(&buffer->sem);
@@ -231,8 +231,8 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
static int check_perm(struct inode * inode, struct file * file)
{
- struct config_item *item = configfs_get_config_item(file->f_dentry->d_parent);
- struct configfs_attribute * attr = to_attr(file->f_dentry);
+ struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
+ struct configfs_attribute * attr = to_attr(file->f_path.dentry);
struct configfs_buffer * buffer;
struct configfs_item_operations * ops = NULL;
int error = 0;
@@ -305,8 +305,8 @@ static int configfs_open_file(struct inode * inode, struct file * filp)
static int configfs_release(struct inode * inode, struct file * filp)
{
- struct config_item * item = to_item(filp->f_dentry->d_parent);
- struct configfs_attribute * attr = to_attr(filp->f_dentry);
+ struct config_item * item = to_item(filp->f_path.dentry->d_parent);
+ struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
struct module * owner = attr->ca_owner;
struct configfs_buffer * buffer = filp->private_data;
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 0509cedd415..6db03fb089d 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -338,7 +338,7 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
*/
static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
char *buf;
unsigned int offset;
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 137d76c3f90..c692487346e 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -24,6 +24,7 @@
#include <linux/kobject.h>
#include <linux/namei.h>
#include <linux/debugfs.h>
+#include <linux/fsnotify.h>
#define DEBUGFS_MAGIC 0x64626720
@@ -54,7 +55,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ /* directory inodes start off with i_nlink == 2
+ * (for "." entry) */
inc_nlink(inode);
break;
}
@@ -87,15 +89,22 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
res = debugfs_mknod(dir, dentry, mode, 0);
- if (!res)
+ if (!res) {
inc_nlink(dir);
+ fsnotify_mkdir(dir, dentry);
+ }
return res;
}
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
+ int res;
+
mode = (mode & S_IALLUGO) | S_IFREG;
- return debugfs_mknod(dir, dentry, mode, 0);
+ res = debugfs_mknod(dir, dentry, mode, 0);
+ if (!res)
+ fsnotify_create(dir, dentry);
+ return res;
}
static inline int debugfs_positive(struct dentry *dentry)
@@ -135,7 +144,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
* block. A pointer to that is in the struct vfsmount that we
* have around.
*/
- if (!parent ) {
+ if (!parent) {
if (debugfs_mount && debugfs_mount->mnt_sb) {
parent = debugfs_mount->mnt_sb->s_root;
}
@@ -153,6 +162,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
error = debugfs_mkdir(parent->d_inode, *dentry, mode);
else
error = debugfs_create(parent->d_inode, *dentry, mode);
+ dput(*dentry);
} else
error = PTR_ERR(*dentry);
mutex_unlock(&parent->d_inode->i_mutex);
@@ -197,13 +207,15 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
pr_debug("debugfs: creating file '%s'\n",name);
- error = simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
+ error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
+ &debugfs_mount_count);
if (error)
goto exit;
error = debugfs_create_by_name(name, mode, parent, &dentry);
if (error) {
dentry = NULL;
+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);
goto exit;
}
@@ -262,6 +274,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_dir);
void debugfs_remove(struct dentry *dentry)
{
struct dentry *parent;
+ int ret = 0;
if (!dentry)
return;
@@ -273,11 +286,19 @@ void debugfs_remove(struct dentry *dentry)
mutex_lock(&parent->d_inode->i_mutex);
if (debugfs_positive(dentry)) {
if (dentry->d_inode) {
- if (S_ISDIR(dentry->d_inode->i_mode))
- simple_rmdir(parent->d_inode, dentry);
- else
+ dget(dentry);
+ if (S_ISDIR(dentry->d_inode->i_mode)) {
+ ret = simple_rmdir(parent->d_inode, dentry);
+ if (ret)
+ printk(KERN_ERR
+ "DebugFS rmdir on %s failed : "
+ "directory not empty.\n",
+ dentry->d_name.name);
+ } else
simple_unlink(parent->d_inode, dentry);
- dput(dentry);
+ if (!ret)
+ d_delete(dentry);
+ dput(dentry);
}
}
mutex_unlock(&parent->d_inode->i_mutex);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 5981e17f46f..d9d0833444f 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/bio.h>
#include <linux/wait.h>
#include <linux/err.h>
@@ -121,8 +122,7 @@ struct dio {
/* BIO completion state */
spinlock_t bio_lock; /* protects BIO fields below */
- int bio_count; /* nr bios to be completed */
- int bios_in_flight; /* nr bios in flight */
+ unsigned long refcount; /* direct_io_worker() and bios */
struct bio *bio_list; /* singly linked via bi_private */
struct task_struct *waiter; /* waiting task (NULL if none) */
@@ -209,76 +209,55 @@ static struct page *dio_get_page(struct dio *dio)
return dio->pages[dio->head++];
}
-/*
- * Called when all DIO BIO I/O has been completed - let the filesystem
- * know, if it registered an interest earlier via get_block. Pass the
- * private field of the map buffer_head so that filesystems can use it
- * to hold additional state between get_block calls and dio_complete.
- */
-static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
-{
- if (dio->end_io && dio->result)
- dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
- if (dio->lock_type == DIO_LOCKING)
- /* lockdep: non-owner release */
- up_read_non_owner(&dio->inode->i_alloc_sem);
-}
-
-/*
- * Called when a BIO has been processed. If the count goes to zero then IO is
- * complete and we can signal this to the AIO layer.
+/**
+ * dio_complete() - called when all DIO BIO I/O has been completed
+ * @offset: the byte offset in the file of the completed operation
+ *
+ * This releases locks as dictated by the locking type, lets interested parties
+ * know that a DIO operation has completed, and calculates the resulting return
+ * code for the operation.
+ *
+ * It lets the filesystem know if it registered an interest earlier via
+ * get_block. Pass the private field of the map buffer_head so that
+ * filesystems can use it to hold additional state between get_block calls and
+ * dio_complete.
*/
-static void finished_one_bio(struct dio *dio)
+static int dio_complete(struct dio *dio, loff_t offset, int ret)
{
- unsigned long flags;
+ ssize_t transferred = 0;
- spin_lock_irqsave(&dio->bio_lock, flags);
- if (dio->bio_count == 1) {
- if (dio->is_async) {
- ssize_t transferred;
- loff_t offset;
-
- /*
- * Last reference to the dio is going away.
- * Drop spinlock and complete the DIO.
- */
- spin_unlock_irqrestore(&dio->bio_lock, flags);
+ /*
+ * AIO submission can race with bio completion to get here while
+ * expecting to have the last io completed by bio completion.
+ * In that case -EIOCBQUEUED is in fact not an error we want
+ * to preserve through this call.
+ */
+ if (ret == -EIOCBQUEUED)
+ ret = 0;
- /* Check for short read case */
- transferred = dio->result;
- offset = dio->iocb->ki_pos;
+ if (dio->result) {
+ transferred = dio->result;
- if ((dio->rw == READ) &&
- ((offset + transferred) > dio->i_size))
- transferred = dio->i_size - offset;
+ /* Check for short read case */
+ if ((dio->rw == READ) && ((offset + transferred) > dio->i_size))
+ transferred = dio->i_size - offset;
+ }
- /* check for error in completion path */
- if (dio->io_error)
- transferred = dio->io_error;
+ if (dio->end_io && dio->result)
+ dio->end_io(dio->iocb, offset, transferred,
+ dio->map_bh.b_private);
+ if (dio->lock_type == DIO_LOCKING)
+ /* lockdep: non-owner release */
+ up_read_non_owner(&dio->inode->i_alloc_sem);
- dio_complete(dio, offset, transferred);
+ if (ret == 0)
+ ret = dio->page_errors;
+ if (ret == 0)
+ ret = dio->io_error;
+ if (ret == 0)
+ ret = transferred;
- /* Complete AIO later if falling back to buffered i/o */
- if (dio->result == dio->size ||
- ((dio->rw == READ) && dio->result)) {
- aio_complete(dio->iocb, transferred, 0);
- kfree(dio);
- return;
- } else {
- /*
- * Falling back to buffered
- */
- spin_lock_irqsave(&dio->bio_lock, flags);
- dio->bio_count--;
- if (dio->waiter)
- wake_up_process(dio->waiter);
- spin_unlock_irqrestore(&dio->bio_lock, flags);
- return;
- }
- }
- }
- dio->bio_count--;
- spin_unlock_irqrestore(&dio->bio_lock, flags);
+ return ret;
}
static int dio_bio_complete(struct dio *dio, struct bio *bio);
@@ -288,12 +267,27 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio);
static int dio_bio_end_aio(struct bio *bio, unsigned int bytes_done, int error)
{
struct dio *dio = bio->bi_private;
+ unsigned long remaining;
+ unsigned long flags;
if (bio->bi_size)
return 1;
/* cleanup the bio */
dio_bio_complete(dio, bio);
+
+ spin_lock_irqsave(&dio->bio_lock, flags);
+ remaining = --dio->refcount;
+ if (remaining == 1 && dio->waiter)
+ wake_up_process(dio->waiter);
+ spin_unlock_irqrestore(&dio->bio_lock, flags);
+
+ if (remaining == 0) {
+ int ret = dio_complete(dio, dio->iocb->ki_pos, 0);
+ aio_complete(dio->iocb, ret, 0);
+ kfree(dio);
+ }
+
return 0;
}
@@ -315,8 +309,7 @@ static int dio_bio_end_io(struct bio *bio, unsigned int bytes_done, int error)
spin_lock_irqsave(&dio->bio_lock, flags);
bio->bi_private = dio->bio_list;
dio->bio_list = bio;
- dio->bios_in_flight--;
- if (dio->waiter && dio->bios_in_flight == 0)
+ if (--dio->refcount == 1 && dio->waiter)
wake_up_process(dio->waiter);
spin_unlock_irqrestore(&dio->bio_lock, flags);
return 0;
@@ -347,6 +340,8 @@ dio_bio_alloc(struct dio *dio, struct block_device *bdev,
* In the AIO read case we speculatively dirty the pages before starting IO.
* During IO completion, any of these pages which happen to have been written
* back will be redirtied by bio_check_pages_dirty().
+ *
+ * bios hold a dio reference between submit_bio and ->end_io.
*/
static void dio_bio_submit(struct dio *dio)
{
@@ -354,12 +349,14 @@ static void dio_bio_submit(struct dio *dio)
unsigned long flags;
bio->bi_private = dio;
+
spin_lock_irqsave(&dio->bio_lock, flags);
- dio->bio_count++;
- dio->bios_in_flight++;
+ dio->refcount++;
spin_unlock_irqrestore(&dio->bio_lock, flags);
+
if (dio->is_async && dio->rw == READ)
bio_set_pages_dirty(bio);
+
submit_bio(dio->rw, bio);
dio->bio = NULL;
@@ -376,28 +373,37 @@ static void dio_cleanup(struct dio *dio)
}
/*
- * Wait for the next BIO to complete. Remove it and return it.
+ * Wait for the next BIO to complete. Remove it and return it. NULL is
+ * returned once all BIOs have been completed. This must only be called once
+ * all bios have been issued so that dio->refcount can only decrease. This
+ * requires that that the caller hold a reference on the dio.
*/
static struct bio *dio_await_one(struct dio *dio)
{
unsigned long flags;
- struct bio *bio;
+ struct bio *bio = NULL;
spin_lock_irqsave(&dio->bio_lock, flags);
- while (dio->bio_list == NULL) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- if (dio->bio_list == NULL) {
- dio->waiter = current;
- spin_unlock_irqrestore(&dio->bio_lock, flags);
- blk_run_address_space(dio->inode->i_mapping);
- io_schedule();
- spin_lock_irqsave(&dio->bio_lock, flags);
- dio->waiter = NULL;
- }
- set_current_state(TASK_RUNNING);
+
+ /*
+ * Wait as long as the list is empty and there are bios in flight. bio
+ * completion drops the count, maybe adds to the list, and wakes while
+ * holding the bio_lock so we don't need set_current_state()'s barrier
+ * and can call it after testing our condition.
+ */
+ while (dio->refcount > 1 && dio->bio_list == NULL) {
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ dio->waiter = current;
+ spin_unlock_irqrestore(&dio->bio_lock, flags);
+ io_schedule();
+ /* wake up sets us TASK_RUNNING */
+ spin_lock_irqsave(&dio->bio_lock, flags);
+ dio->waiter = NULL;
+ }
+ if (dio->bio_list) {
+ bio = dio->bio_list;
+ dio->bio_list = bio->bi_private;
}
- bio = dio->bio_list;
- dio->bio_list = bio->bi_private;
spin_unlock_irqrestore(&dio->bio_lock, flags);
return bio;
}
@@ -426,34 +432,24 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
}
bio_put(bio);
}
- finished_one_bio(dio);
return uptodate ? 0 : -EIO;
}
/*
- * Wait on and process all in-flight BIOs.
+ * Wait on and process all in-flight BIOs. This must only be called once
+ * all bios have been issued so that the refcount can only decrease.
+ * This just waits for all bios to make it through dio_bio_complete. IO
+ * errors are propogated through dio->io_error and should be propogated via
+ * dio_complete().
*/
-static int dio_await_completion(struct dio *dio)
+static void dio_await_completion(struct dio *dio)
{
- int ret = 0;
-
- if (dio->bio)
- dio_bio_submit(dio);
-
- /*
- * The bio_lock is not held for the read of bio_count.
- * This is ok since it is the dio_bio_complete() that changes
- * bio_count.
- */
- while (dio->bio_count) {
- struct bio *bio = dio_await_one(dio);
- int ret2;
-
- ret2 = dio_bio_complete(dio, bio);
- if (ret == 0)
- ret = ret2;
- }
- return ret;
+ struct bio *bio;
+ do {
+ bio = dio_await_one(dio);
+ if (bio)
+ dio_bio_complete(dio, bio);
+ } while (bio);
}
/*
@@ -675,6 +671,13 @@ submit_page_section(struct dio *dio, struct page *page,
{
int ret = 0;
+ if (dio->rw & WRITE) {
+ /*
+ * Read accounting is performed in submit_bio()
+ */
+ task_io_account_write(len);
+ }
+
/*
* Can we just grow the current page's presence in the dio?
*/
@@ -953,6 +956,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
struct dio *dio)
{
unsigned long user_addr;
+ unsigned long flags;
int seg;
ssize_t ret = 0;
ssize_t ret2;
@@ -983,17 +987,8 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
dio->iocb = iocb;
dio->i_size = i_size_read(inode);
- /*
- * BIO completion state.
- *
- * ->bio_count starts out at one, and we decrement it to zero after all
- * BIOs are submitted. This to avoid the situation where a really fast
- * (or synchronous) device could take the count to zero while we're
- * still submitting BIOs.
- */
- dio->bio_count = 1;
- dio->bios_in_flight = 0;
spin_lock_init(&dio->bio_lock);
+ dio->refcount = 1;
dio->bio_list = NULL;
dio->waiter = NULL;
@@ -1069,6 +1064,9 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
if (dio->bio)
dio_bio_submit(dio);
+ /* All IO is now issued, send it on its way */
+ blk_run_address_space(inode->i_mapping);
+
/*
* It is possible that, we return short IO due to end of file.
* In that case, we need to release all the pages we got hold on.
@@ -1084,74 +1082,41 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
mutex_unlock(&dio->inode->i_mutex);
/*
- * OK, all BIOs are submitted, so we can decrement bio_count to truly
- * reflect the number of to-be-processed BIOs.
+ * The only time we want to leave bios in flight is when a successful
+ * partial aio read or full aio write have been setup. In that case
+ * bio completion will call aio_complete. The only time it's safe to
+ * call aio_complete is when we return -EIOCBQUEUED, so we key on that.
+ * This had *better* be the only place that raises -EIOCBQUEUED.
*/
- if (dio->is_async) {
- int should_wait = 0;
+ BUG_ON(ret == -EIOCBQUEUED);
+ if (dio->is_async && ret == 0 && dio->result &&
+ ((rw & READ) || (dio->result == dio->size)))
+ ret = -EIOCBQUEUED;
- if (dio->result < dio->size && (rw & WRITE)) {
- dio->waiter = current;
- should_wait = 1;
- }
- if (ret == 0)
- ret = dio->result;
- finished_one_bio(dio); /* This can free the dio */
- blk_run_address_space(inode->i_mapping);
- if (should_wait) {
- unsigned long flags;
- /*
- * Wait for already issued I/O to drain out and
- * release its references to user-space pages
- * before returning to fallback on buffered I/O
- */
-
- spin_lock_irqsave(&dio->bio_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- while (dio->bio_count) {
- spin_unlock_irqrestore(&dio->bio_lock, flags);
- io_schedule();
- spin_lock_irqsave(&dio->bio_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- }
- spin_unlock_irqrestore(&dio->bio_lock, flags);
- set_current_state(TASK_RUNNING);
- kfree(dio);
- }
- } else {
- ssize_t transferred = 0;
-
- finished_one_bio(dio);
- ret2 = dio_await_completion(dio);
- if (ret == 0)
- ret = ret2;
- if (ret == 0)
- ret = dio->page_errors;
- if (dio->result) {
- loff_t i_size = i_size_read(inode);
-
- transferred = dio->result;
- /*
- * Adjust the return value if the read crossed a
- * non-block-aligned EOF.
- */
- if (rw == READ && (offset + transferred > i_size))
- transferred = i_size - offset;
- }
- dio_complete(dio, offset, transferred);
- if (ret == 0)
- ret = transferred;
+ if (ret != -EIOCBQUEUED)
+ dio_await_completion(dio);
- /* We could have also come here on an AIO file extend */
- if (!is_sync_kiocb(iocb) && (rw & WRITE) &&
- ret >= 0 && dio->result == dio->size)
- /*
- * For AIO writes where we have completed the
- * i/o, we have to mark the the aio complete.
- */
- aio_complete(iocb, ret, 0);
+ /*
+ * Sync will always be dropping the final ref and completing the
+ * operation. AIO can if it was a broken operation described above or
+ * in fact if all the bios race to complete before we get here. In
+ * that case dio_complete() translates the EIOCBQUEUED into the proper
+ * return code that the caller will hand to aio_complete().
+ *
+ * This is managed by the bio_lock instead of being an atomic_t so that
+ * completion paths can drop their ref and use the remaining count to
+ * decide to wake the submission path atomically.
+ */
+ spin_lock_irqsave(&dio->bio_lock, flags);
+ ret2 = --dio->refcount;
+ spin_unlock_irqrestore(&dio->bio_lock, flags);
+ BUG_ON(!dio->is_async && ret2 != 0);
+ if (ret2 == 0) {
+ ret = dio_complete(dio, offset, ret);
kfree(dio);
- }
+ } else
+ BUG_ON(ret != -EIOCBQUEUED);
+
return ret;
}
diff --git a/fs/dlm/lowcomms-tcp.c b/fs/dlm/lowcomms-tcp.c
index 8f2791fc844..9be3a440c42 100644
--- a/fs/dlm/lowcomms-tcp.c
+++ b/fs/dlm/lowcomms-tcp.c
@@ -143,7 +143,7 @@ static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_waitq);
/* An array of pointers to connections, indexed by NODEID */
static struct connection **connections;
static DECLARE_MUTEX(connections_lock);
-static kmem_cache_t *con_cache;
+static struct kmem_cache *con_cache;
static int conn_array_size;
/* List of sockets that have reads pending */
diff --git a/fs/dnotify.c b/fs/dnotify.c
index 1f26a2b9eee..936409fcd93 100644
--- a/fs/dnotify.c
+++ b/fs/dnotify.c
@@ -42,7 +42,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
struct dnotify_struct **prev;
struct inode *inode;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (!S_ISDIR(inode->i_mode))
return;
spin_lock(&inode->i_lock);
@@ -74,7 +74,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
}
if (!dir_notify_enable)
return -EINVAL;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (!S_ISDIR(inode->i_mode))
return -ENOTDIR;
dn = kmem_cache_alloc(dn_cache, GFP_KERNEL);
diff --git a/fs/dquot.c b/fs/dquot.c
index f9cd5e23ebd..0952cc474d9 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -694,9 +694,9 @@ restart:
file_list_lock();
list_for_each(p, &sb->s_files) {
struct file *filp = list_entry(p, struct file, f_u.fu_list);
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
- struct dentry *dentry = dget(filp->f_dentry);
+ struct dentry *dentry = dget(filp->f_path.dentry);
file_list_unlock();
sb->dq_op->initialize(inode, type);
dput(dentry);
@@ -828,6 +828,7 @@ static inline int need_print_warning(struct dquot *dquot)
static void print_warning(struct dquot *dquot, const char warntype)
{
char *msg = NULL;
+ struct tty_struct *tty;
int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B :
((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0);
@@ -835,14 +836,15 @@ static void print_warning(struct dquot *dquot, const char warntype)
return;
mutex_lock(&tty_mutex);
- if (!current->signal->tty)
+ tty = get_current_tty();
+ if (!tty)
goto out_lock;
- tty_write_message(current->signal->tty, dquot->dq_sb->s_id);
+ tty_write_message(tty, dquot->dq_sb->s_id);
if (warntype == ISOFTWARN || warntype == BSOFTWARN)
- tty_write_message(current->signal->tty, ": warning, ");
+ tty_write_message(tty, ": warning, ");
else
- tty_write_message(current->signal->tty, ": write failed, ");
- tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]);
+ tty_write_message(tty, ": write failed, ");
+ tty_write_message(tty, quotatypes[dquot->dq_type]);
switch (warntype) {
case IHARDWARN:
msg = " file limit reached.\r\n";
@@ -863,7 +865,7 @@ static void print_warning(struct dquot *dquot, const char warntype)
msg = " block quota exceeded.\r\n";
break;
}
- tty_write_message(current->signal->tty, msg);
+ tty_write_message(tty, msg);
out_lock:
mutex_unlock(&tty_mutex);
}
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index 52d1e36dc74..329efcd3d8c 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -25,6 +25,7 @@
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/fs_stack.h>
#include "ecryptfs_kernel.h"
/**
@@ -61,7 +62,7 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
struct inode *lower_inode =
ecryptfs_inode_to_lower(dentry->d_inode);
- ecryptfs_copy_attr_all(dentry->d_inode, lower_inode);
+ fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
}
out:
return rc;
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index f992533d169..afb64bdbe6a 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -28,6 +28,8 @@
#include <keys/user-type.h>
#include <linux/fs.h>
+#include <linux/fs_stack.h>
+#include <linux/namei.h>
#include <linux/scatterlist.h>
/* Version verification for shared data structures w/ userspace */
@@ -227,8 +229,7 @@ struct ecryptfs_inode_info {
/* dentry private data. Each dentry must keep track of a lower
* vfsmount too. */
struct ecryptfs_dentry_info {
- struct dentry *wdi_dentry;
- struct vfsmount *lower_mnt;
+ struct path lower_path;
struct ecryptfs_crypt_stat *crypt_stat;
};
@@ -355,26 +356,26 @@ ecryptfs_set_dentry_private(struct dentry *dentry,
static inline struct dentry *
ecryptfs_dentry_to_lower(struct dentry *dentry)
{
- return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry;
+ return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry;
}
static inline void
ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry)
{
- ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry =
+ ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry =
lower_dentry;
}
static inline struct vfsmount *
ecryptfs_dentry_to_lower_mnt(struct dentry *dentry)
{
- return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt;
+ return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt;
}
static inline void
ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
{
- ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt =
+ ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt =
lower_mnt;
}
@@ -413,9 +414,6 @@ int ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
const char *name, int length,
char **encoded_name);
struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry);
-void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src);
-void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src);
-void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src);
void ecryptfs_dump_hex(char *data, int bytes);
int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
int sg_size);
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 42099e779a5..c5a2e5298f1 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -30,6 +30,7 @@
#include <linux/security.h>
#include <linux/smp_lock.h>
#include <linux/compat.h>
+#include <linux/fs_stack.h>
#include "ecryptfs_kernel.h"
/**
@@ -75,7 +76,7 @@ static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
}
ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
if (expanding_file) {
- rc = ecryptfs_truncate(file->f_dentry, new_end_pos);
+ rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos);
if (rc) {
rv = rc;
ecryptfs_printk(KERN_ERR, "Error on attempt to "
@@ -116,8 +117,8 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
if (-EIOCBQUEUED == rc)
rc = wait_on_sync_kiocb(iocb);
if (rc >= 0) {
- lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry);
- lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_dentry);
+ lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
+ lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
touch_atime(lower_vfsmount, lower_dentry);
}
return rc;
@@ -176,10 +177,10 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
lower_file = ecryptfs_file_to_lower(file);
lower_file->f_pos = file->f_pos;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
memset(&buf, 0, sizeof(buf));
buf.dirent = dirent;
- buf.dentry = file->f_dentry;
+ buf.dentry = file->f_path.dentry;
buf.filldir = filldir;
retry:
buf.filldir_called = 0;
@@ -192,7 +193,7 @@ retry:
goto retry;
file->f_pos = lower_file->f_pos;
if (rc >= 0)
- ecryptfs_copy_attr_atime(inode, lower_file->f_dentry->d_inode);
+ fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode);
return rc;
}
@@ -239,7 +240,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
int rc = 0;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
- struct dentry *ecryptfs_dentry = file->f_dentry;
+ struct dentry *ecryptfs_dentry = file->f_path.dentry;
/* Private value of ecryptfs_dentry allocated in
* ecryptfs_lookup() */
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 8a1945a84c3..11f5e5076ae 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -30,6 +30,7 @@
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/crypto.h>
+#include <linux/fs_stack.h>
#include "ecryptfs_kernel.h"
static struct dentry *lock_parent(struct dentry *dentry)
@@ -53,48 +54,6 @@ static void unlock_dir(struct dentry *dir)
dput(dir);
}
-void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src)
-{
- i_size_write(dst, i_size_read((struct inode *)src));
- dst->i_blocks = src->i_blocks;
-}
-
-void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src)
-{
- dest->i_atime = src->i_atime;
-}
-
-static void ecryptfs_copy_attr_times(struct inode *dest,
- const struct inode *src)
-{
- dest->i_atime = src->i_atime;
- dest->i_mtime = src->i_mtime;
- dest->i_ctime = src->i_ctime;
-}
-
-static void ecryptfs_copy_attr_timesizes(struct inode *dest,
- const struct inode *src)
-{
- dest->i_atime = src->i_atime;
- dest->i_mtime = src->i_mtime;
- dest->i_ctime = src->i_ctime;
- ecryptfs_copy_inode_size(dest, src);
-}
-
-void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src)
-{
- dest->i_mode = src->i_mode;
- dest->i_nlink = src->i_nlink;
- dest->i_uid = src->i_uid;
- dest->i_gid = src->i_gid;
- dest->i_rdev = src->i_rdev;
- dest->i_atime = src->i_atime;
- dest->i_mtime = src->i_mtime;
- dest->i_ctime = src->i_ctime;
- dest->i_blkbits = src->i_blkbits;
- dest->i_flags = src->i_flags;
-}
-
/**
* ecryptfs_create_underlying_file
* @lower_dir_inode: inode of the parent in the lower fs of the new file
@@ -171,8 +130,8 @@ ecryptfs_do_create(struct inode *directory_inode,
ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
goto out_lock;
}
- ecryptfs_copy_attr_timesizes(directory_inode,
- lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
+ fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
out_lock:
unlock_dir(lower_dir_dentry);
out:
@@ -196,7 +155,7 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file,
struct ecryptfs_file_info tmp_file_info;
memset(&fake_file, 0, sizeof(fake_file));
- fake_file.f_dentry = ecryptfs_dentry;
+ fake_file.f_path.dentry = ecryptfs_dentry;
memset(&tmp_file_info, 0, sizeof(tmp_file_info));
ecryptfs_set_file_private(&fake_file, &tmp_file_info);
ecryptfs_set_file_lower(&fake_file, lower_file);
@@ -365,7 +324,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
"d_name.name = [%s]\n", lower_dentry,
lower_dentry->d_name.name);
lower_inode = lower_dentry->d_inode;
- ecryptfs_copy_attr_atime(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_atime(dir, lower_dir_dentry->d_inode);
BUG_ON(!atomic_read(&lower_dentry->d_count));
ecryptfs_set_dentry_private(dentry,
kmem_cache_alloc(ecryptfs_dentry_info_cache,
@@ -462,7 +421,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
if (rc)
goto out_lock;
- ecryptfs_copy_attr_timesizes(dir, lower_new_dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_new_dentry->d_inode);
+ fsstack_copy_inode_size(dir, lower_new_dentry->d_inode);
old_dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
i_size_write(new_dentry->d_inode, file_size_save);
@@ -488,7 +448,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
goto out_unlock;
}
- ecryptfs_copy_attr_times(dir, lower_dir_inode);
+ fsstack_copy_attr_times(dir, lower_dir_inode);
dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
dentry->d_inode->i_ctime = dir->i_ctime;
@@ -527,7 +487,8 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
if (rc)
goto out_lock;
- ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
out_lock:
unlock_dir(lower_dir_dentry);
dput(lower_dentry);
@@ -550,7 +511,8 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
if (rc)
goto out;
- ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
out:
unlock_dir(lower_dir_dentry);
@@ -573,7 +535,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
dput(lower_dentry);
if (!rc)
d_delete(lower_dentry);
- ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
unlock_dir(lower_dir_dentry);
if (!rc)
@@ -597,7 +559,8 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
if (rc)
goto out;
- ecryptfs_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
out:
unlock_dir(lower_dir_dentry);
if (!dentry->d_inode)
@@ -626,9 +589,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
lower_new_dir_dentry->d_inode, lower_new_dentry);
if (rc)
goto out_lock;
- ecryptfs_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
+ fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
if (new_dir != old_dir)
- ecryptfs_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
+ fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
out_lock:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_new_dentry->d_parent);
@@ -684,8 +647,8 @@ ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
rc = -EFAULT;
}
kfree(decoded_name);
- ecryptfs_copy_attr_atime(dentry->d_inode,
- lower_dentry->d_inode);
+ fsstack_copy_attr_atime(dentry->d_inode,
+ lower_dentry->d_inode);
}
out_free_lower_buf:
kfree(lower_buf);
@@ -791,7 +754,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
* the file in the underlying filesystem so that the
* truncation has an effect there as well. */
memset(&fake_ecryptfs_file, 0, sizeof(fake_ecryptfs_file));
- fake_ecryptfs_file.f_dentry = dentry;
+ fake_ecryptfs_file.f_path.dentry = dentry;
/* Released at out_free: label */
ecryptfs_set_file_private(&fake_ecryptfs_file,
kmem_cache_alloc(ecryptfs_file_info_cache,
@@ -915,7 +878,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
}
rc = notify_change(lower_dentry, ia);
out:
- ecryptfs_copy_attr_all(inode, lower_inode);
+ fsstack_copy_attr_all(inode, lower_inode, NULL);
return rc;
}
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 3ede12b2593..d0541ae8fab 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -35,6 +35,7 @@
#include <linux/pagemap.h>
#include <linux/key.h>
#include <linux/parser.h>
+#include <linux/fs_stack.h>
#include "ecryptfs_kernel.h"
/**
@@ -112,10 +113,10 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
d_add(dentry, inode);
else
d_instantiate(dentry, inode);
- ecryptfs_copy_attr_all(inode, lower_inode);
+ fsstack_copy_attr_all(inode, lower_inode, NULL);
/* This size will be overwritten for real files w/ headers and
* other metadata */
- ecryptfs_copy_inode_size(inode, lower_inode);
+ fsstack_copy_inode_size(inode, lower_inode);
out:
return rc;
}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 924dd90a4cf..06843d24f23 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -51,7 +51,7 @@ static struct page *ecryptfs_get1page(struct file *file, int index)
struct inode *inode;
struct address_space *mapping;
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
inode = dentry->d_inode;
mapping = inode->i_mapping;
page = read_cache_page(mapping, index,
@@ -84,7 +84,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros);
int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
{
int rc = 0;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
pgoff_t old_end_page_index = 0;
pgoff_t index = old_end_page_index;
@@ -218,7 +218,7 @@ int ecryptfs_do_readpage(struct file *file, struct page *page,
char *lower_page_data;
const struct address_space_operations *lower_a_ops;
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
lower_file = ecryptfs_file_to_lower(file);
lower_dentry = ecryptfs_dentry_to_lower(dentry);
inode = dentry->d_inode;
@@ -275,9 +275,9 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
int rc = 0;
struct ecryptfs_crypt_stat *crypt_stat;
- BUG_ON(!(file && file->f_dentry && file->f_dentry->d_inode));
- crypt_stat =
- &ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat;
+ BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode));
+ crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
+ ->crypt_stat;
if (!crypt_stat
|| !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
|| ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
@@ -638,8 +638,8 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
lower_inode = ecryptfs_inode_to_lower(inode);
lower_file = ecryptfs_file_to_lower(file);
mutex_lock(&lower_inode->i_mutex);
- crypt_stat =
- &ecryptfs_inode_to_private(file->f_dentry->d_inode)->crypt_stat;
+ crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
+ ->crypt_stat;
if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
"crypt_stat at memory location [%p]\n", crypt_stat);
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index 17f5b2d3c16..b46c488eefc 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -20,7 +20,7 @@ struct inode_operations efs_dir_inode_operations = {
};
static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct buffer_head *bh;
struct efs_dir *dirblock;
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 88a6f8d0b88..3ae644e7e86 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -795,8 +795,8 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
goto eexit_4;
dentry->d_op = &eventpollfs_dentry_operations;
d_add(dentry, inode);
- file->f_vfsmnt = mntget(eventpoll_mnt);
- file->f_dentry = dentry;
+ file->f_path.mnt = mntget(eventpoll_mnt);
+ file->f_path.dentry = dentry;
file->f_mapping = inode->i_mapping;
file->f_pos = 0;
diff --git a/fs/exec.c b/fs/exec.c
index add0e03c3ea..11fe93f7363 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -38,6 +38,7 @@
#include <linux/binfmts.h>
#include <linux/swap.h>
#include <linux/utsname.h>
+#include <linux/pid_namespace.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/proc_fs.h>
@@ -620,8 +621,8 @@ static int de_thread(struct task_struct *tsk)
* Reparenting needs write_lock on tasklist_lock,
* so it is safe to do it under read_lock.
*/
- if (unlikely(tsk->group_leader == child_reaper))
- child_reaper = tsk;
+ if (unlikely(tsk->group_leader == child_reaper(tsk)))
+ tsk->nsproxy->pid_ns->child_reaper = tsk;
zap_other_threads(tsk);
read_unlock(&tasklist_lock);
@@ -782,7 +783,7 @@ static void flush_old_files(struct files_struct * files)
j++;
i = j * __NFDBITS;
fdt = files_fdtable(files);
- if (i >= fdt->max_fds || i >= fdt->max_fdset)
+ if (i >= fdt->max_fds)
break;
set = fdt->close_on_exec->fds_bits[j];
if (!set)
@@ -912,7 +913,7 @@ EXPORT_SYMBOL(flush_old_exec);
int prepare_binprm(struct linux_binprm *bprm)
{
int mode;
- struct inode * inode = bprm->file->f_dentry->d_inode;
+ struct inode * inode = bprm->file->f_path.dentry->d_inode;
int retval;
mode = inode->i_mode;
@@ -922,7 +923,7 @@ int prepare_binprm(struct linux_binprm *bprm)
bprm->e_uid = current->euid;
bprm->e_gid = current->egid;
- if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {
+ if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
/* Set-uid? */
if (mode & S_ISUID) {
current->personality &= ~PER_CLEAR_ON_SETID;
@@ -1519,10 +1520,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
0600);
if (IS_ERR(file))
goto fail_unlock;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (inode->i_nlink > 1)
goto close_fail; /* multiple links - don't dump */
- if (!ispipe && d_unhashed(file->f_dentry))
+ if (!ispipe && d_unhashed(file->f_path.dentry))
goto close_fail;
/* AK: actually i see no reason to not allow this for named pipes etc.,
@@ -1533,7 +1534,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
goto close_fail;
if (!file->f_op->write)
goto close_fail;
- if (!ispipe && do_truncate(file->f_dentry, 0, 0, file) != 0)
+ if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
goto close_fail;
retval = binfmt->core_dump(signr, regs, file);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 3e7a84a1e50..0b02ba9642d 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -248,7 +248,7 @@ static int
ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
{
loff_t pos = filp->f_pos;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index e3cf8c81507..4b099d31071 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -90,7 +90,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
#ifdef CONFIG_COMPAT
long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int ret;
/* These are just misnamed, they actually get/put from/to user an int */
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 255cef5f742..6347c2dbdd8 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -597,8 +597,6 @@ static int ext2_check_descriptors (struct super_block * sb)
return 1;
}
-#define log2(n) ffz(~(n))
-
/*
* Maximal file size. There is a direct, and {,double-,triple-}indirect
* block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
@@ -834,9 +832,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_sbh = bh;
sbi->s_mount_state = le16_to_cpu(es->s_state);
sbi->s_addr_per_block_bits =
- log2 (EXT2_ADDR_PER_BLOCK(sb));
+ ilog2 (EXT2_ADDR_PER_BLOCK(sb));
sbi->s_desc_per_block_bits =
- log2 (EXT2_DESC_PER_BLOCK(sb));
+ ilog2 (EXT2_DESC_PER_BLOCK(sb));
if (sb->s_magic != EXT2_SUPER_MAGIC)
goto cantfind_ext2;
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 5a9313ecd4e..665adee99b3 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -103,7 +103,7 @@ static int ext3_readdir(struct file * filp,
struct ext3_dir_entry_2 *de;
struct super_block *sb;
int err;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int ret = 0;
sb = inode->i_sb;
@@ -122,7 +122,7 @@ static int ext3_readdir(struct file * filp,
* We don't set the inode dirty flag since it's not
* critical that it get flushed back to the disk.
*/
- EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
+ EXT3_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
}
#endif
stored = 0;
@@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent,
{
struct dir_private_info *info = filp->private_data;
loff_t curr_pos;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block * sb;
int error;
@@ -432,7 +432,7 @@ static int ext3_dx_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
struct dir_private_info *info = filp->private_data;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct fname *fname;
int ret;
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index e96c388047e..881f6365c41 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -52,7 +52,7 @@ ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
ssize_t ret;
int err;
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 12daa686957..9b8090d94e6 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -257,7 +257,7 @@ flags_err:
#ifdef CONFIG_COMPAT
long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int ret;
/* These are just misnamed, they actually get/put from/to user an int */
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 60d2f9dbdb0..4df39c4315e 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -602,7 +602,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
start_minor_hash));
- dir = dir_file->f_dentry->d_inode;
+ dir = dir_file->f_path.dentry->d_inode;
if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) {
hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
@@ -613,7 +613,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
}
hinfo.hash = start_hash;
hinfo.minor_hash = 0;
- frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
+ frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
if (!frame)
return err;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 580b8a6ca97..b34886734a4 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1347,8 +1347,6 @@ static void ext3_orphan_cleanup (struct super_block * sb,
sb->s_flags = s_flags; /* Restore MS_RDONLY status */
}
-#define log2(n) ffz(~(n))
-
/*
* Maximal file size. There is a direct, and {,double-,triple-}indirect
* block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
@@ -1597,8 +1595,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);
sbi->s_sbh = bh;
sbi->s_mount_state = le16_to_cpu(es->s_state);
- sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
- sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
+ sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb));
+ sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb));
for (i=0; i < 4; i++)
sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
sbi->s_def_hash_version = es->s_def_hash_version;
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index f2ed3e7fb9f..da80368b66f 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -103,7 +103,7 @@ static int ext4_readdir(struct file * filp,
struct ext4_dir_entry_2 *de;
struct super_block *sb;
int err;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int ret = 0;
sb = inode->i_sb;
@@ -122,7 +122,7 @@ static int ext4_readdir(struct file * filp,
* We don't set the inode dirty flag since it's not
* critical that it get flushed back to the disk.
*/
- EXT4_I(filp->f_dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
+ EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
}
#endif
stored = 0;
@@ -402,7 +402,7 @@ static int call_filldir(struct file * filp, void * dirent,
{
struct dir_private_info *info = filp->private_data;
loff_t curr_pos;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block * sb;
int error;
@@ -432,7 +432,7 @@ static int ext4_dx_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
struct dir_private_info *info = filp->private_data;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct fname *fname;
int ret;
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 0b622c0624b..3bbc24b5878 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -52,7 +52,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
ssize_t ret;
int err;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1d85d4ec959..a127cc03c9f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1232,7 +1232,7 @@ retry:
from, to, NULL, do_journal_get_write_access);
if (ret)
/* fatal error, just put the handle and return */
- journal_stop(handle);
+ ext4_journal_stop(handle);
}
return ret;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 22a737c306c..500567dd53b 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -256,7 +256,7 @@ flags_err:
#ifdef CONFIG_COMPAT
long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int ret;
/* These are just misnamed, they actually get/put from/to user an int */
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 859990eac50..e5a74a5ac26 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -602,7 +602,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
start_minor_hash));
- dir = dir_file->f_dentry->d_inode;
+ dir = dir_file->f_path.dentry->d_inode;
if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
@@ -613,7 +613,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
}
hinfo.hash = start_hash;
hinfo.minor_hash = 0;
- frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
+ frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
if (!frame)
return err;
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 69c439f4438..c16af246d24 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -579,7 +579,7 @@ parse_record:
if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
inum = inode->i_ino;
else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
- inum = parent_ino(filp->f_dentry);
+ inum = parent_ino(filp->f_path.dentry);
} else {
loff_t i_pos = fat_make_i_pos(sb, bh, de);
struct inode *tmp = fat_iget(sb, i_pos);
@@ -643,7 +643,7 @@ out:
static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
}
@@ -782,7 +782,7 @@ static long fat_compat_dir_ioctl(struct file *file, unsigned cmd,
set_fs(KERNEL_DS);
lock_kernel();
- ret = fat_dir_ioctl(file->f_dentry->d_inode, file,
+ ret = fat_dir_ioctl(file->f_path.dentry->d_inode, file,
cmd, (unsigned long) &d);
unlock_kernel();
set_fs(oldfs);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 0aa813d944a..c1237b70c1f 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
}
/* This MUST be done before doing anything irreversible... */
- err = notify_change(filp->f_dentry, &ia);
+ err = notify_change(filp->f_path.dentry, &ia);
if (err)
goto up;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 4740d35e52c..8e382a5d51b 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -77,10 +77,9 @@ repeat:
start = files->next_fd;
newfd = start;
- if (start < fdt->max_fdset) {
+ if (start < fdt->max_fds)
newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
- fdt->max_fdset, start);
- }
+ fdt->max_fds, start);
error = -EMFILE;
if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
@@ -204,7 +203,7 @@ asmlinkage long sys_dup(unsigned int fildes)
static int setfl(int fd, struct file * filp, unsigned long arg)
{
- struct inode * inode = filp->f_dentry->d_inode;
+ struct inode * inode = filp->f_path.dentry->d_inode;
int error = 0;
/*
diff --git a/fs/file.c b/fs/file.c
index 51aef675470..c5575de0111 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -32,46 +32,28 @@ struct fdtable_defer {
*/
static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
-
-/*
- * Allocate an fd array, using kmalloc or vmalloc.
- * Note: the array isn't cleared at allocation time.
- */
-struct file ** alloc_fd_array(int num)
+static inline void * alloc_fdmem(unsigned int size)
{
- struct file **new_fds;
- int size = num * sizeof(struct file *);
-
if (size <= PAGE_SIZE)
- new_fds = (struct file **) kmalloc(size, GFP_KERNEL);
- else
- new_fds = (struct file **) vmalloc(size);
- return new_fds;
+ return kmalloc(size, GFP_KERNEL);
+ else
+ return vmalloc(size);
}
-void free_fd_array(struct file **array, int num)
+static inline void free_fdarr(struct fdtable *fdt)
{
- int size = num * sizeof(struct file *);
-
- if (!array) {
- printk (KERN_ERR "free_fd_array: array = 0 (num = %d)\n", num);
- return;
- }
-
- if (num <= NR_OPEN_DEFAULT) /* Don't free the embedded fd array! */
- return;
- else if (size <= PAGE_SIZE)
- kfree(array);
+ if (fdt->max_fds <= (PAGE_SIZE / sizeof(struct file *)))
+ kfree(fdt->fd);
else
- vfree(array);
+ vfree(fdt->fd);
}
-static void __free_fdtable(struct fdtable *fdt)
+static inline void free_fdset(struct fdtable *fdt)
{
- free_fdset(fdt->open_fds, fdt->max_fdset);
- free_fdset(fdt->close_on_exec, fdt->max_fdset);
- free_fd_array(fdt->fd, fdt->max_fds);
- kfree(fdt);
+ if (fdt->max_fds <= (PAGE_SIZE * BITS_PER_BYTE / 2))
+ kfree(fdt->open_fds);
+ else
+ vfree(fdt->open_fds);
}
static void free_fdtable_work(struct work_struct *work)
@@ -86,41 +68,32 @@ static void free_fdtable_work(struct work_struct *work)
spin_unlock_bh(&f->lock);
while(fdt) {
struct fdtable *next = fdt->next;
- __free_fdtable(fdt);
+ vfree(fdt->fd);
+ free_fdset(fdt);
+ kfree(fdt);
fdt = next;
}
}
-static void free_fdtable_rcu(struct rcu_head *rcu)
+void free_fdtable_rcu(struct rcu_head *rcu)
{
struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
- int fdset_size, fdarray_size;
struct fdtable_defer *fddef;
BUG_ON(!fdt);
- fdset_size = fdt->max_fdset / 8;
- fdarray_size = fdt->max_fds * sizeof(struct file *);
- if (fdt->free_files) {
+ if (fdt->max_fds <= NR_OPEN_DEFAULT) {
/*
- * The this fdtable was embedded in the files structure
- * and the files structure itself was getting destroyed.
- * It is now safe to free the files structure.
+ * This fdtable is embedded in the files structure and that
+ * structure itself is getting destroyed.
*/
- kmem_cache_free(files_cachep, fdt->free_files);
+ kmem_cache_free(files_cachep,
+ container_of(fdt, struct files_struct, fdtab));
return;
}
- if (fdt->max_fdset <= EMBEDDED_FD_SET_SIZE &&
- fdt->max_fds <= NR_OPEN_DEFAULT) {
- /*
- * The fdtable was embedded
- */
- return;
- }
- if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) {
- kfree(fdt->open_fds);
- kfree(fdt->close_on_exec);
+ if (fdt->max_fds <= (PAGE_SIZE / sizeof(struct file *))) {
kfree(fdt->fd);
+ kfree(fdt->open_fds);
kfree(fdt);
} else {
fddef = &get_cpu_var(fdtable_defer_list);
@@ -134,136 +107,74 @@ static void free_fdtable_rcu(struct rcu_head *rcu)
}
}
-void free_fdtable(struct fdtable *fdt)
-{
- if (fdt->free_files ||
- fdt->max_fdset > EMBEDDED_FD_SET_SIZE ||
- fdt->max_fds > NR_OPEN_DEFAULT)
- call_rcu(&fdt->rcu, free_fdtable_rcu);
-}
-
/*
* Expand the fdset in the files_struct. Called with the files spinlock
* held for write.
*/
-static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt)
+static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
{
- int i;
- int count;
-
- BUG_ON(nfdt->max_fdset < fdt->max_fdset);
- BUG_ON(nfdt->max_fds < fdt->max_fds);
- /* Copy the existing tables and install the new pointers */
-
- i = fdt->max_fdset / (sizeof(unsigned long) * 8);
- count = (nfdt->max_fdset - fdt->max_fdset) / 8;
+ unsigned int cpy, set;
- /*
- * Don't copy the entire array if the current fdset is
- * not yet initialised.
- */
- if (i) {
- memcpy (nfdt->open_fds, fdt->open_fds,
- fdt->max_fdset/8);
- memcpy (nfdt->close_on_exec, fdt->close_on_exec,
- fdt->max_fdset/8);
- memset (&nfdt->open_fds->fds_bits[i], 0, count);
- memset (&nfdt->close_on_exec->fds_bits[i], 0, count);
- }
-
- /* Don't copy/clear the array if we are creating a new
- fd array for fork() */
- if (fdt->max_fds) {
- memcpy(nfdt->fd, fdt->fd,
- fdt->max_fds * sizeof(struct file *));
- /* clear the remainder of the array */
- memset(&nfdt->fd[fdt->max_fds], 0,
- (nfdt->max_fds - fdt->max_fds) *
- sizeof(struct file *));
- }
-}
-
-/*
- * Allocate an fdset array, using kmalloc or vmalloc.
- * Note: the array isn't cleared at allocation time.
- */
-fd_set * alloc_fdset(int num)
-{
- fd_set *new_fdset;
- int size = num / 8;
+ BUG_ON(nfdt->max_fds < ofdt->max_fds);
+ if (ofdt->max_fds == 0)
+ return;
- if (size <= PAGE_SIZE)
- new_fdset = (fd_set *) kmalloc(size, GFP_KERNEL);
- else
- new_fdset = (fd_set *) vmalloc(size);
- return new_fdset;
+ cpy = ofdt->max_fds * sizeof(struct file *);
+ set = (nfdt->max_fds - ofdt->max_fds) * sizeof(struct file *);
+ memcpy(nfdt->fd, ofdt->fd, cpy);
+ memset((char *)(nfdt->fd) + cpy, 0, set);
+
+ cpy = ofdt->max_fds / BITS_PER_BYTE;
+ set = (nfdt->max_fds - ofdt->max_fds) / BITS_PER_BYTE;
+ memcpy(nfdt->open_fds, ofdt->open_fds, cpy);
+ memset((char *)(nfdt->open_fds) + cpy, 0, set);
+ memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy);
+ memset((char *)(nfdt->close_on_exec) + cpy, 0, set);
}
-void free_fdset(fd_set *array, int num)
+static struct fdtable * alloc_fdtable(unsigned int nr)
{
- if (num <= EMBEDDED_FD_SET_SIZE) /* Don't free an embedded fdset */
- return;
- else if (num <= 8 * PAGE_SIZE)
- kfree(array);
- else
- vfree(array);
-}
+ struct fdtable *fdt;
+ char *data;
-static struct fdtable *alloc_fdtable(int nr)
-{
- struct fdtable *fdt = NULL;
- int nfds = 0;
- fd_set *new_openset = NULL, *new_execset = NULL;
- struct file **new_fds;
+ /*
+ * Figure out how many fds we actually want to support in this fdtable.
+ * Allocation steps are keyed to the size of the fdarray, since it
+ * grows far faster than any of the other dynamic data. We try to fit
+ * the fdarray into comfortable page-tuned chunks: starting at 1024B
+ * and growing in powers of two from there on.
+ */
+ nr /= (1024 / sizeof(struct file *));
+ nr = roundup_pow_of_two(nr + 1);
+ nr *= (1024 / sizeof(struct file *));
+ if (nr > NR_OPEN)
+ nr = NR_OPEN;
- fdt = kzalloc(sizeof(*fdt), GFP_KERNEL);
+ fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL);
if (!fdt)
- goto out;
-
- nfds = max_t(int, 8 * L1_CACHE_BYTES, roundup_pow_of_two(nr + 1));
- if (nfds > NR_OPEN)
- nfds = NR_OPEN;
+ goto out;
+ fdt->max_fds = nr;
+ data = alloc_fdmem(nr * sizeof(struct file *));
+ if (!data)
+ goto out_fdt;
+ fdt->fd = (struct file **)data;
+ data = alloc_fdmem(max_t(unsigned int,
+ 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES));
+ if (!data)
+ goto out_arr;
+ fdt->open_fds = (fd_set *)data;
+ data += nr / BITS_PER_BYTE;
+ fdt->close_on_exec = (fd_set *)data;
+ INIT_RCU_HEAD(&fdt->rcu);
+ fdt->next = NULL;
- new_openset = alloc_fdset(nfds);
- new_execset = alloc_fdset(nfds);
- if (!new_openset || !new_execset)
- goto out;
- fdt->open_fds = new_openset;
- fdt->close_on_exec = new_execset;
- fdt->max_fdset = nfds;
-
- nfds = NR_OPEN_DEFAULT;
- /*
- * Expand to the max in easy steps, and keep expanding it until
- * we have enough for the requested fd array size.
- */
- do {
-#if NR_OPEN_DEFAULT < 256
- if (nfds < 256)
- nfds = 256;
- else
-#endif
- if (nfds < (PAGE_SIZE / sizeof(struct file *)))
- nfds = PAGE_SIZE / sizeof(struct file *);
- else {
- nfds = nfds * 2;
- if (nfds > NR_OPEN)
- nfds = NR_OPEN;
- }
- } while (nfds <= nr);
- new_fds = alloc_fd_array(nfds);
- if (!new_fds)
- goto out2;
- fdt->fd = new_fds;
- fdt->max_fds = nfds;
- fdt->free_files = NULL;
return fdt;
-out2:
- nfds = fdt->max_fdset;
-out:
- free_fdset(new_openset, nfds);
- free_fdset(new_execset, nfds);
+
+out_arr:
+ free_fdarr(fdt);
+out_fdt:
kfree(fdt);
+out:
return NULL;
}
@@ -290,14 +201,17 @@ static int expand_fdtable(struct files_struct *files, int nr)
* we dropped the lock
*/
cur_fdt = files_fdtable(files);
- if (nr >= cur_fdt->max_fds || nr >= cur_fdt->max_fdset) {
+ if (nr >= cur_fdt->max_fds) {
/* Continue as planned */
copy_fdtable(new_fdt, cur_fdt);
rcu_assign_pointer(files->fdt, new_fdt);
- free_fdtable(cur_fdt);
+ if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
+ free_fdtable(cur_fdt);
} else {
/* Somebody else expanded, so undo our attempt */
- __free_fdtable(new_fdt);
+ free_fdarr(new_fdt);
+ free_fdset(new_fdt);
+ kfree(new_fdt);
}
return 1;
}
@@ -316,11 +230,10 @@ int expand_files(struct files_struct *files, int nr)
fdt = files_fdtable(files);
/* Do we need to expand? */
- if (nr < fdt->max_fdset && nr < fdt->max_fds)
+ if (nr < fdt->max_fds)
return 0;
/* Can we expand? */
- if (fdt->max_fdset >= NR_OPEN || fdt->max_fds >= NR_OPEN ||
- nr >= NR_OPEN)
+ if (nr >= NR_OPEN)
return -EMFILE;
/* All good, so we try */
diff --git a/fs/file_table.c b/fs/file_table.c
index 24f25a057d9..4c17a18d8c1 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -152,8 +152,8 @@ EXPORT_SYMBOL(fput);
*/
void fastcall __fput(struct file *file)
{
- struct dentry *dentry = file->f_dentry;
- struct vfsmount *mnt = file->f_vfsmnt;
+ struct dentry *dentry = file->f_path.dentry;
+ struct vfsmount *mnt = file->f_path.mnt;
struct inode *inode = dentry->d_inode;
might_sleep();
@@ -176,8 +176,8 @@ void fastcall __fput(struct file *file)
put_write_access(inode);
put_pid(file->f_owner.pid);
file_kill(file);
- file->f_dentry = NULL;
- file->f_vfsmnt = NULL;
+ file->f_path.dentry = NULL;
+ file->f_path.mnt = NULL;
file_free(file);
dput(dentry);
mntput(mnt);
@@ -271,7 +271,7 @@ int fs_may_remount_ro(struct super_block *sb)
file_list_lock();
list_for_each(p, &sb->s_files) {
struct file *file = list_entry(p, struct file, f_u.fu_list);
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
/* File with pending delete? */
if (inode->i_nlink == 0)
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 43886fa00a2..3995d7fbeda 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -240,7 +240,7 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
static int
vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
{
- struct inode *ip = fp->f_dentry->d_inode;
+ struct inode *ip = fp->f_path.dentry->d_inode;
struct super_block *sbp = ip->i_sb;
u_long bsize = sbp->s_blocksize;
u_long page, npages, block, pblocks, nblocks, offset;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index c403b66ec83..a4b142a6a2c 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -251,8 +251,19 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
WARN_ON(inode->i_state & I_WILL_FREE);
if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) {
+ struct address_space *mapping = inode->i_mapping;
+ int ret;
+
list_move(&inode->i_list, &inode->i_sb->s_dirty);
- return 0;
+
+ /*
+ * Even if we don't actually write the inode itself here,
+ * we can at least start some of the data writeout..
+ */
+ spin_unlock(&inode_lock);
+ ret = do_writepages(mapping, wbc);
+ spin_lock(&inode_lock);
+ return ret;
}
/*
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 16b39c053d4..1794305f9ed 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -23,7 +23,7 @@ static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
{
struct fuse_conn *fc;
mutex_lock(&fuse_mutex);
- fc = file->f_dentry->d_inode->i_private;
+ fc = file->f_path.dentry->d_inode->i_private;
if (fc)
fc = fuse_conn_get(fc);
mutex_unlock(&fuse_mutex);
@@ -193,8 +193,12 @@ static int fuse_ctl_get_sb(struct file_system_type *fs_type, int flags,
static void fuse_ctl_kill_sb(struct super_block *sb)
{
+ struct fuse_conn *fc;
+
mutex_lock(&fuse_mutex);
fuse_control_sb = NULL;
+ list_for_each_entry(fc, &fuse_conn_list, entry)
+ fc->ctl_ndents = 0;
mutex_unlock(&fuse_mutex);
kill_litter_super(sb);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 1cabdb229ad..40080477ceb 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -856,7 +856,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
int err;
size_t nbytes;
struct page *page;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 128f79c4080..f63efe1337e 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -141,8 +141,8 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir)
isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
/* Hold vfsmount and dentry until release is finished */
- req->vfsmount = mntget(file->f_vfsmnt);
- req->dentry = dget(file->f_dentry);
+ req->vfsmount = mntget(file->f_path.mnt);
+ req->dentry = dget(file->f_path.dentry);
request_send_background(fc, req);
}
@@ -184,7 +184,7 @@ static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
static int fuse_flush(struct file *file, fl_owner_t id)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
struct fuse_req *req;
@@ -483,10 +483,8 @@ static int fuse_commit_write(struct file *file, struct page *page,
i_size_write(inode, pos);
spin_unlock(&fc->lock);
- if (offset == 0 && to == PAGE_CACHE_SIZE) {
- clear_page_dirty(page);
+ if (offset == 0 && to == PAGE_CACHE_SIZE)
SetPageUptodate(page);
- }
}
fuse_invalidate_attr(inode);
return err;
@@ -533,7 +531,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
size_t count, loff_t *ppos, int write)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
size_t nmax = write ? fc->max_write : fc->max_read;
loff_t pos = *ppos;
@@ -607,7 +605,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
ssize_t res;
/* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex);
@@ -662,7 +660,7 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
static void fuse_lk_fill(struct fuse_req *req, struct file *file,
const struct file_lock *fl, int opcode, pid_t pid)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
struct fuse_lk_in *arg = &req->misc.lk_in;
@@ -682,7 +680,7 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
static int fuse_getlk(struct file *file, struct file_lock *fl)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_lk_out outarg;
@@ -707,7 +705,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
static int fuse_setlk(struct file *file, struct file_lock *fl)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
@@ -734,7 +732,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
int err;
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index c0791cbacad..6a2ffa2db14 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -34,7 +34,9 @@ config GFS2_FS_LOCKING_NOLOCK
config GFS2_FS_LOCKING_DLM
tristate "GFS2 DLM locking module"
- depends on GFS2_FS
+ depends on GFS2_FS && NET && INET && (IPV6 || IPV6=n)
+ select IP_SCTP if DLM_SCTP
+ select CONFIGFS_FS
select DLM
help
Multiple node locking module for GFS2
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index b3f1e0349ae..faa07e4b97d 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -247,7 +247,7 @@ static const u32 gfs2_to_fsflags[32] = {
static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
int error;
@@ -305,7 +305,7 @@ void gfs2_set_inode_flags(struct inode *inode)
*/
static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct buffer_head *bh;
@@ -588,7 +588,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
{
struct gfs2_file *fp = file->private_data;
struct gfs2_holder *fl_gh = &fp->f_fl_gh;
- struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode);
+ struct gfs2_inode *ip = GFS2_I(file->f_path.dentry->d_inode);
struct gfs2_glock *gl;
unsigned int state;
int flags;
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index d14e139d267..ee80b8a5e7b 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -867,9 +867,9 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
error = -EBUSY;
goto error;
}
- mutex_lock(&sb->s_bdev->bd_mount_mutex);
+ down(&sb->s_bdev->bd_mount_sem);
new = sget(fs_type, test_bdev_super, set_bdev_super, sb->s_bdev);
- mutex_unlock(&sb->s_bdev->bd_mount_mutex);
+ up(&sb->s_bdev->bd_mount_sem);
if (IS_ERR(new)) {
error = PTR_ERR(new);
goto error;
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 37d681b4f21..e2e0358da33 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -53,7 +53,7 @@ done:
*/
static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
int len, err;
char strbuf[HFS_MAX_NAMELEN];
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 02f5573e034..5cb7f8fee8d 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -102,7 +102,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
const struct iovec *iov, loff_t offset, unsigned long nr_segs)
{
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+ struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, hfs_get_block, NULL);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 7e309751645..e886ac8460d 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -111,7 +111,7 @@ fail:
static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
int len, err;
char strbuf[HFSPLUS_MAX_STRLEN + 1];
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 9e367524963..75e8c4d8aac 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -97,7 +97,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
const struct iovec *iov, loff_t offset, unsigned long nr_segs)
{
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+ struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, hfsplus_get_block, NULL);
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index cca3fb693f9..70543b17e4c 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -76,7 +76,7 @@ extern int make_symlink(const char *from, const char *to);
extern int unlink_file(const char *file);
extern int do_mkdir(const char *file, int mode);
extern int do_rmdir(const char *file);
-extern int do_mknod(const char *file, int mode, int dev);
+extern int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor);
extern int link_file(const char *from, const char *to);
extern int do_readlink(char *file, char *buf, int size);
extern int rename_file(char *from, char *to);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index b6bd33ca373..69a376f35a6 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -35,7 +35,7 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
}
-#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode)
+#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
int hostfs_d_delete(struct dentry *dentry)
{
@@ -325,7 +325,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
unsigned long long next, ino;
int error, len;
- name = dentry_name(file->f_dentry, 0);
+ name = dentry_name(file->f_path.dentry, 0);
if(name == NULL) return(-ENOMEM);
dir = open_dir(name, &error);
kfree(name);
@@ -366,7 +366,7 @@ int hostfs_file_open(struct inode *ino, struct file *file)
if(w)
r = 1;
- name = dentry_name(file->f_dentry, 0);
+ name = dentry_name(file->f_path.dentry, 0);
if(name == NULL)
return(-ENOMEM);
@@ -755,7 +755,7 @@ int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
goto out_put;
init_special_inode(inode, mode, dev);
- err = do_mknod(name, mode, dev);
+ err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
if(err)
goto out_free;
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 23b7cee7212..1ed5ea389f1 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -295,11 +295,11 @@ int do_rmdir(const char *file)
return(0);
}
-int do_mknod(const char *file, int mode, int dev)
+int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
{
int err;
- err = mknod(file, mode, dev);
+ err = mknod(file, mode, makedev(major, minor));
if(err) return(-errno);
return(0);
}
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 594f9c428fc..6916c41d701 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -24,7 +24,7 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
loff_t new_off = off + (whence == 1 ? filp->f_pos : 0);
loff_t pos;
struct quad_buffer_head qbh;
- struct inode *i = filp->f_dentry->d_inode;
+ struct inode *i = filp->f_path.dentry->d_inode;
struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
struct super_block *s = i->i_sb;
@@ -52,7 +52,7 @@ fail:
static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
struct quad_buffer_head qbh;
struct hpfs_dirent *de;
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 8b94d24855f..fb4c8915010 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -115,7 +115,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
retval = do_sync_write(file, buf, count, ppos);
if (retval > 0)
- hpfs_i(file->f_dentry->d_inode)->i_dirty = 1;
+ hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
return retval;
}
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index 642675fc394..afd340a45da 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -221,7 +221,7 @@ static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t n;
- read = file->f_dentry->d_inode->i_fop->read;
+ read = file->f_path.dentry->d_inode->i_fop->read;
if(!is_user)
set_fs(KERNEL_DS);
@@ -320,7 +320,7 @@ static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
int err;
- write = proc_file->f_dentry->d_inode->i_fop->write;
+ write = proc_file->f_path.dentry->d_inode->i_fop->write;
proc_file->f_pos = file->f_pos;
err = (*write)(proc_file, buf, len, &proc_file->f_pos);
@@ -464,7 +464,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
if(data == NULL)
goto out;
- host_file = dentry_name(file->f_dentry, strlen("/rw"));
+ host_file = dentry_name(file->f_path.dentry, strlen("/rw"));
if(host_file == NULL)
goto out_free2;
@@ -547,7 +547,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
loff_t (*llseek)(struct file *, loff_t, int);
loff_t ret;
- llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
+ llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek;
if(llseek != NULL){
ret = (*llseek)(proc_file, off, where);
if(ret < 0)
@@ -591,10 +591,10 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
struct hppfs_dirent dirent = ((struct hppfs_dirent)
{ .vfs_dirent = ent,
.filldir = filldir,
- .dentry = file->f_dentry } );
+ .dentry = file->f_path.dentry } );
int err;
- readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
+ readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir;
proc_file->f_pos = file->f_pos;
err = (*readdir)(proc_file, &dirent, hppfs_filldir);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 0706f5aac6a..4f4cd132b57 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -58,7 +58,7 @@ static void huge_pagevec_release(struct pagevec *pvec)
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
loff_t len, vma_len;
int ret;
@@ -176,7 +176,7 @@ static int hugetlbfs_commit_write(struct file *file,
static void truncate_huge_page(struct page *page)
{
- clear_page_dirty(page);
+ cancel_dirty_page(page, /* No IO accounting for huge pages? */0);
ClearPageUptodate(page);
remove_from_page_cache(page);
put_page(page);
@@ -774,8 +774,8 @@ struct file *hugetlb_zero_setup(size_t size)
d_instantiate(dentry, inode);
inode->i_size = size;
inode->i_nlink = 0;
- file->f_vfsmnt = mntget(hugetlbfs_vfsmount);
- file->f_dentry = dentry;
+ file->f_path.mnt = mntget(hugetlbfs_vfsmount);
+ file->f_path.dentry = dentry;
file->f_mapping = inode->i_mapping;
file->f_op = &hugetlbfs_file_operations;
file->f_mode = FMODE_WRITE | FMODE_READ;
diff --git a/fs/inode.c b/fs/inode.c
index 9ecccab7326..bf21dc6d0db 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1144,7 +1144,6 @@ sector_t bmap(struct inode * inode, sector_t block)
res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
return res;
}
-
EXPORT_SYMBOL(bmap);
/**
@@ -1163,27 +1162,43 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
if (IS_RDONLY(inode))
return;
-
- if ((inode->i_flags & S_NOATIME) ||
- (inode->i_sb->s_flags & MS_NOATIME) ||
- ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
+ if (inode->i_flags & S_NOATIME)
+ return;
+ if (inode->i_sb->s_flags & MS_NOATIME)
+ return;
+ if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
return;
/*
* We may have a NULL vfsmount when coming from NFSD
*/
- if (mnt &&
- ((mnt->mnt_flags & MNT_NOATIME) ||
- ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
- return;
+ if (mnt) {
+ if (mnt->mnt_flags & MNT_NOATIME)
+ return;
+ if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+ return;
- now = current_fs_time(inode->i_sb);
- if (!timespec_equal(&inode->i_atime, &now)) {
- inode->i_atime = now;
- mark_inode_dirty_sync(inode);
+ if (mnt->mnt_flags & MNT_RELATIME) {
+ /*
+ * With relative atime, only update atime if the
+ * previous atime is earlier than either the ctime or
+ * mtime.
+ */
+ if (timespec_compare(&inode->i_mtime,
+ &inode->i_atime) < 0 &&
+ timespec_compare(&inode->i_ctime,
+ &inode->i_atime) < 0)
+ return;
+ }
}
-}
+ now = current_fs_time(inode->i_sb);
+ if (timespec_equal(&inode->i_atime, &now))
+ return;
+
+ inode->i_atime = now;
+ mark_inode_dirty_sync(inode);
+}
EXPORT_SYMBOL(touch_atime);
/**
@@ -1200,7 +1215,7 @@ EXPORT_SYMBOL(touch_atime);
void file_update_time(struct file *file)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct timespec now;
int sync_it = 0;
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index e1956e6f116..55f6da55b7c 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -570,9 +570,9 @@ asmlinkage long sys_inotify_init(void)
dev->ih = ih;
filp->f_op = &inotify_fops;
- filp->f_vfsmnt = mntget(inotify_mnt);
- filp->f_dentry = dget(inotify_mnt->mnt_root);
- filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+ filp->f_path.mnt = mntget(inotify_mnt);
+ filp->f_path.dentry = dget(inotify_mnt->mnt_root);
+ filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
filp->f_mode = FMODE_READ;
filp->f_flags = O_RDONLY;
filp->private_data = dev;
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 4b7660b09ac..ff61772ceed 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -31,7 +31,7 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
goto out;
} else if (filp->f_op->ioctl) {
lock_kernel();
- error = filp->f_op->ioctl(filp->f_dentry->d_inode,
+ error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
filp, cmd, arg);
unlock_kernel();
}
@@ -45,7 +45,7 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
{
int error;
int block;
- struct inode * inode = filp->f_dentry->d_inode;
+ struct inode * inode = filp->f_path.dentry->d_inode;
int __user *p = (int __user *)arg;
switch (cmd) {
@@ -137,17 +137,17 @@ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned lon
break;
case FIOQSIZE:
- if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
- S_ISREG(filp->f_dentry->d_inode->i_mode) ||
- S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
- loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
+ if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
+ S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
+ S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
+ loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode);
error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
}
else
error = -ENOTTY;
break;
default:
- if (S_ISREG(filp->f_dentry->d_inode->i_mode))
+ if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
else
error = do_ioctl(filp, cmd, arg);
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 731816332b1..6bbbdb53581 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -42,7 +42,7 @@ static struct semaphore zisofs_zlib_semaphore;
*/
static int zisofs_readpage(struct file *file, struct page *page)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
unsigned int maxpage, xpage, fpage, blockindex;
unsigned long offset;
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 27e276987fd..4af2548f97a 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -183,7 +183,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle the case of the '..' directory */
if (de->name_len[0] == 1 && de->name[0] == 1) {
- inode_number = parent_ino(filp->f_dentry);
+ inode_number = parent_ino(filp->f_path.dentry);
if (filldir(dirent, "..", 2, filp->f_pos, inode_number, DT_DIR) < 0)
break;
filp->f_pos += de_len;
@@ -255,8 +255,7 @@ static int isofs_readdir(struct file *filp,
int result;
char * tmpname;
struct iso_directory_record * tmpde;
- struct inode *inode = filp->f_dentry->d_inode;
-
+ struct inode *inode = filp->f_path.dentry->d_inode;
tmpname = (char *)__get_free_page(GFP_KERNEL);
if (tmpname == NULL)
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 10be51290a2..be4648bc7a2 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -248,8 +248,12 @@ write_out_data:
bufs = 0;
goto write_out_data;
}
- }
- else {
+ } else if (!locked && buffer_locked(bh)) {
+ __journal_file_buffer(jh, commit_transaction,
+ BJ_Locked);
+ jbd_unlock_bh_state(bh);
+ put_bh(bh);
+ } else {
BUFFER_TRACE(bh, "writeout complete: unfile");
__journal_unfile_buffer(jh);
jbd_unlock_bh_state(bh);
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index d38e0d575e4..cceaf57e377 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -55,7 +55,7 @@ get_transaction(journal_t *journal, transaction_t *transaction)
spin_lock_init(&transaction->t_handle_lock);
/* Set up the commit timer for the new transaction. */
- journal->j_commit_timer.expires = transaction->t_expires;
+ journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
add_timer(&journal->j_commit_timer);
J_ASSERT(journal->j_running_transaction == NULL);
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 9f15bce9202..43baa1afa02 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -566,7 +566,7 @@ static int
jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct jffs_file *f;
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
int j;
@@ -818,7 +818,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
D1({
int len = dentry->d_name.len;
- char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
+ char *_name = kmalloc(len + 1, GFP_KERNEL);
memcpy(_name, dentry->d_name.name, len);
_name[len] = '\0';
printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
@@ -964,7 +964,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
D1({
int len = dentry->d_name.len;
const char *name = dentry->d_name.name;
- char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
+ char *_name = kmalloc(len + 1, GFP_KERNEL);
memcpy(_name, name, len);
_name[len] = '\0';
printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
@@ -1372,7 +1372,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
struct jffs_control *c;
struct jffs_file *f;
struct jffs_node *node;
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
int recoverable = 0;
size_t written = 0;
@@ -1380,7 +1380,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
loff_t pos = *ppos;
int err;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
"filp: 0x%p, buf: 0x%p, count: %d\n",
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index d0e783f199e..6dd18911b44 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -436,7 +436,7 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
int i, length;
/* Allocate read buffer */
- read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL);
+ read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
if (!read_buf) {
printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n");
return -ENOMEM;
@@ -744,11 +744,11 @@ static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
/* Allocate read buffers */
- read_buf1 = (__u8 *) kmalloc (sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
+ read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
if (!read_buf1)
return -ENOMEM;
- read_buf2 = (__u8 *) kmalloc (sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
+ read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
if (!read_buf2) {
kfree(read_buf1);
return -ENOMEM;
@@ -876,7 +876,7 @@ jffs_scan_flash(struct jffs_control *c)
}
/* Allocate read buffer */
- read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL);
+ read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
if (!read_buf) {
flash_safe_release(fmc->mtd);
return -ENOMEM;
@@ -1463,7 +1463,7 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
kfree(f->name);
DJM(no_name--);
}
- if (!(f->name = (char *) kmalloc(raw_inode->nsize + 1,
+ if (!(f->name = kmalloc(raw_inode->nsize + 1,
GFP_KERNEL))) {
return -ENOMEM;
}
@@ -1737,7 +1737,7 @@ jffs_find_child(struct jffs_file *dir, const char *name, int len)
printk("jffs_find_child(): Found \"%s\".\n", f->name);
}
else {
- char *copy = (char *) kmalloc(len + 1, GFP_KERNEL);
+ char *copy = kmalloc(len + 1, GFP_KERNEL);
if (copy) {
memcpy(copy, name, len);
copy[len] = '\0';
@@ -2627,7 +2627,7 @@ jffs_print_tree(struct jffs_file *first_file, int indent)
return;
}
- if (!(space = (char *) kmalloc(indent + 1, GFP_KERNEL))) {
+ if (!(space = kmalloc(indent + 1, GFP_KERNEL))) {
printk("jffs_print_tree(): Out of memory!\n");
return;
}
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index 077258b2103..5a95fbdd6fd 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -17,6 +17,7 @@
*
*/
#include <linux/slab.h>
+#include <linux/err.h>
#include <linux/blkdev.h>
#include <linux/jffs.h>
#include "jffs_fm.h"
@@ -104,7 +105,7 @@ jffs_build_begin(struct jffs_control *c, int unit)
mtd = get_mtd_device(NULL, unit);
- if (!mtd) {
+ if (IS_ERR(mtd)) {
kfree(fmc);
DJM(no_jffs_fmcontrol--);
return NULL;
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 72b4fc13a10..4189e4a3605 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -178,8 +178,8 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
while (ref2) {
uint32_t totlen = ref_totlen(c, jeb, ref2);
- if (ref2->flash_offset < jeb->offset ||
- ref2->flash_offset > jeb->offset + c->sector_size) {
+ if (ref_offset(ref2) < jeb->offset ||
+ ref_offset(ref2) > jeb->offset + c->sector_size) {
JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
ref_offset(ref2), jeb->offset);
goto error;
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 3daf3bca037..f89c85d5a3f 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -13,6 +13,7 @@
#ifndef _JFFS2_DEBUG_H_
#define _JFFS2_DEBUG_H_
+#include <linux/sched.h>
#ifndef CONFIG_JFFS2_FS_DEBUG
#define CONFIG_JFFS2_FS_DEBUG 0
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 9def6adf4a5..da6034d5071 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -123,11 +123,11 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct jffs2_inode_info *f;
struct jffs2_sb_info *c;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct jffs2_full_dirent *fd;
unsigned long offset, curofs;
- D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino));
+ D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_path.dentry->d_inode->i_ino));
f = JFFS2_INODE_INFO(inode);
c = JFFS2_SB_INFO(inode->i_sb);
@@ -141,7 +141,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
offset++;
}
if (offset == 1) {
- unsigned long pino = parent_ino(filp->f_dentry);
+ unsigned long pino = parent_ino(filp->f_path.dentry);
D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", pino));
if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0)
goto out;
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 7bc1a4201c0..abb90c0c09c 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -502,12 +502,11 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
if (ret)
return ret;
- c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
+ c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
if (!c->inocache_list) {
ret = -ENOMEM;
goto out_wbuf;
}
- memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
jffs2_init_xattr_subsystem(c);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index daff3341ff9..3a3cf225981 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -838,6 +838,8 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
+ cond_resched();
+
/* We only care about obsolete ones */
if (!(ref_obsolete(raw)))
continue;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 0ddfd70307f..4178b4b5594 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -294,23 +294,21 @@ static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
{
- struct rb_node *node = root->rb_node;
+ struct rb_node *node = rb_first(root);
if (!node)
return NULL;
- while(node->rb_left)
- node = node->rb_left;
+
return rb_entry(node, struct jffs2_node_frag, rb);
}
static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
{
- struct rb_node *node = root->rb_node;
+ struct rb_node *node = rb_last(root);
if (!node)
return NULL;
- while(node->rb_right)
- node = node->rb_right;
+
return rb_entry(node, struct jffs2_node_frag, rb);
}
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 266423b2709..58a0b912e9d 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -944,13 +944,12 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
{
struct jffs2_raw_inode n;
- struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
+ struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL);
int ret;
if (!f)
return -ENOMEM;
- memset(f, 0, sizeof(*f));
init_MUTEX_LOCKED(&f->sem);
f->inocache = ic;
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index e2413466ddd..3af746eaff0 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -128,17 +128,19 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
}
if (jffs2_sum_active()) {
- s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
+ s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
if (!s) {
+ kfree(flashbuf);
JFFS2_WARNING("Can't allocate memory for summary\n");
return -ENOMEM;
}
- memset(s, 0, sizeof(struct jffs2_summary));
}
for (i=0; i<c->nr_blocks; i++) {
struct jffs2_eraseblock *jeb = &c->blocks[i];
+ cond_resched();
+
/* reset summary info for next eraseblock scan */
jffs2_sum_reset_collected(s);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index e52cef526d9..25265965bdc 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -26,15 +26,13 @@
int jffs2_sum_init(struct jffs2_sb_info *c)
{
- c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
+ c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
if (!c->summary) {
JFFS2_WARNING("Can't allocate memory for summary information!\n");
return -ENOMEM;
}
- memset(c->summary, 0, sizeof(struct jffs2_summary));
-
c->summary->sum_buf = vmalloc(c->sector_size);
if (!c->summary->sum_buf) {
@@ -398,6 +396,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
dbg_summary("processing summary index %d\n", i);
+ cond_resched();
+
/* Make sure there's a spare ref for dirty space */
err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
if (err)
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 7deb7825402..08a0e6c49e6 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/fs.h>
+#include <linux/err.h>
#include <linux/mount.h>
#include <linux/jffs2.h>
#include <linux/pagemap.h>
@@ -184,9 +185,9 @@ static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
struct mtd_info *mtd;
mtd = get_mtd_device(NULL, mtdnr);
- if (!mtd) {
+ if (IS_ERR(mtd)) {
D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
- return -EINVAL;
+ return PTR_ERR(mtd);
}
return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
@@ -221,7 +222,7 @@ static int jffs2_get_sb(struct file_system_type *fs_type,
D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
mtd = get_mtd_device(NULL, mtdnr);
- if (mtd) {
+ if (!IS_ERR(mtd)) {
if (!strcmp(mtd->name, dev_name+4))
return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
put_mtd_device(mtd);
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index fc211b6e9b0..b90d5aa3d96 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -51,7 +51,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
*/
if (!p) {
- printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n");
+ printk(KERN_ERR "jffs2_follow_link(): can't find symlink target\n");
p = ERR_PTR(-EIO);
}
D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target));
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 70707309dfa..9c99859f5ed 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -969,8 +969,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
int oobsize = c->mtd->oobsize;
struct mtd_oob_ops ops;
- ops.len = NR_OOB_SCAN_PAGES * oobsize;
- ops.ooblen = oobsize;
+ ops.ooblen = NR_OOB_SCAN_PAGES * oobsize;
ops.oobbuf = c->oobbuf;
ops.ooboffs = 0;
ops.datbuf = NULL;
@@ -983,10 +982,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
return ret;
}
- if (ops.retlen < ops.len) {
+ if (ops.oobretlen < ops.ooblen) {
D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
"returned short read (%zd bytes not %d) for block "
- "at %08x\n", ops.retlen, ops.len, jeb->offset));
+ "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset));
return -EIO;
}
@@ -1005,7 +1004,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
}
/* we know, we are aligned :) */
- for (page = oobsize; page < ops.len; page += sizeof(long)) {
+ for (page = oobsize; page < ops.ooblen; page += sizeof(long)) {
long dat = *(long *)(&ops.oobbuf[page]);
if(dat != -1)
return 1;
@@ -1033,7 +1032,6 @@ int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
return 2;
}
- ops.len = oobsize;
ops.ooblen = oobsize;
ops.oobbuf = c->oobbuf;
ops.ooboffs = 0;
@@ -1048,10 +1046,10 @@ int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
return ret;
}
- if (ops.retlen < ops.len) {
+ if (ops.oobretlen < ops.ooblen) {
D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
"Read OOB return short read (%zd bytes not %d) "
- "for block at %08x\n", ops.retlen, ops.len,
+ "for block at %08x\n", ops.oobretlen, ops.ooblen,
jeb->offset));
return -EIO;
}
@@ -1090,8 +1088,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
n.totlen = cpu_to_je32(8);
- ops.len = c->fsdata_len;
- ops.ooblen = c->fsdata_len;;
+ ops.ooblen = c->fsdata_len;
ops.oobbuf = (uint8_t *)&n;
ops.ooboffs = c->fsdata_pos;
ops.datbuf = NULL;
@@ -1105,10 +1102,10 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
jeb->offset, ret));
return ret;
}
- if (ops.retlen != ops.len) {
+ if (ops.oobretlen != ops.ooblen) {
D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
"Short write for block at %08x: %zd not %d\n",
- jeb->offset, ops.retlen, ops.len));
+ jeb->offset, ops.oobretlen, ops.ooblen));
return -EIO;
}
return 0;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 4da09ce1d1f..4bb3f189733 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -399,8 +399,6 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu
{
/* must be called under down_write(xattr_sem) */
if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
- uint32_t xid = xd->xid, version = xd->version;
-
unload_xattr_datum(c, xd);
xd->flags |= JFFS2_XFLAGS_DEAD;
if (xd->node == (void *)xd) {
@@ -411,7 +409,8 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu
}
spin_unlock(&c->erase_completion_lock);
- dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version);
+ dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n",
+ xd->xid, xd->version);
}
}
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ecb2216d881..6d62f322289 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -3009,7 +3009,7 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
*/
int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *ip = filp->f_dentry->d_inode;
+ struct inode *ip = filp->f_path.dentry->d_inode;
struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
int rc = 0;
loff_t dtpos; /* legacy OS/2 style position */
@@ -3777,12 +3777,12 @@ static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
struct component_name lkey;
struct component_name rkey;
- lkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
GFP_KERNEL);
if (lkey.name == NULL)
return -ENOMEM;
- rkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
GFP_KERNEL);
if (rkey.name == NULL) {
kfree(lkey.name);
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index eb550b339bb..38f70ac03be 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -29,31 +29,21 @@
/*
* file system option (superblock flag)
*/
-/* mount time flag to disable journaling to disk */
-#define JFS_NOINTEGRITY 0x00000010
+
+/* directory option */
+#define JFS_UNICODE 0x00000001 /* unicode name */
/* mount time flags for error handling */
#define JFS_ERR_REMOUNT_RO 0x00000002 /* remount read-only */
#define JFS_ERR_CONTINUE 0x00000004 /* continue */
#define JFS_ERR_PANIC 0x00000008 /* panic */
+/* Quota support */
#define JFS_USRQUOTA 0x00000010
#define JFS_GRPQUOTA 0x00000020
-/* platform option (conditional compilation) */
-#define JFS_AIX 0x80000000 /* AIX support */
-/* POSIX name/directory support */
-
-#define JFS_OS2 0x40000000 /* OS/2 support */
-/* case-insensitive name/directory support */
-
-#define JFS_DFS 0x20000000 /* DCE DFS LFS support */
-
-#define JFS_LINUX 0x10000000 /* Linux support */
-/* case-sensitive name/directory support */
-
-/* directory option */
-#define JFS_UNICODE 0x00000001 /* unicode name */
+/* mount time flag to disable journaling to disk */
+#define JFS_NOINTEGRITY 0x00000040
/* commit option */
#define JFS_COMMIT 0x00000f00 /* commit option mask */
@@ -61,6 +51,7 @@
#define JFS_LAZYCOMMIT 0x00000200 /* lazy commit */
#define JFS_TMPFS 0x00000400 /* temporary file system -
* do not log/commit:
+ * Never implemented
*/
/* log logical volume option */
@@ -74,16 +65,25 @@
#define JFS_SPARSE 0x00020000 /* sparse regular file */
/* DASD Limits F226941 */
-#define JFS_DASD_ENABLED 0x00040000 /* DASD limits enabled */
-#define JFS_DASD_PRIME 0x00080000 /* Prime DASD usage on boot */
+#define JFS_DASD_ENABLED 0x00040000 /* DASD limits enabled */
+#define JFS_DASD_PRIME 0x00080000 /* Prime DASD usage on boot */
/* big endian flag */
-#define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */
+#define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */
/* Directory index */
-#define JFS_DIR_INDEX 0x00200000 /* Persistent index for */
- /* directory entries */
+#define JFS_DIR_INDEX 0x00200000 /* Persistent index for */
+/* platform options */
+#define JFS_LINUX 0x10000000 /* Linux support */
+#define JFS_DFS 0x20000000 /* DCE DFS LFS support */
+/* Never implemented */
+
+#define JFS_OS2 0x40000000 /* OS/2 support */
+/* case-insensitive name/directory support */
+
+#define JFS_AIX 0x80000000 /* AIX support */
+/* POSIX name/directory support - Never implemented*/
/*
* buffer cache configuration
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index ee9b473b7b8..53f63b47a6d 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -120,7 +120,7 @@ int diMount(struct inode *ipimap)
* allocate/initialize the in-memory inode map control structure
*/
/* allocate the in-memory inode map control structure. */
- imap = (struct inomap *) kmalloc(sizeof(struct inomap), GFP_KERNEL);
+ imap = kmalloc(sizeof(struct inomap), GFP_KERNEL);
if (imap == NULL) {
jfs_err("diMount: kmalloc returned NULL!");
return -ENOMEM;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index b1a1c729601..ceaf03b9493 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -764,22 +764,9 @@ void release_metapage(struct metapage * mp)
} else if (mp->lsn) /* discard_metapage doesn't remove it */
remove_from_logsync(mp);
-#if MPS_PER_PAGE == 1
- /*
- * If we know this is the only thing in the page, we can throw
- * the page out of the page cache. If pages are larger, we
- * don't want to do this.
- */
-
- /* Retest mp->count since we may have released page lock */
- if (test_bit(META_discard, &mp->flag) && !mp->count) {
- clear_page_dirty(page);
- ClearPageUptodate(page);
- }
-#else
/* Try to keep metapages from using up too much memory */
drop_metapage(page, mp);
-#endif
+
unlock_page(page);
page_cache_release(page);
}
diff --git a/fs/libfs.c b/fs/libfs.c
index bd08e0e64a8..503898d5c4a 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -63,7 +63,7 @@ int dcache_dir_open(struct inode *inode, struct file *file)
{
static struct qstr cursor_name = {.len = 1, .name = "."};
- file->private_data = d_alloc(file->f_dentry, &cursor_name);
+ file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
return file->private_data ? 0 : -ENOMEM;
}
@@ -76,7 +76,7 @@ int dcache_dir_close(struct inode *inode, struct file *file)
loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
{
- mutex_lock(&file->f_dentry->d_inode->i_mutex);
+ mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
switch (origin) {
case 1:
offset += file->f_pos;
@@ -84,7 +84,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
@@ -96,8 +96,8 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
spin_lock(&dcache_lock);
list_del(&cursor->d_u.d_child);
- p = file->f_dentry->d_subdirs.next;
- while (n && p != &file->f_dentry->d_subdirs) {
+ p = file->f_path.dentry->d_subdirs.next;
+ while (n && p != &file->f_path.dentry->d_subdirs) {
struct dentry *next;
next = list_entry(p, struct dentry, d_u.d_child);
if (!d_unhashed(next) && next->d_inode)
@@ -108,7 +108,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
spin_unlock(&dcache_lock);
}
}
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return offset;
}
@@ -126,7 +126,7 @@ static inline unsigned char dt_type(struct inode *inode)
int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct dentry *cursor = filp->private_data;
struct list_head *p, *q = &cursor->d_u.d_child;
ino_t ino;
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index b85a0ad2cfb..f4d45d4d835 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -36,7 +36,7 @@ struct nlm_wait {
struct nlm_host * b_host;
struct file_lock * b_lock; /* local file lock */
unsigned short b_reclaim; /* got to reclaim lock */
- u32 b_status; /* grant callback status */
+ __be32 b_status; /* grant callback status */
};
static LIST_HEAD(nlm_blocked);
@@ -53,7 +53,7 @@ struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *
block->b_host = host;
block->b_lock = fl;
init_waitqueue_head(&block->b_wait);
- block->b_status = NLM_LCK_BLOCKED;
+ block->b_status = nlm_lck_blocked;
list_add(&block->b_list, &nlm_blocked);
}
return block;
@@ -89,7 +89,7 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
* nlmclnt_lock for an explanation.
*/
ret = wait_event_interruptible_timeout(block->b_wait,
- block->b_status != NLM_LCK_BLOCKED,
+ block->b_status != nlm_lck_blocked,
timeout);
if (ret < 0)
return -ERESTARTSYS;
@@ -126,12 +126,12 @@ __be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock
continue;
if (!nlm_cmp_addr(&block->b_host->h_addr, addr))
continue;
- if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_dentry->d_inode) ,fh) != 0)
+ if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
continue;
/* Alright, we found a lock. Set the return status
* and wake up the caller
*/
- block->b_status = NLM_LCK_GRANTED;
+ block->b_status = nlm_granted;
wake_up(&block->b_wait);
res = nlm_granted;
}
@@ -176,7 +176,7 @@ reclaimer(void *ptr)
lock_kernel();
lockd_up(0); /* note: this cannot fail as lockd is already running */
- dprintk("lockd: reclaiming locks for host %s", host->h_name);
+ dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
restart:
nsmstate = host->h_nsmstate;
@@ -206,12 +206,12 @@ restart:
host->h_reclaiming = 0;
up_write(&host->h_rwsem);
- dprintk("NLM: done reclaiming locks for host %s", host->h_name);
+ dprintk("NLM: done reclaiming locks for host %s\n", host->h_name);
/* Now, wake up all processes that sleep on a blocked lock */
list_for_each_entry(block, &nlm_blocked, b_list) {
if (block->b_host == host) {
- block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
+ block->b_status = nlm_lck_denied_grace_period;
wake_up(&block->b_wait);
}
}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 497c3cd59d5..0b4acc1c5e7 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -27,7 +27,7 @@
static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
-static int nlm_stat_to_errno(u32 stat);
+static int nlm_stat_to_errno(__be32 stat);
static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
static int nlmclnt_cancel(struct nlm_host *, int , struct file_lock *);
@@ -129,7 +129,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
nlmclnt_next_cookie(&argp->cookie);
argp->state = nsm_local_state;
- memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
+ memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh));
lock->caller = utsname()->nodename;
lock->oh.data = req->a_owner;
lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
@@ -325,7 +325,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
}
break;
} else
- if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
+ if (resp->status == nlm_lck_denied_grace_period) {
dprintk("lockd: server in grace period\n");
if (argp->reclaim) {
printk(KERN_WARNING
@@ -411,10 +411,10 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
goto out;
switch (req->a_res.status) {
- case NLM_LCK_GRANTED:
+ case nlm_granted:
fl->fl_type = F_UNLCK;
break;
- case NLM_LCK_DENIED:
+ case nlm_lck_denied:
/*
* Report the conflicting lock back to the application.
*/
@@ -524,9 +524,9 @@ again:
if (!req->a_args.block)
break;
/* Did a reclaimer thread notify us of a server reboot? */
- if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD)
+ if (resp->status == nlm_lck_denied_grace_period)
continue;
- if (resp->status != NLM_LCK_BLOCKED)
+ if (resp->status != nlm_lck_blocked)
break;
/* Wait on an NLM blocking lock */
status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
@@ -535,11 +535,11 @@ again:
*/
if (status < 0)
goto out_unblock;
- if (resp->status != NLM_LCK_BLOCKED)
+ if (resp->status != nlm_lck_blocked)
break;
}
- if (resp->status == NLM_LCK_GRANTED) {
+ if (resp->status == nlm_granted) {
down_read(&host->h_rwsem);
/* Check whether or not the server has rebooted */
if (fl->fl_u.nfs_fl.state != host->h_state) {
@@ -556,7 +556,7 @@ again:
out_unblock:
nlmclnt_finish_block(block);
/* Cancel the blocked request if it is still pending */
- if (resp->status == NLM_LCK_BLOCKED)
+ if (resp->status == nlm_lck_blocked)
nlmclnt_cancel(host, req->a_args.block, fl);
out:
nlm_release_call(req);
@@ -585,12 +585,12 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
req->a_args.reclaim = 1;
if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
- && req->a_res.status == NLM_LCK_GRANTED)
+ && req->a_res.status == nlm_granted)
return 0;
printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
"(errno %d, status %d)\n", fl->fl_pid,
- status, req->a_res.status);
+ status, ntohl(req->a_res.status));
/*
* FIXME: This is a serious failure. We can
@@ -637,10 +637,10 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
if (status < 0)
goto out;
- if (resp->status == NLM_LCK_GRANTED)
+ if (resp->status == nlm_granted)
goto out;
- if (resp->status != NLM_LCK_DENIED_NOLOCKS)
+ if (resp->status != nlm_lck_denied_nolocks)
printk("lockd: unexpected unlock status: %d\n", resp->status);
/* What to do now? I'm out of my depth... */
status = -ENOLCK;
@@ -652,7 +652,7 @@ out:
static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
{
struct nlm_rqst *req = data;
- int status = req->a_res.status;
+ u32 status = ntohl(req->a_res.status);
if (RPC_ASSASSINATED(task))
goto die;
@@ -720,6 +720,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
{
struct nlm_rqst *req = data;
+ u32 status = ntohl(req->a_res.status);
if (RPC_ASSASSINATED(task))
goto die;
@@ -731,9 +732,9 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
}
dprintk("lockd: cancel status %u (task %u)\n",
- req->a_res.status, task->tk_pid);
+ status, task->tk_pid);
- switch (req->a_res.status) {
+ switch (status) {
case NLM_LCK_GRANTED:
case NLM_LCK_DENIED_GRACE_PERIOD:
case NLM_LCK_DENIED:
@@ -744,7 +745,7 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
goto retry_cancel;
default:
printk(KERN_NOTICE "lockd: weird return %d for CANCEL call\n",
- req->a_res.status);
+ status);
}
die:
@@ -768,9 +769,9 @@ static const struct rpc_call_ops nlmclnt_cancel_ops = {
* Convert an NLM status code to a generic kernel errno
*/
static int
-nlm_stat_to_errno(u32 status)
+nlm_stat_to_errno(__be32 status)
{
- switch(status) {
+ switch(ntohl(status)) {
case NLM_LCK_GRANTED:
return 0;
case NLM_LCK_DENIED:
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 7e219b93855..c7db0a5bccd 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -343,8 +343,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
__be32 ret;
dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
- file->f_file->f_dentry->d_inode->i_sb->s_id,
- file->f_file->f_dentry->d_inode->i_ino,
+ file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+ file->f_file->f_path.dentry->d_inode->i_ino,
lock->fl.fl_type, lock->fl.fl_pid,
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end,
@@ -420,8 +420,8 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
struct nlm_lock *conflock)
{
dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
- file->f_file->f_dentry->d_inode->i_sb->s_id,
- file->f_file->f_dentry->d_inode->i_ino,
+ file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+ file->f_file->f_path.dentry->d_inode->i_ino,
lock->fl.fl_type,
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end);
@@ -454,8 +454,8 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
int error;
dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
- file->f_file->f_dentry->d_inode->i_sb->s_id,
- file->f_file->f_dentry->d_inode->i_ino,
+ file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+ file->f_file->f_path.dentry->d_inode->i_ino,
lock->fl.fl_pid,
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end);
@@ -483,8 +483,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
int status = 0;
dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
- file->f_file->f_dentry->d_inode->i_sb->s_id,
- file->f_file->f_dentry->d_inode->i_ino,
+ file->f_file->f_path.dentry->d_inode->i_sb->s_id,
+ file->f_file->f_path.dentry->d_inode->i_ino,
lock->fl.fl_pid,
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end);
@@ -645,7 +645,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops = {
* block.
*/
void
-nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
+nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
{
struct nlm_block *block;
@@ -655,7 +655,7 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
return;
if (block) {
- if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
+ if (status == nlm_lck_denied_grace_period) {
/* Try again in a couple of seconds */
nlmsvc_insert_block(block, 10 * HZ);
} else {
diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
index 6220dc2a3f2..068886de4dd 100644
--- a/fs/lockd/svcshare.c
+++ b/fs/lockd/svcshare.c
@@ -39,7 +39,7 @@ nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
return nlm_lck_denied;
}
- share = (struct nlm_share *) kmalloc(sizeof(*share) + oh->len,
+ share = kmalloc(sizeof(*share) + oh->len,
GFP_KERNEL);
if (share == NULL)
return nlm_lck_denied_nolocks;
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index e83024e1604..c0df00c74ce 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -43,7 +43,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
static inline void nlm_debug_print_file(char *msg, struct nlm_file *file)
{
- struct inode *inode = file->f_file->f_dentry->d_inode;
+ struct inode *inode = file->f_file->f_path.dentry->d_inode;
dprintk("lockd: %s %s/%ld\n",
msg, inode->i_sb->s_id, inode->i_ino);
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index b7c949256e5..34dae5d7073 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -361,7 +361,7 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
{
if (!(p = nlm_decode_cookie(p, &resp->cookie)))
return 0;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return xdr_argsize_check(rqstp, p);
}
@@ -407,8 +407,8 @@ nlmclt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
{
if (!(p = nlm_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
- if (resp->status == NLM_LCK_DENIED) {
+ resp->status = *p++;
+ if (resp->status == nlm_lck_denied) {
struct file_lock *fl = &resp->lock.fl;
u32 excl;
s32 start, len, end;
@@ -506,7 +506,7 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
{
if (!(p = nlm_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return 0;
}
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index f4c0b2b9f75..a7824055121 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -367,7 +367,7 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
{
if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
return 0;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return xdr_argsize_check(rqstp, p);
}
@@ -413,8 +413,8 @@ nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
{
if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
- if (resp->status == NLM_LCK_DENIED) {
+ resp->status = *p++;
+ if (resp->status == nlm_lck_denied) {
struct file_lock *fl = &resp->lock.fl;
u32 excl;
s64 start, end, len;
@@ -512,7 +512,7 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
{
if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
return -EIO;
- resp->status = ntohl(*p++);
+ resp->status = *p++;
return 0;
}
diff --git a/fs/locks.c b/fs/locks.c
index 1cb0c57fedb..52a81005dab 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -321,7 +321,7 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
start = filp->f_pos;
break;
case SEEK_END:
- start = i_size_read(filp->f_dentry->d_inode);
+ start = i_size_read(filp->f_path.dentry->d_inode);
break;
default:
return -EINVAL;
@@ -371,7 +371,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
start = filp->f_pos;
break;
case SEEK_END:
- start = i_size_read(filp->f_dentry->d_inode);
+ start = i_size_read(filp->f_path.dentry->d_inode);
break;
default:
return -EINVAL;
@@ -672,7 +672,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl,
struct file_lock *cfl;
lock_kernel();
- for (cfl = filp->f_dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
+ for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
if (!IS_POSIX(cfl))
continue;
if (posix_locks_conflict(cfl, fl))
@@ -734,7 +734,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
{
struct file_lock *new_fl = NULL;
struct file_lock **before;
- struct inode * inode = filp->f_dentry->d_inode;
+ struct inode * inode = filp->f_path.dentry->d_inode;
int error = 0;
int found = 0;
@@ -1018,7 +1018,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
*/
int posix_lock_file(struct file *filp, struct file_lock *fl)
{
- return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
+ return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, NULL);
}
EXPORT_SYMBOL(posix_lock_file);
@@ -1033,7 +1033,7 @@ EXPORT_SYMBOL(posix_lock_file);
int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
struct file_lock *conflock)
{
- return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
+ return __posix_lock_file_conf(filp->f_path.dentry->d_inode, fl, conflock);
}
EXPORT_SYMBOL(posix_lock_file_conf);
@@ -1333,8 +1333,8 @@ int fcntl_getlease(struct file *filp)
int type = F_UNLCK;
lock_kernel();
- time_out_leases(filp->f_dentry->d_inode);
- for (fl = filp->f_dentry->d_inode->i_flock; fl && IS_LEASE(fl);
+ time_out_leases(filp->f_path.dentry->d_inode);
+ for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
fl = fl->fl_next) {
if (fl->fl_file == filp) {
type = fl->fl_type & ~F_INPROGRESS;
@@ -1359,7 +1359,7 @@ int fcntl_getlease(struct file *filp)
static int __setlease(struct file *filp, long arg, struct file_lock **flp)
{
struct file_lock *fl, **before, **my_before = NULL, *lease;
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
int error, rdlease_count = 0, wrlease_count = 0;
@@ -1448,7 +1448,7 @@ out:
int setlease(struct file *filp, long arg, struct file_lock **lease)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
int error;
@@ -1482,7 +1482,7 @@ EXPORT_SYMBOL(setlease);
int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
{
struct file_lock fl, *flp = &fl;
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
int error;
@@ -1692,7 +1692,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
@@ -1835,7 +1835,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
@@ -1922,7 +1922,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
* posix_lock_file(). Another process could be setting a lock on this
* file at the same time, but we wouldn't remove that lock anyway.
*/
- if (!filp->f_dentry->d_inode->i_flock)
+ if (!filp->f_path.dentry->d_inode->i_flock)
return;
lock.fl_type = F_UNLCK;
@@ -1951,7 +1951,7 @@ EXPORT_SYMBOL(locks_remove_posix);
*/
void locks_remove_flock(struct file *filp)
{
- struct inode * inode = filp->f_dentry->d_inode;
+ struct inode * inode = filp->f_path.dentry->d_inode;
struct file_lock *fl;
struct file_lock **before;
@@ -2020,7 +2020,7 @@ static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx)
struct inode *inode = NULL;
if (fl->fl_file != NULL)
- inode = fl->fl_file->f_dentry->d_inode;
+ inode = fl->fl_file->f_path.dentry->d_inode;
out += sprintf(out, "%d:%s ", id, pfx);
if (IS_POSIX(fl)) {
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 2b0a389d198..ab782c4086f 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -82,7 +82,7 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned long pos = filp->f_pos;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
unsigned offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT;
diff --git a/fs/namei.c b/fs/namei.c
index db1bca26d88..e4f108f0823 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -297,7 +297,7 @@ int vfs_permission(struct nameidata *nd, int mask)
*/
int file_permission(struct file *file, int mask)
{
- return permission(file->f_dentry->d_inode, mask, NULL);
+ return permission(file->f_path.dentry->d_inode, mask, NULL);
}
/*
@@ -333,7 +333,7 @@ int get_write_access(struct inode * inode)
int deny_write_access(struct file * file)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
spin_lock(&inode->i_lock);
if (atomic_read(&inode->i_writecount) > 0) {
@@ -368,7 +368,7 @@ void path_release_on_umount(struct nameidata *nd)
*/
void release_open_intent(struct nameidata *nd)
{
- if (nd->intent.open.file->f_dentry == NULL)
+ if (nd->intent.open.file->f_path.dentry == NULL)
put_filp(nd->intent.open.file);
else
fput(nd->intent.open.file);
@@ -572,11 +572,6 @@ fail:
return PTR_ERR(link);
}
-struct path {
- struct vfsmount *mnt;
- struct dentry *dentry;
-};
-
static inline void dput_path(struct path *path, struct nameidata *nd)
{
dput(path->dentry);
@@ -1143,7 +1138,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
if (!file)
goto out_fail;
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
retval = -ENOTDIR;
if (!S_ISDIR(dentry->d_inode->i_mode))
@@ -1153,7 +1148,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
if (retval)
goto fput_fail;
- nd->mnt = mntget(file->f_vfsmnt);
+ nd->mnt = mntget(file->f_path.mnt);
nd->dentry = dget(dentry);
fput_light(file, fput_needed);
diff --git a/fs/namespace.c b/fs/namespace.c
index b00ac84ebbd..5ef336c1103 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -20,7 +20,7 @@
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/seq_file.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/namei.h>
#include <linux/security.h>
#include <linux/mount.h>
@@ -133,10 +133,10 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
static inline int check_mnt(struct vfsmount *mnt)
{
- return mnt->mnt_namespace == current->nsproxy->namespace;
+ return mnt->mnt_ns == current->nsproxy->mnt_ns;
}
-static void touch_namespace(struct namespace *ns)
+static void touch_mnt_namespace(struct mnt_namespace *ns)
{
if (ns) {
ns->event = ++event;
@@ -144,7 +144,7 @@ static void touch_namespace(struct namespace *ns)
}
}
-static void __touch_namespace(struct namespace *ns)
+static void __touch_mnt_namespace(struct mnt_namespace *ns)
{
if (ns && ns->event != event) {
ns->event = event;
@@ -187,19 +187,19 @@ static void commit_tree(struct vfsmount *mnt)
struct vfsmount *parent = mnt->mnt_parent;
struct vfsmount *m;
LIST_HEAD(head);
- struct namespace *n = parent->mnt_namespace;
+ struct mnt_namespace *n = parent->mnt_ns;
BUG_ON(parent == mnt);
list_add_tail(&head, &mnt->mnt_list);
list_for_each_entry(m, &head, mnt_list)
- m->mnt_namespace = n;
+ m->mnt_ns = n;
list_splice(&head, n->list.prev);
list_add_tail(&mnt->mnt_hash, mount_hashtable +
hash(parent, mnt->mnt_mountpoint));
list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
- touch_namespace(n);
+ touch_mnt_namespace(n);
}
static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root)
@@ -320,7 +320,7 @@ EXPORT_SYMBOL(mnt_unpin);
/* iterator */
static void *m_start(struct seq_file *m, loff_t *pos)
{
- struct namespace *n = m->private;
+ struct mnt_namespace *n = m->private;
struct list_head *p;
loff_t l = *pos;
@@ -333,7 +333,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
static void *m_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct namespace *n = m->private;
+ struct mnt_namespace *n = m->private;
struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
(*pos)++;
return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
@@ -368,6 +368,7 @@ static int show_vfsmnt(struct seq_file *m, void *v)
{ MNT_NOEXEC, ",noexec" },
{ MNT_NOATIME, ",noatime" },
{ MNT_NODIRATIME, ",nodiratime" },
+ { MNT_RELATIME, ",relatime" },
{ 0, NULL }
};
struct proc_fs_info *fs_infop;
@@ -526,8 +527,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
list_for_each_entry(p, kill, mnt_hash) {
list_del_init(&p->mnt_expire);
list_del_init(&p->mnt_list);
- __touch_namespace(p->mnt_namespace);
- p->mnt_namespace = NULL;
+ __touch_mnt_namespace(p->mnt_ns);
+ p->mnt_ns = NULL;
list_del_init(&p->mnt_child);
if (p->mnt_parent != p)
p->mnt_mountpoint->d_mounted--;
@@ -830,7 +831,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
if (parent_nd) {
detach_mnt(source_mnt, parent_nd);
attach_mnt(source_mnt, nd);
- touch_namespace(current->nsproxy->namespace);
+ touch_mnt_namespace(current->nsproxy->mnt_ns);
} else {
mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
commit_tree(source_mnt);
@@ -1145,9 +1146,9 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
*/
if (!propagate_mount_busy(mnt, 2)) {
/* delete from the namespace */
- touch_namespace(mnt->mnt_namespace);
+ touch_mnt_namespace(mnt->mnt_ns);
list_del_init(&mnt->mnt_list);
- mnt->mnt_namespace = NULL;
+ mnt->mnt_ns = NULL;
umount_tree(mnt, 1, umounts);
spin_unlock(&vfsmount_lock);
} else {
@@ -1168,7 +1169,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts,
*/
static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)
{
- struct namespace *namespace;
+ struct mnt_namespace *ns;
struct vfsmount *mnt;
while (!list_empty(graveyard)) {
@@ -1178,10 +1179,10 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou
/* don't do anything if the namespace is dead - all the
* vfsmounts from it are going away anyway */
- namespace = mnt->mnt_namespace;
- if (!namespace || !namespace->root)
+ ns = mnt->mnt_ns;
+ if (!ns || !ns->root)
continue;
- get_namespace(namespace);
+ get_mnt_ns(ns);
spin_unlock(&vfsmount_lock);
down_write(&namespace_sem);
@@ -1189,7 +1190,7 @@ static void expire_mount_list(struct list_head *graveyard, struct list_head *mou
up_write(&namespace_sem);
release_mounts(&umounts);
mntput(mnt);
- put_namespace(namespace);
+ put_mnt_ns(ns);
spin_lock(&vfsmount_lock);
}
}
@@ -1405,9 +1406,11 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
mnt_flags |= MNT_NOATIME;
if (flags & MS_NODIRATIME)
mnt_flags |= MNT_NODIRATIME;
+ if (flags & MS_RELATIME)
+ mnt_flags |= MNT_RELATIME;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
- MS_NOATIME | MS_NODIRATIME);
+ MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
/* ... and get the mountpoint */
retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
@@ -1439,14 +1442,15 @@ dput_out:
* Allocate a new namespace structure and populate it with contents
* copied from the namespace of the passed in task structure.
*/
-struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
+struct mnt_namespace *dup_mnt_ns(struct task_struct *tsk,
+ struct fs_struct *fs)
{
- struct namespace *namespace = tsk->nsproxy->namespace;
- struct namespace *new_ns;
+ struct mnt_namespace *mnt_ns = tsk->nsproxy->mnt_ns;
+ struct mnt_namespace *new_ns;
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
struct vfsmount *p, *q;
- new_ns = kmalloc(sizeof(struct namespace), GFP_KERNEL);
+ new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
if (!new_ns)
return NULL;
@@ -1457,7 +1461,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
down_write(&namespace_sem);
/* First pass: copy the tree topology */
- new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root,
+ new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
CL_COPY_ALL | CL_EXPIRE);
if (!new_ns->root) {
up_write(&namespace_sem);
@@ -1473,10 +1477,10 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
* as belonging to new namespace. We have already acquired a private
* fs_struct, so tsk->fs->lock is not needed.
*/
- p = namespace->root;
+ p = mnt_ns->root;
q = new_ns->root;
while (p) {
- q->mnt_namespace = new_ns;
+ q->mnt_ns = new_ns;
if (fs) {
if (p == fs->rootmnt) {
rootmnt = p;
@@ -1491,7 +1495,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
fs->altrootmnt = mntget(q);
}
}
- p = next_mnt(p, namespace->root);
+ p = next_mnt(p, mnt_ns->root);
q = next_mnt(q, new_ns->root);
}
up_write(&namespace_sem);
@@ -1506,16 +1510,16 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
return new_ns;
}
-int copy_namespace(int flags, struct task_struct *tsk)
+int copy_mnt_ns(int flags, struct task_struct *tsk)
{
- struct namespace *namespace = tsk->nsproxy->namespace;
- struct namespace *new_ns;
+ struct mnt_namespace *ns = tsk->nsproxy->mnt_ns;
+ struct mnt_namespace *new_ns;
int err = 0;
- if (!namespace)
+ if (!ns)
return 0;
- get_namespace(namespace);
+ get_mnt_ns(ns);
if (!(flags & CLONE_NEWNS))
return 0;
@@ -1525,16 +1529,16 @@ int copy_namespace(int flags, struct task_struct *tsk)
goto out;
}
- new_ns = dup_namespace(tsk, tsk->fs);
+ new_ns = dup_mnt_ns(tsk, tsk->fs);
if (!new_ns) {
err = -ENOMEM;
goto out;
}
- tsk->nsproxy->namespace = new_ns;
+ tsk->nsproxy->mnt_ns = new_ns;
out:
- put_namespace(namespace);
+ put_mnt_ns(ns);
return err;
}
@@ -1754,7 +1758,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
detach_mnt(user_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 / */
- touch_namespace(current->nsproxy->namespace);
+ touch_mnt_namespace(current->nsproxy->mnt_ns);
spin_unlock(&vfsmount_lock);
chroot_fs_refs(&user_nd, &new_nd);
security_sb_post_pivotroot(&user_nd, &new_nd);
@@ -1779,27 +1783,27 @@ out3:
static void __init init_mount_tree(void)
{
struct vfsmount *mnt;
- struct namespace *namespace;
+ struct mnt_namespace *ns;
mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
if (IS_ERR(mnt))
panic("Can't create rootfs");
- namespace = kmalloc(sizeof(*namespace), GFP_KERNEL);
- if (!namespace)
+ ns = kmalloc(sizeof(*ns), GFP_KERNEL);
+ if (!ns)
panic("Can't allocate initial namespace");
- atomic_set(&namespace->count, 1);
- INIT_LIST_HEAD(&namespace->list);
- init_waitqueue_head(&namespace->poll);
- namespace->event = 0;
- list_add(&mnt->mnt_list, &namespace->list);
- namespace->root = mnt;
- mnt->mnt_namespace = namespace;
-
- init_task.nsproxy->namespace = namespace;
- get_namespace(namespace);
-
- set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
- set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
+ atomic_set(&ns->count, 1);
+ INIT_LIST_HEAD(&ns->list);
+ init_waitqueue_head(&ns->poll);
+ ns->event = 0;
+ list_add(&mnt->mnt_list, &ns->list);
+ ns->root = mnt;
+ mnt->mnt_ns = ns;
+
+ init_task.nsproxy->mnt_ns = ns;
+ get_mnt_ns(ns);
+
+ set_fs_pwd(current->fs, ns->root, ns->root->mnt_root);
+ set_fs_root(current->fs, ns->root, ns->root->mnt_root);
}
void __init mnt_init(unsigned long mempages)
@@ -1860,11 +1864,11 @@ void __init mnt_init(unsigned long mempages)
init_mount_tree();
}
-void __put_namespace(struct namespace *namespace)
+void __put_mnt_ns(struct mnt_namespace *ns)
{
- struct vfsmount *root = namespace->root;
+ struct vfsmount *root = ns->root;
LIST_HEAD(umount_list);
- namespace->root = NULL;
+ ns->root = NULL;
spin_unlock(&vfsmount_lock);
down_write(&namespace_sem);
spin_lock(&vfsmount_lock);
@@ -1872,5 +1876,5 @@ void __put_namespace(struct namespace *namespace)
spin_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);
- kfree(namespace);
+ kfree(ns);
}
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 458b3b78519..73747772c3b 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -402,7 +402,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct page *page = NULL;
struct ncp_server *server = NCP_SERVER(inode);
@@ -554,7 +554,7 @@ static int
ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
{
- struct dentry *newdent, *dentry = filp->f_dentry;
+ struct dentry *newdent, *dentry = filp->f_path.dentry;
struct inode *newino, *inode = dentry->d_inode;
struct ncp_cache_control ctl = *ctrl;
struct qstr qname;
@@ -649,7 +649,7 @@ static void
ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
struct ncp_cache_control *ctl)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct ncp_server *server = NCP_SERVER(inode);
struct ncp_volume_info info;
@@ -685,7 +685,7 @@ static void
ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
struct ncp_cache_control *ctl)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *dir = dentry->d_inode;
struct ncp_server *server = NCP_SERVER(dir);
struct nw_search_sequence seq;
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index df37524b85d..b91fea03b1c 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -101,7 +101,7 @@ out:
static ssize_t
ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
size_t already_read = 0;
off_t pos;
@@ -182,7 +182,7 @@ outrel:
static ssize_t
ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
size_t already_written = 0;
off_t pos;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index fae53243bb9..67a90bf795d 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -327,11 +327,12 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
char *optarg;
unsigned long optint;
int version = 0;
+ int ret;
data->flags = 0;
data->int_flags = 0;
data->mounted_uid = 0;
- data->wdog_pid = -1;
+ data->wdog_pid = NULL;
data->ncp_fd = ~0;
data->time_out = 10;
data->retry_count = 20;
@@ -343,8 +344,9 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
data->mounted_vol[0] = 0;
while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
- if (optval < 0)
- return optval;
+ ret = optval;
+ if (ret < 0)
+ goto err;
switch (optval) {
case 'u':
data->uid = optint;
@@ -371,7 +373,7 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
data->flags = optint;
break;
case 'w':
- data->wdog_pid = optint;
+ data->wdog_pid = find_get_pid(optint);
break;
case 'n':
data->ncp_fd = optint;
@@ -380,18 +382,21 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
data->info_fd = optint;
break;
case 'v':
- if (optint < NCP_MOUNT_VERSION_V4) {
- return -ECHRNG;
- }
- if (optint > NCP_MOUNT_VERSION_V5) {
- return -ECHRNG;
- }
+ ret = -ECHRNG;
+ if (optint < NCP_MOUNT_VERSION_V4)
+ goto err;
+ if (optint > NCP_MOUNT_VERSION_V5)
+ goto err;
version = optint;
break;
}
}
return 0;
+err:
+ put_pid(data->wdog_pid);
+ data->wdog_pid = NULL;
+ return ret;
}
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
@@ -409,6 +414,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
#endif
struct ncp_entry_info finfo;
+ data.wdog_pid = NULL;
server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
if (!server)
return -ENOMEM;
@@ -425,7 +431,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
data.flags = md->flags;
data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
data.mounted_uid = md->mounted_uid;
- data.wdog_pid = md->wdog_pid;
+ data.wdog_pid = find_get_pid(md->wdog_pid);
data.ncp_fd = md->ncp_fd;
data.time_out = md->time_out;
data.retry_count = md->retry_count;
@@ -445,7 +451,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
data.flags = md->flags;
data.int_flags = 0;
data.mounted_uid = md->mounted_uid;
- data.wdog_pid = md->wdog_pid;
+ data.wdog_pid = find_get_pid(md->wdog_pid);
data.ncp_fd = md->ncp_fd;
data.time_out = md->time_out;
data.retry_count = md->retry_count;
@@ -471,7 +477,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
if (!ncp_filp)
goto out;
error = -ENOTSOCK;
- sock_inode = ncp_filp->f_dentry->d_inode;
+ sock_inode = ncp_filp->f_path.dentry->d_inode;
if (!S_ISSOCK(sock_inode->i_mode))
goto out_fput;
sock = SOCKET_I(sock_inode);
@@ -504,7 +510,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
if (!server->info_filp)
goto out_fput;
error = -ENOTSOCK;
- sock_inode = server->info_filp->f_dentry->d_inode;
+ sock_inode = server->info_filp->f_path.dentry->d_inode;
if (!S_ISSOCK(sock_inode->i_mode))
goto out_fput2;
info_sock = SOCKET_I(sock_inode);
@@ -679,6 +685,7 @@ out_fput:
*/
fput(ncp_filp);
out:
+ put_pid(data.wdog_pid);
sb->s_fs_info = NULL;
kfree(server);
return error;
@@ -711,7 +718,8 @@ static void ncp_put_super(struct super_block *sb)
if (server->info_filp)
fput(server->info_filp);
fput(server->ncp_filp);
- kill_proc(server->m.wdog_pid, SIGTERM, 1);
+ kill_pid(server->m.wdog_pid, SIGTERM, 1);
+ put_pid(server->m.wdog_pid);
kfree(server->priv.data);
kfree(server->auth.object_name);
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 589d1eac55c..8843a83d4ef 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -35,7 +35,7 @@ static int
ncp_get_fs_info(struct ncp_server * server, struct file *file,
struct ncp_fs_info __user *arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct ncp_fs_info info;
if ((file_permission(file, MAY_WRITE) != 0)
@@ -65,7 +65,7 @@ static int
ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
struct ncp_fs_info_v2 __user * arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct ncp_fs_info_v2 info2;
if ((file_permission(file, MAY_WRITE) != 0)
@@ -136,7 +136,7 @@ static int
ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
struct compat_ncp_fs_info_v2 __user * arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct compat_ncp_fs_info_v2 info2;
if ((file_permission(file, MAY_WRITE) != 0)
@@ -824,7 +824,7 @@ outrel:
#ifdef CONFIG_COMPAT
long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int ret;
lock_kernel();
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index e7d5a3097fe..70a69115500 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -29,7 +29,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
unsigned long address, int *type)
{
struct file *file = area->vm_file;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct page* page;
char *pg_addr;
@@ -106,7 +106,7 @@ static struct vm_operations_struct ncp_file_mmap =
/* This is used for a general mmap of a ncp file */
int ncp_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
DPRINTK("ncp_mmap: called\n");
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index b34cd16f472..d9ba8cb0ee7 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -172,7 +172,7 @@ static
int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
{
struct file *file = desc->file;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct rpc_cred *cred = nfs_file_cred(file);
unsigned long timestamp;
int error;
@@ -183,7 +183,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
again:
timestamp = jiffies;
- error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page,
+ error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
NFS_SERVER(inode)->dtsize, desc->plus);
if (error < 0) {
/* We requested READDIRPLUS, but the server doesn't grok it */
@@ -308,7 +308,7 @@ int find_dirent_index(nfs_readdir_descriptor_t *desc)
static inline
int find_dirent_page(nfs_readdir_descriptor_t *desc)
{
- struct inode *inode = desc->file->f_dentry->d_inode;
+ struct inode *inode = desc->file->f_path.dentry->d_inode;
struct page *page;
int status;
@@ -464,7 +464,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
filldir_t filldir)
{
struct file *file = desc->file;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct rpc_cred *cred = nfs_file_cred(file);
struct page *page = NULL;
int status;
@@ -477,7 +477,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
status = -ENOMEM;
goto out;
}
- desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie,
+ desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
page,
NFS_SERVER(inode)->dtsize,
desc->plus);
@@ -516,7 +516,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
*/
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
nfs_readdir_descriptor_t my_desc,
*desc = &my_desc;
@@ -532,7 +532,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
lock_kernel();
- res = nfs_revalidate_mapping(inode, filp->f_mapping);
+ res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping);
if (res < 0) {
unlock_kernel();
return res;
@@ -599,7 +599,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
{
- mutex_lock(&filp->f_dentry->d_inode->i_mutex);
+ mutex_lock(&filp->f_path.dentry->d_inode->i_mutex);
switch (origin) {
case 1:
offset += filp->f_pos;
@@ -615,7 +615,7 @@ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
}
out:
- mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex);
return offset;
}
@@ -1102,7 +1102,7 @@ no_open:
static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
{
- struct dentry *parent = desc->file->f_dentry;
+ struct dentry *parent = desc->file->f_path.dentry;
struct inode *dir = parent->d_inode;
struct nfs_entry *entry = desc->entry;
struct dentry *dentry, *alias;
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index f9d678f4ae0..bd21d7fde65 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -116,7 +116,7 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
{
dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
- iocb->ki_filp->f_dentry->d_name.name,
+ iocb->ki_filp->f_path.dentry->d_name.name,
(long long) pos, nr_segs);
return -EINVAL;
@@ -734,8 +734,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
size_t count = iov[0].iov_len;
dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
- file->f_dentry->d_parent->d_name.name,
- file->f_dentry->d_name.name,
+ file->f_path.dentry->d_parent->d_name.name,
+ file->f_path.dentry->d_name.name,
(unsigned long) count, (long long) pos);
if (nr_segs != 1)
@@ -798,8 +798,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
size_t count = iov[0].iov_len;
dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
- file->f_dentry->d_parent->d_name.name,
- file->f_dentry->d_name.name,
+ file->f_path.dentry->d_parent->d_name.name,
+ file->f_path.dentry->d_name.name,
(unsigned long) count, (long long) pos);
if (nr_segs != 1)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 8e28bffc35a..9e4a2b70995 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -176,7 +176,7 @@ static int
nfs_file_flush(struct file *file, fl_owner_t id)
{
struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int status;
dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
@@ -201,7 +201,7 @@ static ssize_t
nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
- struct dentry * dentry = iocb->ki_filp->f_dentry;
+ struct dentry * dentry = iocb->ki_filp->f_path.dentry;
struct inode * inode = dentry->d_inode;
ssize_t result;
size_t count = iov_length(iov, nr_segs);
@@ -226,7 +226,7 @@ static ssize_t
nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
read_actor_t actor, void *target)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
ssize_t res;
@@ -243,7 +243,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
static int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
int status;
@@ -315,14 +315,13 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset)
static int nfs_release_page(struct page *page, gfp_t gfp)
{
- /*
- * Avoid deadlock on nfs_wait_on_request().
- */
- if (!(gfp & __GFP_FS))
- return 0;
- /* Hack... Force nfs_wb_page() to write out the page */
- SetPageDirty(page);
- return !nfs_wb_page(page->mapping->host, page);
+ /* If PagePrivate() is set, then the page is not freeable */
+ return 0;
+}
+
+static int nfs_launder_page(struct page *page)
+{
+ return nfs_wb_page(page->mapping->host, page);
}
const struct address_space_operations nfs_file_aops = {
@@ -338,12 +337,13 @@ const struct address_space_operations nfs_file_aops = {
#ifdef CONFIG_NFS_DIRECTIO
.direct_IO = nfs_direct_IO,
#endif
+ .launder_page = nfs_launder_page,
};
static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
- struct dentry * dentry = iocb->ki_filp->f_dentry;
+ struct dentry * dentry = iocb->ki_filp->f_path.dentry;
struct inode * inode = dentry->d_inode;
ssize_t result;
size_t count = iov_length(iov, nr_segs);
@@ -434,8 +434,9 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
BUG();
}
if (res < 0)
- printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
- __FUNCTION__);
+ dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager"
+ " - error %d!\n",
+ __FUNCTION__, res);
return res;
}
@@ -535,8 +536,8 @@ 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)
{
dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
- filp->f_dentry->d_inode->i_sb->s_id,
- filp->f_dentry->d_inode->i_ino,
+ filp->f_path.dentry->d_inode->i_sb->s_id,
+ filp->f_path.dentry->d_inode->i_ino,
fl->fl_type, fl->fl_flags);
/*
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 20c6f39ea38..8391bd7a83c 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -31,7 +31,7 @@
#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/security.h>
#include <asm/system.h>
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 82ad7110a1c..9d4a6b2d199 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -377,7 +377,7 @@ idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
static ssize_t
idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{
- struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+ struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
struct idmap *idmap = (struct idmap *)rpci->private;
struct idmap_msg im_in, *im = &idmap->idmap_im;
struct idmap_hashtable *h;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 36680d1061b..d8349828283 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -496,7 +496,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
*/
static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct nfs_inode *nfsi = NFS_I(inode);
filp->private_data = get_nfs_open_context(ctx);
@@ -528,7 +528,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
static void nfs_file_clear_open_context(struct file *filp)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
if (ctx) {
@@ -551,7 +551,7 @@ int nfs_open(struct inode *inode, struct file *filp)
cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
if (IS_ERR(cred))
return PTR_ERR(cred);
- ctx = alloc_nfs_open_context(filp->f_vfsmnt, filp->f_dentry, cred);
+ ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
put_rpccred(cred);
if (ctx == NULL)
return -ENOMEM;
@@ -665,49 +665,86 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
return __nfs_revalidate_inode(server, inode);
}
+static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if (mapping->nrpages != 0) {
+ int ret = invalidate_inode_pages2(mapping);
+ if (ret < 0)
+ return ret;
+ }
+ spin_lock(&inode->i_lock);
+ nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
+ if (S_ISDIR(inode->i_mode)) {
+ memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
+ /* This ensures we revalidate child dentries */
+ nfsi->cache_change_attribute = jiffies;
+ }
+ spin_unlock(&inode->i_lock);
+ nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
+ dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
+ inode->i_sb->s_id, (long long)NFS_FILEID(inode));
+ return 0;
+}
+
+static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
+{
+ int ret = 0;
+
+ mutex_lock(&inode->i_mutex);
+ if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_DATA) {
+ ret = nfs_sync_mapping(mapping);
+ if (ret == 0)
+ ret = nfs_invalidate_mapping_nolock(inode, mapping);
+ }
+ mutex_unlock(&inode->i_mutex);
+ return ret;
+}
+
/**
- * nfs_revalidate_mapping - Revalidate the pagecache
+ * nfs_revalidate_mapping_nolock - Revalidate the pagecache
* @inode - pointer to host inode
* @mapping - pointer to mapping
*/
-int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
{
struct nfs_inode *nfsi = NFS_I(inode);
int ret = 0;
- if (NFS_STALE(inode))
- ret = -ESTALE;
if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
- || nfs_attribute_timeout(inode))
+ || nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
- if (ret < 0)
- goto out;
+ if (ret < 0)
+ goto out;
+ }
+ if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
+ ret = nfs_invalidate_mapping_nolock(inode, mapping);
+out:
+ return ret;
+}
- if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
- if (mapping->nrpages != 0) {
- if (S_ISREG(inode->i_mode)) {
- ret = nfs_sync_mapping(mapping);
- if (ret < 0)
- goto out;
- }
- ret = invalidate_inode_pages2(mapping);
- if (ret < 0)
- goto out;
- }
- spin_lock(&inode->i_lock);
- nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;
- if (S_ISDIR(inode->i_mode)) {
- memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
- /* This ensures we revalidate child dentries */
- nfsi->cache_change_attribute = jiffies;
- }
- spin_unlock(&inode->i_lock);
+/**
+ * nfs_revalidate_mapping - Revalidate the pagecache
+ * @inode - pointer to host inode
+ * @mapping - pointer to mapping
+ *
+ * This version of the function will take the inode->i_mutex and attempt to
+ * flush out all dirty data if it needs to invalidate the page cache.
+ */
+int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ int ret = 0;
- nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
- dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
- inode->i_sb->s_id,
- (long long)NFS_FILEID(inode));
+ if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
+ || nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
+ ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ if (ret < 0)
+ goto out;
}
+ if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
+ ret = nfs_invalidate_mapping(inode, mapping);
out:
return ret;
}
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 510ae524f3f..acd8fe9762d 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -841,7 +841,7 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
static int
nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
{
- return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
+ return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
}
const struct nfs_rpc_ops nfs_v3_clientops = {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ee458aeab24..b3fd29baadc 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1877,7 +1877,7 @@ static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
struct nfs_server *server = NFS_SERVER(dir->d_inode);
struct unlink_desc *up;
- up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL);
+ up = kmalloc(sizeof(*up), GFP_KERNEL);
if (!up)
return -ENOMEM;
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 10f5e80ca15..560536ad74a 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -651,7 +651,7 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how)
static int
nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
{
- return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl);
+ return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl);
}
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 6c686112cc0..525c136c7d8 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -50,7 +50,9 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
struct page *page;
- void *err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
+ void *err;
+
+ err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
if (err)
goto read_failed;
page = read_cache_page(&inode->i_data, 0,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 594eb16879e..345492e7864 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -754,8 +754,8 @@ int nfs_updatepage(struct file *file, struct page *page,
nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n",
- file->f_dentry->d_parent->d_name.name,
- file->f_dentry->d_name.name, count,
+ file->f_path.dentry->d_parent->d_name.name,
+ file->f_path.dentry->d_name.name, count,
(long long)(page_offset(page) +offset));
/* If we're not using byte range locks, and we know the page
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index f37df46d2ea..49c310b8492 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -35,7 +35,6 @@
#include <linux/lockd/bind.h>
#define NFSDDBG_FACILITY NFSDDBG_EXPORT
-#define NFSD_PARANOIA 1
typedef struct auth_domain svc_client;
typedef struct svc_export svc_export;
@@ -787,15 +786,20 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
key.ex_dentry = dentry;
exp = svc_export_lookup(&key);
- if (exp != NULL)
- switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
+ if (exp != NULL) {
+ int err;
+
+ err = cache_check(&svc_export_cache, &exp->h, reqp);
+ switch (err) {
case 0: break;
case -EAGAIN:
- exp = ERR_PTR(-EAGAIN);
+ case -ETIMEDOUT:
+ exp = ERR_PTR(err);
break;
default:
exp = NULL;
}
+ }
return exp;
}
@@ -950,6 +954,8 @@ exp_export(struct nfsctl_export *nxp)
exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
+ memset(&new, 0, sizeof(new));
+
/* must make sure there won't be an ex_fsid clash */
if ((nxp->ex_flags & NFSEXP_FSID) &&
(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
@@ -980,6 +986,9 @@ exp_export(struct nfsctl_export *nxp)
new.h.expiry_time = NEVER;
new.h.flags = 0;
+ new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL);
+ if (!new.ex_path)
+ goto finish;
new.ex_client = clp;
new.ex_mnt = nd.mnt;
new.ex_dentry = nd.dentry;
@@ -1000,10 +1009,11 @@ exp_export(struct nfsctl_export *nxp)
/* failed to create at least one index */
exp_do_unexport(exp);
cache_flush();
- err = -ENOMEM;
- }
-
+ } else
+ err = 0;
finish:
+ if (new.ex_path)
+ kfree(new.ex_path);
if (exp)
exp_put(exp);
if (fsid_key && !IS_ERR(fsid_key))
@@ -1104,6 +1114,10 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
path, nd.dentry, clp->name,
inode->i_sb->s_id, inode->i_ino);
exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
+ if (IS_ERR(exp)) {
+ err = PTR_ERR(exp);
+ goto out;
+ }
if (!exp) {
dprintk("nfsd: exp_rootfh export not found.\n");
goto out;
@@ -1159,12 +1173,10 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
mk_fsid_v1(fsidv, 0);
exp = exp_find(clp, 1, fsidv, creq);
- if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
- return nfserr_dropit;
+ if (IS_ERR(exp))
+ return nfserrno(PTR_ERR(exp));
if (exp == NULL)
return nfserr_perm;
- else if (IS_ERR(exp))
- return nfserrno(PTR_ERR(exp));
rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
exp_put(exp);
return rv;
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 11fdaf7721b..221acd1f11f 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -22,7 +22,7 @@
/*
* Note: we hold the dentry use count while the file is open.
*/
-static u32
+static __be32
nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
{
__be32 nfserr;
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index e3eca081698..edde5dc5f79 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -222,12 +222,10 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
{
struct dentry *dentry = resp->fh.fh_dentry;
struct inode *inode = dentry->d_inode;
- int w = nfsacl_size(
- (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
struct kvec *head = rqstp->rq_res.head;
unsigned int base;
int n;
+ int w;
if (dentry == NULL || dentry->d_inode == NULL)
return 0;
@@ -239,7 +237,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
return 0;
base = (char *)p - (char *)head->iov_base;
- rqstp->rq_res.page_len = w;
+ rqstp->rq_res.page_len = w = nfsacl_size(
+ (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
+ (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
while (w > 0) {
if (!rqstp->rq_respages[rqstp->rq_resused++])
return 0;
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index fcad2895ddb..3e3f2de82c3 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -171,19 +171,19 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0 && dentry && dentry->d_inode) {
struct inode *inode = dentry->d_inode;
- int w = nfsacl_size(
- (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
struct kvec *head = rqstp->rq_res.head;
unsigned int base;
int n;
+ int w;
*p++ = htonl(resp->mask);
if (!xdr_ressize_check(rqstp, p))
return 0;
base = (char *)p - (char *)head->iov_base;
- rqstp->rq_res.page_len = w;
+ rqstp->rq_res.page_len = w = nfsacl_size(
+ (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
+ (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
while (w > 0) {
if (!rqstp->rq_respages[rqstp->rq_resused++])
return 0;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 277df40f098..e695660921e 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -990,15 +990,16 @@ encode_entry(struct readdir_cd *ccd, const char *name,
}
int
-nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
- int namlen, loff_t offset, ino_t ino, unsigned int d_type)
+nfs3svc_encode_entry(void *cd, const char *name,
+ int namlen, loff_t offset, u64 ino, unsigned int d_type)
{
return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
}
int
-nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
- int namlen, loff_t offset, ino_t ino, unsigned int d_type)
+nfs3svc_encode_entry_plus(void *cd, const char *name,
+ int namlen, loff_t offset, u64 ino,
+ unsigned int d_type)
{
return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 50bc94243ca..8522729830d 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -33,13 +33,6 @@
* 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.
- *
- * Note: some routines in this file are just trivial wrappers
- * (e.g. nfsd4_lookup()) defined solely for the sake of consistent
- * naming. Since all such routines have been declared "inline",
- * there shouldn't be any associated overhead. At some point in
- * the future, I might inline these "by hand" to clean up a
- * little.
*/
#include <linux/param.h>
@@ -161,8 +154,9 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
}
-static inline __be32
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
+static __be32
+nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_open *open)
{
__be32 status;
dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -179,11 +173,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
status = nfsd4_process_open1(open);
if (status == nfserr_replay_me) {
struct nfs4_replay *rp = &open->op_stateowner->so_replay;
- fh_put(current_fh);
- current_fh->fh_handle.fh_size = rp->rp_openfh_len;
- memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh,
+ fh_put(&cstate->current_fh);
+ cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
+ memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
rp->rp_openfh_len);
- status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
dprintk("nfsd4_open: replay failed"
" restoring previous filehandle\n");
@@ -215,7 +209,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
* (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);
+ status = do_open_lookup(rqstp, &cstate->current_fh,
+ open);
if (status)
goto out;
break;
@@ -227,7 +222,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
* open->op_truncate if the file is to be truncated
* after opening, (3) do permission checking.
*/
- status = do_open_fhandle(rqstp, current_fh, open);
+ status = do_open_fhandle(rqstp, &cstate->current_fh,
+ open);
if (status)
goto out;
break;
@@ -248,11 +244,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
* successful, it (1) truncates the file if open->op_truncate was
* set, (2) sets open->op_stateid, (3) sets open->op_delegation.
*/
- status = nfsd4_process_open2(rqstp, current_fh, open);
+ status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
out:
if (open->op_stateowner) {
nfs4_get_stateowner(open->op_stateowner);
- *replay_owner = open->op_stateowner;
+ cstate->replay_owner = open->op_stateowner;
}
nfs4_unlock_state();
return status;
@@ -261,71 +257,80 @@ out:
/*
* filehandle-manipulating ops.
*/
-static inline __be32
-nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
+static __be32
+nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct svc_fh **getfh)
{
- if (!current_fh->fh_dentry)
+ if (!cstate->current_fh.fh_dentry)
return nfserr_nofilehandle;
- *getfh = current_fh;
+ *getfh = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
+static __be32
+nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_putfh *putfh)
{
- fh_put(current_fh);
- current_fh->fh_handle.fh_size = putfh->pf_fhlen;
- memcpy(&current_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen);
- return fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ fh_put(&cstate->current_fh);
+ cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
+ memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
+ putfh->pf_fhlen);
+ return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
}
-static inline __be32
-nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+static __be32
+nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
__be32 status;
- fh_put(current_fh);
- status = exp_pseudoroot(rqstp->rq_client, current_fh,
+ fh_put(&cstate->current_fh);
+ status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
&rqstp->rq_chandle);
return status;
}
-static inline __be32
-nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+static __be32
+nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
- if (!save_fh->fh_dentry)
+ if (!cstate->save_fh.fh_dentry)
return nfserr_restorefh;
- fh_dup2(current_fh, save_fh);
+ fh_dup2(&cstate->current_fh, &cstate->save_fh);
return nfs_ok;
}
-static inline __be32
-nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+static __be32
+nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
- if (!current_fh->fh_dentry)
+ if (!cstate->current_fh.fh_dentry)
return nfserr_nofilehandle;
- fh_dup2(save_fh, current_fh);
+ fh_dup2(&cstate->save_fh, &cstate->current_fh);
return nfs_ok;
}
/*
* misc nfsv4 ops
*/
-static inline __be32
-nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
+static __be32
+nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_access *access)
{
if (access->ac_req_access & ~NFS3_ACCESS_FULL)
return nfserr_inval;
access->ac_resp_access = access->ac_req_access;
- return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
+ return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
+ &access->ac_supported);
}
-static inline __be32
-nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
+static __be32
+nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_commit *commit)
{
__be32 status;
@@ -333,14 +338,16 @@ nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_com
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
- status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
+ status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
+ commit->co_count);
if (status == nfserr_symlink)
status = nfserr_inval;
return status;
}
static __be32
-nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
+nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_create *create)
{
struct svc_fh resfh;
__be32 status;
@@ -348,7 +355,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
fh_init(&resfh, NFS4_FHSIZE);
- status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
+ status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE);
if (status == nfserr_symlink)
status = nfserr_notdir;
if (status)
@@ -365,9 +372,10 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
*/
create->cr_linkname[create->cr_linklen] = 0;
- status = nfsd_symlink(rqstp, current_fh, create->cr_name,
- create->cr_namelen, create->cr_linkname,
- create->cr_linklen, &resfh, &create->cr_iattr);
+ status = nfsd_symlink(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ create->cr_linkname, create->cr_linklen,
+ &resfh, &create->cr_iattr);
break;
case NF4BLK:
@@ -375,9 +383,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
if (MAJOR(rdev) != create->cr_specdata1 ||
MINOR(rdev) != create->cr_specdata2)
return nfserr_inval;
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFBLK, rdev, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFBLK, rdev, &resfh);
break;
case NF4CHR:
@@ -385,28 +393,28 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
if (MAJOR(rdev) != create->cr_specdata1 ||
MINOR(rdev) != create->cr_specdata2)
return nfserr_inval;
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFCHR, rdev, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr,S_IFCHR, rdev, &resfh);
break;
case NF4SOCK:
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFSOCK, 0, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFSOCK, 0, &resfh);
break;
case NF4FIFO:
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFIFO, 0, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFIFO, 0, &resfh);
break;
case NF4DIR:
create->cr_iattr.ia_valid &= ~ATTR_SIZE;
- status = nfsd_create(rqstp, current_fh, create->cr_name,
- create->cr_namelen, &create->cr_iattr,
- S_IFDIR, 0, &resfh);
+ status = nfsd_create(rqstp, &cstate->current_fh,
+ create->cr_name, create->cr_namelen,
+ &create->cr_iattr, S_IFDIR, 0, &resfh);
break;
default:
@@ -414,21 +422,22 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
}
if (!status) {
- fh_unlock(current_fh);
- set_change_info(&create->cr_cinfo, current_fh);
- fh_dup2(current_fh, &resfh);
+ fh_unlock(&cstate->current_fh);
+ set_change_info(&create->cr_cinfo, &cstate->current_fh);
+ fh_dup2(&cstate->current_fh, &resfh);
}
fh_put(&resfh);
return status;
}
-static inline __be32
-nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
+static __be32
+nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_getattr *getattr)
{
__be32 status;
- status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
return status;
@@ -438,26 +447,28 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ge
getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
- getattr->ga_fhp = current_fh;
+ getattr->ga_fhp = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct svc_fh *save_fh, struct nfsd4_link *link)
+static __be32
+nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_link *link)
{
__be32 status = nfserr_nofilehandle;
- if (!save_fh->fh_dentry)
+ if (!cstate->save_fh.fh_dentry)
return status;
- status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
+ status = nfsd_link(rqstp, &cstate->current_fh,
+ link->li_name, link->li_namelen, &cstate->save_fh);
if (!status)
- set_change_info(&link->li_cinfo, current_fh);
+ set_change_info(&link->li_cinfo, &cstate->current_fh);
return status;
}
static __be32
-nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ void *arg)
{
struct svc_fh tmp_fh;
__be32 ret;
@@ -466,22 +477,27 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
&rqstp->rq_chandle)) != 0)
return ret;
- if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
+ if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
fh_put(&tmp_fh);
return nfserr_noent;
}
fh_put(&tmp_fh);
- return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
+ return nfsd_lookup(rqstp, &cstate->current_fh,
+ "..", 2, &cstate->current_fh);
}
-static inline __be32
-nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
+static __be32
+nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_lookup *lookup)
{
- return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
+ return nfsd_lookup(rqstp, &cstate->current_fh,
+ lookup->lo_name, lookup->lo_len,
+ &cstate->current_fh);
}
-static inline __be32
-nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
+static __be32
+nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_read *read)
{
__be32 status;
@@ -493,7 +509,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
nfs4_lock_state();
/* check stateid */
- if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+ if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+ &read->rd_stateid,
CHECK_FH | RD_STATE, &read->rd_filp))) {
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
goto out;
@@ -504,12 +521,13 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
out:
nfs4_unlock_state();
read->rd_rqstp = rqstp;
- read->rd_fhp = current_fh;
+ read->rd_fhp = &cstate->current_fh;
return status;
}
-static inline __be32
-nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
+static __be32
+nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_readdir *readdir)
{
u64 cookie = readdir->rd_cookie;
static const nfs4_verifier zeroverf;
@@ -527,48 +545,51 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_re
return nfserr_bad_cookie;
readdir->rd_rqstp = rqstp;
- readdir->rd_fhp = current_fh;
+ readdir->rd_fhp = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
+static __be32
+nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_readlink *readlink)
{
readlink->rl_rqstp = rqstp;
- readlink->rl_fhp = current_fh;
+ readlink->rl_fhp = &cstate->current_fh;
return nfs_ok;
}
-static inline __be32
-nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
+static __be32
+nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_remove *remove)
{
__be32 status;
if (nfs4_in_grace())
return nfserr_grace;
- status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
+ status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
+ remove->rm_name, remove->rm_namelen);
if (status == nfserr_symlink)
return nfserr_notdir;
if (!status) {
- fh_unlock(current_fh);
- set_change_info(&remove->rm_cinfo, current_fh);
+ fh_unlock(&cstate->current_fh);
+ set_change_info(&remove->rm_cinfo, &cstate->current_fh);
}
return status;
}
-static inline __be32
-nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct svc_fh *save_fh, struct nfsd4_rename *rename)
+static __be32
+nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_rename *rename)
{
__be32 status = nfserr_nofilehandle;
- if (!save_fh->fh_dentry)
+ if (!cstate->save_fh.fh_dentry)
return status;
- if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
+ if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
& NFSEXP_NOSUBTREECHECK))
return nfserr_grace;
- status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
- rename->rn_snamelen, current_fh,
+ status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+ rename->rn_snamelen, &cstate->current_fh,
rename->rn_tname, rename->rn_tnamelen);
/* the underlying filesystem returns different error's than required
@@ -576,27 +597,28 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
if (status == nfserr_isdir)
status = nfserr_exist;
else if ((status == nfserr_notdir) &&
- (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
- S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
+ (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
+ S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
status = nfserr_exist;
else if (status == nfserr_symlink)
status = nfserr_notdir;
if (!status) {
- set_change_info(&rename->rn_sinfo, current_fh);
- set_change_info(&rename->rn_tinfo, save_fh);
+ set_change_info(&rename->rn_sinfo, &cstate->current_fh);
+ set_change_info(&rename->rn_tinfo, &cstate->save_fh);
}
return status;
}
-static inline __be32
-nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
+static __be32
+nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_setattr *setattr)
{
__be32 status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh,
+ status = nfs4_preprocess_stateid_op(&cstate->current_fh,
&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
nfs4_unlock_state();
if (status) {
@@ -606,16 +628,18 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
}
status = nfs_ok;
if (setattr->sa_acl != NULL)
- status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+ status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
+ setattr->sa_acl);
if (status)
return status;
- status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+ status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
0, (time_t)0);
return status;
}
-static inline __be32
-nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
+static __be32
+nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_write *write)
{
stateid_t *stateid = &write->wr_stateid;
struct file *filp = NULL;
@@ -628,7 +652,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
return nfserr_inval;
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh, stateid,
+ status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
CHECK_FH | WR_STATE, &filp);
if (filp)
get_file(filp);
@@ -645,9 +669,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
- status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
- rqstp->rq_vec, write->wr_vlen, write->wr_buflen,
- &write->wr_how_written);
+ status = nfsd_write(rqstp, &cstate->current_fh, filp,
+ write->wr_offset, rqstp->rq_vec, write->wr_vlen,
+ write->wr_buflen, &write->wr_how_written);
if (filp)
fput(filp);
@@ -662,13 +686,14 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
* to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
*/
static __be32
-nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
+_nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_verify *verify)
{
__be32 *buf, *p;
int count;
__be32 status;
- status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+ status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
if (status)
return status;
@@ -689,8 +714,9 @@ nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ver
if (!buf)
return nfserr_resource;
- status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
- current_fh->fh_dentry, buf,
+ status = nfsd4_encode_fattr(&cstate->current_fh,
+ cstate->current_fh.fh_export,
+ cstate->current_fh.fh_dentry, buf,
&count, verify->ve_bmval,
rqstp);
@@ -712,6 +738,26 @@ out_kfree:
return status;
}
+static __be32
+nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_verify *verify)
+{
+ __be32 status;
+
+ status = _nfsd4_verify(rqstp, cstate, verify);
+ return status == nfserr_not_same ? nfs_ok : status;
+}
+
+static __be32
+nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_verify *verify)
+{
+ __be32 status;
+
+ status = _nfsd4_verify(rqstp, cstate, verify);
+ return status == nfserr_same ? nfs_ok : status;
+}
+
/*
* NULL call.
*/
@@ -727,6 +773,42 @@ static inline void nfsd4_increment_op_stats(u32 opnum)
nfsdstats.nfs4_opcount[opnum]++;
}
+static void cstate_free(struct nfsd4_compound_state *cstate)
+{
+ if (cstate == NULL)
+ return;
+ fh_put(&cstate->current_fh);
+ fh_put(&cstate->save_fh);
+ BUG_ON(cstate->replay_owner);
+ kfree(cstate);
+}
+
+static struct nfsd4_compound_state *cstate_alloc(void)
+{
+ struct nfsd4_compound_state *cstate;
+
+ cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
+ if (cstate == NULL)
+ return NULL;
+ fh_init(&cstate->current_fh, NFS4_FHSIZE);
+ fh_init(&cstate->save_fh, NFS4_FHSIZE);
+ cstate->replay_owner = NULL;
+ return cstate;
+}
+
+typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
+ void *);
+
+struct nfsd4_operation {
+ nfsd4op_func op_func;
+ u32 op_flags;
+/* Most ops require a valid current filehandle; a few don't: */
+#define ALLOWED_WITHOUT_FH 1
+/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
+#define ALLOWED_ON_ABSENT_FS 2
+};
+
+static struct nfsd4_operation nfsd4_ops[];
/*
* COMPOUND call.
@@ -737,21 +819,15 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
struct nfsd4_compoundres *resp)
{
struct nfsd4_op *op;
- struct svc_fh *current_fh = NULL;
- struct svc_fh *save_fh = NULL;
- struct nfs4_stateowner *replay_owner = NULL;
- int slack_space; /* in words, not bytes! */
+ struct nfsd4_operation *opdesc;
+ struct nfsd4_compound_state *cstate = NULL;
+ int slack_bytes;
__be32 status;
status = nfserr_resource;
- current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL);
- if (current_fh == NULL)
- goto out;
- fh_init(current_fh, NFS4_FHSIZE);
- save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL);
- if (save_fh == NULL)
+ cstate = cstate_alloc();
+ if (cstate == NULL)
goto out;
- fh_init(save_fh, NFS4_FHSIZE);
resp->xbuf = &rqstp->rq_res;
resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
@@ -790,164 +866,44 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* failed response to the next operation. If we don't
* have enough room, fail with ERR_RESOURCE.
*/
-/* FIXME - is slack_space *really* words, or bytes??? - neilb */
- slack_space = (char *)resp->end - (char *)resp->p;
- if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) {
- BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE);
+ slack_bytes = (char *)resp->end - (char *)resp->p;
+ if (slack_bytes < COMPOUND_SLACK_SPACE
+ + COMPOUND_ERR_SLACK_SPACE) {
+ BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
op->status = nfserr_resource;
goto encode_op;
}
- /* All operations except RENEW, SETCLIENTID, RESTOREFH
- * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
- * require a valid current filehandle
- */
- if (!current_fh->fh_dentry) {
- if (!((op->opnum == OP_PUTFH) ||
- (op->opnum == OP_PUTROOTFH) ||
- (op->opnum == OP_SETCLIENTID) ||
- (op->opnum == OP_SETCLIENTID_CONFIRM) ||
- (op->opnum == OP_RENEW) ||
- (op->opnum == OP_RESTOREFH) ||
- (op->opnum == OP_RELEASE_LOCKOWNER))) {
+ opdesc = &nfsd4_ops[op->opnum];
+
+ if (!cstate->current_fh.fh_dentry) {
+ if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
op->status = nfserr_nofilehandle;
goto encode_op;
}
- }
- /* Check must be done at start of each operation, except
- * for GETATTR and ops not listed as returning NFS4ERR_MOVED
- */
- else if (current_fh->fh_export->ex_fslocs.migrated &&
- !((op->opnum == OP_GETATTR) ||
- (op->opnum == OP_PUTROOTFH) ||
- (op->opnum == OP_PUTPUBFH) ||
- (op->opnum == OP_RENEW) ||
- (op->opnum == OP_SETCLIENTID) ||
- (op->opnum == OP_RELEASE_LOCKOWNER))) {
+ } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
+ !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
op->status = nfserr_moved;
goto encode_op;
}
- switch (op->opnum) {
- case OP_ACCESS:
- op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
- break;
- case OP_CLOSE:
- op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
- break;
- case OP_COMMIT:
- op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
- break;
- case OP_CREATE:
- op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
- break;
- case OP_DELEGRETURN:
- op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn);
- break;
- case OP_GETATTR:
- op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
- break;
- case OP_GETFH:
- op->status = nfsd4_getfh(current_fh, &op->u.getfh);
- break;
- case OP_LINK:
- op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
- break;
- case OP_LOCK:
- op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
- break;
- case OP_LOCKT:
- op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
- break;
- case OP_LOCKU:
- op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
- break;
- case OP_LOOKUP:
- op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
- break;
- case OP_LOOKUPP:
- op->status = nfsd4_lookupp(rqstp, current_fh);
- break;
- case OP_NVERIFY:
- op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
- if (op->status == nfserr_not_same)
- op->status = nfs_ok;
- break;
- case OP_OPEN:
- op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
- break;
- case OP_OPEN_CONFIRM:
- op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
- break;
- case OP_OPEN_DOWNGRADE:
- op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
- break;
- case OP_PUTFH:
- op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
- break;
- case OP_PUTROOTFH:
- op->status = nfsd4_putrootfh(rqstp, current_fh);
- break;
- case OP_READ:
- op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
- break;
- case OP_READDIR:
- op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
- break;
- case OP_READLINK:
- op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
- break;
- case OP_REMOVE:
- op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
- break;
- case OP_RENAME:
- op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
- break;
- case OP_RENEW:
- op->status = nfsd4_renew(&op->u.renew);
- break;
- case OP_RESTOREFH:
- op->status = nfsd4_restorefh(current_fh, save_fh);
- break;
- case OP_SAVEFH:
- op->status = nfsd4_savefh(current_fh, save_fh);
- break;
- case OP_SETATTR:
- op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
- break;
- case OP_SETCLIENTID:
- op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
- break;
- case OP_SETCLIENTID_CONFIRM:
- op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
- break;
- case OP_VERIFY:
- op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify);
- if (op->status == nfserr_same)
- op->status = nfs_ok;
- break;
- case OP_WRITE:
- op->status = nfsd4_write(rqstp, current_fh, &op->u.write);
- break;
- case OP_RELEASE_LOCKOWNER:
- op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
- break;
- default:
+
+ if (opdesc->op_func)
+ op->status = opdesc->op_func(rqstp, cstate, &op->u);
+ else
BUG_ON(op->status == nfs_ok);
- break;
- }
encode_op:
if (op->status == nfserr_replay_me) {
- op->replay = &replay_owner->so_replay;
+ op->replay = &cstate->replay_owner->so_replay;
nfsd4_encode_replay(resp, op);
status = op->status = op->replay->rp_status;
} else {
nfsd4_encode_operation(resp, op);
status = op->status;
}
- if (replay_owner && (replay_owner != (void *)(-1))) {
- nfs4_put_stateowner(replay_owner);
- replay_owner = NULL;
+ if (cstate->replay_owner) {
+ nfs4_put_stateowner(cstate->replay_owner);
+ cstate->replay_owner = NULL;
}
/* XXX Ugh, we need to get rid of this kind of special case: */
if (op->opnum == OP_READ && op->u.read.rd_filp)
@@ -958,15 +914,124 @@ encode_op:
out:
nfsd4_release_compoundargs(args);
- if (current_fh)
- fh_put(current_fh);
- kfree(current_fh);
- if (save_fh)
- fh_put(save_fh);
- kfree(save_fh);
+ cstate_free(cstate);
return status;
}
+static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
+ [OP_ACCESS] = {
+ .op_func = (nfsd4op_func)nfsd4_access,
+ },
+ [OP_CLOSE] = {
+ .op_func = (nfsd4op_func)nfsd4_close,
+ },
+ [OP_COMMIT] = {
+ .op_func = (nfsd4op_func)nfsd4_commit,
+ },
+ [OP_CREATE] = {
+ .op_func = (nfsd4op_func)nfsd4_create,
+ },
+ [OP_DELEGRETURN] = {
+ .op_func = (nfsd4op_func)nfsd4_delegreturn,
+ },
+ [OP_GETATTR] = {
+ .op_func = (nfsd4op_func)nfsd4_getattr,
+ .op_flags = ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_GETFH] = {
+ .op_func = (nfsd4op_func)nfsd4_getfh,
+ },
+ [OP_LINK] = {
+ .op_func = (nfsd4op_func)nfsd4_link,
+ },
+ [OP_LOCK] = {
+ .op_func = (nfsd4op_func)nfsd4_lock,
+ },
+ [OP_LOCKT] = {
+ .op_func = (nfsd4op_func)nfsd4_lockt,
+ },
+ [OP_LOCKU] = {
+ .op_func = (nfsd4op_func)nfsd4_locku,
+ },
+ [OP_LOOKUP] = {
+ .op_func = (nfsd4op_func)nfsd4_lookup,
+ },
+ [OP_LOOKUPP] = {
+ .op_func = (nfsd4op_func)nfsd4_lookupp,
+ },
+ [OP_NVERIFY] = {
+ .op_func = (nfsd4op_func)nfsd4_nverify,
+ },
+ [OP_OPEN] = {
+ .op_func = (nfsd4op_func)nfsd4_open,
+ },
+ [OP_OPEN_CONFIRM] = {
+ .op_func = (nfsd4op_func)nfsd4_open_confirm,
+ },
+ [OP_OPEN_DOWNGRADE] = {
+ .op_func = (nfsd4op_func)nfsd4_open_downgrade,
+ },
+ [OP_PUTFH] = {
+ .op_func = (nfsd4op_func)nfsd4_putfh,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_PUTPUBFH] = {
+ /* unsupported; just for future reference: */
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_PUTROOTFH] = {
+ .op_func = (nfsd4op_func)nfsd4_putrootfh,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_READ] = {
+ .op_func = (nfsd4op_func)nfsd4_read,
+ },
+ [OP_READDIR] = {
+ .op_func = (nfsd4op_func)nfsd4_readdir,
+ },
+ [OP_READLINK] = {
+ .op_func = (nfsd4op_func)nfsd4_readlink,
+ },
+ [OP_REMOVE] = {
+ .op_func = (nfsd4op_func)nfsd4_remove,
+ },
+ [OP_RENAME] = {
+ .op_func = (nfsd4op_func)nfsd4_rename,
+ },
+ [OP_RENEW] = {
+ .op_func = (nfsd4op_func)nfsd4_renew,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_RESTOREFH] = {
+ .op_func = (nfsd4op_func)nfsd4_restorefh,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_SAVEFH] = {
+ .op_func = (nfsd4op_func)nfsd4_savefh,
+ },
+ [OP_SETATTR] = {
+ .op_func = (nfsd4op_func)nfsd4_setattr,
+ },
+ [OP_SETCLIENTID] = {
+ .op_func = (nfsd4op_func)nfsd4_setclientid,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_SETCLIENTID_CONFIRM] = {
+ .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+ [OP_VERIFY] = {
+ .op_func = (nfsd4op_func)nfsd4_verify,
+ },
+ [OP_WRITE] = {
+ .op_func = (nfsd4op_func)nfsd4_write,
+ },
+ [OP_RELEASE_LOCKOWNER] = {
+ .op_func = (nfsd4op_func)nfsd4_release_lockowner,
+ .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
+ },
+};
+
#define nfs4svc_decode_voidargs NULL
#define nfs4svc_release_void NULL
#define nfsd4_voidres nfsd4_voidargs
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 81b8565d383..c7774e3a946 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -259,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
printk("nfsd4: non-file found in client recovery directory\n");
return -EINVAL;
}
- mutex_lock(&dir->d_inode->i_mutex);
+ mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
status = vfs_unlink(dir->d_inode, dentry);
mutex_unlock(&dir->d_inode->i_mutex);
return status;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 640c92b2a9f..9de89df961f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -711,7 +711,8 @@ out_err:
*
*/
__be32
-nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_setclientid *setclid)
{
__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
struct xdr_netobj clname = {
@@ -876,7 +877,9 @@ out:
* NOTE: callback information will be processed here in a future patch
*/
__be32
-nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
+nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *cstate,
+ struct nfsd4_setclientid_confirm *setclientid_confirm)
{
__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
struct nfs4_client *conf, *unconf;
@@ -1310,7 +1313,7 @@ static inline void
nfs4_file_downgrade(struct file *filp, unsigned int share_access)
{
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
- put_write_access(filp->f_dentry->d_inode);
+ put_write_access(filp->f_path.dentry->d_inode);
filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
}
}
@@ -1623,7 +1626,7 @@ static __be32
nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
{
struct file *filp = stp->st_vfs_file;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
unsigned int share_access, new_writer;
__be32 status;
@@ -1833,7 +1836,8 @@ static void laundromat_main(struct work_struct *);
static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
__be32
-nfsd4_renew(clientid_t *clid)
+nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ clientid_t *clid)
{
struct nfs4_client *clp;
__be32 status;
@@ -1965,7 +1969,7 @@ search_close_lru(u32 st_id, int flags)
static inline int
nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
{
- return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode;
+ return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
}
static int
@@ -2241,24 +2245,25 @@ check_replay:
}
__be32
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_open_confirm *oc)
{
__be32 status;
struct nfs4_stateowner *sop;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
- (int)current_fh->fh_dentry->d_name.len,
- current_fh->fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_dentry->d_name.len,
+ cstate->current_fh.fh_dentry->d_name.name);
- status = fh_verify(rqstp, current_fh, S_IFREG, 0);
+ status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
if (status)
return status;
nfs4_lock_state();
- if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
- &oc->oc_req_stateid,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ oc->oc_seqid, &oc->oc_req_stateid,
CHECK_FH | CONFIRM | OPEN_STATE,
&oc->oc_stateowner, &stp, NULL)))
goto out;
@@ -2278,7 +2283,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
out:
if (oc->oc_stateowner) {
nfs4_get_stateowner(oc->oc_stateowner);
- *replay_owner = oc->oc_stateowner;
+ cstate->replay_owner = oc->oc_stateowner;
}
nfs4_unlock_state();
return status;
@@ -2310,22 +2315,25 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap)
}
__be32
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
+nfsd4_open_downgrade(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *cstate,
+ struct nfsd4_open_downgrade *od)
{
__be32 status;
struct nfs4_stateid *stp;
unsigned int share_access;
dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
- (int)current_fh->fh_dentry->d_name.len,
- current_fh->fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_dentry->d_name.len,
+ cstate->current_fh.fh_dentry->d_name.name);
if (!access_valid(od->od_share_access)
|| !deny_valid(od->od_share_deny))
return nfserr_inval;
nfs4_lock_state();
- if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ od->od_seqid,
&od->od_stateid,
CHECK_FH | OPEN_STATE,
&od->od_stateowner, &stp, NULL)))
@@ -2355,7 +2363,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
out:
if (od->od_stateowner) {
nfs4_get_stateowner(od->od_stateowner);
- *replay_owner = od->od_stateowner;
+ cstate->replay_owner = od->od_stateowner;
}
nfs4_unlock_state();
return status;
@@ -2365,18 +2373,20 @@ out:
* nfs4_unlock_state() called after encode
*/
__be32
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
+nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_close *close)
{
__be32 status;
struct nfs4_stateid *stp;
dprintk("NFSD: nfsd4_close on file %.*s\n",
- (int)current_fh->fh_dentry->d_name.len,
- current_fh->fh_dentry->d_name.name);
+ (int)cstate->current_fh.fh_dentry->d_name.len,
+ cstate->current_fh.fh_dentry->d_name.name);
nfs4_lock_state();
/* check close_lru for replay */
- if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ close->cl_seqid,
&close->cl_stateid,
CHECK_FH | OPEN_STATE | CLOSE_STATE,
&close->cl_stateowner, &stp, NULL)))
@@ -2397,22 +2407,24 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
out:
if (close->cl_stateowner) {
nfs4_get_stateowner(close->cl_stateowner);
- *replay_owner = close->cl_stateowner;
+ cstate->replay_owner = close->cl_stateowner;
}
nfs4_unlock_state();
return status;
}
__be32
-nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr)
+nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_delegreturn *dr)
{
__be32 status;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
+ if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
goto out;
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
+ status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+ &dr->dr_stateid, DELEG_RET, NULL);
nfs4_unlock_state();
out:
return status;
@@ -2635,7 +2647,8 @@ check_lock_length(u64 offset, u64 length)
* LOCK operation
*/
__be32
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
+nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_lock *lock)
{
struct nfs4_stateowner *open_sop = NULL;
struct nfs4_stateowner *lock_sop = NULL;
@@ -2654,7 +2667,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (check_lock_length(lock->lk_offset, lock->lk_length))
return nfserr_inval;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+ if ((status = fh_verify(rqstp, &cstate->current_fh,
+ S_IFREG, MAY_LOCK))) {
dprintk("NFSD: nfsd4_lock: permission denied!\n");
return status;
}
@@ -2675,7 +2689,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
goto out;
/* validate and update open stateid and open seqid */
- status = nfs4_preprocess_seqid_op(current_fh,
+ status = nfs4_preprocess_seqid_op(&cstate->current_fh,
lock->lk_new_open_seqid,
&lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE,
@@ -2702,7 +2716,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
goto out;
} else {
/* lock (lock owner + lock stateid) already exists */
- status = nfs4_preprocess_seqid_op(current_fh,
+ status = nfs4_preprocess_seqid_op(&cstate->current_fh,
lock->lk_old_lock_seqid,
&lock->lk_old_lock_stateid,
CHECK_FH | LOCK_STATE,
@@ -2759,7 +2773,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
conflock.fl_ops = NULL;
conflock.fl_lmops = NULL;
err = posix_lock_file_conf(filp, &file_lock, &conflock);
- dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
switch (-err) {
case 0: /* success! */
update_stateid(&lock_stp->st_stateid);
@@ -2785,7 +2798,7 @@ out:
release_stateowner(lock_sop);
if (lock->lk_replay_owner) {
nfs4_get_stateowner(lock->lk_replay_owner);
- *replay_owner = lock->lk_replay_owner;
+ cstate->replay_owner = lock->lk_replay_owner;
}
nfs4_unlock_state();
return status;
@@ -2795,7 +2808,8 @@ out:
* LOCKT operation
*/
__be32
-nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
+nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_lockt *lockt)
{
struct inode *inode;
struct file file;
@@ -2816,14 +2830,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (STALE_CLIENTID(&lockt->lt_clientid))
goto out;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
+ if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) {
dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
if (status == nfserr_symlink)
status = nfserr_inval;
goto out;
}
- inode = current_fh->fh_dentry->d_inode;
+ inode = cstate->current_fh.fh_dentry->d_inode;
locks_init_lock(&file_lock);
switch (lockt->lt_type) {
case NFS4_READ_LT:
@@ -2862,7 +2876,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* only the dentry:inode set.
*/
memset(&file, 0, sizeof (struct file));
- file.f_dentry = current_fh->fh_dentry;
+ file.f_path.dentry = cstate->current_fh.fh_dentry;
status = nfs_ok;
if (posix_test_lock(&file, &file_lock, &conflock)) {
@@ -2875,7 +2889,8 @@ out:
}
__be32
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
+nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ struct nfsd4_locku *locku)
{
struct nfs4_stateid *stp;
struct file *filp = NULL;
@@ -2892,7 +2907,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
nfs4_lock_state();
- if ((status = nfs4_preprocess_seqid_op(current_fh,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
locku->lu_seqid,
&locku->lu_stateid,
CHECK_FH | LOCK_STATE,
@@ -2933,7 +2948,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
out:
if (locku->lu_stateowner) {
nfs4_get_stateowner(locku->lu_stateowner);
- *replay_owner = locku->lu_stateowner;
+ cstate->replay_owner = locku->lu_stateowner;
}
nfs4_unlock_state();
return status;
@@ -2952,7 +2967,7 @@ static int
check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
{
struct file_lock **flpp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int status = 0;
lock_kernel();
@@ -2968,7 +2983,9 @@ out:
}
__be32
-nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
+nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *cstate,
+ struct nfsd4_release_lockowner *rlockowner)
{
clientid_t *clid = &rlockowner->rl_clientid;
struct nfs4_stateowner *sop;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f3f239db04b..18aa9440df1 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1845,15 +1845,11 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
exp_get(exp);
if (d_mountpoint(dentry)) {
- if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) {
- /*
- * -EAGAIN is the only error returned from
- * nfsd_cross_mnt() and it indicates that an
- * up-call has been initiated to fill in the export
- * options on exp. When the answer comes back,
- * this call will be retried.
- */
- nfserr = nfserr_dropit;
+ int err;
+
+ err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+ if (err) {
+ nfserr = nfserrno(err);
goto out_put;
}
@@ -1884,9 +1880,10 @@ nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
}
static int
-nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
- loff_t offset, ino_t ino, unsigned int d_type)
+nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
+ loff_t offset, u64 ino, unsigned int d_type)
{
+ struct readdir_cd *ccd = ccdv;
struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
int buflen;
__be32 *p = cd->buffer;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 6100bbe2743..f90d7047585 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -66,14 +66,13 @@ nfsd_cache_init(void)
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);
+ hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
if (!hash_list) {
nfsd_cache_shutdown();
printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
HASHSIZE * sizeof(struct hlist_head));
return;
}
- memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
cache_disabled = 0;
}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 39aed901514..eedf2e3990a 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -111,7 +111,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
{
- ino_t ino = file->f_dentry->d_inode->i_ino;
+ ino_t ino = file->f_path.dentry->d_inode->i_ino;
char *data;
ssize_t rv;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 727ab3bd450..c59d6fbb7a6 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -24,8 +24,6 @@
#include <linux/nfsd/nfsd.h>
#define NFSDDBG_FACILITY NFSDDBG_FH
-#define NFSD_PARANOIA 1
-/* #define NFSD_DEBUG_VERBOSE 1 */
static int nfsd_nr_verified;
@@ -169,9 +167,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
}
- error = nfserr_dropit;
- if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
+ if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
+ || PTR_ERR(exp) == -ETIMEDOUT)) {
+ error = nfserrno(PTR_ERR(exp));
goto out;
+ }
error = nfserr_stale;
if (!exp || IS_ERR(exp))
@@ -228,13 +228,12 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
error = nfserrno(PTR_ERR(dentry));
goto out;
}
-#ifdef NFSD_PARANOIA
+
if (S_ISDIR(dentry->d_inode->i_mode) &&
(dentry->d_flags & DCACHE_DISCONNECTED)) {
printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
}
-#endif
fhp->fh_dentry = dentry;
fhp->fh_export = exp;
@@ -265,12 +264,13 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
/* Finally, check access permissions. */
error = nfsd_permission(exp, dentry, access);
-#ifdef NFSD_PARANOIA_EXTREME
if (error) {
- printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
+ dprintk("fh_verify: %s/%s permission failure, "
+ "acc=%x, error=%d\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name,
+ access, ntohl(error));
}
-#endif
out:
if (exp && !IS_ERR(exp))
exp_put(exp);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 0aaccb03bf7..fbf5d51947e 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -72,7 +72,7 @@ static struct svc_program nfsd_acl_program = {
.pg_prog = NFS_ACL_PROGRAM,
.pg_nvers = NFSD_ACL_NRVERS,
.pg_vers = nfsd_acl_versions,
- .pg_name = "nfsd",
+ .pg_name = "nfsacl",
.pg_class = "nfsd",
.pg_stats = &nfsd_acl_svcstats,
.pg_authenticate = &svc_set_client,
@@ -118,16 +118,16 @@ int nfsd_vers(int vers, enum vers_op change)
switch(change) {
case NFSD_SET:
nfsd_versions[vers] = nfsd_version[vers];
- break;
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
if (vers < NFSD_ACL_NRVERS)
- nfsd_acl_version[vers] = nfsd_acl_version[vers];
+ nfsd_acl_versions[vers] = nfsd_acl_version[vers];
#endif
+ break;
case NFSD_CLEAR:
nfsd_versions[vers] = NULL;
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
if (vers < NFSD_ACL_NRVERS)
- nfsd_acl_version[vers] = NULL;
+ nfsd_acl_versions[vers] = NULL;
#endif
break;
case NFSD_TEST:
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index f5243f94399..6555c50d900 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -462,9 +462,10 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p,
}
int
-nfssvc_encode_entry(struct readdir_cd *ccd, const char *name,
- int namlen, loff_t offset, ino_t ino, unsigned int d_type)
+nfssvc_encode_entry(void *ccdv, const char *name,
+ int namlen, loff_t offset, u64 ino, unsigned int d_type)
{
+ struct readdir_cd *ccd = ccdv;
struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common);
__be32 *p = cd->buffer;
int buflen, slen;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index bb4d926e448..8283236c6a0 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -59,7 +59,6 @@
#include <asm/uaccess.h>
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
-#define NFSD_PARANOIA
/* We must ignore files (but only files) which might have mandatory
@@ -99,7 +98,7 @@ static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
/*
* Called from nfsd_lookup and encode_dirent. Check if we have crossed
* a mount point.
- * Returns -EAGAIN leaving *dpp and *expp unchanged,
+ * Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
* or nfs_ok having possibly changed *dpp and *expp
*/
int
@@ -736,10 +735,10 @@ static int
nfsd_sync(struct file *filp)
{
int err;
- struct inode *inode = filp->f_dentry->d_inode;
- dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
mutex_lock(&inode->i_mutex);
- err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
+ err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
mutex_unlock(&inode->i_mutex);
return err;
@@ -822,7 +821,8 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
rqstp->rq_res.page_len = size;
} else if (page != pp[-1]) {
get_page(page);
- put_page(*pp);
+ if (*pp)
+ put_page(*pp);
*pp = page;
rqstp->rq_resused++;
rqstp->rq_res.page_len += size;
@@ -845,7 +845,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
int host_err;
err = nfserr_perm;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(!lock_may_read(inode, offset, *count)))
@@ -883,7 +883,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
nfsdstats.io_read += host_err;
*count = host_err;
err = 0;
- fsnotify_access(file->f_dentry);
+ fsnotify_access(file->f_path.dentry);
} else
err = nfserrno(host_err);
out:
@@ -917,11 +917,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
err = nfserr_perm;
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
- (!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
+ (!lock_may_write(file->f_path.dentry->d_inode, offset, cnt)))
goto out;
#endif
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
inode = dentry->d_inode;
exp = fhp->fh_export;
@@ -950,7 +950,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
set_fs(oldfs);
if (host_err >= 0) {
nfsdstats.io_write += cnt;
- fsnotify_modify(file->f_dentry);
+ fsnotify_modify(file->f_path.dentry);
}
/* clear setuid/setgid flag after write */
@@ -1244,7 +1244,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
__be32 err;
int host_err;
__u32 v_mtime=0, v_atime=0;
- int v_mode=0;
err = nfserr_perm;
if (!flen)
@@ -1281,16 +1280,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out;
if (createmode == NFS3_CREATE_EXCLUSIVE) {
- /* while the verifier would fit in mtime+atime,
- * solaris7 gets confused (bugid 4218508) if these have
- * the high bit set, so we use the mode as well
+ /* solaris7 gets confused (bugid 4218508) if these have
+ * the high bit set, so just clear the high bits.
*/
v_mtime = verifier[0]&0x7fffffff;
v_atime = verifier[1]&0x7fffffff;
- v_mode = S_IFREG
- | ((verifier[0]&0x80000000) >> (32-7)) /* u+x */
- | ((verifier[1]&0x80000000) >> (32-9)) /* u+r */
- ;
}
if (dchild->d_inode) {
@@ -1318,7 +1312,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
case NFS3_CREATE_EXCLUSIVE:
if ( dchild->d_inode->i_mtime.tv_sec == v_mtime
&& dchild->d_inode->i_atime.tv_sec == v_atime
- && dchild->d_inode->i_mode == v_mode
&& dchild->d_inode->i_size == 0 )
break;
/* fallthru */
@@ -1340,26 +1333,22 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
}
if (createmode == NFS3_CREATE_EXCLUSIVE) {
- /* Cram the verifier into atime/mtime/mode */
+ /* Cram the verifier into atime/mtime */
iap->ia_valid = ATTR_MTIME|ATTR_ATIME
- | ATTR_MTIME_SET|ATTR_ATIME_SET
- | ATTR_MODE;
+ | ATTR_MTIME_SET|ATTR_ATIME_SET;
/* XXX someone who knows this better please fix it for nsec */
iap->ia_mtime.tv_sec = v_mtime;
iap->ia_atime.tv_sec = v_atime;
iap->ia_mtime.tv_nsec = 0;
iap->ia_atime.tv_nsec = 0;
- iap->ia_mode = v_mode;
}
/* Set file attributes.
- * Mode has already been set but we might need to reset it
- * for CREATE_EXCLUSIVE
* Irix appears to send along the gid when it tries to
* implement setgid directories via NFS. Clear out all that cruft.
*/
set_attr:
- if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
if (err2)
err = err2;
@@ -1726,7 +1715,7 @@ out:
*/
__be32
nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
- struct readdir_cd *cdp, encode_dent_fn func)
+ struct readdir_cd *cdp, filldir_t func)
{
__be32 err;
int host_err;
@@ -1751,7 +1740,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
do {
cdp->err = nfserr_eof; /* will be cleared on successful read */
- host_err = vfs_readdir(file, (filldir_t) func, cdp);
+ host_err = vfs_readdir(file, func, cdp);
} while (host_err >=0 && cdp->err == nfs_ok);
if (host_err)
err = nfserrno(host_err);
@@ -1885,28 +1874,27 @@ nfsd_racache_init(int cache_size)
return 0;
if (cache_size < 2*RAPARM_HASH_SIZE)
cache_size = 2*RAPARM_HASH_SIZE;
- raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL);
-
- if (raparml != NULL) {
- dprintk("nfsd: allocating %d readahead buffers.\n",
- cache_size);
- for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
- raparm_hash[i].pb_head = NULL;
- spin_lock_init(&raparm_hash[i].pb_lock);
- }
- nperbucket = cache_size >> RAPARM_HASH_BITS;
- memset(raparml, 0, sizeof(struct raparms) * cache_size);
- for (i = 0; i < cache_size - 1; i++) {
- if (i % nperbucket == 0)
- raparm_hash[j++].pb_head = raparml + i;
- if (i % nperbucket < nperbucket-1)
- raparml[i].p_next = raparml + i + 1;
- }
- } else {
+ raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL);
+
+ if (!raparml) {
printk(KERN_WARNING
- "nfsd: Could not allocate memory read-ahead cache.\n");
+ "nfsd: Could not allocate memory read-ahead cache.\n");
return -ENOMEM;
}
+
+ dprintk("nfsd: allocating %d readahead buffers.\n", cache_size);
+ for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
+ raparm_hash[i].pb_head = NULL;
+ spin_lock_init(&raparm_hash[i].pb_lock);
+ }
+ nperbucket = cache_size >> RAPARM_HASH_BITS;
+ for (i = 0; i < cache_size - 1; i++) {
+ if (i % nperbucket == 0)
+ raparm_hash[j++].pb_head = raparml + i;
+ if (i % nperbucket < nperbucket-1)
+ raparml[i].p_next = raparml + i + 1;
+ }
+
nfsdstats.ra_size = cache_size;
return 0;
}
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 35cc4b1d60f..af4ef808fa9 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -17,6 +17,13 @@ ToDo/Notes:
happen is unclear however so it is worth waiting until someone hits
the problem.
+2.1.28 - Fix a deadlock.
+
+ - Fix deadlock in fs/ntfs/inode.c::ntfs_put_inode(). Thanks to Sergey
+ Vlasov for the report and detailed analysis of the deadlock. The fix
+ involved getting rid of ntfs_put_inode() altogether and hence NTFS no
+ longer has a ->put_inode super operation.
+
2.1.27 - Various bug fixes and cleanups.
- Fix two compiler warnings on Alpha. Thanks to Andrew Morton for
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index e27b4eacffb..82550838556 100644
--- a/fs/ntfs/Makefile
+++ b/fs/ntfs/Makefile
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
unistr.o upcase.o
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.27\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.28\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 7b2c8f4f6a6..629e7abdd84 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -92,10 +92,12 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
ofs = 0;
if (file_ofs < init_size)
ofs = init_size - file_ofs;
+ local_irq_save(flags);
kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
memset(kaddr + bh_offset(bh) + ofs, 0,
bh->b_size - ofs);
kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+ local_irq_restore(flags);
flush_dcache_page(page);
}
} else {
@@ -143,11 +145,13 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
recs = PAGE_CACHE_SIZE / rec_size;
/* Should have been verified before we got here... */
BUG_ON(!recs);
+ local_irq_save(flags);
kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
for (i = 0; i < recs; i++)
post_read_mst_fixup((NTFS_RECORD*)(kaddr +
i * rec_size), rec_size);
kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+ local_irq_restore(flags);
flush_dcache_page(page);
if (likely(page_uptodate && !PageError(page)))
SetPageUptodate(page);
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 85c36b8ca45..74f99a6a369 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1,7 +1,7 @@
/**
* dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project.
*
- * Copyright (c) 2001-2005 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
* Copyright (c) 2002 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
@@ -1101,7 +1101,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
s64 ia_pos, ia_start, prev_ia_pos, bmp_pos;
loff_t fpos, i_size;
- struct inode *bmp_vi, *vdir = filp->f_dentry->d_inode;
+ struct inode *bmp_vi, *vdir = filp->f_path.dentry->d_inode;
struct super_block *sb = vdir->i_sb;
ntfs_inode *ndir = NTFS_I(vdir);
ntfs_volume *vol = NTFS_SB(sb);
@@ -1136,9 +1136,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (fpos == 1) {
ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, "
"inode 0x%lx, DT_DIR.",
- (unsigned long)parent_ino(filp->f_dentry));
+ (unsigned long)parent_ino(filp->f_path.dentry));
rc = filldir(dirent, "..", 2, fpos,
- parent_ino(filp->f_dentry), DT_DIR);
+ parent_ino(filp->f_path.dentry), DT_DIR);
if (rc)
goto done;
fpos++;
@@ -1249,16 +1249,12 @@ skip_index_root:
/* Get the offset into the index allocation attribute. */
ia_pos = (s64)fpos - vol->mft_record_size;
ia_mapping = vdir->i_mapping;
- bmp_vi = ndir->itype.index.bmp_ino;
- if (unlikely(!bmp_vi)) {
- ntfs_debug("Inode 0x%lx, regetting index bitmap.", vdir->i_ino);
- bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
- if (IS_ERR(bmp_vi)) {
- ntfs_error(sb, "Failed to get bitmap attribute.");
- err = PTR_ERR(bmp_vi);
- goto err_out;
- }
- ndir->itype.index.bmp_ino = bmp_vi;
+ ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino);
+ bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
+ if (IS_ERR(bmp_vi)) {
+ ntfs_error(sb, "Failed to get bitmap attribute.");
+ err = PTR_ERR(bmp_vi);
+ goto err_out;
}
bmp_mapping = bmp_vi->i_mapping;
/* Get the starting bitmap bit position and sanity check it. */
@@ -1266,7 +1262,7 @@ skip_index_root:
if (unlikely(bmp_pos >> 3 >= i_size_read(bmp_vi))) {
ntfs_error(sb, "Current index allocation position exceeds "
"index bitmap size.");
- goto err_out;
+ goto iput_err_out;
}
/* Get the starting bit position in the current bitmap page. */
cur_bmp_pos = bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1);
@@ -1282,7 +1278,7 @@ get_next_bmp_page:
ntfs_error(sb, "Reading index bitmap failed.");
err = PTR_ERR(bmp_page);
bmp_page = NULL;
- goto err_out;
+ goto iput_err_out;
}
bmp = (u8*)page_address(bmp_page);
/* Find next index block in use. */
@@ -1429,6 +1425,7 @@ find_next_index_buffer:
/* @ia_page is already unlocked in this case. */
ntfs_unmap_page(ia_page);
ntfs_unmap_page(bmp_page);
+ iput(bmp_vi);
goto abort;
}
}
@@ -1439,6 +1436,7 @@ unm_EOD:
ntfs_unmap_page(ia_page);
}
ntfs_unmap_page(bmp_page);
+ iput(bmp_vi);
EOD:
/* We are finished, set fpos to EOD. */
fpos = i_size + vol->mft_record_size;
@@ -1455,8 +1453,11 @@ done:
filp->f_pos = fpos;
return 0;
err_out:
- if (bmp_page)
+ if (bmp_page) {
ntfs_unmap_page(bmp_page);
+iput_err_out:
+ iput(bmp_vi);
+ }
if (ia_page) {
unlock_page(ia_page);
ntfs_unmap_page(ia_page);
@@ -1529,14 +1530,22 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)
static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync)
{
- struct inode *vi = dentry->d_inode;
- ntfs_inode *ni = NTFS_I(vi);
+ struct inode *bmp_vi, *vi = dentry->d_inode;
int err, ret;
+ ntfs_attr na;
ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
BUG_ON(!S_ISDIR(vi->i_mode));
- if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino)
- write_inode_now(ni->itype.index.bmp_ino, !datasync);
+ /* If the bitmap attribute inode is in memory sync it, too. */
+ na.mft_no = vi->i_ino;
+ na.type = AT_BITMAP;
+ na.name = I30;
+ na.name_len = 4;
+ bmp_vi = ilookup5(vi->i_sb, vi->i_ino, (test_t)ntfs_test_inode, &na);
+ if (bmp_vi) {
+ write_inode_now(bmp_vi, !datasync);
+ iput(bmp_vi);
+ }
ret = ntfs_write_inode(vi, 1);
write_inode_now(vi, !datasync);
err = sync_blockdev(vi->i_sb->s_bdev);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index ae2fe0016d2..076c9420c25 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2162,7 +2162,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
goto out;
if (!count)
goto out;
- err = remove_suid(file->f_dentry);
+ err = remove_suid(file->f_path.dentry);
if (err)
goto out;
file_update_time(file);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 247989891b4..f8bf8da67ee 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1,7 +1,7 @@
/**
* inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
*
- * Copyright (c) 2001-2006 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -95,7 +95,7 @@ int ntfs_test_inode(struct inode *vi, ntfs_attr *na)
* If initializing the normal file/directory inode, set @na->type to AT_UNUSED.
* In that case, @na->name and @na->name_len should be set to NULL and 0,
* respectively. Although that is not strictly necessary as
- * ntfs_read_inode_locked() will fill them in later.
+ * ntfs_read_locked_inode() will fill them in later.
*
* Return 0 on success and -errno on error.
*
@@ -171,8 +171,8 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi,
struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no)
{
struct inode *vi;
- ntfs_attr na;
int err;
+ ntfs_attr na;
na.mft_no = mft_no;
na.type = AT_UNUSED;
@@ -229,8 +229,8 @@ struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPE type,
ntfschar *name, u32 name_len)
{
struct inode *vi;
- ntfs_attr na;
int err;
+ ntfs_attr na;
/* Make sure no one calls ntfs_attr_iget() for indices. */
BUG_ON(type == AT_INDEX_ALLOCATION);
@@ -287,8 +287,8 @@ struct inode *ntfs_index_iget(struct inode *base_vi, ntfschar *name,
u32 name_len)
{
struct inode *vi;
- ntfs_attr na;
int err;
+ ntfs_attr na;
na.mft_no = base_vi->i_ino;
na.type = AT_INDEX_ALLOCATION;
@@ -402,7 +402,6 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
ntfs_init_runlist(&ni->attr_list_rl);
lockdep_set_class(&ni->attr_list_rl.lock,
&attr_list_rl_lock_class);
- ni->itype.index.bmp_ino = NULL;
ni->itype.index.block_size = 0;
ni->itype.index.vcn_size = 0;
ni->itype.index.collation_rule = 0;
@@ -546,6 +545,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
{
ntfs_volume *vol = NTFS_SB(vi->i_sb);
ntfs_inode *ni;
+ struct inode *bvi;
MFT_RECORD *m;
ATTR_RECORD *a;
STANDARD_INFORMATION *si;
@@ -780,7 +780,6 @@ skip_attr_list_load:
*/
if (S_ISDIR(vi->i_mode)) {
loff_t bvi_size;
- struct inode *bvi;
ntfs_inode *bni;
INDEX_ROOT *ir;
u8 *ir_end, *index_end;
@@ -985,13 +984,12 @@ skip_attr_list_load:
err = PTR_ERR(bvi);
goto unm_err_out;
}
- ni->itype.index.bmp_ino = bvi;
bni = NTFS_I(bvi);
if (NInoCompressed(bni) || NInoEncrypted(bni) ||
NInoSparse(bni)) {
ntfs_error(vi->i_sb, "$BITMAP attribute is compressed "
"and/or encrypted and/or sparse.");
- goto unm_err_out;
+ goto iput_unm_err_out;
}
/* Consistency check bitmap size vs. index allocation size. */
bvi_size = i_size_read(bvi);
@@ -1000,8 +998,10 @@ skip_attr_list_load:
ntfs_error(vi->i_sb, "Index bitmap too small (0x%llx) "
"for index allocation (0x%llx).",
bvi_size << 3, vi->i_size);
- goto unm_err_out;
+ goto iput_unm_err_out;
}
+ /* No longer need the bitmap attribute inode. */
+ iput(bvi);
skip_large_dir_stuff:
/* Setup the operations for this inode. */
vi->i_op = &ntfs_dir_inode_ops;
@@ -1176,7 +1176,8 @@ no_data_attr_special_case:
vi->i_blocks = ni->allocated_size >> 9;
ntfs_debug("Done.");
return 0;
-
+iput_unm_err_out:
+ iput(bvi);
unm_err_out:
if (!err)
err = -EIO;
@@ -1697,7 +1698,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
vi->i_size);
goto iput_unm_err_out;
}
- ni->itype.index.bmp_ino = bvi;
+ iput(bvi);
skip_large_index_stuff:
/* Setup the operations for this index inode. */
vi->i_op = NULL;
@@ -1714,7 +1715,6 @@ skip_large_index_stuff:
ntfs_debug("Done.");
return 0;
-
iput_unm_err_out:
iput(bvi);
unm_err_out:
@@ -2191,37 +2191,6 @@ err_out:
return -1;
}
-/**
- * ntfs_put_inode - handler for when the inode reference count is decremented
- * @vi: vfs inode
- *
- * The VFS calls ntfs_put_inode() every time the inode reference count (i_count)
- * is about to be decremented (but before the decrement itself.
- *
- * If the inode @vi is a directory with two references, one of which is being
- * dropped, we need to put the attribute inode for the directory index bitmap,
- * if it is present, otherwise the directory inode would remain pinned for
- * ever.
- */
-void ntfs_put_inode(struct inode *vi)
-{
- if (S_ISDIR(vi->i_mode) && atomic_read(&vi->i_count) == 2) {
- ntfs_inode *ni = NTFS_I(vi);
- if (NInoIndexAllocPresent(ni)) {
- struct inode *bvi = NULL;
- mutex_lock(&vi->i_mutex);
- if (atomic_read(&vi->i_count) == 2) {
- bvi = ni->itype.index.bmp_ino;
- if (bvi)
- ni->itype.index.bmp_ino = NULL;
- }
- mutex_unlock(&vi->i_mutex);
- if (bvi)
- iput(bvi);
- }
- }
-}
-
static void __ntfs_clear_inode(ntfs_inode *ni)
{
/* Free all alocated memory. */
@@ -2287,18 +2256,6 @@ void ntfs_clear_big_inode(struct inode *vi)
{
ntfs_inode *ni = NTFS_I(vi);
- /*
- * If the inode @vi is an index inode we need to put the attribute
- * inode for the index bitmap, if it is present, otherwise the index
- * inode would disappear and the attribute inode for the index bitmap
- * would no longer be referenced from anywhere and thus it would remain
- * pinned for ever.
- */
- if (NInoAttr(ni) && (ni->type == AT_INDEX_ALLOCATION) &&
- NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino) {
- iput(ni->itype.index.bmp_ino);
- ni->itype.index.bmp_ino = NULL;
- }
#ifdef NTFS_RW
if (NInoDirty(ni)) {
bool was_bad = (is_bad_inode(vi));
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index f088291e017..117eaf8032a 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -2,7 +2,7 @@
* inode.h - Defines for inode structures NTFS Linux kernel driver. Part of
* the Linux-NTFS project.
*
- * Copyright (c) 2001-2005 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
* Copyright (c) 2002 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
@@ -101,8 +101,6 @@ struct _ntfs_inode {
runlist attr_list_rl; /* Run list for the attribute list value. */
union {
struct { /* It is a directory, $MFT, or an index inode. */
- struct inode *bmp_ino; /* Attribute inode for the
- index $BITMAP. */
u32 block_size; /* Size of an index block. */
u32 vcn_size; /* Size of a vcn in this
index. */
@@ -300,8 +298,6 @@ extern void ntfs_clear_extent_inode(ntfs_inode *ni);
extern int ntfs_read_inode_mount(struct inode *vi);
-extern void ntfs_put_inode(struct inode *vi);
-
extern int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt);
#ifdef NTFS_RW
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 03a391ac714..babf94d90de 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -1,7 +1,7 @@
/*
* super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
*
- * Copyright (c) 2001-2006 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
* Copyright (c) 2001,2002 Richard Russon
*
* This program/include file is free software; you can redistribute it and/or
@@ -2702,9 +2702,6 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
static struct super_operations ntfs_sops = {
.alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */
.destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */
- .put_inode = ntfs_put_inode, /* VFS: Called just before
- the inode reference count
- is decreased. */
#ifdef NTFS_RW
//.dirty_inode = NULL, /* VFS: Called from
// __mark_inode_dirty(). */
@@ -3261,7 +3258,7 @@ static void __exit exit_ntfs_fs(void)
}
MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>");
-MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2006 Anton Altaparmakov");
+MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2007 Anton Altaparmakov");
MODULE_VERSION(NTFS_VERSION);
MODULE_LICENSE("GPL");
#ifdef DEBUG
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index edc91ca3792..f27e5378caf 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1959,7 +1959,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
goto bail;
}
- *tc = kcalloc(1, sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
+ *tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
if (!(*tc)) {
status = -ENOMEM;
mlog_errno(status);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 2f7268e8152..93628b02ef5 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -540,8 +540,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
int ret;
- u64 vbo_max; /* file offset, max_blocks from iblock */
- u64 p_blkno;
+ u64 p_blkno, inode_blocks;
int contig_blocks;
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
@@ -550,12 +549,23 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
* nicely aligned and of the right size, so there's no need
* for us to check any of that. */
- vbo_max = ((u64)iblock + max_blocks) << blocksize_bits;
-
spin_lock(&OCFS2_I(inode)->ip_lock);
- if ((iblock + max_blocks) >
- ocfs2_clusters_to_blocks(inode->i_sb,
- OCFS2_I(inode)->ip_clusters)) {
+ inode_blocks = ocfs2_clusters_to_blocks(inode->i_sb,
+ OCFS2_I(inode)->ip_clusters);
+
+ /*
+ * For a read which begins past the end of file, we return a hole.
+ */
+ if (!create && (iblock >= inode_blocks)) {
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ ret = 0;
+ goto bail;
+ }
+
+ /*
+ * Any write past EOF is not allowed because we'd be extending.
+ */
+ if (create && (iblock + max_blocks) > inode_blocks) {
spin_unlock(&OCFS2_I(inode)->ip_lock);
ret = -EIO;
goto bail;
@@ -595,7 +605,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
ssize_t bytes,
void *private)
{
- struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+ struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
/* this io's submitter should not have unlocked this before we could */
BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
@@ -611,7 +621,7 @@ static ssize_t ocfs2_direct_IO(int rw,
unsigned long nr_segs)
{
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+ struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
int ret;
mlog_entry_void();
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 4cd9a958045..277ca67a2ad 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -1447,6 +1447,15 @@ out:
return ret;
}
+static ssize_t o2hb_region_pid_read(struct o2hb_region *reg,
+ char *page)
+{
+ if (!reg->hr_task)
+ return 0;
+
+ return sprintf(page, "%u\n", reg->hr_task->pid);
+}
+
struct o2hb_region_attribute {
struct configfs_attribute attr;
ssize_t (*show)(struct o2hb_region *, char *);
@@ -1485,11 +1494,19 @@ static struct o2hb_region_attribute o2hb_region_attr_dev = {
.store = o2hb_region_dev_write,
};
+static struct o2hb_region_attribute o2hb_region_attr_pid = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "pid",
+ .ca_mode = S_IRUGO | S_IRUSR },
+ .show = o2hb_region_pid_read,
+};
+
static struct configfs_attribute *o2hb_region_attrs[] = {
&o2hb_region_attr_block_bytes.attr,
&o2hb_region_attr_start_block.attr,
&o2hb_region_attr_blocks.attr,
&o2hb_region_attr_dev.attr,
+ &o2hb_region_attr_pid.attr,
NULL,
};
@@ -1553,7 +1570,7 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
struct o2hb_region *reg = NULL;
struct config_item *ret = NULL;
- reg = kcalloc(1, sizeof(struct o2hb_region), GFP_KERNEL);
+ reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL);
if (reg == NULL)
goto out; /* ENOMEM */
@@ -1679,7 +1696,7 @@ struct config_group *o2hb_alloc_hb_set(void)
struct o2hb_heartbeat_group *hs = NULL;
struct config_group *ret = NULL;
- hs = kcalloc(1, sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
+ hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
if (hs == NULL)
goto out;
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
index d11753c50bc..b17333a0606 100644
--- a/fs/ocfs2/cluster/nodemanager.c
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -35,7 +35,7 @@
/* for now we operate under the assertion that there can be only one
* cluster active at a time. Changing this will require trickling
* cluster references throughout where nodes are looked up */
-static struct o2nm_cluster *o2nm_single_cluster = NULL;
+struct o2nm_cluster *o2nm_single_cluster = NULL;
#define OCFS2_MAX_HB_CTL_PATH 256
static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";
@@ -97,17 +97,6 @@ const char *o2nm_get_hb_ctl_path(void)
}
EXPORT_SYMBOL_GPL(o2nm_get_hb_ctl_path);
-struct o2nm_cluster {
- struct config_group cl_group;
- unsigned cl_has_local:1;
- u8 cl_local_node;
- rwlock_t cl_nodes_lock;
- struct o2nm_node *cl_nodes[O2NM_MAX_NODES];
- struct rb_root cl_node_ip_tree;
- /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */
- unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
-};
-
struct o2nm_node *o2nm_get_node_by_num(u8 node_num)
{
struct o2nm_node *node = NULL;
@@ -543,6 +532,179 @@ static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
}
#endif
+struct o2nm_cluster_attribute {
+ struct configfs_attribute attr;
+ ssize_t (*show)(struct o2nm_cluster *, char *);
+ ssize_t (*store)(struct o2nm_cluster *, const char *, size_t);
+};
+
+static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
+ unsigned int *val)
+{
+ unsigned long tmp;
+ char *p = (char *)page;
+
+ tmp = simple_strtoul(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ if (tmp == 0)
+ return -EINVAL;
+ if (tmp >= (u32)-1)
+ return -ERANGE;
+
+ *val = tmp;
+
+ return count;
+}
+
+static ssize_t o2nm_cluster_attr_idle_timeout_ms_read(
+ struct o2nm_cluster *cluster, char *page)
+{
+ return sprintf(page, "%u\n", cluster->cl_idle_timeout_ms);
+}
+
+static ssize_t o2nm_cluster_attr_idle_timeout_ms_write(
+ struct o2nm_cluster *cluster, const char *page, size_t count)
+{
+ ssize_t ret;
+ unsigned int val;
+
+ ret = o2nm_cluster_attr_write(page, count, &val);
+
+ if (ret > 0) {
+ if (cluster->cl_idle_timeout_ms != val
+ && o2net_num_connected_peers()) {
+ mlog(ML_NOTICE,
+ "o2net: cannot change idle timeout after "
+ "the first peer has agreed to it."
+ " %d connected peers\n",
+ o2net_num_connected_peers());
+ ret = -EINVAL;
+ } else if (val <= cluster->cl_keepalive_delay_ms) {
+ mlog(ML_NOTICE, "o2net: idle timeout must be larger "
+ "than keepalive delay\n");
+ ret = -EINVAL;
+ } else {
+ cluster->cl_idle_timeout_ms = val;
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t o2nm_cluster_attr_keepalive_delay_ms_read(
+ struct o2nm_cluster *cluster, char *page)
+{
+ return sprintf(page, "%u\n", cluster->cl_keepalive_delay_ms);
+}
+
+static ssize_t o2nm_cluster_attr_keepalive_delay_ms_write(
+ struct o2nm_cluster *cluster, const char *page, size_t count)
+{
+ ssize_t ret;
+ unsigned int val;
+
+ ret = o2nm_cluster_attr_write(page, count, &val);
+
+ if (ret > 0) {
+ if (cluster->cl_keepalive_delay_ms != val
+ && o2net_num_connected_peers()) {
+ mlog(ML_NOTICE,
+ "o2net: cannot change keepalive delay after"
+ " the first peer has agreed to it."
+ " %d connected peers\n",
+ o2net_num_connected_peers());
+ ret = -EINVAL;
+ } else if (val >= cluster->cl_idle_timeout_ms) {
+ mlog(ML_NOTICE, "o2net: keepalive delay must be "
+ "smaller than idle timeout\n");
+ ret = -EINVAL;
+ } else {
+ cluster->cl_keepalive_delay_ms = val;
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t o2nm_cluster_attr_reconnect_delay_ms_read(
+ struct o2nm_cluster *cluster, char *page)
+{
+ return sprintf(page, "%u\n", cluster->cl_reconnect_delay_ms);
+}
+
+static ssize_t o2nm_cluster_attr_reconnect_delay_ms_write(
+ struct o2nm_cluster *cluster, const char *page, size_t count)
+{
+ return o2nm_cluster_attr_write(page, count,
+ &cluster->cl_reconnect_delay_ms);
+}
+static struct o2nm_cluster_attribute o2nm_cluster_attr_idle_timeout_ms = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "idle_timeout_ms",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_cluster_attr_idle_timeout_ms_read,
+ .store = o2nm_cluster_attr_idle_timeout_ms_write,
+};
+
+static struct o2nm_cluster_attribute o2nm_cluster_attr_keepalive_delay_ms = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "keepalive_delay_ms",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_cluster_attr_keepalive_delay_ms_read,
+ .store = o2nm_cluster_attr_keepalive_delay_ms_write,
+};
+
+static struct o2nm_cluster_attribute o2nm_cluster_attr_reconnect_delay_ms = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "reconnect_delay_ms",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_cluster_attr_reconnect_delay_ms_read,
+ .store = o2nm_cluster_attr_reconnect_delay_ms_write,
+};
+
+static struct configfs_attribute *o2nm_cluster_attrs[] = {
+ &o2nm_cluster_attr_idle_timeout_ms.attr,
+ &o2nm_cluster_attr_keepalive_delay_ms.attr,
+ &o2nm_cluster_attr_reconnect_delay_ms.attr,
+ NULL,
+};
+static ssize_t o2nm_cluster_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster(item);
+ struct o2nm_cluster_attribute *o2nm_cluster_attr =
+ container_of(attr, struct o2nm_cluster_attribute, attr);
+ ssize_t ret = 0;
+
+ if (o2nm_cluster_attr->show)
+ ret = o2nm_cluster_attr->show(cluster, page);
+ return ret;
+}
+
+static ssize_t o2nm_cluster_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster(item);
+ struct o2nm_cluster_attribute *o2nm_cluster_attr =
+ container_of(attr, struct o2nm_cluster_attribute, attr);
+ ssize_t ret;
+
+ if (o2nm_cluster_attr->store == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = o2nm_cluster_attr->store(cluster, page, count);
+ if (ret < count)
+ goto out;
+out:
+ return ret;
+}
+
static struct config_item *o2nm_node_group_make_item(struct config_group *group,
const char *name)
{
@@ -552,7 +714,7 @@ static struct config_item *o2nm_node_group_make_item(struct config_group *group,
if (strlen(name) > O2NM_MAX_NAME_LEN)
goto out; /* ENAMETOOLONG */
- node = kcalloc(1, sizeof(struct o2nm_node), GFP_KERNEL);
+ node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL);
if (node == NULL)
goto out; /* ENOMEM */
@@ -624,10 +786,13 @@ static void o2nm_cluster_release(struct config_item *item)
static struct configfs_item_operations o2nm_cluster_item_ops = {
.release = o2nm_cluster_release,
+ .show_attribute = o2nm_cluster_show,
+ .store_attribute = o2nm_cluster_store,
};
static struct config_item_type o2nm_cluster_type = {
.ct_item_ops = &o2nm_cluster_item_ops,
+ .ct_attrs = o2nm_cluster_attrs,
.ct_owner = THIS_MODULE,
};
@@ -660,8 +825,8 @@ static struct config_group *o2nm_cluster_group_make_group(struct config_group *g
if (o2nm_single_cluster)
goto out; /* ENOSPC */
- cluster = kcalloc(1, sizeof(struct o2nm_cluster), GFP_KERNEL);
- ns = kcalloc(1, sizeof(struct o2nm_node_group), GFP_KERNEL);
+ cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL);
+ ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL);
defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
o2hb_group = o2hb_alloc_hb_set();
if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL)
@@ -678,6 +843,9 @@ static struct config_group *o2nm_cluster_group_make_group(struct config_group *g
cluster->cl_group.default_groups[2] = NULL;
rwlock_init(&cluster->cl_nodes_lock);
cluster->cl_node_ip_tree = RB_ROOT;
+ cluster->cl_reconnect_delay_ms = O2NET_RECONNECT_DELAY_MS_DEFAULT;
+ cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT;
+ cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT;
ret = &cluster->cl_group;
o2nm_single_cluster = cluster;
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
index fce8033c310..8fb23cacc2f 100644
--- a/fs/ocfs2/cluster/nodemanager.h
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -53,6 +53,23 @@ struct o2nm_node {
unsigned long nd_set_attributes;
};
+struct o2nm_cluster {
+ struct config_group cl_group;
+ unsigned cl_has_local:1;
+ u8 cl_local_node;
+ rwlock_t cl_nodes_lock;
+ struct o2nm_node *cl_nodes[O2NM_MAX_NODES];
+ struct rb_root cl_node_ip_tree;
+ unsigned int cl_idle_timeout_ms;
+ unsigned int cl_keepalive_delay_ms;
+ unsigned int cl_reconnect_delay_ms;
+
+ /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */
+ unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+};
+
+extern struct o2nm_cluster *o2nm_single_cluster;
+
u8 o2nm_this_node(void);
int o2nm_configured_node_map(unsigned long *map, unsigned bytes);
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 9b3209dc0b1..ae4ff4a6636 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -147,6 +147,28 @@ static void o2net_listen_data_ready(struct sock *sk, int bytes);
static void o2net_sc_send_keep_req(struct work_struct *work);
static void o2net_idle_timer(unsigned long data);
static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
+static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc);
+
+/*
+ * FIXME: These should use to_o2nm_cluster_from_node(), but we end up
+ * losing our parent link to the cluster during shutdown. This can be
+ * solved by adding a pre-removal callback to configfs, or passing
+ * around the cluster with the node. -jeffm
+ */
+static inline int o2net_reconnect_delay(struct o2nm_node *node)
+{
+ return o2nm_single_cluster->cl_reconnect_delay_ms;
+}
+
+static inline int o2net_keepalive_delay(struct o2nm_node *node)
+{
+ return o2nm_single_cluster->cl_keepalive_delay_ms;
+}
+
+static inline int o2net_idle_timeout(struct o2nm_node *node)
+{
+ return o2nm_single_cluster->cl_idle_timeout_ms;
+}
static inline int o2net_sys_err_to_errno(enum o2net_system_error err)
{
@@ -271,6 +293,8 @@ static void sc_kref_release(struct kref *kref)
{
struct o2net_sock_container *sc = container_of(kref,
struct o2net_sock_container, sc_kref);
+ BUG_ON(timer_pending(&sc->sc_idle_timeout));
+
sclog(sc, "releasing\n");
if (sc->sc_sock) {
@@ -300,7 +324,7 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node)
struct page *page = NULL;
page = alloc_page(GFP_NOFS);
- sc = kcalloc(1, sizeof(*sc), GFP_NOFS);
+ sc = kzalloc(sizeof(*sc), GFP_NOFS);
if (sc == NULL || page == NULL)
goto out;
@@ -356,6 +380,13 @@ static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc,
sc_put(sc);
}
+static atomic_t o2net_connected_peers = ATOMIC_INIT(0);
+
+int o2net_num_connected_peers(void)
+{
+ return atomic_read(&o2net_connected_peers);
+}
+
static void o2net_set_nn_state(struct o2net_node *nn,
struct o2net_sock_container *sc,
unsigned valid, int err)
@@ -366,6 +397,11 @@ static void o2net_set_nn_state(struct o2net_node *nn,
assert_spin_locked(&nn->nn_lock);
+ if (old_sc && !sc)
+ atomic_dec(&o2net_connected_peers);
+ else if (!old_sc && sc)
+ atomic_inc(&o2net_connected_peers);
+
/* the node num comparison and single connect/accept path should stop
* an non-null sc from being overwritten with another */
BUG_ON(sc && nn->nn_sc && nn->nn_sc != sc);
@@ -424,9 +460,9 @@ static void o2net_set_nn_state(struct o2net_node *nn,
/* delay if we're withing a RECONNECT_DELAY of the
* last attempt */
delay = (nn->nn_last_connect_attempt +
- msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS))
+ msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
- jiffies;
- if (delay > msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS))
+ if (delay > msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
delay = 0;
mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
@@ -678,7 +714,7 @@ int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
goto out;
}
- nmh = kcalloc(1, sizeof(struct o2net_msg_handler), GFP_NOFS);
+ nmh = kzalloc(sizeof(struct o2net_msg_handler), GFP_NOFS);
if (nmh == NULL) {
ret = -ENOMEM;
goto out;
@@ -1099,13 +1135,51 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
return -1;
}
+ /*
+ * Ensure timeouts are consistent with other nodes, otherwise
+ * we can end up with one node thinking that the other must be down,
+ * but isn't. This can ultimately cause corruption.
+ */
+ if (be32_to_cpu(hand->o2net_idle_timeout_ms) !=
+ o2net_idle_timeout(sc->sc_node)) {
+ mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of "
+ "%u ms, but we use %u ms locally. disconnecting\n",
+ SC_NODEF_ARGS(sc),
+ be32_to_cpu(hand->o2net_idle_timeout_ms),
+ o2net_idle_timeout(sc->sc_node));
+ o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ return -1;
+ }
+
+ if (be32_to_cpu(hand->o2net_keepalive_delay_ms) !=
+ o2net_keepalive_delay(sc->sc_node)) {
+ mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of "
+ "%u ms, but we use %u ms locally. disconnecting\n",
+ SC_NODEF_ARGS(sc),
+ be32_to_cpu(hand->o2net_keepalive_delay_ms),
+ o2net_keepalive_delay(sc->sc_node));
+ o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ return -1;
+ }
+
+ if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) !=
+ O2HB_MAX_WRITE_TIMEOUT_MS) {
+ mlog(ML_NOTICE, SC_NODEF_FMT " uses a heartbeat timeout of "
+ "%u ms, but we use %u ms locally. disconnecting\n",
+ SC_NODEF_ARGS(sc),
+ be32_to_cpu(hand->o2hb_heartbeat_timeout_ms),
+ O2HB_MAX_WRITE_TIMEOUT_MS);
+ o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ return -1;
+ }
+
sc->sc_handshake_ok = 1;
spin_lock(&nn->nn_lock);
/* set valid and queue the idle timers only if it hasn't been
* shut down already */
if (nn->nn_sc == sc) {
- o2net_sc_postpone_idle(sc);
+ o2net_sc_reset_idle_timer(sc);
o2net_set_nn_state(nn, sc, 1, 0);
}
spin_unlock(&nn->nn_lock);
@@ -1131,6 +1205,23 @@ static int o2net_advance_rx(struct o2net_sock_container *sc)
sclog(sc, "receiving\n");
do_gettimeofday(&sc->sc_tv_advance_start);
+ if (unlikely(sc->sc_handshake_ok == 0)) {
+ if(sc->sc_page_off < sizeof(struct o2net_handshake)) {
+ data = page_address(sc->sc_page) + sc->sc_page_off;
+ datalen = sizeof(struct o2net_handshake) - sc->sc_page_off;
+ ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen);
+ if (ret > 0)
+ sc->sc_page_off += ret;
+ }
+
+ if (sc->sc_page_off == sizeof(struct o2net_handshake)) {
+ o2net_check_handshake(sc);
+ if (unlikely(sc->sc_handshake_ok == 0))
+ ret = -EPROTO;
+ }
+ goto out;
+ }
+
/* do we need more header? */
if (sc->sc_page_off < sizeof(struct o2net_msg)) {
data = page_address(sc->sc_page) + sc->sc_page_off;
@@ -1138,15 +1229,6 @@ static int o2net_advance_rx(struct o2net_sock_container *sc)
ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen);
if (ret > 0) {
sc->sc_page_off += ret;
-
- /* this working relies on the handshake being
- * smaller than the normal message header */
- if (sc->sc_page_off >= sizeof(struct o2net_handshake)&&
- !sc->sc_handshake_ok && o2net_check_handshake(sc)) {
- ret = -EPROTO;
- goto out;
- }
-
/* only swab incoming here.. we can
* only get here once as we cross from
* being under to over */
@@ -1248,6 +1330,18 @@ static int o2net_set_nodelay(struct socket *sock)
return ret;
}
+static void o2net_initialize_handshake(void)
+{
+ o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32(
+ O2HB_MAX_WRITE_TIMEOUT_MS);
+ o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(
+ o2net_idle_timeout(NULL));
+ o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32(
+ o2net_keepalive_delay(NULL));
+ o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32(
+ o2net_reconnect_delay(NULL));
+}
+
/* ------------------------------------------------------------ */
/* called when a connect completes and after a sock is accepted. the
@@ -1262,6 +1356,7 @@ static void o2net_sc_connect_completed(struct work_struct *work)
(unsigned long long)O2NET_PROTOCOL_VERSION,
(unsigned long long)be64_to_cpu(o2net_hand->connector_id));
+ o2net_initialize_handshake();
o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand));
sc_put(sc);
}
@@ -1287,8 +1382,10 @@ static void o2net_idle_timer(unsigned long data)
do_gettimeofday(&now);
- printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for 10 "
- "seconds, shutting it down.\n", SC_NODEF_ARGS(sc));
+ printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
+ "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
+ o2net_idle_timeout(sc->sc_node) / 1000,
+ o2net_idle_timeout(sc->sc_node) % 1000);
mlog(ML_NOTICE, "here are some times that might help debug the "
"situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
"%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
@@ -1306,14 +1403,21 @@ static void o2net_idle_timer(unsigned long data)
o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
}
-static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)
{
o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work,
- O2NET_KEEPALIVE_DELAY_SECS * HZ);
+ msecs_to_jiffies(o2net_keepalive_delay(sc->sc_node)));
do_gettimeofday(&sc->sc_tv_timer);
mod_timer(&sc->sc_idle_timeout,
- jiffies + (O2NET_IDLE_TIMEOUT_SECS * HZ));
+ jiffies + msecs_to_jiffies(o2net_idle_timeout(sc->sc_node)));
+}
+
+static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+{
+ /* Only push out an existing timer */
+ if (timer_pending(&sc->sc_idle_timeout))
+ o2net_sc_reset_idle_timer(sc);
}
/* this work func is kicked whenever a path sets the nn state which doesn't
@@ -1435,9 +1539,12 @@ static void o2net_connect_expired(struct work_struct *work)
spin_lock(&nn->nn_lock);
if (!nn->nn_sc_valid) {
+ struct o2nm_node *node = nn->nn_sc->sc_node;
mlog(ML_ERROR, "no connection established with node %u after "
- "%u seconds, giving up and returning errors.\n",
- o2net_num_from_nn(nn), O2NET_IDLE_TIMEOUT_SECS);
+ "%u.%u seconds, giving up and returning errors.\n",
+ o2net_num_from_nn(nn),
+ o2net_idle_timeout(node) / 1000,
+ o2net_idle_timeout(node) % 1000);
o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
}
@@ -1478,6 +1585,8 @@ static void o2net_hb_node_down_cb(struct o2nm_node *node, int node_num,
if (node_num != o2nm_this_node())
o2net_disconnect_node(node);
+
+ BUG_ON(atomic_read(&o2net_connected_peers) < 0);
}
static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
@@ -1489,14 +1598,14 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
/* ensure an immediate connect attempt */
nn->nn_last_connect_attempt = jiffies -
- (msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS) + 1);
+ (msecs_to_jiffies(o2net_reconnect_delay(node)) + 1);
if (node_num != o2nm_this_node()) {
/* heartbeat doesn't work unless a local node number is
* configured and doing so brings up the o2net_wq, so we can
* use it.. */
queue_delayed_work(o2net_wq, &nn->nn_connect_expired,
- O2NET_IDLE_TIMEOUT_SECS * HZ);
+ msecs_to_jiffies(o2net_idle_timeout(node)));
/* believe it or not, accept and node hearbeating testing
* can succeed for this node before we got here.. so
@@ -1641,6 +1750,7 @@ static int o2net_accept_one(struct socket *sock)
o2net_register_callbacks(sc->sc_sock->sk, sc);
o2net_sc_queue_work(sc, &sc->sc_rx_work);
+ o2net_initialize_handshake();
o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand));
out:
@@ -1808,9 +1918,9 @@ int o2net_init(void)
o2quo_init();
- o2net_hand = kcalloc(1, sizeof(struct o2net_handshake), GFP_KERNEL);
- o2net_keep_req = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
- o2net_keep_resp = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
+ o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL);
+ o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+ o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
if (!o2net_hand || !o2net_keep_req || !o2net_keep_resp) {
kfree(o2net_hand);
kfree(o2net_keep_req);
diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h
index 616ff2b8434..21a4e43df83 100644
--- a/fs/ocfs2/cluster/tcp.h
+++ b/fs/ocfs2/cluster/tcp.h
@@ -54,6 +54,13 @@ typedef int (o2net_msg_handler_func)(struct o2net_msg *msg, u32 len, void *data)
#define O2NET_MAX_PAYLOAD_BYTES (4096 - sizeof(struct o2net_msg))
+/* same as hb delay, we're waiting for another node to recognize our hb */
+#define O2NET_RECONNECT_DELAY_MS_DEFAULT 2000
+
+#define O2NET_KEEPALIVE_DELAY_MS_DEFAULT 5000
+#define O2NET_IDLE_TIMEOUT_MS_DEFAULT 10000
+
+
/* TODO: figure this out.... */
static inline int o2net_link_down(int err, struct socket *sock)
{
@@ -101,6 +108,7 @@ void o2net_unregister_hb_callbacks(void);
int o2net_start_listening(struct o2nm_node *node);
void o2net_stop_listening(struct o2nm_node *node);
void o2net_disconnect_node(struct o2nm_node *node);
+int o2net_num_connected_peers(void);
int o2net_init(void);
void o2net_exit(void);
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h
index daebbd3a2c8..b700dc9624d 100644
--- a/fs/ocfs2/cluster/tcp_internal.h
+++ b/fs/ocfs2/cluster/tcp_internal.h
@@ -27,23 +27,20 @@
#define O2NET_MSG_KEEP_REQ_MAGIC ((u16)0xfa57)
#define O2NET_MSG_KEEP_RESP_MAGIC ((u16)0xfa58)
-/* same as hb delay, we're waiting for another node to recognize our hb */
-#define O2NET_RECONNECT_DELAY_MS O2HB_REGION_TIMEOUT_MS
-
/* we're delaying our quorum decision so that heartbeat will have timed
* out truly dead nodes by the time we come around to making decisions
* on their number */
#define O2NET_QUORUM_DELAY_MS ((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS)
-#define O2NET_KEEPALIVE_DELAY_SECS 5
-#define O2NET_IDLE_TIMEOUT_SECS 10
-
/*
* This version number represents quite a lot, unfortunately. It not
* only represents the raw network message protocol on the wire but also
* locking semantics of the file system using the protocol. It should
* be somewhere else, I'm sure, but right now it isn't.
*
+ * New in version 5:
+ * - Network timeout checking protocol
+ *
* New in version 4:
* - Remove i_generation from lock names for better stat performance.
*
@@ -54,10 +51,14 @@
* - full 64 bit i_size in the metadata lock lvbs
* - introduction of "rw" lock and pushing meta/data locking down
*/
-#define O2NET_PROTOCOL_VERSION 4ULL
+#define O2NET_PROTOCOL_VERSION 5ULL
struct o2net_handshake {
__be64 protocol_version;
__be64 connector_id;
+ __be32 o2hb_heartbeat_timeout_ms;
+ __be32 o2net_idle_timeout_ms;
+ __be32 o2net_keepalive_delay_ms;
+ __be32 o2net_reconnect_delay_ms;
};
struct o2net_node {
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index baad2aa27c1..66821e17816 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -79,7 +79,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
struct buffer_head * bh, * tmp;
struct ocfs2_dir_entry * de;
int err;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block * sb = inode->i_sb;
unsigned int ra_sectors = 16;
int lock_level = 0;
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 420a375a394..f0b25f2dd20 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -920,7 +920,7 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
mlog_entry("%p", dlm);
- ctxt = kcalloc(1, sizeof(*ctxt), GFP_KERNEL);
+ ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
if (!ctxt) {
status = -ENOMEM;
mlog_errno(status);
@@ -1223,7 +1223,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
int i;
struct dlm_ctxt *dlm = NULL;
- dlm = kcalloc(1, sizeof(*dlm), GFP_KERNEL);
+ dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
if (!dlm) {
mlog_errno(-ENOMEM);
goto leave;
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 941acf14e61..b7f0ba97a1a 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -176,7 +176,7 @@ static ssize_t dlmfs_file_read(struct file *filp,
int bytes_left;
ssize_t readlen;
char *lvb_buf;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
inode->i_ino, count, *ppos);
@@ -220,7 +220,7 @@ static ssize_t dlmfs_file_write(struct file *filp,
int bytes_left;
ssize_t writelen;
char *lvb_buf;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
inode->i_ino, count, *ppos);
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 42a1b91979b..e5ca3db197f 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -408,13 +408,13 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
struct dlm_lock *lock;
int kernel_allocated = 0;
- lock = kcalloc(1, sizeof(*lock), GFP_NOFS);
+ lock = kzalloc(sizeof(*lock), GFP_NOFS);
if (!lock)
return NULL;
if (!lksb) {
/* zero memory only if kernel-allocated */
- lksb = kcalloc(1, sizeof(*lksb), GFP_NOFS);
+ lksb = kzalloc(sizeof(*lksb), GFP_NOFS);
if (!lksb) {
kfree(lock);
return NULL;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 856012b4fa4..0ad872055cb 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1939,7 +1939,7 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
int ignore_higher, u8 request_from, u32 flags)
{
struct dlm_work_item *item;
- item = kcalloc(1, sizeof(*item), GFP_NOFS);
+ item = kzalloc(sizeof(*item), GFP_NOFS);
if (!item)
return -ENOMEM;
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index fb3e2b0817f..367a11e9e2e 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -757,7 +757,7 @@ static int dlm_init_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
}
BUG_ON(num == dead_node);
- ndata = kcalloc(1, sizeof(*ndata), GFP_NOFS);
+ ndata = kzalloc(sizeof(*ndata), GFP_NOFS);
if (!ndata) {
dlm_destroy_recovery_area(dlm, dead_node);
return -ENOMEM;
@@ -842,7 +842,7 @@ int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data)
}
BUG_ON(lr->dead_node != dlm->reco.dead_node);
- item = kcalloc(1, sizeof(*item), GFP_NOFS);
+ item = kzalloc(sizeof(*item), GFP_NOFS);
if (!item) {
dlm_put(dlm);
return -ENOMEM;
@@ -1323,7 +1323,7 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data)
ret = -ENOMEM;
buf = kmalloc(be16_to_cpu(msg->data_len), GFP_NOFS);
- item = kcalloc(1, sizeof(*item), GFP_NOFS);
+ item = kzalloc(sizeof(*item), GFP_NOFS);
if (!buf || !item)
goto leave;
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 69fba16efbd..e335541727f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -770,7 +770,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
int dlm_flags)
{
int ret = 0;
- enum dlm_status status;
+ enum dlm_status status = DLM_NORMAL;
unsigned long flags;
mlog_entry_void();
@@ -1138,6 +1138,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
{
int status, level;
struct ocfs2_lock_res *lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
BUG_ON(!inode);
@@ -1147,6 +1148,9 @@ int ocfs2_rw_lock(struct inode *inode, int write)
(unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
+ if (ocfs2_mount_local(osb))
+ return 0;
+
lockres = &OCFS2_I(inode)->ip_rw_lockres;
level = write ? LKM_EXMODE : LKM_PRMODE;
@@ -1164,6 +1168,7 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
{
int level = write ? LKM_EXMODE : LKM_PRMODE;
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry_void();
@@ -1171,7 +1176,8 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
(unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
- ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
+ if (!ocfs2_mount_local(osb))
+ ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
mlog_exit_void();
}
@@ -1182,6 +1188,7 @@ int ocfs2_data_lock_full(struct inode *inode,
{
int status = 0, level;
struct ocfs2_lock_res *lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
BUG_ON(!inode);
@@ -1201,6 +1208,9 @@ int ocfs2_data_lock_full(struct inode *inode,
goto out;
}
+ if (ocfs2_mount_local(osb))
+ goto out;
+
lockres = &OCFS2_I(inode)->ip_data_lockres;
level = write ? LKM_EXMODE : LKM_PRMODE;
@@ -1269,6 +1279,7 @@ void ocfs2_data_unlock(struct inode *inode,
{
int level = write ? LKM_EXMODE : LKM_PRMODE;
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry_void();
@@ -1276,7 +1287,8 @@ void ocfs2_data_unlock(struct inode *inode,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
- if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+ if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
+ !ocfs2_mount_local(osb))
ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
mlog_exit_void();
@@ -1467,8 +1479,9 @@ static int ocfs2_meta_lock_update(struct inode *inode,
{
int status = 0;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
- struct ocfs2_lock_res *lockres;
+ struct ocfs2_lock_res *lockres = NULL;
struct ocfs2_dinode *fe;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry_void();
@@ -1483,10 +1496,12 @@ static int ocfs2_meta_lock_update(struct inode *inode,
}
spin_unlock(&oi->ip_lock);
- lockres = &oi->ip_meta_lockres;
+ if (!ocfs2_mount_local(osb)) {
+ lockres = &oi->ip_meta_lockres;
- if (!ocfs2_should_refresh_lock_res(lockres))
- goto bail;
+ if (!ocfs2_should_refresh_lock_res(lockres))
+ goto bail;
+ }
/* This will discard any caching information we might have had
* for the inode metadata. */
@@ -1496,7 +1511,7 @@ static int ocfs2_meta_lock_update(struct inode *inode,
* map (directories, bitmap files, etc) */
ocfs2_extent_map_trunc(inode, 0);
- if (ocfs2_meta_lvb_is_trustable(inode, lockres)) {
+ if (lockres && ocfs2_meta_lvb_is_trustable(inode, lockres)) {
mlog(0, "Trusting LVB on inode %llu\n",
(unsigned long long)oi->ip_blkno);
ocfs2_refresh_inode_from_lvb(inode);
@@ -1543,7 +1558,8 @@ static int ocfs2_meta_lock_update(struct inode *inode,
status = 0;
bail_refresh:
- ocfs2_complete_lock_res_refresh(lockres, status);
+ if (lockres)
+ ocfs2_complete_lock_res_refresh(lockres, status);
bail:
mlog_exit(status);
return status;
@@ -1585,7 +1601,7 @@ int ocfs2_meta_lock_full(struct inode *inode,
int arg_flags)
{
int status, level, dlm_flags, acquired;
- struct ocfs2_lock_res *lockres;
+ struct ocfs2_lock_res *lockres = NULL;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct buffer_head *local_bh = NULL;
@@ -1607,6 +1623,9 @@ int ocfs2_meta_lock_full(struct inode *inode,
goto bail;
}
+ if (ocfs2_mount_local(osb))
+ goto local;
+
if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
wait_event(osb->recovery_event,
ocfs2_node_map_is_empty(osb, &osb->recovery_map));
@@ -1636,6 +1655,7 @@ int ocfs2_meta_lock_full(struct inode *inode,
wait_event(osb->recovery_event,
ocfs2_node_map_is_empty(osb, &osb->recovery_map));
+local:
/*
* We only see this flag if we're being called from
* ocfs2_read_locked_inode(). It means we're locking an inode
@@ -1644,7 +1664,8 @@ int ocfs2_meta_lock_full(struct inode *inode,
*/
if (inode->i_state & I_NEW) {
status = 0;
- ocfs2_complete_lock_res_refresh(lockres, 0);
+ if (lockres)
+ ocfs2_complete_lock_res_refresh(lockres, 0);
goto bail;
}
@@ -1767,6 +1788,7 @@ void ocfs2_meta_unlock(struct inode *inode,
{
int level = ex ? LKM_EXMODE : LKM_PRMODE;
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry_void();
@@ -1774,7 +1796,8 @@ void ocfs2_meta_unlock(struct inode *inode,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
ex ? "EXMODE" : "PRMODE");
- if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+ if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
+ !ocfs2_mount_local(osb))
ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
mlog_exit_void();
@@ -1783,7 +1806,7 @@ void ocfs2_meta_unlock(struct inode *inode,
int ocfs2_super_lock(struct ocfs2_super *osb,
int ex)
{
- int status;
+ int status = 0;
int level = ex ? LKM_EXMODE : LKM_PRMODE;
struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
struct buffer_head *bh;
@@ -1794,6 +1817,9 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
if (ocfs2_is_hard_readonly(osb))
return -EROFS;
+ if (ocfs2_mount_local(osb))
+ goto bail;
+
status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
if (status < 0) {
mlog_errno(status);
@@ -1832,7 +1858,8 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
int level = ex ? LKM_EXMODE : LKM_PRMODE;
struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
- ocfs2_cluster_unlock(osb, lockres, level);
+ if (!ocfs2_mount_local(osb))
+ ocfs2_cluster_unlock(osb, lockres, level);
}
int ocfs2_rename_lock(struct ocfs2_super *osb)
@@ -1843,6 +1870,9 @@ int ocfs2_rename_lock(struct ocfs2_super *osb)
if (ocfs2_is_hard_readonly(osb))
return -EROFS;
+ if (ocfs2_mount_local(osb))
+ return 0;
+
status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
if (status < 0)
mlog_errno(status);
@@ -1854,7 +1884,8 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb)
{
struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
- ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
+ if (!ocfs2_mount_local(osb))
+ ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
}
int ocfs2_dentry_lock(struct dentry *dentry, int ex)
@@ -1869,6 +1900,9 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
if (ocfs2_is_hard_readonly(osb))
return -EROFS;
+ if (ocfs2_mount_local(osb))
+ return 0;
+
ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
if (ret < 0)
mlog_errno(ret);
@@ -1882,7 +1916,8 @@ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
- ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
+ if (!ocfs2_mount_local(osb))
+ ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
}
/* Reference counting of the dlm debug structure. We want this because
@@ -2145,12 +2180,15 @@ static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
int ocfs2_dlm_init(struct ocfs2_super *osb)
{
- int status;
+ int status = 0;
u32 dlm_key;
- struct dlm_ctxt *dlm;
+ struct dlm_ctxt *dlm = NULL;
mlog_entry_void();
+ if (ocfs2_mount_local(osb))
+ goto local;
+
status = ocfs2_dlm_init_debug(osb);
if (status < 0) {
mlog_errno(status);
@@ -2178,11 +2216,12 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
goto bail;
}
+ dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
+
+local:
ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
- dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
-
osb->dlm = dlm;
status = 0;
@@ -2679,6 +2718,15 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
inode = ocfs2_lock_res_inode(lockres);
mapping = inode->i_mapping;
+ /*
+ * We need this before the filemap_fdatawrite() so that it can
+ * transfer the dirty bit from the PTE to the
+ * page. Unfortunately this means that even for EX->PR
+ * downconverts, we'll lose our mappings and have to build
+ * them up again.
+ */
+ unmap_mapping_range(mapping, 0, 0, 0);
+
if (filemap_fdatawrite(mapping)) {
mlog(ML_ERROR, "Could not sync inode %llu for downconvert!",
(unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -2686,7 +2734,6 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
sync_mapping_buffers(mapping);
if (blocking == LKM_EXMODE) {
truncate_inode_pages(mapping, 0);
- unmap_mapping_range(mapping, 0, 0, 0);
} else {
/* We only need to wait on the I/O if we're not also
* truncating pages because truncate_inode_pages waits
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 06be6e774cf..56e1fefc120 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -60,14 +60,11 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp)
inode = ocfs2_iget(OCFS2_SB(sb), handle->ih_blkno, 0);
- if (IS_ERR(inode)) {
- mlog_errno(PTR_ERR(inode));
+ if (IS_ERR(inode))
return (void *)inode;
- }
if (handle->ih_generation != inode->i_generation) {
iput(inode);
- mlog_errno(-ESTALE);
return ERR_PTR(-ESTALE);
}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8786b3c490a..10953a508f2 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -68,7 +68,7 @@ static int ocfs2_file_open(struct inode *inode, struct file *file)
struct ocfs2_inode_info *oi = OCFS2_I(inode);
mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
- file->f_dentry->d_name.len, file->f_dentry->d_name.name);
+ file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name);
spin_lock(&oi->ip_lock);
@@ -98,8 +98,8 @@ static int ocfs2_file_release(struct inode *inode, struct file *file)
struct ocfs2_inode_info *oi = OCFS2_I(inode);
mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
- file->f_dentry->d_name.len,
- file->f_dentry->d_name.name);
+ file->f_path.dentry->d_name.len,
+ file->f_path.dentry->d_name.name);
spin_lock(&oi->ip_lock);
if (!--oi->ip_open_count)
@@ -149,10 +149,29 @@ int ocfs2_should_update_atime(struct inode *inode,
((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
return 0;
+ /*
+ * We can be called with no vfsmnt structure - NFSD will
+ * sometimes do this.
+ *
+ * Note that our action here is different than touch_atime() -
+ * if we can't tell whether this is a noatime mount, then we
+ * don't know whether to trust the value of s_atime_quantum.
+ */
+ if (vfsmnt == NULL)
+ return 0;
+
if ((vfsmnt->mnt_flags & MNT_NOATIME) ||
((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
return 0;
+ if (vfsmnt->mnt_flags & MNT_RELATIME) {
+ if ((timespec_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
+ (timespec_compare(&inode->i_atime, &inode->i_ctime) <= 0))
+ return 1;
+
+ return 0;
+ }
+
now = CURRENT_TIME;
if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum))
return 0;
@@ -958,8 +977,6 @@ int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
}
ret = generic_permission(inode, mask, NULL);
- if (ret)
- mlog_errno(ret);
ocfs2_meta_unlock(inode, 0);
out:
@@ -1131,13 +1148,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
{
int ret, rw_level, have_alloc_sem = 0;
struct file *filp = iocb->ki_filp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int appending = filp->f_flags & O_APPEND ? 1 : 0;
mlog_entry("(0x%p, %u, '%.*s')\n", filp,
(unsigned int)nr_segs,
- filp->f_dentry->d_name.len,
- filp->f_dentry->d_name.name);
+ filp->f_path.dentry->d_name.len,
+ filp->f_path.dentry->d_name.name);
/* happy write of zero bytes */
if (iocb->ki_left == 0)
@@ -1159,7 +1176,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
goto out;
}
- ret = ocfs2_prepare_inode_for_write(filp->f_dentry, &iocb->ki_pos,
+ ret = ocfs2_prepare_inode_for_write(filp->f_path.dentry, &iocb->ki_pos,
iocb->ki_left, appending);
if (ret < 0) {
mlog_errno(ret);
@@ -1207,12 +1224,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
unsigned int flags)
{
int ret;
- struct inode *inode = out->f_dentry->d_inode;
+ struct inode *inode = out->f_path.dentry->d_inode;
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe,
(unsigned int)len,
- out->f_dentry->d_name.len,
- out->f_dentry->d_name.name);
+ out->f_path.dentry->d_name.len,
+ out->f_path.dentry->d_name.name);
inode_double_lock(inode, pipe->inode);
@@ -1222,7 +1239,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
goto out;
}
- ret = ocfs2_prepare_inode_for_write(out->f_dentry, ppos, len, 0);
+ ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
@@ -1247,12 +1264,12 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
unsigned int flags)
{
int ret = 0;
- struct inode *inode = in->f_dentry->d_inode;
+ struct inode *inode = in->f_path.dentry->d_inode;
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe,
(unsigned int)len,
- in->f_dentry->d_name.len,
- in->f_dentry->d_name.name);
+ in->f_path.dentry->d_name.len,
+ in->f_path.dentry->d_name.name);
/*
* See the comment in ocfs2_file_aio_read()
@@ -1278,12 +1295,12 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
{
int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0;
struct file *filp = iocb->ki_filp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
mlog_entry("(0x%p, %u, '%.*s')\n", filp,
(unsigned int)nr_segs,
- filp->f_dentry->d_name.len,
- filp->f_dentry->d_name.name);
+ filp->f_path.dentry->d_name.len,
+ filp->f_path.dentry->d_name.name);
if (!inode) {
ret = -EINVAL;
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
index cbfd45a97a6..8fc52d6d0ce 100644
--- a/fs/ocfs2/heartbeat.c
+++ b/fs/ocfs2/heartbeat.c
@@ -154,6 +154,9 @@ int ocfs2_register_hb_callbacks(struct ocfs2_super *osb)
{
int status;
+ if (ocfs2_mount_local(osb))
+ return 0;
+
status = o2hb_register_callback(&osb->osb_hb_down);
if (status < 0) {
mlog_errno(status);
@@ -172,6 +175,9 @@ void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb)
{
int status;
+ if (ocfs2_mount_local(osb))
+ return;
+
status = o2hb_unregister_callback(&osb->osb_hb_down);
if (status < 0)
mlog_errno(status);
@@ -186,6 +192,9 @@ void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
int ret;
char *argv[5], *envp[3];
+ if (ocfs2_mount_local(osb))
+ return;
+
if (!osb->uuid_str) {
/* This can happen if we don't get far enough in mount... */
mlog(0, "No UUID with which to stop heartbeat!\n\n");
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 42e361f3054..28ab56f2b98 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -146,7 +146,6 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, int flags)
if (is_bad_inode(inode)) {
iput(inode);
inode = ERR_PTR(-ESTALE);
- mlog_errno(PTR_ERR(inode));
goto bail;
}
@@ -155,8 +154,7 @@ bail:
mlog(0, "returning inode with number %llu\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno);
mlog_exit_ptr(inode);
- } else
- mlog_errno(PTR_ERR(inode));
+ }
return inode;
}
@@ -247,7 +245,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
* today. change if needed. */
if (!OCFS2_IS_VALID_DINODE(fe) ||
!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
- mlog(ML_ERROR, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "
+ mlog(0, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "
"signature = %.*s, flags = 0x%x\n",
inode->i_ino,
(unsigned long long)le64_to_cpu(fe->i_blkno), 7,
@@ -423,7 +421,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
* cluster lock before trusting anything anyway.
*/
can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
- && !(args->fi_flags & OCFS2_FI_FLAG_NOLOCK);
+ && !(args->fi_flags & OCFS2_FI_FLAG_NOLOCK)
+ && !ocfs2_mount_local(osb);
/*
* To maintain backwards compatibility with older versions of
@@ -477,11 +476,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
S_ISBLK(le16_to_cpu(fe->i_mode)))
inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
- if (ocfs2_populate_inode(inode, fe, 0) < 0) {
- mlog(ML_ERROR, "populate failed! i_blkno=%llu, i_ino=%lu\n",
- (unsigned long long)fe->i_blkno, inode->i_ino);
+ if (ocfs2_populate_inode(inode, fe, 0) < 0)
goto bail;
- }
BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 1d7f4ab1e5e..825cb0ae1b4 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -144,8 +144,10 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
ocfs2_abort(osb->sb, "Detected aborted journal");
handle = ERR_PTR(-EROFS);
}
- } else
- atomic_inc(&(osb->journal->j_num_trans));
+ } else {
+ if (!ocfs2_mount_local(osb))
+ atomic_inc(&(osb->journal->j_num_trans));
+ }
return handle;
}
@@ -507,9 +509,23 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
- status = ocfs2_journal_toggle_dirty(osb, 0);
- if (status < 0)
- mlog_errno(status);
+ if (ocfs2_mount_local(osb)) {
+ journal_lock_updates(journal->j_journal);
+ status = journal_flush(journal->j_journal);
+ journal_unlock_updates(journal->j_journal);
+ if (status < 0)
+ mlog_errno(status);
+ }
+
+ if (status == 0) {
+ /*
+ * Do not toggle if flush was unsuccessful otherwise
+ * will leave dirty metadata in a "clean" journal
+ */
+ status = ocfs2_journal_toggle_dirty(osb, 0);
+ if (status < 0)
+ mlog_errno(status);
+ }
/* Shutdown the kernel journal system */
journal_destroy(journal->j_journal);
@@ -549,7 +565,7 @@ static void ocfs2_clear_journal_error(struct super_block *sb,
}
}
-int ocfs2_journal_load(struct ocfs2_journal *journal)
+int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
{
int status = 0;
struct ocfs2_super *osb;
@@ -576,14 +592,18 @@ int ocfs2_journal_load(struct ocfs2_journal *journal)
}
/* Launch the commit thread */
- osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt");
- if (IS_ERR(osb->commit_task)) {
- status = PTR_ERR(osb->commit_task);
+ if (!local) {
+ osb->commit_task = kthread_run(ocfs2_commit_thread, osb,
+ "ocfs2cmt");
+ if (IS_ERR(osb->commit_task)) {
+ status = PTR_ERR(osb->commit_task);
+ osb->commit_task = NULL;
+ mlog(ML_ERROR, "unable to launch ocfs2commit thread, "
+ "error=%d", status);
+ goto done;
+ }
+ } else
osb->commit_task = NULL;
- mlog(ML_ERROR, "unable to launch ocfs2commit thread, error=%d",
- status);
- goto done;
- }
done:
mlog_exit(status);
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 899112ad813..e1216364d19 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -157,7 +157,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal,
void ocfs2_journal_shutdown(struct ocfs2_super *osb);
int ocfs2_journal_wipe(struct ocfs2_journal *journal,
int full);
-int ocfs2_journal_load(struct ocfs2_journal *journal);
+int ocfs2_journal_load(struct ocfs2_journal *journal, int local);
int ocfs2_check_journals_nolocks(struct ocfs2_super *osb);
void ocfs2_recovery_thread(struct ocfs2_super *osb,
int node_num);
@@ -174,6 +174,9 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
{
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ if (ocfs2_mount_local(osb))
+ return;
+
if (!ocfs2_inode_fully_checkpointed(inode)) {
/* WARNING: This only kicks off a single
* checkpoint. If someone races you and adds more
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 698d79a74ef..4dedd978910 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -776,7 +776,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
{
int status;
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 69f85ae392d..51b02044768 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -83,10 +83,12 @@ static struct vm_operations_struct ocfs2_file_vm_ops = {
int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret = 0, lock_level = 0;
+ struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
/* We don't want to support shared writable mappings yet. */
- if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
- && ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
+ if (!ocfs2_mount_local(osb) &&
+ ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
+ ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
/* This is -EINVAL because generic_file_readonly_mmap
* returns it in a similar situation. */
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 21db45ddf14..f3d7803b4b4 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -587,9 +587,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
}
ocfs2_inode_set_new(osb, inode);
- status = ocfs2_create_new_inode_locks(inode);
- if (status < 0)
- mlog_errno(status);
+ if (!ocfs2_mount_local(osb)) {
+ status = ocfs2_create_new_inode_locks(inode);
+ if (status < 0)
+ mlog_errno(status);
+ }
status = 0; /* error in ocfs2_create_new_inode_locks is not
* critical */
@@ -930,14 +932,15 @@ static int ocfs2_unlink(struct inode *dir,
goto leave;
}
- if (S_ISDIR(inode->i_mode)) {
+ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ if (S_ISDIR(inode->i_mode))
drop_nlink(dir);
- status = ocfs2_mark_inode_dirty(handle, dir,
- parent_node_bh);
- if (status < 0) {
- mlog_errno(status);
+
+ status = ocfs2_mark_inode_dirty(handle, dir, parent_node_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ if (S_ISDIR(inode->i_mode))
inc_nlink(dir);
- }
}
leave:
@@ -1066,6 +1069,7 @@ static int ocfs2_rename(struct inode *old_dir,
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
struct buffer_head *orphan_entry_bh = NULL;
struct buffer_head *newfe_bh = NULL;
+ struct buffer_head *old_inode_bh = NULL;
struct buffer_head *insert_entry_bh = NULL;
struct ocfs2_super *osb = NULL;
u64 newfe_blkno;
@@ -1077,7 +1081,7 @@ static int ocfs2_rename(struct inode *old_dir,
struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above
struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
// this is the 1st dirent bh
- nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
+ nlink_t old_dir_nlink = old_dir->i_nlink;
/* At some point it might be nice to break this function up a
* bit. */
@@ -1137,12 +1141,11 @@ static int ocfs2_rename(struct inode *old_dir,
}
/*
- * Though we don't require an inode meta data update if
- * old_inode is not a directory, we lock anyway here to ensure
- * the vote thread on other nodes won't have to concurrently
- * downconvert the inode and the dentry locks.
+ * Aside from allowing a meta data update, the locking here
+ * also ensures that the vote thread on other nodes won't have
+ * to concurrently downconvert the inode and the dentry locks.
*/
- status = ocfs2_meta_lock(old_inode, NULL, 1);
+ status = ocfs2_meta_lock(old_inode, &old_inode_bh, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
@@ -1353,6 +1356,7 @@ static int ocfs2_rename(struct inode *old_dir,
old_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(old_inode);
+ ocfs2_mark_inode_dirty(handle, old_inode, old_inode_bh);
/* now that the name has been added to new_dir, remove the old name */
status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh);
@@ -1382,27 +1386,22 @@ static int ocfs2_rename(struct inode *old_dir,
}
}
mark_inode_dirty(old_dir);
- if (new_inode)
+ ocfs2_mark_inode_dirty(handle, old_dir, old_dir_bh);
+ if (new_inode) {
mark_inode_dirty(new_inode);
+ ocfs2_mark_inode_dirty(handle, new_inode, newfe_bh);
+ }
- if (old_dir != new_dir)
- if (new_dir_nlink != new_dir->i_nlink) {
- if (!new_dir_bh) {
- mlog(ML_ERROR, "need to change nlink for new "
- "dir %llu from %d to %d but bh is NULL\n",
- (unsigned long long)OCFS2_I(new_dir)->ip_blkno,
- (int)new_dir_nlink, new_dir->i_nlink);
- } else {
- struct ocfs2_dinode *fe;
- status = ocfs2_journal_access(handle,
- new_dir,
- new_dir_bh,
- OCFS2_JOURNAL_ACCESS_WRITE);
- fe = (struct ocfs2_dinode *) new_dir_bh->b_data;
- fe->i_links_count = cpu_to_le16(new_dir->i_nlink);
- status = ocfs2_journal_dirty(handle, new_dir_bh);
- }
- }
+ if (old_dir != new_dir) {
+ /* Keep the same times on both directories.*/
+ new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime;
+
+ /*
+ * This will also pick up the i_nlink change from the
+ * block above.
+ */
+ ocfs2_mark_inode_dirty(handle, new_dir, new_dir_bh);
+ }
if (old_dir_nlink != old_dir->i_nlink) {
if (!old_dir_bh) {
@@ -1453,6 +1452,8 @@ bail:
iput(new_inode);
if (newfe_bh)
brelse(newfe_bh);
+ if (old_inode_bh)
+ brelse(old_inode_bh);
if (old_dir_bh)
brelse(old_dir_bh);
if (new_dir_bh)
@@ -1824,6 +1825,13 @@ static int __ocfs2_add_entry(handle_t *handle,
(le16_to_cpu(de->rec_len) >= rec_len)) ||
(le16_to_cpu(de->rec_len) >=
(OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
+ if (retval < 0) {
+ mlog_errno(retval);
+ goto bail;
+ }
+
status = ocfs2_journal_access(handle, dir, insert_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
/* By now the buffer is marked for journaling */
@@ -1846,7 +1854,6 @@ static int __ocfs2_add_entry(handle_t *handle,
de->name_len = namelen;
memcpy(de->name, name, namelen);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
dir->i_version++;
status = ocfs2_journal_dirty(handle, insert_bh);
retval = 0;
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index b767fd7da6e..db8e77cd35d 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -349,6 +349,11 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
return ret;
}
+static inline int ocfs2_mount_local(struct ocfs2_super *osb)
+{
+ return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT);
+}
+
#define OCFS2_IS_VALID_DINODE(ptr) \
(!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 3330a5dc6be..e61e218f5e0 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -85,8 +85,8 @@
#define OCFS2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
-#define OCFS2_FEATURE_COMPAT_SUPP 0
-#define OCFS2_FEATURE_INCOMPAT_SUPP 0
+#define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB
+#define OCFS2_FEATURE_INCOMPAT_SUPP OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT
#define OCFS2_FEATURE_RO_COMPAT_SUPP 0
/*
@@ -96,6 +96,32 @@
*/
#define OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV 0x0002
+/*
+ * tunefs sets this incompat flag before starting the resize and clears it
+ * at the end. This flag protects users from inadvertently mounting the fs
+ * after an aborted run without fsck-ing.
+ */
+#define OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG 0x0004
+
+/* Used to denote a non-clustered volume */
+#define OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT 0x0008
+
+/* Support for sparse allocation in b-trees */
+#define OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC 0x0010
+
+/*
+ * backup superblock flag is used to indicate that this volume
+ * has backup superblocks.
+ */
+#define OCFS2_FEATURE_COMPAT_BACKUP_SB 0x0001
+
+/* The byte offset of the first backup block will be 1G.
+ * The following will be 4G, 16G, 64G, 256G and 1T.
+ */
+#define OCFS2_BACKUP_SB_START 1 << 30
+
+/* the max backup superblock nums */
+#define OCFS2_MAX_BACKUP_SUPERBLOCKS 6
/*
* Flags on ocfs2_dinode.i_flags
@@ -554,6 +580,20 @@ static inline int ocfs2_truncate_recs_per_inode(struct super_block *sb)
return size / sizeof(struct ocfs2_truncate_rec);
}
+
+static inline u64 ocfs2_backup_super_blkno(struct super_block *sb, int index)
+{
+ u64 offset = OCFS2_BACKUP_SB_START;
+
+ if (index >= 0 && index < OCFS2_MAX_BACKUP_SUPERBLOCKS) {
+ offset <<= (2 * index);
+ offset >>= sb->s_blocksize_bits;
+ return offset;
+ }
+
+ return 0;
+
+}
#else
static inline int ocfs2_fast_symlink_chars(int blocksize)
{
@@ -619,6 +659,19 @@ static inline int ocfs2_truncate_recs_per_inode(int blocksize)
return size / sizeof(struct ocfs2_truncate_rec);
}
+
+static inline uint64_t ocfs2_backup_super_blkno(int blocksize, int index)
+{
+ uint64_t offset = OCFS2_BACKUP_SB_START;
+
+ if (index >= 0 && index < OCFS2_MAX_BACKUP_SUPERBLOCKS) {
+ offset <<= (2 * index);
+ offset /= blocksize;
+ return offset;
+ }
+
+ return 0;
+}
#endif /* __KERNEL__ */
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index aa6f5aadedc..2d3ac32cb74 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -175,7 +175,7 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
struct buffer_head *bh = NULL;
struct ocfs2_slot_info *si;
- si = kcalloc(1, sizeof(struct ocfs2_slot_info), GFP_KERNEL);
+ si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
if (!si) {
status = -ENOMEM;
mlog_errno(status);
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 000d71cca6c..6dbb1176275 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -488,7 +488,7 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
int status;
u32 slot;
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
@@ -530,7 +530,7 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
{
int status;
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
@@ -595,7 +595,7 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
mlog_entry_void();
- *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
if (!(*ac)) {
status = -ENOMEM;
mlog_errno(status);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 4bf39540e65..6e300a88a47 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -508,6 +508,27 @@ bail:
return status;
}
+static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+{
+ if (ocfs2_mount_local(osb)) {
+ if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+ mlog(ML_ERROR, "Cannot heartbeat on a locally "
+ "mounted device.\n");
+ return -EINVAL;
+ }
+ }
+
+ if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+ if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb)) {
+ mlog(ML_ERROR, "Heartbeat has to be started to mount "
+ "a read-write clustered device.\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
{
struct dentry *root;
@@ -516,16 +537,24 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
struct inode *inode = NULL;
struct ocfs2_super *osb = NULL;
struct buffer_head *bh = NULL;
+ char nodestr[8];
mlog_entry("%p, %p, %i", sb, data, silent);
- /* for now we only have one cluster/node, make sure we see it
- * in the heartbeat universe */
- if (!o2hb_check_local_node_heartbeating()) {
+ if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
status = -EINVAL;
goto read_super_error;
}
+ /* for now we only have one cluster/node, make sure we see it
+ * in the heartbeat universe */
+ if (parsed_opt & OCFS2_MOUNT_HB_LOCAL) {
+ if (!o2hb_check_local_node_heartbeating()) {
+ status = -EINVAL;
+ goto read_super_error;
+ }
+ }
+
/* probe for superblock */
status = ocfs2_sb_probe(sb, &bh, &sector_size);
if (status < 0) {
@@ -541,11 +570,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
}
brelse(bh);
bh = NULL;
-
- if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
- status = -EINVAL;
- goto read_super_error;
- }
osb->s_mount_opt = parsed_opt;
sb->s_magic = OCFS2_SUPER_MAGIC;
@@ -588,21 +612,16 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
}
if (!ocfs2_is_hard_readonly(osb)) {
- /* If this isn't a hard readonly mount, then we need
- * to make sure that heartbeat is in a valid state,
- * and that we mark ourselves soft readonly is -oro
- * was specified. */
- if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
- mlog(ML_ERROR, "No heartbeat for device (%s)\n",
- sb->s_id);
- status = -EINVAL;
- goto read_super_error;
- }
-
if (sb->s_flags & MS_RDONLY)
ocfs2_set_ro_flag(osb, 0);
}
+ status = ocfs2_verify_heartbeat(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto read_super_error;
+ }
+
osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
ocfs2_debugfs_root);
if (!osb->osb_debug_root) {
@@ -635,9 +654,14 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
ocfs2_complete_mount_recovery(osb);
- printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %d, slot %d) "
+ if (ocfs2_mount_local(osb))
+ snprintf(nodestr, sizeof(nodestr), "local");
+ else
+ snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
+
+ printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d) "
"with %s data mode.\n",
- osb->dev_str, osb->node_num, osb->slot_num,
+ osb->dev_str, nodestr, osb->slot_num,
osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" :
"ordered");
@@ -999,7 +1023,11 @@ static int ocfs2_fill_local_node_info(struct ocfs2_super *osb)
/* XXX hold a ref on the node while mounte? easy enough, if
* desirable. */
- osb->node_num = o2nm_this_node();
+ if (ocfs2_mount_local(osb))
+ osb->node_num = 0;
+ else
+ osb->node_num = o2nm_this_node();
+
if (osb->node_num == O2NM_MAX_NODES) {
mlog(ML_ERROR, "could not find this host's node number\n");
status = -ENOENT;
@@ -1084,6 +1112,9 @@ static int ocfs2_mount_volume(struct super_block *sb)
goto leave;
}
+ if (ocfs2_mount_local(osb))
+ goto leave;
+
/* This should be sent *after* we recovered our journal as it
* will cause other nodes to unmark us as needing
* recovery. However, we need to send it *before* dropping the
@@ -1114,6 +1145,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
{
int tmp;
struct ocfs2_super *osb = NULL;
+ char nodestr[8];
mlog_entry("(0x%p)\n", sb);
@@ -1177,8 +1209,13 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
- printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %d)\n",
- osb->dev_str, osb->node_num);
+ if (ocfs2_mount_local(osb))
+ snprintf(nodestr, sizeof(nodestr), "local");
+ else
+ snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
+
+ printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n",
+ osb->dev_str, nodestr);
ocfs2_delete_osb(osb);
kfree(osb);
@@ -1194,7 +1231,7 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu
BUG_ON(uuid_bytes != OCFS2_VOL_UUID_LEN);
- osb->uuid_str = kcalloc(1, OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
+ osb->uuid_str = kzalloc(OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
if (osb->uuid_str == NULL)
return -ENOMEM;
@@ -1225,7 +1262,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
mlog_entry_void();
- osb = kcalloc(1, sizeof(struct ocfs2_super), GFP_KERNEL);
+ osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL);
if (!osb) {
status = -ENOMEM;
mlog_errno(status);
@@ -1350,7 +1387,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
*/
/* initialize our journal structure */
- journal = kcalloc(1, sizeof(struct ocfs2_journal), GFP_KERNEL);
+ journal = kzalloc(sizeof(struct ocfs2_journal), GFP_KERNEL);
if (!journal) {
mlog(ML_ERROR, "unable to alloc journal\n");
status = -ENOMEM;
@@ -1536,6 +1573,7 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
{
int status = 0;
int dirty;
+ int local;
struct ocfs2_dinode *local_alloc = NULL; /* only used if we
* recover
* ourselves. */
@@ -1563,8 +1601,10 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
"recovering volume.\n");
}
+ local = ocfs2_mount_local(osb);
+
/* will play back anything left in the journal. */
- ocfs2_journal_load(osb->journal);
+ ocfs2_journal_load(osb->journal, local);
if (dirty) {
/* recover my local alloc if we didn't unmount cleanly. */
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 957d6878b03..03b0191534d 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -158,8 +158,7 @@ static void *ocfs2_follow_link(struct dentry *dentry,
}
status = vfs_follow_link(nd, link);
- if (status && status != -ENOENT)
- mlog_errno(status);
+
bail:
if (page) {
kunmap(page);
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index 5b4dca79990..0afd8b9af70 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -479,7 +479,7 @@ static struct ocfs2_net_wait_ctxt *ocfs2_new_net_wait_ctxt(unsigned int response
{
struct ocfs2_net_wait_ctxt *w;
- w = kcalloc(1, sizeof(*w), GFP_NOFS);
+ w = kzalloc(sizeof(*w), GFP_NOFS);
if (!w) {
mlog_errno(-ENOMEM);
goto bail;
@@ -642,7 +642,7 @@ static struct ocfs2_vote_msg * ocfs2_new_vote_request(struct ocfs2_super *osb,
BUG_ON(!ocfs2_is_valid_vote_request(type));
- request = kcalloc(1, sizeof(*request), GFP_NOFS);
+ request = kzalloc(sizeof(*request), GFP_NOFS);
if (!request) {
mlog_errno(-ENOMEM);
} else {
@@ -1000,6 +1000,9 @@ int ocfs2_register_net_handlers(struct ocfs2_super *osb)
{
int status = 0;
+ if (ocfs2_mount_local(osb))
+ return 0;
+
status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE,
osb->net_key,
sizeof(struct ocfs2_response_msg),
diff --git a/fs/open.c b/fs/open.c
index 89e0c237a63..c989fb4cf7b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -165,7 +165,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf)
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs_native(file->f_dentry, &tmp);
+ error = vfs_statfs_native(file->f_path.dentry, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
@@ -186,7 +186,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user
file = fget(fd);
if (!file)
goto out;
- error = vfs_statfs64(file->f_dentry, &tmp);
+ error = vfs_statfs64(file->f_path.dentry, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
@@ -302,7 +302,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
if (file->f_flags & O_LARGEFILE)
small = 0;
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
inode = dentry->d_inode;
error = -EINVAL;
if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
@@ -448,8 +448,8 @@ asmlinkage long sys_fchdir(unsigned int fd)
if (!file)
goto out;
- dentry = file->f_dentry;
- mnt = file->f_vfsmnt;
+ dentry = file->f_path.dentry;
+ mnt = file->f_path.mnt;
inode = dentry->d_inode;
error = -ENOTDIR;
@@ -503,7 +503,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
if (!file)
goto out;
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
inode = dentry->d_inode;
audit_inode(NULL, inode);
@@ -662,7 +662,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
if (!file)
goto out;
- dentry = file->f_dentry;
+ dentry = file->f_path.dentry;
audit_inode(NULL, dentry->d_inode);
error = chown_common(dentry, user, group);
fput(file);
@@ -688,8 +688,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
}
f->f_mapping = inode->i_mapping;
- f->f_dentry = dentry;
- f->f_vfsmnt = mnt;
+ f->f_path.dentry = dentry;
+ f->f_path.mnt = mnt;
f->f_pos = 0;
f->f_op = fops_get(inode->i_fop);
file_move(f, &inode->i_sb->s_files);
@@ -723,8 +723,8 @@ cleanup_all:
if (f->f_mode & FMODE_WRITE)
put_write_access(inode);
file_kill(f);
- f->f_dentry = NULL;
- f->f_vfsmnt = NULL;
+ f->f_path.dentry = NULL;
+ f->f_path.mnt = NULL;
cleanup_file:
put_filp(f);
dput(dentry);
@@ -822,7 +822,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
/* Pick up the filp from the open intent */
filp = nd->intent.open.file;
/* Has the filesystem initialised the file for us? */
- if (filp->f_dentry == NULL)
+ if (filp->f_path.dentry == NULL)
filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
else
path_release(nd);
@@ -864,8 +864,7 @@ int get_unused_fd(void)
repeat:
fdt = files_fdtable(files);
- fd = find_next_zero_bit(fdt->open_fds->fds_bits,
- fdt->max_fdset,
+ fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
files->next_fd);
/*
@@ -965,7 +964,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
- fsnotify_open(f->f_dentry);
+ fsnotify_open(f->f_path.dentry);
fd_install(fd, f);
}
}
@@ -1087,6 +1086,7 @@ EXPORT_SYMBOL(sys_close);
asmlinkage long sys_vhangup(void)
{
if (capable(CAP_SYS_TTY_CONFIG)) {
+ /* XXX: this needs locking */
tty_vhangup(current->signal->tty);
return 0;
}
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 26f44e0074e..99c0bc37ba0 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -262,7 +262,7 @@ found:
static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct op_inode_info *oi = OP_I(inode);
struct device_node *dp = oi->u.node;
struct device_node *child;
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index e478f194183..74552c60b67 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -194,7 +194,7 @@ config LDM_DEBUG
config SGI_PARTITION
bool "SGI partition support" if PARTITION_ADVANCED
- default y if (SGI_IP22 || SGI_IP27 || ((MACH_JAZZ || SNI_RM200_PCI) && !CPU_LITTLE_ENDIAN))
+ default y if (SGI_IP22 || SGI_IP27 || ((MACH_JAZZ || SNI_RM) && !CPU_LITTLE_ENDIAN))
help
Say Y here if you would like to be able to read the hard disk
partition table format used by SGI machines.
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 1901137f4ec..3d73d94d93a 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -276,12 +276,39 @@ static struct part_attribute part_attr_stat = {
.show = part_stat_read
};
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+
+static ssize_t part_fail_store(struct hd_struct * p,
+ const char *buf, size_t count)
+{
+ int i;
+
+ if (count > 0 && sscanf(buf, "%d", &i) > 0)
+ p->make_it_fail = (i == 0) ? 0 : 1;
+
+ return count;
+}
+static ssize_t part_fail_read(struct hd_struct * p, char *page)
+{
+ return sprintf(page, "%d\n", p->make_it_fail);
+}
+static struct part_attribute part_attr_fail = {
+ .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
+ .store = part_fail_store,
+ .show = part_fail_read
+};
+
+#endif
+
static struct attribute * default_attrs[] = {
&part_attr_uevent.attr,
&part_attr_dev.attr,
&part_attr_start.attr,
&part_attr_size.attr,
&part_attr_stat.attr,
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+ &part_attr_fail.attr,
+#endif
NULL,
};
diff --git a/fs/pipe.c b/fs/pipe.c
index ae36b89b1a3..68090e84f58 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -207,7 +207,7 @@ int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
return 0;
}
-static struct pipe_buf_operations anon_pipe_buf_ops = {
+static const struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
@@ -222,7 +222,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
unsigned long nr_segs, loff_t pos)
{
struct file *filp = iocb->ki_filp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct pipe_inode_info *pipe;
int do_wakeup;
ssize_t ret;
@@ -243,7 +243,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
if (bufs) {
int curbuf = pipe->curbuf;
struct pipe_buffer *buf = pipe->bufs + curbuf;
- struct pipe_buf_operations *ops = buf->ops;
+ const struct pipe_buf_operations *ops = buf->ops;
void *addr;
size_t chars = buf->len;
int error, atomic;
@@ -335,7 +335,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
unsigned long nr_segs, loff_t ppos)
{
struct file *filp = iocb->ki_filp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct pipe_inode_info *pipe;
ssize_t ret;
int do_wakeup;
@@ -365,7 +365,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
(PIPE_BUFFERS-1);
struct pipe_buffer *buf = pipe->bufs + lastbuf;
- struct pipe_buf_operations *ops = buf->ops;
+ const struct pipe_buf_operations *ops = buf->ops;
int offset = buf->offset + buf->len;
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
@@ -520,7 +520,7 @@ static int
pipe_ioctl(struct inode *pino, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct pipe_inode_info *pipe;
int count, buf, nrbufs;
@@ -548,7 +548,7 @@ static unsigned int
pipe_poll(struct file *filp, poll_table *wait)
{
unsigned int mask;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct pipe_inode_info *pipe = inode->i_pipe;
int nrbufs;
@@ -601,7 +601,7 @@ pipe_release(struct inode *inode, int decr, int decw)
static int
pipe_read_fasync(int fd, struct file *filp, int on)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int retval;
mutex_lock(&inode->i_mutex);
@@ -618,7 +618,7 @@ pipe_read_fasync(int fd, struct file *filp, int on)
static int
pipe_write_fasync(int fd, struct file *filp, int on)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int retval;
mutex_lock(&inode->i_mutex);
@@ -635,7 +635,7 @@ pipe_write_fasync(int fd, struct file *filp, int on)
static int
pipe_rdwr_fasync(int fd, struct file *filp, int on)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct pipe_inode_info *pipe = inode->i_pipe;
int retval;
@@ -756,7 +756,7 @@ const struct file_operations rdwr_fifo_fops = {
.fasync = pipe_rdwr_fasync,
};
-static struct file_operations read_pipe_fops = {
+static const struct file_operations read_pipe_fops = {
.llseek = no_llseek,
.read = do_sync_read,
.aio_read = pipe_read,
@@ -768,7 +768,7 @@ static struct file_operations read_pipe_fops = {
.fasync = pipe_read_fasync,
};
-static struct file_operations write_pipe_fops = {
+static const struct file_operations write_pipe_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
.write = do_sync_write,
@@ -780,7 +780,7 @@ static struct file_operations write_pipe_fops = {
.fasync = pipe_write_fasync,
};
-static struct file_operations rdwr_pipe_fops = {
+static const struct file_operations rdwr_pipe_fops = {
.llseek = no_llseek,
.read = do_sync_read,
.aio_read = pipe_read,
@@ -914,8 +914,8 @@ struct file *create_write_pipe(void)
*/
dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(dentry, inode);
- f->f_vfsmnt = mntget(pipe_mnt);
- f->f_dentry = dentry;
+ f->f_path.mnt = mntget(pipe_mnt);
+ f->f_path.dentry = dentry;
f->f_mapping = inode->i_mapping;
f->f_flags = O_WRONLY;
@@ -935,8 +935,9 @@ struct file *create_write_pipe(void)
void free_write_pipe(struct file *f)
{
- mntput(f->f_vfsmnt);
- dput(f->f_dentry);
+ free_pipe_info(f->f_dentry->d_inode);
+ dput(f->f_path.dentry);
+ mntput(f->f_path.mnt);
put_filp(f);
}
@@ -947,9 +948,9 @@ struct file *create_read_pipe(struct file *wrf)
return ERR_PTR(-ENFILE);
/* Grab pipe from the writer */
- f->f_vfsmnt = mntget(wrf->f_vfsmnt);
- f->f_dentry = dget(wrf->f_dentry);
- f->f_mapping = wrf->f_dentry->d_inode->i_mapping;
+ f->f_path.mnt = mntget(wrf->f_path.mnt);
+ f->f_path.dentry = dget(wrf->f_path.dentry);
+ f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
f->f_pos = 0;
f->f_flags = O_RDONLY;
@@ -994,6 +995,8 @@ int do_pipe(int *fd)
err_fdr:
put_unused_fd(fdr);
err_read_pipe:
+ dput(fr->f_dentry);
+ mntput(fr->f_vfsmnt);
put_filp(fr);
err_write_pipe:
free_write_pipe(fw);
diff --git a/fs/pnode.c b/fs/pnode.c
index da42ee61c1d..56aacead836 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -6,7 +6,7 @@
* Author : Ram Pai (linuxram@us.ibm.com)
*
*/
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/mount.h>
#include <linux/fs.h>
#include "pnode.h"
diff --git a/fs/pnode.h b/fs/pnode.h
index 020e1bb60fd..d45bd8ec36b 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -13,7 +13,7 @@
#define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED)
#define IS_MNT_SLAVE(mnt) (mnt->mnt_master)
-#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace)
+#define IS_MNT_NEW(mnt) (!mnt->mnt_ns)
#define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED)
#define IS_MNT_UNBINDABLE(mnt) (mnt->mnt_flags & MNT_UNBINDABLE)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 25e917fb473..70e4fab117b 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -346,20 +346,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
sigemptyset(&sigcatch);
cutime = cstime = utime = stime = cputime_zero;
- mutex_lock(&tty_mutex);
rcu_read_lock();
if (lock_task_sighand(task, &flags)) {
struct signal_struct *sig = task->signal;
- struct tty_struct *tty = sig->tty;
-
- if (tty) {
- /*
- * sig->tty is not stable, but tty_mutex
- * protects us from release_dev(tty)
- */
- barrier();
- tty_pgrp = tty->pgrp;
- tty_nr = new_encode_dev(tty_devnum(tty));
+
+ if (sig->tty) {
+ tty_pgrp = sig->tty->pgrp;
+ tty_nr = new_encode_dev(tty_devnum(sig->tty));
}
num_threads = atomic_read(&sig->count);
@@ -388,14 +381,13 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
stime = cputime_add(stime, sig->stime);
}
- sid = sig->session;
+ sid = signal_session(sig);
pgid = process_group(task);
ppid = rcu_dereference(task->real_parent)->tgid;
unlock_task_sighand(task, &flags);
}
rcu_read_unlock();
- mutex_unlock(&tty_mutex);
if (!whole || num_threads<2)
wchan = get_wchan(task);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index b859fc749c0..1a979ea3b37 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -59,7 +59,7 @@
#include <linux/string.h>
#include <linux/seq_file.h>
#include <linux/namei.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/rcupdate.h>
@@ -365,33 +365,35 @@ struct proc_mounts {
static int mounts_open(struct inode *inode, struct file *file)
{
struct task_struct *task = get_proc_task(inode);
- struct namespace *namespace = NULL;
+ struct mnt_namespace *ns = NULL;
struct proc_mounts *p;
int ret = -EINVAL;
if (task) {
task_lock(task);
- namespace = task->nsproxy->namespace;
- if (namespace)
- get_namespace(namespace);
+ if (task->nsproxy) {
+ ns = task->nsproxy->mnt_ns;
+ if (ns)
+ get_mnt_ns(ns);
+ }
task_unlock(task);
put_task_struct(task);
}
- if (namespace) {
+ if (ns) {
ret = -ENOMEM;
p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
if (p) {
file->private_data = &p->m;
ret = seq_open(file, &mounts_op);
if (!ret) {
- p->m.private = namespace;
- p->event = namespace->event;
+ p->m.private = ns;
+ p->event = ns->event;
return 0;
}
kfree(p);
}
- put_namespace(namespace);
+ put_mnt_ns(ns);
}
return ret;
}
@@ -399,15 +401,15 @@ static int mounts_open(struct inode *inode, struct file *file)
static int mounts_release(struct inode *inode, struct file *file)
{
struct seq_file *m = file->private_data;
- struct namespace *namespace = m->private;
- put_namespace(namespace);
+ struct mnt_namespace *ns = m->private;
+ put_mnt_ns(ns);
return seq_release(inode, file);
}
static unsigned mounts_poll(struct file *file, poll_table *wait)
{
struct proc_mounts *p = file->private_data;
- struct namespace *ns = p->m.private;
+ struct mnt_namespace *ns = p->m.private;
unsigned res = 0;
poll_wait(file, &ns->poll, wait);
@@ -437,21 +439,21 @@ static int mountstats_open(struct inode *inode, struct file *file)
if (!ret) {
struct seq_file *m = file->private_data;
- struct namespace *namespace = NULL;
+ struct mnt_namespace *mnt_ns = NULL;
struct task_struct *task = get_proc_task(inode);
if (task) {
task_lock(task);
if (task->nsproxy)
- namespace = task->nsproxy->namespace;
- if (namespace)
- get_namespace(namespace);
+ mnt_ns = task->nsproxy->mnt_ns;
+ if (mnt_ns)
+ get_mnt_ns(mnt_ns);
task_unlock(task);
put_task_struct(task);
}
- if (namespace)
- m->private = namespace;
+ if (mnt_ns)
+ m->private = mnt_ns;
else {
seq_release(inode, file);
ret = -EINVAL;
@@ -472,7 +474,7 @@ static struct file_operations proc_mountstats_operations = {
static ssize_t proc_info_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
unsigned long page;
ssize_t length;
struct task_struct *task = get_proc_task(inode);
@@ -512,7 +514,7 @@ static int mem_open(struct inode* inode, struct file* file)
static ssize_t mem_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
- struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
char *page;
unsigned long src = *ppos;
int ret = -ESRCH;
@@ -584,7 +586,7 @@ static ssize_t mem_write(struct file * file, const char * buf,
{
int copied;
char *page;
- struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
unsigned long dst = *ppos;
copied = -ESRCH;
@@ -654,7 +656,7 @@ static struct file_operations proc_mem_operations = {
static ssize_t oom_adjust_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
char buffer[PROC_NUMBUF];
size_t len;
int oom_adjust;
@@ -694,7 +696,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
return -EINVAL;
if (*end == '\n')
end++;
- task = get_proc_task(file->f_dentry->d_inode);
+ task = get_proc_task(file->f_path.dentry->d_inode);
if (!task)
return -ESRCH;
if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
@@ -718,7 +720,7 @@ static struct file_operations proc_oom_adjust_operations = {
static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
ssize_t length;
char tmpbuf[TMPBUFLEN];
@@ -734,7 +736,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
char *page, *tmp;
ssize_t length;
uid_t loginuid;
@@ -853,6 +855,65 @@ static struct file_operations proc_seccomp_operations = {
};
#endif /* CONFIG_SECCOMP */
+#ifdef CONFIG_FAULT_INJECTION
+static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+ char buffer[PROC_NUMBUF];
+ size_t len;
+ int make_it_fail;
+ loff_t __ppos = *ppos;
+
+ if (!task)
+ return -ESRCH;
+ make_it_fail = task->make_it_fail;
+ put_task_struct(task);
+
+ len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail);
+ if (__ppos >= len)
+ return 0;
+ if (count > len-__ppos)
+ count = len-__ppos;
+ if (copy_to_user(buf, buffer + __ppos, count))
+ return -EFAULT;
+ *ppos = __ppos + count;
+ return count;
+}
+
+static ssize_t proc_fault_inject_write(struct file * file,
+ const char __user * buf, size_t count, loff_t *ppos)
+{
+ struct task_struct *task;
+ char buffer[PROC_NUMBUF], *end;
+ int make_it_fail;
+
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+ memset(buffer, 0, sizeof(buffer));
+ if (count > sizeof(buffer) - 1)
+ count = sizeof(buffer) - 1;
+ if (copy_from_user(buffer, buf, count))
+ return -EFAULT;
+ make_it_fail = simple_strtol(buffer, &end, 0);
+ if (*end == '\n')
+ end++;
+ task = get_proc_task(file->f_dentry->d_inode);
+ if (!task)
+ return -ESRCH;
+ task->make_it_fail = make_it_fail;
+ put_task_struct(task);
+ if (end - buffer == 0)
+ return -EIO;
+ return end - buffer;
+}
+
+static struct file_operations proc_fault_inject_operations = {
+ .read = proc_fault_inject_read,
+ .write = proc_fault_inject_write,
+};
+#endif
+
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
@@ -1078,7 +1139,7 @@ static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
char *name, int len,
instantiate_t instantiate, struct task_struct *task, void *ptr)
{
- struct dentry *child, *dir = filp->f_dentry;
+ struct dentry *child, *dir = filp->f_path.dentry;
struct inode *inode;
struct qstr qname;
ino_t ino = 0;
@@ -1157,8 +1218,8 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (file) {
- *mnt = mntget(file->f_vfsmnt);
- *dentry = dget(file->f_dentry);
+ *mnt = mntget(file->f_path.mnt);
+ *dentry = dget(file->f_path.dentry);
spin_unlock(&files->file_lock);
put_files_struct(files);
return 0;
@@ -1293,7 +1354,7 @@ static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir
static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct task_struct *p = get_proc_task(inode);
unsigned int fd, tid, ino;
@@ -1440,7 +1501,7 @@ static int proc_pident_readdir(struct file *filp,
{
int i;
int pid;
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
struct pid_entry *p, *last;
@@ -1496,7 +1557,7 @@ out_no_task:
static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
unsigned long page;
ssize_t length;
struct task_struct *task = get_proc_task(inode);
@@ -1512,7 +1573,7 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
goto out;
length = security_getprocattr(task,
- (char*)file->f_dentry->d_name.name,
+ (char*)file->f_path.dentry->d_name.name,
(void*)page, count);
if (length >= 0)
length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
@@ -1526,7 +1587,7 @@ out_no_task:
static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
char *page;
ssize_t length;
struct task_struct *task = get_proc_task(inode);
@@ -1552,7 +1613,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
goto out_free;
length = security_setprocattr(task,
- (char*)file->f_dentry->d_name.name,
+ (char*)file->f_path.dentry->d_name.name,
(void*)page, count);
out_free:
free_page((unsigned long) page);
@@ -1745,6 +1806,27 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filld
proc_base_instantiate, task, p);
}
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
+{
+ return sprintf(buffer,
+ "rchar: %llu\n"
+ "wchar: %llu\n"
+ "syscr: %llu\n"
+ "syscw: %llu\n"
+ "read_bytes: %llu\n"
+ "write_bytes: %llu\n"
+ "cancelled_write_bytes: %llu\n",
+ (unsigned long long)task->rchar,
+ (unsigned long long)task->wchar,
+ (unsigned long long)task->syscr,
+ (unsigned long long)task->syscw,
+ (unsigned long long)task->ioac.read_bytes,
+ (unsigned long long)task->ioac.write_bytes,
+ (unsigned long long)task->ioac.cancelled_write_bytes);
+}
+#endif
+
/*
* Thread groups
*/
@@ -1793,6 +1875,12 @@ static struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_AUDITSYSCALL
REG("loginuid", S_IWUSR|S_IRUGO, loginuid),
#endif
+#ifdef CONFIG_FAULT_INJECTION
+ REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+#endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+ INF("io", S_IRUGO, pid_io_accounting),
+#endif
};
static int proc_tgid_base_readdir(struct file * filp,
@@ -1994,7 +2082,7 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
- struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode);
+ struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
struct task_struct *task;
int tgid;
@@ -2068,6 +2156,9 @@ static struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_AUDITSYSCALL
REG("loginuid", S_IWUSR|S_IRUGO, loginuid),
#endif
+#ifdef CONFIG_FAULT_INJECTION
+ REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
+#endif
};
static int proc_tid_base_readdir(struct file * filp,
@@ -2235,15 +2326,25 @@ static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filld
/* for the /proc/TGID/task/ directories */
static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
- struct task_struct *leader = get_proc_task(inode);
+ struct task_struct *leader = NULL;
struct task_struct *task;
int retval = -ENOENT;
ino_t ino;
int tid;
unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */
+ task = get_proc_task(inode);
+ if (!task)
+ goto out_no_task;
+ rcu_read_lock();
+ if (pid_alive(task)) {
+ leader = task->group_leader;
+ get_task_struct(leader);
+ }
+ rcu_read_unlock();
+ put_task_struct(task);
if (!leader)
goto out_no_task;
retval = 0;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 4ba03009cf7..853cb877d5f 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -52,7 +52,7 @@ static ssize_t
proc_file_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
char *page;
ssize_t retval=0;
int eof=0;
@@ -203,7 +203,7 @@ static ssize_t
proc_file_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct proc_dir_entry * dp;
dp = PDE(inode);
@@ -432,7 +432,7 @@ int proc_readdir(struct file * filp,
struct proc_dir_entry * de;
unsigned int ino;
int i;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
int ret = 0;
lock_kernel();
@@ -453,7 +453,7 @@ int proc_readdir(struct file * filp,
/* fall through */
case 1:
if (filldir(dirent, "..", 2, i,
- parent_ino(filp->f_dentry),
+ parent_ino(filp->f_path.dentry),
DT_DIR) < 0)
goto out;
i++;
@@ -558,7 +558,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
file_list_lock();
list_for_each(p, &sb->s_files) {
struct file * filp = list_entry(p, struct file, f_u.fu_list);
- struct dentry * dentry = filp->f_dentry;
+ struct dentry * dentry = filp->f_path.dentry;
struct inode * inode;
const struct file_operations *fops;
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index d7dbdf9e0f4..5ec67257e5f 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -46,7 +46,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
file = vma->vm_file;
if (file) {
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
}
@@ -67,7 +67,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
if (len < 1)
len = 1;
seq_printf(m, "%*c", len, ' ');
- seq_path(m, file->f_vfsmnt, file->f_dentry, "");
+ seq_path(m, file->f_path.mnt, file->f_path.dentry, "");
}
seq_putc(m, '\n');
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 51815cece6f..b37ce33f67e 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -39,13 +39,14 @@
#include <linux/seq_file.h>
#include <linux/times.h>
#include <linux/profile.h>
+#include <linux/utsname.h>
#include <linux/blkdev.h>
#include <linux/hugetlb.h>
#include <linux/jiffies.h>
#include <linux/sysrq.h>
#include <linux/vmalloc.h>
#include <linux/crash_dump.h>
-#include <linux/pspace.h>
+#include <linux/pid_namespace.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -92,7 +93,7 @@ static int loadavg_read_proc(char *page, char **start, off_t off,
LOAD_INT(a), LOAD_FRAC(a),
LOAD_INT(b), LOAD_FRAC(b),
LOAD_INT(c), LOAD_FRAC(c),
- nr_running(), nr_threads, init_pspace.last_pid);
+ nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid);
return proc_calc_metrics(page, start, off, count, eof, len);
}
@@ -252,8 +253,10 @@ static int version_read_proc(char *page, char **start, off_t off,
{
int len;
- strcpy(page, linux_banner);
- len = strlen(page);
+ len = snprintf(page, PAGE_SIZE, linux_proc_banner,
+ utsname()->sysname,
+ utsname()->release,
+ utsname()->version);
return proc_calc_metrics(page, start, off, count, eof, len);
}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 6b769afac55..55ade0d1562 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -94,8 +94,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
}
if (vma) {
- *mnt = mntget(vma->vm_file->f_vfsmnt);
- *dentry = dget(vma->vm_file->f_dentry);
+ *mnt = mntget(vma->vm_file->f_path.mnt);
+ *dentry = dget(vma->vm_file->f_path.dentry);
result = 0;
}
@@ -135,7 +135,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
int len;
if (file) {
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
}
@@ -156,7 +156,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
*/
if (file) {
pad_len_spaces(m, len);
- seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
+ seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n");
} else {
const char *name = arch_vma_name(vma);
if (!name) {
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 091aa8e48e0..fcc5caf93f5 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -126,8 +126,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount *
}
if (vma) {
- *mnt = mntget(vma->vm_file->f_vfsmnt);
- *dentry = dget(vma->vm_file->f_dentry);
+ *mnt = mntget(vma->vm_file->f_path.mnt);
+ *dentry = dget(vma->vm_file->f_path.dentry);
result = 0;
}
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 0d7103fa0df..c94db1db7a7 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -22,7 +22,7 @@
static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
unsigned int offset;
struct buffer_head *bh;
struct qnx4_inode_entry *de;
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 0947fb57dcf..54ebbc84207 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -25,11 +25,13 @@
*/
#include <linux/fs.h>
+#include <linux/mm.h>
const struct address_space_operations ramfs_aops = {
.readpage = simple_readpage,
.prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write
+ .commit_write = simple_commit_write,
+ .set_page_dirty = __set_page_dirty_nobuffers,
};
const struct file_operations ramfs_file_operations = {
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index bfe5dbf1002..e9d6c473328 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/init.h>
@@ -30,7 +31,8 @@ static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
const struct address_space_operations ramfs_aops = {
.readpage = simple_readpage,
.prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write
+ .commit_write = simple_commit_write,
+ .set_page_dirty = __set_page_dirty_nobuffers,
};
const struct file_operations ramfs_file_operations = {
@@ -232,7 +234,7 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
unsigned long pgoff, unsigned long flags)
{
unsigned long maxpages, lpages, nr, loop, ret;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct page **pages = NULL, **ptr, *page;
loff_t isize;
diff --git a/fs/read_write.c b/fs/read_write.c
index f792000a28e..707ac21700d 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -64,13 +64,13 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
lock_kernel();
switch (origin) {
case 2:
- offset += i_size_read(file->f_dentry->d_inode);
+ offset += i_size_read(file->f_path.dentry->d_inode);
break;
case 1:
offset += file->f_pos;
}
retval = -EINVAL;
- if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
+ if (offset>=0 && offset<=file->f_path.dentry->d_inode->i_sb->s_maxbytes) {
if (offset != file->f_pos) {
file->f_pos = offset;
file->f_version = 0;
@@ -95,7 +95,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
lock_kernel();
switch (origin) {
case 2:
- offset += i_size_read(file->f_dentry->d_inode);
+ offset += i_size_read(file->f_path.dentry->d_inode);
break;
case 1:
offset += file->f_pos;
@@ -203,7 +203,7 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
goto Einval;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
int retval = locks_mandatory_area(
read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
@@ -273,7 +273,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
else
ret = do_sync_read(file, buf, count, pos);
if (ret > 0) {
- fsnotify_access(file->f_dentry);
+ fsnotify_access(file->f_path.dentry);
current->rchar += ret;
}
current->syscr++;
@@ -331,7 +331,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
else
ret = do_sync_write(file, buf, count, pos);
if (ret > 0) {
- fsnotify_modify(file->f_dentry);
+ fsnotify_modify(file->f_path.dentry);
current->wchar += ret;
}
current->syscw++;
@@ -450,8 +450,6 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
return seg;
}
-EXPORT_UNUSED_SYMBOL(iov_shorten); /* June 2006 */
-
ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
{
@@ -628,9 +626,9 @@ out:
kfree(iov);
if ((ret + (type == READ)) > 0) {
if (type == READ)
- fsnotify_access(file->f_dentry);
+ fsnotify_access(file->f_path.dentry);
else
- fsnotify_modify(file->f_dentry);
+ fsnotify_modify(file->f_path.dentry);
}
return ret;
}
@@ -722,7 +720,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
if (!(in_file->f_mode & FMODE_READ))
goto fput_in;
retval = -EINVAL;
- in_inode = in_file->f_dentry->d_inode;
+ in_inode = in_file->f_path.dentry->d_inode;
if (!in_inode)
goto fput_in;
if (!in_file->f_op || !in_file->f_op->sendfile)
@@ -754,7 +752,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
retval = -EINVAL;
if (!out_file->f_op || !out_file->f_op->sendpage)
goto fput_out;
- out_inode = out_file->f_dentry->d_inode;
+ out_inode = out_file->f_path.dentry->d_inode;
retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
if (retval < 0)
goto fput_out;
diff --git a/fs/readdir.c b/fs/readdir.c
index bff3ee58e2f..f39f5b31325 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -21,7 +21,7 @@
int vfs_readdir(struct file *file, filldir_t filler, void *buf)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int res = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
goto out;
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index e3d466a228d..b286ccb0858 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -708,7 +708,7 @@ static void oid_groups(reiserfs_blocknr_hint_t * hint)
*/
static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
{
- struct path *path;
+ struct treepath *path;
struct buffer_head *bh;
struct item_head *ih;
int pos_in_item;
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index 657050ad743..96a2f8889da 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -45,7 +45,7 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
//
static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */
INITIALIZE_PATH(path_to_entry);
struct buffer_head *bh;
@@ -135,7 +135,7 @@ static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Ignore the .reiserfs_priv entry */
if (reiserfs_xattrs(inode->i_sb) &&
!old_format_only(inode->i_sb) &&
- filp->f_dentry == inode->i_sb->s_root &&
+ filp->f_path.dentry == inode->i_sb->s_root &&
REISERFS_SB(inode->i_sb)->priv_root &&
REISERFS_SB(inode->i_sb)->priv_root->d_inode
&& deh_objectid(deh) ==
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 373d862c3f8..5109f1d5e7f 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -48,6 +48,11 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
}
mutex_lock(&inode->i_mutex);
+
+ mutex_lock(&(REISERFS_I(inode)->i_mmap));
+ if (REISERFS_I(inode)->i_flags & i_ever_mapped)
+ REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+
reiserfs_write_lock(inode->i_sb);
/* freeing preallocation only involves relogging blocks that
* are already in the current transaction. preallocation gets
@@ -100,11 +105,24 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
err = reiserfs_truncate_file(inode, 0);
}
out:
+ mutex_unlock(&(REISERFS_I(inode)->i_mmap));
mutex_unlock(&inode->i_mutex);
reiserfs_write_unlock(inode->i_sb);
return err;
}
+static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct inode *inode;
+
+ inode = file->f_path.dentry->d_inode;
+ mutex_lock(&(REISERFS_I(inode)->i_mmap));
+ REISERFS_I(inode)->i_flags |= i_ever_mapped;
+ mutex_unlock(&(REISERFS_I(inode)->i_mmap));
+
+ return generic_file_mmap(file, vma);
+}
+
static void reiserfs_vfs_truncate_file(struct inode *inode)
{
reiserfs_truncate_file(inode, 1);
@@ -1288,7 +1306,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
loff_t pos; // Current position in the file.
ssize_t res; // return value of various functions that we call.
int err = 0;
- struct inode *inode = file->f_dentry->d_inode; // Inode of the file that we are writing to.
+ struct inode *inode = file->f_path.dentry->d_inode; // Inode of the file that we are writing to.
/* To simplify coding at this time, we store
locked pages in array for now */
struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME];
@@ -1335,7 +1353,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
if (count == 0)
goto out;
- res = remove_suid(file->f_dentry);
+ res = remove_suid(file->f_path.dentry);
if (res)
goto out;
@@ -1527,7 +1545,7 @@ const struct file_operations reiserfs_file_operations = {
#ifdef CONFIG_COMPAT
.compat_ioctl = reiserfs_compat_ioctl,
#endif
- .mmap = generic_file_mmap,
+ .mmap = reiserfs_file_mmap,
.open = generic_file_open,
.release = reiserfs_file_release,
.fsync = reiserfs_sync_file,
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index 6d0e554daa9..0ee35c6c9b7 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -957,7 +957,7 @@ static int get_far_parent(struct tree_balance *p_s_tb,
{
struct buffer_head *p_s_parent;
INITIALIZE_PATH(s_path_to_neighbor_father);
- struct path *p_s_path = p_s_tb->tb_path;
+ struct treepath *p_s_path = p_s_tb->tb_path;
struct cpu_key s_lr_father_key;
int n_counter,
n_position = INT_MAX,
@@ -1074,7 +1074,7 @@ static int get_far_parent(struct tree_balance *p_s_tb,
*/
static int get_parents(struct tree_balance *p_s_tb, int n_h)
{
- struct path *p_s_path = p_s_tb->tb_path;
+ struct treepath *p_s_path = p_s_tb->tb_path;
int n_position,
n_ret_value,
n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
@@ -1885,7 +1885,7 @@ static int check_balance(int mode,
static int get_direct_parent(struct tree_balance *p_s_tb, int n_h)
{
struct buffer_head *p_s_bh;
- struct path *p_s_path = p_s_tb->tb_path;
+ struct treepath *p_s_path = p_s_tb->tb_path;
int n_position,
n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 254239e6f9e..9fcbfe31697 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -207,7 +207,7 @@ static int file_capable(struct inode *inode, long block)
}
/*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
- struct inode *inode, struct path *path)
+ struct inode *inode, struct treepath *path)
{
struct super_block *s = th->t_super;
int len = th->t_blocks_allocated;
@@ -570,7 +570,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
long block,
struct inode *inode,
b_blocknr_t * allocated_block_nr,
- struct path *path, int flags)
+ struct treepath *path, int flags)
{
BUG_ON(!th->t_trans_id);
@@ -1107,7 +1107,7 @@ static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size)
//
// called by read_locked_inode
-static void init_inode(struct inode *inode, struct path *path)
+static void init_inode(struct inode *inode, struct treepath *path)
{
struct buffer_head *bh;
struct item_head *ih;
@@ -1125,6 +1125,7 @@ static void init_inode(struct inode *inode, struct path *path)
REISERFS_I(inode)->i_prealloc_count = 0;
REISERFS_I(inode)->i_trans_id = 0;
REISERFS_I(inode)->i_jl = NULL;
+ mutex_init(&(REISERFS_I(inode)->i_mmap));
reiserfs_init_acl_access(inode);
reiserfs_init_acl_default(inode);
reiserfs_init_xattr_rwsem(inode);
@@ -1284,7 +1285,7 @@ static void inode2sd_v1(void *sd, struct inode *inode, loff_t size)
/* NOTE, you must prepare the buffer head before sending it here,
** and then log it after the call
*/
-static void update_stat_data(struct path *path, struct inode *inode,
+static void update_stat_data(struct treepath *path, struct inode *inode,
loff_t size)
{
struct buffer_head *bh;
@@ -1653,7 +1654,7 @@ int reiserfs_write_inode(struct inode *inode, int do_sync)
containing "." and ".." entries */
static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
struct inode *inode,
- struct item_head *ih, struct path *path,
+ struct item_head *ih, struct treepath *path,
struct inode *dir)
{
struct super_block *sb = th->t_super;
@@ -1712,7 +1713,7 @@ static int reiserfs_new_directory(struct reiserfs_transaction_handle *th,
containing the body of symlink */
static int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, struct inode *inode, /* Inode of symlink */
struct item_head *ih,
- struct path *path, const char *symname,
+ struct treepath *path, const char *symname,
int item_len)
{
struct super_block *sb = th->t_super;
@@ -1832,6 +1833,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
REISERFS_I(inode)->i_attrs =
REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
+ mutex_init(&(REISERFS_I(inode)->i_mmap));
reiserfs_init_acl_access(inode);
reiserfs_init_acl_default(inode);
reiserfs_init_xattr_rwsem(inode);
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 9c57578cb83..b484d2913c0 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -99,7 +99,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int ret;
/* These are just misnamed, they actually get/put from/to user an int */
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index abde1edc223..23f5cd5bbf5 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -54,7 +54,7 @@ static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off)
// comment? maybe something like set de to point to what the path points to?
static inline void set_de_item_location(struct reiserfs_dir_entry *de,
- struct path *path)
+ struct treepath *path)
{
de->de_bh = get_last_bh(path);
de->de_ih = get_ih(path);
@@ -113,7 +113,7 @@ entry position in the item
/* The function is NOT SCHEDULE-SAFE! */
int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
- struct path *path, struct reiserfs_dir_entry *de)
+ struct treepath *path, struct reiserfs_dir_entry *de)
{
int retval;
@@ -282,7 +282,7 @@ static int linear_search_in_dir_item(struct cpu_key *key,
// may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
// FIXME: should add something like IOERROR
static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
- struct path *path_to_entry,
+ struct treepath *path_to_entry,
struct reiserfs_dir_entry *de)
{
struct cpu_key key_to_search;
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index c533ec1bcae..ecc9943202f 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -295,7 +295,7 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb)
}
#if defined( REISERFS_USE_OIDMAPF )
if (sb_info->oidmap.use_file && (sb_info->oidmap.mapf != NULL)) {
- loff_t size = sb_info->oidmap.mapf->f_dentry->d_inode->i_size;
+ loff_t size = sb_info->oidmap.mapf->f_path.dentry->d_inode->i_size;
total_used += size / sizeof(reiserfs_oidinterval_d_t);
}
#endif
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 5240abe1a70..afb21ea4530 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -244,7 +244,7 @@ static const struct reiserfs_key MAX_KEY = {
of the path, and going upwards. We must check the path's validity at each step. If the key is not in
the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this
case we return a special key, either MIN_KEY or MAX_KEY. */
-static inline const struct reiserfs_key *get_lkey(const struct path
+static inline const struct reiserfs_key *get_lkey(const struct treepath
*p_s_chk_path,
const struct super_block
*p_s_sb)
@@ -290,7 +290,7 @@ static inline const struct reiserfs_key *get_lkey(const struct path
}
/* Get delimiting key of the buffer at the path and its right neighbor. */
-inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
+inline const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
const struct super_block *p_s_sb)
{
int n_position, n_path_offset = p_s_chk_path->path_length;
@@ -337,7 +337,7 @@ inline const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
the path. These delimiting keys are stored at least one level above that buffer in the tree. If the
buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
-static inline int key_in_buffer(struct path *p_s_chk_path, /* Path which should be checked. */
+static inline int key_in_buffer(struct treepath *p_s_chk_path, /* Path which should be checked. */
const struct cpu_key *p_s_key, /* Key which should be checked. */
struct super_block *p_s_sb /* Super block pointer. */
)
@@ -374,7 +374,7 @@ inline void decrement_bcount(struct buffer_head *p_s_bh)
}
/* Decrement b_count field of the all buffers in the path. */
-void decrement_counters_in_path(struct path *p_s_search_path)
+void decrement_counters_in_path(struct treepath *p_s_search_path)
{
int n_path_offset = p_s_search_path->path_length;
@@ -391,7 +391,7 @@ void decrement_counters_in_path(struct path *p_s_search_path)
p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
}
-int reiserfs_check_path(struct path *p)
+int reiserfs_check_path(struct treepath *p)
{
RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET,
"path not properly relsed");
@@ -403,7 +403,7 @@ int reiserfs_check_path(struct path *p)
**
** only called from fix_nodes()
*/
-void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path)
+void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path)
{
int n_path_offset = p_s_search_path->path_length;
@@ -421,7 +421,7 @@ void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path)
}
/* Release all buffers in the path. */
-void pathrelse(struct path *p_s_search_path)
+void pathrelse(struct treepath *p_s_search_path)
{
int n_path_offset = p_s_search_path->path_length;
@@ -602,7 +602,7 @@ static void search_by_key_reada(struct super_block *s,
correctness of the bottom of the path */
/* The function is NOT SCHEDULE-SAFE! */
int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /* Key to search. */
- struct path *p_s_search_path, /* This structure was
+ struct treepath *p_s_search_path,/* This structure was
allocated and initialized
by the calling
function. It is filled up
@@ -813,7 +813,7 @@ int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key, /*
/* The function is NOT SCHEDULE-SAFE! */
int search_for_position_by_key(struct super_block *p_s_sb, /* Pointer to the super block. */
const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */
- struct path *p_s_search_path /* Filled up by this function. */
+ struct treepath *p_s_search_path /* Filled up by this function. */
)
{
struct item_head *p_le_ih; /* pointer to on-disk structure */
@@ -884,7 +884,7 @@ int search_for_position_by_key(struct super_block *p_s_sb, /* Pointer to the sup
}
/* Compare given item and item pointed to by the path. */
-int comp_items(const struct item_head *stored_ih, const struct path *p_s_path)
+int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path)
{
struct buffer_head *p_s_bh;
struct item_head *ih;
@@ -911,7 +911,7 @@ int comp_items(const struct item_head *stored_ih, const struct path *p_s_path)
#define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh)))
// prepare for delete or cut of direct item
-static inline int prepare_for_direct_item(struct path *path,
+static inline int prepare_for_direct_item(struct treepath *path,
struct item_head *le_ih,
struct inode *inode,
loff_t new_file_length, int *cut_size)
@@ -952,7 +952,7 @@ static inline int prepare_for_direct_item(struct path *path,
return M_CUT; /* Cut from this item. */
}
-static inline int prepare_for_direntry_item(struct path *path,
+static inline int prepare_for_direntry_item(struct treepath *path,
struct item_head *le_ih,
struct inode *inode,
loff_t new_file_length,
@@ -987,7 +987,7 @@ static inline int prepare_for_direntry_item(struct path *path,
In case of file truncate calculate whether this item must be deleted/truncated or last
unformatted node of this item will be converted to a direct item.
This function returns a determination of what balance mode the calling function should employ. */
-static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct path *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed, /* Number of unformatted nodes which were removed
+static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed, /* Number of unformatted nodes which were removed
from end of the file. */
int *p_n_cut_size, unsigned long long n_new_file_length /* MAX_KEY_OFFSET in case of delete. */
)
@@ -1125,7 +1125,7 @@ static int calc_deleted_bytes_number(struct tree_balance *p_s_tb, char c_mode)
static void init_tb_struct(struct reiserfs_transaction_handle *th,
struct tree_balance *p_s_tb,
struct super_block *p_s_sb,
- struct path *p_s_path, int n_size)
+ struct treepath *p_s_path, int n_size)
{
BUG_ON(!th->t_trans_id);
@@ -1176,7 +1176,7 @@ char head2type(struct item_head *ih)
#endif
/* Delete object item. */
-int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct path *p_s_path, /* Path to the deleted item. */
+int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path, /* Path to the deleted item. */
const struct cpu_key *p_s_item_key, /* Key to search for the deleted item. */
struct inode *p_s_inode, /* inode is here just to update i_blocks and quotas */
struct buffer_head *p_s_un_bh)
@@ -1459,7 +1459,7 @@ static void unmap_buffers(struct page *page, loff_t pos)
bh = next;
} while (bh != head);
if (PAGE_SIZE == bh->b_size) {
- clear_page_dirty(page);
+ cancel_dirty_page(page, PAGE_CACHE_SIZE);
}
}
}
@@ -1468,7 +1468,7 @@ static void unmap_buffers(struct page *page, loff_t pos)
static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
struct inode *p_s_inode,
struct page *page,
- struct path *p_s_path,
+ struct treepath *p_s_path,
const struct cpu_key *p_s_item_key,
loff_t n_new_file_size, char *p_c_mode)
{
@@ -1503,7 +1503,7 @@ static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
pointer being converted. Therefore we have to delete inserted
direct item(s) */
static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
- struct inode *inode, struct path *path)
+ struct inode *inode, struct treepath *path)
{
struct cpu_key tail_key;
int tail_len;
@@ -1545,7 +1545,7 @@ static void indirect_to_direct_roll_back(struct reiserfs_transaction_handle *th,
/* (Truncate or cut entry) or delete object item. Returns < 0 on failure */
int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
- struct path *p_s_path,
+ struct treepath *p_s_path,
struct cpu_key *p_s_item_key,
struct inode *p_s_inode,
struct page *page, loff_t n_new_file_size)
@@ -1920,7 +1920,7 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p
#ifdef CONFIG_REISERFS_CHECK
// this makes sure, that we __append__, not overwrite or add holes
-static void check_research_for_paste(struct path *path,
+static void check_research_for_paste(struct treepath *path,
const struct cpu_key *p_s_key)
{
struct item_head *found_ih = get_ih(path);
@@ -1954,7 +1954,7 @@ static void check_research_for_paste(struct path *path,
#endif /* config reiserfs check */
/* Paste bytes to the existing item. Returns bytes number pasted into the item. */
-int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path *p_s_search_path, /* Path to the pasted item. */
+int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_search_path, /* Path to the pasted item. */
const struct cpu_key *p_s_key, /* Key to search for the needed item. */
struct inode *inode, /* Inode item belongs to */
const char *p_c_body, /* Pointer to the bytes to paste. */
@@ -2036,7 +2036,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct path
}
/* Insert new item into the buffer at the path. */
-int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct path *p_s_path, /* Path to the inserteded item. */
+int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path, /* Path to the inserteded item. */
const struct cpu_key *key, struct item_head *p_s_ih, /* Pointer to the item header to insert. */
struct inode *inode, const char *p_c_body)
{ /* Pointer to the bytes to insert. */
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 7fb5fb036f9..58ad4551a7c 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -23,7 +23,7 @@
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/vfs.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/quotaops.h>
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index 36f108fc1cf..f8121a1147e 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -15,7 +15,7 @@
/* path points to first direct item of the file regarless of how many of
them are there */
int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
- struct path *path, struct buffer_head *unbh,
+ struct treepath *path, struct buffer_head *unbh,
loff_t tail_offset)
{
struct super_block *sb = inode->i_sb;
@@ -171,7 +171,7 @@ void reiserfs_unmap_buffer(struct buffer_head *bh)
what we expect from it (number of cut bytes). But when tail remains
in the unformatted node, we set mode to SKIP_BALANCING and unlock
inode */
-int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct path *p_s_path, /* path to the indirect item. */
+int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct treepath *p_s_path, /* path to the indirect item. */
const struct cpu_key *p_s_item_key, /* Key to look for unformatted node pointer to be cut. */
loff_t n_new_file_size, /* New file size. */
char *p_c_mode)
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 1e4d6859017..f01389fd162 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -274,7 +274,7 @@ static struct file *open_xa_file(const struct inode *inode, const char *name,
*/
static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */
INITIALIZE_PATH(path_to_entry);
struct buffer_head *bh;
@@ -420,7 +420,7 @@ static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
static
int xattr_readdir(struct file *file, filldir_t filler, void *buf)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int res = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
goto out;
@@ -508,7 +508,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
goto out;
}
- xinode = fp->f_dentry->d_inode;
+ xinode = fp->f_path.dentry->d_inode;
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
/* we need to copy it off.. */
@@ -527,7 +527,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
newattrs.ia_size = buffer_size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
mutex_lock(&xinode->i_mutex);
- err = notify_change(fp->f_dentry, &newattrs);
+ err = notify_change(fp->f_path.dentry, &newattrs);
if (err)
goto out_filp;
@@ -626,7 +626,7 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
goto out;
}
- xinode = fp->f_dentry->d_inode;
+ xinode = fp->f_path.dentry->d_inode;
isize = xinode->i_size;
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 97ae1b92bc4..5296a29cc5e 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -135,7 +135,7 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
int n;
*size = reiserfs_acl_size(acl->a_count);
- ext_acl = (reiserfs_acl_header *) kmalloc(sizeof(reiserfs_acl_header) +
+ ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
acl->a_count *
sizeof(reiserfs_acl_entry),
GFP_NOFS);
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index c5af088d4a4..d3e243a6f60 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -276,7 +276,7 @@ static unsigned char romfs_dtype_table[] = {
static int
romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *i = filp->f_dentry->d_inode;
+ struct inode *i = filp->f_path.dentry->d_inode;
struct romfs_inode ri;
unsigned long offset, maxoff;
int j, ino, nextfh;
diff --git a/fs/select.c b/fs/select.c
index dcbc1112b7e..fe0893afd93 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -311,7 +311,7 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
{
fd_set_bits fds;
void *bits;
- int ret, max_fdset;
+ int ret, max_fds;
unsigned int size;
struct fdtable *fdt;
/* Allocate small arguments on the stack to save memory and be faster */
@@ -321,13 +321,13 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
if (n < 0)
goto out_nofds;
- /* max_fdset can increase, so grab it once to avoid race */
+ /* max_fds can increase, so grab it once to avoid race */
rcu_read_lock();
fdt = files_fdtable(current->files);
- max_fdset = fdt->max_fdset;
+ max_fds = fdt->max_fds;
rcu_read_unlock();
- if (n > max_fdset)
- n = max_fdset;
+ if (n > max_fds)
+ n = max_fds;
/*
* We need 6 bitmaps (in/out/ex for both incoming and outgoing),
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 10690aa401c..0ac22af7afe 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -269,7 +269,7 @@ EXPORT_SYMBOL(seq_lseek);
/**
* seq_release - free the structures associated with sequential file.
* @file: file in question
- * @inode: file->f_dentry->d_inode
+ * @inode: file->f_path.dentry->d_inode
*
* Frees the structures associated with sequential file; can be used
* as ->f_op->release() if you don't have private data to destroy.
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index 74b86d9725a..8182f0542a2 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -125,7 +125,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
struct smb_cache_control *ctrl, struct qstr *qname,
struct smb_fattr *entry)
{
- struct dentry *newdent, *dentry = filp->f_dentry;
+ struct dentry *newdent, *dentry = filp->f_path.dentry;
struct inode *newino, *inode = dentry->d_inode;
struct smb_cache_control ctl = *ctrl;
int valid = 0;
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 70d9c5a37f5..b1e58d1ac9c 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -78,7 +78,7 @@ struct inode_operations smb_dir_inode_operations_unix =
static int
smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct inode *dir = dentry->d_inode;
struct smb_sb_info *server = server_from_dentry(dentry);
union smb_dir_cache *cache = NULL;
@@ -238,12 +238,12 @@ out:
static int
smb_dir_open(struct inode *dir, struct file *file)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct smb_sb_info *server;
int error = 0;
VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
- file->f_dentry->d_name.name);
+ file->f_path.dentry->d_name.name);
/*
* Directory timestamps in the core protocol aren't updated
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 50784d13c87..e50533a7951 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -102,7 +102,7 @@ static int
smb_readpage(struct file *file, struct page *page)
{
int error;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
page_cache_get(page);
error = smb_readpage_sync(dentry, page);
@@ -205,7 +205,7 @@ static int
smb_updatepage(struct file *file, struct page *page, unsigned long offset,
unsigned int count)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
@@ -218,7 +218,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
struct file * file = iocb->ki_filp;
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
ssize_t status;
VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
@@ -243,7 +243,7 @@ out:
static int
smb_file_mmap(struct file * file, struct vm_area_struct * vma)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
int status;
VERBOSE("file %s/%s, address %lu - %lu\n",
@@ -264,7 +264,7 @@ static ssize_t
smb_file_sendfile(struct file *file, loff_t *ppos,
size_t count, read_actor_t actor, void *target)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
ssize_t status;
VERBOSE("file %s/%s, pos=%Ld, count=%d\n",
@@ -323,7 +323,7 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
struct file * file = iocb->ki_filp;
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
ssize_t result;
VERBOSE("file %s/%s, count=%lu@%lu\n",
@@ -355,7 +355,7 @@ static int
smb_file_open(struct inode *inode, struct file * file)
{
int result;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int smb_mode = (file->f_mode & O_ACCMODE) - 1;
lock_kernel();
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 4af4cd729a5..84dfe3f3482 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -482,12 +482,13 @@ smb_put_super(struct super_block *sb)
smb_close_socket(server);
if (server->conn_pid)
- kill_proc(server->conn_pid, SIGTERM, 1);
+ kill_pid(server->conn_pid, SIGTERM, 1);
kfree(server->ops);
smb_unload_nls(server);
sb->s_fs_info = NULL;
smb_unlock_server(server);
+ put_pid(server->conn_pid);
kfree(server);
}
@@ -530,7 +531,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
INIT_LIST_HEAD(&server->xmitq);
INIT_LIST_HEAD(&server->recvq);
server->conn_error = 0;
- server->conn_pid = 0;
+ server->conn_pid = NULL;
server->state = CONN_INVALID; /* no connection yet */
server->generation = 0;
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 40e174db987..feac4605061 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -873,11 +873,11 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
filp = fget(opt->fd);
if (!filp)
goto out;
- if (!smb_valid_socket(filp->f_dentry->d_inode))
+ if (!smb_valid_socket(filp->f_path.dentry->d_inode))
goto out_putf;
server->sock_file = filp;
- server->conn_pid = current->pid;
+ server->conn_pid = get_pid(task_pid(current));
server->opt = *opt;
server->generation += 1;
server->state = CONN_VALID;
@@ -898,7 +898,7 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
/*
* Store the server in sock user_data (Only used by sunrpc)
*/
- sk = SOCKET_I(filp->f_dentry->d_inode)->sk;
+ sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk;
sk->sk_user_data = server;
/* chain into the data_ready callback */
@@ -971,8 +971,8 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
}
VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
- server->opt.protocol, server->opt.max_xmit, server->conn_pid,
- server->opt.capabilities);
+ server->opt.protocol, server->opt.max_xmit,
+ pid_nr(server->conn_pid), server->opt.capabilities);
/* FIXME: this really should be done by smbmount. */
if (server->opt.max_xmit > SMB_MAX_PACKET_SIZE) {
@@ -1939,7 +1939,7 @@ static int
smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
struct smb_cache_control *ctl)
{
- struct dentry *dir = filp->f_dentry;
+ struct dentry *dir = filp->f_path.dentry;
struct smb_sb_info *server = server_from_dentry(dir);
struct qstr qname;
struct smb_fattr fattr;
@@ -2291,7 +2291,7 @@ static int
smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
struct smb_cache_control *ctl)
{
- struct dentry *dir = filp->f_dentry;
+ struct dentry *dir = filp->f_path.dentry;
struct smb_sb_info *server = server_from_dentry(dir);
struct qstr qname;
struct smb_fattr fattr;
@@ -2859,7 +2859,7 @@ static int
smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir,
struct smb_cache_control *ctl)
{
- struct smb_sb_info *server = server_from_dentry(filp->f_dentry);
+ struct smb_sb_info *server = server_from_dentry(filp->f_path.dentry);
if (smb_proc_ops_wait(server) < 0)
return -EIO;
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
index e6754044128..89eaf31f1d4 100644
--- a/fs/smbfs/smbiod.c
+++ b/fs/smbfs/smbiod.c
@@ -152,7 +152,7 @@ int smbiod_retry(struct smb_sb_info *server)
{
struct list_head *head;
struct smb_request *req;
- pid_t pid = server->conn_pid;
+ struct pid *pid = get_pid(server->conn_pid);
int result = 0;
VERBOSE("state: %d\n", server->state);
@@ -222,7 +222,7 @@ int smbiod_retry(struct smb_sb_info *server)
/*
* Note: use the "priv" flag, as a user process may need to reconnect.
*/
- result = kill_proc(pid, SIGUSR1, 1);
+ result = kill_pid(pid, SIGUSR1, 1);
if (result) {
/* FIXME: this is most likely fatal, umount? */
printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
@@ -233,6 +233,7 @@ int smbiod_retry(struct smb_sb_info *server)
/* FIXME: The retried requests should perhaps get a "time boost". */
out:
+ put_pid(pid);
return result;
}
diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c
index 6815b1b12b6..92ea6b2367d 100644
--- a/fs/smbfs/sock.c
+++ b/fs/smbfs/sock.c
@@ -82,10 +82,10 @@ server_sock(struct smb_sb_info *server)
if (server && (file = server->sock_file))
{
#ifdef SMBFS_PARANOIA
- if (!smb_valid_socket(file->f_dentry->d_inode))
+ if (!smb_valid_socket(file->f_path.dentry->d_inode))
PARANOIA("bad socket!\n");
#endif
- return SOCKET_I(file->f_dentry->d_inode);
+ return SOCKET_I(file->f_path.dentry->d_inode);
}
return NULL;
}
diff --git a/fs/splice.c b/fs/splice.c
index da74583a00e..2fca6ebf4cc 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -42,7 +42,7 @@ struct splice_pipe_desc {
struct partial_page *partial; /* pages[] may not be contig */
int nr_pages; /* number of pages in map */
unsigned int flags; /* splice flags */
- struct pipe_buf_operations *ops;/* ops associated with output pipe */
+ const struct pipe_buf_operations *ops;/* ops associated with output pipe */
};
/*
@@ -139,7 +139,7 @@ error:
return err;
}
-static struct pipe_buf_operations page_cache_pipe_buf_ops = {
+static const struct pipe_buf_operations page_cache_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
@@ -159,7 +159,7 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
return generic_pipe_buf_steal(pipe, buf);
}
-static struct pipe_buf_operations user_page_pipe_buf_ops = {
+static const struct pipe_buf_operations user_page_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
@@ -724,7 +724,7 @@ static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
for (;;) {
if (pipe->nrbufs) {
struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
- struct pipe_buf_operations *ops = buf->ops;
+ const struct pipe_buf_operations *ops = buf->ops;
sd.len = buf->len;
if (sd.len > sd.total_len)
@@ -844,7 +844,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
ssize_t ret;
int err;
- err = remove_suid(out->f_dentry);
+ err = remove_suid(out->f_path.dentry);
if (unlikely(err))
return err;
@@ -890,10 +890,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
ssize_t ret;
int err;
- err = should_remove_suid(out->f_dentry);
+ err = should_remove_suid(out->f_path.dentry);
if (unlikely(err)) {
mutex_lock(&inode->i_mutex);
- err = __remove_suid(out->f_dentry, err);
+ err = __remove_suid(out->f_path.dentry, err);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
@@ -1008,7 +1008,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
* randomly drop data for eg socket -> socket splicing. Use the
* piped splicing for that!
*/
- i_mode = in->f_dentry->d_inode->i_mode;
+ i_mode = in->f_path.dentry->d_inode->i_mode;
if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
return -EINVAL;
@@ -1132,7 +1132,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
loff_t offset, *off;
long ret;
- pipe = pipe_info(in->f_dentry->d_inode);
+ pipe = pipe_info(in->f_path.dentry->d_inode);
if (pipe) {
if (off_in)
return -ESPIPE;
@@ -1153,7 +1153,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
return ret;
}
- pipe = pipe_info(out->f_dentry->d_inode);
+ pipe = pipe_info(out->f_path.dentry->d_inode);
if (pipe) {
if (off_out)
return -ESPIPE;
@@ -1321,7 +1321,7 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
.ops = &user_page_pipe_buf_ops,
};
- pipe = pipe_info(file->f_dentry->d_inode);
+ pipe = pipe_info(file->f_path.dentry->d_inode);
if (!pipe)
return -EBADF;
if (unlikely(nr_segs > UIO_MAXIOV))
@@ -1549,8 +1549,8 @@ static int link_pipe(struct pipe_inode_info *ipipe,
static long do_tee(struct file *in, struct file *out, size_t len,
unsigned int flags)
{
- struct pipe_inode_info *ipipe = pipe_info(in->f_dentry->d_inode);
- struct pipe_inode_info *opipe = pipe_info(out->f_dentry->d_inode);
+ struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode);
+ struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode);
int ret = -EINVAL;
/*
diff --git a/fs/stack.c b/fs/stack.c
new file mode 100644
index 00000000000..8ffb880d2f4
--- /dev/null
+++ b/fs/stack.c
@@ -0,0 +1,38 @@
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/fs_stack.h>
+
+/* does _NOT_ require i_mutex to be held.
+ *
+ * This function cannot be inlined since i_size_{read,write} is rather
+ * heavy-weight on 32-bit systems
+ */
+void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
+{
+ i_size_write(dst, i_size_read((struct inode *)src));
+ dst->i_blocks = src->i_blocks;
+}
+EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
+
+/* copy all attributes; get_nlinks is optional way to override the i_nlink
+ * copying
+ */
+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+ int (*get_nlinks)(struct inode *))
+{
+ if (!get_nlinks)
+ dest->i_nlink = src->i_nlink;
+ else
+ dest->i_nlink = (*get_nlinks)(dest);
+
+ dest->i_mode = src->i_mode;
+ dest->i_uid = src->i_uid;
+ dest->i_gid = src->i_gid;
+ dest->i_rdev = src->i_rdev;
+ dest->i_atime = src->i_atime;
+ dest->i_mtime = src->i_mtime;
+ dest->i_ctime = src->i_ctime;
+ dest->i_blkbits = src->i_blkbits;
+ dest->i_flags = src->i_flags;
+}
+EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/fs/stat.c b/fs/stat.c
index a0ebfc7f8a6..38a8cb2a28d 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -102,7 +102,7 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
int error = -EBADF;
if (f) {
- error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
+ error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
fput(f);
}
return error;
diff --git a/fs/super.c b/fs/super.c
index 84c320f6ad7..3e7458c2bb7 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -570,7 +570,7 @@ static void mark_files_ro(struct super_block *sb)
file_list_lock();
list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
- if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f))
+ if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f))
f->f_mode &= ~FMODE_WRITE;
}
file_list_unlock();
@@ -753,9 +753,9 @@ int get_sb_bdev(struct file_system_type *fs_type,
* will protect the lockfs code from trying to start a snapshot
* while we are mounting
*/
- mutex_lock(&bdev->bd_mount_mutex);
+ down(&bdev->bd_mount_sem);
s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
- mutex_unlock(&bdev->bd_mount_mutex);
+ up(&bdev->bd_mount_sem);
if (IS_ERR(s))
goto error_s;
diff --git a/fs/sync.c b/fs/sync.c
index 865f32be386..d0feff61e6a 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -94,7 +94,7 @@ long do_fsync(struct file *file, int datasync)
* livelocks in fsync_buffers_list().
*/
mutex_lock(&mapping->host->i_mutex);
- err = file->f_op->fsync(file, file->f_dentry, datasync);
+ err = file->f_op->fsync(file, file->f_path.dentry, datasync);
if (!ret)
ret = err;
mutex_unlock(&mapping->host->i_mutex);
@@ -223,7 +223,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
if (!file)
goto out;
- i_mode = file->f_dentry->d_inode->i_mode;
+ i_mode = file->f_path.dentry->d_inode->i_mode;
ret = -ESPIPE;
if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
!S_ISLNK(i_mode))
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 98022e41cda..e8f540d38d4 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -35,7 +35,7 @@ static ssize_t
read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
char *buffer = file->private_data;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
int ret;
@@ -81,7 +81,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
size_t count, loff_t * off)
{
char *buffer = file->private_data;
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
@@ -105,7 +105,7 @@ static ssize_t write(struct file * file, const char __user * userbuf,
static int mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct bin_attribute *attr = to_bin_attr(dentry);
struct kobject *kobj = to_kobj(dentry->d_parent);
@@ -117,8 +117,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
static int open(struct inode * inode, struct file * file)
{
- struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
- struct bin_attribute * attr = to_bin_attr(file->f_dentry);
+ struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+ struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
int error = -EINVAL;
if (!kobj || !attr)
@@ -153,8 +153,8 @@ static int open(struct inode * inode, struct file * file)
static int release(struct inode * inode, struct file * file)
{
- struct kobject * kobj = to_kobj(file->f_dentry->d_parent);
- struct bin_attribute * attr = to_bin_attr(file->f_dentry);
+ struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
+ struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
u8 * buffer = file->private_data;
if (kobj)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index a5782e8c7f0..511edef8b32 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -419,7 +419,7 @@ out:
static int sysfs_dir_open(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
mutex_lock(&dentry->d_inode->i_mutex);
@@ -432,7 +432,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
static int sysfs_dir_close(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
struct sysfs_dirent * cursor = file->private_data;
mutex_lock(&dentry->d_inode->i_mutex);
@@ -452,7 +452,7 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- struct dentry *dentry = filp->f_dentry;
+ struct dentry *dentry = filp->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
struct sysfs_dirent *cursor = filp->private_data;
struct list_head *p, *q = &cursor->s_sibling;
@@ -509,7 +509,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
{
- struct dentry * dentry = file->f_dentry;
+ struct dentry * dentry = file->f_path.dentry;
mutex_lock(&dentry->d_inode->i_mutex);
switch (origin) {
@@ -519,7 +519,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 95c165101c9..9cfe53e1e00 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -154,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
down(&buffer->sem);
if (buffer->needs_read_fill) {
- if ((retval = fill_read_buffer(file->f_dentry,buffer)))
+ if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
goto out;
}
pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -245,7 +245,7 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
down(&buffer->sem);
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
- len = flush_write_buffer(file->f_dentry, buffer, len);
+ len = flush_write_buffer(file->f_path.dentry, buffer, len);
if (len > 0)
*ppos += len;
up(&buffer->sem);
@@ -254,8 +254,8 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
static int check_perm(struct inode * inode, struct file * file)
{
- struct kobject *kobj = sysfs_get_kobject(file->f_dentry->d_parent);
- struct attribute * attr = to_attr(file->f_dentry);
+ struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
+ struct attribute * attr = to_attr(file->f_path.dentry);
struct sysfs_buffer * buffer;
struct sysfs_ops * ops = NULL;
int error = 0;
@@ -337,8 +337,8 @@ static int sysfs_open_file(struct inode * inode, struct file * filp)
static int sysfs_release(struct inode * inode, struct file * filp)
{
- struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
- struct attribute * attr = to_attr(filp->f_dentry);
+ struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
+ struct attribute * attr = to_attr(filp->f_path.dentry);
struct module * owner = attr->owner;
struct sysfs_buffer * buffer = filp->private_data;
@@ -372,8 +372,8 @@ static int sysfs_release(struct inode * inode, struct file * filp)
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
{
struct sysfs_buffer * buffer = filp->private_data;
- struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
- struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
+ struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
+ struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
int res = 0;
poll_wait(filp, &kobj->poll, wait);
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index f2bef962d30..ebf7007fa16 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -70,7 +70,7 @@ fail:
static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned long pos = filp->f_pos;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
unsigned offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT;
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index dc9e7dc07fb..6f9707a1b95 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -528,9 +528,6 @@ static struct file_system_type v7_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
-extern int sysv_init_icache(void) __init;
-extern void sysv_destroy_icache(void);
-
static int __init init_sysv_fs(void)
{
int error;
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 9dcc8212093..dcb18b2171f 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -143,6 +143,9 @@ extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *, int);
extern void sysv_set_inode(struct inode *, dev_t);
extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int sysv_init_icache(void);
+extern void sysv_destroy_icache(void);
+
/* dir.c */
extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **);
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 8c28efa3b8f..2391c9150c4 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -77,7 +77,7 @@ const struct file_operations udf_dir_operations = {
int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *dir = filp->f_dentry->d_inode;
+ struct inode *dir = filp->f_path.dentry->d_inode;
int result;
lock_kernel();
@@ -225,7 +225,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
if ( cfi.fileCharacteristics & FID_FILE_CHAR_PARENT )
{
- iblock = parent_ino(filp->f_dentry);
+ iblock = parent_ino(filp->f_path.dentry);
flen = 2;
memcpy(fname, "..", flen);
dt_type = DT_DIR;
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 7aedd552cba..d81f2db7b0e 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -108,7 +108,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
{
ssize_t retval;
struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int err, pos;
size_t count = iocb->ki_left;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index b8238147577..638f4c585e8 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -227,24 +227,27 @@ failed:
* We can come here from ufs_writepage or ufs_prepare_write,
* locked_page is argument of these functions, so we already lock it.
*/
-static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
+static void ufs_change_blocknr(struct inode *inode, unsigned int beg,
unsigned int count, unsigned int oldb,
unsigned int newb, struct page *locked_page)
{
- unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- struct address_space *mapping = inode->i_mapping;
- pgoff_t index, cur_index = locked_page->index;
- unsigned int i, j;
+ const unsigned mask = (1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1;
+ struct address_space * const mapping = inode->i_mapping;
+ pgoff_t index, cur_index;
+ unsigned end, pos, j;
struct page *page;
struct buffer_head *head, *bh;
UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
inode->i_ino, count, oldb, newb);
+ BUG_ON(!locked_page);
BUG_ON(!PageLocked(locked_page));
- for (i = 0; i < count; i += blk_per_page) {
- index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ cur_index = locked_page->index;
+
+ for (end = count + beg; beg < end; beg = (beg | mask) + 1) {
+ index = beg >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
if (likely(cur_index != index)) {
page = ufs_get_locked_page(mapping, index);
@@ -253,21 +256,32 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
} else
page = locked_page;
- j = i;
head = page_buffers(page);
bh = head;
+ pos = beg & mask;
+ for (j = 0; j < pos; ++j)
+ bh = bh->b_this_page;
+ j = 0;
do {
- if (likely(bh->b_blocknr == j + oldb && j < count)) {
- unmap_underlying_metadata(bh->b_bdev,
- bh->b_blocknr);
- bh->b_blocknr = newb + j++;
- mark_buffer_dirty(bh);
+ if (buffer_mapped(bh)) {
+ pos = bh->b_blocknr - oldb;
+ if (pos < count) {
+ UFSD(" change from %llu to %llu\n",
+ (unsigned long long)pos + oldb,
+ (unsigned long long)pos + newb);
+ bh->b_blocknr = newb + pos;
+ unmap_underlying_metadata(bh->b_bdev,
+ bh->b_blocknr);
+ mark_buffer_dirty(bh);
+ ++j;
+ }
}
bh = bh->b_this_page;
} while (bh != head);
- set_page_dirty(page);
+ if (j)
+ set_page_dirty(page);
if (likely(cur_index != index))
ufs_put_locked_page(page);
@@ -275,6 +289,25 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
UFSD("EXIT\n");
}
+static void ufs_clear_frags(struct inode *inode, sector_t beg, unsigned int n,
+ int sync)
+{
+ struct buffer_head *bh;
+ sector_t end = beg + n;
+
+ for (; beg < end; ++beg) {
+ bh = sb_getblk(inode->i_sb, beg);
+ lock_buffer(bh);
+ memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ if (IS_SYNC(inode) || sync)
+ sync_dirty_buffer(bh);
+ brelse(bh);
+ }
+}
+
unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
unsigned goal, unsigned count, int * err, struct page *locked_page)
{
@@ -350,6 +383,8 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
*p = cpu_to_fs32(sb, result);
*err = 0;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
+ ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
+ locked_page != NULL);
}
unlock_super(sb);
UFSD("EXIT, result %u\n", result);
@@ -363,6 +398,8 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
if (result) {
*err = 0;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
+ ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
+ locked_page != NULL);
unlock_super(sb);
UFSD("EXIT, result %u\n", result);
return result;
@@ -392,6 +429,8 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
}
result = ufs_alloc_fragments (inode, cgno, goal, request, err);
if (result) {
+ ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
+ locked_page != NULL);
ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
result, locked_page);
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 7f0a0aa6358..433b6f68403 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -426,7 +426,7 @@ static int
ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
loff_t pos = filp->f_pos;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block *sb = inode->i_sb;
unsigned int offset = pos & ~PAGE_CACHE_MASK;
unsigned long n = pos >> PAGE_CACHE_SHIFT;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index ee1eaa6f4ec..4295ca91cf8 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -156,36 +156,6 @@ out:
return ret;
}
-static void ufs_clear_frag(struct inode *inode, struct buffer_head *bh)
-{
- lock_buffer(bh);
- memset(bh->b_data, 0, inode->i_sb->s_blocksize);
- set_buffer_uptodate(bh);
- mark_buffer_dirty(bh);
- unlock_buffer(bh);
- if (IS_SYNC(inode))
- sync_dirty_buffer(bh);
-}
-
-static struct buffer_head *
-ufs_clear_frags(struct inode *inode, sector_t beg,
- unsigned int n, sector_t want)
-{
- struct buffer_head *res = NULL, *bh;
- sector_t end = beg + n;
-
- for (; beg < end; ++beg) {
- bh = sb_getblk(inode->i_sb, beg);
- ufs_clear_frag(inode, bh);
- if (want != beg)
- brelse(bh);
- else
- res = bh;
- }
- BUG_ON(!res);
- return res;
-}
-
/**
* ufs_inode_getfrag() - allocate new fragment(s)
* @inode - pointer to inode
@@ -272,7 +242,8 @@ repeat:
goal = tmp + uspi->s_fpb;
tmp = ufs_new_fragments (inode, p, fragment - blockoff,
goal, required + blockoff,
- err, locked_page);
+ err,
+ phys != NULL ? locked_page : NULL);
}
/*
* We will extend last allocated block
@@ -280,7 +251,7 @@ repeat:
else if (lastblock == block) {
tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff),
- err, locked_page);
+ err, phys != NULL ? locked_page : NULL);
} else /* (lastblock > block) */ {
/*
* We will allocate new block before last allocated block
@@ -291,7 +262,8 @@ repeat:
goal = tmp + uspi->s_fpb;
}
tmp = ufs_new_fragments(inode, p, fragment - blockoff,
- goal, uspi->s_fpb, err, locked_page);
+ goal, uspi->s_fpb, err,
+ phys != NULL ? locked_page : NULL);
}
if (!tmp) {
if ((!blockoff && *p) ||
@@ -302,7 +274,7 @@ repeat:
}
if (!phys) {
- result = ufs_clear_frags(inode, tmp, required, tmp + blockoff);
+ result = sb_getblk(sb, tmp + blockoff);
} else {
*phys = tmp + blockoff;
result = NULL;
@@ -403,8 +375,7 @@ repeat:
if (!phys) {
- result = ufs_clear_frags(inode, tmp, uspi->s_fpb,
- tmp + blockoff);
+ result = sb_getblk(sb, tmp + blockoff);
} else {
*phys = tmp + blockoff;
*new = 1;
@@ -469,15 +440,17 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head
* it much more readable:
*/
#define GET_INODE_DATABLOCK(x) \
- ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page)
+ ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\
+ bh_result->b_page)
#define GET_INODE_PTR(x) \
- ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, bh_result->b_page)
+ ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\
+ bh_result->b_page)
#define GET_INDIRECT_DATABLOCK(x) \
ufs_inode_getblock(inode, bh, x, fragment, \
- &err, &phys, &new, bh_result->b_page);
+ &err, &phys, &new, bh_result->b_page)
#define GET_INDIRECT_PTR(x) \
ufs_inode_getblock(inode, bh, x, fragment, \
- &err, NULL, NULL, bh_result->b_page);
+ &err, NULL, NULL, NULL)
if (ptr < UFS_NDIR_FRAGMENT) {
bh = GET_INODE_DATABLOCK(ptr);
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index ea11d04c41a..0437b0a6fe9 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -109,10 +109,10 @@ static int ufs_trunc_direct (struct inode * inode)
tmp = fs32_to_cpu(sb, *p);
if (!tmp )
ufs_panic (sb, "ufs_trunc_direct", "internal error");
+ frag2 -= frag1;
frag1 = ufs_fragnum (frag1);
- frag2 = ufs_fragnum (frag2);
- ufs_free_fragments (inode, tmp + frag1, frag2 - frag1);
+ ufs_free_fragments(inode, tmp + frag1, frag2);
mark_inode_dirty(inode);
frag_to_free = tmp + frag1;
diff --git a/fs/xattr.c b/fs/xattr.c
index 0901bdc2ce2..38646132ab0 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -268,7 +268,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
f = fget(fd);
if (!f)
return error;
- dentry = f->f_dentry;
+ dentry = f->f_path.dentry;
audit_inode(NULL, dentry->d_inode);
error = setxattr(dentry, name, value, size, flags);
fput(f);
@@ -351,7 +351,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
f = fget(fd);
if (!f)
return error;
- error = getxattr(f->f_dentry, name, value, size);
+ error = getxattr(f->f_path.dentry, name, value, size);
fput(f);
return error;
}
@@ -423,7 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
f = fget(fd);
if (!f)
return error;
- error = listxattr(f->f_dentry, list, size);
+ error = listxattr(f->f_path.dentry, list, size);
fput(f);
return error;
}
@@ -484,7 +484,7 @@ sys_fremovexattr(int fd, char __user *name)
f = fget(fd);
if (!f)
return error;
- dentry = f->f_dentry;
+ dentry = f->f_path.dentry;
audit_inode(NULL, dentry->d_inode);
error = removexattr(dentry, name);
fput(f);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 8e6b56fc1ca..7b54461695e 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -341,9 +341,9 @@ xfs_start_page_writeback(
{
ASSERT(PageLocked(page));
ASSERT(!PageWriteback(page));
- set_page_writeback(page);
if (clear_dirty)
- clear_page_dirty(page);
+ clear_page_dirty_for_io(page);
+ set_page_writeback(page);
unlock_page(page);
if (!buffers) {
end_page_writeback(page);
@@ -1406,7 +1406,7 @@ xfs_vm_direct_IO(
xfs_end_io_direct);
}
- if (unlikely(ret <= 0 && iocb->private))
+ if (unlikely(ret != -EIOCBQUEUED && iocb->private))
xfs_destroy_ioend(iocb->private);
return ret;
}
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index d93d8dd1958..d26f5cd2ba7 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -55,7 +55,7 @@ __xfs_file_read(
loff_t pos)
{
struct file *file = iocb->ki_filp;
- bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode);
+ bhv_vnode_t *vp = vn_from_inode(file->f_path.dentry->d_inode);
BUG_ON(iocb->ki_pos != pos);
if (unlikely(file->f_flags & O_DIRECT))
@@ -131,7 +131,7 @@ xfs_file_sendfile(
read_actor_t actor,
void *target)
{
- return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
+ return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
filp, pos, 0, count, actor, target, NULL);
}
@@ -143,7 +143,7 @@ xfs_file_sendfile_invis(
read_actor_t actor,
void *target)
{
- return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
+ return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
filp, pos, IO_INVIS, count, actor, target, NULL);
}
@@ -155,7 +155,7 @@ xfs_file_splice_read(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
+ return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
infilp, ppos, pipe, len, flags, 0, NULL);
}
@@ -167,7 +167,7 @@ xfs_file_splice_read_invis(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
+ return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
infilp, ppos, pipe, len, flags, IO_INVIS,
NULL);
}
@@ -180,7 +180,7 @@ xfs_file_splice_write(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
+ return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
pipe, outfilp, ppos, len, flags, 0, NULL);
}
@@ -192,7 +192,7 @@ xfs_file_splice_write_invis(
size_t len,
unsigned int flags)
{
- return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
+ return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
pipe, outfilp, ppos, len, flags, IO_INVIS,
NULL);
}
@@ -212,7 +212,7 @@ xfs_file_close(
struct file *filp,
fl_owner_t id)
{
- return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0,
+ return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0,
file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
}
@@ -251,7 +251,7 @@ xfs_vm_nopage(
unsigned long address,
int *type)
{
- struct inode *inode = area->vm_file->f_dentry->d_inode;
+ struct inode *inode = area->vm_file->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
@@ -268,7 +268,7 @@ xfs_file_readdir(
filldir_t filldir)
{
int error = 0;
- bhv_vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode);
+ bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode);
uio_t uio;
iovec_t iov;
int eof = 0;
@@ -345,7 +345,7 @@ xfs_file_mmap(
vma->vm_ops = &xfs_file_vm_ops;
#ifdef CONFIG_XFS_DMAPI
- if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
+ if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
vma->vm_ops = &xfs_dmapi_file_vm_ops;
#endif /* CONFIG_XFS_DMAPI */
@@ -360,7 +360,7 @@ xfs_file_ioctl(
unsigned long p)
{
int error;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
@@ -382,7 +382,7 @@ xfs_file_ioctl_invis(
unsigned long p)
{
int error;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
@@ -404,7 +404,7 @@ xfs_vm_mprotect(
struct vm_area_struct *vma,
unsigned int newflags)
{
- bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
+ bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode);
int error = 0;
if (vp->v_vfsp->vfs_flag & VFS_DMI) {
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 74d094829a4..f011c9cd0d6 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -107,9 +107,9 @@ xfs_find_handle(
if (!file)
return -EBADF;
- ASSERT(file->f_dentry);
- ASSERT(file->f_dentry->d_inode);
- inode = igrab(file->f_dentry->d_inode);
+ ASSERT(file->f_path.dentry);
+ ASSERT(file->f_path.dentry->d_inode);
+ inode = igrab(file->f_path.dentry->d_inode);
fput(file);
break;
}
@@ -333,10 +333,10 @@ xfs_open_by_handle(
}
/* Ensure umount returns EBUSY on umounts while this file is open. */
- mntget(parfilp->f_vfsmnt);
+ mntget(parfilp->f_path.mnt);
/* Create file pointer. */
- filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags);
+ filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags);
if (IS_ERR(filp)) {
put_unused_fd(new_fd);
return -XFS_ERROR(-PTR_ERR(filp));
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 270db0f3861..b83cebc165f 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -112,7 +112,7 @@ xfs_compat_ioctl(
unsigned cmd,
unsigned long arg)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
int error;
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index fa842f1c9fa..65e79b471d4 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -805,7 +805,7 @@ start:
!capable(CAP_FSETID)) {
error = xfs_write_clear_setuid(xip);
if (likely(!error))
- error = -remove_suid(file->f_dentry);
+ error = -remove_suid(file->f_path.dentry);
if (unlikely(error)) {
xfs_iunlock(xip, iolock);
goto out_unlock_mutex;
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 80562b60fb9..50d0faea371 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -71,7 +71,7 @@ xfs_swapext(
/* Pull information for the target fd */
if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) ||
- ((vp = vn_from_inode(fp->f_dentry->d_inode)) == NULL)) {
+ ((vp = vn_from_inode(fp->f_path.dentry->d_inode)) == NULL)) {
error = XFS_ERROR(EINVAL);
goto error0;
}
@@ -83,7 +83,7 @@ xfs_swapext(
}
if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) ||
- ((tvp = vn_from_inode(tfp->f_dentry->d_inode)) == NULL)) {
+ ((tvp = vn_from_inode(tfp->f_path.dentry->d_inode)) == NULL)) {
error = XFS_ERROR(EINVAL);
goto error0;
}
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 9e6c23c360b..ebc1f697615 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -105,7 +105,7 @@
/* Maximum object reference count (detects object deletion issues) */
-#define ACPI_MAX_REFERENCE_COUNT 0x800
+#define ACPI_MAX_REFERENCE_COUNT 0x1000
/* Size of cached memory mapping for system memory operation region */
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 049e9aa1b86..81458767a90 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -97,11 +97,12 @@ acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address);
acpi_status acpi_load_tables(void);
-#ifdef ACPI_FUTURE_USAGE
acpi_status acpi_load_table(struct acpi_table_header *table_ptr);
-acpi_status acpi_unload_table(acpi_table_type table_type);
+acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id);
+#ifdef ACPI_FUTURE_USAGE
+acpi_status acpi_unload_table(acpi_table_type table_type);
acpi_status
acpi_get_table_header(acpi_table_type table_type,
u32 instance, struct acpi_table_header *out_table_header);
@@ -180,6 +181,8 @@ acpi_get_next_object(acpi_object_type type,
acpi_status acpi_get_type(acpi_handle object, acpi_object_type * out_type);
+acpi_status acpi_get_id(acpi_handle object, acpi_owner_id * out_type);
+
acpi_status acpi_get_parent(acpi_handle object, acpi_handle * out_handle);
/*
diff --git a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h
index 805640b4107..b686cc7fc44 100644
--- a/include/asm-alpha/cacheflush.h
+++ b/include/asm-alpha/cacheflush.h
@@ -6,6 +6,7 @@
/* Caches aren't brain-dead on the Alpha. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index 57e09f5e342..75a1aff5b57 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -41,9 +41,9 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
#define dma_map_single(dev, va, size, dir) virt_to_phys(va)
#define dma_map_page(dev, page, off, size, dir) (page_to_pa(page) + off)
-#define dma_unmap_single(dev, addr, size, dir) do { } while (0)
-#define dma_unmap_page(dev, addr, size, dir) do { } while (0)
-#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0)
+#define dma_unmap_single(dev, addr, size, dir) ((void)0)
+#define dma_unmap_page(dev, addr, size, dir) ((void)0)
+#define dma_unmap_sg(dev, sg, nents, dir) ((void)0)
#define dma_mapping_error(addr) (0)
@@ -55,12 +55,14 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
int dma_set_mask(struct device *dev, u64 mask);
-#define dma_sync_single_for_cpu(dev, addr, size, dir) do { } while (0)
-#define dma_sync_single_for_device(dev, addr, size, dir) do { } while (0)
-#define dma_sync_single_range(dev, addr, off, size, dir) do { } while (0)
-#define dma_sync_sg_for_cpu(dev, sg, nents, dir) do { } while (0)
-#define dma_sync_sg_for_device(dev, sg, nents, dir) do { } while (0)
-#define dma_cache_sync(dev, va, size, dir) do { } while (0)
+#define dma_sync_single_for_cpu(dev, addr, size, dir) ((void)0)
+#define dma_sync_single_for_device(dev, addr, size, dir) ((void)0)
+#define dma_sync_single_range(dev, addr, off, size, dir) ((void)0)
+#define dma_sync_sg_for_cpu(dev, sg, nents, dir) ((void)0)
+#define dma_sync_sg_for_device(dev, sg, nents, dir) ((void)0)
+#define dma_cache_sync(dev, va, size, dir) ((void)0)
+#define dma_sync_single_range_for_cpu(dev, addr, offset, size, dir) ((void)0)
+#define dma_sync_single_range_for_device(dev, addr, offset, size, dir) ((void)0)
#define dma_get_cache_alignment() L1_CACHE_BYTES
diff --git a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h
index c78c04a94f4..db167413300 100644
--- a/include/asm-alpha/posix_types.h
+++ b/include/asm-alpha/posix_types.h
@@ -49,7 +49,7 @@ typedef unsigned int __kernel_old_dev_t;
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
#define __FD_ZERO(set) \
- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+ ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
#else /* __GNUC__ */
diff --git a/include/asm-alpha/termbits.h b/include/asm-alpha/termbits.h
index 5541101b58a..ad854a4a3af 100644
--- a/include/asm-alpha/termbits.h
+++ b/include/asm-alpha/termbits.h
@@ -25,6 +25,19 @@ struct termios {
speed_t c_ospeed; /* output speed */
};
+/* Alpha has matching termios and ktermios */
+
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t c_line; /* line discipline (== c_cc[19]) */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VEOF 0
#define VEOL 1
diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
index 84313d14e78..e58a427012d 100644
--- a/include/asm-alpha/unistd.h
+++ b/include/asm-alpha/unistd.h
@@ -342,9 +342,14 @@
#define __NR_io_cancel 402
#define __NR_exit_group 405
#define __NR_lookup_dcookie 406
-#define __NR_sys_epoll_create 407
-#define __NR_sys_epoll_ctl 408
-#define __NR_sys_epoll_wait 409
+#define __NR_epoll_create 407
+#define __NR_epoll_ctl 408
+#define __NR_epoll_wait 409
+/* Feb 2007: These three sys_epoll defines shouldn't be here but culling
+ * them would break userspace apps ... we'll kill them off in 2010 :) */
+#define __NR_sys_epoll_create __NR_epoll_create
+#define __NR_sys_epoll_ctl __NR_epoll_ctl
+#define __NR_sys_epoll_wait __NR_epoll_wait
#define __NR_remap_file_pages 410
#define __NR_set_tid_address 411
#define __NR_restart_syscall 412
diff --git a/include/asm-arm/arch-at91rm9200/at91_ecc.h b/include/asm-arm/arch-at91rm9200/at91_ecc.h
index fddf256a98d..5c564ede5c5 100644
--- a/include/asm-arm/arch-at91rm9200/at91_ecc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_ecc.h
@@ -14,7 +14,7 @@
#define AT91_ECC_H
#define AT91_ECC_CR (AT91_ECC + 0x00) /* Control register */
-#define AT91_ECC_RST (1 << 0) /* Reset parity */
+#define AT91_ECC_RST (1 << 0) /* Reset parity */
#define AT91_ECC_MR (AT91_ECC + 0x04) /* Mode register */
#define AT91_ECC_PAGESIZE (3 << 0) /* Page Size */
@@ -23,16 +23,16 @@
#define AT91_ECC_PAGESIZE_2112 (2)
#define AT91_ECC_PAGESIZE_4224 (3)
-#define AT91_ECC_SR (AT91_ECC + 0x08) /* Status register */
+#define AT91_ECC_SR (AT91_ECC + 0x08) /* Status register */
#define AT91_ECC_RECERR (1 << 0) /* Recoverable Error */
#define AT91_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
#define AT91_ECC_MULERR (1 << 2) /* Multiple Errors */
-#define AT91_ECC_PR (AT91_ECC + 0x0c) /* Parity register */
+#define AT91_ECC_PR (AT91_ECC + 0x0c) /* Parity register */
#define AT91_ECC_BITADDR (0xf << 0) /* Bit Error Address */
#define AT91_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
-#define AT91_ECC_NPR (AT91_ECC + 0x10) /* NParity register */
+#define AT91_ECC_NPR (AT91_ECC + 0x10) /* NParity register */
#define AT91_ECC_NPARITY (0xffff << 0) /* NParity */
#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_pmc.h b/include/asm-arm/arch-at91rm9200/at91_pmc.h
index de8c3da74a0..c3b489d09b6 100644
--- a/include/asm-arm/arch-at91rm9200/at91_pmc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_pmc.h
@@ -61,7 +61,7 @@
#define AT91_PMC_CSS_PLLA (2 << 0)
#define AT91_PMC_CSS_PLLB (3 << 0)
#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */
-#define AT91_PMC_PRES_1 (0 << 2)
+#define AT91_PMC_PRES_1 (0 << 2)
#define AT91_PMC_PRES_2 (1 << 2)
#define AT91_PMC_PRES_4 (2 << 2)
#define AT91_PMC_PRES_8 (3 << 2)
diff --git a/include/asm-arm/arch-at91rm9200/at91_rstc.h b/include/asm-arm/arch-at91rm9200/at91_rstc.h
index ccdc52da973..237d3c40b31 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rstc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_rstc.h
@@ -17,7 +17,7 @@
#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
-#define AT01_RSTC_KEY (0xff << 24) /* KEY Password */
+#define AT91_RSTC_KEY (0xff << 24) /* KEY Password */
#define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */
#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtc.h b/include/asm-arm/arch-at91rm9200/at91_rtc.h
index 6e5065d5626..095fe088310 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rtc.h
+++ b/include/asm-arm/arch-at91rm9200/at91_rtc.h
@@ -21,21 +21,21 @@
#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar Register */
#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */
#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8)
-#define AT91_RTC_TIMEVSEL_HOUR (1 << 8)
-#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8)
-#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8)
+#define AT91_RTC_TIMEVSEL_HOUR (1 << 8)
+#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8)
+#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8)
#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */
-#define AT91_RTC_CALEVSEL_WEEK (0 << 16)
-#define AT91_RTC_CALEVSEL_MONTH (1 << 16)
-#define AT91_RTC_CALEVSEL_YEAR (2 << 16)
+#define AT91_RTC_CALEVSEL_WEEK (0 << 16)
+#define AT91_RTC_CALEVSEL_MONTH (1 << 16)
+#define AT91_RTC_CALEVSEL_YEAR (2 << 16)
#define AT91_RTC_MR (AT91_RTC + 0x04) /* Mode Register */
-#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */
+#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */
#define AT91_RTC_TIMR (AT91_RTC + 0x08) /* Time Register */
#define AT91_RTC_SEC (0x7f << 0) /* Current Second */
#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */
-#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */
+#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */
#define AT91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */
#define AT91_RTC_CALR (AT91_RTC + 0x0c) /* Calendar Register */
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h
index 4d51177efdd..c569b6a21a4 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200.h
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200.h
@@ -274,7 +274,7 @@
#define AT91_PD19_TPK7 (1 << 19) /* B: ETM Trace Packet Port 7 */
#define AT91_PD20_NPCS3 (1 << 20) /* A: SPI Peripheral Chip Select 3 */
#define AT91_PD20_TPK8 (1 << 20) /* B: ETM Trace Packet Port 8 */
-#define AT91_PD21_RTS0 (1 << 21) /* A: USART Ready To Send 0 */
+#define AT91_PD21_RTS0 (1 << 21) /* A: USART Ready To Send 0 */
#define AT91_PD21_TPK9 (1 << 21) /* B: ETM Trace Packet Port 9 */
#define AT91_PD22_RTS1 (1 << 22) /* A: USART Ready To Send 1 */
#define AT91_PD22_TPK10 (1 << 22) /* B: ETM Trace Packet Port 10 */
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
index 746d973705b..78f6b4917b8 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+++ b/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
@@ -58,7 +58,7 @@
#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x11C) /* EBI Chip Select Assignment Register */
-#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */
+#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */
#define AT91_MATRIX_CS1A_SMC (0 << 1)
#define AT91_MATRIX_CS1A_SDRAMC (1 << 1)
#define AT91_MATRIX_CS3A (1 << 3) /* Chip Select 3 Assignment */
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
index 270a5dcdf1c..ec88efabbe6 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+++ b/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
@@ -15,7 +15,7 @@
#define AT91_MATRIX_MCFG (AT91_MATRIX + 0x00) /* Master Configuration Register */
#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define AT01_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x04) /* Slave Configuration Register 0 */
#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x08) /* Slave Configuration Register 1 */
@@ -43,8 +43,8 @@
#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x30) /* EBI Chip Select Assignment Register */
#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */
-#define AT91_MATRIX_CS1A_SMC (0 << 1)
-#define AT91_MATRIX_CS1A_SDRAMC (1 << 1)
+#define AT91_MATRIX_CS1A_SMC (0 << 1)
+#define AT91_MATRIX_CS1A_SDRAMC (1 << 1)
#define AT91_MATRIX_CS3A (1 << 3) /* Chip Select 3 Assignment */
#define AT91_MATRIX_CS3A_SMC (0 << 3)
#define AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
diff --git a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
index 7d94968b5d5..972e7531c7f 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+++ b/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
@@ -33,14 +33,14 @@
#define AT91_SDRAMC_NC_9 (1 << 0)
#define AT91_SDRAMC_NC_10 (2 << 0)
#define AT91_SDRAMC_NC_11 (3 << 0)
-#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */
+#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */
#define AT91_SDRAMC_NR_11 (0 << 2)
#define AT91_SDRAMC_NR_12 (1 << 2)
#define AT91_SDRAMC_NR_13 (2 << 2)
-#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */
+#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */
#define AT91_SDRAMC_NB_2 (0 << 4)
-#define AT91_SDRAMC_NB_4 (1 << 4)
-#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */
+#define AT91_SDRAMC_NB_4 (1 << 4)
+#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */
#define AT91_SDRAMC_CAS_1 (1 << 5)
#define AT91_SDRAMC_CAS_2 (2 << 5)
#define AT91_SDRAMC_CAS_3 (3 << 5)
@@ -110,10 +110,10 @@
#define AT91_SMC_MODE(n) (AT91_SMC + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
#define AT91_SMC_READMODE (1 << 0) /* Read Mode */
#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */
-#define AT91_SMC_EXNWMODE (3 << 5) /* NWAIT Mode */
-#define AT91_SMC_EXNWMODE_DISABLE (0 << 5)
-#define AT91_SMC_EXNWMODE_FROZEN (2 << 5)
-#define AT91_SMC_EXNWMODE_READY (3 << 5)
+#define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */
+#define AT91_SMC_EXNWMODE_DISABLE (0 << 4)
+#define AT91_SMC_EXNWMODE_FROZEN (2 << 4)
+#define AT91_SMC_EXNWMODE_READY (3 << 4)
#define AT91_SMC_BAT (1 << 8) /* Byte Access Type */
#define AT91_SMC_BAT_SELECT (0 << 8)
#define AT91_SMC_BAT_WRITE (1 << 8)
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
index 9a42f5de9e5..ae532e304bf 100644
--- a/include/asm-arm/arch-ep93xx/irqs.h
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -22,9 +22,9 @@
#define IRQ_EP93XX_DMAM2P9 16
#define IRQ_EP93XX_DMAM2M0 17
#define IRQ_EP93XX_DMAM2M1 18
-#define IRQ_EP93XX_GPIO0MUX 20
-#define IRQ_EP93XX_GPIO1MUX 21
-#define IRQ_EP93XX_GPIO2MUX 22
+#define IRQ_EP93XX_GPIO0MUX 19
+#define IRQ_EP93XX_GPIO1MUX 20
+#define IRQ_EP93XX_GPIO2MUX 21
#define IRQ_EP93XX_GPIO3MUX 22
#define IRQ_EP93XX_UART1RX 23
#define IRQ_EP93XX_UART1TX 24
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
index a6912b3d867..e56a4e247d6 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -41,7 +41,13 @@
/* PLL registers */
#define CSCR __REG(IMX_PLL_BASE) /* Clock Source Control Register */
-#define CSCR_SYSTEM_SEL (1<<16)
+#define CSCR_SPLL_RESTART (1<<22)
+#define CSCR_MPLL_RESTART (1<<21)
+#define CSCR_SYSTEM_SEL (1<<16)
+#define CSCR_BCLK_DIV (0xf<<10)
+#define CSCR_MPU_PRESC (1<<15)
+#define CSCR_SPEN (1<<1)
+#define CSCR_MPEN (1<<0)
#define MPCTL0 __REG(IMX_PLL_BASE + 0x4) /* MCU PLL Control Register 0 */
#define MPCTL1 __REG(IMX_PLL_BASE + 0x8) /* MCU PLL and System Clock Register 1 */
@@ -49,8 +55,6 @@
#define SPCTL1 __REG(IMX_PLL_BASE + 0x10) /* System PLL Control Register 1 */
#define PCDR __REG(IMX_PLL_BASE + 0x20) /* Peripheral Clock Divider Register */
-#define CSCR_MPLL_RESTART (1<<21)
-
/*
* GPIO Module and I/O Multiplexer
* x = 0..3 for reg_A, reg_B, reg_C, reg_D
diff --git a/include/asm-arm/arch-iop13xx/io.h b/include/asm-arm/arch-iop13xx/io.h
index db6de2480a2..5a7bdb52660 100644
--- a/include/asm-arm/arch-iop13xx/io.h
+++ b/include/asm-arm/arch-iop13xx/io.h
@@ -21,10 +21,11 @@
#define IO_SPACE_LIMIT 0xffffffff
-#define __io(a) (a)
+#define __io(a) __iop13xx_io(a)
#define __mem_pci(a) (a)
#define __mem_isa(a) (a)
+extern void __iomem * __iop13xx_io(unsigned long io_addr);
extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
extern void __iomem *__iop13xx_ioremap(unsigned long cookie, size_t size,
unsigned long flags);
diff --git a/include/asm-arm/arch-iop13xx/iq81340.h b/include/asm-arm/arch-iop13xx/iq81340.h
index b98f8f109c2..ba2cf931e9c 100644
--- a/include/asm-arm/arch-iop13xx/iq81340.h
+++ b/include/asm-arm/arch-iop13xx/iq81340.h
@@ -24,8 +24,5 @@
#define PBI_CF_IDE_BASE (IQ81340_CMP_FLSH)
#define PBI_CF_BAR_ADDR (IOP13XX_PBI_BAR1)
-/* These are the values used in the Machine description */
-#define PHYS_IO 0xfeffff00
-#define IO_PG_OFFSET 0xffffff00
-#define BOOT_PARAM_OFFSET 0x00000100
+
#endif /* _IQ81340_H_ */
diff --git a/include/asm-arm/arch-iop32x/iop32x.h b/include/asm-arm/arch-iop32x/iop32x.h
index 4bbd85f3ed2..2e9469047eb 100644
--- a/include/asm-arm/arch-iop32x/iop32x.h
+++ b/include/asm-arm/arch-iop32x/iop32x.h
@@ -19,7 +19,7 @@
* Peripherals that are shared between the iop32x and iop33x but
* located at different addresses.
*/
-#define IOP3XX_GPIO_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07c0 + (reg))
+#define IOP3XX_GPIO_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07c4 + (reg))
#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
#include <asm/hardware/iop3xx.h>
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
index c85fc06a043..6d859d742d7 100644
--- a/include/asm-arm/arch-ixp23xx/memory.h
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -41,21 +41,7 @@
data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \
__phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
-/*
- * Coherency support. Only supported on A2 CPUs or on A1
- * systems that have the cache coherency workaround.
- */
-static inline int __ixp23xx_arch_is_coherent(void)
-{
- extern unsigned int processor_id;
-
- if (((processor_id & 15) >= 4) || machine_is_roadrunner())
- return 1;
-
- return 0;
-}
-
-#define arch_is_coherent() __ixp23xx_arch_is_coherent()
+#define arch_is_coherent() 1
#endif
diff --git a/include/asm-arm/arch-pnx4008/i2c.h b/include/asm-arm/arch-pnx4008/i2c.h
new file mode 100644
index 00000000000..92e8d65006f
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/i2c.h
@@ -0,0 +1,67 @@
+/*
+ * PNX4008-specific tweaks for I2C IP3204 block
+ *
+ * Author: Vitaly Wool <vwool@ru.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.
+ */
+
+#ifndef __ASM_ARCH_I2C_H__
+#define __ASM_ARCH_I2C_H__
+
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+
+enum {
+ mstatus_tdi = 0x00000001,
+ mstatus_afi = 0x00000002,
+ mstatus_nai = 0x00000004,
+ mstatus_drmi = 0x00000008,
+ mstatus_active = 0x00000020,
+ mstatus_scl = 0x00000040,
+ mstatus_sda = 0x00000080,
+ mstatus_rff = 0x00000100,
+ mstatus_rfe = 0x00000200,
+ mstatus_tff = 0x00000400,
+ mstatus_tfe = 0x00000800,
+};
+
+enum {
+ mcntrl_tdie = 0x00000001,
+ mcntrl_afie = 0x00000002,
+ mcntrl_naie = 0x00000004,
+ mcntrl_drmie = 0x00000008,
+ mcntrl_daie = 0x00000020,
+ mcntrl_rffie = 0x00000040,
+ mcntrl_tffie = 0x00000080,
+ mcntrl_reset = 0x00000100,
+ mcntrl_cdbmode = 0x00000400,
+};
+
+enum {
+ rw_bit = 1 << 0,
+ start_bit = 1 << 8,
+ stop_bit = 1 << 9,
+};
+
+#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
+#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
+#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
+#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
+#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
+#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
+#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
+#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
+#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
+#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
+#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
+#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
+#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
+
+#define HCLK_MHZ 13
+#define I2C_CHIP_NAME "PNX4008-I2C"
+
+#endif /* __ASM_ARCH_I2C_H___ */
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 083e03c5639..e24f6b6c79a 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1626,7 +1626,7 @@
#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */
#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */
#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */
-#define SSCR0_SlotsPerFrm(x) ((x) - 1) /* Time slots per frame [1..8] */
+#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */
#define SSCR0_ADC (1 << 30) /* Audio clock select */
#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */
#endif
@@ -1655,6 +1655,7 @@
#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */
/* extra bits in PXA255, PXA26x and PXA27x SSP ports */
+#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */
#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */
#define SSCR1_TTELP (1 << 31) /* TXD Tristate Enable Last Phase */
#define SSCR1_TTE (1 << 30) /* TXD Tristate Enable */
diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h
index 915590c391c..acc7ec7a84a 100644
--- a/include/asm-arm/arch-pxa/pxa2xx_spi.h
+++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h
@@ -27,16 +27,13 @@
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
-#define SSP_TIMEOUT_SCALE (2712)
#elif defined(CONFIG_PXA27x)
#define CLOCK_SPEED_HZ 13000000
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
-#define SSP_TIMEOUT_SCALE (769)
#endif
-#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE)
#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
@@ -63,7 +60,7 @@ struct pxa2xx_spi_chip {
u8 tx_threshold;
u8 rx_threshold;
u8 dma_burst_size;
- u32 timeout_microsecs;
+ u32 timeout;
u8 enable_loopback;
void (*cs_control)(u32 command);
};
diff --git a/include/asm-arm/arch-s3c2410/anubis-cpld.h b/include/asm-arm/arch-s3c2410/anubis-cpld.h
index 40e8e270d33..dcebf6d6190 100644
--- a/include/asm-arm/arch-s3c2410/anubis-cpld.h
+++ b/include/asm-arm/arch-s3c2410/anubis-cpld.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/anubis-cpld.h
*
- * (c) 2005 Simtec Electronics
+ * Copyright (c) 2005 Simtec Electronics
* http://www.simtec.co.uk/products/
* Ben Dooks <ben@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/anubis-irq.h b/include/asm-arm/arch-s3c2410/anubis-irq.h
index 4b5f423779d..cd77a70d45c 100644
--- a/include/asm-arm/arch-s3c2410/anubis-irq.h
+++ b/include/asm-arm/arch-s3c2410/anubis-irq.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/anubis-irq.h
*
- * (c) 2005 Simtec Electronics
+ * Copyright (c) 2005 Simtec Electronics
* http://www.simtec.co.uk/products/
* Ben Dooks <ben@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h
index 058a2104b03..ab076de4a0d 100644
--- a/include/asm-arm/arch-s3c2410/anubis-map.h
+++ b/include/asm-arm/arch-s3c2410/anubis-map.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/anubis-map.h
*
- * (c) 2005 Simtec Electronics
+ * Copyright (c) 2005 Simtec Electronics
* http://www.simtec.co.uk/products/
* Ben Dooks <ben@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/audio.h b/include/asm-arm/arch-s3c2410/audio.h
index 7e0222276c9..65e0acffa1a 100644
--- a/include/asm-arm/arch-s3c2410/audio.h
+++ b/include/asm-arm/arch-s3c2410/audio.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/audio.h
*
- * (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2005 Simtec Electronics
* http://www.simtec.co.uk/products/SWLINUX/
* Ben Dooks <ben@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/bast-cpld.h b/include/asm-arm/arch-s3c2410/bast-cpld.h
index 8969cffe83f..034d2c5a47c 100644
--- a/include/asm-arm/arch-s3c2410/bast-cpld.h
+++ b/include/asm-arm/arch-s3c2410/bast-cpld.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/bast-cpld.h
*
- * (c) 2003,2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* BAST - CPLD control constants
*
diff --git a/include/asm-arm/arch-s3c2410/bast-irq.h b/include/asm-arm/arch-s3c2410/bast-irq.h
index 15ffa66f501..726c0466f85 100644
--- a/include/asm-arm/arch-s3c2410/bast-irq.h
+++ b/include/asm-arm/arch-s3c2410/bast-irq.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/bast-irq.h
*
- * (c) 2003,2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* Machine BAST - IRQ Number definitions
*
diff --git a/include/asm-arm/arch-s3c2410/bast-map.h b/include/asm-arm/arch-s3c2410/bast-map.h
index 727cef84c70..86ac1c108db 100644
--- a/include/asm-arm/arch-s3c2410/bast-map.h
+++ b/include/asm-arm/arch-s3c2410/bast-map.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/bast-map.h
*
- * (c) 2003,2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* Machine BAST - Memory map definitions
*
diff --git a/include/asm-arm/arch-s3c2410/bast-pmu.h b/include/asm-arm/arch-s3c2410/bast-pmu.h
index 82836027f00..37a11fe54a7 100644
--- a/include/asm-arm/arch-s3c2410/bast-pmu.h
+++ b/include/asm-arm/arch-s3c2410/bast-pmu.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/bast-pmu.h
*
- * (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* Vincent Sanders <vince@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 7ac22483697..58ffa7ba3c8 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -14,7 +14,7 @@
#define __ASM_ARCH_DMA_H __FILE__
#include <linux/sysdev.h>
-#include "hardware.h"
+#include <asm/hardware.h>
/*
* This is the maximum DMA address(physical address) that can be DMAd to.
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index e09a6b8ec15..1eb4e6b8d24 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -20,7 +20,7 @@
#define INTOFFSET (0x14)
#include <asm/hardware.h>
-#include <asm/arch/irqs.h>
+#include <asm/irq.h>
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
index 90894214cac..93a58e7862b 100644
--- a/include/asm-arm/arch-s3c2410/fb.h
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -31,6 +31,9 @@ struct s3c2410fb_hw {
struct s3c2410fb_mach_info {
unsigned char fixed_syncs; /* do not update sync/border */
+ /* LCD types */
+ int type;
+
/* Screen size */
int width;
int height;
diff --git a/include/asm-arm/arch-s3c2410/h1940-latch.h b/include/asm-arm/arch-s3c2410/h1940-latch.h
index c5802411f43..c3de5ab102e 100644
--- a/include/asm-arm/arch-s3c2410/h1940-latch.h
+++ b/include/asm-arm/arch-s3c2410/h1940-latch.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/h1940-latch.h
*
- * (c) 2005 Simtec Electronics
+ * Copyright (c) 2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
@@ -16,7 +16,7 @@
#ifndef __ASSEMBLY__
-#define H1940_LATCH ((void __iomem *)0xF8000000)
+#define H1940_LATCH ((void __force __iomem *)0xF8000000)
#else
#define H1940_LATCH 0xF8000000
#endif
diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
index 871f8af09b8..6dadf58ff98 100644
--- a/include/asm-arm/arch-s3c2410/hardware.h
+++ b/include/asm-arm/arch-s3c2410/hardware.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/hardware.h
*
- * (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - hardware
*
@@ -13,6 +13,10 @@
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
+#ifndef __ASM_HARDWARE_H
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
#ifndef __ASSEMBLY__
/* external functions for GPIO support
diff --git a/include/asm-arm/arch-s3c2410/iic.h b/include/asm-arm/arch-s3c2410/iic.h
index ed3d6c7bf6d..71211c8b538 100644
--- a/include/asm-arm/arch-s3c2410/iic.h
+++ b/include/asm-arm/arch-s3c2410/iic.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/iic.h
*
- * (c) 2004 Simtec Electronics
+ * Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - I2C Controller platfrom_device info
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 39a69829d16..4b7cff456c4 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -12,6 +12,9 @@
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H __FILE__
+#ifndef __ASM_ARM_IRQ_H
+#error "Do not include this directly, instead #include <asm/irq.h>"
+#endif
/* we keep the first set of CPU IRQs out of the range of
* the ISA space, so that the PC104 has them to itself
diff --git a/include/asm-arm/arch-s3c2410/leds-gpio.h b/include/asm-arm/arch-s3c2410/leds-gpio.h
index f07ed040622..800846ebddb 100644
--- a/include/asm-arm/arch-s3c2410/leds-gpio.h
+++ b/include/asm-arm/arch-s3c2410/leds-gpio.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/leds-gpio.h
*
- * (c) 2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index 7895042d176..4505aefbad1 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/map.h
*
- * (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - Memory map definitions
*
@@ -25,7 +25,7 @@
*/
#ifndef __ASSEMBLY__
-#define S3C2410_ADDR(x) ((void __iomem *)0xF0000000 + (x))
+#define S3C2410_ADDR(x) ((void __iomem __force *)0xF0000000 + (x))
#else
#define S3C2410_ADDR(x) (0xF0000000 + (x))
#endif
@@ -47,73 +47,65 @@
#define S3C24XX_SZ_MEMCTRL SZ_1M
/* USB host controller */
-#define S3C24XX_VA_USBHOST S3C2410_ADDR(0x00200000)
#define S3C2400_PA_USBHOST (0x14200000)
#define S3C2410_PA_USBHOST (0x49000000)
#define S3C24XX_SZ_USBHOST SZ_1M
/* DMA controller */
-#define S3C24XX_VA_DMA S3C2410_ADDR(0x00300000)
#define S3C2400_PA_DMA (0x14600000)
#define S3C2410_PA_DMA (0x4B000000)
#define S3C24XX_SZ_DMA SZ_1M
/* Clock and Power management */
-#define S3C24XX_VA_CLKPWR S3C2410_ADDR(0x00400000)
+#define S3C24XX_VA_CLKPWR S3C2410_ADDR(0x00200000)
#define S3C2400_PA_CLKPWR (0x14800000)
#define S3C2410_PA_CLKPWR (0x4C000000)
#define S3C24XX_SZ_CLKPWR SZ_1M
/* LCD controller */
-#define S3C24XX_VA_LCD S3C2410_ADDR(0x00600000)
+#define S3C24XX_VA_LCD S3C2410_ADDR(0x00300000)
#define S3C2400_PA_LCD (0x14A00000)
#define S3C2410_PA_LCD (0x4D000000)
#define S3C24XX_SZ_LCD SZ_1M
/* NAND flash controller */
-#define S3C24XX_VA_NAND S3C2410_ADDR(0x00700000)
#define S3C2410_PA_NAND (0x4E000000)
#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 S3C24XX_VA_UART S3C2410_ADDR(0x00800000)
+#define S3C24XX_VA_UART S3C2410_ADDR(0x00400000)
#define S3C2400_PA_UART (0x15000000)
#define S3C2410_PA_UART (0x50000000)
#define S3C24XX_SZ_UART SZ_1M
/* Timers */
-#define S3C24XX_VA_TIMER S3C2410_ADDR(0x00900000)
+#define S3C24XX_VA_TIMER S3C2410_ADDR(0x00500000)
#define S3C2400_PA_TIMER (0x15100000)
#define S3C2410_PA_TIMER (0x51000000)
#define S3C24XX_SZ_TIMER SZ_1M
/* USB Device port */
-#define S3C24XX_VA_USBDEV S3C2410_ADDR(0x00A00000)
+#define S3C24XX_VA_USBDEV S3C2410_ADDR(0x00600000)
#define S3C2400_PA_USBDEV (0x15200140)
#define S3C2410_PA_USBDEV (0x52000000)
#define S3C24XX_SZ_USBDEV SZ_1M
/* Watchdog */
-#define S3C24XX_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C24XX_VA_WATCHDOG S3C2410_ADDR(0x00700000)
#define S3C2400_PA_WATCHDOG (0x15300000)
#define S3C2410_PA_WATCHDOG (0x53000000)
#define S3C24XX_SZ_WATCHDOG SZ_1M
/* IIC hardware controller */
-#define S3C24XX_VA_IIC S3C2410_ADDR(0x00C00000)
#define S3C2400_PA_IIC (0x15400000)
#define S3C2410_PA_IIC (0x54000000)
#define S3C24XX_SZ_IIC SZ_1M
-#define VA_IIC_BASE (S3C24XX_VA_IIC)
-
/* IIS controller */
-#define S3C24XX_VA_IIS S3C2410_ADDR(0x00D00000)
#define S3C2400_PA_IIS (0x15508000)
#define S3C2410_PA_IIS (0x55000000)
#define S3C24XX_SZ_IIS SZ_1M
@@ -134,25 +126,21 @@
#define S3C24XX_SZ_GPIO SZ_1M
/* RTC */
-#define S3C24XX_VA_RTC S3C2410_ADDR(0x00F00000)
#define S3C2400_PA_RTC (0x15700040)
#define S3C2410_PA_RTC (0x57000000)
#define S3C24XX_SZ_RTC SZ_1M
/* ADC */
-#define S3C24XX_VA_ADC S3C2410_ADDR(0x01000000)
#define S3C2400_PA_ADC (0x15800000)
#define S3C2410_PA_ADC (0x58000000)
#define S3C24XX_SZ_ADC SZ_1M
/* SPI */
-#define S3C24XX_VA_SPI S3C2410_ADDR(0x01100000)
#define S3C2400_PA_SPI (0x15900000)
#define S3C2410_PA_SPI (0x59000000)
#define S3C24XX_SZ_SPI SZ_1M
/* SDI */
-#define S3C24XX_VA_SDI S3C2410_ADDR(0x01200000)
#define S3C2410_PA_SDI (0x5A000000)
#define S3C24XX_SZ_SDI SZ_1M
diff --git a/include/asm-arm/arch-s3c2410/nand.h b/include/asm-arm/arch-s3c2410/nand.h
index e350ae2acfc..8816f7f9cee 100644
--- a/include/asm-arm/arch-s3c2410/nand.h
+++ b/include/asm-arm/arch-s3c2410/nand.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/nand.h
*
- * (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - NAND device controller platfrom_device info
*
diff --git a/include/asm-arm/arch-s3c2410/osiris-cpld.h b/include/asm-arm/arch-s3c2410/osiris-cpld.h
index e9d1ae1f354..3b6498468d6 100644
--- a/include/asm-arm/arch-s3c2410/osiris-cpld.h
+++ b/include/asm-arm/arch-s3c2410/osiris-cpld.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/osiris-cpld.h
*
- * (c) 2005 Simtec Electronics
+ * Copyright (c) 2005 Simtec Electronics
* http://www.simtec.co.uk/products/
* Ben Dooks <ben@simtec.co.uk>
*
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index b2893e32a23..eae91694edc 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -52,10 +52,10 @@
/* general configuration options */
#define S3C2410_GPIO_LEAVE (0xFFFFFFFF)
-#define S3C2410_GPIO_INPUT (0xFFFFFFF0)
+#define S3C2410_GPIO_INPUT (0xFFFFFFF0) /* not available on A */
#define S3C2410_GPIO_OUTPUT (0xFFFFFFF1)
#define S3C2410_GPIO_IRQ (0xFFFFFFF2) /* not available for all */
-#define S3C2410_GPIO_SFN2 (0xFFFFFFF2) /* not available on A */
+#define S3C2410_GPIO_SFN2 (0xFFFFFFF2) /* bank A => addr/cs/nand */
#define S3C2410_GPIO_SFN3 (0xFFFFFFF3) /* not available on A */
/* register address for the GPIO registers.
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
index 375dca50364..e4d82341f7b 100644
--- a/include/asm-arm/arch-s3c2410/regs-mem.h
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h
@@ -133,10 +133,10 @@
#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)
+#define S3C2400_BANKCON_EDO_Trcd1 (0x00 << 4)
+#define S3C2400_BANKCON_EDO_Trcd2 (0x01 << 4)
+#define S3C2400_BANKCON_EDO_Trcd3 (0x02 << 4)
+#define S3C2400_BANKCON_EDO_Trcd4 (0x03 << 4)
/* CAS pulse width */
#define S3C2400_BANKCON_EDO_PULSE1 (0x00 << 3)
@@ -153,9 +153,9 @@
#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)
-#define S3C2410_BANKCON_Trdc4 (0x02 << 2)
+#define S3C2410_BANKCON_Trcd2 (0x00 << 2)
+#define S3C2410_BANKCON_Trcd3 (0x01 << 2)
+#define S3C2410_BANKCON_Trcd4 (0x02 << 2)
/* control column address select */
#define S3C2410_BANKCON_SCANb8 (0x00 << 0)
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 19c77da9c3f..46f52401d13 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -197,7 +197,7 @@ struct s3c2410_uartcfg {
unsigned char hwport; /* hardware port number */
unsigned char unused;
unsigned short flags;
- unsigned long uart_flags; /* default uart flags */
+ upf_t uart_flags; /* default uart flags */
unsigned long ucon; /* value of ucon for port */
unsigned long ulcon; /* value of ulcon for port */
diff --git a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
index 487861d5b49..3c8354619b6 100644
--- a/include/asm-arm/arch-s3c2410/regs-udc.h
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h
@@ -11,8 +11,7 @@
#ifndef __ASM_ARCH_REGS_UDC_H
#define __ASM_ARCH_REGS_UDC_H
-
-#define S3C2410_USBDREG(x) ((x) + S3C24XX_VA_USBDEV)
+#define S3C2410_USBDREG(x) (x)
#define S3C2410_UDC_FUNC_ADDR_REG S3C2410_USBDREG(0x0140)
#define S3C2410_UDC_PWR_REG S3C2410_USBDREG(0x0144)
@@ -136,8 +135,8 @@
#define S3C2410_UDC_OCSR2_ISO (1<<6) // R/W
#define S3C2410_UDC_OCSR2_DMAIEN (1<<5) // R/W
-#define S3C2410_UDC_SETIX(x) \
- __raw_writel(S3C2410_UDC_INDEX_ ## x, S3C2410_UDC_INDEX_REG);
+#define S3C2410_UDC_SETIX(base,x) \
+ writel(S3C2410_UDC_INDEX_ ## x, base+S3C2410_UDC_INDEX_REG);
#define S3C2410_UDC_EP0_CSR_OPKRDY (1<<0)
diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
index 4f72a853a5c..ecf250db45f 100644
--- a/include/asm-arm/arch-s3c2410/system.h
+++ b/include/asm-arm/arch-s3c2410/system.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/system.h
*
- * (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - System function defines and includes
*
diff --git a/include/asm-arm/arch-s3c2410/timex.h b/include/asm-arm/arch-s3c2410/timex.h
index 703c337c561..c16a99c5a59 100644
--- a/include/asm-arm/arch-s3c2410/timex.h
+++ b/include/asm-arm/arch-s3c2410/timex.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/timex.h
*
- * (c) 2003-2005 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - time parameters
*
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index 81b3e91c56a..dcb2cef38f5 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/uncompress.h
*
- * (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - uncompress code
*
@@ -13,6 +13,7 @@
#ifndef __ASM_ARCH_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H
+typedef unsigned int upf_t; /* cannot include linux/serial_core.h */
/* defines for UART registers */
#include "asm/arch/regs-serial.h"
diff --git a/include/asm-arm/arch-s3c2410/usb-control.h b/include/asm-arm/arch-s3c2410/usb-control.h
index 35723569a17..5bfa376e33d 100644
--- a/include/asm-arm/arch-s3c2410/usb-control.h
+++ b/include/asm-arm/arch-s3c2410/usb-control.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/usb-control.h
*
- * (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - usb port information
*
diff --git a/include/asm-arm/arch-s3c2410/vr1000-cpld.h b/include/asm-arm/arch-s3c2410/vr1000-cpld.h
index a341b1e1bd9..0557b0a5ab1 100644
--- a/include/asm-arm/arch-s3c2410/vr1000-cpld.h
+++ b/include/asm-arm/arch-s3c2410/vr1000-cpld.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/vr1000-cpld.h
*
- * (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* VR1000 - CPLD control constants
*
diff --git a/include/asm-arm/arch-s3c2410/vr1000-irq.h b/include/asm-arm/arch-s3c2410/vr1000-irq.h
index c39a0ffa670..890937083c6 100644
--- a/include/asm-arm/arch-s3c2410/vr1000-irq.h
+++ b/include/asm-arm/arch-s3c2410/vr1000-irq.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/vr1000-irq.h
*
- * (c) 2003,2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* Machine VR1000 - IRQ Number definitions
*
diff --git a/include/asm-arm/arch-s3c2410/vr1000-map.h b/include/asm-arm/arch-s3c2410/vr1000-map.h
index 1fe4db36c83..92a56a724a8 100644
--- a/include/asm-arm/arch-s3c2410/vr1000-map.h
+++ b/include/asm-arm/arch-s3c2410/vr1000-map.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-s3c2410/vr1000-map.h
*
- * (c) 2003-2005 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* Machine VR1000 - Memory map definitions
*
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index f0845646aac..5f531ea0305 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -319,6 +319,8 @@ extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
unsigned long len, int write);
#endif
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
/*
* flush_cache_user_range is used when we want to ensure that the
* Harvard caches are synchronised for the user space address range.
@@ -353,6 +355,18 @@ extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
*/
extern void flush_dcache_page(struct page *);
+extern void __flush_dcache_page(struct address_space *mapping, struct page *page);
+
+#define ARCH_HAS_FLUSH_ANON_PAGE
+static inline void flush_anon_page(struct vm_area_struct *vma,
+ struct page *page, unsigned long vmaddr)
+{
+ extern void __flush_anon_page(struct vm_area_struct *vma,
+ struct page *, unsigned long);
+ if (PageAnon(page))
+ __flush_anon_page(vma, page, vmaddr);
+}
+
#define flush_dcache_mmap_lock(mapping) \
write_lock_irq(&(mapping)->tree_lock)
#define flush_dcache_mmap_unlock(mapping) \
diff --git a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h
index 4679f63688e..715e18a4add 100644
--- a/include/asm-arm/cpu-multi32.h
+++ b/include/asm-arm/cpu-multi32.h
@@ -50,9 +50,10 @@ extern struct processor {
*/
void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
/*
- * Set a PTE
+ * Set a possibly extended PTE. Non-extended PTEs should
+ * ignore 'ext'.
*/
- void (*set_pte)(pte_t *ptep, pte_t pte);
+ void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
} processor;
#define cpu_proc_init() processor._proc_init()
@@ -60,5 +61,5 @@ extern struct processor {
#define cpu_reset(addr) processor.reset(addr)
#define cpu_do_idle() processor._do_idle()
#define cpu_dcache_clean_area(addr,sz) processor.dcache_clean_area(addr,sz)
-#define cpu_set_pte(ptep, pte) processor.set_pte(ptep, pte)
+#define cpu_set_pte_ext(ptep,pte,ext) processor.set_pte_ext(ptep,pte,ext)
#define cpu_do_switch_mm(pgd,mm) processor.switch_mm(pgd,mm)
diff --git a/include/asm-arm/cpu-single.h b/include/asm-arm/cpu-single.h
index 6723e67244f..0b120ee3609 100644
--- a/include/asm-arm/cpu-single.h
+++ b/include/asm-arm/cpu-single.h
@@ -28,7 +28,7 @@
#define cpu_do_idle __cpu_fn(CPU_NAME,_do_idle)
#define cpu_dcache_clean_area __cpu_fn(CPU_NAME,_dcache_clean_area)
#define cpu_do_switch_mm __cpu_fn(CPU_NAME,_switch_mm)
-#define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte)
+#define cpu_set_pte_ext __cpu_fn(CPU_NAME,_set_pte_ext)
#include <asm/page.h>
@@ -40,5 +40,5 @@ extern void cpu_proc_fin(void);
extern int cpu_do_idle(void);
extern void cpu_dcache_clean_area(void *, int);
extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
-extern void cpu_set_pte(pte_t *ptep, pte_t pte);
+extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index 642382d2c9f..3679a8a8922 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -52,6 +52,7 @@ typedef struct user_fp elf_fpregset_t;
#define HWCAP_EDSP 128
#define HWCAP_JAVA 256
#define HWCAP_IWMMXT 512
+#define HWCAP_CRUNCH 1024
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
diff --git a/include/asm-arm/flat.h b/include/asm-arm/flat.h
index 96694647858..16f5375e57b 100644
--- a/include/asm-arm/flat.h
+++ b/include/asm-arm/flat.h
@@ -5,7 +5,9 @@
#ifndef __ARM_FLAT_H__
#define __ARM_FLAT_H__
-#define flat_stack_align(sp) /* nothing needed */
+/* An odd number of words will be pushed after this alignment, so
+ deliberately misalign the value. */
+#define flat_stack_align(sp) sp = (void *)(((unsigned long)(sp) - 4) | 4)
#define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 6af4e6bd129..f31cda5a55e 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -35,6 +35,9 @@ struct vfp_hard_struct {
*/
__u32 fpinst;
__u32 fpinst2;
+#ifdef CONFIG_SMP
+ __u32 cpu;
+#endif
};
union vfp_state {
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
index 1018a7486ab..13ac8a4cd01 100644
--- a/include/asm-arm/hardware/iop3xx.h
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -168,9 +168,9 @@ extern void gpio_line_set(int line, int value);
#define IOP3XX_PERCR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0710)
/* General Purpose I/O */
-#define IOP3XX_GPOE (volatile u32 *)IOP3XX_GPIO_REG(0x0004)
-#define IOP3XX_GPID (volatile u32 *)IOP3XX_GPIO_REG(0x0008)
-#define IOP3XX_GPOD (volatile u32 *)IOP3XX_GPIO_REG(0x000c)
+#define IOP3XX_GPOE (volatile u32 *)IOP3XX_GPIO_REG(0x0000)
+#define IOP3XX_GPID (volatile u32 *)IOP3XX_GPIO_REG(0x0004)
+#define IOP3XX_GPOD (volatile u32 *)IOP3XX_GPIO_REG(0x0008)
/* Timers */
#define IOP3XX_TU_TMR0 (volatile u32 *)IOP3XX_TIMER_REG(0x0000)
diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
index 283af50a16c..1b882a255e3 100644
--- a/include/asm-arm/irq.h
+++ b/include/asm-arm/irq.h
@@ -19,7 +19,6 @@
#define NO_IRQ ((unsigned int)(-1))
#endif
-struct irqaction;
/*
* Migration helpers
@@ -37,6 +36,10 @@ struct irqaction;
#define IRQT_HIGH (__IRQT_HIGHLVL)
#define IRQT_PROBE IRQ_TYPE_PROBE
+#ifndef __ASSEMBLY__
+struct irqaction;
extern void migrate_irqs(void);
#endif
+#endif
+
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 88cd5c784ef..b8cf2d5ec30 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -21,6 +21,7 @@
#include <asm/memory.h>
#include <asm/arch/vmalloc.h>
+#include <asm/pgtable-hwdef.h>
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
@@ -170,7 +171,6 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define L_PTE_EXEC (1 << 6)
#define L_PTE_DIRTY (1 << 7)
#define L_PTE_SHARED (1 << 10) /* shared(v6), coherent(xsc3) */
-#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */
#ifndef __ASSEMBLY__
@@ -228,7 +228,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(mm,addr,ptep) set_pte_at((mm),(addr),(ptep), __pte(0))
+#define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0)
#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
#define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr))
#define pte_offset_map(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr))
@@ -236,8 +236,11 @@ extern struct page *empty_zero_page;
#define pte_unmap(pte) do { } while (0)
#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)
+#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+
+#define set_pte_at(mm,addr,ptep,pteval) do { \
+ set_pte_ext(ptep, pteval, (addr) >= PAGE_OFFSET ? 0 : PTE_EXT_NG); \
+ } while (0)
/*
* The following only work if pte_present() is true.
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index b442e8e2a80..1bbf16182d6 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -103,14 +103,14 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
#if __LINUX_ARM_ARCH__ >= 5
#define ARCH_HAS_PREFETCH
-#define prefetch(ptr) \
- ({ \
- __asm__ __volatile__( \
- "pld\t%0" \
- : \
- : "o" (*(char *)(ptr)) \
- : "cc"); \
- })
+static inline void prefetch(const void *ptr)
+{
+ __asm__ __volatile__(
+ "pld\t%0"
+ :
+ : "o" (*(char *)ptr)
+ : "cc");
+}
#define ARCH_HAS_PREFETCHW
#define prefetchw(ptr) prefetch(ptr)
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index f05fbe31576..aa223fc546a 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -73,6 +73,7 @@
#ifndef __ASSEMBLY__
#include <linux/linkage.h>
+#include <linux/irqflags.h>
struct thread_info;
struct task_struct;
@@ -139,23 +140,44 @@ static inline int cpu_is_xsc3(void)
#define cpu_is_xscale() 1
#endif
-#define set_cr(x) \
- __asm__ __volatile__( \
- "mcr p15, 0, %0, c1, c0, 0 @ set CR" \
- : : "r" (x) : "cc")
-
-#define get_cr() \
- ({ \
- unsigned int __val; \
- __asm__ __volatile__( \
- "mrc p15, 0, %0, c1, c0, 0 @ get CR" \
- : "=r" (__val) : : "cc"); \
- __val; \
- })
-
extern unsigned long cr_no_alignment; /* defined in entry-armv.S */
extern unsigned long cr_alignment; /* defined in entry-armv.S */
+static inline unsigned int get_cr(void)
+{
+ unsigned int val;
+ asm("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc");
+ return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+ asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
+ : : "r" (val) : "cc");
+}
+
+#ifndef CONFIG_SMP
+extern void adjust_cr(unsigned long mask, unsigned long set);
+#endif
+
+#define CPACC_FULL(n) (3 << (n * 2))
+#define CPACC_SVC(n) (1 << (n * 2))
+#define CPACC_DISABLE(n) (0 << (n * 2))
+
+static inline unsigned int get_copro_access(void)
+{
+ unsigned int val;
+ asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access"
+ : "=r" (val) : : "cc");
+ return val;
+}
+
+static inline void set_copro_access(unsigned int val)
+{
+ asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
+ : : "r" (val) : "cc");
+}
+
#define UDBG_UNDEFINED (1 << 0)
#define UDBG_SYSCALL (1 << 1)
#define UDBG_BADABORT (1 << 2)
@@ -211,8 +233,6 @@ static inline void sched_cacheflush(void)
{
}
-#include <linux/irqflags.h>
-
#ifdef CONFIG_SMP
#define smp_mb() mb()
diff --git a/include/asm-arm/termbits.h b/include/asm-arm/termbits.h
index bbc6e1d24d3..a3f4fe1742d 100644
--- a/include/asm-arm/termbits.h
+++ b/include/asm-arm/termbits.h
@@ -15,6 +15,18 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index d9b8bddc873..5014794f9eb 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -147,6 +147,7 @@ extern void iwmmxt_task_switch(struct thread_info *);
#define TIF_POLLING_NRFLAG 16
#define TIF_USING_IWMMXT 17
#define TIF_MEMDIE 18
+#define TIF_FREEZE 19
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
@@ -154,6 +155,7 @@ extern void iwmmxt_task_switch(struct thread_info *);
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
+#define _TIF_FREEZE (1 << TIF_FREEZE)
/*
* Change these and you break ASM code in entry-common.S
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index d44c629d842..97e7060000c 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -347,6 +347,31 @@
#define __NR_mbind (__NR_SYSCALL_BASE+319)
#define __NR_get_mempolicy (__NR_SYSCALL_BASE+320)
#define __NR_set_mempolicy (__NR_SYSCALL_BASE+321)
+#define __NR_openat (__NR_SYSCALL_BASE+322)
+#define __NR_mkdirat (__NR_SYSCALL_BASE+323)
+#define __NR_mknodat (__NR_SYSCALL_BASE+324)
+#define __NR_fchownat (__NR_SYSCALL_BASE+325)
+#define __NR_futimesat (__NR_SYSCALL_BASE+326)
+#define __NR_fstatat64 (__NR_SYSCALL_BASE+327)
+#define __NR_unlinkat (__NR_SYSCALL_BASE+328)
+#define __NR_renameat (__NR_SYSCALL_BASE+329)
+#define __NR_linkat (__NR_SYSCALL_BASE+330)
+#define __NR_symlinkat (__NR_SYSCALL_BASE+331)
+#define __NR_readlinkat (__NR_SYSCALL_BASE+332)
+#define __NR_fchmodat (__NR_SYSCALL_BASE+333)
+#define __NR_faccessat (__NR_SYSCALL_BASE+334)
+ /* 335 for pselect6 */
+ /* 336 for ppoll */
+#define __NR_unshare (__NR_SYSCALL_BASE+337)
+#define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
+#define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
+#define __NR_splice (__NR_SYSCALL_BASE+340)
+#define __NR_arm_sync_file_range (__NR_SYSCALL_BASE+341)
+#define __NR_tee (__NR_SYSCALL_BASE+342)
+#define __NR_vmsplice (__NR_SYSCALL_BASE+343)
+#define __NR_move_pages (__NR_SYSCALL_BASE+344)
+#define __NR_getcpu (__NR_SYSCALL_BASE+345)
+ /* 346 for epoll_pwait */
/*
* The following SWIs are ARM private.
diff --git a/include/asm-arm26/cacheflush.h b/include/asm-arm26/cacheflush.h
index 9c1b9c7f2eb..14ae15b6faa 100644
--- a/include/asm-arm26/cacheflush.h
+++ b/include/asm-arm26/cacheflush.h
@@ -22,6 +22,7 @@
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma,start,end) do { } while (0)
#define flush_cache_page(vma,vmaddr,pfn) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h
index bbc6e1d24d3..a3f4fe1742d 100644
--- a/include/asm-arm26/termbits.h
+++ b/include/asm-arm26/termbits.h
@@ -15,6 +15,18 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-avr32/arch-at32ap/at32ap7000.h b/include/asm-avr32/arch-at32ap/at32ap7000.h
new file mode 100644
index 00000000000..ba85e04553d
--- /dev/null
+++ b/include/asm-avr32/arch-at32ap/at32ap7000.h
@@ -0,0 +1,33 @@
+/*
+ * Pin definitions for AT32AP7000.
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_AT32AP7000_H__
+#define __ASM_ARCH_AT32AP7000_H__
+
+#define GPIO_PERIPH_A 0
+#define GPIO_PERIPH_B 1
+
+#define NR_GPIO_CONTROLLERS 4
+
+/*
+ * Pin numbers identifying specific GPIO pins on the chip. They can
+ * also be converted to IRQ numbers by passing them through
+ * gpio_to_irq().
+ */
+#define GPIO_PIOA_BASE (0)
+#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32)
+#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32)
+#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32)
+
+#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N))
+#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N))
+#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N))
+#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
+
+#endif /* __ASM_ARCH_AT32AP7000_H__ */
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
index a39b3e999f1..b120ee030c8 100644
--- a/include/asm-avr32/arch-at32ap/board.h
+++ b/include/asm-avr32/arch-at32ap/board.h
@@ -21,10 +21,7 @@ void at32_map_usart(unsigned int hw_id, unsigned int line);
struct platform_device *at32_add_device_usart(unsigned int id);
struct eth_platform_data {
- u8 valid;
- u8 mii_phy_addr;
u8 is_rmii;
- u8 hw_addr[6];
};
struct platform_device *
at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
diff --git a/include/asm-avr32/arch-at32ap/portmux.h b/include/asm-avr32/arch-at32ap/portmux.h
index 4d50421262a..83c69057132 100644
--- a/include/asm-avr32/arch-at32ap/portmux.h
+++ b/include/asm-avr32/arch-at32ap/portmux.h
@@ -7,10 +7,20 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#ifndef __ASM_AVR32_AT32_PORTMUX_H__
-#define __ASM_AVR32_AT32_PORTMUX_H__
+#ifndef __ASM_ARCH_PORTMUX_H__
+#define __ASM_ARCH_PORTMUX_H__
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
- unsigned int function_id);
+/*
+ * Set up pin multiplexing, called from board init only.
+ *
+ * The following flags determine the initial state of the pin.
+ */
+#define AT32_GPIOF_PULLUP 0x00000001 /* Enable pull-up */
+#define AT32_GPIOF_OUTPUT 0x00000002 /* Enable output driver */
+#define AT32_GPIOF_HIGH 0x00000004 /* Set output high */
+
+void at32_select_periph(unsigned int pin, unsigned int periph,
+ unsigned long flags);
+void at32_select_gpio(unsigned int pin, unsigned long flags);
-#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */
+#endif /* __ASM_ARCH_PORTMUX_H__ */
diff --git a/include/asm-avr32/cacheflush.h b/include/asm-avr32/cacheflush.h
index f1bf1708980..dfaaa88cd41 100644
--- a/include/asm-avr32/cacheflush.h
+++ b/include/asm-avr32/cacheflush.h
@@ -87,6 +87,7 @@ void invalidate_icache_region(void *start, size_t len);
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h
index 0580b5d62bb..5c01e27f0b4 100644
--- a/include/asm-avr32/dma-mapping.h
+++ b/include/asm-avr32/dma-mapping.h
@@ -109,7 +109,7 @@ static inline dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)
{
- dma_cache_sync(cpu_addr, size, direction);
+ dma_cache_sync(dev, cpu_addr, size, direction);
return virt_to_bus(cpu_addr);
}
@@ -211,7 +211,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
virt = page_address(sg[i].page) + sg[i].offset;
- dma_cache_sync(virt, sg[i].length, direction);
+ dma_cache_sync(dev, virt, sg[i].length, direction);
}
return nents;
@@ -256,14 +256,14 @@ static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
- dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+ dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
}
static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
- dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+ dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
}
/**
@@ -286,7 +286,7 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
int i;
for (i = 0; i < nents; i++) {
- dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+ dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
sg[i].length, direction);
}
}
@@ -298,7 +298,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
int i;
for (i = 0; i < nents; i++) {
- dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+ dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
sg[i].length, direction);
}
}
diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h
index 7492cfb92ce..bb82e70cde8 100644
--- a/include/asm-avr32/pgalloc.h
+++ b/include/asm-avr32/pgalloc.h
@@ -28,7 +28,7 @@ static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
{
unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
- pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
+ pgd_t *pgd = kmalloc(pgd_size, GFP_KERNEL);
if (pgd)
memset(pgd, 0, pgd_size);
diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h
index 9dc6eacafa3..c215fafdae4 100644
--- a/include/asm-avr32/termbits.h
+++ b/include/asm-avr32/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h
index 72cc71dffe7..01af2de27c5 100644
--- a/include/asm-cris/cacheflush.h
+++ b/include/asm-cris/cacheflush.h
@@ -9,6 +9,7 @@
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index be0836d2f28..8d8cec225fe 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -19,6 +19,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-frv/Kbuild b/include/asm-frv/Kbuild
index c68e1680da0..966a9836d55 100644
--- a/include/asm-frv/Kbuild
+++ b/include/asm-frv/Kbuild
@@ -1 +1,7 @@
include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+
+unifdef-y += termios.h
+unifdef-y += ptrace.h
+unifdef-y += page.h
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index 1f70d47148b..f8560edf59f 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -256,6 +256,50 @@ int __ffs(unsigned long x)
return 31 - bit;
}
+/*
+ * special slimline version of fls() for calculating ilog2_u32()
+ * - note: no protection against n == 0
+ */
+#define ARCH_HAS_ILOG2_U32
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+ int bit;
+ asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n));
+ return 31 - bit;
+}
+
+/*
+ * special slimline version of fls64() for calculating ilog2_u64()
+ * - note: no protection against n == 0
+ */
+#define ARCH_HAS_ILOG2_U64
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+ union {
+ u64 ll;
+ struct { u32 h, l; };
+ } _;
+ int bit, x, y;
+
+ _.ll = n;
+
+ asm(" subcc %3,gr0,gr0,icc0 \n"
+ " ckeq icc0,cc4 \n"
+ " cscan.p %3,gr0,%0 ,cc4,0 \n"
+ " setlos #63,%1 \n"
+ " cscan.p %4,gr0,%0 ,cc4,1 \n"
+ " setlos #31,%2 \n"
+ " csub.p %1,%0,%0 ,cc4,0 \n"
+ " csub %2,%0,%0 ,cc4,1 \n"
+ : "=&r"(bit), "=r"(x), "=r"(y)
+ : "0r"(_.h), "r"(_.l)
+ : "icc0", "cc4"
+ );
+ return bit;
+}
+
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
diff --git a/include/asm-frv/cacheflush.h b/include/asm-frv/cacheflush.h
index eaa5826bc1c..02500405a6f 100644
--- a/include/asm-frv/cacheflush.h
+++ b/include/asm-frv/cacheflush.h
@@ -20,6 +20,7 @@
*/
#define flush_cache_all() do {} while(0)
#define flush_cache_mm(mm) do {} while(0)
+#define flush_cache_dup_mm(mm) do {} while(0)
#define flush_cache_range(mm, start, end) do {} while(0)
#define flush_cache_page(vma, vmaddr, pfn) do {} while(0)
#define flush_cache_vmap(start, end) do {} while(0)
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index 134cc0cdf6c..213d92fd652 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -76,8 +76,6 @@ extern unsigned long max_pfn;
#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
#define WANT_PAGE_VIRTUAL 1
#endif
@@ -85,4 +83,6 @@ extern unsigned long max_pfn;
#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
+#endif /* __KERNEL__ */
+
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-frv/ptrace.h b/include/asm-frv/ptrace.h
index 9a2241b8eb1..cf6934012b6 100644
--- a/include/asm-frv/ptrace.h
+++ b/include/asm-frv/ptrace.h
@@ -12,9 +12,11 @@
#define _ASM_PTRACE_H
#include <asm/registers.h>
+#ifdef __KERNEL__
#include <asm/irq_regs.h>
#define in_syscall(regs) (((regs)->tbr & TBR_TT) == TBR_TT_TRAP0)
+#endif
#define PT_PSR 0
@@ -60,6 +62,7 @@
#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */
#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */
+#ifdef __KERNEL__
#ifndef __ASSEMBLY__
/*
@@ -74,6 +77,7 @@ register struct pt_regs *__frame asm("gr28");
extern unsigned long user_stack(const struct pt_regs *);
extern void show_regs(struct pt_regs *);
#define profile_pc(regs) ((regs)->pc)
+#endif
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_PTRACE_H */
diff --git a/include/asm-frv/termbits.h b/include/asm-frv/termbits.h
index 74f20d6e292..2d6d389cff4 100644
--- a/include/asm-frv/termbits.h
+++ b/include/asm-frv/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-frv/termios.h b/include/asm-frv/termios.h
index b4a664e7f55..8840cf95e8d 100644
--- a/include/asm-frv/termios.h
+++ b/include/asm-frv/termios.h
@@ -69,6 +69,8 @@ struct termio {
#define N_SYNC_PPP 14
#define N_HCI 15 /* Bluetooth HCI UART */
+#ifdef __KERNEL__
#include <asm-generic/termios.h>
+#endif
#endif /* _ASM_TERMIOS_H */
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index d66c48e6ef1..d881f518e6a 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -116,6 +116,7 @@ register struct thread_info *__current_thread_info asm("gr15");
#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* OOM killer killed process */
+#define TIF_FREEZE 18 /* freezing for suspend */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
@@ -125,6 +126,7 @@ register struct thread_info *__current_thread_info asm("gr15");
#define _TIF_IRET (1 << TIF_IRET)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE (1 << TIF_FREEZE)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index c92ae0f166f..14fae1fa87d 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -4,6 +4,22 @@
#include <linux/compiler.h>
#ifdef CONFIG_BUG
+
+#ifdef CONFIG_GENERIC_BUG
+#ifndef __ASSEMBLY__
+struct bug_entry {
+ unsigned long bug_addr;
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+ const char *file;
+ unsigned short line;
+#endif
+ unsigned short flags;
+};
+#endif /* __ASSEMBLY__ */
+
+#define BUGFLAG_WARNING (1<<0)
+#endif /* CONFIG_GENERIC_BUG */
+
#ifndef HAVE_ARCH_BUG
#define BUG() do { \
printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
@@ -19,7 +35,7 @@
#define WARN_ON(condition) ({ \
typeof(condition) __ret_warn_on = (condition); \
if (unlikely(__ret_warn_on)) { \
- printk("BUG: warning at %s:%d/%s()\n", __FILE__, \
+ printk("BUG: at %s:%d %s()\n", __FILE__, \
__LINE__, __FUNCTION__); \
dump_stack(); \
} \
diff --git a/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h
index 9202fd02d5b..62fb3618293 100644
--- a/include/asm-generic/libata-portmap.h
+++ b/include/asm-generic/libata-portmap.h
@@ -3,10 +3,10 @@
#define ATA_PRIMARY_CMD 0x1F0
#define ATA_PRIMARY_CTL 0x3F6
-#define ATA_PRIMARY_IRQ 14
+#define ATA_PRIMARY_IRQ(dev) 14
#define ATA_SECONDARY_CMD 0x170
#define ATA_SECONDARY_CTL 0x376
-#define ATA_SECONDARY_IRQ 15
+#define ATA_SECONDARY_IRQ(dev) 15
#endif
diff --git a/include/asm-generic/page.h b/include/asm-generic/page.h
index a96b5d986b6..b55052ce233 100644
--- a/include/asm-generic/page.h
+++ b/include/asm-generic/page.h
@@ -4,21 +4,51 @@
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
-#include <linux/compiler.h>
+#include <linux/log2.h>
-/* Pure 2^n version of get_order */
-static __inline__ __attribute_const__ int get_order(unsigned long size)
+/*
+ * non-const pure 2^n version of get_order
+ * - the arch may override these in asm/bitops.h if they can be implemented
+ * more efficiently than using the arch log2 routines
+ * - we use the non-const log2() instead if the arch has defined one suitable
+ */
+#ifndef ARCH_HAS_GET_ORDER
+static inline __attribute__((const))
+int __get_order(unsigned long size, int page_shift)
{
+#if BITS_PER_LONG == 32 && defined(ARCH_HAS_ILOG2_U32)
+ int order = __ilog2_u32(size) - page_shift;
+ return order >= 0 ? order : 0;
+#elif BITS_PER_LONG == 64 && defined(ARCH_HAS_ILOG2_U64)
+ int order = __ilog2_u64(size) - page_shift;
+ return order >= 0 ? order : 0;
+#else
int order;
- size = (size - 1) >> (PAGE_SHIFT - 1);
+ size = (size - 1) >> (page_shift - 1);
order = -1;
do {
size >>= 1;
order++;
} while (size);
return order;
+#endif
}
+#endif
+
+/**
+ * get_order - calculate log2(pages) to hold a block of the specified size
+ * @n - size
+ *
+ * calculate allocation order based on the current page size
+ * - this can be used to initialise global variables from constant data
+ */
+#define get_order(n) \
+( \
+ __builtin_constant_p(n) ? \
+ ((n < (1UL << PAGE_SHIFT)) ? 0 : ilog2(n) - PAGE_SHIFT) : \
+ __get_order(n, PAGE_SHIFT) \
+ )
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-generic/termios.h b/include/asm-generic/termios.h
index 1e58ca39592..3769e6bd63b 100644
--- a/include/asm-generic/termios.h
+++ b/include/asm-generic/termios.h
@@ -11,7 +11,7 @@
/*
* Translate a "termio" structure into a "termios". Ugh.
*/
-static inline int user_termio_to_kernel_termios(struct termios *termios,
+static inline int user_termio_to_kernel_termios(struct ktermios *termios,
struct termio __user *termio)
{
unsigned short tmp;
@@ -48,7 +48,7 @@ static inline int user_termio_to_kernel_termios(struct termios *termios,
* Translate a "termios" structure into a "termio". Ugh.
*/
static inline int kernel_termios_to_user_termio(struct termio __user *termio,
- struct termios *termios)
+ struct ktermios *termios)
{
if (put_user(termios->c_iflag, &termio->c_iflag) < 0 ||
put_user(termios->c_oflag, &termio->c_oflag) < 0 ||
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4d4c62d1105..9fcc8d9fbb1 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -35,6 +35,9 @@
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
*(.pci_fixup_enable) \
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
+ VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
+ *(.pci_fixup_resume) \
+ VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
} \
\
/* RapidIO route ops */ \
@@ -119,8 +122,6 @@
*(__ksymtab_strings) \
} \
\
- EH_FRAME \
- \
/* Built-in module parameters. */ \
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___param) = .; \
@@ -160,26 +161,6 @@
*(.kprobes.text) \
VMLINUX_SYMBOL(__kprobes_text_end) = .;
-#ifdef CONFIG_STACK_UNWIND
-#define EH_FRAME \
- /* Unwind data binary search table */ \
- . = ALIGN(8); \
- .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start_unwind_hdr) = .; \
- *(.eh_frame_hdr) \
- VMLINUX_SYMBOL(__end_unwind_hdr) = .; \
- } \
- /* Unwind data */ \
- . = ALIGN(8); \
- .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start_unwind) = .; \
- *(.eh_frame) \
- VMLINUX_SYMBOL(__end_unwind) = .; \
- }
-#else
-#define EH_FRAME
-#endif
-
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to
the beginning of the section so we begin them at 0. */
@@ -218,6 +199,14 @@
.stab.indexstr 0 : { *(.stab.indexstr) } \
.comment 0 : { *(.comment) }
+#define BUG_TABLE \
+ . = ALIGN(8); \
+ __bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \
+ __start___bug_table = .; \
+ *(__bug_table) \
+ __stop___bug_table = .; \
+ }
+
#define NOTES \
.notes : { *(.note.*) } :note
@@ -234,6 +223,7 @@
*(.initcall4s.init) \
*(.initcall5.init) \
*(.initcall5s.init) \
+ *(.initcallrootfs.init) \
*(.initcall6.init) \
*(.initcall6s.init) \
*(.initcall7.init) \
diff --git a/include/asm-h8300/cacheflush.h b/include/asm-h8300/cacheflush.h
index 1e4d95bb5ec..71210d141b6 100644
--- a/include/asm-h8300/cacheflush.h
+++ b/include/asm-h8300/cacheflush.h
@@ -12,6 +12,7 @@
#define flush_cache_all()
#define flush_cache_mm(mm)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma,a,b)
#define flush_cache_page(vma,p,pfn)
#define flush_dcache_page(page)
diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h
index fa69ae00eda..6a1f4d3807b 100644
--- a/include/asm-h8300/termbits.h
+++ b/include/asm-h8300/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index c80b3a94511..7cfad93edf1 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -56,30 +56,8 @@
#define ACPI_ENABLE_IRQS() local_irq_enable()
#define ACPI_FLUSH_CPU_CACHE() wbinvd()
-
-static inline int
-__acpi_acquire_global_lock (unsigned int *lock)
-{
- unsigned int old, new, val;
- do {
- old = *lock;
- new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
- val = cmpxchg(lock, old, new);
- } while (unlikely (val != old));
- return (new < 3) ? -1 : 0;
-}
-
-static inline int
-__acpi_release_global_lock (unsigned int *lock)
-{
- unsigned int old, new, val;
- do {
- old = *lock;
- new = old & ~0x3;
- val = cmpxchg(lock, old, new);
- } while (unlikely (val != old));
- return old & 0x1;
-}
+int __acpi_acquire_global_lock(unsigned int *lock);
+int __acpi_release_global_lock(unsigned int *lock);
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr))
diff --git a/include/asm-i386/boot.h b/include/asm-i386/boot.h
index 8ce79a6fa89..e7686d0a841 100644
--- a/include/asm-i386/boot.h
+++ b/include/asm-i386/boot.h
@@ -13,7 +13,8 @@
#define ASK_VGA 0xfffd /* ask for it at bootup */
/* Physical address where kenrel should be loaded. */
-#define LOAD_PHYSICAL_ADDR ((0x100000 + CONFIG_PHYSICAL_ALIGN - 1) \
+#define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
+ + (CONFIG_PHYSICAL_ALIGN - 1)) \
& ~(CONFIG_PHYSICAL_ALIGN - 1))
#endif /* _LINUX_BOOT_H */
diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h
index 8062cdbf258..b0fd78ca261 100644
--- a/include/asm-i386/bug.h
+++ b/include/asm-i386/bug.h
@@ -4,20 +4,32 @@
/*
* Tell the user there is some problem.
- * The offending file and line are encoded after the "officially
- * undefined" opcode for parsing in the trap handler.
+ * The offending file and line are encoded encoded in the __bug_table section.
*/
#ifdef CONFIG_BUG
#define HAVE_ARCH_BUG
+
#ifdef CONFIG_DEBUG_BUGVERBOSE
-#define BUG() \
- __asm__ __volatile__( "ud2\n" \
- "\t.word %c0\n" \
- "\t.long %c1\n" \
- : : "i" (__LINE__), "i" (__FILE__))
+#define BUG() \
+ do { \
+ asm volatile("1:\tud2\n" \
+ ".pushsection __bug_table,\"a\"\n" \
+ "2:\t.long 1b, %c0\n" \
+ "\t.word %c1, 0\n" \
+ "\t.org 2b+%c2\n" \
+ ".popsection" \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (sizeof(struct bug_entry))); \
+ for(;;) ; \
+ } while(0)
+
#else
-#define BUG() __asm__ __volatile__("ud2\n")
+#define BUG() \
+ do { \
+ asm volatile("ud2"); \
+ for(;;) ; \
+ } while(0)
#endif
#endif
diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
index 7199f7b326f..74e03c8f2e5 100644
--- a/include/asm-i386/cacheflush.h
+++ b/include/asm-i386/cacheflush.h
@@ -7,6 +7,7 @@
/* Caches aren't brain-dead on the intel. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index 395077aba58..c5b8fc6109d 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -40,7 +40,7 @@ extern int e820_all_mapped(unsigned long start, unsigned long end,
unsigned type);
extern void find_max_pfn(void);
extern void register_bootmem_low_pages(unsigned long max_low_pfn);
-extern void register_memory(void);
+extern void e820_register_memory(void);
extern void limit_regions(unsigned long long size);
extern void print_memory_map(char *who);
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index 45d21a0c95b..369035dfe4b 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -143,11 +143,8 @@ extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct
# define VDSO_PRELINK 0
#endif
-#define VDSO_COMPAT_SYM(x) \
- (VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
-
#define VDSO_SYM(x) \
- (VDSO_BASE + (unsigned long)(x) - VDSO_PRELINK)
+ (VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
#define VDSO_HIGH_EHDR ((const struct elfhdr *) VDSO_HIGH_BASE)
#define VDSO_EHDR ((const struct elfhdr *) VDSO_COMPAT_BASE)
@@ -156,10 +153,12 @@ extern void __kernel_vsyscall;
#define VDSO_ENTRY VDSO_SYM(&__kernel_vsyscall)
+#ifndef CONFIG_COMPAT_VDSO
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int executable_stack);
+#endif
extern unsigned int vdso_enabled;
@@ -169,50 +168,6 @@ do if (vdso_enabled) { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE); \
} while (0)
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents. Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS (VDSO_HIGH_EHDR->e_phnum)
-#define ELF_CORE_WRITE_EXTRA_PHDRS \
-do { \
- const struct elf_phdr *const vsyscall_phdrs = \
- (const struct elf_phdr *) (VDSO_HIGH_BASE \
- + VDSO_HIGH_EHDR->e_phoff); \
- int i; \
- Elf32_Off ofs = 0; \
- for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \
- struct elf_phdr phdr = vsyscall_phdrs[i]; \
- if (phdr.p_type == PT_LOAD) { \
- BUG_ON(ofs != 0); \
- ofs = phdr.p_offset = offset; \
- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
- phdr.p_filesz = phdr.p_memsz; \
- offset += phdr.p_filesz; \
- } \
- else \
- phdr.p_offset += ofs; \
- phdr.p_paddr = 0; /* match other core phdrs */ \
- DUMP_WRITE(&phdr, sizeof(phdr)); \
- } \
-} while (0)
-#define ELF_CORE_WRITE_EXTRA_DATA \
-do { \
- const struct elf_phdr *const vsyscall_phdrs = \
- (const struct elf_phdr *) (VDSO_HIGH_BASE \
- + VDSO_HIGH_EHDR->e_phoff); \
- int i; \
- for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \
- if (vsyscall_phdrs[i].p_type == PT_LOAD) \
- DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
- PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
- } \
-} while (0)
-
#endif
#endif
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 02428cb3662..3e9f610c35d 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -23,6 +23,8 @@
extern unsigned long __FIXADDR_TOP;
#else
#define __FIXADDR_TOP 0xfffff000
+#define FIXADDR_USER_START __fix_to_virt(FIX_VDSO)
+#define FIXADDR_USER_END __fix_to_virt(FIX_VDSO - 1)
#endif
#ifndef __ASSEMBLY__
diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h
index 73465d2892b..0fc240c80f4 100644
--- a/include/asm-i386/ide.h
+++ b/include/asm-i386/ide.h
@@ -40,13 +40,14 @@ static __inline__ int ide_default_irq(unsigned long base)
static __inline__ unsigned long ide_default_io_base(int index)
{
+ struct pci_dev *pdev;
/*
* If PCI is present then it is not safe to poke around
* the other legacy IDE ports. Only 0x1f0 and 0x170 are
* defined compatibility mode ports for PCI. A user can
* override this using ide= but we must default safe.
*/
- if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) == NULL) {
+ if ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL)) == NULL) {
switch(index) {
case 2: return 0x1e8;
case 3: return 0x168;
@@ -54,6 +55,7 @@ static __inline__ unsigned long ide_default_io_base(int index)
case 5: return 0x160;
}
}
+ pci_dev_put(pdev);
switch (index) {
case 0: return 0x1f0;
case 1: return 0x170;
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 5679d499307..609a3899475 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -100,6 +100,8 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
#define MSR_P6_PERFCTR0 0xc1
#define MSR_P6_PERFCTR1 0xc2
+#define MSR_FSB_FREQ 0xcd
+
#define MSR_IA32_BBL_CR_CTL 0x119
@@ -130,6 +132,9 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
#define MSR_IA32_PERF_STATUS 0x198
#define MSR_IA32_PERF_CTL 0x199
+#define MSR_IA32_MPERF 0xE7
+#define MSR_IA32_APERF 0xE8
+
#define MSR_IA32_THERM_CONTROL 0x19a
#define MSR_IA32_THERM_INTERRUPT 0x19b
#define MSR_IA32_THERM_STATUS 0x19c
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index fd3f64ace24..7b19f454761 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -143,7 +143,9 @@ extern int page_is_ram(unsigned long pagenr);
#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
+#ifndef CONFIG_COMPAT_VDSO
#define __HAVE_ARCH_GATE_AREA 1
+#endif
#endif /* __KERNEL__ */
#endif /* _I386_PAGE_H */
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index a52d6544042..359f10b54f5 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -743,6 +743,7 @@ extern void enable_sep_cpu(void);
extern int sysenter_setup(void);
extern int init_gdt(int cpu, struct task_struct *idle);
+extern void cpu_set_gdt(int);
extern void secondary_cpu_init(void);
#endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-i386/termbits.h b/include/asm-i386/termbits.h
index 72c10e3190f..12baf1d6343 100644
--- a/include/asm-i386/termbits.h
+++ b/include/asm-i386/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 46d32ad9208..4b187bb377b 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -134,6 +134,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_MEMDIE 16
#define TIF_DEBUG 17 /* uses debug registers */
#define TIF_IO_BITMAP 18 /* uses I/O bitmap */
+#define TIF_FREEZE 19 /* is freezing for suspend */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -147,6 +148,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 978d0959613..ac58580ad66 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -89,6 +89,7 @@ static inline int node_to_first_cpu(int node)
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_EXEC \
| SD_BALANCE_FORK \
+ | SD_SERIALIZE \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
.balance_interval = 1, \
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
index aa2c931e30d..43c70c3de2f 100644
--- a/include/asm-i386/unwind.h
+++ b/include/asm-i386/unwind.h
@@ -1,95 +1,6 @@
#ifndef _ASM_I386_UNWIND_H
#define _ASM_I386_UNWIND_H
-/*
- * Copyright (C) 2002-2006 Novell, Inc.
- * Jan Beulich <jbeulich@novell.com>
- * This code is released under version 2 of the GNU GPL.
- */
-
-#ifdef CONFIG_STACK_UNWIND
-
-#include <linux/sched.h>
-#include <asm/fixmap.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-
-struct unwind_frame_info
-{
- struct pt_regs regs;
- struct task_struct *task;
- unsigned call_frame:1;
-};
-
-#define UNW_PC(frame) (frame)->regs.eip
-#define UNW_SP(frame) (frame)->regs.esp
-#ifdef CONFIG_FRAME_POINTER
-#define UNW_FP(frame) (frame)->regs.ebp
-#define FRAME_RETADDR_OFFSET 4
-#define FRAME_LINK_OFFSET 0
-#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0)
-#define STACK_TOP(tsk) ((tsk)->thread.esp0)
-#else
-#define UNW_FP(frame) ((void)(frame), 0)
-#endif
-#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1))
-
-#define UNW_REGISTER_INFO \
- PTREGS_INFO(eax), \
- PTREGS_INFO(ecx), \
- PTREGS_INFO(edx), \
- PTREGS_INFO(ebx), \
- PTREGS_INFO(esp), \
- PTREGS_INFO(ebp), \
- PTREGS_INFO(esi), \
- PTREGS_INFO(edi), \
- PTREGS_INFO(eip)
-
-#define UNW_DEFAULT_RA(raItem, dataAlign) \
- ((raItem).where == Memory && \
- !((raItem).value * (dataAlign) + 4))
-
-static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
- /*const*/ struct pt_regs *regs)
-{
- if (user_mode_vm(regs))
- info->regs = *regs;
- else {
- memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
- info->regs.esp = (unsigned long)&regs->esp;
- info->regs.xss = __KERNEL_DS;
- }
-}
-
-static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
-{
- memset(&info->regs, 0, sizeof(info->regs));
- info->regs.eip = info->task->thread.eip;
- info->regs.xcs = __KERNEL_CS;
- __get_user(info->regs.ebp, (long *)info->task->thread.esp);
- info->regs.esp = info->task->thread.esp;
- info->regs.xss = __KERNEL_DS;
- info->regs.xds = __USER_DS;
- info->regs.xes = __USER_DS;
- info->regs.xgs = __KERNEL_PDA;
-}
-
-extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
- asmlinkage int (*callback)(struct unwind_frame_info *,
- void *arg),
- void *arg);
-
-static inline int arch_unw_user_mode(/*const*/ struct unwind_frame_info *info)
-{
- return user_mode_vm(&info->regs)
- || info->regs.eip < PAGE_OFFSET
- || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
- && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
- || info->regs.esp < PAGE_OFFSET;
-}
-
-#else
-
#define UNW_PC(frame) ((void)(frame), 0)
#define UNW_SP(frame) ((void)(frame), 0)
#define UNW_FP(frame) ((void)(frame), 0)
@@ -99,6 +10,4 @@ static inline int arch_unw_user_mode(const void *info)
return 0;
}
-#endif
-
#endif /* _ASM_I386_UNWIND_H */
diff --git a/include/asm-ia64/break.h b/include/asm-ia64/break.h
index 8167828edc4..f0340203989 100644
--- a/include/asm-ia64/break.h
+++ b/include/asm-ia64/break.h
@@ -12,8 +12,8 @@
* OS-specific debug break numbers:
*/
#define __IA64_BREAK_KDB 0x80100
-#define __IA64_BREAK_KPROBE 0x80200
-#define __IA64_BREAK_JPROBE 0x80300
+#define __IA64_BREAK_KPROBE 0x81000 /* .. 0x81fff */
+#define __IA64_BREAK_JPROBE 0x82000
/*
* OS-specific break numbers:
diff --git a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h
index f2dacb4245e..4906916d715 100644
--- a/include/asm-ia64/cacheflush.h
+++ b/include/asm-ia64/cacheflush.h
@@ -18,6 +18,7 @@
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma,page) do { } while (0)
diff --git a/include/asm-ia64/checksum.h b/include/asm-ia64/checksum.h
index 2b78582cbd6..97af155057e 100644
--- a/include/asm-ia64/checksum.h
+++ b/include/asm-ia64/checksum.h
@@ -72,8 +72,8 @@ static inline __sum16 csum_fold(__wsum csum)
#define _HAVE_ARCH_IPV6_CSUM 1
struct in6_addr;
-extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
- struct in6_addr *daddr, __u32 len, unsigned short proto,
- unsigned int csum);
+extern __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr, __u32 len, unsigned short proto,
+ __wsum csum);
#endif /* _ASM_IA64_CHECKSUM_H */
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 1b45b71c79b..828ae00e47c 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -115,6 +115,7 @@ struct arch_specific_insn {
#define INST_FLAG_BREAK_INST 4
unsigned long inst_flag;
unsigned short target_br_reg;
+ unsigned short slot;
};
extern int kprobe_exceptions_notify(struct notifier_block *self,
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index 825eb7d882e..5160233bbfa 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -78,9 +78,6 @@ pcibios_penalize_isa_irq (int irq, int active)
#define pci_dac_dma_sync_single_for_cpu(dev,dma_addr,len,dir) do { } while (0)
#define pci_dac_dma_sync_single_for_device(dev,dma_addr,len,dir) do { mb(); } while (0)
-#define sg_dma_len(sg) ((sg)->dma_length)
-#define sg_dma_address(sg) ((sg)->dma_address)
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -170,4 +167,10 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
#define pcibios_scan_all_fns(a, b) 0
+#define HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return channel ? 15 : 14;
+}
+
#endif /* _ASM_IA64_PCI_H */
diff --git a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h
index adb62272694..17885567b73 100644
--- a/include/asm-ia64/posix_types.h
+++ b/include/asm-ia64/posix_types.h
@@ -54,7 +54,7 @@ typedef unsigned int __kernel_old_dev_t;
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
#define __FD_ZERO(set) \
- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+ ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
# else /* !__GNUC__ */
diff --git a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h
index 834a189ef18..9dbea8844d5 100644
--- a/include/asm-ia64/scatterlist.h
+++ b/include/asm-ia64/scatterlist.h
@@ -25,4 +25,7 @@ struct scatterlist {
*/
#define ISA_DMA_THRESHOLD 0xffffffff
+#define sg_dma_len(sg) ((sg)->dma_length)
+#define sg_dma_address(sg) ((sg)->dma_address)
+
#endif /* _ASM_IA64_SCATTERLIST_H */
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index 1d45e1518fb..e52b8508083 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -673,7 +673,7 @@ extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
extern void xpc_dropped_IPI_check(struct xpc_partition *);
extern void xpc_activate_partition(struct xpc_partition *);
extern void xpc_activate_kthreads(struct xpc_channel *, int);
-extern void xpc_create_kthreads(struct xpc_channel *, int);
+extern void xpc_create_kthreads(struct xpc_channel *, int, int);
extern void xpc_disconnect_wait(int);
diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h
index b9e843f7dc4..4531a511bde 100644
--- a/include/asm-ia64/termbits.h
+++ b/include/asm-ia64/termbits.h
@@ -26,6 +26,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 8adcde0934c..9b505b25544 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -88,6 +88,7 @@ struct thread_info {
#define TIF_MEMDIE 17
#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
#define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */
+#define TIF_FREEZE 20 /* is freezing for suspend */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
@@ -98,6 +99,7 @@ struct thread_info {
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_MCA_INIT (1 << TIF_MCA_INIT)
#define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED)
+#define _TIF_FREEZE (1 << TIF_FREEZE)
/* "work to do on user-return" bits */
#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index a6e38565ab4..22ed6749557 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -101,6 +101,7 @@ void build_cpu_to_node_map(void);
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_EXEC \
| SD_BALANCE_FORK \
+ | SD_SERIALIZE \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
.balance_interval = 64, \
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
index 8b261b49149..56961a9511b 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/include/asm-m32r/cacheflush.h
@@ -9,6 +9,7 @@ extern void _flush_cache_copyback_all(void);
#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
@@ -29,6 +30,7 @@ extern void smp_flush_cache_all(void);
#elif defined(CONFIG_CHIP_M32102)
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
@@ -41,6 +43,7 @@ extern void smp_flush_cache_all(void);
#else
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index 219a0f74eff..c82ebe8f250 100644
--- a/include/asm-m32r/ide.h
+++ b/include/asm-m32r/ide.h
@@ -32,7 +32,8 @@
static __inline__ int ide_default_irq(unsigned long base)
{
switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
+ || defined(CONFIG_PLAT_OPSPUT)
case 0x1f0: return PLD_IRQ_CFIREQ;
default:
return 0;
diff --git a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h
index a1f0d1fe9eb..52807f8db16 100644
--- a/include/asm-m32r/m32102.h
+++ b/include/asm-m32r/m32102.h
@@ -104,7 +104,8 @@
#define M32R_MFT5RLD_PORTL (0x0C+M32R_MFT5_OFFSET) /* MFT4 reload */
#define M32R_MFT5CMPRLD_PORTL (0x10+M32R_MFT5_OFFSET) /* MFT4 compare reload */
-#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32104)
+#if (defined(CONFIG_CHIP_M32700) && !defined(CONFIG_PLAT_MAPPI2)) \
+ || defined(CONFIG_CHIP_M32104)
#define M32R_MFTCR_MFT0MSK (1UL<<31) /* b0 */
#define M32R_MFTCR_MFT1MSK (1UL<<30) /* b1 */
#define M32R_MFTCR_MFT2MSK (1UL<<29) /* b2 */
@@ -117,7 +118,7 @@
#define M32R_MFTCR_MFT3EN (1UL<<20) /* b11 */
#define M32R_MFTCR_MFT4EN (1UL<<19) /* b12 */
#define M32R_MFTCR_MFT5EN (1UL<<18) /* b13 */
-#else /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */
+#else
#define M32R_MFTCR_MFT0MSK (1UL<<15) /* b16 */
#define M32R_MFTCR_MFT1MSK (1UL<<14) /* b17 */
#define M32R_MFTCR_MFT2MSK (1UL<<13) /* b18 */
@@ -130,7 +131,7 @@
#define M32R_MFTCR_MFT3EN (1UL<<4) /* b27 */
#define M32R_MFTCR_MFT4EN (1UL<<3) /* b28 */
#define M32R_MFTCR_MFT5EN (1UL<<2) /* b29 */
-#endif /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */
+#endif
#define M32R_MFTMOD_CC_MASK (1UL<<15) /* b16 */
#define M32R_MFTMOD_TCCR (1UL<<13) /* b18 */
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 2d2a6c97331..632b4ce4269 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -33,21 +33,10 @@
#define PT_R15 PT_SP
/* processor status and miscellaneous context registers. */
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
#define PT_ACC0H 15
#define PT_ACC0L 16
-#define PT_ACC1H 17
-#define PT_ACC1L 18
-#define PT_ACCH PT_ACC0H
-#define PT_ACCL PT_ACC0L
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH 15
-#define PT_ACCL 16
-#define PT_DUMMY_ACC1H 17
-#define PT_DUMMY_ACC1L 18
-#else
-#error unknown isa conifiguration
-#endif
+#define PT_ACC1H 17 /* ISA_DSP_LEVEL2 only */
+#define PT_ACC1L 18 /* ISA_DSP_LEVEL2 only */
#define PT_PSW 19
#define PT_BPC 20
#define PT_BBPSW 21
@@ -103,19 +92,10 @@ struct pt_regs {
long syscall_nr;
/* Saved main processor status and miscellaneous context registers. */
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
unsigned long acc0h;
unsigned long acc0l;
- unsigned long acc1h;
- unsigned long acc1l;
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
- unsigned long acch;
- unsigned long accl;
- unsigned long dummy_acc1h;
- unsigned long dummy_acc1l;
-#else
-#error unknown isa configuration
-#endif
+ unsigned long acc1h; /* ISA_DSP_LEVEL2 only */
+ unsigned long acc1l; /* ISA_DSP_LEVEL2 only */
unsigned long psw;
unsigned long bpc; /* saved PC for TRAP syscalls */
unsigned long bbpsw;
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index 73025c0c41a..62537dc4dec 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -23,19 +23,10 @@ struct sigcontext {
unsigned long sc_r12;
/* Saved main processor status and miscellaneous context registers. */
-#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
unsigned long sc_acc0h;
unsigned long sc_acc0l;
- unsigned long sc_acc1h;
- unsigned long sc_acc1l;
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
- unsigned long sc_acch;
- unsigned long sc_accl;
- unsigned long sc_dummy_acc1h;
- unsigned long sc_dummy_acc1l;
-#else
-#error unknown isa configuration
-#endif
+ unsigned long sc_acc1h; /* ISA_DSP_LEVEL2 only */
+ unsigned long sc_acc1l; /* ISA_DSP_LEVEL2 only */
unsigned long sc_psw;
unsigned long sc_bpc; /* saved PC for TRAP syscalls */
unsigned long sc_bbpsw;
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index 5ace3702df7..faf2bd0504c 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -19,6 +19,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
index 24d3ff44913..16bf375fdbe 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/include/asm-m68k/cacheflush.h
@@ -89,6 +89,8 @@ static inline void flush_cache_mm(struct mm_struct *mm)
__flush_cache_030();
}
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
/* flush_cache_range/flush_cache_page must be macros to avoid
a dependency on linux/mm.h, which includes this file... */
static inline void flush_cache_range(struct vm_area_struct *vma,
diff --git a/include/asm-m68k/sun3-head.h b/include/asm-m68k/sun3-head.h
index f799d95bad5..e74f384e269 100644
--- a/include/asm-m68k/sun3-head.h
+++ b/include/asm-m68k/sun3-head.h
@@ -4,7 +4,6 @@
#define KERNBASE 0xE000000 /* First address the kernel will eventually be */
#define LOAD_ADDR 0x4000 /* prom jumps to us here unless this is elf /boot */
-#define BI_START (KERNBASE + 0x3000) /* beginning of the bootinfo records */
#define FC_CONTROL 3
#define FC_SUPERD 5
#define FC_CPU 7
diff --git a/include/asm-m68k/sun3ints.h b/include/asm-m68k/sun3ints.h
index de91fa071b9..309d6e6a137 100644
--- a/include/asm-m68k/sun3ints.h
+++ b/include/asm-m68k/sun3ints.h
@@ -16,6 +16,7 @@
#include <asm/intersil.h>
#include <asm/oplib.h>
#include <asm/traps.h>
+#include <asm/irq.h>
#define SUN3_INT_VECS 192
diff --git a/include/asm-m68k/swim_iop.h b/include/asm-m68k/swim_iop.h
deleted file mode 100644
index f29b67876b0..00000000000
--- a/include/asm-m68k/swim_iop.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * SWIM access through the IOP
- * Written by Joshua M. Thompson
- */
-
-/* IOP number and channel number for the SWIM */
-
-#define SWIM_IOP IOP_NUM_ISM
-#define SWIM_CHAN 1
-
-/* Command code: */
-
-#define CMD_INIT 0x01 /* Initialize */
-#define CMD_SHUTDOWN 0x02 /* Shutdown */
-#define CMD_START_POLL 0x03 /* Start insert/eject polling */
-#define CMD_STOP_POLL 0x04 /* Stop insert/eject polling */
-#define CMD_SETHFSTAG 0x05 /* Set HFS tag buffer address */
-#define CMD_STATUS 0x06 /* Status */
-#define CMD_EJECT 0x07 /* Eject */
-#define CMD_FORMAT 0x08 /* Format */
-#define CMD_FORMAT_VERIFY 0x09 /* Format and Verify */
-#define CMD_WRITE 0x0A /* Write */
-#define CMD_READ 0x0B /* Read */
-#define CMD_READ_VERIFY 0x0C /* Read and Verify */
-#define CMD_CACHE_CTRL 0x0D /* Cache control */
-#define CMD_TAGBUFF_CTRL 0x0E /* Tag buffer control */
-#define CMD_GET_ICON 0x0F /* Get Icon */
-
-/* Drive types: */
-
-/* note: apple sez DRV_FDHD is 4, but I get back a type */
-/* of 5 when I do a drive status check on my FDHD */
-
-#define DRV_NONE 0 /* No drive */
-#define DRV_UNKNOWN 1 /* Unspecified drive */
-#define DRV_400K 2 /* 400K */
-#define DRV_800K 3 /* 400K/800K */
-#define DRV_FDHD 5 /* 400K/800K/720K/1440K */
-#define DRV_HD20 7 /* Apple HD20 */
-
-/* Format types: */
-
-#define FMT_HD20 0x0001 /* Apple HD20 */
-#define FMT_400K 0x0002 /* 400K (GCR) */
-#define FMT_800K 0x0004 /* 800K (GCR) */
-#define FMT_720K 0x0008 /* 720K (MFM) */
-#define FMT_1440K 0x0010 /* 1.44M (MFM) */
-
-#define FMD_KIND_400K 1
-#define FMD_KIND_800K 2
-#define FMD_KIND_720K 3
-#define FMD_KIND_1440K 1
-
-/* Icon Flags: */
-
-#define ICON_MEDIA 0x01 /* Have IOP supply media icon */
-#define ICON_DRIVE 0x01 /* Have IOP supply drive icon */
-
-/* Error codes: */
-
-#define gcrOnMFMErr -400 /* GCR (400/800K) on HD media */
-#define verErr -84 /* verify failed */
-#define fmt2Err -83 /* can't get enough sync during format */
-#define fmt1Err -82 /* can't find sector 0 after track format */
-#define sectNFErr -81 /* can't find sector */
-#define seekErr -80 /* drive error during seek */
-#define spdAdjErr -79 /* can't set drive speed */
-#define twoSideErr -78 /* drive is single-sided */
-#define initIWMErr -77 /* error during initialization */
-#define tk0badErr -76 /* track zero is bad */
-#define cantStepErr -75 /* drive error during step */
-#define wrUnderrun -74 /* write underrun occurred */
-#define badDBtSlp -73 /* bad data bitslip marks */
-#define badDCksum -72 /* bad data checksum */
-#define noDtaMkErr -71 /* can't find data mark */
-#define badBtSlpErr -70 /* bad address bitslip marks */
-#define badCksmErr -69 /* bad address-mark checksum */
-#define dataVerErr -68 /* read-verify failed */
-#define noAdrMkErr -67 /* can't find an address mark */
-#define noNybErr -66 /* no nybbles? disk is probably degaussed */
-#define offLinErr -65 /* no disk in drive */
-#define noDriveErr -64 /* drive isn't connected */
-#define nsDrvErr -56 /* no such drive */
-#define paramErr -50 /* bad positioning information */
-#define wPrErr -44 /* write protected */
-#define openErr -23 /* already initialized */
-
-#ifndef __ASSEMBLY__
-
-struct swim_drvstatus {
- __u16 curr_track; /* Current track number */
- __u8 write_prot; /* 0x80 if disk is write protected */
- __u8 disk_in_drive; /* 0x01 or 0x02 if a disk is in the drive */
- __u8 installed; /* 0x01 if drive installed, 0xFF if not */
- __u8 num_sides; /* 0x80 if two-sided format supported */
- __u8 two_sided; /* 0xff if two-sided format diskette */
- __u8 new_interface; /* 0x00 if old 400K drive, 0xFF if newer */
- __u16 errors; /* Disk error count */
- struct { /* 32 bits */
- __u16 reserved;
- __u16 :4;
- __u16 external:1; /* Drive is external */
- __u16 scsi:1; /* Drive is a SCSI drive */
- __u16 fixed:1; /* Drive has fixed media */
- __u16 secondary:1; /* Drive is secondary drive */
- __u8 type; /* Drive type */
- } info;
- __u8 mfm_drive; /* 0xFF if this is an FDHD drive */
- __u8 mfm_disk; /* 0xFF if 720K/1440K (MFM) disk */
- __u8 mfm_format; /* 0x00 if 720K, 0xFF if 1440K */
- __u8 ctlr_type; /* 0x00 if IWM, 0xFF if SWIM */
- __u16 curr_format; /* Current format type */
- __u16 allowed_fmt; /* Allowed format types */
- __u32 num_blocks; /* Number of blocks on disk */
- __u8 icon_flags; /* Icon flags */
- __u8 unusued;
-};
-
-/* Commands issued from the host to the IOP: */
-
-struct swimcmd_init {
- __u8 code; /* CMD_INIT */
- __u8 unusued;
- __u16 error;
- __u8 drives[28]; /* drive type list */
-};
-
-struct swimcmd_startpoll {
- __u8 code; /* CMD_START_POLL */
- __u8 unusued;
- __u16 error;
-};
-
-struct swimcmd_sethfstag {
- __u8 code; /* CMD_SETHFSTAG */
- __u8 unusued;
- __u16 error;
- caddr_t tagbuf; /* HFS tag buffer address */
-};
-
-struct swimcmd_status {
- __u8 code; /* CMD_STATUS */
- __u8 drive_num;
- __u16 error;
- struct swim_drvstatus status;
-};
-
-struct swimcmd_eject {
- __u8 code; /* CMD_EJECT */
- __u8 drive_num;
- __u16 error;
- struct swim_drvstatus status;
-};
-
-struct swimcmd_format {
- __u8 code; /* CMD_FORMAT */
- __u8 drive_num;
- __u16 error;
- union {
- struct {
- __u16 fmt; /* format kind */
- __u8 hdrbyte; /* fmt byte for hdr (0=default) */
- __u8 interleave; /* interleave (0 = default) */
- caddr_t databuf; /* sector data buff (0=default */
- caddr_t tagbuf; /* tag data buffer (0=default) */
- } f;
- struct swim_drvstatus status;
- } p;
-};
-
-struct swimcmd_fmtverify {
- __u8 code; /* CMD_FORMAT_VERIFY */
- __u8 drive_num;
- __u16 error;
-};
-
-struct swimcmd_rw {
- __u8 code; /* CMD_READ, CMD_WRITE or CMD_READ_VERIFY */
- __u8 drive_num;
- __u16 error;
- caddr_t buffer; /* R/W buffer address */
- __u32 first_block; /* Starting block */
- __u32 num_blocks; /* Number of blocks */
- __u8 tag[12]; /* tag data */
-};
-
-struct swimcmd_cachectl {
- __u8 code; /* CMD_CACHE_CTRL */
- __u8 unused;
- __u16 error;
- __u8 enable; /* Nonzero to enable cache */
- __u8 install; /* +1 = install, -1 = remove, 0 = neither */
-};
-
-struct swimcmd_tagbufctl {
- __u8 code; /* CMD_TAGBUFF_CTRL */
- __u8 unused;
- __u16 error;
- caddr_t buf; /* buffer address or 0 to disable */
-};
-
-struct swimcmd_geticon {
- __u8 code; /* CMD_GET_ICON */
- __u8 drive_num;
- __u16 error;
- caddr_t buffer; /* Nuffer address */
- __u16 kind; /* 0 = media icon, 1 = drive icon */
- __u16 unused;
- __u16 max_bytes; /* maximum byte count */
-};
-
-/* Messages from the SWIM IOP to the host CPU: */
-
-struct swimmsg_status {
- __u8 code; /* 1 = insert, 2 = eject, 3 = status changed */
- __u8 drive_num;
- __u16 error;
- struct swim_drvstatus status;
-};
-
-#endif /* __ASSEMBLY__ */
diff --git a/include/asm-m68k/termbits.h b/include/asm-m68k/termbits.h
index e9eec3eb071..a194092240f 100644
--- a/include/asm-m68k/termbits.h
+++ b/include/asm-m68k/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index e4c9f080ff2..6a4cf208151 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -7,6 +7,7 @@
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/types.h>
+#include <linux/sched.h>
#include <asm/segment.h>
#define VERIFY_READ 0
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index c3aadf3b0d8..163dcb1a968 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -8,6 +8,7 @@
#define flush_cache_all() __flush_cache_all()
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) __flush_cache_all()
#define flush_cache_page(vma, vmaddr) do { } while (0)
#define flush_dcache_range(start,len) __flush_cache_all()
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index 1e5ccdad3b0..8e321f53a38 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -131,6 +131,7 @@
#define MACH_PHILIPS_NINO 0 /* Nino */
#define MACH_PHILIPS_VELO 1 /* Velo */
#define MACH_PHILIPS_JBS 2 /* JBS */
+#define MACH_PHILIPS_STB810 3 /* STB810 */
/*
* Valid machtype for group SIBYTE
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index e3c9925876a..0ddada3bb0b 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -17,6 +17,7 @@
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_dup mm(mm) handles cache flushing when forking
* - 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
@@ -31,6 +32,7 @@
extern void (*flush_cache_all)(void);
extern void (*__flush_cache_all)(void);
extern void (*flush_cache_mm)(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0)
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, unsigned long pfn);
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index 9b768c3b96b..20a81e1548f 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -29,31 +29,38 @@
*/
__wsum csum_partial(const void *buff, int len, __wsum sum);
+__wsum __csum_partial_copy_user(const void *src, void *dst,
+ int len, __wsum sum, int *err_ptr);
+
/*
* this is a new version of the above that records errors it finds in *errp,
* but continues and zeros the rest of the buffer.
*/
-__wsum csum_partial_copy_from_user(const void __user *src,
- void *dst, int len,
- __wsum sum, int *errp);
+static inline
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+ __wsum sum, int *err_ptr)
+{
+ might_sleep();
+ return __csum_partial_copy_user((__force void *)src, dst,
+ len, sum, err_ptr);
+}
/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static inline __wsum csum_and_copy_to_user (const void *src, void __user *dst,
- int len, __wsum sum,
- int *err_ptr)
+static inline
+__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
+ __wsum sum, int *err_ptr)
{
might_sleep();
- sum = csum_partial(src, len, sum);
-
- if (copy_to_user(dst, src, len)) {
+ if (access_ok(VERIFY_WRITE, dst, len))
+ return __csum_partial_copy_user(src, (__force void *)dst,
+ len, sum, err_ptr);
+ if (len)
*err_ptr = -EFAULT;
- return (__force __wsum)-1;
- }
- return sum;
+ return (__force __wsum)-1; /* invalid checksum */
}
/*
@@ -152,7 +159,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr,
#endif
" .set pop"
: "=r" (sum)
- : "0" (daddr), "r"(saddr),
+ : "0" ((__force unsigned long)daddr),
+ "r" ((__force unsigned long)saddr),
#ifdef __MIPSEL__
"r" ((proto + len) << 8),
#else
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 55a0152feb0..432653d7ae0 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -5,6 +5,7 @@
*/
#include <linux/types.h>
#include <asm/page.h>
+#include <asm/ptrace.h>
#define COMPAT_USER_HZ 100
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index 0fe02945feb..50073157a61 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -157,7 +157,7 @@ ASMMACRO(back_to_back_c0_hazard,
* processors.
*/
ASMMACRO(mtc0_tlbw_hazard,
- nop
+ nop; nop
)
ASMMACRO(tlbw_use_hazard,
nop; nop; nop
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 67657089efa..386da82e577 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -31,14 +31,14 @@ static inline int irq_canonicalize(int irq)
* functions will take over re-enabling the low-level mask.
* Otherwise it will be done on return from exception.
*/
-#define __DO_IRQ_SMTC_HOOK() \
+#define __DO_IRQ_SMTC_HOOK(irq) \
do { \
if (irq_hwmask[irq] & 0x0000ff00) \
write_c0_tccontext(read_c0_tccontext() & \
~(irq_hwmask[irq] & 0x0000ff00)); \
} while (0)
#else
-#define __DO_IRQ_SMTC_HOOK() do { } while (0)
+#define __DO_IRQ_SMTC_HOOK(irq) do { } while (0)
#endif
/*
@@ -52,7 +52,7 @@ do { \
#define do_IRQ(irq) \
do { \
irq_enter(); \
- __DO_IRQ_SMTC_HOOK(); \
+ __DO_IRQ_SMTC_HOOK(irq); \
generic_handle_irq(irq); \
irq_exit(); \
} while (0)
diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h
index 46bf5de5ac7..af3b07dfad4 100644
--- a/include/asm-mips/irqflags.h
+++ b/include/asm-mips/irqflags.h
@@ -15,6 +15,27 @@
#include <asm/hazards.h>
+/*
+ * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs,
+ * at the cost of branch and call overhead on each local_irq_restore()
+ */
+
+#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY
+
+extern void smtc_ipi_replay(void);
+
+#define irq_restore_epilog(flags) \
+do { \
+ if (!(flags & 0x0400)) \
+ smtc_ipi_replay(); \
+} while (0)
+
+#else
+
+#define irq_restore_epilog(ignore) do { } while (0)
+
+#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */
+
__asm__ (
" .macro raw_local_irq_enable \n"
" .set push \n"
@@ -193,6 +214,7 @@ do { \
: "=r" (__tmp1) \
: "0" (flags) \
: "memory"); \
+ irq_restore_epilog(flags); \
} while(0)
static inline int raw_irqs_disabled_flags(unsigned long flags)
diff --git a/include/asm-mips/mach-ip27/irq.h b/include/asm-mips/mach-ip27/irq.h
index 806213ce31b..25f0c3f39ad 100644
--- a/include/asm-mips/mach-ip27/irq.h
+++ b/include/asm-mips/mach-ip27/irq.h
@@ -10,8 +10,6 @@
#ifndef __ASM_MACH_IP27_IRQ_H
#define __ASM_MACH_IP27_IRQ_H
-#include <asm/sn/arch.h>
-
/*
* A hardwired interrupt number is completly stupid for this system - a
* large configuration might have thousands if not tenthousands of
diff --git a/include/asm-mips/mach-ip27/topology.h b/include/asm-mips/mach-ip27/topology.h
index a13b715fd9c..44790fdc5d0 100644
--- a/include/asm-mips/mach-ip27/topology.h
+++ b/include/asm-mips/mach-ip27/topology.h
@@ -1,7 +1,6 @@
#ifndef _ASM_MACH_TOPOLOGY_H
#define _ASM_MACH_TOPOLOGY_H 1
-#include <asm/sn/arch.h>
#include <asm/sn/hub.h>
#include <asm/mmzone.h>
diff --git a/include/asm-mips/mach-rm200/cpu-feature-overrides.h b/include/asm-mips/mach-rm/cpu-feature-overrides.h
index 11410ae10d3..11410ae10d3 100644
--- a/include/asm-mips/mach-rm200/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-rm/cpu-feature-overrides.h
diff --git a/include/asm-mips/mach-rm200/mc146818rtc.h b/include/asm-mips/mach-rm/mc146818rtc.h
index d37ae68dc6a..d37ae68dc6a 100644
--- a/include/asm-mips/mach-rm200/mc146818rtc.h
+++ b/include/asm-mips/mach-rm/mc146818rtc.h
diff --git a/include/asm-mips/mach-rm200/timex.h b/include/asm-mips/mach-rm/timex.h
index 11ff6cb0f21..11ff6cb0f21 100644
--- a/include/asm-mips/mach-rm200/timex.h
+++ b/include/asm-mips/mach-rm/timex.h
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 0dc1a45c27e..2f9e1a9ec51 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -35,7 +35,6 @@
#ifndef __ASSEMBLY__
#include <linux/pfn.h>
-#include <asm/cpu-features.h>
#include <asm/io.h>
extern void clear_page(void * page);
@@ -61,16 +60,13 @@ static inline void clear_user_page(void *addr, unsigned long vaddr,
flush_data_cache_page((unsigned long)addr);
}
-static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
- struct page *to)
-{
- extern void (*flush_data_cache_page)(unsigned long addr);
+extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+ struct page *to);
+struct vm_area_struct;
+extern void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma);
- copy_page(vto, vfrom);
- if (!cpu_has_ic_fills_f_dc ||
- pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
- flush_data_cache_page((unsigned long)vto);
-}
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
/*
* These are used to make use of C type-checking..
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index c4d68bebdca..7f0f120ca07 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -187,4 +187,10 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
/* Do platform specific device initialization at pci_enable_device() time */
extern int pcibios_plat_dev_init(struct pci_dev *dev);
+/* Chances are this interrupt is wired PC-style ... */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return channel ? 15 : 14;
+}
+
#endif /* _ASM_PCI_H */
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index f2e1325fec6..3fcfd7979de 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -69,16 +69,6 @@ extern unsigned long zero_page_mask;
#define ZERO_PAGE(vaddr) \
(virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))))
-#define __HAVE_ARCH_MOVE_PTE
-#define move_pte(pte, prot, old_addr, new_addr) \
-({ \
- pte_t newpte = (pte); \
- if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \
- pte_page(pte) == ZERO_PAGE(old_addr)) \
- newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \
- newpte; \
-})
-
extern void paging_init(void);
/*
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 30bf555faea..8a1f2b6f04a 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -82,6 +82,14 @@ struct pt_regs {
extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
+extern NORET_TYPE void die(const char *, struct pt_regs *);
+
+static inline void die_if_kernel(const char *str, struct pt_regs *regs)
+{
+ if (unlikely(!user_mode(regs)))
+ die(str, regs);
+}
+
#endif
#endif /* _ASM_PTRACE_H */
diff --git a/include/asm-mips/sn/arch.h b/include/asm-mips/sn/arch.h
index 51174af6ac5..da523de628b 100644
--- a/include/asm-mips/sn/arch.h
+++ b/include/asm-mips/sn/arch.h
@@ -18,7 +18,6 @@
#endif
typedef u64 hubreg_t;
-typedef u64 nic_t;
#define cputonasid(cpu) (cpu_data[(cpu)].p_nasid)
#define cputoslice(cpu) (cpu_data[(cpu)].p_slice)
diff --git a/include/asm-mips/sn/klconfig.h b/include/asm-mips/sn/klconfig.h
index 15d70ca5618..82aeb9e322d 100644
--- a/include/asm-mips/sn/klconfig.h
+++ b/include/asm-mips/sn/klconfig.h
@@ -61,6 +61,8 @@
#endif /* CONFIG_SGI_IP35 */
#endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */
+typedef u64 nic_t;
+
#define KLCFGINFO_MAGIC 0xbeedbabe
typedef s32 klconf_off_t;
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 9428057a50c..5e1289c85ed 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -19,7 +19,6 @@
#include <asm/barrier.h>
#include <asm/cpu-features.h>
#include <asm/dsp.h>
-#include <asm/ptrace.h>
#include <asm/war.h>
@@ -336,14 +335,6 @@ extern void *set_except_vector(int n, void *addr);
extern unsigned long ebase;
extern void per_cpu_trap_init(void);
-extern NORET_TYPE void die(const char *, struct pt_regs *);
-
-static inline void die_if_kernel(const char *str, struct pt_regs *regs)
-{
- if (unlikely(!user_mode(regs)))
- die(str, regs);
-}
-
extern int stop_a_enabled;
/*
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
index b62ec7c521c..0bbe07b42a0 100644
--- a/include/asm-mips/termbits.h
+++ b/include/asm-mips/termbits.h
@@ -30,6 +30,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0 /* Interrupt character [ISIG]. */
#define VQUIT 1 /* Quit character [ISIG]. */
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index e475c45ea26..fbcda820447 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -118,6 +118,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18
+#define TIF_FREEZE 19
#define TIF_SYSCALL_TRACE 31 /* syscall trace active */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -129,6 +130,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK (0x0000ffef & ~_TIF_SECCOMP)
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index 3ac146c019c..13a3502eef4 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -76,7 +76,7 @@
/*
* But the RM200C seems to have been shipped only with V2.0 R4600s
*/
-#ifdef CONFIG_SNI_RM200_PCI
+#ifdef CONFIG_SNI_RM
#define R4600_V2_HIT_CACHEOP_WAR 1
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 2bc41f2e027..a799dd8ef39 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -15,6 +15,8 @@
#define flush_cache_mm(mm) flush_cache_all_local()
#endif
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
#define flush_kernel_dcache_range(start,size) \
flush_kernel_dcache_range_asm((start), (start)+(size));
@@ -184,7 +186,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
}
static inline void
-flush_anon_page(struct page *page, unsigned long vmaddr)
+flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
{
if (PageAnon(page))
flush_user_dcache_page(vmaddr);
diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h
index 372b634892c..a46e299a939 100644
--- a/include/asm-parisc/termbits.h
+++ b/include/asm-parisc/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 1e637381c11..703970fb0ec 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -17,7 +17,6 @@ header-y += ipc.h
header-y += poll.h
header-y += shmparam.h
header-y += sockios.h
-header-y += spu_info.h
header-y += ucontext.h
header-y += ioctl.h
header-y += linkage.h
@@ -37,6 +36,7 @@ unifdef-y += posix_types.h
unifdef-y += ptrace.h
unifdef-y += seccomp.h
unifdef-y += signal.h
+unifdef-y += spu_info.h
unifdef-y += termios.h
unifdef-y += types.h
unifdef-y += unistd.h
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index 53283e2540b..f038e33e6d4 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -207,7 +207,8 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
/*
* Atomically test *v and decrement if it is greater than 0.
- * The function returns the old value of *v minus 1.
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
*/
static __inline__ int atomic_dec_if_positive(atomic_t *v)
{
@@ -216,14 +217,15 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
__asm__ __volatile__(
LWSYNC_ON_SMP
"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
- addic. %0,%0,-1\n\
+ cmpwi %0,1\n\
+ addi %0,%0,-1\n\
blt- 2f\n"
PPC405_ERR77(0,%1)
" stwcx. %0,0,%1\n\
bne- 1b"
ISYNC_ON_SMP
"\n\
-2:" : "=&r" (t)
+2:" : "=&b" (t)
: "r" (&v->counter)
: "cc", "memory");
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index c341063d080..8f757f6246e 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -190,7 +190,8 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr)
* Return the zero-based bit position (LE, not IBM bit numbering) of
* the most significant 1-bit in a double word.
*/
-static __inline__ int __ilog2(unsigned long x)
+static __inline__ __attribute__((const))
+int __ilog2(unsigned long x)
{
int lz;
@@ -198,6 +199,24 @@ static __inline__ int __ilog2(unsigned long x)
return BITS_PER_LONG - 1 - lz;
}
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+ int bit;
+ asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n));
+ return 31 - bit;
+}
+
+#ifdef __powerpc64__
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+ int bit;
+ asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n));
+ return 63 - bit;
+}
+#endif
+
/*
* Determines the bit position of the least significant 0 bit in the
* specified double word. The returned bit position will be
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index 978b2c7e84e..f6fa3947484 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -11,24 +11,48 @@
#define BUG_OPCODE .long 0x00b00b00 /* For asm */
#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */
-#ifndef __ASSEMBLY__
-
-struct bug_entry {
- unsigned long bug_addr;
- long line;
- const char *file;
- const char *function;
-};
-
-struct bug_entry *find_bug(unsigned long bugaddr);
+#ifdef CONFIG_BUG
-/*
- * If this bit is set in the line number it means that the trap
- * is for WARN_ON rather than BUG or BUG_ON.
- */
-#define BUG_WARNING_TRAP 0x1000000
+#ifdef __ASSEMBLY__
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+.macro EMIT_BUG_ENTRY addr,file,line,flags
+ .section __bug_table,"a"
+5001: PPC_LONG \addr, 5002f
+ .short \line, \flags
+ .org 5001b+BUG_ENTRY_SIZE
+ .previous
+ .section .rodata,"a"
+5002: .asciz "\file"
+ .previous
+.endm
+#else
+ .macro EMIT_BUG_ENTRY addr,file,line,flags
+ .section __bug_table,"a"
+5001: PPC_LONG \addr
+ .short \flags
+ .org 5001b+BUG_ENTRY_SIZE
+ .previous
+.endm
+#endif /* verbose */
-#ifdef CONFIG_BUG
+#else /* !__ASSEMBLY__ */
+/* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
+ sizeof(struct bug_entry), respectively */
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define _EMIT_BUG_ENTRY \
+ ".section __bug_table,\"a\"\n" \
+ "2:\t" PPC_LONG "1b, %0\n" \
+ "\t.short %1, %2\n" \
+ ".org 2b+%3\n" \
+ ".previous\n"
+#else
+#define _EMIT_BUG_ENTRY \
+ ".section __bug_table,\"a\"\n" \
+ "2:\t" PPC_LONG "1b\n" \
+ "\t.short %2\n" \
+ ".org 2b+%3\n" \
+ ".previous\n"
+#endif
/*
* BUG_ON() and WARN_ON() do their best to cooperate with compile-time
@@ -36,13 +60,13 @@ struct bug_entry *find_bug(unsigned long bugaddr);
* some compiler versions may not produce optimal results.
*/
-#define BUG() do { \
- __asm__ __volatile__( \
- "1: twi 31,0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%0,%1,%2\n" \
- ".previous" \
- : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+#define BUG() do { \
+ __asm__ __volatile__( \
+ "1: twi 31,0,0\n" \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (0), "i" (sizeof(struct bug_entry))); \
+ for(;;) ; \
} while (0)
#define BUG_ON(x) do { \
@@ -51,23 +75,21 @@ struct bug_entry *find_bug(unsigned long bugaddr);
BUG(); \
} else { \
__asm__ __volatile__( \
- "1: "PPC_TLNEI" %0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
- ".previous" \
- : : "r" ((long)(x)), "i" (__LINE__), \
- "i" (__FILE__), "i" (__FUNCTION__)); \
+ "1: "PPC_TLNEI" %4,0\n" \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), "i" (0), \
+ "i" (sizeof(struct bug_entry)), \
+ "r" ((long)(x))); \
} \
} while (0)
#define __WARN() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%0,%1,%2\n" \
- ".previous" \
- : : "i" (__LINE__ + BUG_WARNING_TRAP), \
- "i" (__FILE__), "i" (__FUNCTION__)); \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (BUGFLAG_WARNING), \
+ "i" (sizeof(struct bug_entry))); \
} while (0)
#define WARN_ON(x) ({ \
@@ -77,13 +99,12 @@ struct bug_entry *find_bug(unsigned long bugaddr);
__WARN(); \
} else { \
__asm__ __volatile__( \
- "1: "PPC_TLNEI" %0,0\n" \
- ".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
- ".previous" \
- : : "r" (__ret_warn_on), \
- "i" (__LINE__ + BUG_WARNING_TRAP), \
- "i" (__FILE__), "i" (__FUNCTION__)); \
+ "1: "PPC_TLNEI" %4,0\n" \
+ _EMIT_BUG_ENTRY \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (BUGFLAG_WARNING), \
+ "i" (sizeof(struct bug_entry)), \
+ "r" (__ret_warn_on)); \
} \
unlikely(__ret_warn_on); \
})
@@ -91,8 +112,8 @@ struct bug_entry *find_bug(unsigned long bugaddr);
#define HAVE_ARCH_BUG
#define HAVE_ARCH_BUG_ON
#define HAVE_ARCH_WARN_ON
-#endif /* CONFIG_BUG */
#endif /* __ASSEMBLY __ */
+#endif /* CONFIG_BUG */
#include <asm-generic/bug.h>
diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h
index 8a740c88d93..08e93e78921 100644
--- a/include/asm-powerpc/cacheflush.h
+++ b/include/asm-powerpc/cacheflush.h
@@ -18,6 +18,7 @@
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma, page) do { } while (0)
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 6fe5c9d4ca3..7384b8086b7 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -126,6 +126,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
#define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000)
#define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000)
+#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000)
/*
* Add the 64-bit processor unique features in the top half of the word;
@@ -152,6 +153,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000)
#define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000)
#define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000)
+#define CPU_FTR_DSCR LONG_ASM_CONST(0x0002000000000000)
#ifndef __ASSEMBLY__
@@ -295,6 +297,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_COMMON)
+#define CPU_FTRS_E300C2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
#define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
@@ -330,13 +335,14 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
- CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE)
+ CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
+ CPU_FTR_DSCR)
#define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \
- CPU_FTR_SPURR | CPU_FTR_REAL_LE)
+ CPU_FTR_SPURR | CPU_FTR_REAL_LE | CPU_FTR_DSCR)
#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -364,7 +370,8 @@ enum {
CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 |
CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 |
CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
- CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 |
+ CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
+ CPU_FTRS_CLASSIC32 |
#else
CPU_FTRS_GENERIC_32 |
#endif
@@ -403,7 +410,8 @@ enum {
CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 &
CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 &
CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
- CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 &
+ CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
+ CPU_FTRS_CLASSIC32 &
#else
CPU_FTRS_GENERIC_32 &
#endif
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index fd4a5f5e33d..d7a1bc1551c 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -20,8 +20,7 @@
#ifndef _ASM_POWERPC_DCR_NATIVE_H
#define _ASM_POWERPC_DCR_NATIVE_H
#ifdef __KERNEL__
-
-#include <asm/reg.h>
+#ifndef __ASSEMBLY__
typedef struct {} dcr_host_t;
@@ -32,7 +31,41 @@ typedef struct {} dcr_host_t;
#define dcr_read(host, dcr_n) mfdcr(dcr_n)
#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value)
+/* Device Control Registers */
+void __mtdcr(int reg, unsigned int val);
+unsigned int __mfdcr(int reg);
+#define mfdcr(rn) \
+ ({unsigned int rval; \
+ if (__builtin_constant_p(rn)) \
+ asm volatile("mfdcr %0," __stringify(rn) \
+ : "=r" (rval)); \
+ else \
+ rval = __mfdcr(rn); \
+ rval;})
+
+#define mtdcr(rn, v) \
+do { \
+ if (__builtin_constant_p(rn)) \
+ asm volatile("mtdcr " __stringify(rn) ",%0" \
+ : : "r" (v)); \
+ else \
+ __mtdcr(rn, v); \
+} while (0)
+
+/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
+#define mfdcri(base, reg) \
+({ \
+ mtdcr(base ## _CFGADDR, base ## _ ## reg); \
+ mfdcr(base ## _CFGDATA); \
+})
+
+#define mtdcri(base, reg, data) \
+do { \
+ mtdcr(base ## _CFGADDR, base ## _ ## reg); \
+ mtdcr(base ## _CFGDATA, data); \
+} while (0)
+#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_DCR_NATIVE_H */
diff --git a/include/asm-powerpc/dcr.h b/include/asm-powerpc/dcr.h
index 473f2c7fd89..b66c5e6941f 100644
--- a/include/asm-powerpc/dcr.h
+++ b/include/asm-powerpc/dcr.h
@@ -20,6 +20,7 @@
#ifndef _ASM_POWERPC_DCR_H
#define _ASM_POWERPC_DCR_H
#ifdef __KERNEL__
+#ifdef CONFIG_PPC_DCR
#ifdef CONFIG_PPC_DCR_NATIVE
#include <asm/dcr-native.h>
@@ -38,5 +39,6 @@ extern unsigned int dcr_resource_len(struct device_node *np,
unsigned int index);
#endif /* CONFIG_PPC_MERGE */
+#endif /* CONFIG_PPC_DCR */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_DCR_H */
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index 7c7de87bd8a..a19a6f1a1cf 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -37,9 +37,9 @@ extern void __dma_sync_page(struct page *page, unsigned long offset,
*/
#define __dma_alloc_coherent(gfp, size, handle) NULL
-#define __dma_free_coherent(size, addr) do { } while (0)
-#define __dma_sync(addr, size, rw) do { } while (0)
-#define __dma_sync_page(pg, off, sz, rw) do { } while (0)
+#define __dma_free_coherent(size, addr) ((void)0)
+#define __dma_sync(addr, size, rw) ((void)0)
+#define __dma_sync_page(pg, off, sz, rw) ((void)0)
#endif /* ! CONFIG_NOT_COHERENT_CACHE */
@@ -251,7 +251,7 @@ dma_map_single(struct device *dev, void *ptr, size_t size,
}
/* We do nothing. */
-#define dma_unmap_single(dev, addr, size, dir) do { } while (0)
+#define dma_unmap_single(dev, addr, size, dir) ((void)0)
static inline dma_addr_t
dma_map_page(struct device *dev, struct page *page,
@@ -266,7 +266,7 @@ dma_map_page(struct device *dev, struct page *page,
}
/* We do nothing. */
-#define dma_unmap_page(dev, handle, size, dir) do { } while (0)
+#define dma_unmap_page(dev, handle, size, dir) ((void)0)
static inline int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
@@ -286,7 +286,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
}
/* We don't do anything here. */
-#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0)
+#define dma_unmap_sg(dev, sg, nents, dir) ((void)0)
#endif /* CONFIG_PPC64 */
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 257d1cecb8c..7a500732b67 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -252,8 +252,6 @@ struct hcall_stats {
unsigned long tb_total; /* total wall time (mftb) of calls. */
unsigned long purr_total; /* total cpu time (PURR) of calls. */
};
-void update_hcall_stats(unsigned long opcode, unsigned long tb_delta,
- unsigned long purr_delta);
#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1)
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index d604863d72f..9e4dd98eb22 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -107,25 +107,6 @@ static inline void local_irq_save_ptr(unsigned long *flags)
#endif /* CONFIG_PPC64 */
-#define mask_irq(irq) \
- ({ \
- irq_desc_t *desc = get_irq_desc(irq); \
- if (desc->chip && desc->chip->disable) \
- desc->chip->disable(irq); \
- })
-#define unmask_irq(irq) \
- ({ \
- irq_desc_t *desc = get_irq_desc(irq); \
- if (desc->chip && desc->chip->enable) \
- desc->chip->enable(irq); \
- })
-#define ack_irq(irq) \
- ({ \
- irq_desc_t *desc = get_irq_desc(irq); \
- if (desc->chip && desc->chip->ack) \
- desc->chip->ack(irq); \
- })
-
/*
* interrupt-retrigger: should we handle this via lost interrupts and IPIs
* or should we not care like we do now ? --BenH.
diff --git a/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h
new file mode 100644
index 00000000000..4d8518049f4
--- /dev/null
+++ b/include/asm-powerpc/libata-portmap.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_POWERPC_LIBATA_PORTMAP_H
+#define __ASM_POWERPC_LIBATA_PORTMAP_H
+
+#define ATA_PRIMARY_CMD 0x1F0
+#define ATA_PRIMARY_CTL 0x3F6
+#define ATA_PRIMARY_IRQ(dev) pci_get_legacy_ide_irq(dev, 0)
+
+#define ATA_SECONDARY_CMD 0x170
+#define ATA_SECONDARY_CTL 0x376
+#define ATA_SECONDARY_IRQ(dev) pci_get_legacy_ide_irq(dev, 1)
+
+#endif
diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h
index 584fabfb4f0..e5f14b13ccf 100644
--- a/include/asm-powerpc/module.h
+++ b/include/asm-powerpc/module.h
@@ -46,8 +46,6 @@ struct mod_arch_specific {
unsigned int num_bugs;
};
-extern struct bug_entry *module_find_bug(unsigned long bugaddr);
-
/*
* Select ELF headers.
* Make empty section for module_frob_arch_sections to expand.
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
index 4a28a850998..4560d72fc75 100644
--- a/include/asm-powerpc/mpc52xx.h
+++ b/include/asm-powerpc/mpc52xx.h
@@ -244,6 +244,7 @@ struct mpc52xx_cdm {
extern void __iomem * mpc52xx_find_and_map(const char *);
extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node);
extern void mpc52xx_setup_cpu(void);
+extern void mpc52xx_declare_of_platform_devices(void);
extern void mpc52xx_init_irq(void);
extern unsigned int mpc52xx_get_irq(void);
diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h
index 2677bad70f4..07f6d3cf5e5 100644
--- a/include/asm-powerpc/page_32.h
+++ b/include/asm-powerpc/page_32.h
@@ -26,15 +26,7 @@ extern void clear_pages(void *page, int order);
static inline void clear_page(void *page) { clear_pages(page, 0); }
extern void copy_page(void *to, void *from);
-/* Pure 2^n version of get_order */
-extern __inline__ int get_order(unsigned long size)
-{
- int lz;
-
- size = (size-1) >> PAGE_SHIFT;
- asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
- return 32 - lz;
-}
+#include <asm-generic/page.h>
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 7bb7f900980..cb02c9d1ef9 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -31,12 +31,12 @@ struct pci_controller {
int last_busno;
void __iomem *io_base_virt;
- unsigned long io_base_phys;
+ resource_size_t io_base_phys;
/* Some machines have a non 1:1 mapping of
* the PCI memory space in the CPU bus space
*/
- unsigned long pci_mem_offset;
+ resource_size_t pci_mem_offset;
unsigned long pci_io_size;
struct pci_ops *ops;
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index 16f13319c76..ac656ee6bb1 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -143,8 +143,13 @@ 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
-#ifdef CONFIG_PPC64
-/* pci_unmap_{single,page} is not a nop, thus... */
+#if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE)
+/*
+ * For 64-bit kernels, pci_unmap_{single,page} is not a nop.
+ * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and
+ * so on are not nops.
+ * and thus...
+ */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
@@ -158,6 +163,20 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
+#else /* 32-bit && coherent */
+
+/* pci_unmap_{page,single} is a nop so... */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME) (0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME) (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+
+#endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */
+
+#ifdef CONFIG_PPC64
+
/* The PCI address space does not equal the physical memory address
* space (we have an IOMMU). The IDE and SCSI device layers use
* this boolean for bounce buffer decisions.
@@ -172,16 +191,8 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
*/
#define PCI_DMA_BUS_IS_PHYS (1)
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME) (0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME) (0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-
#endif /* CONFIG_PPC64 */
-
+
extern void pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_bus_region *region,
struct resource *res);
diff --git a/include/asm-powerpc/posix_types.h b/include/asm-powerpc/posix_types.h
index c6391077224..2f2288f520b 100644
--- a/include/asm-powerpc/posix_types.h
+++ b/include/asm-powerpc/posix_types.h
@@ -60,7 +60,7 @@ typedef struct {
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
#define __FD_ZERO(set) \
- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+ ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
#else /* __GNUC__ */
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 6faae7b14d5..a3631b15754 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -143,6 +143,7 @@
/* Special Purpose Registers (SPRNs)*/
#define SPRN_CTR 0x009 /* Count Register */
+#define SPRN_DSCR 0x11
#define SPRN_CTRLF 0x088
#define SPRN_CTRLT 0x098
#define CTRL_CT 0xc0000000 /* current thread */
@@ -163,6 +164,7 @@
#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
+#define SPRN_SPURR 0x134 /* Scaled PURR */
#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
index 5a0c136c041..8eaa7b28d9d 100644
--- a/include/asm-powerpc/rtas.h
+++ b/include/asm-powerpc/rtas.h
@@ -159,6 +159,7 @@ extern struct rtas_t rtas;
extern void enter_rtas(unsigned long);
extern int rtas_token(const char *service);
+extern int rtas_service_present(const char *service);
extern int rtas_call(int token, int, int, int *, ...);
extern void rtas_restart(char *cmd);
extern void rtas_power_off(void);
@@ -221,8 +222,6 @@ extern int rtas_get_error_log_max(void);
extern spinlock_t rtas_data_buf_lock;
extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
-extern void rtas_stop_self(void);
-
/* RMO buffer reserved for user-space RTAS use */
extern unsigned long rtas_rmo_buf;
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index fdad4267b44..3d90264e9d3 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -161,6 +161,7 @@ struct spu_syscall_block {
extern long spu_sys_callback(struct spu_syscall_block *s);
/* syscalls implemented in spufs */
+struct file;
extern struct spufs_calls {
asmlinkage long (*create_thread)(const char __user *name,
unsigned int flags, mode_t mode);
@@ -232,6 +233,7 @@ void spu_remove_sysdev_attr_group(struct attribute_group *attrs);
* to object-id spufs file from user space and the notifer
* function can assume that spu->ctx is valid.
*/
+struct notifier_block;
int spu_switch_event_register(struct notifier_block * n);
int spu_switch_event_unregister(struct notifier_block * n);
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h
index 6d533b07aaf..5e79198f7d1 100644
--- a/include/asm-powerpc/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -30,6 +30,19 @@ struct termios {
speed_t c_ospeed; /* output speed */
};
+/* For PowerPC the termios and ktermios are the same */
+
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t c_line; /* line discipline (== c_cc[19]) */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index d339e2e88b1..3f32ca8bfec 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -122,6 +122,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */
#define TIF_NOERROR 14 /* Force successful syscall return */
#define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */
+#define TIF_FREEZE 16 /* Freezing for suspend */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -138,6 +139,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index 50c014007de..6610495f5f1 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -66,6 +66,7 @@ static inline int pcibus_to_node(struct pci_bus *bus)
| SD_BALANCE_EXEC \
| SD_BALANCE_NEWIDLE \
| SD_WAKE_IDLE \
+ | SD_SERIALIZE \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
.balance_interval = 1, \
diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
index 6c955d0c1ef..4d35b844bc5 100644
--- a/include/asm-ppc/pci-bridge.h
+++ b/include/asm-ppc/pci-bridge.h
@@ -20,8 +20,8 @@ extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
extern struct pci_controller* pcibios_alloc_controller(void);
/* Helper function for setting up resources */
-extern void pci_init_resource(struct resource *res, unsigned long start,
- unsigned long end, int flags, char *name);
+extern void pci_init_resource(struct resource *res, resource_size_t start,
+ resource_size_t end, int flags, char *name);
/* Get the PCI host controller for a bus */
extern struct pci_controller* pci_bus_to_hose(int bus);
@@ -50,12 +50,12 @@ struct pci_controller {
int bus_offset;
void __iomem *io_base_virt;
- unsigned long io_base_phys;
+ resource_size_t io_base_phys;
/* Some machines (PReP) have a non 1:1 mapping of
* the PCI memory space in the CPU bus space
*/
- unsigned long pci_mem_offset;
+ resource_size_t pci_mem_offset;
struct pci_ops *ops;
volatile unsigned int __iomem *cfg_addr;
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
index 11ffaaa5da1..9d162028dab 100644
--- a/include/asm-ppc/pci.h
+++ b/include/asm-ppc/pci.h
@@ -61,6 +61,27 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
*/
#define PCI_DMA_BUS_IS_PHYS (1)
+#ifdef CONFIG_NOT_COHERENT_CACHE
+/*
+ * pci_unmap_{page,single} are NOPs but pci_dma_sync_single_for_cpu()
+ * and so on are not, so...
+ */
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
+ dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
+ __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME) \
+ ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
+ (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME) \
+ ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
+ (((PTR)->LEN_NAME) = (VAL))
+
+#else /* coherent */
+
/* pci_unmap_{page,single} is a nop so... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
@@ -69,6 +90,8 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+#endif /* CONFIG_NOT_COHERENT_CACHE */
+
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 602fbadeaf4..a263fc1e65c 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -9,41 +9,9 @@
#ifndef __ASM_PPC_REG_BOOKE_H__
#define __ASM_PPC_REG_BOOKE_H__
-#ifndef __ASSEMBLY__
-/* Device Control Registers */
-void __mtdcr(int reg, unsigned int val);
-unsigned int __mfdcr(int reg);
-#define mfdcr(rn) \
- ({unsigned int rval; \
- if (__builtin_constant_p(rn)) \
- asm volatile("mfdcr %0," __stringify(rn) \
- : "=r" (rval)); \
- else \
- rval = __mfdcr(rn); \
- rval;})
-
-#define mtdcr(rn, v) \
-do { \
- if (__builtin_constant_p(rn)) \
- asm volatile("mtdcr " __stringify(rn) ",%0" \
- : : "r" (v)); \
- else \
- __mtdcr(rn, v); \
-} while (0)
-
-/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
-#define mfdcri(base, reg) \
-({ \
- mtdcr(base ## _CFGADDR, base ## _ ## reg); \
- mfdcr(base ## _CFGDATA); \
-})
-
-#define mtdcri(base, reg, data) \
-do { \
- mtdcr(base ## _CFGADDR, base ## _ ## reg); \
- mtdcr(base ## _CFGDATA, data); \
-} while (0)
+#include <asm/dcr.h>
+#ifndef __ASSEMBLY__
/* Performance Monitor Registers */
#define mfpmr(rn) ({unsigned int rval; \
asm volatile("mfpmr %0," __stringify(rn) \
diff --git a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h
index e399a8ba2ed..f7cade8083f 100644
--- a/include/asm-s390/cacheflush.h
+++ b/include/asm-s390/cacheflush.h
@@ -7,6 +7,7 @@
/* Caches aren't brain-dead on the s390. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h
index c042f957808..604f68fa6f5 100644
--- a/include/asm-s390/dasd.h
+++ b/include/asm-s390/dasd.h
@@ -69,11 +69,13 @@ typedef struct dasd_information2_t {
* 0x01: readonly (ro)
* 0x02: use diag discipline (diag)
* 0x04: set the device initially online (internal use only)
+ * 0x08: enable ERP related logging
*/
#define DASD_FEATURE_DEFAULT 0x00
#define DASD_FEATURE_READONLY 0x01
#define DASD_FEATURE_USEDIAG 0x02
#define DASD_FEATURE_INITIAL_ONLINE 0x04
+#define DASD_FEATURE_ERPLOG 0x08
#define DASD_PARTN_BITS 2
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
index 5e261e1de67..5c5d02de49e 100644
--- a/include/asm-s390/futex.h
+++ b/include/asm-s390/futex.h
@@ -4,8 +4,8 @@
#ifdef __KERNEL__
#include <linux/futex.h>
+#include <linux/uaccess.h>
#include <asm/errno.h>
-#include <asm/uaccess.h>
static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
{
@@ -21,7 +21,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
return -EFAULT;
+ pagefault_disable();
ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval);
+ pagefault_enable();
if (!ret) {
switch (cmp) {
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 363ea761d5e..05ea6f17278 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -127,6 +127,26 @@ page_get_storage_key(unsigned long addr)
return skey;
}
+extern unsigned long max_pfn;
+
+static inline int pfn_valid(unsigned long pfn)
+{
+ unsigned long dummy;
+ int ccode;
+
+ if (pfn >= max_pfn)
+ return 0;
+
+ asm volatile(
+ " lra %0,0(%2)\n"
+ " ipm %1\n"
+ " srl %1,28\n"
+ : "=d" (dummy), "=d" (ccode)
+ : "a" (pfn << PAGE_SHIFT)
+ : "cc");
+ return !ccode;
+}
+
#endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */
@@ -138,8 +158,6 @@ page_get_storage_key(unsigned long addr)
#define __va(x) (void *)(unsigned long)(x)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-
-#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 28619de5eca..0707a7e2fc1 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -25,8 +25,11 @@ extern void diag10(unsigned long addr);
* Page allocation orders.
*/
#ifndef __s390x__
+# define PTE_ALLOC_ORDER 0
+# define PMD_ALLOC_ORDER 0
# define PGD_ALLOC_ORDER 1
#else /* __s390x__ */
+# define PTE_ALLOC_ORDER 0
# define PMD_ALLOC_ORDER 2
# define PGD_ALLOC_ORDER 2
#endif /* __s390x__ */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 2d968a69ed1..ae61aca5d48 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -107,23 +107,25 @@ extern char empty_zero_page[PAGE_SIZE];
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
* area for the same reason. ;)
*/
+extern unsigned long vmalloc_end;
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \
& ~(VMALLOC_OFFSET-1))
+#define VMALLOC_END vmalloc_end
/*
* We need some free virtual space to be able to do vmalloc.
* VMALLOC_MIN_SIZE defines the minimum size of the vmalloc
* area. On a machine with 2GB memory we make sure that we
* have at least 128MB free space for vmalloc. On a machine
- * with 4TB we make sure we have at least 1GB.
+ * with 4TB we make sure we have at least 128GB.
*/
#ifndef __s390x__
#define VMALLOC_MIN_SIZE 0x8000000UL
-#define VMALLOC_END 0x80000000UL
+#define VMALLOC_END_INIT 0x80000000UL
#else /* __s390x__ */
-#define VMALLOC_MIN_SIZE 0x40000000UL
-#define VMALLOC_END 0x40000000000UL
+#define VMALLOC_MIN_SIZE 0x2000000000UL
+#define VMALLOC_END_INIT 0x40000000000UL
#endif /* __s390x__ */
/*
@@ -815,11 +817,17 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define kern_addr_valid(addr) (1)
+extern int add_shared_memory(unsigned long start, unsigned long size);
+extern int remove_shared_memory(unsigned long start, unsigned long size);
+
/*
* No page table caches to initialise
*/
#define pgtable_cache_init() do { } while (0)
+#define __HAVE_ARCH_MEMMAP_INIT
+extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
+
#define __HAVE_ARCH_PTEP_ESTABLISH
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
diff --git a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h
index b94c98856e1..397d93fba3a 100644
--- a/include/asm-s390/posix_types.h
+++ b/include/asm-s390/posix_types.h
@@ -104,7 +104,7 @@ static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp)
#undef __FD_ZERO
#define __FD_ZERO(fdsetp) \
- ((void) memset ((__ptr_t) (fdsetp), 0, sizeof (__kernel_fd_set)))
+ ((void) memset ((void *) (fdsetp), 0, sizeof (__kernel_fd_set)))
#endif /* __KERNEL__ */
diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h
index 7189c79bc67..127f72e7741 100644
--- a/include/asm-s390/qdio.h
+++ b/include/asm-s390/qdio.h
@@ -34,6 +34,7 @@
#define QDIO_QETH_QFMT 0
#define QDIO_ZFCP_QFMT 1
#define QDIO_IQDIO_QFMT 2
+#define QDIO_IQDIO_QFMT_ASYNCH 3
struct qdio_buffer_element{
unsigned int flags;
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h
index 9b439cf6780..532e65a2aaf 100644
--- a/include/asm-s390/reset.h
+++ b/include/asm-s390/reset.h
@@ -19,5 +19,6 @@ extern void register_reset_call(struct reset_call *reset);
extern void unregister_reset_call(struct reset_call *reset);
extern void s390_reset_system(void);
extern void (*s390_reset_mcck_handler)(void);
+extern void (*s390_reset_pgm_handler)(void);
#endif /* _ASM_S390_RESET_H */
diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h
index eb3f8bfabf6..585c78a6e40 100644
--- a/include/asm-s390/termbits.h
+++ b/include/asm-s390/termbits.h
@@ -25,6 +25,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-sh/atomic-irq.h b/include/asm-sh/atomic-irq.h
new file mode 100644
index 00000000000..74f7943cff6
--- /dev/null
+++ b/include/asm-sh/atomic-irq.h
@@ -0,0 +1,71 @@
+#ifndef __ASM_SH_ATOMIC_IRQ_H
+#define __ASM_SH_ATOMIC_IRQ_H
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+static inline void atomic_add(int i, atomic_t *v)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *(long *)v += i;
+ local_irq_restore(flags);
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *(long *)v -= i;
+ local_irq_restore(flags);
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ unsigned long temp, flags;
+
+ local_irq_save(flags);
+ temp = *(long *)v;
+ temp += i;
+ *(long *)v = temp;
+ local_irq_restore(flags);
+
+ return temp;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ unsigned long temp, flags;
+
+ local_irq_save(flags);
+ temp = *(long *)v;
+ temp -= i;
+ *(long *)v = temp;
+ local_irq_restore(flags);
+
+ return temp;
+}
+
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *(long *)v &= ~mask;
+ local_irq_restore(flags);
+}
+
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *(long *)v |= mask;
+ local_irq_restore(flags);
+}
+
+#endif /* __ASM_SH_ATOMIC_IRQ_H */
diff --git a/include/asm-sh/atomic-llsc.h b/include/asm-sh/atomic-llsc.h
new file mode 100644
index 00000000000..4b00b78e3f4
--- /dev/null
+++ b/include/asm-sh/atomic-llsc.h
@@ -0,0 +1,107 @@
+#ifndef __ASM_SH_ATOMIC_LLSC_H
+#define __ASM_SH_ATOMIC_LLSC_H
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+static inline void atomic_add(int i, atomic_t *v)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+"1: movli.l @%2, %0 ! atomic_add \n"
+" add %1, %0 \n"
+" movco.l %0, @%2 \n"
+" bf 1b \n"
+ : "=&z" (tmp)
+ : "r" (i), "r" (&v->counter)
+ : "t");
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+"1: movli.l @%2, %0 ! atomic_sub \n"
+" sub %1, %0 \n"
+" movco.l %0, @%2 \n"
+" bf 1b \n"
+ : "=&z" (tmp)
+ : "r" (i), "r" (&v->counter)
+ : "t");
+}
+
+/*
+ * SH-4A note:
+ *
+ * We basically get atomic_xxx_return() for free compared with
+ * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
+ * encoding, so the retval is automatically set without having to
+ * do any special work.
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ unsigned long temp;
+
+ __asm__ __volatile__ (
+"1: movli.l @%2, %0 ! atomic_add_return \n"
+" add %1, %0 \n"
+" movco.l %0, @%2 \n"
+" bf 1b \n"
+" synco \n"
+ : "=&z" (temp)
+ : "r" (i), "r" (&v->counter)
+ : "t");
+
+ return temp;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ unsigned long temp;
+
+ __asm__ __volatile__ (
+"1: movli.l @%2, %0 ! atomic_sub_return \n"
+" sub %1, %0 \n"
+" movco.l %0, @%2 \n"
+" bf 1b \n"
+" synco \n"
+ : "=&z" (temp)
+ : "r" (i), "r" (&v->counter)
+ : "t");
+
+ return temp;
+}
+
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+"1: movli.l @%2, %0 ! atomic_clear_mask \n"
+" and %1, %0 \n"
+" movco.l %0, @%2 \n"
+" bf 1b \n"
+ : "=&z" (tmp)
+ : "r" (~mask), "r" (&v->counter)
+ : "t");
+}
+
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+"1: movli.l @%2, %0 ! atomic_set_mask \n"
+" or %1, %0 \n"
+" movco.l %0, @%2 \n"
+" bf 1b \n"
+ : "=&z" (tmp)
+ : "r" (mask), "r" (&v->counter)
+ : "t");
+}
+
+#endif /* __ASM_SH_ATOMIC_LLSC_H */
diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h
index 28305c3cbdd..e12570b9339 100644
--- a/include/asm-sh/atomic.h
+++ b/include/asm-sh/atomic.h
@@ -17,119 +17,14 @@ typedef struct { volatile int counter; } atomic_t;
#include <linux/compiler.h>
#include <asm/system.h>
-/*
- * To get proper branch prediction for the main line, we must branch
- * forward to code at the end of this object's .text section, then
- * branch back to restart the operation.
- */
-static inline void atomic_add(int i, atomic_t *v)
-{
#ifdef CONFIG_CPU_SH4A
- unsigned long tmp;
-
- __asm__ __volatile__ (
-"1: movli.l @%2, %0 ! atomic_add \n"
-" add %1, %0 \n"
-" movco.l %0, @%2 \n"
-" bf 1b \n"
- : "=&z" (tmp)
- : "r" (i), "r" (&v->counter)
- : "t");
+#include <asm/atomic-llsc.h>
#else
- unsigned long flags;
-
- local_irq_save(flags);
- *(long *)v += i;
- local_irq_restore(flags);
-#endif
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-#ifdef CONFIG_CPU_SH4A
- unsigned long tmp;
-
- __asm__ __volatile__ (
-"1: movli.l @%2, %0 ! atomic_sub \n"
-" sub %1, %0 \n"
-" movco.l %0, @%2 \n"
-" bf 1b \n"
- : "=&z" (tmp)
- : "r" (i), "r" (&v->counter)
- : "t");
-#else
- unsigned long flags;
-
- local_irq_save(flags);
- *(long *)v -= i;
- local_irq_restore(flags);
+#include <asm/atomic-irq.h>
#endif
-}
-
-/*
- * SH-4A note:
- *
- * We basically get atomic_xxx_return() for free compared with
- * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
- * encoding, so the retval is automatically set without having to
- * do any special work.
- */
-static inline int atomic_add_return(int i, atomic_t *v)
-{
- unsigned long temp;
-
-#ifdef CONFIG_CPU_SH4A
- __asm__ __volatile__ (
-"1: movli.l @%2, %0 ! atomic_add_return \n"
-" add %1, %0 \n"
-" movco.l %0, @%2 \n"
-" bf 1b \n"
-" synco \n"
- : "=&z" (temp)
- : "r" (i), "r" (&v->counter)
- : "t");
-#else
- unsigned long flags;
-
- local_irq_save(flags);
- temp = *(long *)v;
- temp += i;
- *(long *)v = temp;
- local_irq_restore(flags);
-#endif
-
- return temp;
-}
#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
- unsigned long temp;
-
-#ifdef CONFIG_CPU_SH4A
- __asm__ __volatile__ (
-"1: movli.l @%2, %0 ! atomic_sub_return \n"
-" sub %1, %0 \n"
-" movco.l %0, @%2 \n"
-" bf 1b \n"
-" synco \n"
- : "=&z" (temp)
- : "r" (i), "r" (&v->counter)
- : "t");
-#else
- unsigned long flags;
-
- local_irq_save(flags);
- temp = *(long *)v;
- temp -= i;
- *(long *)v = temp;
- local_irq_restore(flags);
-#endif
-
- return temp;
-}
-
#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic_inc_return(v) atomic_add_return(1,(v))
@@ -180,50 +75,6 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
-#ifdef CONFIG_CPU_SH4A
- unsigned long tmp;
-
- __asm__ __volatile__ (
-"1: movli.l @%2, %0 ! atomic_clear_mask \n"
-" and %1, %0 \n"
-" movco.l %0, @%2 \n"
-" bf 1b \n"
- : "=&z" (tmp)
- : "r" (~mask), "r" (&v->counter)
- : "t");
-#else
- unsigned long flags;
-
- local_irq_save(flags);
- *(long *)v &= ~mask;
- local_irq_restore(flags);
-#endif
-}
-
-static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
-#ifdef CONFIG_CPU_SH4A
- unsigned long tmp;
-
- __asm__ __volatile__ (
-"1: movli.l @%2, %0 ! atomic_set_mask \n"
-" or %1, %0 \n"
-" movco.l %0, @%2 \n"
-" bf 1b \n"
- : "=&z" (tmp)
- : "r" (mask), "r" (&v->counter)
- : "t");
-#else
- unsigned long flags;
-
- local_irq_save(flags);
- *(long *)v |= mask;
- local_irq_restore(flags);
-#endif
-}
-
/* Atomic operations are already serializing on SH */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index 1b4fc52a59e..2f89dd06d0c 100644
--- a/include/asm-sh/bug.h
+++ b/include/asm-sh/bug.h
@@ -1,19 +1,54 @@
#ifndef __ASM_SH_BUG_H
#define __ASM_SH_BUG_H
-
#ifdef CONFIG_BUG
-/*
- * Tell the user there is some problem.
- */
-#define BUG() do { \
- printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
- *(volatile int *)0 = 0; \
+
+struct bug_frame {
+ unsigned short opcode;
+ unsigned short line;
+ const char *file;
+ const char *func;
+};
+
+struct pt_regs;
+
+extern void handle_BUG(struct pt_regs *);
+
+#define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#define BUG() \
+do { \
+ __asm__ __volatile__ ( \
+ ".align 2\n\t" \
+ ".short %O0\n\t" \
+ ".short %O1\n\t" \
+ ".long %O2\n\t" \
+ ".long %O3\n\t" \
+ : \
+ : "n" (TRAPA_BUG_OPCODE), \
+ "i" (__LINE__), "X" (__FILE__), \
+ "X" (__FUNCTION__)); \
+} while (0)
+
+#else
+
+#define BUG() \
+do { \
+ __asm__ __volatile__ ( \
+ ".align 2\n\t" \
+ ".short %O0\n\t" \
+ : \
+ : "n" (TRAPA_BUG_OPCODE)); \
} while (0)
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+
#define HAVE_ARCH_BUG
-#endif
+
+#endif /* CONFIG_BUG */
#include <asm-generic/bug.h>
-#endif
+#endif /* __ASM_SH_BUG_H */
diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
index 795047da5e1..a294997a841 100644
--- a/include/asm-sh/bugs.h
+++ b/include/asm-sh/bugs.h
@@ -16,9 +16,8 @@
static void __init check_bugs(void)
{
- extern char *get_cpu_subtype(void);
extern unsigned long loops_per_jiffy;
- char *p= &init_utsname()->machine[2]; /* "sh" */
+ char *p = &init_utsname()->machine[2]; /* "sh" */
cpu_data->loops_per_jiffy = loops_per_jiffy;
@@ -40,6 +39,15 @@ static void __init check_bugs(void)
*p++ = '4';
*p++ = 'a';
break;
+ case CPU_SH73180 ... CPU_SH7722:
+ *p++ = '4';
+ *p++ = 'a';
+ *p++ = 'l';
+ *p++ = '-';
+ *p++ = 'd';
+ *p++ = 's';
+ *p++ = 'p';
+ break;
default:
*p++ = '?';
*p++ = '!';
diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
index d44344c88e7..4bc8357e889 100644
--- a/include/asm-sh/checksum.h
+++ b/include/asm-sh/checksum.h
@@ -34,25 +34,26 @@ asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
*/
asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
- int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr);
+ int len, __wsum sum,
+ int *src_err_ptr, int *dst_err_ptr);
/*
* Note: when you get a NULL pointer exception here this means someone
- * passed in an incorrect kernel address to one of these functions.
- *
- * If you use these functions directly please don't forget the
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
* access_ok().
*/
-static __inline__
+static inline
__wsum csum_partial_copy_nocheck(const void *src, void *dst,
- int len, __wsum sum)
+ int len, __wsum sum)
{
- return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+ return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
}
-static __inline__
+static inline
__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
- int len, __wsum sum, int *err_ptr)
+ int len, __wsum sum, int *err_ptr)
{
return csum_partial_copy_generic((__force const void *)src, dst,
len, sum, err_ptr, NULL);
@@ -62,7 +63,7 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
* Fold a partial checksum
*/
-static __inline__ __sum16 csum_fold(__wsum sum)
+static inline __sum16 csum_fold(__wsum sum)
{
unsigned int __dummy;
__asm__("swap.w %0, %1\n\t"
@@ -85,7 +86,7 @@ static __inline__ __sum16 csum_fold(__wsum sum)
* i386 version by Jorge Cwik <jorge@laser.satlink.net>, adapted
* for linux by * Arnt Gulbrandsen.
*/
-static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum, __dummy0, __dummy1;
@@ -113,10 +114,10 @@ static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
return csum_fold(sum);
}
-static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
- unsigned short len,
- unsigned short proto,
- __wsum sum)
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
{
#ifdef __LITTLE_ENDIAN__
unsigned long len_proto = (proto + len) << 8;
@@ -132,6 +133,7 @@ static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
: "=r" (sum), "=r" (len_proto)
: "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum)
: "t");
+
return sum;
}
@@ -139,30 +141,28 @@ static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
*/
-static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
- unsigned short len,
- unsigned short proto,
- __wsum sum)
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ unsigned short len,
+ unsigned short proto,
+ __wsum sum)
{
- return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
-
-static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
+static inline __sum16 ip_compute_csum(const void *buff, int len)
{
- return csum_fold (csum_partial(buff, len, 0));
+ return csum_fold(csum_partial(buff, len, 0));
}
#define _HAVE_ARCH_IPV6_CSUM
-#ifdef CONFIG_IPV6
-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- __u32 len, unsigned short proto,
- __wsum sum)
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, unsigned short proto,
+ __wsum sum)
{
unsigned int __dummy;
__asm__("clrt\n\t"
@@ -187,22 +187,21 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
"movt %1\n\t"
"add %1, %0\n"
: "=r" (sum), "=&r" (__dummy)
- : "r" (saddr), "r" (daddr),
+ : "r" (saddr), "r" (daddr),
"r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
: "t");
return csum_fold(sum);
}
-#endif
-/*
+/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ __wsum csum_and_copy_to_user (const void *src,
- void __user *dst,
- int len, __wsum sum,
- int *err_ptr)
+static inline __wsum csum_and_copy_to_user(const void *src,
+ void __user *dst,
+ int len, __wsum sum,
+ int *err_ptr)
{
if (access_ok(VERIFY_WRITE, dst, len))
return csum_partial_copy_generic((__force const void *)src,
diff --git a/include/asm-sh/cpu-sh2/cacheflush.h b/include/asm-sh/cpu-sh2/cacheflush.h
index f556fa80ea9..2979efb26de 100644
--- a/include/asm-sh/cpu-sh2/cacheflush.h
+++ b/include/asm-sh/cpu-sh2/cacheflush.h
@@ -15,6 +15,7 @@
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
@@ -27,6 +28,7 @@
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h
index 03fde97a7fd..f70d8ef76a1 100644
--- a/include/asm-sh/cpu-sh3/cacheflush.h
+++ b/include/asm-sh/cpu-sh3/cacheflush.h
@@ -15,6 +15,7 @@
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ * - flush_cache_dup mm(mm) handles cache flushing when forking
* - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
@@ -39,6 +40,7 @@
void flush_cache_all(void);
void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(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 addr, unsigned long pfn);
@@ -48,6 +50,7 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page);
#else
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-sh/cpu-sh4/cache.h b/include/asm-sh/cpu-sh4/cache.h
index 6e9c7e6ee8e..f92b20a0983 100644
--- a/include/asm-sh/cpu-sh4/cache.h
+++ b/include/asm-sh/cpu-sh4/cache.h
@@ -22,7 +22,7 @@
#define CCR_CACHE_ICE 0x0100 /* Instruction Cache Enable */
#define CCR_CACHE_ICI 0x0800 /* IC Invalidate */
#define CCR_CACHE_IIX 0x8000 /* IC Index Enable */
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
+#ifndef CONFIG_CPU_SH4A
#define CCR_CACHE_EMODE 0x80000000 /* EMODE Enable */
#endif
diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h
index 515fd574267..b01a10f3122 100644
--- a/include/asm-sh/cpu-sh4/cacheflush.h
+++ b/include/asm-sh/cpu-sh4/cacheflush.h
@@ -18,6 +18,7 @@
*/
void flush_cache_all(void);
void flush_cache_mm(struct mm_struct *mm);
+#define flush_cache_dup_mm(mm) flush_cache_mm(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 addr,
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index ef2b9b1ae41..602d061ca2d 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -10,7 +10,7 @@
#ifndef __ASM_CPU_SH4_FREQ_H
#define __ASM_CPU_SH4_FREQ_H
-#if defined(CONFIG_CPU_SUBTYPE_SH73180)
+#if defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7722)
#define FRQCR 0xa4150000
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
#define FRQCR 0xffc80000
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 37ab0c131a4..8d0867b98e0 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -67,7 +67,7 @@ static inline dma_addr_t dma_map_single(struct device *dev,
if (dev->bus == &pci_bus_type)
return virt_to_bus(ptr);
#endif
- dma_cache_sync(ptr, size, dir);
+ dma_cache_sync(dev, ptr, size, dir);
return virt_to_bus(ptr);
}
@@ -81,7 +81,7 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
for (i = 0; i < nents; i++) {
#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
- dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+ dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
sg[i].length, dir);
#endif
sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
@@ -112,7 +112,7 @@ static inline void dma_sync_single(struct device *dev, dma_addr_t dma_handle,
if (dev->bus == &pci_bus_type)
return;
#endif
- dma_cache_sync(bus_to_virt(dma_handle), size, dir);
+ dma_cache_sync(dev, bus_to_virt(dma_handle), size, dir);
}
static inline void dma_sync_single_range(struct device *dev,
@@ -124,7 +124,7 @@ static inline void dma_sync_single_range(struct device *dev,
if (dev->bus == &pci_bus_type)
return;
#endif
- dma_cache_sync(bus_to_virt(dma_handle) + offset, size, dir);
+ dma_cache_sync(dev, bus_to_virt(dma_handle) + offset, size, dir);
}
static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
@@ -134,7 +134,7 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
for (i = 0; i < nelems; i++) {
#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT)
- dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+ dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
sg[i].length, dir);
#endif
sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index fd576088e47..bff965ef4b9 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -37,7 +37,8 @@
# define ONCHIP_NR_IRQS 144
#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
defined(CONFIG_CPU_SUBTYPE_SH73180) || \
- defined(CONFIG_CPU_SUBTYPE_SH7343)
+ defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7722)
# define ONCHIP_NR_IRQS 109
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
# define ONCHIP_NR_IRQS 111
@@ -79,6 +80,8 @@
# define OFFCHIP_NR_IRQS 16
#elif defined(CONFIG_SH_7343_SOLUTION_ENGINE)
# define OFFCHIP_NR_IRQS 12
+#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+# define OFFCHIP_NR_IRQS 14
#elif defined(CONFIG_SH_UNKNOWN)
# define OFFCHIP_NR_IRQS 16 /* Must also be last */
#else
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index c84901dbd8e..036ca284386 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -508,16 +508,50 @@ struct vm_area_struct;
extern void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte);
-/* Encode and de-code a swap entry */
/*
+ * Encode and de-code a swap entry
+ *
+ * Constraints:
+ * _PAGE_FILE at bit 0
+ * _PAGE_PRESENT at bit 8
+ * _PAGE_PROTNONE at bit 9
+ *
+ * For the normal case, we encode the swap type into bits 0:7 and the
+ * swap offset into bits 10:30. For the 64-bit PTE case, we keep the
+ * preserved bits in the low 32-bits and use the upper 32 as the swap
+ * offset (along with a 5-bit type), following the same approach as x86
+ * PAE. This keeps the logic quite simple, and allows for a full 32
+ * PTE_FILE_MAX_BITS, as opposed to the 29-bits we're constrained with
+ * in the pte_low case.
+ *
+ * As is evident by the Alpha code, if we ever get a 64-bit unsigned
+ * long (swp_entry_t) to match up with the 64-bit PTEs, this all becomes
+ * much cleaner..
+ *
* NOTE: We should set ZEROs at the position of _PAGE_PRESENT
* and _PAGE_PROTNONE bits
*/
-#define __swp_type(x) ((x).val & 0xff)
-#define __swp_offset(x) ((x).val >> 10)
-#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 10) })
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 1 })
-#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 1 })
+#ifdef CONFIG_X2TLB
+#define __swp_type(x) ((x).val & 0x1f)
+#define __swp_offset(x) ((x).val >> 5)
+#define __swp_entry(type, offset) ((swp_entry_t){ (type) | (offset) << 5})
+#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high })
+#define __swp_entry_to_pte(x) ((pte_t){ 0, (x).val })
+
+/*
+ * Encode and decode a nonlinear file mapping entry
+ */
+#define pte_to_pgoff(pte) ((pte).pte_high)
+#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) })
+
+#define PTE_FILE_MAX_BITS 32
+#else
+#define __swp_type(x) ((x).val & 0xff)
+#define __swp_offset(x) ((x).val >> 10)
+#define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) <<10})
+
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 1 })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 1 })
/*
* Encode and decode a nonlinear file mapping entry
@@ -525,6 +559,7 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
#define PTE_FILE_MAX_BITS 29
#define pte_to_pgoff(pte) (pte_val(pte) >> 1)
#define pgoff_to_pte(off) ((pte_t) { ((off) << 1) | _PAGE_FILE })
+#endif
typedef pte_t *pte_addr_t;
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index 6f1dd7ca1b1..e29f2abb92d 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -27,6 +27,8 @@
#define CCN_CVR 0xff000040
#define CCN_PRR 0xff000044
+const char *get_cpu_subtype(void);
+
/*
* CPU type and hardware bug flags. Kept separately for each CPU.
*
@@ -52,8 +54,10 @@ enum cpu_type {
CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
/* SH-4A types */
- CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781,
- CPU_SH7785,
+ CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+
+ /* SH4AL-DSP types */
+ CPU_SH73180, CPU_SH7343, CPU_SH7722,
/* Unknown subtype */
CPU_SH_NONE
diff --git a/include/asm-sh/push-switch.h b/include/asm-sh/push-switch.h
index dfc6bad567f..4903f9e52dd 100644
--- a/include/asm-sh/push-switch.h
+++ b/include/asm-sh/push-switch.h
@@ -4,6 +4,7 @@
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
+#include <linux/platform_device.h>
struct push_switch {
/* switch state */
@@ -12,6 +13,8 @@ struct push_switch {
struct timer_list debounce;
/* workqueue */
struct work_struct work;
+ /* platform device, for workqueue handler */
+ struct platform_device *pdev;
};
struct push_switch_platform_info {
diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h
index 4f9822a8e7b..f1b7b46f4e9 100644
--- a/include/asm-sh/termbits.h
+++ b/include/asm-sh/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 0c01dc55081..879f741105d 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -106,6 +106,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18
+#define TIF_FREEZE 19
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -114,6 +115,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_WORK_MASK 0x000000FE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x000000FF /* work to do on any return to u-space */
diff --git a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h
index 55f71aa0aa6..1e53a47bdc9 100644
--- a/include/asm-sh64/cacheflush.h
+++ b/include/asm-sh64/cacheflush.h
@@ -21,6 +21,8 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
struct page *page, unsigned long addr,
int len);
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-sh64/pgalloc.h b/include/asm-sh64/pgalloc.h
index b29dd468817..cb803e56cb6 100644
--- a/include/asm-sh64/pgalloc.h
+++ b/include/asm-sh64/pgalloc.h
@@ -41,7 +41,7 @@ static inline void pgd_init(unsigned long page)
static inline pgd_t *get_pgd_slow(void)
{
unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
- pgd_t *ret = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
+ pgd_t *ret = kmalloc(pgd_size, GFP_KERNEL);
return ret;
}
diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h
index 04aa3318f76..329e696e775 100644
--- a/include/asm-sparc/bitops.h
+++ b/include/asm-sparc/bitops.h
@@ -14,6 +14,10 @@
#ifdef __KERNEL__
+extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
+extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
+extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask);
+
/*
* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
* is in the highest of the four bytes and bit '31' is the high bit
@@ -22,134 +26,62 @@
*/
static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
{
- register unsigned long mask asm("g2");
- register unsigned long *ADDR asm("g1");
- register int tmp1 asm("g3");
- register int tmp2 asm("g4");
- register int tmp3 asm("g5");
- register int tmp4 asm("g7");
+ unsigned long *ADDR, mask;
ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___set_bit\n\t"
- " add %%o7, 8, %%o7\n"
- : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
- : "0" (mask), "r" (ADDR)
- : "memory", "cc");
-
- return mask != 0;
+ return ___set_bit(ADDR, mask) != 0;
}
static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
{
- register unsigned long mask asm("g2");
- register unsigned long *ADDR asm("g1");
- register int tmp1 asm("g3");
- register int tmp2 asm("g4");
- register int tmp3 asm("g5");
- register int tmp4 asm("g7");
+ unsigned long *ADDR, mask;
ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___set_bit\n\t"
- " add %%o7, 8, %%o7\n"
- : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
- : "0" (mask), "r" (ADDR)
- : "memory", "cc");
+ (void) ___set_bit(ADDR, mask);
}
static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
{
- register unsigned long mask asm("g2");
- register unsigned long *ADDR asm("g1");
- register int tmp1 asm("g3");
- register int tmp2 asm("g4");
- register int tmp3 asm("g5");
- register int tmp4 asm("g7");
+ unsigned long *ADDR, mask;
ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___clear_bit\n\t"
- " add %%o7, 8, %%o7\n"
- : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
- : "0" (mask), "r" (ADDR)
- : "memory", "cc");
-
- return mask != 0;
+ return ___clear_bit(ADDR, mask) != 0;
}
static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
{
- register unsigned long mask asm("g2");
- register unsigned long *ADDR asm("g1");
- register int tmp1 asm("g3");
- register int tmp2 asm("g4");
- register int tmp3 asm("g5");
- register int tmp4 asm("g7");
+ unsigned long *ADDR, mask;
ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___clear_bit\n\t"
- " add %%o7, 8, %%o7\n"
- : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
- : "0" (mask), "r" (ADDR)
- : "memory", "cc");
+ (void) ___clear_bit(ADDR, mask);
}
static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
{
- register unsigned long mask asm("g2");
- register unsigned long *ADDR asm("g1");
- register int tmp1 asm("g3");
- register int tmp2 asm("g4");
- register int tmp3 asm("g5");
- register int tmp4 asm("g7");
+ unsigned long *ADDR, mask;
ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___change_bit\n\t"
- " add %%o7, 8, %%o7\n"
- : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
- : "0" (mask), "r" (ADDR)
- : "memory", "cc");
-
- return mask != 0;
+ return ___change_bit(ADDR, mask) != 0;
}
static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
{
- register unsigned long mask asm("g2");
- register unsigned long *ADDR asm("g1");
- register int tmp1 asm("g3");
- register int tmp2 asm("g4");
- register int tmp3 asm("g5");
- register int tmp4 asm("g7");
+ unsigned long *ADDR, mask;
ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);
- __asm__ __volatile__(
- "mov %%o7, %%g4\n\t"
- "call ___change_bit\n\t"
- " add %%o7, 8, %%o7\n"
- : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
- : "0" (mask), "r" (ADDR)
- : "memory", "cc");
+ (void) ___change_bit(ADDR, mask);
}
#include <asm-generic/bitops/non-atomic.h>
diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
index fc632f811cd..68ac1091027 100644
--- a/include/asm-sparc/cacheflush.h
+++ b/include/asm-sparc/cacheflush.h
@@ -48,6 +48,7 @@ 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_dup_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,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
#define flush_icache_range(start, end) do { } while (0)
diff --git a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
index 267e631e9bb..34518ea7bf1 100644
--- a/include/asm-sparc/checksum.h
+++ b/include/asm-sparc/checksum.h
@@ -151,7 +151,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
"xnor\t%%g0, %0, %0"
: "=r" (sum), "=&r" (iph)
: "r" (ihl), "1" (iph)
- : "g2", "g3", "g4", "cc");
+ : "g2", "g3", "g4", "cc", "memory");
return sum;
}
diff --git a/include/asm-sparc/of_device.h b/include/asm-sparc/of_device.h
index 80ea31f6e17..7cb00c1b09c 100644
--- a/include/asm-sparc/of_device.h
+++ b/include/asm-sparc/of_device.h
@@ -33,7 +33,7 @@ struct of_device
#define to_of_device(d) container_of(d, struct of_device, dev)
extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
-extern void of_iounmap(void __iomem *base, unsigned long size);
+extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
extern struct of_device *of_find_device_by_node(struct device_node *);
diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h
index 1794d71134b..5eb00a105d7 100644
--- a/include/asm-sparc/termbits.h
+++ b/include/asm-sparc/termbits.h
@@ -31,6 +31,18 @@ struct termios {
#endif
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
index 745d1ab6037..122e4058dd9 100644
--- a/include/asm-sparc64/cacheflush.h
+++ b/include/asm-sparc64/cacheflush.h
@@ -12,6 +12,7 @@
/* These are the same regardless of whether this is an SMP kernel or not. */
#define flush_cache_mm(__mm) \
do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
#define flush_cache_range(vma, start, end) \
flush_cache_mm((vma)->vm_mm)
#define flush_cache_page(vma, page, pfn) \
diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
index 27f65972b3b..93e5a062df8 100644
--- a/include/asm-sparc64/dma.h
+++ b/include/asm-sparc64/dma.h
@@ -152,9 +152,9 @@ extern void dvma_init(struct sbus_bus *);
#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
/* Yes, I hack a lot of elisp in my spare time... */
-#define DMA_ERROR_P(regs) (((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
-#define DMA_IRQ_P(regs) (((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
-#define DMA_WRITE_P(regs) (((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
+#define DMA_ERROR_P(regs) ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs) ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
+#define DMA_WRITE_P(regs) ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
#define DMA_OFF(__regs) \
do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \
tmp &= ~DMA_ENABLE; \
diff --git a/include/asm-sparc64/hw_irq.h b/include/asm-sparc64/hw_irq.h
index 599b3b07345..8e44a836082 100644
--- a/include/asm-sparc64/hw_irq.h
+++ b/include/asm-sparc64/hw_irq.h
@@ -1,6 +1,4 @@
#ifndef __ASM_SPARC64_HW_IRQ_H
#define __ASM_SPARC64_HW_IRQ_H
-extern void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq);
-
#endif
diff --git a/include/asm-sparc64/irqflags.h b/include/asm-sparc64/irqflags.h
new file mode 100644
index 00000000000..024fc54d068
--- /dev/null
+++ b/include/asm-sparc64/irqflags.h
@@ -0,0 +1,89 @@
+/*
+ * include/asm-sparc64/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+ unsigned long flags;
+
+ __asm__ __volatile__(
+ "rdpr %%pil, %0"
+ : "=r" (flags)
+ );
+
+ return flags;
+}
+
+#define raw_local_save_flags(flags) \
+ do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+ __asm__ __volatile__(
+ "wrpr %0, %%pil"
+ : /* no output */
+ : "r" (flags)
+ : "memory"
+ );
+}
+
+static inline void raw_local_irq_disable(void)
+{
+ __asm__ __volatile__(
+ "wrpr 15, %%pil"
+ : /* no outputs */
+ : /* no inputs */
+ : "memory"
+ );
+}
+
+static inline void raw_local_irq_enable(void)
+{
+ __asm__ __volatile__(
+ "wrpr 0, %%pil"
+ : /* no outputs */
+ : /* no inputs */
+ : "memory"
+ );
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags > 0);
+}
+
+static inline int raw_irqs_disabled(void)
+{
+ unsigned long flags = __raw_local_save_flags();
+
+ return raw_irqs_disabled_flags(flags);
+}
+
+/*
+ * For spinlocks, etc:
+ */
+static inline unsigned long __raw_local_irq_save(void)
+{
+ unsigned long flags = __raw_local_save_flags();
+
+ raw_local_irq_disable();
+
+ return flags;
+}
+
+#define raw_local_irq_save(flags) \
+ do { (flags) = __raw_local_irq_save(); } while (0)
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index c9f5c34d318..becc38fa06c 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -13,7 +13,11 @@ typedef u32 kprobe_opcode_t;
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define arch_remove_kprobe(p) do {} while (0)
#define ARCH_INACTIVE_KPROBE_COUNT 0
-#define flush_insn_slot(p) do { } while (0)
+
+#define flush_insn_slot(p) \
+do { flushi(&(p)->ainsn.insn[0]); \
+ flushi(&(p)->ainsn.insn[1]); \
+} while (0)
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
@@ -23,7 +27,7 @@ struct arch_specific_insn {
struct prev_kprobe {
struct kprobe *kp;
- unsigned int status;
+ unsigned long status;
unsigned long orig_tnpc;
unsigned long orig_tstate_pil;
};
@@ -33,10 +37,7 @@ struct kprobe_ctlblk {
unsigned long kprobe_status;
unsigned long kprobe_orig_tnpc;
unsigned long kprobe_orig_tstate_pil;
- long *jprobe_saved_esp;
struct pt_regs jprobe_saved_regs;
- struct pt_regs *jprobe_saved_regs_location;
- struct sparc_stackf jprobe_saved_stack;
struct prev_kprobe prev_kprobe;
};
diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h
index a62c7b997d6..60e9173c9ac 100644
--- a/include/asm-sparc64/of_device.h
+++ b/include/asm-sparc64/of_device.h
@@ -34,7 +34,7 @@ struct of_device
#define to_of_device(d) container_of(d, struct of_device, dev)
extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
-extern void of_iounmap(void __iomem *base, unsigned long size);
+extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
extern struct of_device *of_find_device_by_node(struct device_node *);
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index ced8cbde046..0d3df76aa47 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -5,6 +5,16 @@
#ifdef CONFIG_SMP
+#ifdef CONFIG_MODULES
+# define PERCPU_MODULE_RESERVE 8192
+#else
+# define PERCPU_MODULE_RESERVE 0
+#endif
+
+#define PERCPU_ENOUGH_ROOM \
+ (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
+ PERCPU_MODULE_RESERVE)
+
extern void setup_per_cpu_areas(void);
extern unsigned long __per_cpu_base;
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h
index cef5e827042..1294b7ce5d0 100644
--- a/include/asm-sparc64/rwsem.h
+++ b/include/asm-sparc64/rwsem.h
@@ -23,20 +23,33 @@ struct rw_semaphore {
signed int count;
spinlock_t wait_lock;
struct list_head wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
};
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
#define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) }
+{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \
+ __RWSEM_DEP_MAP_INIT(name) }
#define DECLARE_RWSEM(name) \
struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-static __inline__ void init_rwsem(struct rw_semaphore *sem)
-{
- sem->count = RWSEM_UNLOCKED_VALUE;
- spin_lock_init(&sem->wait_lock);
- INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+ struct lock_class_key *key);
+
+#define init_rwsem(sem) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __init_rwsem((sem), #sem, &__key); \
+} while (0)
extern void __down_read(struct rw_semaphore *sem);
extern int __down_read_trylock(struct rw_semaphore *sem);
@@ -46,6 +59,11 @@ extern void __up_read(struct rw_semaphore *sem);
extern void __up_write(struct rw_semaphore *sem);
extern void __downgrade_write(struct rw_semaphore *sem);
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+ __down_write(sem);
+}
+
static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
{
return atomic_add_return(delta, (atomic_t *)(&sem->count));
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index a8b7432c9a7..32281acb878 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -7,6 +7,9 @@
#include <asm/visasm.h>
#ifndef __ASSEMBLY__
+
+#include <linux/irqflags.h>
+
/*
* Sparc (general) CPU types
*/
@@ -72,52 +75,6 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
#endif
-#define setipl(__new_ipl) \
- __asm__ __volatile__("wrpr %0, %%pil" : : "r" (__new_ipl) : "memory")
-
-#define local_irq_disable() \
- __asm__ __volatile__("wrpr 15, %%pil" : : : "memory")
-
-#define local_irq_enable() \
- __asm__ __volatile__("wrpr 0, %%pil" : : : "memory")
-
-#define getipl() \
-({ unsigned long retval; __asm__ __volatile__("rdpr %%pil, %0" : "=r" (retval)); retval; })
-
-#define swap_pil(__new_pil) \
-({ unsigned long retval; \
- __asm__ __volatile__("rdpr %%pil, %0\n\t" \
- "wrpr %1, %%pil" \
- : "=&r" (retval) \
- : "r" (__new_pil) \
- : "memory"); \
- retval; \
-})
-
-#define read_pil_and_cli() \
-({ unsigned long retval; \
- __asm__ __volatile__("rdpr %%pil, %0\n\t" \
- "wrpr 15, %%pil" \
- : "=r" (retval) \
- : : "memory"); \
- retval; \
-})
-
-#define local_save_flags(flags) ((flags) = getipl())
-#define local_irq_save(flags) ((flags) = read_pil_and_cli())
-#define local_irq_restore(flags) setipl((flags))
-
-/* On sparc64 IRQ flags are the PIL register. A value of zero
- * means all interrupt levels are enabled, any other value means
- * only IRQ levels greater than that value will be received.
- * Consequently this means that the lowest IRQ level is one.
- */
-#define irqs_disabled() \
-({ unsigned long flags; \
- local_save_flags(flags);\
- (flags > 0); \
-})
-
#define nop() __asm__ __volatile__ ("nop")
#define read_barrier_depends() do { } while(0)
diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h
index b07715273ed..705cd44b417 100644
--- a/include/asm-sparc64/termbits.h
+++ b/include/asm-sparc64/termbits.h
@@ -33,6 +33,18 @@ struct termios {
#endif
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
index f2352606a79..c2a16e18849 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -137,10 +137,49 @@
#endif
#define BREAKPOINT_TRAP TRAP(breakpoint_trap)
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+#define TRAP_IRQ(routine, level) \
+ rdpr %pil, %g2; \
+ wrpr %g0, 15, %pil; \
+ sethi %hi(1f-4), %g7; \
+ ba,pt %xcc, etrap_irq; \
+ or %g7, %lo(1f-4), %g7; \
+ nop; \
+ nop; \
+ nop; \
+ .subsection 2; \
+1: call trace_hardirqs_off; \
+ nop; \
+ mov level, %o0; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o1; \
+ ba,a,pt %xcc, rtrap_irq; \
+ .previous;
+
+#define TICK_SMP_IRQ \
+ rdpr %pil, %g2; \
+ wrpr %g0, 15, %pil; \
+ sethi %hi(1f-4), %g7; \
+ ba,pt %xcc, etrap_irq; \
+ or %g7, %lo(1f-4), %g7; \
+ nop; \
+ nop; \
+ nop; \
+ .subsection 2; \
+1: call trace_hardirqs_off; \
+ nop; \
+ call smp_percpu_timer_interrupt; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,a,pt %xcc, rtrap_irq; \
+ .previous;
+
+#else
+
#define TRAP_IRQ(routine, level) \
rdpr %pil, %g2; \
wrpr %g0, 15, %pil; \
- b,pt %xcc, etrap_irq; \
+ ba,pt %xcc, etrap_irq; \
rd %pc, %g7; \
mov level, %o0; \
call routine; \
@@ -151,12 +190,14 @@
rdpr %pil, %g2; \
wrpr %g0, 15, %pil; \
sethi %hi(109f), %g7; \
- b,pt %xcc, etrap_irq; \
+ ba,pt %xcc, etrap_irq; \
109: or %g7, %lo(109b), %g7; \
call smp_percpu_timer_interrupt; \
add %sp, PTREGS_OFF, %o0; \
ba,a,pt %xcc, rtrap_irq;
+#endif
+
#define TRAP_IVEC TRAP_NOSAVE(do_ivec)
#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)
diff --git a/include/asm-um/bug.h b/include/asm-um/bug.h
index 1e22fa26ff0..3357c5e2468 100644
--- a/include/asm-um/bug.h
+++ b/include/asm-um/bug.h
@@ -1,4 +1,6 @@
#ifndef __UM_BUG_H
#define __UM_BUG_H
-#include <asm-generic/bug.h>
+
+#include <asm/arch/bug.h>
+
#endif
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 188f7262177..e57ff136ee5 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -408,6 +408,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#include <asm-generic/pgtable-nopud.h>
+#ifdef CONFIG_HIGHMEM
+/* Clear a kernel PTE and flush it from the TLB */
+#define kpte_clear_flush(ptep, vaddr) \
+do { \
+ pte_clear(&init_mm, vaddr, ptep); \
+ __flush_tlb_one(vaddr); \
+} while (0)
+#endif
+
#endif
#endif
diff --git a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
index e1a87f82f1a..9ece05a202e 100644
--- a/include/asm-v850/cacheflush.h
+++ b/include/asm-v850/cacheflush.h
@@ -24,6 +24,7 @@
systems with MMUs, so we don't need them. */
#define flush_cache_all() ((void)0)
#define flush_cache_mm(mm) ((void)0)
+#define flush_cache_dup_mm(mm) ((void)0)
#define flush_cache_range(vma, start, end) ((void)0)
#define flush_cache_page(vma, vmaddr, pfn) ((void)0)
#define flush_dcache_page(page) ((void)0)
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
index 212d4e27926..f3b43303208 100644
--- a/include/asm-v850/termbits.h
+++ b/include/asm-v850/termbits.h
@@ -17,6 +17,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
index 9d1916e59c0..6b6fc6f8be7 100644
--- a/include/asm-x86_64/acpi.h
+++ b/include/asm-x86_64/acpi.h
@@ -54,30 +54,8 @@
#define ACPI_ENABLE_IRQS() local_irq_enable()
#define ACPI_FLUSH_CPU_CACHE() wbinvd()
-
-static inline int
-__acpi_acquire_global_lock (unsigned int *lock)
-{
- unsigned int old, new, val;
- do {
- old = *lock;
- new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
- val = cmpxchg(lock, old, new);
- } while (unlikely (val != old));
- return (new < 3) ? -1 : 0;
-}
-
-static inline int
-__acpi_release_global_lock (unsigned int *lock)
-{
- unsigned int old, new, val;
- do {
- old = *lock;
- new = old & ~0x3;
- val = cmpxchg(lock, old, new);
- } while (unlikely (val != old));
- return old & 0x1;
-}
+int __acpi_acquire_global_lock(unsigned int *lock);
+int __acpi_release_global_lock(unsigned int *lock);
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr))
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 5b535eaf530..8da9609070f 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -7,7 +7,13 @@
#include <asm/alternative.h>
-#define ADDR (*(volatile long *) addr)
+#if __GNUC__ < 4 || __GNUC_MINOR__ < 1
+/* Technically wrong, but this avoids compilation errors on some gcc
+ versions. */
+#define ADDR "=m" (*(volatile long *) addr)
+#else
+#define ADDR "+m" (*(volatile long *) addr)
+#endif
/**
* set_bit - Atomically set a bit in memory
@@ -23,7 +29,7 @@ static __inline__ void set_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
- :"+m" (ADDR)
+ :ADDR
:"dIr" (nr) : "memory");
}
@@ -40,7 +46,7 @@ static __inline__ void __set_bit(int nr, volatile void * addr)
{
__asm__ volatile(
"btsl %1,%0"
- :"+m" (ADDR)
+ :ADDR
:"dIr" (nr) : "memory");
}
@@ -58,7 +64,7 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
- :"+m" (ADDR)
+ :ADDR
:"dIr" (nr));
}
@@ -66,7 +72,7 @@ static __inline__ void __clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
"btrl %1,%0"
- :"+m" (ADDR)
+ :ADDR
:"dIr" (nr));
}
@@ -86,7 +92,7 @@ static __inline__ void __change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
"btcl %1,%0"
- :"+m" (ADDR)
+ :ADDR
:"dIr" (nr));
}
@@ -103,7 +109,7 @@ static __inline__ void change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
- :"+m" (ADDR)
+ :ADDR
:"dIr" (nr));
}
@@ -121,7 +127,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"+m" (ADDR)
+ :"=r" (oldbit),ADDR
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -141,7 +147,7 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
__asm__(
"btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"+m" (ADDR)
+ :"=r" (oldbit),ADDR
:"dIr" (nr));
return oldbit;
}
@@ -160,7 +166,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"+m" (ADDR)
+ :"=r" (oldbit),ADDR
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -180,7 +186,7 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
__asm__(
"btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"+m" (ADDR)
+ :"=r" (oldbit),ADDR
:"dIr" (nr));
return oldbit;
}
@@ -192,7 +198,7 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__(
"btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"+m" (ADDR)
+ :"=r" (oldbit),ADDR
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -211,7 +217,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"+m" (ADDR)
+ :"=r" (oldbit),ADDR
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -237,7 +243,7 @@ static __inline__ int variable_test_bit(int nr, volatile const void * addr)
__asm__ __volatile__(
"btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
- :"m" (ADDR),"dIr" (nr));
+ :"m" (*(volatile long *)addr),"dIr" (nr));
return oldbit;
}
diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
index 80ac1fe966a..68260641491 100644
--- a/include/asm-x86_64/bug.h
+++ b/include/asm-x86_64/bug.h
@@ -1,30 +1,30 @@
#ifndef __ASM_X8664_BUG_H
#define __ASM_X8664_BUG_H 1
-#include <linux/stringify.h>
-
-/*
- * Tell the user there is some problem. The exception handler decodes
- * this frame.
- */
-struct bug_frame {
- unsigned char ud2[2];
- unsigned char push;
- signed int filename;
- unsigned char ret;
- unsigned short line;
-} __attribute__((packed));
-
#ifdef CONFIG_BUG
#define HAVE_ARCH_BUG
-/* We turn the bug frame into valid instructions to not confuse
- the disassembler. Thanks to Jan Beulich & Suresh Siddha
- for nice instruction selection.
- The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
-#define BUG() \
- asm volatile( \
- "ud2 ; pushq $%c1 ; ret $%c0" :: \
- "i"(__LINE__), "i" (__FILE__))
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define BUG() \
+ do { \
+ asm volatile("1:\tud2\n" \
+ ".pushsection __bug_table,\"a\"\n" \
+ "2:\t.quad 1b, %c0\n" \
+ "\t.word %c1, 0\n" \
+ "\t.org 2b+%c2\n" \
+ ".popsection" \
+ : : "i" (__FILE__), "i" (__LINE__), \
+ "i" (sizeof(struct bug_entry))); \
+ for(;;) ; \
+ } while(0)
+#else
+#define BUG() \
+ do { \
+ asm volatile("ud2"); \
+ for(;;) ; \
+ } while(0)
+#endif
+
void out_of_line_bug(void);
#else
static inline void out_of_line_bug(void) { }
diff --git a/include/asm-x86_64/cacheflush.h b/include/asm-x86_64/cacheflush.h
index d32f7f58752..ab1cb5c7dc9 100644
--- a/include/asm-x86_64/cacheflush.h
+++ b/include/asm-x86_64/cacheflush.h
@@ -7,6 +7,7 @@
/* Caches aren't brain-dead on the intel. */
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index be9ec689072..49dbab09ef2 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -63,6 +63,9 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
return (dma_addr == bad_dma_address);
}
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
extern void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
diff --git a/include/asm-x86_64/ioctls.h b/include/asm-x86_64/ioctls.h
index 62caf8b6e4e..3fc0b15a0d7 100644
--- a/include/asm-x86_64/ioctls.h
+++ b/include/asm-x86_64/ioctls.h
@@ -46,6 +46,10 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TCGETS2 _IOR('T',0x2A, struct termios2)
+#define TCSETS2 _IOW('T',0x2B, struct termios2)
+#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+#define TCSETSF2 _IOW('T',0x2D, struct termios2)
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 952783d35c7..3227bc93d69 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -189,6 +189,7 @@ static inline unsigned int cpuid_edx(unsigned int op)
#define MSR_IA32_PERFCTR0 0xc1
#define MSR_IA32_PERFCTR1 0xc2
+#define MSR_FSB_FREQ 0xcd
#define MSR_MTRRcap 0x0fe
#define MSR_IA32_BBL_CR_CTL 0x119
@@ -311,6 +312,9 @@ static inline unsigned int cpuid_edx(unsigned int op)
#define MSR_IA32_PERF_STATUS 0x198
#define MSR_IA32_PERF_CTL 0x199
+#define MSR_IA32_MPERF 0xE7
+#define MSR_IA32_APERF 0xE8
+
#define MSR_IA32_THERM_CONTROL 0x19a
#define MSR_IA32_THERM_INTERRUPT 0x19b
#define MSR_IA32_THERM_STATUS 0x19c
diff --git a/include/asm-x86_64/termbits.h b/include/asm-x86_64/termbits.h
index bd950946e52..6cfc3bb10c1 100644
--- a/include/asm-x86_64/termbits.h
+++ b/include/asm-x86_64/termbits.h
@@ -17,6 +17,28 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct termios2 {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
@@ -118,6 +140,7 @@ struct termios {
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
+#define BOTHER 0010000 /* non standard rate */
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
@@ -133,10 +156,12 @@ struct termios {
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
+#define IBSHIFT 8 /* Shift from CBAUD to CIBAUD */
+
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
diff --git a/include/asm-x86_64/termios.h b/include/asm-x86_64/termios.h
index 041a91f7ddf..443b225537f 100644
--- a/include/asm-x86_64/termios.h
+++ b/include/asm-x86_64/termios.h
@@ -98,8 +98,10 @@ struct termio {
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
+#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index 787a08114b4..74a6c74397f 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -122,6 +122,7 @@ static inline struct thread_info *stack_thread_info(void)
#define TIF_MEMDIE 20
#define TIF_DEBUG 21 /* uses debug registers */
#define TIF_IO_BITMAP 22 /* uses I/O bitmap */
+#define TIF_FREEZE 23 /* is freezing for suspend */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -137,6 +138,7 @@ static inline struct thread_info *stack_thread_info(void)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
+#define _TIF_FREEZE (1<<TIF_FREEZE)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index 5c8f49280db..2facec5914d 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -47,6 +47,7 @@ extern int __node_distance(int, int);
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_FORK \
| SD_BALANCE_EXEC \
+ | SD_SERIALIZE \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
.balance_interval = 1, \
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index d5dbc87274f..c0eac519840 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -157,7 +157,7 @@ do { \
case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\
case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\
case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\
- case 8: __put_user_asm(x,ptr,retval,"q","","ir",-EFAULT); break;\
+ case 8: __put_user_asm(x,ptr,retval,"q","","Zr",-EFAULT); break;\
default: __put_user_bad(); \
} \
} while (0)
diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h
index 2f6349e4871..02710f6a456 100644
--- a/include/asm-x86_64/unwind.h
+++ b/include/asm-x86_64/unwind.h
@@ -1,100 +1,6 @@
#ifndef _ASM_X86_64_UNWIND_H
#define _ASM_X86_64_UNWIND_H
-/*
- * Copyright (C) 2002-2006 Novell, Inc.
- * Jan Beulich <jbeulich@novell.com>
- * This code is released under version 2 of the GNU GPL.
- */
-
-#ifdef CONFIG_STACK_UNWIND
-
-#include <linux/sched.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/vsyscall.h>
-
-struct unwind_frame_info
-{
- struct pt_regs regs;
- struct task_struct *task;
- unsigned call_frame:1;
-};
-
-#define UNW_PC(frame) (frame)->regs.rip
-#define UNW_SP(frame) (frame)->regs.rsp
-#ifdef CONFIG_FRAME_POINTER
-#define UNW_FP(frame) (frame)->regs.rbp
-#define FRAME_RETADDR_OFFSET 8
-#define FRAME_LINK_OFFSET 0
-#define STACK_BOTTOM(tsk) (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
-#define STACK_TOP(tsk) ((tsk)->thread.rsp0)
-#endif
-/* Might need to account for the special exception and interrupt handling
- stacks here, since normally
- EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
- but the construct is needed only for getting across the stack switch to
- the interrupt stack - thus considering the IRQ stack itself is unnecessary,
- and the overhead of comparing against all exception handling stacks seems
- not desirable. */
-#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1))
-
-#define UNW_REGISTER_INFO \
- PTREGS_INFO(rax), \
- PTREGS_INFO(rdx), \
- PTREGS_INFO(rcx), \
- PTREGS_INFO(rbx), \
- PTREGS_INFO(rsi), \
- PTREGS_INFO(rdi), \
- PTREGS_INFO(rbp), \
- PTREGS_INFO(rsp), \
- PTREGS_INFO(r8), \
- PTREGS_INFO(r9), \
- PTREGS_INFO(r10), \
- PTREGS_INFO(r11), \
- PTREGS_INFO(r12), \
- PTREGS_INFO(r13), \
- PTREGS_INFO(r14), \
- PTREGS_INFO(r15), \
- PTREGS_INFO(rip)
-
-#define UNW_DEFAULT_RA(raItem, dataAlign) \
- ((raItem).where == Memory && \
- !((raItem).value * (dataAlign) + 8))
-
-static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
- /*const*/ struct pt_regs *regs)
-{
- info->regs = *regs;
-}
-
-static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
-{
- extern const char thread_return[];
-
- memset(&info->regs, 0, sizeof(info->regs));
- info->regs.rip = (unsigned long)thread_return;
- info->regs.cs = __KERNEL_CS;
- __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
- info->regs.rsp = info->task->thread.rsp;
- info->regs.ss = __KERNEL_DS;
-}
-
-extern int arch_unwind_init_running(struct unwind_frame_info *,
- int (*callback)(struct unwind_frame_info *,
- void *arg),
- void *arg);
-
-static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
-{
- return user_mode(&info->regs)
- || (long)info->regs.rip >= 0
- || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
- || (long)info->regs.rsp >= 0;
-}
-
-#else
-
#define UNW_PC(frame) ((void)(frame), 0UL)
#define UNW_SP(frame) ((void)(frame), 0UL)
@@ -103,6 +9,4 @@ static inline int arch_unw_user_mode(const void *info)
return 0;
}
-#endif
-
#endif /* _ASM_X86_64_UNWIND_H */
diff --git a/include/asm-xtensa/asmmacro.h b/include/asm-xtensa/asmmacro.h
new file mode 100644
index 00000000000..76915cabad1
--- /dev/null
+++ b/include/asm-xtensa/asmmacro.h
@@ -0,0 +1,153 @@
+/*
+ * include/asm-xtensa/asmmacro.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ASMMACRO_H
+#define _XTENSA_ASMMACRO_H
+
+#include <asm/variant/core.h>
+
+/*
+ * Some little helpers for loops. Use zero-overhead-loops
+ * where applicable and if supported by the processor.
+ *
+ * __loopi ar, at, size, inc
+ * ar register initialized with the start address
+ * at scratch register used by macro
+ * size size immediate value
+ * inc increment
+ *
+ * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
+ * ar register initialized with the start address
+ * as register initialized with the size
+ * at scratch register use by macro
+ * inc_log2 increment [in log2]
+ * mask_log2 mask [in log2]
+ * cond true condition (used in loop'cond')
+ * ncond false condition (used in b'ncond')
+ *
+ * __loop as
+ * restart loop. 'as' register must not have been modified!
+ *
+ * __endla ar, at, incr
+ * ar start address (modified)
+ * as scratch register used by macro
+ * inc increment
+ */
+
+/*
+ * loop for given size as immediate
+ */
+
+ .macro __loopi ar, at, size, incr
+
+#if XCHAL_HAVE_LOOPS
+ movi \at, ((\size + \incr - 1) / (\incr))
+ loop \at, 99f
+#else
+ addi \at, \ar, \size
+ 98:
+#endif
+
+ .endm
+
+/*
+ * loop for given size in register
+ */
+
+ .macro __loops ar, as, at, incr_log2, mask_log2, cond, ncond
+
+#if XCHAL_HAVE_LOOPS
+ .ifgt \incr_log2 - 1
+ addi \at, \as, (1 << \incr_log2) - 1
+ .ifnc \mask_log2,
+ extui \at, \at, \incr_log2, \mask_log2
+ .else
+ srli \at, \at, \incr_log2
+ .endif
+ .endif
+ loop\cond \at, 99f
+#else
+ .ifnc \mask_log2,
+ extui \at, \as, \incr_log2, \mask_log2
+ .else
+ .ifnc \ncond,
+ srli \at, \as, \incr_log2
+ .endif
+ .endif
+ .ifnc \ncond,
+ b\ncond \at, 99f
+
+ .endif
+ .ifnc \mask_log2,
+ slli \at, \at, \incr_log2
+ add \at, \ar, \at
+ .else
+ add \at, \ar, \as
+ .endif
+#endif
+ 98:
+
+ .endm
+
+/*
+ * loop from ar to ax
+ */
+
+ .macro __loopt ar, as, at, incr_log2
+
+#if XCHAL_HAVE_LOOPS
+ sub \at, \as, \ar
+ .ifgt \incr_log2 - 1
+ addi \at, \at, (1 << \incr_log2) - 1
+ srli \at, \at, \incr_log2
+ .endif
+ loop \at, 99f
+#else
+ 98:
+#endif
+
+ .endm
+
+/*
+ * restart loop. registers must be unchanged
+ */
+
+ .macro __loop as
+
+#if XCHAL_HAVE_LOOPS
+ loop \as, 99f
+#else
+ 98:
+#endif
+
+ .endm
+
+/*
+ * end of loop with no increment of the address.
+ */
+
+ .macro __endl ar, as
+#if !XCHAL_HAVE_LOOPS
+ bltu \ar, \as, 98b
+#endif
+ 99:
+ .endm
+
+/*
+ * end of loop with increment of the address.
+ */
+
+ .macro __endla ar, as, incr
+ addi \ar, \ar, \incr
+ __endl \ar \as
+ .endm
+
+
+#endif /* _XTENSA_ASMMACRO_H */
diff --git a/include/asm-xtensa/bug.h b/include/asm-xtensa/bug.h
index 56703659b20..3e52d72712f 100644
--- a/include/asm-xtensa/bug.h
+++ b/include/asm-xtensa/bug.h
@@ -13,29 +13,6 @@
#ifndef _XTENSA_BUG_H
#define _XTENSA_BUG_H
-#include <linux/stringify.h>
-
-#define ILL __asm__ __volatile__ (".byte 0,0,0\n")
-
-#ifdef CONFIG_KALLSYMS
-# define BUG() do { \
- printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
- ILL; \
-} while (0)
-#else
-# define BUG() do { \
- printk("kernel BUG!\n"); \
- ILL; \
-} while (0)
-#endif
-
-#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 ("Warning in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
- dump_stack(); \
- } \
-} while (0)
+#include <asm-generic/bug.h>
#endif /* _XTENSA_BUG_H */
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
index 0b1552569aa..0f540a5f4c0 100644
--- a/include/asm-xtensa/byteorder.h
+++ b/include/asm-xtensa/byteorder.h
@@ -11,10 +11,9 @@
#ifndef _XTENSA_BYTEORDER_H
#define _XTENSA_BYTEORDER_H
-#include <asm/processor.h>
#include <asm/types.h>
-static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{
__u32 res;
/* instruction sequence from Xtensa ISA release 2/2000 */
@@ -29,7 +28,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
return res;
}
-static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
{
/* Given that 'short' values are signed (i.e., can be negative),
* we cannot assume that the upper 16-bits of the register are
diff --git a/include/asm-xtensa/cache.h b/include/asm-xtensa/cache.h
index 1e79c0e2746..1c4a78f29ae 100644
--- a/include/asm-xtensa/cache.h
+++ b/include/asm-xtensa/cache.h
@@ -4,7 +4,6 @@
* 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.
- * 2 of the License, or (at your option) any later version.
*
* (C) 2001 - 2005 Tensilica Inc.
*/
@@ -12,21 +11,14 @@
#ifndef _XTENSA_CACHE_H
#define _XTENSA_CACHE_H
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
-#if XCHAL_ICACHE_SIZE > 0
-# if (XCHAL_ICACHE_SIZE % (XCHAL_ICACHE_LINESIZE*XCHAL_ICACHE_WAYS*4)) != 0
-# error cache configuration outside expected/supported range!
-# endif
-#endif
+#define L1_CACHE_SHIFT XCHAL_DCACHE_LINEWIDTH
+#define L1_CACHE_BYTES XCHAL_DCACHE_LINESIZE
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#if XCHAL_DCACHE_SIZE > 0
-# if (XCHAL_DCACHE_SIZE % (XCHAL_DCACHE_LINESIZE*XCHAL_DCACHE_WAYS*4)) != 0
-# error cache configuration outside expected/supported range!
-# endif
-#endif
+#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE/XCHAL_DCACHE_WAYS)
+#define ICACHE_WAY_SIZE (XCHAL_ICACHE_SIZE/XCHAL_ICACHE_WAYS)
-#define L1_CACHE_SHIFT XCHAL_CACHE_LINEWIDTH_MAX
-#define L1_CACHE_BYTES XCHAL_CACHE_LINESIZE_MAX
#endif /* _XTENSA_CACHE_H */
diff --git a/include/asm-xtensa/cacheasm.h b/include/asm-xtensa/cacheasm.h
new file mode 100644
index 00000000000..2c20a58f94c
--- /dev/null
+++ b/include/asm-xtensa/cacheasm.h
@@ -0,0 +1,177 @@
+/*
+ * include/asm-xtensa/cacheasm.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Tensilica Inc.
+ */
+
+#include <asm/cache.h>
+#include <asm/asmmacro.h>
+#include <linux/stringify.h>
+
+/*
+ * Define cache functions as macros here so that they can be used
+ * by the kernel and boot loader. We should consider moving them to a
+ * library that can be linked by both.
+ *
+ * Locking
+ *
+ * ___unlock_dcache_all
+ * ___unlock_icache_all
+ *
+ * Flush and invaldating
+ *
+ * ___flush_invalidate_dcache_{all|range|page}
+ * ___flush_dcache_{all|range|page}
+ * ___invalidate_dcache_{all|range|page}
+ * ___invalidate_icache_{all|range|page}
+ *
+ */
+
+ .macro __loop_cache_all ar at insn size line_width
+
+ movi \ar, 0
+
+ __loopi \ar, \at, \size, (4 << (\line_width))
+ \insn \ar, 0 << (\line_width)
+ \insn \ar, 1 << (\line_width)
+ \insn \ar, 2 << (\line_width)
+ \insn \ar, 3 << (\line_width)
+ __endla \ar, \at, 4 << (\line_width)
+
+ .endm
+
+
+ .macro __loop_cache_range ar as at insn line_width
+
+ extui \at, \ar, 0, \line_width
+ add \as, \as, \at
+
+ __loops \ar, \as, \at, \line_width
+ \insn \ar, 0
+ __endla \ar, \at, (1 << (\line_width))
+
+ .endm
+
+
+ .macro __loop_cache_page ar at insn line_width
+
+ __loopi \ar, \at, PAGE_SIZE, 4 << (\line_width)
+ \insn \ar, 0 << (\line_width)
+ \insn \ar, 1 << (\line_width)
+ \insn \ar, 2 << (\line_width)
+ \insn \ar, 3 << (\line_width)
+ __endla \ar, \at, 4 << (\line_width)
+
+ .endm
+
+
+#if XCHAL_DCACHE_LINE_LOCKABLE
+
+ .macro ___unlock_dcache_all ar at
+
+ __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+#endif
+
+#if XCHAL_ICACHE_LINE_LOCKABLE
+
+ .macro ___unlock_icache_all ar at
+
+ __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+#endif
+
+ .macro ___flush_invalidate_dcache_all ar at
+
+ __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___flush_dcache_all ar at
+
+ __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_dcache_all ar at
+
+ __loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \
+ XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_icache_all ar at
+
+ __loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \
+ XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+
+
+
+ .macro ___flush_invalidate_dcache_range ar as at
+
+ __loop_cache_range \ar \as \at dhwbi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___flush_dcache_range ar as at
+
+ __loop_cache_range \ar \as \at dhwb XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_dcache_range ar as at
+
+ __loop_cache_range \ar \as \at dhi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_icache_range ar as at
+
+ __loop_cache_range \ar \as \at ihi XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+
+
+
+ .macro ___flush_invalidate_dcache_page ar as
+
+ __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___flush_dcache_page ar as
+
+ __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_dcache_page ar as
+
+ __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_icache_page ar as
+
+ __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+
diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h
index 44a36e08784..22ef901b784 100644
--- a/include/asm-xtensa/cacheflush.h
+++ b/include/asm-xtensa/cacheflush.h
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * (C) 2001 - 2005 Tensilica Inc.
+ * (C) 2001 - 2006 Tensilica Inc.
*/
#ifndef _XTENSA_CACHEFLUSH_H
@@ -75,6 +75,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
#define flush_cache_all() __flush_invalidate_cache_all();
#define flush_cache_mm(mm) __flush_invalidate_cache_all();
+#define flush_cache_dup_mm(mm) __flush_invalidate_cache_all();
#define flush_cache_vmap(start,end) __flush_invalidate_cache_all();
#define flush_cache_vunmap(start,end) __flush_invalidate_cache_all();
@@ -88,6 +89,7 @@ extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned lon
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_dup_mm(mm) 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-xtensa/checksum.h b/include/asm-xtensa/checksum.h
index 5435aff9a4b..23534c60b3a 100644
--- a/include/asm-xtensa/checksum.h
+++ b/include/asm-xtensa/checksum.h
@@ -12,7 +12,7 @@
#define _XTENSA_CHECKSUM_H
#include <linux/in6.h>
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
/*
* computes the checksum of a memory block at buff, length len,
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
index 5093034723b..bd09ec02d57 100644
--- a/include/asm-xtensa/coprocessor.h
+++ b/include/asm-xtensa/coprocessor.h
@@ -11,7 +11,16 @@
#ifndef _XTENSA_COPROCESSOR_H
#define _XTENSA_COPROCESSOR_H
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
+#include <asm/variant/tie.h>
+
+#if !XCHAL_HAVE_CP
+
+#define XTENSA_CP_EXTRA_OFFSET 0
+#define XTENSA_CP_EXTRA_ALIGN 1 /* must be a power of 2 */
+#define XTENSA_CP_EXTRA_SIZE 0
+
+#else
#define XTOFS(last_start,last_size,align) \
((last_start+last_size+align-1) & -align)
@@ -67,4 +76,6 @@ extern void save_coprocessor_registers(void*, int);
# endif
#endif
+#endif
+
#endif /* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/dma.h b/include/asm-xtensa/dma.h
index db2633f6778..e30f3abf48f 100644
--- a/include/asm-xtensa/dma.h
+++ b/include/asm-xtensa/dma.h
@@ -12,7 +12,6 @@
#define _XTENSA_DMA_H
#include <asm/io.h> /* need byte IO */
-#include <xtensa/config/core.h>
/*
* This is only to be defined if we have PC-like DMA.
@@ -44,7 +43,9 @@
* enters another area, and virt_to_phys() may not return
* the value desired).
*/
-#define MAX_DMA_ADDRESS (PAGE_OFFSET + XCHAL_KSEG_CACHED_SIZE - 1)
+
+#define MAX_DMA_ADDRESS (PAGE_OFFSET + XCHAL_KIO_SIZE - 1)
+
/* Reserve and release a DMA channel */
extern int request_dma(unsigned int dmanr, const char * device_id);
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index de0667453b2..f0f9fd8560a 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -13,9 +13,8 @@
#ifndef _XTENSA_ELF_H
#define _XTENSA_ELF_H
+#include <asm/variant/core.h>
#include <asm/ptrace.h>
-#include <asm/coprocessor.h>
-#include <xtensa/config/core.h>
/* Xtensa processor ELF architecture-magic number */
@@ -118,11 +117,15 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
* using memcpy(). But we do allow space for such alignment,
* to allow optimizations of layout and copying.
*/
-
+#if 0
#define TOTAL_FPREGS_SIZE \
(4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
#define ELF_NFPREG \
((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
+#else
+#define TOTAL_FPREGS_SIZE 0
+#define ELF_NFPREG 0
+#endif
typedef unsigned int elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
index ec066ae96ca..0609fc691b7 100644
--- a/include/asm-xtensa/fcntl.h
+++ b/include/asm-xtensa/fcntl.h
@@ -14,48 +14,86 @@
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
-#define O_APPEND 0x0008
-#define O_SYNC 0x0010
-#define O_NONBLOCK 0x0080
-#define O_CREAT 0x0100 /* not fcntl */
-#define O_EXCL 0x0400 /* not fcntl */
-#define O_NOCTTY 0x0800 /* not fcntl */
-#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
-#define O_LARGEFILE 0x2000 /* allow large file opens - currently ignored */
-#define O_DIRECT 0x8000 /* direct disk access hint - currently ignored*/
-#define O_NOATIME 0x100000
-
-#define F_GETLK 14
-#define F_GETLK64 15
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
+#define O_EXCL 0200 /* not fcntl */
+#define O_NOCTTY 0400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#define O_SYNC 010000
+#define FASYNC 020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT 040000 /* direct disk access hint */
+#define O_LARGEFILE 0100000
+#define O_DIRECTORY 0200000 /* must be a directory */
+#define O_NOFOLLOW 0400000 /* don't follow links */
+#define O_NOATIME 01000000
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get close_on_exec */
+#define F_SETFD 2 /* set/clear close_on_exec */
+#define F_GETFL 3 /* get file->f_flags */
+#define F_SETFL 4 /* set file->f_flags */
+#define F_GETLK 5
#define F_SETLK 6
#define F_SETLKW 7
-#define F_SETLK64 16
-#define F_SETLKW64 17
-#define F_SETOWN 24 /* for sockets. */
-#define F_GETOWN 23 /* for sockets. */
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
-typedef struct flock {
+/* for leases */
+#define F_INPROGRESS 16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock */
+#define LOCK_READ 64 /* ... Which allows concurrent read operations */
+#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
+#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
+
+struct flock {
short l_type;
short l_whence;
- __kernel_off_t l_start;
- __kernel_off_t l_len;
- long l_sysid;
- __kernel_pid_t l_pid;
- long pad[4];
-} flock_t;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
struct flock64 {
short l_type;
short l_whence;
- __kernel_off_t l_start;
- __kernel_off_t l_len;
+ loff_t l_start;
+ loff_t l_len;
pid_t l_pid;
};
-#define HAVE_ARCH_STRUCT_FLOCK
-#define HAVE_ARCH_STRUCT_FLOCK64
-
-#include <asm-generic/fcntl.h>
+#define F_LINUX_SPECIFIC_BASE 1024
#endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/fixmap.h b/include/asm-xtensa/fixmap.h
deleted file mode 100644
index 4423b8ad495..00000000000
--- a/include/asm-xtensa/fixmap.h
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * include/asm-xtensa/fixmap.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_FIXMAP_H
-#define _XTENSA_FIXMAP_H
-
-#include <asm/processor.h>
-
-#ifdef CONFIG_MMU
-
-/*
- * Here we define all the compile-time virtual addresses.
- */
-
-#if XCHAL_SEG_MAPPABLE_VADDR != 0
-# error "Current port requires virtual user space starting at 0"
-#endif
-#if XCHAL_SEG_MAPPABLE_SIZE < 0x80000000
-# error "Current port requires at least 0x8000000 bytes for user space"
-#endif
-
-/* Verify instruction/data ram/rom and xlmi don't overlay vmalloc space. */
-
-#define __IN_VMALLOC(addr) \
- (((addr) >= VMALLOC_START) && ((addr) < VMALLOC_END))
-#define __SPAN_VMALLOC(start,end) \
- (((start) < VMALLOC_START) && ((end) >= VMALLOC_END))
-#define INSIDE_VMALLOC(start,end) \
- (__IN_VMALLOC((start)) || __IN_VMALLOC(end) || __SPAN_VMALLOC((start),(end)))
-
-#if XCHAL_NUM_INSTROM
-# if XCHAL_NUM_INSTROM == 1
-# if INSIDE_VMALLOC(XCHAL_INSTROM0_VADDR,XCHAL_INSTROM0_VADDR+XCHAL_INSTROM0_SIZE)
-# error vmalloc range conflicts with instrom0
-# endif
-# endif
-# if XCHAL_NUM_INSTROM == 2
-# if INSIDE_VMALLOC(XCHAL_INSTROM1_VADDR,XCHAL_INSTROM1_VADDR+XCHAL_INSTROM1_SIZE)
-# error vmalloc range conflicts with instrom1
-# endif
-# endif
-#endif
-
-#if XCHAL_NUM_INSTRAM
-# if XCHAL_NUM_INSTRAM == 1
-# if INSIDE_VMALLOC(XCHAL_INSTRAM0_VADDR,XCHAL_INSTRAM0_VADDR+XCHAL_INSTRAM0_SIZE)
-# error vmalloc range conflicts with instram0
-# endif
-# endif
-# if XCHAL_NUM_INSTRAM == 2
-# if INSIDE_VMALLOC(XCHAL_INSTRAM1_VADDR,XCHAL_INSTRAM1_VADDR+XCHAL_INSTRAM1_SIZE)
-# error vmalloc range conflicts with instram1
-# endif
-# endif
-#endif
-
-#if XCHAL_NUM_DATAROM
-# if XCHAL_NUM_DATAROM == 1
-# if INSIDE_VMALLOC(XCHAL_DATAROM0_VADDR,XCHAL_DATAROM0_VADDR+XCHAL_DATAROM0_SIZE)
-# error vmalloc range conflicts with datarom0
-# endif
-# endif
-# if XCHAL_NUM_DATAROM == 2
-# if INSIDE_VMALLOC(XCHAL_DATAROM1_VADDR,XCHAL_DATAROM1_VADDR+XCHAL_DATAROM1_SIZE)
-# error vmalloc range conflicts with datarom1
-# endif
-# endif
-#endif
-
-#if XCHAL_NUM_DATARAM
-# if XCHAL_NUM_DATARAM == 1
-# if INSIDE_VMALLOC(XCHAL_DATARAM0_VADDR,XCHAL_DATARAM0_VADDR+XCHAL_DATARAM0_SIZE)
-# error vmalloc range conflicts with dataram0
-# endif
-# endif
-# if XCHAL_NUM_DATARAM == 2
-# if INSIDE_VMALLOC(XCHAL_DATARAM1_VADDR,XCHAL_DATARAM1_VADDR+XCHAL_DATARAM1_SIZE)
-# error vmalloc range conflicts with dataram1
-# endif
-# endif
-#endif
-
-#if XCHAL_NUM_XLMI
-# if XCHAL_NUM_XLMI == 1
-# if INSIDE_VMALLOC(XCHAL_XLMI0_VADDR,XCHAL_XLMI0_VADDR+XCHAL_XLMI0_SIZE)
-# error vmalloc range conflicts with xlmi0
-# endif
-# endif
-# if XCHAL_NUM_XLMI == 2
-# if INSIDE_VMALLOC(XCHAL_XLMI1_VADDR,XCHAL_XLMI1_VADDR+XCHAL_XLMI1_SIZE)
-# error vmalloc range conflicts with xlmi1
-# endif
-# endif
-#endif
-
-#if (XCHAL_NUM_INSTROM > 2) || \
- (XCHAL_NUM_INSTRAM > 2) || \
- (XCHAL_NUM_DATARAM > 2) || \
- (XCHAL_NUM_DATAROM > 2) || \
- (XCHAL_NUM_XLMI > 2)
-# error Insufficient checks on vmalloc above for more than 2 devices
-#endif
-
-/*
- * USER_VM_SIZE does not necessarily equal TASK_SIZE. We bumped
- * TASK_SIZE down to 0x4000000 to simplify the handling of windowed
- * call instructions (currently limited to a range of 1 GByte). User
- * tasks may very well reclaim the VM space from 0x40000000 to
- * 0x7fffffff in the future, so we do not want the kernel becoming
- * accustomed to having any of its stuff (e.g., page tables) in this
- * region. This VM region is no-man's land for now.
- */
-
-#define USER_VM_START XCHAL_SEG_MAPPABLE_VADDR
-#define USER_VM_SIZE 0x80000000
-
-/* Size of page table: */
-
-#define PGTABLE_SIZE_BITS (32 - XCHAL_MMU_MIN_PTE_PAGE_SIZE + 2)
-#define PGTABLE_SIZE (1L << PGTABLE_SIZE_BITS)
-
-/* All kernel-mappable space: */
-
-#define KERNEL_ALLMAP_START (USER_VM_START + USER_VM_SIZE)
-#define KERNEL_ALLMAP_SIZE (XCHAL_SEG_MAPPABLE_SIZE - KERNEL_ALLMAP_START)
-
-/* Carve out page table at start of kernel-mappable area: */
-
-#if KERNEL_ALLMAP_SIZE < PGTABLE_SIZE
-#error "Gimme some space for page table!"
-#endif
-#define PGTABLE_START KERNEL_ALLMAP_START
-
-/* Remaining kernel-mappable space: */
-
-#define KERNEL_MAPPED_START (KERNEL_ALLMAP_START + PGTABLE_SIZE)
-#define KERNEL_MAPPED_SIZE (KERNEL_ALLMAP_SIZE - PGTABLE_SIZE)
-
-#if KERNEL_MAPPED_SIZE < 0x01000000 /* 16 MB is arbitrary for now */
-# error "Shouldn't the kernel have at least *some* mappable space?"
-#endif
-
-#define MAX_LOW_MEMORY XCHAL_KSEG_CACHED_SIZE
-
-#endif
-
-/*
- * Some constants used elsewhere, but perhaps only in Xtensa header
- * files, so maybe we can get rid of some and access compile-time HAL
- * directly...
- *
- * Note: We assume that system RAM is located at the very start of the
- * kernel segments !!
- */
-#define KERNEL_VM_LOW XCHAL_KSEG_CACHED_VADDR
-#define KERNEL_VM_HIGH XCHAL_KSEG_BYPASS_VADDR
-#define KERNEL_SPACE XCHAL_KSEG_CACHED_VADDR
-
-/*
- * Returns the physical/virtual addresses of the kernel space
- * (works with the cached kernel segment only, which is the
- * one normally used for kernel operation).
- */
-
-/* PHYSICAL BYPASS CACHED
- *
- * bypass vaddr bypass paddr * cached vaddr
- * cached vaddr cached paddr bypass vaddr *
- * bypass paddr * bypass vaddr cached vaddr
- * cached paddr * bypass vaddr cached vaddr
- * other * * *
- */
-
-#define PHYSADDR(a) \
-(((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR \
- && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_PADDR : \
- ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR \
- && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_PADDR : \
- (unsigned)(a))
-
-#define BYPASS_ADDR(a) \
-(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR \
- && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_VADDR : \
- ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR \
- && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_BYPASS_VADDR : \
- ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR \
- && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_CACHED_SIZE)? \
- (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_BYPASS_VADDR: \
- (unsigned)(a))
-
-#define CACHED_ADDR(a) \
-(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR \
- && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_CACHED_VADDR : \
- ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR \
- && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_VADDR : \
- ((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR \
- && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_CACHED_VADDR : \
- (unsigned)(a))
-
-#define PHYSADDR_IO(a) \
-(((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR \
- && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_PADDR : \
- ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR \
- && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_PADDR : \
- (unsigned)(a))
-
-#define BYPASS_ADDR_IO(a) \
-(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR \
- && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_VADDR : \
- ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR \
- && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_BYPASS_VADDR : \
- ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR \
- && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_BYPASS_VADDR : \
- (unsigned)(a))
-
-#define CACHED_ADDR_IO(a) \
-(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR \
- && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_CACHED_VADDR : \
- ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR \
- && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_VADDR : \
- ((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR \
- && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
- (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_CACHED_VADDR : \
- (unsigned)(a))
-
-#endif /* _XTENSA_ADDRSPACE_H */
-
-
-
-
-
diff --git a/include/asm-xtensa/io.h b/include/asm-xtensa/io.h
index 556e5eed34f..31ffc3f119c 100644
--- a/include/asm-xtensa/io.h
+++ b/include/asm-xtensa/io.h
@@ -1,5 +1,5 @@
/*
- * linux/include/asm-xtensa/io.h
+ * include/asm-xtensa/io.h
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -15,10 +15,11 @@
#include <asm/byteorder.h>
#include <linux/types.h>
-#include <asm/fixmap.h>
-
-#define _IO_BASE 0
+#define XCHAL_KIO_CACHED_VADDR 0xf0000000
+#define XCHAL_KIO_BYPASS_VADDR 0xf8000000
+#define XCHAL_KIO_PADDR 0xf0000000
+#define XCHAL_KIO_SIZE 0x08000000
/*
* swap functions to change byte order from little-endian to big-endian and
@@ -42,40 +43,43 @@ static inline unsigned int _swapl (unsigned int v)
static inline unsigned long virt_to_phys(volatile void * address)
{
- return PHYSADDR((unsigned long)address);
+ return __pa(address);
}
static inline void * phys_to_virt(unsigned long address)
{
- return (void*) CACHED_ADDR(address);
+ return __va(address);
}
/*
- * IO bus memory addresses are also 1:1 with the physical address
+ * virt_to_bus and bus_to_virt are deprecated.
*/
-static inline unsigned long virt_to_bus(volatile void * address)
-{
- return PHYSADDR((unsigned long)address);
-}
-
-static inline void * bus_to_virt (unsigned long address)
-{
- return (void *) CACHED_ADDR(address);
-}
+#define virt_to_bus(x) virt_to_phys(x)
+#define bus_to_virt(x) phys_to_virt(x)
/*
- * Change "struct page" to physical address.
+ * Return the virtual (cached) address for the specified bus memory.
+ * Note that we currently don't support any address outside the KIO segment.
*/
static inline void *ioremap(unsigned long offset, unsigned long size)
{
- return (void *) CACHED_ADDR_IO(offset);
+ if (offset >= XCHAL_KIO_PADDR
+ && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE)
+ return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR);
+
+ else
+ BUG();
}
static inline void *ioremap_nocache(unsigned long offset, unsigned long size)
{
- return (void *) BYPASS_ADDR_IO(offset);
+ if (offset >= XCHAL_KIO_PADDR
+ && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE)
+ return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR);
+ else
+ BUG();
}
static inline void iounmap(void *addr)
@@ -121,9 +125,6 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
*(__force volatile __u32 *)(addr) = b;
}
-
-
-
/* These are the definitions for the x86 IO instructions
* inb/inw/inl/outb/outw/outl, the "string" versions
* insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
@@ -131,11 +132,11 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
* The macros don't do byte-swapping.
*/
-#define inb(port) readb((u8 *)((port)+_IO_BASE))
-#define outb(val, port) writeb((val),(u8 *)((unsigned long)(port)+_IO_BASE))
-#define inw(port) readw((u16 *)((port)+_IO_BASE))
-#define outw(val, port) writew((val),(u16 *)((unsigned long)(port)+_IO_BASE))
-#define inl(port) readl((u32 *)((port)+_IO_BASE))
+#define inb(port) readb((u8 *)((port)))
+#define outb(val, port) writeb((val),(u8 *)((unsigned long)(port)))
+#define inw(port) readw((u16 *)((port)))
+#define outw(val, port) writew((val),(u16 *)((unsigned long)(port)))
+#define inl(port) readl((u32 *)((port)))
#define outl(val, port) writel((val),(u32 *)((unsigned long)(port)))
#define inb_p(port) inb((port))
@@ -180,14 +181,13 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
/*
- * * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * * access
- * */
+ * 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
- * */
+ * Convert a virtual cached pointer to an uncached pointer
+ */
#define xlate_dev_kmem_ptr(p) p
diff --git a/include/asm-xtensa/irq.h b/include/asm-xtensa/irq.h
index 049fde7e752..fc73b7f11af 100644
--- a/include/asm-xtensa/irq.h
+++ b/include/asm-xtensa/irq.h
@@ -12,8 +12,7 @@
#define _XTENSA_IRQ_H
#include <asm/platform/hardware.h>
-
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
#ifndef PLATFORM_NR_IRQS
# define PLATFORM_NR_IRQS 0
@@ -27,10 +26,5 @@ static __inline__ int irq_canonicalize(int irq)
}
struct irqaction;
-#if 0 // FIXME
-extern void disable_irq_nosync(unsigned int);
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-#endif
#endif /* _XTENSA_IRQ_H */
diff --git a/include/asm-xtensa/irq_regs.h b/include/asm-xtensa/irq_regs.h
new file mode 100644
index 00000000000..3dd9c0b7027
--- /dev/null
+++ b/include/asm-xtensa/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
index af683a74a4e..f14851f086c 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/include/asm-xtensa/mmu_context.h
@@ -16,187 +16,32 @@
#include <linux/stringify.h>
#include <asm/pgtable.h>
-#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-/*
- * Linux was ported to Xtensa assuming all auto-refill ways in set 0
- * had the same properties (a very likely assumption). Multiple sets
- * of auto-refill ways will still work properly, but not as optimally
- * as the Xtensa designer may have assumed.
- *
- * We make this case a hard #error, killing the kernel build, to alert
- * the developer to this condition (which is more likely an error).
- * You super-duper clever developers can change it to a warning or
- * remove it altogether if you think you know what you're doing. :)
- */
+#define XCHAL_MMU_ASID_BITS 8
#if (XCHAL_HAVE_TLBS != 1)
# error "Linux must have an MMU!"
#endif
-#if ((XCHAL_ITLB_ARF_WAYS == 0) || (XCHAL_DTLB_ARF_WAYS == 0))
-# error "MMU must have auto-refill ways"
-#endif
-
-#if ((XCHAL_ITLB_ARF_SETS != 1) || (XCHAL_DTLB_ARF_SETS != 1))
-# error Linux may not use all auto-refill ways as efficiently as you think
-#endif
-
-#if (XCHAL_MMU_MAX_PTE_PAGE_SIZE != XCHAL_MMU_MIN_PTE_PAGE_SIZE)
-# error Only one page size allowed!
-#endif
-
extern unsigned long asid_cache;
-extern pgd_t *current_pgd;
-
-/*
- * Define the number of entries per auto-refill way in set 0 of both I and D
- * TLBs. We deal only with set 0 here (an assumption further explained in
- * assertions.h). Also, define the total number of ARF entries in both TLBs.
- */
-
-#define ITLB_ENTRIES_PER_ARF_WAY (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES))
-#define DTLB_ENTRIES_PER_ARF_WAY (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES))
-
-#define ITLB_ENTRIES \
- (ITLB_ENTRIES_PER_ARF_WAY * (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,WAYS)))
-#define DTLB_ENTRIES \
- (DTLB_ENTRIES_PER_ARF_WAY * (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,WAYS)))
-
-
-/*
- * SMALLEST_NTLB_ENTRIES is the smaller of ITLB_ENTRIES and DTLB_ENTRIES.
- * In practice, they are probably equal. This macro simplifies function
- * flush_tlb_range().
- */
-
-#if (DTLB_ENTRIES < ITLB_ENTRIES)
-# define SMALLEST_NTLB_ENTRIES DTLB_ENTRIES
-#else
-# define SMALLEST_NTLB_ENTRIES ITLB_ENTRIES
-#endif
-
-
-/*
- * asid_cache tracks only the ASID[USER_RING] field of the RASID special
- * register, which is the current user-task asid allocation value.
- * mm->context has the same meaning. When it comes time to write the
- * asid_cache or mm->context values to the RASID special register, we first
- * shift the value left by 8, then insert the value.
- * ASID[0] always contains the kernel's asid value, and we reserve three
- * other asid values that we never assign to user tasks.
- */
-
-#define ASID_INC 0x1
-#define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1)
-
-/*
- * XCHAL_MMU_ASID_INVALID is a configurable Xtensa processor constant
- * indicating invalid address space. XCHAL_MMU_ASID_KERNEL is a configurable
- * Xtensa processor constant indicating the kernel address space. They can
- * be arbitrary values.
- *
- * We identify three more unique, reserved ASID values to use in the unused
- * ring positions. No other user process will be assigned these reserved
- * ASID values.
- *
- * For example, given that
- *
- * XCHAL_MMU_ASID_INVALID == 0
- * XCHAL_MMU_ASID_KERNEL == 1
- *
- * the following maze of #if statements would generate
- *
- * ASID_RESERVED_1 == 2
- * ASID_RESERVED_2 == 3
- * ASID_RESERVED_3 == 4
- * ASID_FIRST_NONRESERVED == 5
- */
-
-#if (XCHAL_MMU_ASID_INVALID != XCHAL_MMU_ASID_KERNEL + 1)
-# define ASID_RESERVED_1 ((XCHAL_MMU_ASID_KERNEL + 1) & ASID_MASK)
-#else
-# define ASID_RESERVED_1 ((XCHAL_MMU_ASID_KERNEL + 2) & ASID_MASK)
-#endif
-
-#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_1 + 1)
-# define ASID_RESERVED_2 ((ASID_RESERVED_1 + 1) & ASID_MASK)
-#else
-# define ASID_RESERVED_2 ((ASID_RESERVED_1 + 2) & ASID_MASK)
-#endif
-
-#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_2 + 1)
-# define ASID_RESERVED_3 ((ASID_RESERVED_2 + 1) & ASID_MASK)
-#else
-# define ASID_RESERVED_3 ((ASID_RESERVED_2 + 2) & ASID_MASK)
-#endif
-
-#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_3 + 1)
-# define ASID_FIRST_NONRESERVED ((ASID_RESERVED_3 + 1) & ASID_MASK)
-#else
-# define ASID_FIRST_NONRESERVED ((ASID_RESERVED_3 + 2) & ASID_MASK)
-#endif
-
-#define ASID_ALL_RESERVED ( ((ASID_RESERVED_1) << 24) + \
- ((ASID_RESERVED_2) << 16) + \
- ((ASID_RESERVED_3) << 8) + \
- ((XCHAL_MMU_ASID_KERNEL)) )
-
/*
* NO_CONTEXT is the invalid ASID value that we don't ever assign to
- * any user or kernel context. NO_CONTEXT is a better mnemonic than
- * XCHAL_MMU_ASID_INVALID, so we use it in code instead.
- */
-
-#define NO_CONTEXT XCHAL_MMU_ASID_INVALID
-
-#if (KERNEL_RING != 0)
-# error The KERNEL_RING really should be zero.
-#endif
-
-#if (USER_RING >= XCHAL_MMU_RINGS)
-# error USER_RING cannot be greater than the highest numbered ring.
-#endif
-
-#if (USER_RING == KERNEL_RING)
-# error The user and kernel rings really should not be equal.
-#endif
-
-#if (USER_RING == 1)
-#define ASID_INSERT(x) ( ((ASID_RESERVED_1) << 24) + \
- ((ASID_RESERVED_2) << 16) + \
- (((x) & (ASID_MASK)) << 8) + \
- ((XCHAL_MMU_ASID_KERNEL)) )
-
-#elif (USER_RING == 2)
-#define ASID_INSERT(x) ( ((ASID_RESERVED_1) << 24) + \
- (((x) & (ASID_MASK)) << 16) + \
- ((ASID_RESERVED_2) << 8) + \
- ((XCHAL_MMU_ASID_KERNEL)) )
-
-#elif (USER_RING == 3)
-#define ASID_INSERT(x) ( (((x) & (ASID_MASK)) << 24) + \
- ((ASID_RESERVED_1) << 16) + \
- ((ASID_RESERVED_2) << 8) + \
- ((XCHAL_MMU_ASID_KERNEL)) )
-
-#else
-#error Goofy value for USER_RING
-
-#endif /* USER_RING == 1 */
-
-
-/*
- * All unused by hardware upper bits will be considered
- * as a software asid extension.
+ * any user or kernel context.
+ *
+ * 0 invalid
+ * 1 kernel
+ * 2 reserved
+ * 3 reserved
+ * 4...255 available
*/
-#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
-#define ASID_FIRST_VERSION \
- ((unsigned long)(~ASID_VERSION_MASK) + 1 + ASID_FIRST_NONRESERVED)
+#define NO_CONTEXT 0
+#define ASID_USER_FIRST 4
+#define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1)
+#define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8))
static inline void set_rasid_register (unsigned long val)
{
@@ -207,67 +52,28 @@ static inline void set_rasid_register (unsigned long val)
static inline unsigned long get_rasid_register (void)
{
unsigned long tmp;
- __asm__ __volatile__ (" rsr %0, "__stringify(RASID)"\n\t" : "=a" (tmp));
+ __asm__ __volatile__ (" rsr %0,"__stringify(RASID)"\n\t" : "=a" (tmp));
return tmp;
}
-
-#if ((XCHAL_MMU_ASID_INVALID == 0) && (XCHAL_MMU_ASID_KERNEL == 1))
-
static inline void
-get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+__get_new_mmu_context(struct mm_struct *mm)
{
extern void flush_tlb_all(void);
- if (! ((asid += ASID_INC) & ASID_MASK) ) {
+ if (! (++asid_cache & ASID_MASK) ) {
flush_tlb_all(); /* start new asid cycle */
- if (!asid) /* fix version if needed */
- asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
- asid += ASID_FIRST_NONRESERVED;
+ asid_cache += ASID_USER_FIRST;
}
- mm->context = asid_cache = asid;
-}
-
-#else
-#warning ASID_{INVALID,KERNEL} values impose non-optimal get_new_mmu_context implementation
-
-/* XCHAL_MMU_ASID_INVALID == 0 and XCHAL_MMU_ASID_KERNEL ==1 are
- really the best, but if you insist... */
-
-static inline int validate_asid (unsigned long asid)
-{
- switch (asid) {
- case XCHAL_MMU_ASID_INVALID:
- case XCHAL_MMU_ASID_KERNEL:
- case ASID_RESERVED_1:
- case ASID_RESERVED_2:
- case ASID_RESERVED_3:
- return 0; /* can't use these values as ASIDs */
- }
- return 1; /* valid */
+ mm->context = asid_cache;
}
static inline void
-get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+__load_mmu_context(struct mm_struct *mm)
{
- extern void flush_tlb_all(void);
- while (1) {
- asid += ASID_INC;
- if ( ! (asid & ASID_MASK) ) {
- flush_tlb_all(); /* start new asid cycle */
- if (!asid) /* fix version if needed */
- asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
- asid += ASID_FIRST_NONRESERVED;
- break; /* no need to validate here */
- }
- if (validate_asid (asid & ASID_MASK))
- break;
- }
- mm->context = asid_cache = asid;
+ set_rasid_register(ASID_INSERT(mm->context));
+ invalidate_page_directory();
}
-#endif
-
-
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -280,6 +86,20 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
return 0;
}
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static inline void
+activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+ /* Unconditionally get a new ASID. */
+
+ __get_new_mmu_context(next);
+ __load_mmu_context(next);
+}
+
+
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
@@ -287,11 +107,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
/* Check if our ASID is of an older version and thus invalid */
- if ((next->context ^ asid) & ASID_VERSION_MASK)
- get_new_mmu_context(next, asid);
+ if (next->context == NO_CONTEXT || ((next->context^asid) & ~ASID_MASK))
+ __get_new_mmu_context(next);
- set_rasid_register (ASID_INSERT(next->context));
- invalidate_page_directory();
+ __load_mmu_context(next);
}
#define deactivate_mm(tsk, mm) do { } while(0)
@@ -302,20 +121,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
*/
static inline void destroy_context(struct mm_struct *mm)
{
- /* Nothing to do. */
-}
-
-/*
- * After we have set current->mm to a new value, this activates
- * the context for the new mm so we see the new mappings.
- */
-static inline void
-activate_mm(struct mm_struct *prev, struct mm_struct *next)
-{
- /* Unconditionally get a new ASID. */
-
- get_new_mmu_context(next, asid_cache);
- set_rasid_register (ASID_INSERT(next->context));
invalidate_page_directory();
}
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 40f4c6c3f58..c631d006194 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -15,18 +15,24 @@
#include <asm/processor.h>
+#define XCHAL_KSEG_CACHED_VADDR 0xd0000000
+#define XCHAL_KSEG_BYPASS_VADDR 0xd8000000
+#define XCHAL_KSEG_PADDR 0x00000000
+#define XCHAL_KSEG_SIZE 0x08000000
+
/*
* PAGE_SHIFT determines the page size
* PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
*/
-#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
+#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
-#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
+#define MAX_MEM_PFN XCHAL_KSEG_SIZE
+#define PGTABLE_START 0x80000000
#ifdef __ASSEMBLY__
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
index c0eec8260b0..6f281392e3f 100644
--- a/include/asm-xtensa/param.h
+++ b/include/asm-xtensa/param.h
@@ -11,7 +11,7 @@
#ifndef _XTENSA_PARAM_H
#define _XTENSA_PARAM_H
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
#ifdef __KERNEL__
# define HZ 100 /* internal timer frequency */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index b4318934b10..2d4b5db6ea6 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -14,45 +14,6 @@
#include <asm-generic/pgtable-nopmd.h>
#include <asm/page.h>
-/* Assertions. */
-
-#ifdef CONFIG_MMU
-
-
-#if (XCHAL_MMU_RINGS < 2)
-# error Linux build assumes at least 2 ring levels.
-#endif
-
-#if (XCHAL_MMU_CA_BITS != 4)
-# error We assume exactly four bits for CA.
-#endif
-
-#if (XCHAL_MMU_SR_BITS != 0)
-# error We have no room for SR bits.
-#endif
-
-/*
- * Use the first min-wired way for mapping page-table pages.
- * Page coloring requires a second min-wired way.
- */
-
-#if (XCHAL_DTLB_MINWIRED_SETS == 0)
-# error Need a min-wired way for mapping page-table pages
-#endif
-
-#define DTLB_WAY_PGTABLE XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAY)
-
-#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
-# if XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAYS) >= 2
-# define DTLB_WAY_DCACHE_ALIAS0 (DTLB_WAY_PGTABLE + 1)
-# define DTLB_WAY_DCACHE_ALIAS1 (DTLB_WAY_PGTABLE + 2)
-# else
-# error Page coloring requires its own wired dtlb way!
-# endif
-#endif
-
-#endif /* CONFIG_MMU */
-
/*
* We only use two ring levels, user and kernel space.
*/
@@ -97,7 +58,7 @@
#define PGD_ORDER 0
#define PMD_ORDER 0
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
-#define FIRST_USER_ADDRESS XCHAL_SEG_MAPPABLE_VADDR
+#define FIRST_USER_ADDRESS 0
#define FIRST_USER_PGD_NR (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
/* virtual memory area. We keep a distance to other memory regions to be
diff --git a/include/asm-xtensa/platform-iss/hardware.h b/include/asm-xtensa/platform-iss/hardware.h
index 22240f00180..6930c12adc1 100644
--- a/include/asm-xtensa/platform-iss/hardware.h
+++ b/include/asm-xtensa/platform-iss/hardware.h
@@ -12,18 +12,18 @@
* This file contains the default configuration of ISS.
*/
-#ifndef __ASM_XTENSA_ISS_HARDWARE
-#define __ASM_XTENSA_ISS_HARDWARE
+#ifndef _XTENSA_PLATFORM_ISS_HARDWARE_H
+#define _XTENSA_PLATFORM_ISS_HARDWARE_H
/*
* Memory configuration.
*/
-#define PLATFORM_DEFAULT_MEM_START XSHAL_RAM_PADDR
-#define PLATFORM_DEFAULT_MEM_SIZE XSHAL_RAM_VSIZE
+#define PLATFORM_DEFAULT_MEM_START 0x00000000
+#define PLATFORM_DEFAULT_MEM_SIZE 0x08000000
/*
* Interrupt configuration.
*/
-#endif /* __ASM_XTENSA_ISS_HARDWARE */
+#endif /* _XTENSA_PLATFORM_ISS_HARDWARE_H */
diff --git a/include/asm-xtensa/platform-iss/simcall.h b/include/asm-xtensa/platform-iss/simcall.h
new file mode 100644
index 00000000000..6acb572759a
--- /dev/null
+++ b/include/asm-xtensa/platform-iss/simcall.h
@@ -0,0 +1,62 @@
+/*
+ * include/asm-xtensa/platform-iss/hardware.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H
+#define _XTENSA_PLATFORM_ISS_SIMCALL_H
+
+
+/*
+ * System call like services offered by the simulator host.
+ */
+
+#define SYS_nop 0 /* unused */
+#define SYS_exit 1 /*x*/
+#define SYS_fork 2
+#define SYS_read 3 /*x*/
+#define SYS_write 4 /*x*/
+#define SYS_open 5 /*x*/
+#define SYS_close 6 /*x*/
+#define SYS_rename 7 /*x 38 - waitpid */
+#define SYS_creat 8 /*x*/
+#define SYS_link 9 /*x (not implemented on WIN32) */
+#define SYS_unlink 10 /*x*/
+#define SYS_execv 11 /* n/a - execve */
+#define SYS_execve 12 /* 11 - chdir */
+#define SYS_pipe 13 /* 42 - time */
+#define SYS_stat 14 /* 106 - mknod */
+#define SYS_chmod 15
+#define SYS_chown 16 /* 202 - lchown */
+#define SYS_utime 17 /* 30 - break */
+#define SYS_wait 18 /* n/a - oldstat */
+#define SYS_lseek 19 /*x*/
+#define SYS_getpid 20
+#define SYS_isatty 21 /* n/a - mount */
+#define SYS_fstat 22 /* 108 - oldumount */
+#define SYS_time 23 /* 13 - setuid */
+#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */
+#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */
+#define SYS_socket 26
+#define SYS_sendto 27
+#define SYS_recvfrom 28
+#define SYS_select_one 29 /* not compitible select, one file descriptor at the time */
+#define SYS_bind 30
+#define SYS_ioctl 31
+
+/*
+ * SYS_select_one specifiers
+ */
+
+#define XTISS_SELECT_ONE_READ 1
+#define XTISS_SELECT_ONE_WRITE 2
+#define XTISS_SELECT_ONE_EXCEPT 3
+
+
+#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */
+
diff --git a/include/asm-xtensa/posix_types.h b/include/asm-xtensa/posix_types.h
index 2c816b0e776..4ad77dda6d5 100644
--- a/include/asm-xtensa/posix_types.h
+++ b/include/asm-xtensa/posix_types.h
@@ -21,7 +21,7 @@
typedef unsigned long __kernel_ino_t;
typedef unsigned int __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
+typedef unsigned long __kernel_nlink_t;
typedef long __kernel_off_t;
typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
@@ -60,7 +60,7 @@ typedef struct {
#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
#define __FD_ZERO(set) \
- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+ ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
#else /* __GNUC__ */
diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h
index 8b96e77c9d8..4feb9f7f35a 100644
--- a/include/asm-xtensa/processor.h
+++ b/include/asm-xtensa/processor.h
@@ -11,24 +11,18 @@
#ifndef _XTENSA_PROCESSOR_H
#define _XTENSA_PROCESSOR_H
-#ifdef __ASSEMBLY__
-#define _ASMLANGUAGE
-#endif
-
-#include <xtensa/config/core.h>
-#include <xtensa/config/specreg.h>
-#include <xtensa/config/tie.h>
-#include <xtensa/config/system.h>
+#include <asm/variant/core.h>
+#include <asm/coprocessor.h>
#include <linux/compiler.h>
#include <asm/ptrace.h>
#include <asm/types.h>
-#include <asm/coprocessor.h>
+#include <asm/regs.h>
/* Assertions. */
#if (XCHAL_HAVE_WINDOWED != 1)
-#error Linux requires the Xtensa Windowed Registers Option.
+# error Linux requires the Xtensa Windowed Registers Option.
#endif
/*
@@ -145,11 +139,11 @@ struct thread_struct {
* Note: We set-up ps as if we did a call4 to the new pc.
* set_thread_state in signal.c depends on it.
*/
-#define USER_PS_VALUE ( (1 << XCHAL_PS_WOE_SHIFT) + \
- (1 << XCHAL_PS_CALLINC_SHIFT) + \
- (USER_RING << XCHAL_PS_RING_SHIFT) + \
- (1 << XCHAL_PS_PROGSTACK_SHIFT) + \
- (1 << XCHAL_PS_EXCM_SHIFT) )
+#define USER_PS_VALUE ((1 << PS_WOE_BIT) | \
+ (1 << PS_CALLINC_SHIFT) | \
+ (USER_RING << PS_RING_SHIFT) | \
+ (1 << PS_UM_BIT) | \
+ (1 << PS_EXCM_BIT))
/* Clearing a0 terminates the backtrace. */
#define start_thread(regs, new_pc, new_sp) \
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index a5ac71a5205..1b7fe363fad 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -11,7 +11,7 @@
#ifndef _XTENSA_PTRACE_H
#define _XTENSA_PTRACE_H
-#include <xtensa/config/core.h>
+#include <asm/variant/core.h>
/*
* Kernel stack
diff --git a/include/asm-xtensa/regs.h b/include/asm-xtensa/regs.h
new file mode 100644
index 00000000000..c913d259faa
--- /dev/null
+++ b/include/asm-xtensa/regs.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006 Tensilica, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * 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 Lesser 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.
+ */
+
+#ifndef _XTENSA_REGS_H
+#define _XTENSA_REGS_H
+
+/* Special registers. */
+
+#define LBEG 0
+#define LEND 1
+#define LCOUNT 2
+#define SAR 3
+#define BR 4
+#define SCOMPARE1 12
+#define ACCHI 16
+#define ACCLO 17
+#define MR 32
+#define WINDOWBASE 72
+#define WINDOWSTART 73
+#define PTEVADDR 83
+#define RASID 90
+#define ITLBCFG 91
+#define DTLBCFG 92
+#define IBREAKENABLE 96
+#define DDR 104
+#define IBREAKA 128
+#define DBREAKA 144
+#define DBREAKC 160
+#define EPC 176
+#define EPC_1 177
+#define DEPC 192
+#define EPS 192
+#define EPS_1 193
+#define EXCSAVE 208
+#define EXCSAVE_1 209
+#define INTERRUPT 226
+#define INTENABLE 228
+#define PS 230
+#define THREADPTR 231
+#define EXCCAUSE 232
+#define DEBUGCAUSE 233
+#define CCOUNT 234
+#define PRID 235
+#define ICOUNT 236
+#define ICOUNTLEVEL 237
+#define EXCVADDR 238
+#define CCOMPARE 240
+#define MISC 244
+
+/* Special names for read-only and write-only interrupt registers. */
+
+#define INTREAD 226
+#define INTSET 226
+#define INTCLEAR 227
+
+/* EXCCAUSE register fields */
+
+#define EXCCAUSE_EXCCAUSE_SHIFT 0
+#define EXCCAUSE_EXCCAUSE_MASK 0x3F
+
+#define EXCCAUSE_ILLEGAL_INSTRUCTION 0
+#define EXCCAUSE_SYSTEM_CALL 1
+#define EXCCAUSE_INSTRUCTION_FETCH_ERROR 2
+#define EXCCAUSE_LOAD_STORE_ERROR 3
+#define EXCCAUSE_LEVEL1_INTERRUPT 4
+#define EXCCAUSE_ALLOCA 5
+#define EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6
+#define EXCCAUSE_SPECULATION 7
+#define EXCCAUSE_PRIVILEGED 8
+#define EXCCAUSE_UNALIGNED 9
+#define EXCCAUSE_ITLB_MISS 16
+#define EXCCAUSE_ITLB_MULTIHIT 17
+#define EXCCAUSE_ITLB_PRIVILEGE 18
+#define EXCCAUSE_ITLB_SIZE_RESTRICTION 19
+#define EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20
+#define EXCCAUSE_DTLB_MISS 24
+#define EXCCAUSE_DTLB_MULTIHIT 25
+#define EXCCAUSE_DTLB_PRIVILEGE 26
+#define EXCCAUSE_DTLB_SIZE_RESTRICTION 27
+#define EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28
+#define EXCCAUSE_STORE_CACHE_ATTRIBUTE 29
+#define EXCCAUSE_FLOATING_POINT 40
+
+/* PS register fields. */
+
+#define PS_WOE_BIT 18
+#define PS_CALLINC_SHIFT 16
+#define PS_CALLINC_MASK 0x00030000
+#define PS_OWB_SHIFT 8
+#define PS_OWB_MASK 0x00000F00
+#define PS_RING_SHIFT 6
+#define PS_RING_MASK 0x000000C0
+#define PS_UM_BIT 5
+#define PS_EXCM_BIT 4
+#define PS_INTLEVEL_SHIFT 0
+#define PS_INTLEVEL_MASK 0x0000000F
+
+/* DBREAKCn register fields. */
+
+#define DBREAKC_MASK_BIT 0
+#define DBREAKC_MASK_MASK 0x0000003F
+#define DBREAKC_LOAD_BIT 30
+#define DBREAKC_LOAD_MASK 0x40000000
+#define DBREAKC_STOR_BIT 31
+#define DBREAKC_STOR_MASK 0x80000000
+
+/* DEBUGCAUSE register fields. */
+
+#define DEBUGCAUSE_DEBUGINT_BIT 5 /* External debug interrupt */
+#define DEBUGCAUSE_BREAKN_BIT 4 /* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_BIT 3 /* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_BIT 2 /* DBREAK match */
+#define DEBUGCAUSE_IBREAK_BIT 1 /* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_BIT 0 /* ICOUNT would incr. to zero */
+
+#endif /* _XTENSA_SPECREG_H */
+
diff --git a/include/asm-xtensa/sembuf.h b/include/asm-xtensa/sembuf.h
index 2d26c47666f..c15870493b3 100644
--- a/include/asm-xtensa/sembuf.h
+++ b/include/asm-xtensa/sembuf.h
@@ -25,7 +25,7 @@
struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
-#if XCHAL_HAVE_LE
+#ifdef __XTENSA_EL__
__kernel_time_t sem_otime; /* last semop time */
unsigned long __unused1;
__kernel_time_t sem_ctime; /* last change time */
diff --git a/include/asm-xtensa/shmbuf.h b/include/asm-xtensa/shmbuf.h
index a30b81a4b93..ad4b0121782 100644
--- a/include/asm-xtensa/shmbuf.h
+++ b/include/asm-xtensa/shmbuf.h
@@ -19,6 +19,7 @@
#ifndef _XTENSA_SHMBUF_H
#define _XTENSA_SHMBUF_H
+#if defined (__XTENSA_EL__)
struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */
size_t shm_segsz; /* size of segment (bytes) */
@@ -34,6 +35,26 @@ struct shmid64_ds {
unsigned long __unused4;
unsigned long __unused5;
};
+#elif defined (__XTENSA_EB__)
+struct shmid64_ds {
+ struct ipc64_perm shm_perm; /* operation perms */
+ size_t shm_segsz; /* size of segment (bytes) */
+ __kernel_time_t shm_atime; /* last attach time */
+ unsigned long __unused1;
+ __kernel_time_t shm_dtime; /* last detach time */
+ unsigned long __unused2;
+ __kernel_time_t shm_ctime; /* last change time */
+ unsigned long __unused3;
+ __kernel_pid_t shm_cpid; /* pid of creator */
+ __kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+#else
+# error endian order not defined
+#endif
+
struct shminfo64 {
unsigned long shmmax;
diff --git a/include/asm-xtensa/stat.h b/include/asm-xtensa/stat.h
index 2f4662ff6c3..149f4bce092 100644
--- a/include/asm-xtensa/stat.h
+++ b/include/asm-xtensa/stat.h
@@ -13,93 +13,57 @@
#include <linux/types.h>
-struct __old_kernel_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
-};
-
#define STAT_HAVE_NSEC 1
struct stat {
- unsigned short st_dev;
- unsigned short __pad1;
- unsigned long st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned short __pad2;
- unsigned long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- unsigned long __unused4;
- unsigned long __unused5;
+ unsigned long st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned int st_rdev;
+ off_t st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ unsigned long __unused4;
+ unsigned long __unused5;
};
-/* This matches struct stat64 in glibc-2.2.3. */
+/* This matches struct stat64 in glibc-2.3 */
struct stat64 {
-#ifdef __XTENSA_EL__
- unsigned short st_dev; /* Device */
- unsigned char __pad0[10];
-#else
- unsigned char __pad0[6];
- unsigned short st_dev;
- unsigned char __pad1[2];
-#endif
-
-#define STAT64_HAS_BROKEN_ST_INO 1
- unsigned long __st_ino; /* 32bit file serial number. */
-
+ unsigned long long st_dev; /* Device */
+ unsigned long long st_ino; /* File serial number */
unsigned int st_mode; /* File mode. */
unsigned int st_nlink; /* Link count. */
unsigned int st_uid; /* User ID of the file's owner. */
unsigned int st_gid; /* Group ID of the file's group. */
-
-#ifdef __XTENSA_EL__
- unsigned short st_rdev; /* Device number, if device. */
- unsigned char __pad3[10];
-#else
- unsigned char __pad2[6];
- unsigned short st_rdev;
- unsigned char __pad3[2];
-#endif
-
- long long int st_size; /* Size of file, in bytes. */
- long int st_blksize; /* Optimal block size for I/O. */
-
-#ifdef __XTENSA_EL__
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4;
+ unsigned long long st_rdev; /* Device number, if device. */
+ long long st_size; /* Size of file, in bytes. */
+ long st_blksize; /* Optimal block size for I/O. */
+ unsigned long __unused2;
+#ifdef __XTENSA_EB__
+ unsigned long __unused3;
+ long st_blocks; /* Number 512-byte blocks allocated. */
#else
- unsigned long __pad4;
- unsigned long st_blocks;
+ long st_blocks; /* Number 512-byte blocks allocated. */
+ unsigned long __unused3;
#endif
-
- unsigned long __pad5;
- long int st_atime; /* Time of last access. */
- unsigned long st_atime_nsec;
- long int st_mtime; /* Time of last modification. */
- unsigned long st_mtime_nsec;
- long int st_ctime; /* Time of last status change. */
- unsigned long st_ctime_nsec;
- unsigned long long int st_ino; /* File serial number. */
+ long st_atime; /* Time of last access. */
+ unsigned long st_atime_nsec;
+ long st_mtime; /* Time of last modification. */
+ unsigned long st_mtime_nsec;
+ long st_ctime; /* Time of last status change. */
+ unsigned long st_ctime_nsec;
+ unsigned long __unused4;
+ unsigned long __unused5;
};
#endif /* _XTENSA_STAT_H */
diff --git a/include/asm-xtensa/syscall.h b/include/asm-xtensa/syscall.h
new file mode 100644
index 00000000000..6cb0d42f11c
--- /dev/null
+++ b/include/asm-xtensa/syscall.h
@@ -0,0 +1,20 @@
+struct pt_regs;
+struct sigaction;
+asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
+asmlinkage long xtensa_pipe(int __user *);
+asmlinkage long xtensa_mmap2(unsigned long, unsigned long, unsigned long,
+ unsigned long, unsigned long, unsigned long);
+asmlinkage long xtensa_ptrace(long, long, long, long);
+asmlinkage long xtensa_sigreturn(struct pt_regs*);
+asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
+asmlinkage long xtensa_sigsuspend(struct pt_regs*);
+asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*);
+asmlinkage long xtensa_sigaction(int, const struct old_sigaction*,
+ struct old_sigaction*);
+asmlinkage long xtensa_sigaltstack(struct pt_regs *regs);
+asmlinkage long sys_rt_sigaction(int,
+ const struct sigaction __user *,
+ struct sigaction __user *,
+ size_t);
+asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg);
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
index 932bda92a21..4aaed7fe6cf 100644
--- a/include/asm-xtensa/system.h
+++ b/include/asm-xtensa/system.h
@@ -213,7 +213,7 @@ static inline void spill_registers(void)
unsigned int a0, ps;
__asm__ __volatile__ (
- "movi a14," __stringify (PS_EXCM_MASK) " | 1\n\t"
+ "movi a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
"mov a12, a0\n\t"
"rsr a13," __stringify(SAR) "\n\t"
"xsr a14," __stringify(PS) "\n\t"
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
index c780593ff5f..057b9a3d8f8 100644
--- a/include/asm-xtensa/termbits.h
+++ b/include/asm-xtensa/termbits.h
@@ -30,6 +30,17 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
/* c_cc characters */
#define VINTR 0
diff --git a/include/asm-xtensa/timex.h b/include/asm-xtensa/timex.h
index c7b705e6665..28c7985a400 100644
--- a/include/asm-xtensa/timex.h
+++ b/include/asm-xtensa/timex.h
@@ -16,17 +16,22 @@
#include <asm/processor.h>
#include <linux/stringify.h>
-#if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
+#define _INTLEVEL(x) XCHAL_INT ## x ## _LEVEL
+#define INTLEVEL(x) _INTLEVEL(x)
+
+#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) == 1
# define LINUX_TIMER 0
-#elif XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
+# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT
+#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) == 1
# define LINUX_TIMER 1
-#elif XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
+# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT
+#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) == 1
# define LINUX_TIMER 2
+# define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT
#else
# error "Bad timer number for Linux configurations!"
#endif
-#define LINUX_TIMER_INT XCHAL_TIMER_INTERRUPT(LINUX_TIMER)
#define LINUX_TIMER_MASK (1L << LINUX_TIMER_INT)
#define CLOCK_TICK_RATE 1193180 /* (everyone is using this value) */
@@ -60,8 +65,8 @@ extern cycles_t cacheflush_time;
#define WSR_CCOUNT(r) __asm__("wsr %0,"__stringify(CCOUNT) :: "a" (r))
#define RSR_CCOUNT(r) __asm__("rsr %0,"__stringify(CCOUNT) : "=a" (r))
-#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) :: "a"(r))
-#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) : "=a"(r))
+#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r))
+#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r))
static inline unsigned long get_ccount (void)
{
diff --git a/include/asm-xtensa/tlbflush.h b/include/asm-xtensa/tlbflush.h
index 43f6ec859af..7c637b3c352 100644
--- a/include/asm-xtensa/tlbflush.h
+++ b/include/asm-xtensa/tlbflush.h
@@ -11,12 +11,20 @@
#ifndef _XTENSA_TLBFLUSH_H
#define _XTENSA_TLBFLUSH_H
-#define DEBUG_TLB
-
#ifdef __KERNEL__
-#include <asm/processor.h>
#include <linux/stringify.h>
+#include <asm/processor.h>
+
+#define DTLB_WAY_PGD 7
+
+#define ITLB_ARF_WAYS 4
+#define DTLB_ARF_WAYS 4
+
+#define ITLB_HIT_BIT 3
+#define DTLB_HIT_BIT 4
+
+#ifndef __ASSEMBLY__
/* TLB flushing:
*
@@ -46,11 +54,6 @@ static inline void flush_tlb_pgtables(struct mm_struct *mm,
/* TLB operations. */
-#define ITLB_WAYS_LOG2 XCHAL_ITLB_WAY_BITS
-#define DTLB_WAYS_LOG2 XCHAL_DTLB_WAY_BITS
-#define ITLB_PROBE_SUCCESS (1 << ITLB_WAYS_LOG2)
-#define DTLB_PROBE_SUCCESS (1 << DTLB_WAYS_LOG2)
-
static inline unsigned long itlb_probe(unsigned long addr)
{
unsigned long tmp;
@@ -131,29 +134,30 @@ static inline void write_itlb_entry (pte_t entry, int way)
static inline void invalidate_page_directory (void)
{
- invalidate_dtlb_entry (DTLB_WAY_PGTABLE);
+ invalidate_dtlb_entry (DTLB_WAY_PGD);
+ invalidate_dtlb_entry (DTLB_WAY_PGD+1);
+ invalidate_dtlb_entry (DTLB_WAY_PGD+2);
}
static inline void invalidate_itlb_mapping (unsigned address)
{
unsigned long tlb_entry;
- while ((tlb_entry = itlb_probe (address)) & ITLB_PROBE_SUCCESS)
- invalidate_itlb_entry (tlb_entry);
+ if (((tlb_entry = itlb_probe(address)) & (1 << ITLB_HIT_BIT)) != 0)
+ invalidate_itlb_entry(tlb_entry);
}
static inline void invalidate_dtlb_mapping (unsigned address)
{
unsigned long tlb_entry;
- while ((tlb_entry = dtlb_probe (address)) & DTLB_PROBE_SUCCESS)
- invalidate_dtlb_entry (tlb_entry);
+ if (((tlb_entry = dtlb_probe(address)) & (1 << DTLB_HIT_BIT)) != 0)
+ invalidate_dtlb_entry(tlb_entry);
}
#define check_pgt_cache() do { } while (0)
-#ifdef DEBUG_TLB
-
-/* DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa
+/*
+ * DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa
* ISA and exist only for test purposes..
* You may find it helpful for MMU debugging, however.
*
@@ -193,8 +197,6 @@ static inline unsigned long read_itlb_translation (int way)
return tmp;
}
-#endif /* DEBUG_TLB */
-
-
+#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
-#endif /* _XTENSA_PGALLOC_H */
+#endif /* _XTENSA_TLBFLUSH_H */
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
index 88a64e1144d..d6352da05b1 100644
--- a/include/asm-xtensa/uaccess.h
+++ b/include/asm-xtensa/uaccess.h
@@ -23,7 +23,6 @@
#ifdef __ASSEMBLY__
-#define _ASMLANGUAGE
#include <asm/current.h>
#include <asm/asm-offsets.h>
#include <asm/processor.h>
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
index 2e1a1b997e7..8a7fb6964ce 100644
--- a/include/asm-xtensa/unistd.h
+++ b/include/asm-xtensa/unistd.h
@@ -11,212 +11,593 @@
#ifndef _XTENSA_UNISTD_H
#define _XTENSA_UNISTD_H
-#define __NR_spill 0
-#define __NR_exit 1
-#define __NR_read 3
-#define __NR_write 4
-#define __NR_open 5
-#define __NR_close 6
-#define __NR_creat 8
-#define __NR_link 9
-#define __NR_unlink 10
-#define __NR_execve 11
-#define __NR_chdir 12
-#define __NR_mknod 14
-#define __NR_chmod 15
-#define __NR_lchown 16
-#define __NR_break 17
-#define __NR_lseek 19
-#define __NR_getpid 20
-#define __NR_mount 21
-#define __NR_setuid 23
-#define __NR_getuid 24
-#define __NR_ptrace 26
-#define __NR_utime 30
-#define __NR_stty 31
-#define __NR_gtty 32
-#define __NR_access 33
-#define __NR_ftime 35
-#define __NR_sync 36
-#define __NR_kill 37
-#define __NR_rename 38
-#define __NR_mkdir 39
-#define __NR_rmdir 40
-#define __NR_dup 41
-#define __NR_pipe 42
-#define __NR_times 43
-#define __NR_prof 44
-#define __NR_brk 45
-#define __NR_setgid 46
-#define __NR_getgid 47
-#define __NR_signal 48
-#define __NR_geteuid 49
-#define __NR_getegid 50
-#define __NR_acct 51
-#define __NR_lock 53
-#define __NR_ioctl 54
-#define __NR_fcntl 55
-#define __NR_setpgid 57
-#define __NR_ulimit 58
-#define __NR_umask 60
-#define __NR_chroot 61
-#define __NR_ustat 62
-#define __NR_dup2 63
-#define __NR_getppid 64
-#define __NR_setsid 66
-#define __NR_sigaction 67
-#define __NR_setreuid 70
-#define __NR_setregid 71
-#define __NR_sigsuspend 72
-#define __NR_sigpending 73
-#define __NR_sethostname 74
-#define __NR_setrlimit 75
-#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
-#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
-#define __NR_getgroups 80
-#define __NR_setgroups 81
-#define __NR_select 82
-#define __NR_symlink 83
-#define __NR_readlink 85
-#define __NR_uselib 86
-#define __NR_swapon 87
-#define __NR_reboot 88
-#define __NR_munmap 91
-#define __NR_truncate 92
-#define __NR_ftruncate 93
-#define __NR_fchmod 94
-#define __NR_fchown 95
-#define __NR_getpriority 96
-#define __NR_setpriority 97
-#define __NR_profil 98
-#define __NR_statfs 99
-#define __NR_fstatfs 100
-#define __NR_ioperm 101
-#define __NR_syslog 103
-#define __NR_setitimer 104
-#define __NR_getitimer 105
-#define __NR_stat 106
-#define __NR_lstat 107
-#define __NR_fstat 108
-#define __NR_iopl 110
-#define __NR_vhangup 111
-#define __NR_idle 112
-#define __NR_wait4 114
-#define __NR_swapoff 115
-#define __NR_sysinfo 116
-#define __NR_fsync 118
-#define __NR_sigreturn 119
-#define __NR_clone 120
-#define __NR_setdomainname 121
-#define __NR_uname 122
-#define __NR_modify_ldt 123
-#define __NR_adjtimex 124
-#define __NR_mprotect 125
-#define __NR_create_module 127
-#define __NR_init_module 128
-#define __NR_delete_module 129
-#define __NR_quotactl 131
-#define __NR_getpgid 132
-#define __NR_fchdir 133
-#define __NR_bdflush 134
-#define __NR_sysfs 135
-#define __NR_personality 136
-#define __NR_setfsuid 138
-#define __NR_setfsgid 139
-#define __NR__llseek 140
-#define __NR_getdents 141
-#define __NR__newselect 142
-#define __NR_flock 143
-#define __NR_msync 144
-#define __NR_readv 145
-#define __NR_writev 146
-#define __NR_cacheflush 147
-#define __NR_cachectl 148
-#define __NR_sysxtensa 149
-#define __NR_sysdummy 150
-#define __NR_getsid 151
-#define __NR_fdatasync 152
-#define __NR__sysctl 153
-#define __NR_mlock 154
-#define __NR_munlock 155
-#define __NR_mlockall 156
-#define __NR_munlockall 157
-#define __NR_sched_setparam 158
-#define __NR_sched_getparam 159
-#define __NR_sched_setscheduler 160
-#define __NR_sched_getscheduler 161
-#define __NR_sched_yield 162
-#define __NR_sched_get_priority_max 163
-#define __NR_sched_get_priority_min 164
-#define __NR_sched_rr_get_interval 165
-#define __NR_nanosleep 166
-#define __NR_mremap 167
-#define __NR_accept 168
-#define __NR_bind 169
-#define __NR_connect 170
-#define __NR_getpeername 171
-#define __NR_getsockname 172
-#define __NR_getsockopt 173
-#define __NR_listen 174
-#define __NR_recv 175
-#define __NR_recvfrom 176
-#define __NR_recvmsg 177
-#define __NR_send 178
-#define __NR_sendmsg 179
-#define __NR_sendto 180
-#define __NR_setsockopt 181
-#define __NR_shutdown 182
-#define __NR_socket 183
-#define __NR_socketpair 184
-#define __NR_setresuid 185
-#define __NR_getresuid 186
-#define __NR_query_module 187
-#define __NR_poll 188
-#define __NR_nfsservctl 189
-#define __NR_setresgid 190
-#define __NR_getresgid 191
-#define __NR_prctl 192
-#define __NR_rt_sigreturn 193
-#define __NR_rt_sigaction 194
-#define __NR_rt_sigprocmask 195
-#define __NR_rt_sigpending 196
-#define __NR_rt_sigtimedwait 197
-#define __NR_rt_sigqueueinfo 198
-#define __NR_rt_sigsuspend 199
-#define __NR_pread 200
-#define __NR_pwrite 201
-#define __NR_chown 202
-#define __NR_getcwd 203
-#define __NR_capget 204
-#define __NR_capset 205
-#define __NR_sigaltstack 206
-#define __NR_sendfile 207
-#define __NR_mmap2 210
-#define __NR_truncate64 211
-#define __NR_ftruncate64 212
-#define __NR_stat64 213
-#define __NR_lstat64 214
-#define __NR_fstat64 215
-#define __NR_pivot_root 216
-#define __NR_mincore 217
-#define __NR_madvise 218
-#define __NR_getdents64 219
-
-/* Keep this last; should always equal the last valid call number. */
-#define __NR_Linux_syscalls 220
-
-/* user-visible error numbers are in the range -1 - -125: see
- * <asm-xtensa/errno.h> */
-
-#define SYSXTENSA_RESERVED 0 /* don't use this */
-#define SYSXTENSA_ATOMIC_SET 1 /* set variable */
-#define SYSXTENSA_ATOMIC_EXG_ADD 2 /* exchange memory and add */
-#define SYSXTENSA_ATOMIC_ADD 3 /* add to memory */
-#define SYSXTENSA_ATOMIC_CMP_SWP 4 /* compare and swap */
-
-#define SYSXTENSA_COUNT 5 /* count of syscall0 functions*/
+#ifndef __SYSCALL
+# define __SYSCALL(nr,func,nargs)
+#endif
+
+#define __NR_spill 0
+__SYSCALL( 0, sys_ni_syscall, 0)
+#define __NR_xtensa 1
+__SYSCALL( 1, sys_ni_syscall, 0)
+#define __NR_available4 2
+__SYSCALL( 2, sys_ni_syscall, 0)
+#define __NR_available5 3
+__SYSCALL( 3, sys_ni_syscall, 0)
+#define __NR_available6 4
+__SYSCALL( 4, sys_ni_syscall, 0)
+#define __NR_available7 5
+__SYSCALL( 5, sys_ni_syscall, 0)
+#define __NR_available8 6
+__SYSCALL( 6, sys_ni_syscall, 0)
+#define __NR_available9 7
+__SYSCALL( 7, sys_ni_syscall, 0)
+
+/* File Operations */
+
+#define __NR_open 8
+__SYSCALL( 8, sys_open, 3)
+#define __NR_close 9
+__SYSCALL( 9, sys_close, 1)
+#define __NR_dup 10
+__SYSCALL( 10, sys_dup, 1)
+#define __NR_dup2 11
+__SYSCALL( 11, sys_dup2, 2)
+#define __NR_read 12
+__SYSCALL( 12, sys_read, 3)
+#define __NR_write 13
+__SYSCALL( 13, sys_write, 3)
+#define __NR_select 14
+__SYSCALL( 14, sys_select, 5)
+#define __NR_lseek 15
+__SYSCALL( 15, sys_lseek, 3)
+#define __NR_poll 16
+__SYSCALL( 16, sys_poll, 3)
+#define __NR__llseek 17
+__SYSCALL( 17, sys_llseek, 5)
+#define __NR_epoll_wait 18
+__SYSCALL( 18, sys_epoll_wait, 4)
+#define __NR_epoll_ctl 19
+__SYSCALL( 19, sys_epoll_ctl, 4)
+#define __NR_epoll_create 20
+__SYSCALL( 20, sys_epoll_create, 1)
+#define __NR_creat 21
+__SYSCALL( 21, sys_creat, 2)
+#define __NR_truncate 22
+__SYSCALL( 22, sys_truncate, 2)
+#define __NR_ftruncate 23
+__SYSCALL( 23, sys_ftruncate, 2)
+#define __NR_readv 24
+__SYSCALL( 24, sys_readv, 3)
+#define __NR_writev 25
+__SYSCALL( 25, sys_writev, 3)
+#define __NR_fsync 26
+__SYSCALL( 26, sys_fsync, 1)
+#define __NR_fdatasync 27
+__SYSCALL( 27, sys_fdatasync, 1)
+#define __NR_truncate64 28
+__SYSCALL( 28, sys_truncate64, 2)
+#define __NR_ftruncate64 29
+__SYSCALL( 29, sys_ftruncate64, 2)
+#define __NR_pread64 30
+__SYSCALL( 30, sys_pread64, 6)
+#define __NR_pwrite64 31
+__SYSCALL( 31, sys_pwrite64, 6)
+
+#define __NR_link 32
+__SYSCALL( 32, sys_link, 2)
+#define __NR_rename 33
+__SYSCALL( 33, sys_rename, 2)
+#define __NR_symlink 34
+__SYSCALL( 34, sys_symlink, 2)
+#define __NR_readlink 35
+__SYSCALL( 35, sys_readlink, 3)
+#define __NR_mknod 36
+__SYSCALL( 36, sys_mknod, 3)
+#define __NR_pipe 37
+__SYSCALL( 37, xtensa_pipe, 1)
+#define __NR_unlink 38
+__SYSCALL( 38, sys_unlink, 1)
+#define __NR_rmdir 39
+__SYSCALL( 39, sys_rmdir, 1)
+
+#define __NR_mkdir 40
+__SYSCALL( 40, sys_mkdir, 2)
+#define __NR_chdir 41
+__SYSCALL( 41, sys_chdir, 1)
+#define __NR_fchdir 42
+__SYSCALL( 42, sys_fchdir, 1)
+#define __NR_getcwd 43
+__SYSCALL( 43, sys_getcwd, 2)
+
+#define __NR_chmod 44
+__SYSCALL( 44, sys_chmod, 2)
+#define __NR_chown 45
+__SYSCALL( 45, sys_chown, 3)
+#define __NR_stat 46
+__SYSCALL( 46, sys_newstat, 2)
+#define __NR_stat64 47
+__SYSCALL( 47, sys_stat64, 2)
+
+#define __NR_lchown 48
+__SYSCALL( 48, sys_lchown, 3)
+#define __NR_lstat 49
+__SYSCALL( 49, sys_newlstat, 2)
+#define __NR_lstat64 50
+__SYSCALL( 50, sys_lstat64, 2)
+#define __NR_available51 51
+__SYSCALL( 51, sys_ni_syscall, 0)
+
+#define __NR_fchmod 52
+__SYSCALL( 52, sys_fchmod, 2)
+#define __NR_fchown 53
+__SYSCALL( 53, sys_fchown, 3)
+#define __NR_fstat 54
+__SYSCALL( 54, sys_newfstat, 2)
+#define __NR_fstat64 55
+__SYSCALL( 55, sys_fstat64, 2)
+
+#define __NR_flock 56
+__SYSCALL( 56, sys_flock, 2)
+#define __NR_access 57
+__SYSCALL( 57, sys_access, 2)
+#define __NR_umask 58
+__SYSCALL( 58, sys_umask, 1)
+#define __NR_getdents 59
+__SYSCALL( 59, sys_getdents, 3)
+#define __NR_getdents64 60
+__SYSCALL( 60, sys_getdents64, 3)
+#define __NR_fcntl64 61
+__SYSCALL( 61, sys_fcntl64, 3)
+#define __NR_available62 62
+__SYSCALL( 62, sys_ni_syscall, 0)
+#define __NR_fadvise64_64 63
+__SYSCALL( 63, sys_fadvise64_64, 6)
+#define __NR_utime 64 /* glibc 2.3.3 ?? */
+__SYSCALL( 64, sys_utime, 2)
+#define __NR_utimes 65
+__SYSCALL( 65, sys_utimes, 2)
+#define __NR_ioctl 66
+__SYSCALL( 66, sys_ioctl, 3)
+#define __NR_fcntl 67
+__SYSCALL( 67, sys_fcntl, 3)
+
+#define __NR_setxattr 68
+__SYSCALL( 68, sys_setxattr, 5)
+#define __NR_getxattr 69
+__SYSCALL( 69, sys_getxattr, 4)
+#define __NR_listxattr 70
+__SYSCALL( 70, sys_listxattr, 3)
+#define __NR_removexattr 71
+__SYSCALL( 71, sys_removexattr, 2)
+#define __NR_lsetxattr 72
+__SYSCALL( 72, sys_lsetxattr, 5)
+#define __NR_lgetxattr 73
+__SYSCALL( 73, sys_lgetxattr, 4)
+#define __NR_llistxattr 74
+__SYSCALL( 74, sys_llistxattr, 3)
+#define __NR_lremovexattr 75
+__SYSCALL( 75, sys_lremovexattr, 2)
+#define __NR_fsetxattr 76
+__SYSCALL( 76, sys_fsetxattr, 5)
+#define __NR_fgetxattr 77
+__SYSCALL( 77, sys_fgetxattr, 4)
+#define __NR_flistxattr 78
+__SYSCALL( 78, sys_flistxattr, 3)
+#define __NR_fremovexattr 79
+__SYSCALL( 79, sys_fremovexattr, 2)
+
+/* File Map / Shared Memory Operations */
+
+#define __NR_mmap2 80
+__SYSCALL( 80, xtensa_mmap2, 6)
+#define __NR_munmap 81
+__SYSCALL( 81, sys_munmap, 2)
+#define __NR_mprotect 82
+__SYSCALL( 82, sys_mprotect, 3)
+#define __NR_brk 83
+__SYSCALL( 83, sys_brk, 1)
+#define __NR_mlock 84
+__SYSCALL( 84, sys_mlock, 2)
+#define __NR_munlock 85
+__SYSCALL( 85, sys_munlock, 2)
+#define __NR_mlockall 86
+__SYSCALL( 86, sys_mlockall, 1)
+#define __NR_munlockall 87
+__SYSCALL( 87, sys_munlockall, 0)
+#define __NR_mremap 88
+__SYSCALL( 88, sys_mremap, 4)
+#define __NR_msync 89
+__SYSCALL( 89, sys_msync, 3)
+#define __NR_mincore 90
+__SYSCALL( 90, sys_mincore, 3)
+#define __NR_madvise 91
+__SYSCALL( 91, sys_madvise, 3)
+#define __NR_shmget 92
+__SYSCALL( 92, sys_shmget, 4)
+#define __NR_shmat 93
+__SYSCALL( 93, xtensa_shmat, 4)
+#define __NR_shmctl 94
+__SYSCALL( 94, sys_shmctl, 4)
+#define __NR_shmdt 95
+__SYSCALL( 95, sys_shmdt, 4)
+
+/* Socket Operations */
+
+#define __NR_socket 96
+__SYSCALL( 96, sys_socket, 3)
+#define __NR_setsockopt 97
+__SYSCALL( 97, sys_setsockopt, 5)
+#define __NR_getsockopt 98
+__SYSCALL( 98, sys_getsockopt, 5)
+#define __NR_shutdown 99
+__SYSCALL( 99, sys_shutdown, 2)
+
+#define __NR_bind 100
+__SYSCALL(100, sys_bind, 3)
+#define __NR_connect 101
+__SYSCALL(101, sys_connect, 3)
+#define __NR_listen 102
+__SYSCALL(102, sys_listen, 2)
+#define __NR_accept 103
+__SYSCALL(103, sys_accept, 3)
+
+#define __NR_getsockname 104
+__SYSCALL(104, sys_getsockname, 3)
+#define __NR_getpeername 105
+__SYSCALL(105, sys_getpeername, 3)
+#define __NR_sendmsg 106
+__SYSCALL(106, sys_sendmsg, 3)
+#define __NR_recvmsg 107
+__SYSCALL(107, sys_recvmsg, 3)
+#define __NR_send 108
+__SYSCALL(108, sys_send, 4)
+#define __NR_recv 109
+__SYSCALL(109, sys_recv, 4)
+#define __NR_sendto 110
+__SYSCALL(110, sys_sendto, 6)
+#define __NR_recvfrom 111
+__SYSCALL(111, sys_recvfrom, 6)
+
+#define __NR_socketpair 112
+__SYSCALL(112, sys_socketpair, 4)
+#define __NR_sendfile 113
+__SYSCALL(113, sys_sendfile, 4)
+#define __NR_sendfile64 114
+__SYSCALL(114, sys_sendfile64, 4)
+#define __NR_available115 115
+__SYSCALL(115, sys_ni_syscall, 0)
+
+/* Process Operations */
+
+#define __NR_clone 116
+__SYSCALL(116, xtensa_clone, 5)
+#define __NR_execve 117
+__SYSCALL(117, xtensa_execve, 3)
+#define __NR_exit 118
+__SYSCALL(118, sys_exit, 1)
+#define __NR_exit_group 119
+__SYSCALL(119, sys_exit_group, 1)
+#define __NR_getpid 120
+__SYSCALL(120, sys_getpid, 0)
+#define __NR_wait4 121
+__SYSCALL(121, sys_wait4, 4)
+#define __NR_waitid 122
+__SYSCALL(122, sys_waitid, 5)
+#define __NR_kill 123
+__SYSCALL(123, sys_kill, 2)
+#define __NR_tkill 124
+__SYSCALL(124, sys_tkill, 2)
+#define __NR_tgkill 125
+__SYSCALL(125, sys_tgkill, 3)
+#define __NR_set_tid_address 126
+__SYSCALL(126, sys_set_tid_address, 1)
+#define __NR_gettid 127
+__SYSCALL(127, sys_gettid, 0)
+#define __NR_setsid 128
+__SYSCALL(128, sys_setsid, 0)
+#define __NR_getsid 129
+__SYSCALL(129, sys_getsid, 1)
+#define __NR_prctl 130
+__SYSCALL(130, sys_prctl, 5)
+#define __NR_personality 131
+__SYSCALL(131, sys_personality, 1)
+#define __NR_getpriority 132
+__SYSCALL(132, sys_getpriority, 2)
+#define __NR_setpriority 133
+__SYSCALL(133, sys_setpriority, 3)
+#define __NR_setitimer 134
+__SYSCALL(134, sys_setitimer, 3)
+#define __NR_getitimer 135
+__SYSCALL(135, sys_getitimer, 2)
+#define __NR_setuid 136
+__SYSCALL(136, sys_setuid, 1)
+#define __NR_getuid 137
+__SYSCALL(137, sys_getuid, 0)
+#define __NR_setgid 138
+__SYSCALL(138, sys_setgid, 1)
+#define __NR_getgid 139
+__SYSCALL(139, sys_getgid, 0)
+#define __NR_geteuid 140
+__SYSCALL(140, sys_geteuid, 0)
+#define __NR_getegid 141
+__SYSCALL(141, sys_getegid, 0)
+#define __NR_setreuid 142
+__SYSCALL(142, sys_setreuid, 2)
+#define __NR_setregid 143
+__SYSCALL(143, sys_setregid, 2)
+#define __NR_setresuid 144
+__SYSCALL(144, sys_setresuid, 3)
+#define __NR_getresuid 145
+__SYSCALL(145, sys_getresuid, 3)
+#define __NR_setresgid 146
+__SYSCALL(146, sys_setresgid, 3)
+#define __NR_getresgid 147
+__SYSCALL(147, sys_getresgid, 3)
+#define __NR_setpgid 148
+__SYSCALL(148, sys_setpgid, 2)
+#define __NR_getpgid 149
+__SYSCALL(149, sys_getpgid, 1)
+#define __NR_getppid 150
+__SYSCALL(150, sys_getppid, 0)
+#define __NR_available151 151
+__SYSCALL(151, sys_ni_syscall, 0)
+
+#define __NR_reserved152 152 /* set_thread_area */
+__SYSCALL(152, sys_ni_syscall, 0)
+#define __NR_reserved153 153 /* get_thread_area */
+__SYSCALL(153, sys_ni_syscall, 0)
+#define __NR_times 154
+__SYSCALL(154, sys_times, 1)
+#define __NR_acct 155
+__SYSCALL(155, sys_acct, 1)
+#define __NR_sched_setaffinity 156
+__SYSCALL(156, sys_sched_setaffinity, 3)
+#define __NR_sched_getaffinity 157
+__SYSCALL(157, sys_sched_getaffinity, 3)
+#define __NR_capget 158
+__SYSCALL(158, sys_capget, 2)
+#define __NR_capset 159
+__SYSCALL(159, sys_capset, 2)
+#define __NR_ptrace 160
+__SYSCALL(160, sys_ptrace, 4)
+#define __NR_semtimedop 161
+__SYSCALL(161, sys_semtimedop, 5)
+#define __NR_semget 162
+__SYSCALL(162, sys_semget, 4)
+#define __NR_semop 163
+__SYSCALL(163, sys_semop, 4)
+#define __NR_semctl 164
+__SYSCALL(164, sys_semctl, 4)
+#define __NR_available165 165
+__SYSCALL(165, sys_ni_syscall, 0)
+#define __NR_msgget 166
+__SYSCALL(166, sys_msgget, 4)
+#define __NR_msgsnd 167
+__SYSCALL(167, sys_msgsnd, 4)
+#define __NR_msgrcv 168
+__SYSCALL(168, sys_msgrcv, 4)
+#define __NR_msgctl 169
+__SYSCALL(169, sys_msgctl, 4)
+#define __NR_available170 170
+__SYSCALL(170, sys_ni_syscall, 0)
+#define __NR_available171 171
+__SYSCALL(171, sys_ni_syscall, 0)
+
+/* File System */
+
+#define __NR_mount 172
+__SYSCALL(172, sys_mount, 5)
+#define __NR_swapon 173
+__SYSCALL(173, sys_swapon, 2)
+#define __NR_chroot 174
+__SYSCALL(174, sys_chroot, 1)
+#define __NR_pivot_root 175
+__SYSCALL(175, sys_pivot_root, 2)
+#define __NR_umount 176
+__SYSCALL(176, sys_umount, 2)
+#define __NR_swapoff 177
+__SYSCALL(177, sys_swapoff, 1)
+#define __NR_sync 178
+__SYSCALL(178, sys_sync, 0)
+#define __NR_available179 179
+__SYSCALL(179, sys_ni_syscall, 0)
+#define __NR_setfsuid 180
+__SYSCALL(180, sys_setfsuid, 1)
+#define __NR_setfsgid 181
+__SYSCALL(181, sys_setfsgid, 1)
+#define __NR_sysfs 182
+__SYSCALL(182, sys_sysfs, 3)
+#define __NR_ustat 183
+__SYSCALL(183, sys_ustat, 2)
+#define __NR_statfs 184
+__SYSCALL(184, sys_statfs, 2)
+#define __NR_fstatfs 185
+__SYSCALL(185, sys_fstatfs, 2)
+#define __NR_statfs64 186
+__SYSCALL(186, sys_statfs64, 3)
+#define __NR_fstatfs64 187
+__SYSCALL(187, sys_fstatfs64, 3)
+
+/* System */
+
+#define __NR_setrlimit 188
+__SYSCALL(188, sys_setrlimit, 2)
+#define __NR_getrlimit 189
+__SYSCALL(189, sys_getrlimit, 2)
+#define __NR_getrusage 190
+__SYSCALL(190, sys_getrusage, 2)
+#define __NR_futex 191
+__SYSCALL(191, sys_futex, 5)
+#define __NR_gettimeofday 192
+__SYSCALL(192, sys_gettimeofday, 2)
+#define __NR_settimeofday 193
+__SYSCALL(193, sys_settimeofday, 2)
+#define __NR_adjtimex 194
+__SYSCALL(194, sys_adjtimex, 1)
+#define __NR_nanosleep 195
+__SYSCALL(195, sys_nanosleep, 2)
+#define __NR_getgroups 196
+__SYSCALL(196, sys_getgroups, 2)
+#define __NR_setgroups 197
+__SYSCALL(197, sys_setgroups, 2)
+#define __NR_sethostname 198
+__SYSCALL(198, sys_sethostname, 2)
+#define __NR_setdomainname 199
+__SYSCALL(199, sys_setdomainname, 2)
+#define __NR_syslog 200
+__SYSCALL(200, sys_syslog, 3)
+#define __NR_vhangup 201
+__SYSCALL(201, sys_vhangup, 0)
+#define __NR_uselib 202
+__SYSCALL(202, sys_uselib, 1)
+#define __NR_reboot 203
+__SYSCALL(203, sys_reboot, 3)
+#define __NR_quotactl 204
+__SYSCALL(204, sys_quotactl, 4)
+#define __NR_nfsservctl 205
+__SYSCALL(205, sys_nfsservctl, 3)
+#define __NR__sysctl 206
+__SYSCALL(206, sys_sysctl, 1)
+#define __NR_bdflush 207
+__SYSCALL(207, sys_bdflush, 2)
+#define __NR_uname 208
+__SYSCALL(208, sys_newuname, 1)
+#define __NR_sysinfo 209
+__SYSCALL(209, sys_sysinfo, 1)
+#define __NR_init_module 210
+__SYSCALL(210, sys_init_module, 2)
+#define __NR_delete_module 211
+__SYSCALL(211, sys_delete_module, 1)
+
+#define __NR_sched_setparam 212
+__SYSCALL(212, sys_sched_setparam, 2)
+#define __NR_sched_getparam 213
+__SYSCALL(213, sys_sched_getparam, 2)
+#define __NR_sched_setscheduler 214
+__SYSCALL(214, sys_sched_setscheduler, 3)
+#define __NR_sched_getscheduler 215
+__SYSCALL(215, sys_sched_getscheduler, 1)
+#define __NR_sched_get_priority_max 216
+__SYSCALL(216, sys_sched_get_priority_max, 1)
+#define __NR_sched_get_priority_min 217
+__SYSCALL(217, sys_sched_get_priority_min, 1)
+#define __NR_sched_rr_get_interval 218
+__SYSCALL(218, sys_sched_rr_get_interval, 2)
+#define __NR_sched_yield 219
+__SYSCALL(219, sys_sched_yield, 0)
+#define __NR_sigreturn 222
+__SYSCALL(222, xtensa_sigreturn, 0)
+
+/* Signal Handling */
+
+#define __NR_restart_syscall 223
+__SYSCALL(223, sys_restart_syscall, 0)
+#define __NR_sigaltstack 224
+__SYSCALL(224, xtensa_sigaltstack, 2)
+#define __NR_rt_sigreturn 225
+__SYSCALL(225, xtensa_rt_sigreturn, 1)
+#define __NR_rt_sigaction 226
+__SYSCALL(226, sys_rt_sigaction, 4)
+#define __NR_rt_sigprocmask 227
+__SYSCALL(227, sys_rt_sigprocmask, 4)
+#define __NR_rt_sigpending 228
+__SYSCALL(228, sys_rt_sigpending, 2)
+#define __NR_rt_sigtimedwait 229
+__SYSCALL(229, sys_rt_sigtimedwait, 4)
+#define __NR_rt_sigqueueinfo 230
+__SYSCALL(230, sys_rt_sigqueueinfo, 3)
+#define __NR_rt_sigsuspend 231
+__SYSCALL(231, xtensa_rt_sigsuspend, 2)
+
+/* Message */
+
+#define __NR_mq_open 232
+__SYSCALL(232, sys_mq_open, 4)
+#define __NR_mq_unlink 233
+__SYSCALL(233, sys_mq_unlink, 1)
+#define __NR_mq_timedsend 234
+__SYSCALL(234, sys_mq_timedsend, 5)
+#define __NR_mq_timedreceive 235
+__SYSCALL(235, sys_mq_timedreceive, 5)
+#define __NR_mq_notify 236
+__SYSCALL(236, sys_mq_notify, 2)
+#define __NR_mq_getsetattr 237
+__SYSCALL(237, sys_mq_getsetattr, 3)
+#define __NR_available238 238
+__SYSCALL(238, sys_ni_syscall, 0)
+
+/* IO */
+
+#define __NR_io_setup 239
+__SYSCALL(239, sys_io_setup, 2)
+#define __NR_io_destroy 240
+__SYSCALL(240, sys_io_destroy, 1)
+#define __NR_io_submit 241
+__SYSCALL(241, sys_io_submit, 3)
+#define __NR_io_getevents 242
+__SYSCALL(242, sys_io_getevents, 5)
+#define __NR_io_cancel 243
+__SYSCALL(243, sys_io_cancel, 3)
+#define __NR_clock_settime 244
+__SYSCALL(244, sys_clock_settime, 2)
+#define __NR_clock_gettime 245
+__SYSCALL(245, sys_clock_gettime, 2)
+#define __NR_clock_getres 246
+__SYSCALL(246, sys_clock_getres, 2)
+#define __NR_clock_nanosleep 247
+__SYSCALL(247, sys_clock_nanosleep, 4)
+
+/* Timer */
+
+#define __NR_timer_create 248
+__SYSCALL(248, sys_timer_create, 3)
+#define __NR_timer_delete 249
+__SYSCALL(249, sys_timer_delete, 1)
+#define __NR_timer_settime 250
+__SYSCALL(250, sys_timer_settime, 4)
+#define __NR_timer_gettime 251
+__SYSCALL(251, sys_timer_gettime, 2)
+#define __NR_timer_getoverrun 252
+__SYSCALL(252, sys_timer_getoverrun, 1)
+
+/* System */
+
+#define __NR_reserved244 253
+__SYSCALL(253, sys_ni_syscall, 0)
+#define __NR_lookup_dcookie 254
+__SYSCALL(254, sys_lookup_dcookie, 4)
+#define __NR_available255 255
+__SYSCALL(255, sys_ni_syscall, 0)
+#define __NR_add_key 256
+__SYSCALL(256, sys_add_key, 5)
+#define __NR_request_key 257
+__SYSCALL(257, sys_request_key, 5)
+#define __NR_keyctl 258
+__SYSCALL(258, sys_keyctl, 5)
+#define __NR_available259 259
+__SYSCALL(259, sys_ni_syscall, 0)
+
+#define __NR_syscall_count 261
+
+/*
+ * sysxtensa syscall handler
+ *
+ * int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ * a2 a6 a3 a4 a5
+ */
+
+#define SYS_XTENSA_RESERVED 0 /* don't use this */
+#define SYS_XTENSA_ATOMIC_SET 1 /* set variable */
+#define SYS_XTENSA_ATOMIC_EXG_ADD 2 /* exchange memory and add */
+#define SYS_XTENSA_ATOMIC_ADD 3 /* add to memory */
+#define SYS_XTENSA_ATOMIC_CMP_SWP 4 /* compare and swap */
+
+#define SYS_XTENSA_COUNT 5 /* count */
+
+#ifdef __KERNEL__
/*
* "Conditional" syscalls
@@ -230,6 +611,9 @@
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_RT_SIGACTION
-#endif /* __KERNEL__ */
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+
+#endif /* __KERNEL__ */
#endif /* _XTENSA_UNISTD_H */
+
diff --git a/include/asm-xtensa/variant-fsf/core.h b/include/asm-xtensa/variant-fsf/core.h
new file mode 100644
index 00000000000..2f337605c74
--- /dev/null
+++ b/include/asm-xtensa/variant-fsf/core.h
@@ -0,0 +1,359 @@
+/*
+ * Xtensa processor core configuration information.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999-2006 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CORE_H
+#define _XTENSA_CORE_H
+
+
+/****************************************************************************
+ Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ * configured, and a value of 0 otherwise. These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+ ISA
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE 1 /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */
+#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG 1 /* debug option */
+#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */
+#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX 0 /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT 0 /* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS 0 /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16 0 /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32 0 /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_L32R 1 /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS 1 /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */
+#define XCHAL_HAVE_ABS 1 /* ABS instruction */
+/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */
+/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC 0 /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION 0 /* speculation */
+#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS 1 /* */
+#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID 1 /* processor ID register */
+#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS 0 /* boolean registers */
+#define XCHAL_HAVE_CP 0 /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG 0 /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16 0 /* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */
+#define XCHAL_HAVE_FP 0 /* floating point pkg */
+#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */
+#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */
+#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */
+
+
+/*----------------------------------------------------------------------
+ MISC
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH 4 /* data width in bytes */
+/* In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/
+
+#define XCHAL_CORE_ID "fsf" /* alphanum core name
+ (CoreID) set in the Xtensa
+ Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID 0x00006700 /* 22-bit sw build ID */
+
+/*
+ * These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0 0xC103C3FF /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1 0x0C006700 /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME "LX2.0.0" /* full version name */
+#define XCHAL_HW_VERSION_MAJOR 2200 /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR 0 /* minor ver# of targeted hw */
+#define XTHAL_HW_REL_LX2 1
+#define XTHAL_HW_REL_LX2_0 1
+#define XTHAL_HW_REL_LX2_0_0 1
+#define XCHAL_HW_CONFIGID_RELIABLE 1
+/* If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR 2200 /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR 0 /* minor v of earliest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR 2200 /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR 0 /* minor v of latest tgt hw */
+
+
+/*----------------------------------------------------------------------
+ CACHE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE 16 /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE 16 /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH 4 /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH 4 /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE 8192 /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE 8192 /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */
+
+
+
+
+/****************************************************************************
+ Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+ CACHE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */
+
+/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */
+
+/* Number of cache sets in log2(lines per way): */
+#define XCHAL_ICACHE_SETWIDTH 8
+#define XCHAL_DCACHE_SETWIDTH 8
+
+/* Cache set associativity (number of ways): */
+#define XCHAL_ICACHE_WAYS 2
+#define XCHAL_DCACHE_WAYS 2
+
+/* Cache features: */
+#define XCHAL_ICACHE_LINE_LOCKABLE 0
+#define XCHAL_DCACHE_LINE_LOCKABLE 0
+#define XCHAL_ICACHE_ECC_PARITY 0
+#define XCHAL_DCACHE_ECC_PARITY 0
+
+/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */
+#define XCHAL_CA_BITS 4
+
+
+/*----------------------------------------------------------------------
+ INTERNAL I/D RAM/ROMs and XLMI
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */
+#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */
+
+
+/*----------------------------------------------------------------------
+ INTERRUPTS and TIMERS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI 0 /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS 17 /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS 10 /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels
+ (not including level zero) */
+#define XCHAL_EXCM_LEVEL 1 /* level masked by PS.EXCM */
+ /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/* Masks of interrupts at each interrupt level: */
+#define XCHAL_INTLEVEL1_MASK 0x000064F9
+#define XCHAL_INTLEVEL2_MASK 0x00008902
+#define XCHAL_INTLEVEL3_MASK 0x00011204
+#define XCHAL_INTLEVEL4_MASK 0x00000000
+#define XCHAL_INTLEVEL5_MASK 0x00000000
+#define XCHAL_INTLEVEL6_MASK 0x00000000
+#define XCHAL_INTLEVEL7_MASK 0x00000000
+
+/* Masks of interrupts at each range 1..n of interrupt levels: */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000064F9
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x0000EDFB
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x0001FFFF
+
+/* Level of each interrupt: */
+#define XCHAL_INT0_LEVEL 1
+#define XCHAL_INT1_LEVEL 2
+#define XCHAL_INT2_LEVEL 3
+#define XCHAL_INT3_LEVEL 1
+#define XCHAL_INT4_LEVEL 1
+#define XCHAL_INT5_LEVEL 1
+#define XCHAL_INT6_LEVEL 1
+#define XCHAL_INT7_LEVEL 1
+#define XCHAL_INT8_LEVEL 2
+#define XCHAL_INT9_LEVEL 3
+#define XCHAL_INT10_LEVEL 1
+#define XCHAL_INT11_LEVEL 2
+#define XCHAL_INT12_LEVEL 3
+#define XCHAL_INT13_LEVEL 1
+#define XCHAL_INT14_LEVEL 1
+#define XCHAL_INT15_LEVEL 2
+#define XCHAL_INT16_LEVEL 3
+#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT 0 /* OCD external db interrupt */
+
+/* Type of each interrupt: */
+#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT12_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT13_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT16_TYPE XTHAL_INTTYPE_SOFTWARE
+
+/* Masks of interrupts for each type of interrupt: */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFE0000
+#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0001E000
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000380
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000007F
+#define XCHAL_INTTYPE_MASK_TIMER 0x00001C00
+#define XCHAL_INTTYPE_MASK_NMI 0x00000000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000
+
+/* Interrupt numbers assigned to specific interrupt sources: */
+#define XCHAL_TIMER0_INTERRUPT 10 /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT 11 /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT 12 /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED
+
+/* Interrupt numbers for levels at which only one interrupt is configured: */
+/* (There are many interrupts each at level(s) 1, 2, 3.) */
+
+
+/*
+ * External interrupt vectors/levels.
+ * These macros describe how Xtensa processor interrupt numbers
+ * (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ * map to external BInterrupt<n> pins, for those interrupts
+ * configured as external (level-triggered, edge-triggered, or NMI).
+ * See the Xtensa processor databook for more details.
+ */
+
+/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */
+#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM 1 /* (intlevel 2) */
+#define XCHAL_EXTINT2_NUM 2 /* (intlevel 3) */
+#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */
+#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */
+#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */
+#define XCHAL_EXTINT9_NUM 9 /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+ EXCEPTIONS and VECTORS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture
+ number: 1 == XEA1 (old)
+ 2 == XEA2 (new)
+ 0 == XEAX (extern) */
+#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */
+#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */
+
+#define XCHAL_RESET_VECTOR_VADDR 0xFE000020
+#define XCHAL_RESET_VECTOR_PADDR 0xFE000020
+#define XCHAL_USER_VECTOR_VADDR 0xD0000220
+#define XCHAL_USER_VECTOR_PADDR 0x00000220
+#define XCHAL_KERNEL_VECTOR_VADDR 0xD0000200
+#define XCHAL_KERNEL_VECTOR_PADDR 0x00000200
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xD0000290
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x00000290
+#define XCHAL_WINDOW_VECTORS_VADDR 0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR 0x00000000
+#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xD0000240
+#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000240
+#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xD0000250
+#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x00000250
+#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xFE000520
+#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xFE000520
+#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+ DEBUG
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+ MMU
+ ----------------------------------------------------------------------*/
+
+/* See <xtensa/config/core-matmap.h> header file for more details. */
+
+#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */
+#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU 1 /* full MMU (with page table
+ [autorefill] and protection)
+ usable for an MMU-based OS */
+/* If none of the above last 4 are set, it's a custom TLB configuration. */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS 4 /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS 2 /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
+
diff --git a/include/asm-xtensa/variant-fsf/tie.h b/include/asm-xtensa/variant-fsf/tie.h
new file mode 100644
index 00000000000..a73c7166491
--- /dev/null
+++ b/include/asm-xtensa/variant-fsf/tie.h
@@ -0,0 +1,22 @@
+/*
+ * Xtensa processor core configuration information.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999-2006 Tensilica Inc.
+ */
+
+#ifndef XTENSA_TIE_H
+#define XTENSA_TIE_H
+
+/*----------------------------------------------------------------------
+ COPROCESSORS and EXTRA STATE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_CP_NUM 0 /* number of coprocessors */
+#define XCHAL_CP_MASK 0x00
+
+#endif /*XTENSA_CONFIG_TIE_H*/
+
diff --git a/include/asm-xtensa/xtensa/cacheasm.h b/include/asm-xtensa/xtensa/cacheasm.h
deleted file mode 100644
index 0cdbb0bf180..00000000000
--- a/include/asm-xtensa/xtensa/cacheasm.h
+++ /dev/null
@@ -1,708 +0,0 @@
-#ifndef XTENSA_CACHEASM_H
-#define XTENSA_CACHEASM_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/cacheasm.h -- assembler-specific cache
- * related definitions that depend on CORE configuration.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/coreasm.h>
-
-
-/*
- * This header file defines assembler macros of the form:
- * <x>cache_<func>
- * where <x> is 'i' or 'd' for instruction and data caches,
- * and <func> indicates the function of the macro.
- *
- * The following functions <func> are defined,
- * and apply only to the specified cache (I or D):
- *
- * reset
- * Resets the cache.
- *
- * sync
- * Makes sure any previous cache instructions have been completed;
- * ie. makes sure any previous cache control operations
- * have had full effect and been synchronized to memory.
- * Eg. any invalidate completed [so as not to generate a hit],
- * any writebacks or other pipelined writes written to memory, etc.
- *
- * invalidate_line (single cache line)
- * invalidate_region (specified memory range)
- * invalidate_all (entire cache)
- * Invalidates all cache entries that cache
- * data from the specified memory range.
- * NOTE: locked entries are not invalidated.
- *
- * writeback_line (single cache line)
- * writeback_region (specified memory range)
- * writeback_all (entire cache)
- * Writes back to memory all dirty cache entries
- * that cache data from the specified memory range,
- * and marks these entries as clean.
- * NOTE: on some future implementations, this might
- * also invalidate.
- * NOTE: locked entries are written back, but never invalidated.
- * NOTE: instruction caches never implement writeback.
- *
- * writeback_inv_line (single cache line)
- * writeback_inv_region (specified memory range)
- * writeback_inv_all (entire cache)
- * Writes back to memory all dirty cache entries
- * that cache data from the specified memory range,
- * and invalidates these entries (including all clean
- * cache entries that cache data from that range).
- * NOTE: locked entries are written back but not invalidated.
- * NOTE: instruction caches never implement writeback.
- *
- * lock_line (single cache line)
- * lock_region (specified memory range)
- * Prefetch and lock the specified memory range into cache.
- * NOTE: if any part of the specified memory range cannot
- * be locked, a ??? exception occurs. These macros don't
- * do anything special (yet anyway) to handle this situation.
- *
- * unlock_line (single cache line)
- * unlock_region (specified memory range)
- * unlock_all (entire cache)
- * Unlock cache entries that cache the specified memory range.
- * Entries not already locked are unaffected.
- */
-
-
-
-/*************************** GENERIC -- ALL CACHES ***************************/
-
-
-/*
- * The following macros assume the following cache size/parameter limits
- * in the current Xtensa core implementation:
- * cache size: 1024 bytes minimum
- * line size: 16 - 64 bytes
- * way count: 1 - 4
- *
- * Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4
- * Hence the assumption that each loop can execute four cache instructions.
- *
- * Correspondingly, the offset range of instructions is assumed able to cover
- * four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for
- * both hit and indexed cache instructions. Ie. these offsets are all
- * valid: 0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64).
- * This is true of all original cache instructions
- * (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets
- * of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2).
- * This is also true of subsequent cache instructions
- * (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets
- * of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4).
- *
- * (Maximum cache size, currently 32k, doesn't affect the following macros.
- * Cache ways > MMU min page size cause aliasing but that's another matter.)
- */
-
-
-
-/*
- * Macro to apply an 'indexed' cache instruction to the entire cache.
- *
- * Parameters:
- * cainst instruction/ that takes an address register parameter
- * and an offset parameter (in range 0 .. 3*linesize).
- * size size of cache in bytes
- * linesize size of cache line in bytes
- * assoc_or1 number of associativities (ways/sets) in cache
- * if all sets affected by cainst,
- * or 1 if only one set (or not all sets) of the cache
- * is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]).
- * aa, ab unique address registers (temporaries)
- */
-
- .macro cache_index_all cainst, size, linesize, assoc_or1, aa, ab
-
- // Sanity-check on cache parameters:
- .ifne (\size % (\linesize * \assoc_or1 * 4))
- .err // cache configuration outside expected/supported range!
- .endif
-
- // \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst.
- movi \aa, (\size / (\linesize * \assoc_or1 * 4))
- // Possible improvement: need only loop if \aa > 1 ;
- // however that particular condition is highly unlikely.
- movi \ab, 0 // to iterate over cache
- floop \aa, cachex\@
- \cainst \ab, 0*\linesize
- \cainst \ab, 1*\linesize
- \cainst \ab, 2*\linesize
- \cainst \ab, 3*\linesize
- addi \ab, \ab, 4*\linesize // move to next line
- floopend \aa, cachex\@
-
- .endm
-
-
-/*
- * Macro to apply a 'hit' cache instruction to a memory region,
- * ie. to any cache entries that cache a specified portion (region) of memory.
- * Takes care of the unaligned cases, ie. may apply to one
- * more cache line than $asize / lineSize if $aaddr is not aligned.
- *
- *
- * Parameters are:
- * cainst instruction/macro that takes an address register parameter
- * and an offset parameter (currently always zero)
- * and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.)
- * linesize_log2 log2(size of cache line in bytes)
- * addr register containing start address of region (clobbered)
- * asize register containing size of the region in bytes (clobbered)
- * askew unique register used as temporary
- *
- * !?!?! 2DO: optimization: iterate max(cache_size and \asize) / linesize
- */
-
- .macro cache_hit_region cainst, linesize_log2, addr, asize, askew
-
- // Make \asize the number of iterations:
- extui \askew, \addr, 0, \linesize_log2 // get unalignment amount of \addr
- add \asize, \asize, \askew // ... and add it to \asize
- addi \asize, \asize, (1 << \linesize_log2) - 1 // round up!
- srli \asize, \asize, \linesize_log2
-
- // Iterate over region:
- floopnez \asize, cacheh\@
- \cainst \addr, 0
- addi \addr, \addr, (1 << \linesize_log2) // move to next line
- floopend \asize, cacheh\@
-
- .endm
-
-
-
-
-
-/*************************** INSTRUCTION CACHE ***************************/
-
-
-/*
- * Reset/initialize the instruction cache by simply invalidating it:
- * (need to unlock first also, if cache locking implemented):
- *
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro icache_reset aa, ab
- icache_unlock_all \aa, \ab
- icache_invalidate_all \aa, \ab
- .endm
-
-
-/*
- * Synchronize after an instruction cache operation,
- * to be sure everything is in sync with memory as to be
- * expected following any previous instruction cache control operations.
- *
- * Parameters are:
- * ar an address register (temporary) (currently unused, but may be used in future)
- */
- .macro icache_sync ar
-#if XCHAL_ICACHE_SIZE > 0
- isync
-#endif
- .endm
-
-
-
-/*
- * Invalidate a single line of the instruction cache.
- * Parameters are:
- * ar address register that contains (virtual) address to invalidate
- * (may get clobbered in a future implementation, but not currently)
- * offset (optional) offset to add to \ar to compute effective address to invalidate
- * (note: some number of lsbits are ignored)
- */
- .macro icache_invalidate_line ar, offset
-#if XCHAL_ICACHE_SIZE > 0
- ihi \ar, \offset // invalidate icache line
- /*
- * NOTE: in some version of the silicon [!!!SHOULD HAVE BEEN DOCUMENTED!!!]
- * 'ihi' doesn't work, so it had been replaced with 'iii'
- * (which would just invalidate more than it should,
- * which should be okay other than the performance hit
- * because cache locking did not exist in that version,
- * unless user somehow relies on something being cached).
- * [WHAT VERSION IS IT!!?!?
- * IS THERE ANY WAY TO TEST FOR THAT HERE, TO OUTPUT 'III' ONLY IF NEEDED!?!?].
- *
- * iii \ar, \offset
- */
- icache_sync \ar
-#endif
- .endm
-
-
-
-
-/*
- * Invalidate instruction cache entries that cache a specified portion of memory.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro icache_invalidate_region astart, asize, ac
-#if XCHAL_ICACHE_SIZE > 0
- // Instruction cache region invalidation:
- cache_hit_region ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
- icache_sync \ac
- // End of instruction cache region invalidation
-#endif
- .endm
-
-
-
-/*
- * Invalidate entire instruction cache.
- *
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro icache_invalidate_all aa, ab
-#if XCHAL_ICACHE_SIZE > 0
- // Instruction cache invalidation:
- cache_index_all iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab
- icache_sync \aa
- // End of instruction cache invalidation
-#endif
- .endm
-
-
-
-/*
- * Lock (prefetch & lock) a single line of the instruction cache.
- *
- * Parameters are:
- * ar address register that contains (virtual) address to lock
- * (may get clobbered in a future implementation, but not currently)
- * offset offset to add to \ar to compute effective address to lock
- * (note: some number of lsbits are ignored)
- */
- .macro icache_lock_line ar, offset
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
- ipfl \ar, \offset /* prefetch and lock icache line */
- icache_sync \ar
-#endif
- .endm
-
-
-
-/*
- * Lock (prefetch & lock) a specified portion of memory into the instruction cache.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro icache_lock_region astart, asize, ac
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
- // Instruction cache region lock:
- cache_hit_region ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
- icache_sync \ac
- // End of instruction cache region lock
-#endif
- .endm
-
-
-
-/*
- * Unlock a single line of the instruction cache.
- *
- * Parameters are:
- * ar address register that contains (virtual) address to unlock
- * (may get clobbered in a future implementation, but not currently)
- * offset offset to add to \ar to compute effective address to unlock
- * (note: some number of lsbits are ignored)
- */
- .macro icache_unlock_line ar, offset
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
- ihu \ar, \offset /* unlock icache line */
- icache_sync \ar
-#endif
- .endm
-
-
-
-/*
- * Unlock a specified portion of memory from the instruction cache.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro icache_unlock_region astart, asize, ac
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
- // Instruction cache region unlock:
- cache_hit_region ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
- icache_sync \ac
- // End of instruction cache region unlock
-#endif
- .endm
-
-
-
-/*
- * Unlock entire instruction cache.
- *
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro icache_unlock_all aa, ab
-#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
- // Instruction cache unlock:
- cache_index_all iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab
- icache_sync \aa
- // End of instruction cache unlock
-#endif
- .endm
-
-
-
-
-
-/*************************** DATA CACHE ***************************/
-
-
-
-/*
- * Reset/initialize the data cache by simply invalidating it
- * (need to unlock first also, if cache locking implemented):
- *
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro dcache_reset aa, ab
- dcache_unlock_all \aa, \ab
- dcache_invalidate_all \aa, \ab
- .endm
-
-
-
-
-/*
- * Synchronize after a data cache operation,
- * to be sure everything is in sync with memory as to be
- * expected following any previous data cache control operations.
- *
- * Parameters are:
- * ar an address register (temporary) (currently unused, but may be used in future)
- */
- .macro dcache_sync ar
-#if XCHAL_DCACHE_SIZE > 0
- // This previous sequence errs on the conservative side (too much so); a DSYNC should be sufficient:
- //memw // synchronize data cache changes relative to subsequent memory accesses
- //isync // be conservative and ISYNC as well (just to be sure)
-
- dsync
-#endif
- .endm
-
-
-
-/*
- * Synchronize after a data store operation,
- * to be sure the stored data is completely off the processor
- * (and assuming there is no buffering outside the processor,
- * that the data is in memory). This may be required to
- * ensure that the processor's write buffers are emptied.
- * A MEMW followed by a read guarantees this, by definition.
- * We also try to make sure the read itself completes.
- *
- * Parameters are:
- * ar an address register (temporary)
- */
- .macro write_sync ar
- memw // ensure previous memory accesses are complete prior to subsequent memory accesses
- l32i \ar, sp, 0 // completing this read ensures any previous write has completed, because of MEMW
- //slot
- add \ar, \ar, \ar // use the result of the read to help ensure the read completes (in future architectures)
- .endm
-
-
-/*
- * Invalidate a single line of the data cache.
- * Parameters are:
- * ar address register that contains (virtual) address to invalidate
- * (may get clobbered in a future implementation, but not currently)
- * offset (optional) offset to add to \ar to compute effective address to invalidate
- * (note: some number of lsbits are ignored)
- */
- .macro dcache_invalidate_line ar, offset
-#if XCHAL_DCACHE_SIZE > 0
- dhi \ar, \offset
- dcache_sync \ar
-#endif
- .endm
-
-
-
-
-
-/*
- * Invalidate data cache entries that cache a specified portion of memory.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro dcache_invalidate_region astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0
- // Data cache region invalidation:
- cache_hit_region dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
- dcache_sync \ac
- // End of data cache region invalidation
-#endif
- .endm
-
-
-
-#if 0
-/*
- * This is a work-around for a bug in SiChip1 (???).
- * There should be a proper mechanism for not outputting
- * these instructions when not needed.
- * To enable work-around, uncomment this and replace 'dii'
- * with 'dii_s1' everywhere, eg. in dcache_invalidate_all
- * macro below.
- */
- .macro dii_s1 ar, offset
- dii \ar, \offset
- or \ar, \ar, \ar
- or \ar, \ar, \ar
- or \ar, \ar, \ar
- or \ar, \ar, \ar
- .endm
-#endif
-
-
-/*
- * Invalidate entire data cache.
- *
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro dcache_invalidate_all aa, ab
-#if XCHAL_DCACHE_SIZE > 0
- // Data cache invalidation:
- cache_index_all dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab
- dcache_sync \aa
- // End of data cache invalidation
-#endif
- .endm
-
-
-
-/*
- * Writeback a single line of the data cache.
- * Parameters are:
- * ar address register that contains (virtual) address to writeback
- * (may get clobbered in a future implementation, but not currently)
- * offset offset to add to \ar to compute effective address to writeback
- * (note: some number of lsbits are ignored)
- */
- .macro dcache_writeback_line ar, offset
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
- dhwb \ar, \offset
- dcache_sync \ar
-#endif
- .endm
-
-
-
-/*
- * Writeback dirty data cache entries that cache a specified portion of memory.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro dcache_writeback_region astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
- // Data cache region writeback:
- cache_hit_region dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
- dcache_sync \ac
- // End of data cache region writeback
-#endif
- .endm
-
-
-
-/*
- * Writeback entire data cache.
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro dcache_writeback_all aa, ab
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
- // Data cache writeback:
- cache_index_all diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
- dcache_sync \aa
- // End of data cache writeback
-#endif
- .endm
-
-
-
-/*
- * Writeback and invalidate a single line of the data cache.
- * Parameters are:
- * ar address register that contains (virtual) address to writeback and invalidate
- * (may get clobbered in a future implementation, but not currently)
- * offset offset to add to \ar to compute effective address to writeback and invalidate
- * (note: some number of lsbits are ignored)
- */
- .macro dcache_writeback_inv_line ar, offset
-#if XCHAL_DCACHE_SIZE > 0
- dhwbi \ar, \offset /* writeback and invalidate dcache line */
- dcache_sync \ar
-#endif
- .endm
-
-
-
-/*
- * Writeback and invalidate data cache entries that cache a specified portion of memory.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro dcache_writeback_inv_region astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0
- // Data cache region writeback and invalidate:
- cache_hit_region dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
- dcache_sync \ac
- // End of data cache region writeback and invalidate
-#endif
- .endm
-
-
-
-/*
- * Writeback and invalidate entire data cache.
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro dcache_writeback_inv_all aa, ab
-#if XCHAL_DCACHE_SIZE > 0
- // Data cache writeback and invalidate:
-#if XCHAL_DCACHE_IS_WRITEBACK
- cache_index_all diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
- dcache_sync \aa
-#else /*writeback*/
- // Data cache does not support writeback, so just invalidate: */
- dcache_invalidate_all \aa, \ab
-#endif /*writeback*/
- // End of data cache writeback and invalidate
-#endif
- .endm
-
-
-
-
-/*
- * Lock (prefetch & lock) a single line of the data cache.
- *
- * Parameters are:
- * ar address register that contains (virtual) address to lock
- * (may get clobbered in a future implementation, but not currently)
- * offset offset to add to \ar to compute effective address to lock
- * (note: some number of lsbits are ignored)
- */
- .macro dcache_lock_line ar, offset
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
- dpfl \ar, \offset /* prefetch and lock dcache line */
- dcache_sync \ar
-#endif
- .endm
-
-
-
-/*
- * Lock (prefetch & lock) a specified portion of memory into the data cache.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro dcache_lock_region astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
- // Data cache region lock:
- cache_hit_region dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
- dcache_sync \ac
- // End of data cache region lock
-#endif
- .endm
-
-
-
-/*
- * Unlock a single line of the data cache.
- *
- * Parameters are:
- * ar address register that contains (virtual) address to unlock
- * (may get clobbered in a future implementation, but not currently)
- * offset offset to add to \ar to compute effective address to unlock
- * (note: some number of lsbits are ignored)
- */
- .macro dcache_unlock_line ar, offset
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
- dhu \ar, \offset /* unlock dcache line */
- dcache_sync \ar
-#endif
- .endm
-
-
-
-/*
- * Unlock a specified portion of memory from the data cache.
- * Parameters are:
- * astart start address (register gets clobbered)
- * asize size of the region in bytes (register gets clobbered)
- * ac unique register used as temporary
- */
- .macro dcache_unlock_region astart, asize, ac
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
- // Data cache region unlock:
- cache_hit_region dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
- dcache_sync \ac
- // End of data cache region unlock
-#endif
- .endm
-
-
-
-/*
- * Unlock entire data cache.
- *
- * Parameters:
- * aa, ab unique address registers (temporaries)
- */
- .macro dcache_unlock_all aa, ab
-#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
- // Data cache unlock:
- cache_index_all diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
- dcache_sync \aa
- // End of data cache unlock
-#endif
- .endm
-
-
-#endif /*XTENSA_CACHEASM_H*/
-
diff --git a/include/asm-xtensa/xtensa/cacheattrasm.h b/include/asm-xtensa/xtensa/cacheattrasm.h
deleted file mode 100644
index 1c3e117b359..00000000000
--- a/include/asm-xtensa/xtensa/cacheattrasm.h
+++ /dev/null
@@ -1,432 +0,0 @@
-#ifndef XTENSA_CACHEATTRASM_H
-#define XTENSA_CACHEATTRASM_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/cacheattrasm.h -- assembler-specific
- * CACHEATTR register related definitions that depend on CORE
- * configuration.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/coreasm.h>
-
-
-/*
- * This header file defines assembler macros of the form:
- * <x>cacheattr_<func>
- * where:
- * <x> is 'i', 'd' or absent for instruction, data
- * or both caches; and
- * <func> indicates the function of the macro.
- *
- * The following functions are defined:
- *
- * icacheattr_get
- * Reads I-cache CACHEATTR into a2 (clobbers a3-a5).
- *
- * dcacheattr_get
- * Reads D-cache CACHEATTR into a2 (clobbers a3-a5).
- * (Note: for configs with a real CACHEATTR register, the
- * above two macros are identical.)
- *
- * cacheattr_set
- * Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered).
- * Works even when changing one's own code's attributes.
- *
- * icacheattr_is_enabled label
- * Branches to \label if I-cache appears to have been enabled
- * (eg. if CACHEATTR contains a cache-enabled attribute).
- * (clobbers a2-a5,SAR)
- *
- * dcacheattr_is_enabled label
- * Branches to \label if D-cache appears to have been enabled
- * (eg. if CACHEATTR contains a cache-enabled attribute).
- * (clobbers a2-a5,SAR)
- *
- * cacheattr_is_enabled label
- * Branches to \label if either I-cache or D-cache appears to have been enabled
- * (eg. if CACHEATTR contains a cache-enabled attribute).
- * (clobbers a2-a5,SAR)
- *
- * The following macros are only defined under certain conditions:
- *
- * icacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
- * Writes I-cache CACHEATTR from a2 (a3-a8 clobbered).
- *
- * dcacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
- * Writes D-cache CACHEATTR from a2 (a3-a8 clobbered).
- */
-
-
-
-/*************************** GENERIC -- ALL CACHES ***************************/
-
-/*
- * _cacheattr_get
- *
- * (Internal macro.)
- * Returns value of CACHEATTR register (or closest equivalent) in a2.
- *
- * Entry:
- * (none)
- * Exit:
- * a2 value read from CACHEATTR
- * a3-a5 clobbered (temporaries)
- */
- .macro _cacheattr_get tlb
-#if XCHAL_HAVE_CACHEATTR
- rsr a2, CACHEATTR
-#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
- // We have a config that "mimics" CACHEATTR using a simplified
- // "MMU" composed of a single statically-mapped way.
- // DTLB and ITLB are independent, so there's no single
- // cache attribute that can describe both. So for now
- // just return the DTLB state.
- movi a5, 0xE0000000
- movi a2, 0
- movi a3, 0
-1: add a3, a3, a5 // next segment
- r&tlb&1 a4, a3 // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0
- dsync // interlock???
- slli a2, a2, 4
- extui a4, a4, 0, 4 // extract CA
- or a2, a2, a4
- bnez a3, 1b
-#else
- // This macro isn't applicable to arbitrary MMU configurations.
- // Just return zero.
- movi a2, 0
-#endif
- .endm
-
- .macro icacheattr_get
- _cacheattr_get itlb
- .endm
-
- .macro dcacheattr_get
- _cacheattr_get dtlb
- .endm
-
-
-#define XCHAL_CACHEATTR_ALL_BYPASS 0x22222222 /* default (powerup/reset) value of CACHEATTR, all BYPASS
- mode (ie. disabled/bypassed caches) */
-
-#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
-
-#define XCHAL_FCA_ENAMASK 0x001A /* bitmap of fetch attributes that require enabled icache */
-#define XCHAL_LCA_ENAMASK 0x0003 /* bitmap of load attributes that require enabled dcache */
-#define XCHAL_SCA_ENAMASK 0x0003 /* bitmap of store attributes that require enabled dcache */
-#define XCHAL_LSCA_ENAMASK (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK) /* l/s attrs requiring enabled dcache */
-#define XCHAL_ALLCA_ENAMASK (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK) /* all attrs requiring enabled caches */
-
-/*
- * _cacheattr_is_enabled
- *
- * (Internal macro.)
- * Branches to \label if CACHEATTR in a2 indicates an enabled
- * cache, using mask in a3.
- *
- * Parameters:
- * label where to branch to if cache is enabled
- * Entry:
- * a2 contains CACHEATTR value used to determine whether
- * caches are enabled
- * a3 16-bit constant where each bit correspond to
- * one of the 16 possible CA values (in a CACHEATTR mask);
- * CA values that indicate the cache is enabled
- * have their corresponding bit set in this mask
- * (eg. use XCHAL_xCA_ENAMASK , above)
- * Exit:
- * a2,a4,a5 clobbered
- * SAR clobbered
- */
- .macro _cacheattr_is_enabled label
- movi a4, 8 // loop 8 times
-.Lcaife\@:
- extui a5, a2, 0, 4 // get CA nibble
- ssr a5 // index into mask according to CA...
- srl a5, a3 // ...and get CA's mask bit in a5 bit 0
- bbsi.l a5, 0, \label // if CA indicates cache enabled, jump to label
- srli a2, a2, 4 // next nibble
- addi a4, a4, -1
- bnez a4, .Lcaife\@ // loop for each nibble
- .endm
-
-#else /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
- .macro _cacheattr_is_enabled label
- j \label // macro not applicable, assume caches always enabled
- .endm
-#endif /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
-
-
-
-/*
- * icacheattr_is_enabled
- *
- * Branches to \label if I-cache is enabled.
- *
- * Parameters:
- * label where to branch to if icache is enabled
- * Entry:
- * (none)
- * Exit:
- * a2-a5, SAR clobbered (temporaries)
- */
- .macro icacheattr_is_enabled label
-#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
- icacheattr_get
- movi a3, XCHAL_FCA_ENAMASK
-#endif
- _cacheattr_is_enabled \label
- .endm
-
-/*
- * dcacheattr_is_enabled
- *
- * Branches to \label if D-cache is enabled.
- *
- * Parameters:
- * label where to branch to if dcache is enabled
- * Entry:
- * (none)
- * Exit:
- * a2-a5, SAR clobbered (temporaries)
- */
- .macro dcacheattr_is_enabled label
-#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
- dcacheattr_get
- movi a3, XCHAL_LSCA_ENAMASK
-#endif
- _cacheattr_is_enabled \label
- .endm
-
-/*
- * cacheattr_is_enabled
- *
- * Branches to \label if either I-cache or D-cache is enabled.
- *
- * Parameters:
- * label where to branch to if a cache is enabled
- * Entry:
- * (none)
- * Exit:
- * a2-a5, SAR clobbered (temporaries)
- */
- .macro cacheattr_is_enabled label
-#if XCHAL_HAVE_CACHEATTR
- rsr a2, CACHEATTR
- movi a3, XCHAL_ALLCA_ENAMASK
-#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
- icacheattr_get
- movi a3, XCHAL_FCA_ENAMASK
- _cacheattr_is_enabled \label
- dcacheattr_get
- movi a3, XCHAL_LSCA_ENAMASK
-#endif
- _cacheattr_is_enabled \label
- .endm
-
-
-
-/*
- * The ISA does not have a defined way to change the
- * instruction cache attributes of the running code,
- * ie. of the memory area that encloses the current PC.
- * However, each micro-architecture (or class of
- * configurations within a micro-architecture)
- * provides a way to deal with this issue.
- *
- * Here are a few macros used to implement the relevant
- * approach taken.
- */
-
-#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
- // We have a config that "mimics" CACHEATTR using a simplified
- // "MMU" composed of a single statically-mapped way.
-
-/*
- * icacheattr_set
- *
- * Entry:
- * a2 cacheattr value to set
- * Exit:
- * a2 unchanged
- * a3-a8 clobbered (temporaries)
- */
- .macro icacheattr_set
-
- movi a5, 0xE0000000 // mask of upper 3 bits
- movi a6, 3f // PC where ITLB is set
- movi a3, 0 // start at region 0 (0 .. 7)
- and a6, a6, a5 // upper 3 bits of local PC area
- mov a7, a2 // copy a2 so it doesn't get clobbered
- j 3f
-
-# if XCHAL_HAVE_XLT_CACHEATTR
- // Can do translations, use generic method:
-1: sub a6, a3, a5 // address of some other segment
- ritlb1 a8, a6 // save its PPN+CA
- dsync // interlock??
- witlb a4, a6 // make it translate to this code area
- movi a6, 5f // where to jump into it
- isync
- sub a6, a6, a5 // adjust jump address within that other segment
- jx a6
-
- // Note that in the following code snippet, which runs at a different virtual
- // address than it is assembled for, we avoid using literals (eg. via movi/l32r)
- // just in case literals end up in a different 512 MB segment, and we avoid
- // instructions that rely on the current PC being what is expected.
- //
- .align 4
- _j 6f // this is at label '5' minus 4 bytes
- .align 4
-5: witlb a4, a3 // we're in other segment, now can write previous segment's CA
- isync
- add a6, a6, a5 // back to previous segment
- addi a6, a6, -4 // next jump label
- jx a6
-
-6: sub a6, a3, a5 // address of some other segment
- witlb a8, a6 // restore PPN+CA of other segment
- mov a6, a3 // restore a6
- isync
-# else /* XCHAL_HAVE_XLT_CACHEATTR */
- // Use micro-architecture specific method.
- // The following 4-instruction sequence is aligned such that
- // it all fits within a single I-cache line. Sixteen byte
- // alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE
- // actually causes problems because that can be greater than
- // the alignment of the reset vector, where this macro is often
- // invoked, which would cause the linker to align the reset
- // vector code away from the reset vector!!).
- .align 16 /*XCHAL_ICACHE_LINESIZE*/
-1: _witlb a4, a3 // write wired PTE (CA, no PPN) of 512MB segment to ITLB
- _isync
- nop
- nop
-# endif /* XCHAL_HAVE_XLT_CACHEATTR */
- beq a3, a5, 4f // done?
-
- // Note that in the WITLB loop, we don't do any load/stores
- // (may not be an issue here, but it is important in the DTLB case).
-2: srli a7, a7, 4 // next CA
- sub a3, a3, a5 // next segment (add 0x20000000)
-3:
-# if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */
- ritlb1 a8, a3 // get current PPN+CA of segment
- dsync // interlock???
- extui a4, a7, 0, 4 // extract CA to set
- srli a8, a8, 4 // clear CA but keep PPN ...
- slli a8, a8, 4 // ...
- add a4, a4, a8 // combine new CA with PPN to preserve
-# else
- extui a4, a7, 0, 4 // extract CA
-# endif
- beq a3, a6, 1b // current PC's region? if so, do it in a safe way
- witlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to ITLB
- bne a3, a5, 2b
- isync // make sure all ifetch changes take effect
-4:
- .endm // icacheattr_set
-
-
-/*
- * dcacheattr_set
- *
- * Entry:
- * a2 cacheattr value to set
- * Exit:
- * a2 unchanged
- * a3-a8 clobbered (temporaries)
- */
-
- .macro dcacheattr_set
-
- movi a5, 0xE0000000 // mask of upper 3 bits
- movi a3, 0 // start at region 0 (0 .. 7)
- mov a7, a2 // copy a2 so it doesn't get clobbered
- j 3f
- // Note that in the WDTLB loop, we don't do any load/stores
- // (including implicit l32r via movi) because it isn't safe.
-2: srli a7, a7, 4 // next CA
- sub a3, a3, a5 // next segment (add 0x20000000)
-3:
-# if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */
- rdtlb1 a8, a3 // get current PPN+CA of segment
- dsync // interlock???
- extui a4, a7, 0, 4 // extract CA to set
- srli a8, a8, 4 // clear CA but keep PPN ...
- slli a8, a8, 4 // ...
- add a4, a4, a8 // combine new CA with PPN to preserve
-# else
- extui a4, a7, 0, 4 // extract CA to set
-# endif
- wdtlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to DTLB
- bne a3, a5, 2b
- dsync // make sure all data path changes take effect
- .endm // dcacheattr_set
-
-#endif /* XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
-
-
-
-/*
- * cacheattr_set
- *
- * Macro that sets the current CACHEATTR safely
- * (both i and d) according to the current contents of a2.
- * It works even when changing the cache attributes of
- * the currently running code.
- *
- * Entry:
- * a2 cacheattr value to set
- * Exit:
- * a2 unchanged
- * a3-a8 clobbered (temporaries)
- */
- .macro cacheattr_set
-
-#if XCHAL_HAVE_CACHEATTR
-# if XCHAL_ICACHE_LINESIZE < 4
- // No i-cache, so can always safely write to CACHEATTR:
- wsr a2, CACHEATTR
-# else
- // The Athens micro-architecture, when using the old
- // exception architecture option (ie. with the CACHEATTR register)
- // allows changing the cache attributes of the running code
- // using the following exact sequence aligned to be within
- // an instruction cache line. (NOTE: using XCHAL_ICACHE_LINESIZE
- // alignment actually causes problems because that can be greater
- // than the alignment of the reset vector, where this macro is often
- // invoked, which would cause the linker to align the reset
- // vector code away from the reset vector!!).
- j 1f
- .align 16 /*XCHAL_ICACHE_LINESIZE*/ // align to within an I-cache line
-1: _wsr a2, CACHEATTR
- _isync
- nop
- nop
-# endif
-#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
- // DTLB and ITLB are independent, but to keep semantics
- // of this macro we simply write to both.
- icacheattr_set
- dcacheattr_set
-#else
- // This macro isn't applicable to arbitrary MMU configurations.
- // Do nothing in this case.
-#endif
- .endm
-
-
-#endif /*XTENSA_CACHEATTRASM_H*/
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/core.h b/include/asm-xtensa/xtensa/config-linux_be/core.h
deleted file mode 100644
index d54fe5eb106..00000000000
--- a/include/asm-xtensa/xtensa/config-linux_be/core.h
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*
- * xtensa/config/core.h -- HAL definitions that are dependent on CORE configuration
- *
- * This header file is sometimes referred to as the "compile-time HAL" or CHAL.
- * It was generated for a specific Xtensa processor configuration.
- *
- * Source for configuration-independent binaries (which link in a
- * configuration-specific HAL library) must NEVER include this file.
- * It is perfectly normal, however, for the HAL source itself to include this file.
- */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * 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 Lesser 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.
- */
-
-
-#ifndef XTENSA_CONFIG_CORE_H
-#define XTENSA_CONFIG_CORE_H
-
-#include <xtensa/hal.h>
-
-
-/*----------------------------------------------------------------------
- GENERAL
- ----------------------------------------------------------------------*/
-
-/*
- * Separators for macros that expand into arrays.
- * These can be predefined by files that #include this one,
- * when different separators are required.
- */
-/* Element separator for macros that expand into 1-dimensional arrays: */
-#ifndef XCHAL_SEP
-#define XCHAL_SEP ,
-#endif
-/* Array separator for macros that expand into 2-dimensional arrays: */
-#ifndef XCHAL_SEP2
-#define XCHAL_SEP2 },{
-#endif
-
-
-/*----------------------------------------------------------------------
- ENDIANNESS
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_BE 1
-#define XCHAL_HAVE_LE 0
-#define XCHAL_MEMORY_ORDER XTHAL_BIGENDIAN
-
-
-/*----------------------------------------------------------------------
- REGISTER WINDOWS
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_WINDOWED 1 /* 1 if windowed registers option configured, 0 otherwise */
-#define XCHAL_NUM_AREGS 64 /* number of physical address regs */
-#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */
-
-
-/*----------------------------------------------------------------------
- ADDRESS ALIGNMENT
- ----------------------------------------------------------------------*/
-
-/* These apply to a selected set of core load and store instructions only (see ISA): */
-#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* 1 if unaligned loads cause an exception, 0 otherwise */
-#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* 1 if unaligned stores cause an exception, 0 otherwise */
-
-
-/*----------------------------------------------------------------------
- INTERRUPTS
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_INTERRUPTS 1 /* 1 if interrupt option configured, 0 otherwise */
-#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* 1 if high-priority interrupt option configured, 0 otherwise */
-#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS XCHAL_HAVE_HIGHPRI_INTERRUPTS
-#define XCHAL_HAVE_NMI 0 /* 1 if NMI option configured, 0 otherwise */
-#define XCHAL_NUM_INTERRUPTS 17 /* number of interrupts */
-#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* number of bits to hold an interrupt number: roundup(log2(number of interrupts)) */
-#define XCHAL_NUM_EXTINTERRUPTS 10 /* number of external interrupts */
-#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels (not including level zero!) */
-#define XCHAL_NUM_LOWPRI_LEVELS 1 /* number of low-priority interrupt levels (always 1) */
-#define XCHAL_FIRST_HIGHPRI_LEVEL (XCHAL_NUM_LOWPRI_LEVELS+1) /* level of first high-priority interrupt (always 2) */
-#define XCHAL_EXCM_LEVEL 1 /* level of interrupts masked by PS.EXCM (XEA2 only; always 1 in T10xx);
- for XEA1, where there is no PS.EXCM, this is always 1;
- interrupts at levels FIRST_HIGHPRI <= n <= EXCM_LEVEL, if any,
- are termed "medium priority" interrupts (post T10xx only) */
-/* Note: 1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15 */
-
-/* Masks of interrupts at each interrupt level: */
-#define XCHAL_INTLEVEL0_MASK 0x00000000
-#define XCHAL_INTLEVEL1_MASK 0x000064F9
-#define XCHAL_INTLEVEL2_MASK 0x00008902
-#define XCHAL_INTLEVEL3_MASK 0x00011204
-#define XCHAL_INTLEVEL4_MASK 0x00000000
-#define XCHAL_INTLEVEL5_MASK 0x00000000
-#define XCHAL_INTLEVEL6_MASK 0x00000000
-#define XCHAL_INTLEVEL7_MASK 0x00000000
-#define XCHAL_INTLEVEL8_MASK 0x00000000
-#define XCHAL_INTLEVEL9_MASK 0x00000000
-#define XCHAL_INTLEVEL10_MASK 0x00000000
-#define XCHAL_INTLEVEL11_MASK 0x00000000
-#define XCHAL_INTLEVEL12_MASK 0x00000000
-#define XCHAL_INTLEVEL13_MASK 0x00000000
-#define XCHAL_INTLEVEL14_MASK 0x00000000
-#define XCHAL_INTLEVEL15_MASK 0x00000000
-/* As an array of entries (eg. for C constant arrays): */
-#define XCHAL_INTLEVEL_MASKS 0x00000000 XCHAL_SEP \
- 0x000064F9 XCHAL_SEP \
- 0x00008902 XCHAL_SEP \
- 0x00011204 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000 XCHAL_SEP \
- 0x00000000
-
-/* Masks of interrupts at each range 1..n of interrupt levels: */
-#define XCHAL_INTLEVEL0_ANDBELOW_MASK 0x00000000
-#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000064F9
-#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x0000EDFB
-#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL8_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL9_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL10_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL11_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL12_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL13_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL14_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_INTLEVEL15_ANDBELOW_MASK 0x0001FFFF
-#define XCHAL_LOWPRI_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK /* mask of all low-priority interrupts */
-#define XCHAL_EXCM_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK /* mask of all interrupts masked by PS.EXCM (or CEXCM) */
-/* As an array of entries (eg. for C constant arrays): */
-#define XCHAL_INTLEVEL_ANDBELOW_MASKS 0x00000000 XCHAL_SEP \
- 0x000064F9 XCHAL_SEP \
- 0x0000EDFB XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF XCHAL_SEP \
- 0x0001FFFF
-
-/* Interrupt numbers for each interrupt level at which only one interrupt was configured: */
-/*#define XCHAL_INTLEVEL1_NUM ...more than one interrupt at this level...*/
-/*#define XCHAL_INTLEVEL2_NUM ...more than one interrupt at this level...*/
-/*#define XCHAL_INTLEVEL3_NUM ...more than one interrupt at this level...*/
-
-/* Level of each interrupt: */
-#define XCHAL_INT0_LEVEL 1
-#define XCHAL_INT1_LEVEL 2
-#define XCHAL_INT2_LEVEL 3
-#define XCHAL_INT3_LEVEL 1
-#define XCHAL_INT4_LEVEL 1
-#define XCHAL_INT5_LEVEL 1
-#define XCHAL_INT6_LEVEL 1
-#define XCHAL_INT7_LEVEL 1
-#define XCHAL_INT8_LEVEL 2
-#define XCHAL_INT9_LEVEL 3
-#define XCHAL_INT10_LEVEL 1
-#define XCHAL_INT11_LEVEL 2
-#define XCHAL_INT12_LEVEL 3
-#define XCHAL_INT13_LEVEL 1
-#define XCHAL_INT14_LEVEL 1
-#define XCHAL_INT15_LEVEL 2
-#define XCHAL_INT16_LEVEL 3
-#define XCHAL_INT17_LEVEL 0
-#define XCHAL_INT18_LEVEL 0
-#define XCHAL_INT19_LEVEL 0
-#define XCHAL_INT20_LEVEL 0
-#define XCHAL_INT21_LEVEL 0
-#define XCHAL_INT22_LEVEL 0
-#define XCHAL_INT23_LEVEL 0
-#define XCHAL_INT24_LEVEL 0
-#define XCHAL_INT25_LEVEL 0
-#define XCHAL_INT26_LEVEL 0
-#define XCHAL_INT27_LEVEL 0
-#define XCHAL_INT28_LEVEL 0
-#define XCHAL_INT29_LEVEL 0
-#define XCHAL_INT30_LEVEL 0
-#define XCHAL_INT31_LEVEL 0
-/* As an array of entries (eg. for C constant arrays): */
-#define XCHAL_INT_LEVELS 1 XCHAL_SEP \
- 2 XCHAL_SEP \
- 3 XCHAL_SEP \
- 1 XCHAL_SEP \
- 1 XCHAL_SEP \
- 1 XCHAL_SEP \
- 1 XCHAL_SEP \
- 1 XCHAL_SEP \
- 2 XCHAL_SEP \
- 3 XCHAL_SEP \
- 1 XCHAL_SEP \
- 2 XCHAL_SEP \
- 3 XCHAL_SEP \
- 1 XCHAL_SEP \
- 1 XCHAL_SEP \
- 2 XCHAL_SEP \
- 3 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0 XCHAL_SEP \
- 0
-
-/* Type of each interrupt: */
-#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
-#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_EDGE
-#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_EDGE
-#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_EDGE
-#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER
-#define XCHAL_INT11_TYPE XTHAL_INTTYPE_TIMER
-#define XCHAL_INT12_TYPE XTHAL_INTTYPE_TIMER
-#define XCHAL_INT13_TYPE XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT16_TYPE XTHAL_INTTYPE_SOFTWARE
-#define XCHAL_INT17_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT18_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT19_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT20_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT21_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT22_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT23_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT24_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT25_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT26_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT27_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT28_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT29_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT30_TYPE XTHAL_INTTYPE_UNCONFIGURED
-#define XCHAL_INT31_TYPE XTHAL_INTTYPE_UNCONFIGURED
-/* As an array of entries (eg. for C constant arrays): */
-#define XCHAL_INT_TYPES XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
- XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
- XTHAL_INTTYPE_TIMER XCHAL_SEP \
- XTHAL_INTTYPE_TIMER XCHAL_SEP \
- XTHAL_INTTYPE_TIMER XCHAL_SEP \
- XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
- XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
- XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
- XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
- XTHAL_INTTYPE_UNCONFIGURED
-
-/* Masks of interrupts for each type of interrupt: */
-#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFE0000
-#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0001E000
-#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000380
-#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000007F
-#define XCHAL_INTTYPE_MASK_TIMER 0x00001C00
-#define XCHAL_INTTYPE_MASK_NMI 0x00000000
-/* As an array of entries (eg. for C constant arrays): */
-#define XCHAL_INTTYPE_MASKS 0xFFFE0000 XCHAL_SEP \
- 0x0001E000 XCHAL_SEP \
- 0x00000380 XCHAL_SEP \
- 0x0000007F XCHAL_SEP \
- 0x00001C00 XCHAL_SEP \
- 0x00000000
-
-/* Interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned */
-#define XCHAL_TIMER0_INTERRUPT 10
-#define XCHAL_TIMER1_INTERRUPT 11
-#define XCHAL_TIMER2_INTERRUPT 12
-#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED
-/* As an array of entries (eg. for C constant arrays): */
-#define XCHAL_TIMER_INTERRUPTS 10 XCHAL_SEP \
- 11 XCHAL_SEP \
- 12 XCHAL_SEP \
- XTHAL_TIMER_UNCONFIGURED
-
-/* Indexing macros: */
-#define _XCHAL_INTLEVEL_MASK(n) XCHAL_INTLEVEL ## n ## _MASK
-#define XCHAL_INTLEVEL_MASK(n) _XCHAL_INTLEVEL_MASK(n) /* n = 0 .. 15 */
-#define _XCHAL_INTLEVEL_ANDBELOWMASK(n) XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK
-#define XCHAL_INTLEVEL_ANDBELOW_MASK(n) _XCHAL_INTLEVEL_ANDBELOWMASK(n) /* n = 0 .. 15 */
-#define _XCHAL_INT_LEVEL(n) XCHAL_INT ## n ## _LEVEL
-#define XCHAL_INT_LEVEL(n) _XCHAL_INT_LEVEL(n) /* n = 0 .. 31 */
-#define _XCHAL_INT_TYPE(n) XCHAL_INT ## n ## _TYPE
-#define XCHAL_INT_TYPE(n) _XCHAL_INT_TYPE(n) /* n = 0 .. 31 */
-#define _XCHAL_TIMER_INTERRUPT(n) XCHAL_TIMER ## n ## _INTERRUPT
-#define XCHAL_TIMER_INTERRUPT(n) _XCHAL_TIMER_INTERRUPT(n) /* n = 0 .. 3 */
-
-
-
-/*
- * External interrupt vectors/levels.
- * These macros describe how Xtensa processor interrupt numbers
- * (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
- * map to external BInterrupt<n> pins, for those interrupts
- * configured as external (level-triggered, edge-triggered, or NMI).
- * See the Xtensa processor databook for more details.
- */
-
-/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */
-#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */
-#define XCHAL_EXTINT1_NUM 1 /* (intlevel 2) */
-#define XCHAL_EXTINT2_NUM 2 /* (intlevel 3) */
-#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */
-#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */
-#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */
-#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */
-#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */
-#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */
-#define XCHAL_EXTINT9_NUM 9 /* (intlevel 3) */
-
-/* Corresponding interrupt masks: */
-#define XCHAL_EXTINT0_MASK 0x00000001
-#define XCHAL_EXTINT1_MASK 0x00000002
-#define XCHAL_EXTINT2_MASK 0x00000004
-#define XCHAL_EXTINT3_MASK 0x00000008
-#define XCHAL_EXTINT4_MASK 0x00000010
-#define XCHAL_EXTINT5_MASK 0x00000020
-#define XCHAL_EXTINT6_MASK 0x00000040
-#define XCHAL_EXTINT7_MASK 0x00000080
-#define XCHAL_EXTINT8_MASK 0x00000100
-#define XCHAL_EXTINT9_MASK 0x00000200
-
-/* Core config interrupt levels mapped to each external interrupt: */
-#define XCHAL_EXTINT0_LEVEL 1 /* (int number 0) */
-#define XCHAL_EXTINT1_LEVEL 2 /* (int number 1) */
-#define XCHAL_EXTINT2_LEVEL 3 /* (int number 2) */
-#define XCHAL_EXTINT3_LEVEL 1 /* (int number 3) */
-#define XCHAL_EXTINT4_LEVEL 1 /* (int number 4) */
-#define XCHAL_EXTINT5_LEVEL 1 /* (int number 5) */
-#define XCHAL_EXTINT6_LEVEL 1 /* (int number 6) */
-#define XCHAL_EXTINT7_LEVEL 1 /* (int number 7) */
-#define XCHAL_EXTINT8_LEVEL 2 /* (int number 8) */
-#define XCHAL_EXTINT9_LEVEL 3 /* (int number 9) */
-
-
-/*----------------------------------------------------------------------
- EXCEPTIONS and VECTORS
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_EXCEPTIONS 1 /* 1 if exception option configured, 0 otherwise */
-
-#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture number: 1 for XEA1 (old), 2 for XEA2 (new) */
-#define XCHAL_HAVE_XEA1 0 /* 1 if XEA1, 0 otherwise */
-#define XCHAL_HAVE_XEA2 1 /* 1 if XEA2, 0 otherwise */
-/* For backward compatibility ONLY -- DO NOT USE (will be removed in future release): */
-#define XCHAL_HAVE_OLD_EXC_ARCH XCHAL_HAVE_XEA1 /* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */
-#define XCHAL_HAVE_EXCM XCHAL_HAVE_XEA2 /* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */
-
-#define XCHAL_RESET_VECTOR_VADDR 0xFE000020
-#define XCHAL_RESET_VECTOR_PADDR 0xFE000020
-#define XCHAL_USER_VECTOR_VADDR 0xD0000220
-#define XCHAL_PROGRAMEXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR /* for backward compatibility */
-#define XCHAL_USEREXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR /* for backward compatibility */
-#define XCHAL_USER_VECTOR_PADDR 0x00000220
-#define XCHAL_PROGRAMEXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR /* for backward compatibility */
-#define XCHAL_USEREXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR /* for backward compatibility */
-#define XCHAL_KERNEL_VECTOR_VADDR 0xD0000200
-#define XCHAL_STACKEDEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR /* for backward compatibility */
-#define XCHAL_KERNELEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR /* for backward compatibility */
-#define XCHAL_KERNEL_VECTOR_PADDR 0x00000200
-#define XCHAL_STACKEDEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR /* for backward compatibility */
-#define XCHAL_KERNELEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR /* for backward compatibility */
-#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xD0000290
-#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x00000290
-#define XCHAL_WINDOW_VECTORS_VADDR 0xD0000000
-#define XCHAL_WINDOW_VECTORS_PADDR 0x00000000
-#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xD0000240
-#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000240
-#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xD0000250
-#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x00000250
-#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xFE000520
-#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xFE000520
-#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR
-#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR
-
-/* Indexing macros: */
-#define _XCHAL_INTLEVEL_VECTOR_VADDR(n) XCHAL_INTLEVEL ## n ## _VECTOR_VADDR
-#define XCHAL_INTLEVEL_VECTOR_VADDR(n) _XCHAL_INTLEVEL_VECTOR_VADDR(n) /* n = 0 .. 15 */
-
-/*
- * General Exception Causes
- * (values of EXCCAUSE special register set by general exceptions,
- * which vector to the user, kernel, or double-exception vectors):
- */
-#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION 0 /* Illegal Instruction (IllegalInstruction) */
-#define XCHAL_EXCCAUSE_SYSTEM_CALL 1 /* System Call (SystemCall) */
-#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR 2 /* Instruction Fetch Error (InstructionFetchError) */
-#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error (LoadStoreError) */
-#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt (Level1Interrupt) */
-#define XCHAL_EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (Alloca) */
-#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero (IntegerDivideByZero) */
-#define XCHAL_EXCCAUSE_SPECULATION 7 /* Speculation (Speculation) */
-#define XCHAL_EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction (Privileged) */
-#define XCHAL_EXCCAUSE_UNALIGNED 9 /* Unaligned Load Store (Unaligned) */
-#define XCHAL_EXCCAUSE_ITLB_MISS 16 /* ITlb Miss Exception (ITlbMiss) */
-#define XCHAL_EXCCAUSE_ITLB_MULTIHIT 17 /* ITlb Mutltihit Exception (ITlbMultihit) */
-#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE 18 /* ITlb Privilege Exception (ITlbPrivilege) */
-#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION 19 /* ITlb Size Restriction Exception (ITlbSizeRestriction) */
-#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20 /* Fetch Cache Attribute Exception (FetchCacheAttribute) */
-#define XCHAL_EXCCAUSE_DTLB_MISS 24 /* DTlb Miss Exception (DTlbMiss) */
-#define XCHAL_EXCCAUSE_DTLB_MULTIHIT 25 /* DTlb Multihit Exception (DTlbMultihit) */
-#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE 26 /* DTlb Privilege Exception (DTlbPrivilege) */
-#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION 27 /* DTlb Size Restriction Exception (DTlbSizeRestriction) */
-#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28 /* Load Cache Attribute Exception (LoadCacheAttribute) */
-#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE 29 /* Store Cache Attribute Exception (StoreCacheAttribute) */
-#define XCHAL_EXCCAUSE_FLOATING_POINT 40 /* Floating Point Exception (FloatingPoint) */
-
-
-
-/*----------------------------------------------------------------------
- TIMERS
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_CCOUNT 1 /* 1 if have CCOUNT, 0 otherwise */
-/*#define XCHAL_HAVE_TIMERS XCHAL_HAVE_CCOUNT*/
-#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */
-
-
-
-/*----------------------------------------------------------------------
- DEBUG
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_DEBUG 1 /* 1 if debug option configured, 0 otherwise */
-#define XCHAL_HAVE_OCD 1 /* 1 if OnChipDebug option configured, 0 otherwise */
-#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */
-#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */
-#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */
-/*DebugExternalInterrupt 0 0|1*/
-/*DebugUseDIRArray 0 0|1*/
-
-
-
-
-/*----------------------------------------------------------------------
- COPROCESSORS and EXTRA STATE
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_CP 0 /* 1 if coprocessor option configured (CPENABLE present) */
-#define XCHAL_CP_MAXCFG 0 /* max allowed cp id plus one (per cfg) */
-
-#include <xtensa/config/tie.h>
-
-
-
-
-/*----------------------------------------------------------------------
- INTERNAL I/D RAM/ROMs and XLMI
- ----------------------------------------------------------------------*/
-
-#define XCHAL_NUM_INSTROM 0 /* number of core instruction ROMs configured */
-#define XCHAL_NUM_INSTRAM 0 /* number of core instruction RAMs configured */
-#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs configured */
-#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs configured */
-#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports configured */
-#define XCHAL_NUM_IROM XCHAL_NUM_INSTROM /* (DEPRECATED) */
-#define XCHAL_NUM_IRAM XCHAL_NUM_INSTRAM /* (DEPRECATED) */
-#define XCHAL_NUM_DROM XCHAL_NUM_DATAROM /* (DEPRECATED) */
-#define XCHAL_NUM_DRAM XCHAL_NUM_DATARAM /* (DEPRECATED) */
-
-
-
-/*----------------------------------------------------------------------
- CACHE
- ----------------------------------------------------------------------*/
-
-/* Size of the cache lines in log2(bytes): */
-#define XCHAL_ICACHE_LINEWIDTH 4
-#define XCHAL_DCACHE_LINEWIDTH 4
-/* Size of the cache lines in bytes: */
-#define XCHAL_ICACHE_LINESIZE 16
-#define XCHAL_DCACHE_LINESIZE 16
-/* Max for both I-cache and D-cache (used for general alignment): */
-#define XCHAL_CACHE_LINEWIDTH_MAX 4
-#define XCHAL_CACHE_LINESIZE_MAX 16
-
-/* Number of cache sets in log2(lines per way): */
-#define XCHAL_ICACHE_SETWIDTH 8
-#define XCHAL_DCACHE_SETWIDTH 8
-/* Max for both I-cache and D-cache (used for general cache-coherency page alignment): */
-#define XCHAL_CACHE_SETWIDTH_MAX 8
-#define XCHAL_CACHE_SETSIZE_MAX 256
-
-/* Cache set associativity (number of ways): */
-#define XCHAL_ICACHE_WAYS 2
-#define XCHAL_DCACHE_WAYS 2
-
-/* Size of the caches in bytes (ways * 2^(linewidth + setwidth)): */
-#define XCHAL_ICACHE_SIZE 8192
-#define XCHAL_DCACHE_SIZE 8192
-
-/* Cache features: */
-#define XCHAL_DCACHE_IS_WRITEBACK 0
-/* Whether cache locking feature is available: */
-#define XCHAL_ICACHE_LINE_LOCKABLE 0
-#define XCHAL_DCACHE_LINE_LOCKABLE 0
-
-/* Number of (encoded) cache attribute bits: */
-#define XCHAL_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */
-/* (The number of access mode bits (decoded cache attribute bits) is defined by the architecture; see xtensa/hal.h?) */
-
-
-/* Cache Attribute encodings -- lists of access modes for each cache attribute: */
-#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_BYPASS XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_BYPASS XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_CACHED XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_CACHED XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_CACHED XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_CACHED XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_EXCEPTION XCHAL_SEP \
- XTHAL_FAM_EXCEPTION
-#define XCHAL_LCA_LIST XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_BYPASSG XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_BYPASSG XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_CACHED XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_CACHED XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_NACACHED XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_NACACHED XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_ISOLATE XCHAL_SEP \
- XTHAL_LAM_EXCEPTION XCHAL_SEP \
- XTHAL_LAM_CACHED
-#define XCHAL_SCA_LIST XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_BYPASS XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_WRITETHRU XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_WRITETHRU XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_ISOLATE XCHAL_SEP \
- XTHAL_SAM_EXCEPTION XCHAL_SEP \
- XTHAL_SAM_WRITETHRU
-
-/* Test:
- read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
- read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
- all: 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
- fault: 0 + 2 + 4 + 6 + 8 + 10 + 12 + 14
- r/w/x cached:
- r/w/x dcached:
- I-bypass: 1 + 3
-
- load guard bit set: 1 + 3
- load guard bit clr: 0 + 2 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
- hit-cache r/w/x: 7 + 11
-
- fams: 5
- fams: 0 / 6 / 18 / 1 / 2
- fams: Bypass / Isolate / Cached / Exception / NACached
-
- MMU okay: yes
-*/
-
-
-/*----------------------------------------------------------------------
- MMU
- ----------------------------------------------------------------------*/
-
-/*
- * General notes on MMU parameters.
- *
- * Terminology:
- * ASID = address-space ID (acts as an "extension" of virtual addresses)
- * VPN = virtual page number
- * PPN = physical page number
- * CA = encoded cache attribute (access modes)
- * TLB = translation look-aside buffer (term is stretched somewhat here)
- * I = instruction (fetch accesses)
- * D = data (load and store accesses)
- * way = each TLB (ITLB and DTLB) consists of a number of "ways"
- * that simultaneously match the virtual address of an access;
- * a TLB successfully translates a virtual address if exactly
- * one way matches the vaddr; if none match, it is a miss;
- * if multiple match, one gets a "multihit" exception;
- * each way can be independently configured in terms of number of
- * entries, page sizes, which fields are writable or constant, etc.
- * set = group of contiguous ways with exactly identical parameters
- * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE
- * from the page table and storing it in one of the auto-refill ways;
- * if this PTE load also misses, a miss exception is posted for s/w.
- * min-wired = a "min-wired" way can be used to map a single (minimum-sized)
- * page arbitrarily under program control; it has a single entry,
- * is non-auto-refill (some other way(s) must be auto-refill),
- * all its fields (VPN, PPN, ASID, CA) are all writable, and it
- * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current
- * restriction is that this be the only page size it supports).
- *
- * TLB way entries are virtually indexed.
- * TLB ways that support multiple page sizes:
- * - must have all writable VPN and PPN fields;
- * - can only use one page size at any given time (eg. setup at startup),
- * selected by the respective ITLBCFG or DTLBCFG special register,
- * whose bits n*4+3 .. n*4 index the list of page sizes for way n
- * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n);
- * this list may be sparse for auto-refill ways because auto-refill
- * ways have independent lists of supported page sizes sharing a
- * common encoding with PTE entries; the encoding is the index into
- * this list; unsupported sizes for a given way are zero in the list;
- * selecting unsupported sizes results in undefined hardware behaviour;
- * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition).
- */
-
-#define XCHAL_HAVE_CACHEATTR 0 /* 1 if CACHEATTR register present, 0 if TLBs present instead */
-#define XCHAL_HAVE_TLBS 1 /* 1 if TLBs present, 0 if CACHEATTR present instead */
-#define XCHAL_HAVE_MMU XCHAL_HAVE_TLBS /* (DEPRECATED; use XCHAL_HAVE_TLBS instead; will be removed in future release) */
-#define XCHAL_HAVE_SPANNING_WAY 0 /* 1 if single way maps entire virtual address space in I+D */
-#define XCHAL_HAVE_IDENTITY_MAP 0 /* 1 if virtual addr == physical addr always, 0 otherwise */
-#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* 1 if have MMU that mimics a CACHEATTR config (CaMMU) */
-#define XCHAL_HAVE_XLT_CACHEATTR 0 /* 1 if have MMU that mimics a CACHEATTR config, but with translation (CaXltMMU) */
-
-#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs (address space IDs) */
-#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */
-#define XCHAL_MMU_ASID_KERNEL 1 /* ASID value indicating kernel (ring 0) address space */
-#define XCHAL_MMU_RINGS 4 /* number of rings supported (1..4) */
-#define XCHAL_MMU_RING_BITS 2 /* number of bits needed to hold ring number */
-#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */
-#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */
-#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 12 /* max page size in a PTE structure (log2) */
-#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12 /* min page size in a PTE structure (log2) */
-
-
-/*** Instruction TLB: ***/
-
-#define XCHAL_ITLB_WAY_BITS 3 /* number of bits holding the ways */
-#define XCHAL_ITLB_WAYS 7 /* number of ways (n-way set-associative TLB) */
-#define XCHAL_ITLB_ARF_WAYS 4 /* number of auto-refill ways */
-#define XCHAL_ITLB_SETS 4 /* number of sets (groups of ways with identical settings) */
-
-/* Way set to which each way belongs: */
-#define XCHAL_ITLB_WAY0_SET 0
-#define XCHAL_ITLB_WAY1_SET 0
-#define XCHAL_ITLB_WAY2_SET 0
-#define XCHAL_ITLB_WAY3_SET 0
-#define XCHAL_ITLB_WAY4_SET 1
-#define XCHAL_ITLB_WAY5_SET 2
-#define XCHAL_ITLB_WAY6_SET 3
-
-/* Ways sets that are used by hardware auto-refill (ARF): */
-#define XCHAL_ITLB_ARF_SETS 1 /* number of auto-refill sets */
-#define XCHAL_ITLB_ARF_SET0 0 /* index of n'th auto-refill set */
-
-/* Way sets that are "min-wired" (see terminology comment above): */
-#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */
-
-
-/* ITLB way set 0 (group of ways 0 thru 3): */
-#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */
-#define XCHAL_ITLB_SET0_WAYS 4 /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/* ITLB way set 1 (group of ways 4 thru 4): */
-#define XCHAL_ITLB_SET1_WAY 4 /* index of first way in this way set */
-#define XCHAL_ITLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET1_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET1_PAGESIZES 4 /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET1_PAGESZ_BITS 2 /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET1_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/* ITLB way set 2 (group of ways 5 thru 5): */
-#define XCHAL_ITLB_SET2_WAY 5 /* index of first way in this way set */
-#define XCHAL_ITLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET2_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET2_ENTRIES 2 /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET2_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MAX 27 /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET2_PAGESZ_LOG2_LIST 27 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET2_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_VPN_CONSTMASK 0xF0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_PPN_CONSTMASK 0xF8000000 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/* Constant ASID values for each entry of ITLB way set 2 (because ASID_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET2_E0_ASID_CONST 0x01
-#define XCHAL_ITLB_SET2_E1_ASID_CONST 0x01
-/* Constant VPN values for each entry of ITLB way set 2 (because VPN_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET2_E0_VPN_CONST 0xD0000000
-#define XCHAL_ITLB_SET2_E1_VPN_CONST 0xD8000000
-/* Constant PPN values for each entry of ITLB way set 2 (because PPN_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET2_E0_PPN_CONST 0x00000000
-#define XCHAL_ITLB_SET2_E1_PPN_CONST 0x00000000
-/* Constant CA values for each entry of ITLB way set 2 (because CA_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET2_E0_CA_CONST 0x07
-#define XCHAL_ITLB_SET2_E1_CA_CONST 0x03
-
-/* ITLB way set 3 (group of ways 6 thru 6): */
-#define XCHAL_ITLB_SET3_WAY 6 /* index of first way in this way set */
-#define XCHAL_ITLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */
-#define XCHAL_ITLB_SET3_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
-#define XCHAL_ITLB_SET3_ENTRIES 2 /* number of entries in this way (always a power of 2) */
-#define XCHAL_ITLB_SET3_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_ITLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_ITLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */
-#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */
-#define XCHAL_ITLB_SET3_PAGESZ_LOG2_LIST 28 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_ITLB_SET3_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_VPN_CONSTMASK 0xE0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_PPN_CONSTMASK 0xF0000000 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
-#define XCHAL_ITLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_ITLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/* Constant ASID values for each entry of ITLB way set 3 (because ASID_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET3_E0_ASID_CONST 0x01
-#define XCHAL_ITLB_SET3_E1_ASID_CONST 0x01
-/* Constant VPN values for each entry of ITLB way set 3 (because VPN_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET3_E0_VPN_CONST 0xE0000000
-#define XCHAL_ITLB_SET3_E1_VPN_CONST 0xF0000000
-/* Constant PPN values for each entry of ITLB way set 3 (because PPN_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET3_E0_PPN_CONST 0xF0000000
-#define XCHAL_ITLB_SET3_E1_PPN_CONST 0xF0000000
-/* Constant CA values for each entry of ITLB way set 3 (because CA_CONSTMASK is non-zero): */
-#define XCHAL_ITLB_SET3_E0_CA_CONST 0x07
-#define XCHAL_ITLB_SET3_E1_CA_CONST 0x03
-
-/* Indexing macros: */
-#define _XCHAL_ITLB_SET(n,_what) XCHAL_ITLB_SET ## n ## _what
-#define XCHAL_ITLB_SET(n,what) _XCHAL_ITLB_SET(n, _ ## what )
-#define _XCHAL_ITLB_SET_E(n,i,_what) XCHAL_ITLB_SET ## n ## _E ## i ## _what
-#define XCHAL_ITLB_SET_E(n,i,what) _XCHAL_ITLB_SET_E(n,i, _ ## what )
-/*
- * Example use: XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES)
- * to get the value of XCHAL_ITLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
- */
-
-
-/*** Data TLB: ***/
-
-#define XCHAL_DTLB_WAY_BITS 4 /* number of bits holding the ways */
-#define XCHAL_DTLB_WAYS 10 /* number of ways (n-way set-associative TLB) */
-#define XCHAL_DTLB_ARF_WAYS 4 /* number of auto-refill ways */
-#define XCHAL_DTLB_SETS 5 /* number of sets (groups of ways with identical settings) */
-
-/* Way set to which each way belongs: */
-#define XCHAL_DTLB_WAY0_SET 0
-#define XCHAL_DTLB_WAY1_SET 0
-#define XCHAL_DTLB_WAY2_SET 0
-#define XCHAL_DTLB_WAY3_SET 0
-#define XCHAL_DTLB_WAY4_SET 1
-#define XCHAL_DTLB_WAY5_SET 2
-#define XCHAL_DTLB_WAY6_SET 3
-#define XCHAL_DTLB_WAY7_SET 4
-#define XCHAL_DTLB_WAY8_SET 4
-#define XCHAL_DTLB_WAY9_SET 4
-
-/* Ways sets that are used by hardware auto-refill (ARF): */
-#define XCHAL_DTLB_ARF_SETS 1 /* number of auto-refill sets */
-#define XCHAL_DTLB_ARF_SET0 0 /* index of n'th auto-refill set */
-
-/* Way sets that are "min-wired" (see terminology comment above): */
-#define XCHAL_DTLB_MINWIRED_SETS 1 /* number of "min-wired" sets */
-#define XCHAL_DTLB_MINWIRED_SET0 4 /* index of n'th "min-wired" set */
-
-
-/* DTLB way set 0 (group of ways 0 thru 3): */
-#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */
-#define XCHAL_DTLB_SET0_WAYS 4 /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/* DTLB way set 1 (group of ways 4 thru 4): */
-#define XCHAL_DTLB_SET1_WAY 4 /* index of first way in this way set */
-#define XCHAL_DTLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET1_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET1_PAGESIZES 4 /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET1_PAGESZ_BITS 2 /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET1_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/* DTLB way set 2 (group of ways 5 thru 5): */
-#define XCHAL_DTLB_SET2_WAY 5 /* index of first way in this way set */
-#define XCHAL_DTLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET2_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET2_ENTRIES 2 /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET2_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MAX 27 /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET2_PAGESZ_LOG2_LIST 27 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET2_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_VPN_CONSTMASK 0xF0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_PPN_CONSTMASK 0xF8000000 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/* Constant ASID values for each entry of DTLB way set 2 (because ASID_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET2_E0_ASID_CONST 0x01
-#define XCHAL_DTLB_SET2_E1_ASID_CONST 0x01
-/* Constant VPN values for each entry of DTLB way set 2 (because VPN_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET2_E0_VPN_CONST 0xD0000000
-#define XCHAL_DTLB_SET2_E1_VPN_CONST 0xD8000000
-/* Constant PPN values for each entry of DTLB way set 2 (because PPN_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET2_E0_PPN_CONST 0x00000000
-#define XCHAL_DTLB_SET2_E1_PPN_CONST 0x00000000
-/* Constant CA values for each entry of DTLB way set 2 (because CA_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET2_E0_CA_CONST 0x07
-#define XCHAL_DTLB_SET2_E1_CA_CONST 0x03
-
-/* DTLB way set 3 (group of ways 6 thru 6): */
-#define XCHAL_DTLB_SET3_WAY 6 /* index of first way in this way set */
-#define XCHAL_DTLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET3_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET3_ENTRIES 2 /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET3_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET3_PAGESZ_LOG2_LIST 28 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET3_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_VPN_CONSTMASK 0xE0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_PPN_CONSTMASK 0xF0000000 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-/* Constant ASID values for each entry of DTLB way set 3 (because ASID_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET3_E0_ASID_CONST 0x01
-#define XCHAL_DTLB_SET3_E1_ASID_CONST 0x01
-/* Constant VPN values for each entry of DTLB way set 3 (because VPN_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET3_E0_VPN_CONST 0xE0000000
-#define XCHAL_DTLB_SET3_E1_VPN_CONST 0xF0000000
-/* Constant PPN values for each entry of DTLB way set 3 (because PPN_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET3_E0_PPN_CONST 0xF0000000
-#define XCHAL_DTLB_SET3_E1_PPN_CONST 0xF0000000
-/* Constant CA values for each entry of DTLB way set 3 (because CA_CONSTMASK is non-zero): */
-#define XCHAL_DTLB_SET3_E0_CA_CONST 0x07
-#define XCHAL_DTLB_SET3_E1_CA_CONST 0x03
-
-/* DTLB way set 4 (group of ways 7 thru 9): */
-#define XCHAL_DTLB_SET4_WAY 7 /* index of first way in this way set */
-#define XCHAL_DTLB_SET4_WAYS 3 /* number of (contiguous) ways in this way set */
-#define XCHAL_DTLB_SET4_ENTRIES_LOG2 0 /* log2(number of entries in this way) */
-#define XCHAL_DTLB_SET4_ENTRIES 1 /* number of entries in this way (always a power of 2) */
-#define XCHAL_DTLB_SET4_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
-#define XCHAL_DTLB_SET4_PAGESIZES 1 /* number of supported page sizes in this way */
-#define XCHAL_DTLB_SET4_PAGESZ_BITS 0 /* number of bits to encode the page size */
-#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
-#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
-#define XCHAL_DTLB_SET4_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
- 2^PAGESZ_BITS entries in list, unsupported entries are zero */
-#define XCHAL_DTLB_SET4_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
-#define XCHAL_DTLB_SET4_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET4_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET4_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
-#define XCHAL_DTLB_SET4_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
-
-/* Indexing macros: */
-#define _XCHAL_DTLB_SET(n,_what) XCHAL_DTLB_SET ## n ## _what
-#define XCHAL_DTLB_SET(n,what) _XCHAL_DTLB_SET(n, _ ## what )
-#define _XCHAL_DTLB_SET_E(n,i,_what) XCHAL_DTLB_SET ## n ## _E ## i ## _what
-#define XCHAL_DTLB_SET_E(n,i,what) _XCHAL_DTLB_SET_E(n,i, _ ## what )
-/*
- * Example use: XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES)
- * to get the value of XCHAL_DTLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
- */
-
-
-/*
- * Determine whether we have a full MMU (with Page Table and Protection)
- * usable for an MMU-based OS:
- */
-#if XCHAL_HAVE_TLBS && !XCHAL_HAVE_SPANNING_WAY && XCHAL_ITLB_ARF_WAYS > 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2
-# define XCHAL_HAVE_PTP_MMU 1 /* have full MMU (with page table [autorefill] and protection) */
-#else
-# define XCHAL_HAVE_PTP_MMU 0 /* don't have full MMU */
-#endif
-
-/*
- * For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings:
- */
-#if XCHAL_HAVE_PTP_MMU
-#define XCHAL_KSEG_CACHED_VADDR 0xD0000000 /* virt.addr of kernel RAM cached static map */
-#define XCHAL_KSEG_CACHED_PADDR 0x00000000 /* phys.addr of kseg_cached */
-#define XCHAL_KSEG_CACHED_SIZE 0x08000000 /* size in bytes of kseg_cached (assumed power of 2!!!) */
-#define XCHAL_KSEG_BYPASS_VADDR 0xD8000000 /* virt.addr of kernel RAM bypass (uncached) static map */
-#define XCHAL_KSEG_BYPASS_PADDR 0x00000000 /* phys.addr of kseg_bypass */
-#define XCHAL_KSEG_BYPASS_SIZE 0x08000000 /* size in bytes of kseg_bypass (assumed power of 2!!!) */
-
-#define XCHAL_KIO_CACHED_VADDR 0xE0000000 /* virt.addr of kernel I/O cached static map */
-#define XCHAL_KIO_CACHED_PADDR 0xF0000000 /* phys.addr of kio_cached */
-#define XCHAL_KIO_CACHED_SIZE 0x10000000 /* size in bytes of kio_cached (assumed power of 2!!!) */
-#define XCHAL_KIO_BYPASS_VADDR 0xF0000000 /* virt.addr of kernel I/O bypass (uncached) static map */
-#define XCHAL_KIO_BYPASS_PADDR 0xF0000000 /* phys.addr of kio_bypass */
-#define XCHAL_KIO_BYPASS_SIZE 0x10000000 /* size in bytes of kio_bypass (assumed power of 2!!!) */
-
-#define XCHAL_SEG_MAPPABLE_VADDR 0x00000000 /* start of largest non-static-mapped virtual addr area */
-#define XCHAL_SEG_MAPPABLE_SIZE 0xD0000000 /* size in bytes of " */
-/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size. */
-#endif
-
-
-/*----------------------------------------------------------------------
- MISC
- ----------------------------------------------------------------------*/
-
-#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* number of write buffer entries */
-
-#define XCHAL_CORE_ID "linux_be" /* configuration's alphanumeric core identifier
- (CoreID) set in the Xtensa Processor Generator */
-
-#define XCHAL_BUILD_UNIQUE_ID 0x00003256 /* software build-unique ID (22-bit) */
-
-/* These definitions describe the hardware targeted by this software: */
-#define XCHAL_HW_CONFIGID0 0xC103D1FF /* config ID reg 0 value (upper 32 of 64 bits) */
-#define XCHAL_HW_CONFIGID1 0x00803256 /* config ID reg 1 value (lower 32 of 64 bits) */
-#define XCHAL_CONFIGID0 XCHAL_HW_CONFIGID0 /* for backward compatibility only -- don't use! */
-#define XCHAL_CONFIGID1 XCHAL_HW_CONFIGID1 /* for backward compatibility only -- don't use! */
-#define XCHAL_HW_RELEASE_MAJOR 1050 /* major release of targeted hardware */
-#define XCHAL_HW_RELEASE_MINOR 1 /* minor release of targeted hardware */
-#define XCHAL_HW_RELEASE_NAME "T1050.1" /* full release name of targeted hardware */
-#define XTHAL_HW_REL_T1050 1
-#define XTHAL_HW_REL_T1050_1 1
-#define XCHAL_HW_CONFIGID_RELIABLE 1
-
-
-/*
- * Miscellaneous special register fields:
- */
-
-
-/* DBREAKC (special register number 160): */
-#define XCHAL_DBREAKC_VALIDMASK 0xC000003F /* bits of DBREAKC that are defined */
-/* MASK field: */
-#define XCHAL_DBREAKC_MASK_BITS 6 /* number of bits in MASK field */
-#define XCHAL_DBREAKC_MASK_NUM 64 /* max number of possible causes (2^bits) */
-#define XCHAL_DBREAKC_MASK_SHIFT 0 /* position of MASK bits in DBREAKC, starting from lsbit */
-#define XCHAL_DBREAKC_MASK_MASK 0x0000003F /* mask of bits in MASK field of DBREAKC */
-/* LOADBREAK field: */
-#define XCHAL_DBREAKC_LOADBREAK_BITS 1 /* number of bits in LOADBREAK field */
-#define XCHAL_DBREAKC_LOADBREAK_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DBREAKC_LOADBREAK_SHIFT 30 /* position of LOADBREAK bits in DBREAKC, starting from lsbit */
-#define XCHAL_DBREAKC_LOADBREAK_MASK 0x40000000 /* mask of bits in LOADBREAK field of DBREAKC */
-/* STOREBREAK field: */
-#define XCHAL_DBREAKC_STOREBREAK_BITS 1 /* number of bits in STOREBREAK field */
-#define XCHAL_DBREAKC_STOREBREAK_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DBREAKC_STOREBREAK_SHIFT 31 /* position of STOREBREAK bits in DBREAKC, starting from lsbit */
-#define XCHAL_DBREAKC_STOREBREAK_MASK 0x80000000 /* mask of bits in STOREBREAK field of DBREAKC */
-
-/* PS (special register number 230): */
-#define XCHAL_PS_VALIDMASK 0x00070FFF /* bits of PS that are defined */
-/* INTLEVEL field: */
-#define XCHAL_PS_INTLEVEL_BITS 4 /* number of bits in INTLEVEL field */
-#define XCHAL_PS_INTLEVEL_NUM 16 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_INTLEVEL_SHIFT 0 /* position of INTLEVEL bits in PS, starting from lsbit */
-#define XCHAL_PS_INTLEVEL_MASK 0x0000000F /* mask of bits in INTLEVEL field of PS */
-/* EXCM field: */
-#define XCHAL_PS_EXCM_BITS 1 /* number of bits in EXCM field */
-#define XCHAL_PS_EXCM_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_EXCM_SHIFT 4 /* position of EXCM bits in PS, starting from lsbit */
-#define XCHAL_PS_EXCM_MASK 0x00000010 /* mask of bits in EXCM field of PS */
-/* PROGSTACK field: */
-#define XCHAL_PS_PROGSTACK_BITS 1 /* number of bits in PROGSTACK field */
-#define XCHAL_PS_PROGSTACK_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_PROGSTACK_SHIFT 5 /* position of PROGSTACK bits in PS, starting from lsbit */
-#define XCHAL_PS_PROGSTACK_MASK 0x00000020 /* mask of bits in PROGSTACK field of PS */
-/* RING field: */
-#define XCHAL_PS_RING_BITS 2 /* number of bits in RING field */
-#define XCHAL_PS_RING_NUM 4 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_RING_SHIFT 6 /* position of RING bits in PS, starting from lsbit */
-#define XCHAL_PS_RING_MASK 0x000000C0 /* mask of bits in RING field of PS */
-/* OWB field: */
-#define XCHAL_PS_OWB_BITS 4 /* number of bits in OWB field */
-#define XCHAL_PS_OWB_NUM 16 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_OWB_SHIFT 8 /* position of OWB bits in PS, starting from lsbit */
-#define XCHAL_PS_OWB_MASK 0x00000F00 /* mask of bits in OWB field of PS */
-/* CALLINC field: */
-#define XCHAL_PS_CALLINC_BITS 2 /* number of bits in CALLINC field */
-#define XCHAL_PS_CALLINC_NUM 4 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_CALLINC_SHIFT 16 /* position of CALLINC bits in PS, starting from lsbit */
-#define XCHAL_PS_CALLINC_MASK 0x00030000 /* mask of bits in CALLINC field of PS */
-/* WOE field: */
-#define XCHAL_PS_WOE_BITS 1 /* number of bits in WOE field */
-#define XCHAL_PS_WOE_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_PS_WOE_SHIFT 18 /* position of WOE bits in PS, starting from lsbit */
-#define XCHAL_PS_WOE_MASK 0x00040000 /* mask of bits in WOE field of PS */
-
-/* EXCCAUSE (special register number 232): */
-#define XCHAL_EXCCAUSE_VALIDMASK 0x0000003F /* bits of EXCCAUSE that are defined */
-/* EXCCAUSE field: */
-#define XCHAL_EXCCAUSE_BITS 6 /* number of bits in EXCCAUSE register */
-#define XCHAL_EXCCAUSE_NUM 64 /* max number of possible causes (2^bits) */
-#define XCHAL_EXCCAUSE_SHIFT 0 /* position of EXCCAUSE bits in register, starting from lsbit */
-#define XCHAL_EXCCAUSE_MASK 0x0000003F /* mask of bits in EXCCAUSE register */
-
-/* DEBUGCAUSE (special register number 233): */
-#define XCHAL_DEBUGCAUSE_VALIDMASK 0x0000003F /* bits of DEBUGCAUSE that are defined */
-/* ICOUNT field: */
-#define XCHAL_DEBUGCAUSE_ICOUNT_BITS 1 /* number of bits in ICOUNT field */
-#define XCHAL_DEBUGCAUSE_ICOUNT_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT 0 /* position of ICOUNT bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_ICOUNT_MASK 0x00000001 /* mask of bits in ICOUNT field of DEBUGCAUSE */
-/* IBREAK field: */
-#define XCHAL_DEBUGCAUSE_IBREAK_BITS 1 /* number of bits in IBREAK field */
-#define XCHAL_DEBUGCAUSE_IBREAK_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT 1 /* position of IBREAK bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_IBREAK_MASK 0x00000002 /* mask of bits in IBREAK field of DEBUGCAUSE */
-/* DBREAK field: */
-#define XCHAL_DEBUGCAUSE_DBREAK_BITS 1 /* number of bits in DBREAK field */
-#define XCHAL_DEBUGCAUSE_DBREAK_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT 2 /* position of DBREAK bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_DBREAK_MASK 0x00000004 /* mask of bits in DBREAK field of DEBUGCAUSE */
-/* BREAK field: */
-#define XCHAL_DEBUGCAUSE_BREAK_BITS 1 /* number of bits in BREAK field */
-#define XCHAL_DEBUGCAUSE_BREAK_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_BREAK_SHIFT 3 /* position of BREAK bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_BREAK_MASK 0x00000008 /* mask of bits in BREAK field of DEBUGCAUSE */
-/* BREAKN field: */
-#define XCHAL_DEBUGCAUSE_BREAKN_BITS 1 /* number of bits in BREAKN field */
-#define XCHAL_DEBUGCAUSE_BREAKN_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT 4 /* position of BREAKN bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_BREAKN_MASK 0x00000010 /* mask of bits in BREAKN field of DEBUGCAUSE */
-/* DEBUGINT field: */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS 1 /* number of bits in DEBUGINT field */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM 2 /* max number of possible causes (2^bits) */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT 5 /* position of DEBUGINT bits in DEBUGCAUSE, starting from lsbit */
-#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK 0x00000020 /* mask of bits in DEBUGINT field of DEBUGCAUSE */
-
-
-
-/*----------------------------------------------------------------------
- ISA
- ----------------------------------------------------------------------*/
-
-#define XCHAL_HAVE_DENSITY 1 /* 1 if density option configured, 0 otherwise */
-#define XCHAL_HAVE_LOOPS 1 /* 1 if zero-overhead loops option configured, 0 otherwise */
-/* Misc instructions: */
-#define XCHAL_HAVE_NSA 0 /* 1 if NSA/NSAU instructions option configured, 0 otherwise */
-#define XCHAL_HAVE_MINMAX 0 /* 1 if MIN/MAX instructions option configured, 0 otherwise */
-#define XCHAL_HAVE_SEXT 0 /* 1 if sign-extend instruction option configured, 0 otherwise */
-#define XCHAL_HAVE_CLAMPS 0 /* 1 if CLAMPS instruction option configured, 0 otherwise */
-#define XCHAL_HAVE_MAC16 0 /* 1 if MAC16 option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL16 0 /* 1 if 16-bit integer multiply option configured, 0 otherwise */
-/*#define XCHAL_HAVE_POPC 0*/ /* 1 if CRC instruction option configured, 0 otherwise */
-/*#define XCHAL_HAVE_CRC 0*/ /* 1 if POPC instruction option configured, 0 otherwise */
-
-#define XCHAL_HAVE_SPECULATION 0 /* 1 if speculation option configured, 0 otherwise */
-/*#define XCHAL_HAVE_MP_SYNC 0*/ /* 1 if multiprocessor sync. option configured, 0 otherwise */
-#define XCHAL_HAVE_PRID 0 /* 1 if processor ID register configured, 0 otherwise */
-
-#define XCHAL_NUM_MISC_REGS 2 /* number of miscellaneous registers (0..4) */
-
-/* These relate a bit more to TIE: */
-#define XCHAL_HAVE_BOOLEANS 0 /* 1 if booleans option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL32 0 /* 1 if 32-bit integer multiply option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL32_HIGH 0 /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
-#define XCHAL_HAVE_FP 0 /* 1 if floating point option configured, 0 otherwise */
-
-
-/*----------------------------------------------------------------------
- DERIVED
- ----------------------------------------------------------------------*/
-
-#if XCHAL_HAVE_BE
-#define XCHAL_INST_ILLN 0xD60F /* 2-byte illegal instruction, msb-first */
-#define XCHAL_INST_ILLN_BYTE0 0xD6 /* 2-byte illegal instruction, 1st byte */
-#define XCHAL_INST_ILLN_BYTE1 0x0F /* 2-byte illegal instruction, 2nd byte */
-#else
-#define XCHAL_INST_ILLN 0xF06D /* 2-byte illegal instruction, lsb-first */
-#define XCHAL_INST_ILLN_BYTE0 0x6D /* 2-byte illegal instruction, 1st byte */
-#define XCHAL_INST_ILLN_BYTE1 0xF0 /* 2-byte illegal instruction, 2nd byte */
-#endif
-/* Belongs in xtensa/hal.h: */
-#define XTHAL_INST_ILL 0x000000 /* 3-byte illegal instruction */
-
-
-/*
- * Because information as to exactly which hardware release is targeted
- * by a given software build is not always available, compile-time HAL
- * Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE):
- */
-#ifndef XCHAL_HW_RELEASE_MAJOR
-# define XCHAL_HW_CONFIGID_RELIABLE 0
-#endif
-#if XCHAL_HW_CONFIGID_RELIABLE
-# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) (XTHAL_REL_LE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
-# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) (XTHAL_REL_GE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
-# define XCHAL_HW_RELEASE_AT(major,minor) (XTHAL_REL_EQ( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
-# define XCHAL_HW_RELEASE_MAJOR_AT(major) ((XCHAL_HW_RELEASE_MAJOR == (major)) ? 1 : 0)
-#else
-# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) ( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \
- : ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \
- : XTHAL_MAYBE )
-# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) ( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \
- : (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \
- : XTHAL_MAYBE )
-# define XCHAL_HW_RELEASE_AT(major,minor) ( (((major) < 1040 && XCHAL_HAVE_XEA2) || \
- ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE)
-# define XCHAL_HW_RELEASE_MAJOR_AT(major) XCHAL_HW_RELEASE_AT(major,0)
-#endif
-
-/*
- * Specific errata:
- */
-
-/*
- * Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1;
- * relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled):
- */
-#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN (XCHAL_HAVE_XEA1 && \
- (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \
- || XCHAL_HW_RELEASE_AT(1050,0)))
-
-
-
-#endif /*XTENSA_CONFIG_CORE_H*/
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/defs.h b/include/asm-xtensa/xtensa/config-linux_be/defs.h
deleted file mode 100644
index f7c58b27337..00000000000
--- a/include/asm-xtensa/xtensa/config-linux_be/defs.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/* Definitions for Xtensa instructions, types, and protos. */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * 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 Lesser 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.
- */
-
-/* Do not modify. This is automatically generated.*/
-
-#ifndef _XTENSA_BASE_HEADER
-#define _XTENSA_BASE_HEADER
-
-#ifdef __XTENSA__
-#if defined(__GNUC__) && !defined(__XCC__)
-
-#define L8UI_ASM(arr, ars, imm) { \
- __asm__ volatile("l8ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L8UI(ars, imm) \
-({ \
- unsigned char _arr; \
- const unsigned char *_ars = ars; \
- L8UI_ASM(_arr, _ars, imm); \
- _arr; \
-})
-
-#define L16UI_ASM(arr, ars, imm) { \
- __asm__ volatile("l16ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L16UI(ars, imm) \
-({ \
- unsigned short _arr; \
- const unsigned short *_ars = ars; \
- L16UI_ASM(_arr, _ars, imm); \
- _arr; \
-})
-
-#define L16SI_ASM(arr, ars, imm) {\
- __asm__ volatile("l16si %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L16SI(ars, imm) \
-({ \
- signed short _arr; \
- const signed short *_ars = ars; \
- L16SI_ASM(_arr, _ars, imm); \
- _arr; \
-})
-
-#define L32I_ASM(arr, ars, imm) { \
- __asm__ volatile("l32i %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
-}
-
-#define XT_L32I(ars, imm) \
-({ \
- unsigned _arr; \
- const unsigned *_ars = ars; \
- L32I_ASM(_arr, _ars, imm); \
- _arr; \
-})
-
-#define S8I_ASM(arr, ars, imm) {\
- __asm__ volatile("s8i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
-}
-
-#define XT_S8I(arr, ars, imm) \
-({ \
- signed char _arr = arr; \
- const signed char *_ars = ars; \
- S8I_ASM(_arr, _ars, imm); \
-})
-
-#define S16I_ASM(arr, ars, imm) {\
- __asm__ volatile("s16i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
-}
-
-#define XT_S16I(arr, ars, imm) \
-({ \
- signed short _arr = arr; \
- const signed short *_ars = ars; \
- S16I_ASM(_arr, _ars, imm); \
-})
-
-#define S32I_ASM(arr, ars, imm) { \
- __asm__ volatile("s32i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
-}
-
-#define XT_S32I(arr, ars, imm) \
-({ \
- signed int _arr = arr; \
- const signed int *_ars = ars; \
- S32I_ASM(_arr, _ars, imm); \
-})
-
-#define ADDI_ASM(art, ars, imm) {\
- __asm__ ("addi %0, %1, %2" : "=a" (art) : "a" (ars), "i" (imm)); \
-}
-
-#define XT_ADDI(ars, imm) \
-({ \
- unsigned _art; \
- unsigned _ars = ars; \
- ADDI_ASM(_art, _ars, imm); \
- _art; \
-})
-
-#define ABS_ASM(arr, art) {\
- __asm__ ("abs %0, %1" : "=a" (arr) : "a" (art)); \
-}
-
-#define XT_ABS(art) \
-({ \
- unsigned _arr; \
- signed _art = art; \
- ABS_ASM(_arr, _art); \
- _arr; \
-})
-
-/* Note: In the following macros that reference SAR, the magic "state"
- register is used to capture the dependency on SAR. This is because
- SAR is a 5-bit register and thus there are no C types that can be
- used to represent it. It doesn't appear that the SAR register is
- even relevant to GCC, but it is marked as "clobbered" just in
- case. */
-
-#define SRC_ASM(arr, ars, art) {\
- register int _xt_sar __asm__ ("state"); \
- __asm__ ("src %0, %1, %2" \
- : "=a" (arr) : "a" (ars), "a" (art), "t" (_xt_sar)); \
-}
-
-#define XT_SRC(ars, art) \
-({ \
- unsigned _arr; \
- unsigned _ars = ars; \
- unsigned _art = art; \
- SRC_ASM(_arr, _ars, _art); \
- _arr; \
-})
-
-#define SSR_ASM(ars) {\
- register int _xt_sar __asm__ ("state"); \
- __asm__ ("ssr %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSR(ars) \
-({ \
- unsigned _ars = ars; \
- SSR_ASM(_ars); \
-})
-
-#define SSL_ASM(ars) {\
- register int _xt_sar __asm__ ("state"); \
- __asm__ ("ssl %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSL(ars) \
-({ \
- unsigned _ars = ars; \
- SSL_ASM(_ars); \
-})
-
-#define SSA8B_ASM(ars) {\
- register int _xt_sar __asm__ ("state"); \
- __asm__ ("ssa8b %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSA8B(ars) \
-({ \
- unsigned _ars = ars; \
- SSA8B_ASM(_ars); \
-})
-
-#define SSA8L_ASM(ars) {\
- register int _xt_sar __asm__ ("state"); \
- __asm__ ("ssa8l %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
-}
-
-#define XT_SSA8L(ars) \
-({ \
- unsigned _ars = ars; \
- SSA8L_ASM(_ars); \
-})
-
-#define SSAI_ASM(imm) {\
- register int _xt_sar __asm__ ("state"); \
- __asm__ ("ssai %1" : "=t" (_xt_sar) : "i" (imm) : "sar"); \
-}
-
-#define XT_SSAI(imm) \
-({ \
- SSAI_ASM(imm); \
-})
-
-
-
-
-
-
-
-
-#endif /* __GNUC__ && !__XCC__ */
-
-#ifdef __XCC__
-
-/* Core load/store instructions */
-extern unsigned char _TIE_L8UI(const unsigned char * ars, immediate imm);
-extern unsigned short _TIE_L16UI(const unsigned short * ars, immediate imm);
-extern signed short _TIE_L16SI(const signed short * ars, immediate imm);
-extern unsigned _TIE_L32I(const unsigned * ars, immediate imm);
-extern void _TIE_S8I(unsigned char arr, unsigned char * ars, immediate imm);
-extern void _TIE_S16I(unsigned short arr, unsigned short * ars, immediate imm);
-extern void _TIE_S32I(unsigned arr, unsigned * ars, immediate imm);
-
-#define XT_L8UI _TIE_L8UI
-#define XT_L16UI _TIE_L16UI
-#define XT_L16SI _TIE_L16SI
-#define XT_L32I _TIE_L32I
-#define XT_S8I _TIE_S8I
-#define XT_S16I _TIE_S16I
-#define XT_S32I _TIE_S32I
-
-/* Add-immediate instruction */
-extern unsigned _TIE_ADDI(unsigned ars, immediate imm);
-#define XT_ADDI _TIE_ADDI
-
-/* Absolute value instruction */
-extern unsigned _TIE_ABS(int art);
-#define XT_ABS _TIE_ABS
-
-/* funnel shift instructions */
-extern unsigned _TIE_SRC(unsigned ars, unsigned art);
-#define XT_SRC _TIE_SRC
-extern void _TIE_SSR(unsigned ars);
-#define XT_SSR _TIE_SSR
-extern void _TIE_SSL(unsigned ars);
-#define XT_SSL _TIE_SSL
-extern void _TIE_SSA8B(unsigned ars);
-#define XT_SSA8B _TIE_SSA8B
-extern void _TIE_SSA8L(unsigned ars);
-#define XT_SSA8L _TIE_SSA8L
-extern void _TIE_SSAI(immediate imm);
-#define XT_SSAI _TIE_SSAI
-
-
-#endif /* __XCC__ */
-
-#endif /* __XTENSA__ */
-#endif /* !_XTENSA_BASE_HEADER */
diff --git a/include/asm-xtensa/xtensa/config-linux_be/specreg.h b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
deleted file mode 100644
index fa4106aa9a0..00000000000
--- a/include/asm-xtensa/xtensa/config-linux_be/specreg.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Xtensa Special Register symbolic names
- */
-
-/* $Id: specreg.h,v 1.2 2003/03/07 19:15:18 joetaylor Exp $ */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * 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 Lesser 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.
- */
-
-#ifndef XTENSA_SPECREG_H
-#define XTENSA_SPECREG_H
-
-/* Include these special register bitfield definitions, for historical reasons: */
-#include <xtensa/corebits.h>
-
-
-/* Special registers: */
-#define LBEG 0
-#define LEND 1
-#define LCOUNT 2
-#define SAR 3
-#define WINDOWBASE 72
-#define WINDOWSTART 73
-#define PTEVADDR 83
-#define RASID 90
-#define ITLBCFG 91
-#define DTLBCFG 92
-#define IBREAKENABLE 96
-#define DDR 104
-#define IBREAKA_0 128
-#define IBREAKA_1 129
-#define DBREAKA_0 144
-#define DBREAKA_1 145
-#define DBREAKC_0 160
-#define DBREAKC_1 161
-#define EPC_1 177
-#define EPC_2 178
-#define EPC_3 179
-#define EPC_4 180
-#define DEPC 192
-#define EPS_2 194
-#define EPS_3 195
-#define EPS_4 196
-#define EXCSAVE_1 209
-#define EXCSAVE_2 210
-#define EXCSAVE_3 211
-#define EXCSAVE_4 212
-#define INTERRUPT 226
-#define INTENABLE 228
-#define PS 230
-#define EXCCAUSE 232
-#define DEBUGCAUSE 233
-#define CCOUNT 234
-#define ICOUNT 236
-#define ICOUNTLEVEL 237
-#define EXCVADDR 238
-#define CCOMPARE_0 240
-#define CCOMPARE_1 241
-#define CCOMPARE_2 242
-#define MISC_REG_0 244
-#define MISC_REG_1 245
-
-/* Special cases (bases of special register series): */
-#define IBREAKA 128
-#define DBREAKA 144
-#define DBREAKC 160
-#define EPC 176
-#define EPS 192
-#define EXCSAVE 208
-#define CCOMPARE 240
-
-/* Special names for read-only and write-only interrupt registers: */
-#define INTREAD 226
-#define INTSET 226
-#define INTCLEAR 227
-
-#endif /* XTENSA_SPECREG_H */
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/system.h b/include/asm-xtensa/xtensa/config-linux_be/system.h
deleted file mode 100644
index cf9d4d308e3..00000000000
--- a/include/asm-xtensa/xtensa/config-linux_be/system.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration
- *
- * NOTE: The location and contents of this file are highly subject to change.
- *
- * Source for configuration-independent binaries (which link in a
- * configuration-specific HAL library) must NEVER include this file.
- * The HAL itself has historically included this file in some instances,
- * but this is not appropriate either, because the HAL is meant to be
- * core-specific but system independent.
- */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * 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 Lesser 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.
- */
-
-
-#ifndef XTENSA_CONFIG_SYSTEM_H
-#define XTENSA_CONFIG_SYSTEM_H
-
-/*#include <xtensa/hal.h>*/
-
-
-
-/*----------------------------------------------------------------------
- DEVICE ADDRESSES
- ----------------------------------------------------------------------*/
-
-/*
- * Strange place to find these, but the configuration GUI
- * allows moving these around to account for various core
- * configurations. Specific boards (and their BSP software)
- * will have specific meanings for these components.
- */
-
-/* I/O Block areas: */
-#define XSHAL_IOBLOCK_CACHED_VADDR 0xE0000000
-#define XSHAL_IOBLOCK_CACHED_PADDR 0xF0000000
-#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000
-
-#define XSHAL_IOBLOCK_BYPASS_VADDR 0xF0000000
-#define XSHAL_IOBLOCK_BYPASS_PADDR 0xF0000000
-#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000
-
-/* System ROM: */
-#define XSHAL_ROM_VADDR 0xEE000000
-#define XSHAL_ROM_PADDR 0xFE000000
-#define XSHAL_ROM_SIZE 0x00400000
-/* Largest available area (free of vectors): */
-#define XSHAL_ROM_AVAIL_VADDR 0xEE00052C
-#define XSHAL_ROM_AVAIL_VSIZE 0x003FFAD4
-
-/* System RAM: */
-#define XSHAL_RAM_VADDR 0xD0000000
-#define XSHAL_RAM_PADDR 0x00000000
-#define XSHAL_RAM_VSIZE 0x08000000
-#define XSHAL_RAM_PSIZE 0x10000000
-#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE
-/* Largest available area (free of vectors): */
-#define XSHAL_RAM_AVAIL_VADDR 0xD0000370
-#define XSHAL_RAM_AVAIL_VSIZE 0x07FFFC90
-
-/*
- * Shadow system RAM (same device as system RAM, at different address).
- * (Emulation boards need this for the SONIC Ethernet driver
- * when data caches are configured for writeback mode.)
- * NOTE: on full MMU configs, this points to the BYPASS virtual address
- * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual
- * addresses are viewed through the BYPASS static map rather than
- * the CACHED static map.
- */
-#define XSHAL_RAM_BYPASS_VADDR 0xD8000000
-#define XSHAL_RAM_BYPASS_PADDR 0x00000000
-#define XSHAL_RAM_BYPASS_PSIZE 0x08000000
-
-/* Alternate system RAM (different device than system RAM): */
-#define XSHAL_ALTRAM_VADDR 0xCEE00000
-#define XSHAL_ALTRAM_PADDR 0xC0000000
-#define XSHAL_ALTRAM_SIZE 0x00200000
-
-
-/*----------------------------------------------------------------------
- * DEVICE-ADDRESS DEPENDENT...
- *
- * Values written to CACHEATTR special register (or its equivalent)
- * to enable and disable caches in various modes.
- *----------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------
- BACKWARD COMPATIBILITY ...
- ----------------------------------------------------------------------*/
-
-/*
- * NOTE: the following two macros are DEPRECATED. Use the latter
- * board-specific macros instead, which are specially tuned for the
- * particular target environments' memory maps.
- */
-#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */
-#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */
-
-/*----------------------------------------------------------------------
- ISS (Instruction Set Simulator) SPECIFIC ...
- ----------------------------------------------------------------------*/
-
-#define XSHAL_ISS_CACHEATTR_WRITEBACK 0x1122222F /* enable caches in write-back mode */
-#define XSHAL_ISS_CACHEATTR_WRITEALLOC 0x1122222F /* enable caches in write-allocate mode */
-#define XSHAL_ISS_CACHEATTR_WRITETHRU 0x1122222F /* enable caches in write-through mode */
-#define XSHAL_ISS_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */
-#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_WRITEBACK /* default setting to enable caches */
-
-/* For Coware only: */
-#define XSHAL_COWARE_CACHEATTR_WRITEBACK 0x11222222 /* enable caches in write-back mode */
-#define XSHAL_COWARE_CACHEATTR_WRITEALLOC 0x11222222 /* enable caches in write-allocate mode */
-#define XSHAL_COWARE_CACHEATTR_WRITETHRU 0x11222222 /* enable caches in write-through mode */
-#define XSHAL_COWARE_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */
-#define XSHAL_COWARE_CACHEATTR_DEFAULT XSHAL_COWARE_CACHEATTR_WRITEBACK /* default setting to enable caches */
-
-/* For BFM and other purposes: */
-#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x11222222 /* enable caches without any invalid regions */
-#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting for caches without any invalid regions */
-
-#define XSHAL_ISS_PIPE_REGIONS 0
-#define XSHAL_ISS_SDRAM_REGIONS 0
-
-
-/*----------------------------------------------------------------------
- XT2000 BOARD SPECIFIC ...
- ----------------------------------------------------------------------*/
-
-#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x22FFFFFF /* enable caches in write-back mode */
-#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x22FFFFFF /* enable caches in write-allocate mode */
-#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x22FFFFFF /* enable caches in write-through mode */
-#define XSHAL_XT2000_CACHEATTR_BYPASS 0x22FFFFFF /* disable caches in bypass mode */
-#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */
-
-#define XSHAL_XT2000_PIPE_REGIONS 0x00001000 /* BusInt pipeline regions */
-#define XSHAL_XT2000_SDRAM_REGIONS 0x00000005 /* BusInt SDRAM regions */
-
-
-/*----------------------------------------------------------------------
- VECTOR SIZES
- ----------------------------------------------------------------------*/
-
-/*
- * Sizes allocated to vectors by the system (memory map) configuration.
- * These sizes are constrained by core configuration (eg. one vector's
- * code cannot overflow into another vector) but are dependent on the
- * system or board (or LSP) memory map configuration.
- *
- * Whether or not each vector happens to be in a system ROM is also
- * a system configuration matter, sometimes useful, included here also:
- */
-#define XSHAL_RESET_VECTOR_SIZE 0x000004E0
-#define XSHAL_RESET_VECTOR_ISROM 1
-#define XSHAL_USER_VECTOR_SIZE 0x0000001C
-#define XSHAL_USER_VECTOR_ISROM 0
-#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */
-#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */
-#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C
-#define XSHAL_KERNEL_VECTOR_ISROM 0
-#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */
-#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */
-#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x000000E0
-#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0
-#define XSHAL_WINDOW_VECTORS_SIZE 0x00000180
-#define XSHAL_WINDOW_VECTORS_ISROM 0
-#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000000C
-#define XSHAL_INTLEVEL2_VECTOR_ISROM 0
-#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000000C
-#define XSHAL_INTLEVEL3_VECTOR_ISROM 0
-#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000000C
-#define XSHAL_INTLEVEL4_VECTOR_ISROM 1
-#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL4_VECTOR_SIZE
-#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL4_VECTOR_ISROM
-
-
-#endif /*XTENSA_CONFIG_SYSTEM_H*/
-
diff --git a/include/asm-xtensa/xtensa/config-linux_be/tie.h b/include/asm-xtensa/xtensa/config-linux_be/tie.h
deleted file mode 100644
index 3c2e514602f..00000000000
--- a/include/asm-xtensa/xtensa/config-linux_be/tie.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * xtensa/config/tie.h -- HAL definitions that are dependent on CORE and TIE configuration
- *
- * This header file is sometimes referred to as the "compile-time HAL" or CHAL.
- * It was generated for a specific Xtensa processor configuration,
- * and furthermore for a specific set of TIE source files that extend
- * basic core functionality.
- *
- * Source for configuration-independent binaries (which link in a
- * configuration-specific HAL library) must NEVER include this file.
- * It is perfectly normal, however, for the HAL source itself to include this file.
- */
-
-/*
- * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2.1 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * 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 Lesser 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.
- */
-
-
-#ifndef XTENSA_CONFIG_TIE_H
-#define XTENSA_CONFIG_TIE_H
-
-#include <xtensa/hal.h>
-
-
-/*----------------------------------------------------------------------
- GENERAL
- ----------------------------------------------------------------------*/
-
-/*
- * Separators for macros that expand into arrays.
- * These can be predefined by files that #include this one,
- * when different separators are required.
- */
-/* Element separator for macros that expand into 1-dimensional arrays: */
-#ifndef XCHAL_SEP
-#define XCHAL_SEP ,
-#endif
-/* Array separator for macros that expand into 2-dimensional arrays: */
-#ifndef XCHAL_SEP2
-#define XCHAL_SEP2 },{
-#endif
-
-
-
-
-
-
-/*----------------------------------------------------------------------
- COPROCESSORS and EXTRA STATE
- ----------------------------------------------------------------------*/
-
-#define XCHAL_CP_NUM 0 /* number of coprocessors */
-#define XCHAL_CP_MAX 0 /* max coprocessor id plus one (0 if none) */
-#define XCHAL_CP_MASK 0x00 /* bitmask of coprocessors by id */
-
-/* Space for coprocessors' state save areas: */
-#define XCHAL_CP0_SA_SIZE 0
-#define XCHAL_CP1_SA_SIZE 0
-#define XCHAL_CP2_SA_SIZE 0
-#define XCHAL_CP3_SA_SIZE 0
-#define XCHAL_CP4_SA_SIZE 0
-#define XCHAL_CP5_SA_SIZE 0
-#define XCHAL_CP6_SA_SIZE 0
-#define XCHAL_CP7_SA_SIZE 0
-/* Minimum required alignments of CP state save areas: */
-#define XCHAL_CP0_SA_ALIGN 1
-#define XCHAL_CP1_SA_ALIGN 1
-#define XCHAL_CP2_SA_ALIGN 1
-#define XCHAL_CP3_SA_ALIGN 1
-#define XCHAL_CP4_SA_ALIGN 1
-#define XCHAL_CP5_SA_ALIGN 1
-#define XCHAL_CP6_SA_ALIGN 1
-#define XCHAL_CP7_SA_ALIGN 1
-
-/* Indexing macros: */
-#define _XCHAL_CP_SA_SIZE(n) XCHAL_CP ## n ## _SA_SIZE
-#define XCHAL_CP_SA_SIZE(n) _XCHAL_CP_SA_SIZE(n) /* n = 0 .. 7 */
-#define _XCHAL_CP_SA_ALIGN(n) XCHAL_CP ## n ## _SA_ALIGN
-#define XCHAL_CP_SA_ALIGN(n) _XCHAL_CP_SA_ALIGN(n) /* n = 0 .. 7 */
-
-
-/* Space for "extra" state (user special registers and non-cp TIE) save area: */
-#define XCHAL_EXTRA_SA_SIZE 0
-#define XCHAL_EXTRA_SA_ALIGN 1
-
-/* Total save area size (extra + all coprocessors) */
-/* (not useful until xthal_{save,restore}_all_extra() is implemented, */
-/* but included for Tor2 beta; doesn't account for alignment!): */
-#define XCHAL_CPEXTRA_SA_SIZE_TOR2 0 /* Tor2Beta temporary definition -- do not use */
-
-/* Combined required alignment for all CP and EXTRA state save areas */
-/* (does not include required alignment for any base config registers): */
-#define XCHAL_CPEXTRA_SA_ALIGN 1
-
-/* ... */
-
-
-#ifdef _ASMLANGUAGE
-/*
- * Assembly-language specific definitions (assembly macros, etc.).
- */
-#include <xtensa/config/specreg.h>
-
-/********************
- * Macros to save and restore the non-coprocessor TIE portion of EXTRA state.
- */
-
-/* (none) */
-
-
-/********************
- * Macros to create functions that save and restore all EXTRA (non-coprocessor) state
- * (does not include zero-overhead loop registers and non-optional registers).
- */
-
- /*
- * Macro that expands to the body of a function that
- * stores the extra (non-coprocessor) optional/custom state.
- * Entry: a2 = ptr to save area in which to save extra state
- * Exit: any register a2-a15 (?) may have been clobbered.
- */
- .macro xchal_extra_store_funcbody
- .endm
-
-
- /*
- * Macro that expands to the body of a function that
- * loads the extra (non-coprocessor) optional/custom state.
- * Entry: a2 = ptr to save area from which to restore extra state
- * Exit: any register a2-a15 (?) may have been clobbered.
- */
- .macro xchal_extra_load_funcbody
- .endm
-
-
-/********************
- * Macros to save and restore the state of each TIE coprocessor.
- */
-
-
-
-/********************
- * Macros to create functions that save and restore the state of *any* TIE coprocessor.
- */
-
- /*
- * Macro that expands to the body of a function
- * that stores the selected coprocessor's state (registers etc).
- * Entry: a2 = ptr to save area in which to save cp state
- * a3 = coprocessor number
- * Exit: any register a2-a15 (?) may have been clobbered.
- */
- .macro xchal_cpi_store_funcbody
- .endm
-
-
- /*
- * Macro that expands to the body of a function
- * that loads the selected coprocessor's state (registers etc).
- * Entry: a2 = ptr to save area from which to restore cp state
- * a3 = coprocessor number
- * Exit: any register a2-a15 (?) may have been clobbered.
- */
- .macro xchal_cpi_load_funcbody
- .endm
-
-#endif /*_ASMLANGUAGE*/
-
-
-/*
- * Contents of save areas in terms of libdb register numbers.
- * NOTE: CONTENTS_LIBDB_{UREG,REGF} macros are not defined in this file;
- * it is up to the user of this header file to define these macros
- * usefully before each expansion of the CONTENTS_LIBDB macros.
- * (Fields rsv[123] are reserved for future additions; they are currently
- * set to zero but may be set to some useful values in the future.)
- *
- * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, bitmask, rsv2, rsv3)
- * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, bitmask, rsv2, rsv3)
- * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, numentries, contentsize, regname_base, regfile_name, rsv2, rsv3)
- */
-
-#define XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_EXTRA_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP0_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP1_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP2_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP3_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP4_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP5_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP6_SA_CONTENTS_LIBDB /* empty */
-
-#define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM 0
-#define XCHAL_CP7_SA_CONTENTS_LIBDB /* empty */
-
-
-
-
-
-
-/*----------------------------------------------------------------------
- MISC
- ----------------------------------------------------------------------*/
-
-#if 0 /* is there something equivalent for user TIE? */
-#define XCHAL_CORE_ID "linux_be" /* configuration's alphanumeric core identifier
- (CoreID) set in the Xtensa Processor Generator */
-
-#define XCHAL_BUILD_UNIQUE_ID 0x00003256 /* software build-unique ID (22-bit) */
-
-/* These definitions describe the hardware targeted by this software: */
-#define XCHAL_HW_CONFIGID0 0xC103D1FF /* config ID reg 0 value (upper 32 of 64 bits) */
-#define XCHAL_HW_CONFIGID1 0x00803256 /* config ID reg 1 value (lower 32 of 64 bits) */
-#define XCHAL_CONFIGID0 XCHAL_HW_CONFIGID0 /* for backward compatibility only -- don't use! */
-#define XCHAL_CONFIGID1 XCHAL_HW_CONFIGID1 /* for backward compatibility only -- don't use! */
-#define XCHAL_HW_RELEASE_MAJOR 1050 /* major release of targeted hardware */
-#define XCHAL_HW_RELEASE_MINOR 1 /* minor release of targeted hardware */
-#define XCHAL_HW_RELEASE_NAME "T1050.1" /* full release name of targeted hardware */
-#define XTHAL_HW_REL_T1050 1
-#define XTHAL_HW_REL_T1050_1 1
-#define XCHAL_HW_CONFIGID_RELIABLE 1
-#endif /*0*/
-
-
-
-/*----------------------------------------------------------------------
- ISA
- ----------------------------------------------------------------------*/
-
-#if 0 /* these probably don't belong here, but are related to or implemented using TIE */
-#define XCHAL_HAVE_BOOLEANS 0 /* 1 if booleans option configured, 0 otherwise */
-/* Misc instructions: */
-#define XCHAL_HAVE_MUL32 0 /* 1 if 32-bit integer multiply option configured, 0 otherwise */
-#define XCHAL_HAVE_MUL32_HIGH 0 /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
-
-#define XCHAL_HAVE_FP 0 /* 1 if floating point option configured, 0 otherwise */
-#endif /*0*/
-
-
-#endif /*XTENSA_CONFIG_TIE_H*/
-
diff --git a/include/asm-xtensa/xtensa/coreasm.h b/include/asm-xtensa/xtensa/coreasm.h
deleted file mode 100644
index a8cfb54c20a..00000000000
--- a/include/asm-xtensa/xtensa/coreasm.h
+++ /dev/null
@@ -1,526 +0,0 @@
-#ifndef XTENSA_COREASM_H
-#define XTENSA_COREASM_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/coreasm.h -- assembler-specific
- * definitions that depend on CORE configuration.
- *
- * Source for configuration-independent binaries (which link in a
- * configuration-specific HAL library) must NEVER include this file.
- * It is perfectly normal, however, for the HAL itself to include this
- * file.
- *
- * This file must NOT include xtensa/config/system.h. Any assembler
- * header file that depends on system information should likely go in
- * a new systemasm.h (or sysasm.h) header file.
- *
- * NOTE: macro beqi32 is NOT configuration-dependent, and is placed
- * here til we will have configuration-independent header file.
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/config/core.h>
-#include <xtensa/config/specreg.h>
-
-/*
- * Assembly-language specific definitions (assembly macros, etc.).
- */
-
-/*----------------------------------------------------------------------
- * find_ms_setbit
- *
- * This macro finds the most significant bit that is set in <as>
- * and return its index + <base> in <ad>, or <base> - 1 if <as> is zero.
- * The index counts starting at zero for the lsbit, so the return
- * value ranges from <base>-1 (no bit set) to <base>+31 (msbit set).
- *
- * Parameters:
- * <ad> destination address register (any register)
- * <as> source address register
- * <at> temporary address register (must be different than <as>)
- * <base> constant value added to result (usually 0 or 1)
- * On entry:
- * <ad> = undefined if different than <as>
- * <as> = value whose most significant set bit is to be found
- * <at> = undefined
- * no other registers are used by this macro.
- * On exit:
- * <ad> = <base> + index of msbit set in original <as>,
- * = <base> - 1 if original <as> was zero.
- * <as> clobbered (if not <ad>)
- * <at> clobbered (if not <ad>)
- * Example:
- * find_ms_setbit a0, a4, a0, 0 -- return in a0 index of msbit set in a4
- */
-
- .macro find_ms_setbit ad, as, at, base
-#if XCHAL_HAVE_NSA
- movi \at, 31+\base
- nsau \as, \as // get index of \as, numbered from msbit (32 if absent)
- sub \ad, \at, \as // get numbering from lsbit (0..31, -1 if absent)
-#else /* XCHAL_HAVE_NSA */
- movi \at, \base // start with result of 0 (point to lsbit of 32)
-
- beqz \as, 2f // special case for zero argument: return -1
- bltui \as, 0x10000, 1f // is it one of the 16 lsbits? (if so, check lower 16 bits)
- addi \at, \at, 16 // no, increment result to upper 16 bits (of 32)
- //srli \as, \as, 16 // check upper half (shift right 16 bits)
- extui \as, \as, 16, 16 // check upper half (shift right 16 bits)
-1: bltui \as, 0x100, 1f // is it one of the 8 lsbits? (if so, check lower 8 bits)
- addi \at, \at, 8 // no, increment result to upper 8 bits (of 16)
- srli \as, \as, 8 // shift right to check upper 8 bits
-1: bltui \as, 0x10, 1f // is it one of the 4 lsbits? (if so, check lower 4 bits)
- addi \at, \at, 4 // no, increment result to upper 4 bits (of 8)
- srli \as, \as, 4 // shift right 4 bits to check upper half
-1: bltui \as, 0x4, 1f // is it one of the 2 lsbits? (if so, check lower 2 bits)
- addi \at, \at, 2 // no, increment result to upper 2 bits (of 4)
- srli \as, \as, 2 // shift right 2 bits to check upper half
-1: bltui \as, 0x2, 1f // is it the lsbit?
- addi \at, \at, 2 // no, increment result to upper bit (of 2)
-2: addi \at, \at, -1 // (from just above: add 1; from beqz: return -1)
- //srli \as, \as, 1
-1: // done! \at contains index of msbit set (or -1 if none set)
- .if 0x\ad - 0x\at // destination different than \at ? (works because regs are a0-a15)
- mov \ad, \at // then move result to \ad
- .endif
-#endif /* XCHAL_HAVE_NSA */
- .endm // find_ms_setbit
-
-/*----------------------------------------------------------------------
- * find_ls_setbit
- *
- * This macro finds the least significant bit that is set in <as>,
- * and return its index in <ad>.
- * Usage is the same as for the find_ms_setbit macro.
- * Example:
- * find_ls_setbit a0, a4, a0, 0 -- return in a0 index of lsbit set in a4
- */
-
- .macro find_ls_setbit ad, as, at, base
- neg \at, \as // keep only the least-significant bit that is set...
- and \as, \at, \as // ... in \as
- find_ms_setbit \ad, \as, \at, \base
- .endm // find_ls_setbit
-
-/*----------------------------------------------------------------------
- * find_ls_one
- *
- * Same as find_ls_setbit with base zero.
- * Source (as) and destination (ad) registers must be different.
- * Provided for backward compatibility.
- */
-
- .macro find_ls_one ad, as
- find_ls_setbit \ad, \as, \ad, 0
- .endm // find_ls_one
-
-/*----------------------------------------------------------------------
- * floop, floopnez, floopgtz, floopend
- *
- * These macros are used for fast inner loops that
- * work whether or not the Loops options is configured.
- * If the Loops option is configured, they simply use
- * the zero-overhead LOOP instructions; otherwise
- * they use explicit decrement and branch instructions.
- *
- * They are used in pairs, with floop, floopnez or floopgtz
- * at the beginning of the loop, and floopend at the end.
- *
- * Each pair of loop macro calls must be given the loop count
- * address register and a unique label for that loop.
- *
- * Example:
- *
- * movi a3, 16 // loop 16 times
- * floop a3, myloop1
- * :
- * bnez a7, end1 // exit loop if a7 != 0
- * :
- * floopend a3, myloop1
- * end1:
- *
- * Like the LOOP instructions, these macros cannot be
- * nested, must include at least one instruction,
- * cannot call functions inside the loop, etc.
- * The loop can be exited by jumping to the instruction
- * following floopend (or elsewhere outside the loop),
- * or continued by jumping to a NOP instruction placed
- * immediately before floopend.
- *
- * Unlike LOOP instructions, the register passed to floop*
- * cannot be used inside the loop, because it is used as
- * the loop counter if the Loops option is not configured.
- * And its value is undefined after exiting the loop.
- * And because the loop counter register is active inside
- * the loop, you can't easily use this construct to loop
- * across a register file using ROTW as you might with LOOP
- * instructions, unless you copy the loop register along.
- */
-
- /* Named label version of the macros: */
-
- .macro floop ar, endlabel
- floop_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
- .endm
-
- .macro floopnez ar, endlabel
- floopnez_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
- .endm
-
- .macro floopgtz ar, endlabel
- floopgtz_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
- .endm
-
- .macro floopend ar, endlabel
- floopend_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
- .endm
-
- /* Numbered local label version of the macros: */
-#if 0 /*UNTESTED*/
- .macro floop89 ar
- floop_ \ar, 8, 9f
- .endm
-
- .macro floopnez89 ar
- floopnez_ \ar, 8, 9f
- .endm
-
- .macro floopgtz89 ar
- floopgtz_ \ar, 8, 9f
- .endm
-
- .macro floopend89 ar
- floopend_ \ar, 8b, 9
- .endm
-#endif /*0*/
-
- /* Underlying version of the macros: */
-
- .macro floop_ ar, startlabel, endlabelref
- .ifdef _infloop_
- .if _infloop_
- .err // Error: floop cannot be nested
- .endif
- .endif
- .set _infloop_, 1
-#if XCHAL_HAVE_LOOPS
- loop \ar, \endlabelref
-#else /* XCHAL_HAVE_LOOPS */
-\startlabel:
- addi \ar, \ar, -1
-#endif /* XCHAL_HAVE_LOOPS */
- .endm // floop_
-
- .macro floopnez_ ar, startlabel, endlabelref
- .ifdef _infloop_
- .if _infloop_
- .err // Error: floopnez cannot be nested
- .endif
- .endif
- .set _infloop_, 1
-#if XCHAL_HAVE_LOOPS
- loopnez \ar, \endlabelref
-#else /* XCHAL_HAVE_LOOPS */
- beqz \ar, \endlabelref
-\startlabel:
- addi \ar, \ar, -1
-#endif /* XCHAL_HAVE_LOOPS */
- .endm // floopnez_
-
- .macro floopgtz_ ar, startlabel, endlabelref
- .ifdef _infloop_
- .if _infloop_
- .err // Error: floopgtz cannot be nested
- .endif
- .endif
- .set _infloop_, 1
-#if XCHAL_HAVE_LOOPS
- loopgtz \ar, \endlabelref
-#else /* XCHAL_HAVE_LOOPS */
- bltz \ar, \endlabelref
- beqz \ar, \endlabelref
-\startlabel:
- addi \ar, \ar, -1
-#endif /* XCHAL_HAVE_LOOPS */
- .endm // floopgtz_
-
-
- .macro floopend_ ar, startlabelref, endlabel
- .ifndef _infloop_
- .err // Error: floopend without matching floopXXX
- .endif
- .ifeq _infloop_
- .err // Error: floopend without matching floopXXX
- .endif
- .set _infloop_, 0
-#if ! XCHAL_HAVE_LOOPS
- bnez \ar, \startlabelref
-#endif /* XCHAL_HAVE_LOOPS */
-\endlabel:
- .endm // floopend_
-
-/*----------------------------------------------------------------------
- * crsil -- conditional RSIL (read/set interrupt level)
- *
- * Executes the RSIL instruction if it exists, else just reads PS.
- * The RSIL instruction does not exist in the new exception architecture
- * if the interrupt option is not selected.
- */
-
- .macro crsil ar, newlevel
-#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS
- rsil \ar, \newlevel
-#else
- rsr \ar, PS
-#endif
- .endm // crsil
-
-/*----------------------------------------------------------------------
- * window_spill{4,8,12}
- *
- * These macros spill callers' register windows to the stack.
- * They work for both privileged and non-privileged tasks.
- * Must be called from a windowed ABI context, eg. within
- * a windowed ABI function (ie. valid stack frame, window
- * exceptions enabled, not in exception mode, etc).
- *
- * This macro requires a single invocation of the window_spill_common
- * macro in the same assembly unit and section.
- *
- * Note that using window_spill{4,8,12} macros is more efficient
- * than calling a function implemented using window_spill_function,
- * because the latter needs extra code to figure out the size of
- * the call to the spilling function.
- *
- * Example usage:
- *
- * .text
- * .align 4
- * .global some_function
- * .type some_function,@function
- * some_function:
- * entry a1, 16
- * :
- * :
- *
- * window_spill4 // spill windows of some_function's callers; preserves a0..a3 only;
- * // to use window_spill{8,12} in this example function we'd have
- * // to increase space allocated by the entry instruction, because
- * // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed
- * // for call8/window_spill8 or call12/window_spill12 respectively.
- * :
- *
- * retw
- *
- * window_spill_common // instantiates code used by window_spill4
- *
- *
- * On entry:
- * none (if window_spill4)
- * stack frame has enough space allocated for call8 (if window_spill8)
- * stack frame has enough space allocated for call12 (if window_spill12)
- * On exit:
- * a4..a15 clobbered (if window_spill4)
- * a8..a15 clobbered (if window_spill8)
- * a12..a15 clobbered (if window_spill12)
- * no caller windows are in live registers
- */
-
- .macro window_spill4
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 16
- movi a15, 0 // for 16-register files, no need to call to reach the end
-# elif XCHAL_NUM_AREGS == 32
- call4 .L__wdwspill_assist28 // call deep enough to clear out any live callers
-# elif XCHAL_NUM_AREGS == 64
- call4 .L__wdwspill_assist60 // call deep enough to clear out any live callers
-# endif
-#endif
- .endm // window_spill4
-
- .macro window_spill8
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 16
- movi a15, 0 // for 16-register files, no need to call to reach the end
-# elif XCHAL_NUM_AREGS == 32
- call8 .L__wdwspill_assist24 // call deep enough to clear out any live callers
-# elif XCHAL_NUM_AREGS == 64
- call8 .L__wdwspill_assist56 // call deep enough to clear out any live callers
-# endif
-#endif
- .endm // window_spill8
-
- .macro window_spill12
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 16
- movi a15, 0 // for 16-register files, no need to call to reach the end
-# elif XCHAL_NUM_AREGS == 32
- call12 .L__wdwspill_assist20 // call deep enough to clear out any live callers
-# elif XCHAL_NUM_AREGS == 64
- call12 .L__wdwspill_assist52 // call deep enough to clear out any live callers
-# endif
-#endif
- .endm // window_spill12
-
-/*----------------------------------------------------------------------
- * window_spill_function
- *
- * This macro outputs a function that will spill its caller's callers'
- * register windows to the stack. Eg. it could be used to implement
- * a version of xthal_window_spill() that works in non-privileged tasks.
- * This works for both privileged and non-privileged tasks.
- *
- * Typical usage:
- *
- * .text
- * .align 4
- * .global my_spill_function
- * .type my_spill_function,@function
- * my_spill_function:
- * window_spill_function
- *
- * On entry to resulting function:
- * none
- * On exit from resulting function:
- * none (no caller windows are in live registers)
- */
-
- .macro window_spill_function
-#if XCHAL_HAVE_WINDOWED
-# if XCHAL_NUM_AREGS == 32
- entry sp, 48
- bbci.l a0, 31, 1f // branch if called with call4
- bbsi.l a0, 30, 2f // branch if called with call12
- call8 .L__wdwspill_assist16 // called with call8, only need another 8
- retw
-1: call12 .L__wdwspill_assist16 // called with call4, only need another 12
- retw
-2: call4 .L__wdwspill_assist16 // called with call12, only need another 4
- retw
-# elif XCHAL_NUM_AREGS == 64
- entry sp, 48
- bbci.l a0, 31, 1f // branch if called with call4
- bbsi.l a0, 30, 2f // branch if called with call12
- call4 .L__wdwspill_assist52 // called with call8, only need a call4
- retw
-1: call8 .L__wdwspill_assist52 // called with call4, only need a call8
- retw
-2: call12 .L__wdwspill_assist40 // called with call12, can skip a call12
- retw
-# elif XCHAL_NUM_AREGS == 16
- entry sp, 16
- bbci.l a0, 31, 1f // branch if called with call4
- bbsi.l a0, 30, 2f // branch if called with call12
- movi a7, 0 // called with call8
- retw
-1: movi a11, 0 // called with call4
-2: retw // if called with call12, everything already spilled
-
-// movi a15, 0 // trick to spill all but the direct caller
-// j 1f
-// // The entry instruction is magical in the assembler (gets auto-aligned)
-// // so we have to jump to it to avoid falling through the padding.
-// // We need entry/retw to know where to return.
-//1: entry sp, 16
-// retw
-# else
-# error "unrecognized address register file size"
-# endif
-#endif /* XCHAL_HAVE_WINDOWED */
- window_spill_common
- .endm // window_spill_function
-
-/*----------------------------------------------------------------------
- * window_spill_common
- *
- * Common code used by any number of invocations of the window_spill##
- * and window_spill_function macros.
- *
- * Must be instantiated exactly once within a given assembly unit,
- * within call/j range of and same section as window_spill##
- * macro invocations for that assembly unit.
- * (Is automatically instantiated by the window_spill_function macro.)
- */
-
- .macro window_spill_common
-#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64)
- .ifndef .L__wdwspill_defined
-# if XCHAL_NUM_AREGS >= 64
-.L__wdwspill_assist60:
- entry sp, 32
- call8 .L__wdwspill_assist52
- retw
-.L__wdwspill_assist56:
- entry sp, 16
- call4 .L__wdwspill_assist52
- retw
-.L__wdwspill_assist52:
- entry sp, 48
- call12 .L__wdwspill_assist40
- retw
-.L__wdwspill_assist40:
- entry sp, 48
- call12 .L__wdwspill_assist28
- retw
-# endif
-.L__wdwspill_assist28:
- entry sp, 48
- call12 .L__wdwspill_assist16
- retw
-.L__wdwspill_assist24:
- entry sp, 32
- call8 .L__wdwspill_assist16
- retw
-.L__wdwspill_assist20:
- entry sp, 16
- call4 .L__wdwspill_assist16
- retw
-.L__wdwspill_assist16:
- entry sp, 16
- movi a15, 0
- retw
- .set .L__wdwspill_defined, 1
- .endif
-#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */
- .endm // window_spill_common
-
-/*----------------------------------------------------------------------
- * beqi32
- *
- * macro implements version of beqi for arbitrary 32-bit immidiate value
- *
- * beqi32 ax, ay, imm32, label
- *
- * Compares value in register ax with imm32 value and jumps to label if
- * equal. Clobberes register ay if needed
- *
- */
- .macro beqi32 ax, ay, imm, label
- .ifeq ((\imm-1) & ~7) // 1..8 ?
- beqi \ax, \imm, \label
- .else
- .ifeq (\imm+1) // -1 ?
- beqi \ax, \imm, \label
- .else
- .ifeq (\imm) // 0 ?
- beqz \ax, \label
- .else
- // We could also handle immediates 10,12,16,32,64,128,256
- // but it would be a long macro...
- movi \ay, \imm
- beq \ax, \ay, \label
- .endif
- .endif
- .endif
- .endm // beqi32
-
-#endif /*XTENSA_COREASM_H*/
-
diff --git a/include/asm-xtensa/xtensa/corebits.h b/include/asm-xtensa/xtensa/corebits.h
deleted file mode 100644
index e578ade4163..00000000000
--- a/include/asm-xtensa/xtensa/corebits.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef XTENSA_COREBITS_H
-#define XTENSA_COREBITS_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * xtensa/corebits.h - Xtensa Special Register field positions and masks.
- *
- * (In previous releases, these were defined in specreg.h, a generated file.
- * This file is not generated, i.e. it is processor configuration independent.)
- */
-
-
-/* EXCCAUSE register fields: */
-#define EXCCAUSE_EXCCAUSE_SHIFT 0
-#define EXCCAUSE_EXCCAUSE_MASK 0x3F
-/* Exception causes (mostly incomplete!): */
-#define EXCCAUSE_ILLEGAL 0
-#define EXCCAUSE_SYSCALL 1
-#define EXCCAUSE_IFETCHERROR 2
-#define EXCCAUSE_LOADSTOREERROR 3
-#define EXCCAUSE_LEVEL1INTERRUPT 4
-#define EXCCAUSE_ALLOCA 5
-
-/* PS register fields: */
-#define PS_WOE_SHIFT 18
-#define PS_WOE_MASK 0x00040000
-#define PS_WOE PS_WOE_MASK
-#define PS_CALLINC_SHIFT 16
-#define PS_CALLINC_MASK 0x00030000
-#define PS_CALLINC(n) (((n)&3)<<PS_CALLINC_SHIFT) /* n = 0..3 */
-#define PS_OWB_SHIFT 8
-#define PS_OWB_MASK 0x00000F00
-#define PS_OWB(n) (((n)&15)<<PS_OWB_SHIFT) /* n = 0..15 (or 0..7) */
-#define PS_RING_SHIFT 6
-#define PS_RING_MASK 0x000000C0
-#define PS_RING(n) (((n)&3)<<PS_RING_SHIFT) /* n = 0..3 */
-#define PS_UM_SHIFT 5
-#define PS_UM_MASK 0x00000020
-#define PS_UM PS_UM_MASK
-#define PS_EXCM_SHIFT 4
-#define PS_EXCM_MASK 0x00000010
-#define PS_EXCM PS_EXCM_MASK
-#define PS_INTLEVEL_SHIFT 0
-#define PS_INTLEVEL_MASK 0x0000000F
-#define PS_INTLEVEL(n) ((n)&PS_INTLEVEL_MASK) /* n = 0..15 */
-/* Backward compatibility (deprecated): */
-#define PS_PROGSTACK_SHIFT PS_UM_SHIFT
-#define PS_PROGSTACK_MASK PS_UM_MASK
-#define PS_PROG_SHIFT PS_UM_SHIFT
-#define PS_PROG_MASK PS_UM_MASK
-#define PS_PROG PS_UM
-
-/* DBREAKCn register fields: */
-#define DBREAKC_MASK_SHIFT 0
-#define DBREAKC_MASK_MASK 0x0000003F
-#define DBREAKC_LOADBREAK_SHIFT 30
-#define DBREAKC_LOADBREAK_MASK 0x40000000
-#define DBREAKC_STOREBREAK_SHIFT 31
-#define DBREAKC_STOREBREAK_MASK 0x80000000
-
-/* DEBUGCAUSE register fields: */
-#define DEBUGCAUSE_DEBUGINT_SHIFT 5
-#define DEBUGCAUSE_DEBUGINT_MASK 0x20 /* debug interrupt */
-#define DEBUGCAUSE_BREAKN_SHIFT 4
-#define DEBUGCAUSE_BREAKN_MASK 0x10 /* BREAK.N instruction */
-#define DEBUGCAUSE_BREAK_SHIFT 3
-#define DEBUGCAUSE_BREAK_MASK 0x08 /* BREAK instruction */
-#define DEBUGCAUSE_DBREAK_SHIFT 2
-#define DEBUGCAUSE_DBREAK_MASK 0x04 /* DBREAK match */
-#define DEBUGCAUSE_IBREAK_SHIFT 1
-#define DEBUGCAUSE_IBREAK_MASK 0x02 /* IBREAK match */
-#define DEBUGCAUSE_ICOUNT_SHIFT 0
-#define DEBUGCAUSE_ICOUNT_MASK 0x01 /* ICOUNT would increment to zero */
-
-#endif /*XTENSA_COREBITS_H*/
-
diff --git a/include/asm-xtensa/xtensa/hal.h b/include/asm-xtensa/xtensa/hal.h
deleted file mode 100644
index d1047250545..00000000000
--- a/include/asm-xtensa/xtensa/hal.h
+++ /dev/null
@@ -1,822 +0,0 @@
-#ifndef XTENSA_HAL_H
-#define XTENSA_HAL_H
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/hal.h -- contains a definition of the
- * Core HAL interface.
- *
- * All definitions in this header file are independent of any specific
- * Xtensa processor configuration. Thus an OS or other software can
- * include this header file and be compiled into configuration-
- * independent objects that can be distributed and eventually linked
- * to the HAL library (libhal.a) to create a configuration-specific
- * final executable.
- *
- * Certain definitions, however, are release-specific -- such as the
- * XTHAL_RELEASE_xxx macros (or additions made in later releases).
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-/*----------------------------------------------------------------------
- Constant Definitions
- (shared with assembly)
- ----------------------------------------------------------------------*/
-
-/* Software release information (not configuration-specific!): */
-#define XTHAL_RELEASE_MAJOR 1050
-#define XTHAL_RELEASE_MINOR 0
-#define XTHAL_RELEASE_NAME "T1050.0-2002-08-06-eng0"
-#define XTHAL_RELEASE_INTERNAL "2002-08-06-eng0"
-#define XTHAL_REL_T1050 1
-#define XTHAL_REL_T1050_0 1
-#define XTHAL_REL_T1050_0_2002 1
-#define XTHAL_REL_T1050_0_2002_08 1
-#define XTHAL_REL_T1050_0_2002_08_06 1
-#define XTHAL_REL_T1050_0_2002_08_06_ENG0 1
-
-/* HAL version numbers (these names are for backward compatibility): */
-#define XTHAL_MAJOR_REV XTHAL_RELEASE_MAJOR
-#define XTHAL_MINOR_REV XTHAL_RELEASE_MINOR
-/*
- * A bit of software release history on values of XTHAL_{MAJOR,MINOR}_REV:
- *
- * Release MAJOR MINOR Comment
- * ======= ===== ===== =======
- * T1015.n n/a n/a (HAL not yet available)
- * T1020.{0,1,2} 0 1 (HAL beta)
- * T1020.{3,4} 0 2 First release.
- * T1020.n (n>4) 0 2 or >3 (TBD)
- * T1030.0 0 1 (HAL beta)
- * T1030.{1,2} 0 3 Equivalent to first release.
- * T1030.n (n>=3) 0 >= 3 (TBD)
- * T1040.n 1040 n Full CHAL available from T1040.2
- * T1050.n 1050 n Current release.
- *
- *
- * Note: there is a distinction between the software release with
- * which something is compiled (accessible using XTHAL_RELEASE_* macros)
- * and the software release with which the HAL library was compiled
- * (accessible using Xthal_release_* global variables). This
- * distinction is particularly relevant for vendors that distribute
- * configuration-independent binaries (eg. an OS), where their customer
- * might link it with a HAL of a different Xtensa software release.
- * In this case, it may be appropriate for the OS to verify at run-time
- * whether XTHAL_RELEASE_* and Xthal_release_* are compatible.
- * [Guidelines as to which release is compatible with which are not
- * currently provided explicitly, but might be inferred from reading
- * OSKit documentation for all releases -- compatibility is also highly
- * dependent on which HAL features are used. Each release is usually
- * backward compatible, with very few exceptions if any.]
- *
- * Notes:
- * Tornado 2.0 supported in T1020.3+, T1030.1+, and T1040.{0,1} only.
- * Tornado 2.0.2 supported in T1040.2+, and T1050.
- * Compile-time HAL port of NucleusPlus supported by T1040.2+ and T1050.
- */
-
-
-/*
- * Architectural limits, independent of configuration.
- * Note that these are ISA-defined limits, not micro-architecture implementation
- * limits enforced by the Xtensa Processor Generator (which may be stricter than
- * these below).
- */
-#define XTHAL_MAX_CPS 8 /* max number of coprocessors (0..7) */
-#define XTHAL_MAX_INTERRUPTS 32 /* max number of interrupts (0..31) */
-#define XTHAL_MAX_INTLEVELS 16 /* max number of interrupt levels (0..15) */
- /* (as of T1040, implementation limit is 7: 0..6) */
-#define XTHAL_MAX_TIMERS 4 /* max number of timers (CCOMPARE0..CCOMPARE3) */
- /* (as of T1040, implementation limit is 3: 0..2) */
-
-/* Misc: */
-#define XTHAL_LITTLEENDIAN 0
-#define XTHAL_BIGENDIAN 1
-
-
-/* Interrupt types: */
-#define XTHAL_INTTYPE_UNCONFIGURED 0
-#define XTHAL_INTTYPE_SOFTWARE 1
-#define XTHAL_INTTYPE_EXTERN_EDGE 2
-#define XTHAL_INTTYPE_EXTERN_LEVEL 3
-#define XTHAL_INTTYPE_TIMER 4
-#define XTHAL_INTTYPE_NMI 5
-#define XTHAL_MAX_INTTYPES 6 /* number of interrupt types */
-
-/* Timer related: */
-#define XTHAL_TIMER_UNCONFIGURED -1 /* Xthal_timer_interrupt[] value for non-existent timers */
-#define XTHAL_TIMER_UNASSIGNED XTHAL_TIMER_UNCONFIGURED /* (for backwards compatibility only) */
-
-
-/* Access Mode bits (tentative): */ /* bit abbr unit short_name PPC equ - Description */
-#define XTHAL_AMB_EXCEPTION 0 /* 001 E EX fls: EXception none - generate exception on any access (aka "illegal") */
-#define XTHAL_AMB_HITCACHE 1 /* 002 C CH fls: use Cache on Hit ~(I CI) - use cache on hit -- way from tag match [or H HC, or U UC] (ISA: same, except for Isolate case) */
-#define XTHAL_AMB_ALLOCATE 2 /* 004 A AL fl?: ALlocate none - refill cache on miss -- way from LRU [or F FI fill] (ISA: Read/Write Miss Refill) */
-#define XTHAL_AMB_WRITETHRU 3 /* 008 W WT --s: WriteThrough W WT - store immediately to memory (ISA: same) */
-#define XTHAL_AMB_ISOLATE 4 /* 010 I IS fls: ISolate none - use cache regardless of hit-vs-miss -- way from vaddr (ISA: use-cache-on-miss+hit) */
-#define XTHAL_AMB_GUARD 5 /* 020 G GU ?l?: GUard G * - non-speculative; spec/replay refs not permitted */
-#if 0
-#define XTHAL_AMB_ORDERED x /* 000 O OR fls: ORdered G * - mem accesses cannot be out of order */
-#define XTHAL_AMB_FUSEWRITES x /* 000 F FW --s: FuseWrites none - allow combining/merging multiple writes (to same datapath data unit) into one (implied by writeback) */
-#define XTHAL_AMB_COHERENT x /* 000 M MC fl?: Mem/MP Coherent M - on reads, other CPUs/bus-masters may need to supply data */
-#define XTHAL_AMB_TRUSTED x /* 000 T TR ?l?: TRusted none - memory will not bus error (if it does, handle as fatal imprecise interrupt) */
-#define XTHAL_AMB_PREFETCH x /* 000 P PR fl?: PRefetch none - on refill, read line+1 into prefetch buffers */
-#define XTHAL_AMB_STREAM x /* 000 S ST ???: STreaming none - access one of N stream buffers */
-#endif /*0*/
-
-#define XTHAL_AM_EXCEPTION (1<<XTHAL_AMB_EXCEPTION)
-#define XTHAL_AM_HITCACHE (1<<XTHAL_AMB_HITCACHE)
-#define XTHAL_AM_ALLOCATE (1<<XTHAL_AMB_ALLOCATE)
-#define XTHAL_AM_WRITETHRU (1<<XTHAL_AMB_WRITETHRU)
-#define XTHAL_AM_ISOLATE (1<<XTHAL_AMB_ISOLATE)
-#define XTHAL_AM_GUARD (1<<XTHAL_AMB_GUARD)
-#if 0
-#define XTHAL_AM_ORDERED (1<<XTHAL_AMB_ORDERED)
-#define XTHAL_AM_FUSEWRITES (1<<XTHAL_AMB_FUSEWRITES)
-#define XTHAL_AM_COHERENT (1<<XTHAL_AMB_COHERENT)
-#define XTHAL_AM_TRUSTED (1<<XTHAL_AMB_TRUSTED)
-#define XTHAL_AM_PREFETCH (1<<XTHAL_AMB_PREFETCH)
-#define XTHAL_AM_STREAM (1<<XTHAL_AMB_STREAM)
-#endif /*0*/
-
-/*
- * Allowed Access Modes (bit combinations).
- *
- * Columns are:
- * "FOGIWACE"
- * Access mode bits (see XTHAL_AMB_xxx above).
- * <letter> = bit is set
- * '-' = bit is clear
- * '.' = bit is irrelevant / don't care, as follows:
- * E=1 makes all others irrelevant
- * W,F relevant only for stores
- * "2345"
- * Indicates which Xtensa releases support the corresponding
- * access mode. Releases for each character column are:
- * 2 = prior to T1020.2: T1015 (V1.5), T1020.0, T1020.1
- * 3 = T1020.2 and later: T1020.2+, T1030
- * 4 = T1040
- * 5 = T1050 (maybe)
- * And the character column contents are:
- * <number> = support by release(s)
- * "." = unsupported by release(s)
- * "?" = support unknown
- */
- /* FOGIWACE 2345 */
-/* For instruction fetch: */
-#define XTHAL_FAM_EXCEPTION 0x001 /* .......E 2345 exception */
-#define XTHAL_FAM_ISOLATE 0x012 /* .--I.-C- .... isolate */
-#define XTHAL_FAM_BYPASS 0x000 /* .---.--- 2345 bypass */
-#define XTHAL_FAM_NACACHED 0x002 /* .---.-C- .... cached no-allocate (frozen) */
-#define XTHAL_FAM_CACHED 0x006 /* .---.AC- 2345 cached */
-/* For data load: */
-#define XTHAL_LAM_EXCEPTION 0x001 /* .......E 2345 exception */
-#define XTHAL_LAM_ISOLATE 0x012 /* .--I.-C- 2345 isolate */
-#define XTHAL_LAM_BYPASS 0x000 /* .O--.--- 2... bypass speculative */
-#define XTHAL_LAM_BYPASSG 0x020 /* .OG-.--- .345 bypass guarded */
-#define XTHAL_LAM_NACACHED 0x002 /* .O--.-C- 2... cached no-allocate speculative */
-#define XTHAL_LAM_NACACHEDG 0x022 /* .OG-.-C- .345 cached no-allocate guarded */
-#define XTHAL_LAM_CACHED 0x006 /* .---.AC- 2345 cached speculative */
-#define XTHAL_LAM_CACHEDG 0x026 /* .?G-.AC- .... cached guarded */
-/* For data store: */
-#define XTHAL_SAM_EXCEPTION 0x001 /* .......E 2345 exception */
-#define XTHAL_SAM_ISOLATE 0x032 /* .-GI--C- 2345 isolate */
-#define XTHAL_SAM_BYPASS 0x028 /* -OG-W--- 2345 bypass */
-/*efine XTHAL_SAM_BYPASSF 0x028*/ /* F-G-W--- ...? bypass write-combined */
-#define XTHAL_SAM_WRITETHRU 0x02A /* -OG-W-C- 234? writethrough */
-/*efine XTHAL_SAM_WRITETHRUF 0x02A*/ /* F-G-W-C- ...5 writethrough write-combined */
-#define XTHAL_SAM_WRITEALLOC 0x02E /* -OG-WAC- ...? writethrough-allocate */
-/*efine XTHAL_SAM_WRITEALLOCF 0x02E*/ /* F-G-WAC- ...? writethrough-allocate write-combined */
-#define XTHAL_SAM_WRITEBACK 0x026 /* F-G--AC- ...5 writeback */
-
-#if 0
-/*
- Cache attribute encoding for CACHEATTR (per ISA):
- (Note: if this differs from ISA Ref Manual, ISA has precedence)
-
- Inst-fetches Loads Stores
- ------------- ------------ -------------
-0x0 FCA_EXCEPTION ?LCA_NACACHED_G* SCA_WRITETHRU "uncached"
-0x1 FCA_CACHED LCA_CACHED SCA_WRITETHRU cached
-0x2 FCA_BYPASS LCA_BYPASS_G* SCA_BYPASS bypass
-0x3 FCA_CACHED LCA_CACHED SCA_WRITEALLOCF write-allocate
- or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented)
-0x4 FCA_CACHED LCA_CACHED SCA_WRITEBACK write-back
- or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented)
-0x5..D FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (reserved)
-0xE FCA_EXCEPTION LCA_ISOLATE SCA_ISOLATE isolate
-0xF FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION illegal
- * Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G)
-*/
-#endif /*0*/
-
-
-#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*----------------------------------------------------------------------
- HAL
- ----------------------------------------------------------------------*/
-
-/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */
-extern const unsigned int Xthal_rev_no;
-
-
-/*----------------------------------------------------------------------
- Processor State
- ----------------------------------------------------------------------*/
-/* save & restore the extra processor state */
-extern void xthal_save_extra(void *base);
-extern void xthal_restore_extra(void *base);
-
-extern void xthal_save_cpregs(void *base, int);
-extern void xthal_restore_cpregs(void *base, int);
-
-/*extern void xthal_save_all_extra(void *base);*/
-/*extern void xthal_restore_all_extra(void *base);*/
-
-/* space for processor state */
-extern const unsigned int Xthal_extra_size;
-extern const unsigned int Xthal_extra_align;
-/* space for TIE register files */
-extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS];
-extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS];
-
-/* total of space for the processor state (for Tor2) */
-extern const unsigned int Xthal_all_extra_size;
-extern const unsigned int Xthal_all_extra_align;
-
-/* initialize the extra processor */
-/*extern void xthal_init_extra(void);*/
-/* initialize the TIE coprocessor */
-/*extern void xthal_init_cp(int);*/
-
-/* initialize the extra processor */
-extern void xthal_init_mem_extra(void *);
-/* initialize the TIE coprocessor */
-extern void xthal_init_mem_cp(void *, int);
-
-/* validate & invalidate the TIE register file */
-extern void xthal_validate_cp(int);
-extern void xthal_invalidate_cp(int);
-
-/* the number of TIE coprocessors contiguous from zero (for Tor2) */
-extern const unsigned int Xthal_num_coprocessors;
-
-/* actual number of coprocessors */
-extern const unsigned char Xthal_cp_num;
-/* index of highest numbered coprocessor, plus one */
-extern const unsigned char Xthal_cp_max;
-/* index of highest allowed coprocessor number, per cfg, plus one */
-/*extern const unsigned char Xthal_cp_maxcfg;*/
-/* bitmask of which coprocessors are present */
-extern const unsigned int Xthal_cp_mask;
-
-/* read and write cpenable register */
-extern void xthal_set_cpenable(unsigned);
-extern unsigned xthal_get_cpenable(void);
-
-/* read & write extra state register */
-/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/
-/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/
-
-/* read & write a TIE coprocessor register */
-/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/
-/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/
-
-/* return coprocessor number based on register */
-/*extern int xthal_which_cp(unsigned reg);*/
-
-/*----------------------------------------------------------------------
- Interrupts
- ----------------------------------------------------------------------*/
-
-/* the number of interrupt levels */
-extern const unsigned char Xthal_num_intlevels;
-/* the number of interrupts */
-extern const unsigned char Xthal_num_interrupts;
-
-/* mask for level of interrupts */
-extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS];
-/* mask for level 0 to N interrupts */
-extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS];
-
-/* level of each interrupt */
-extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS];
-
-/* type per interrupt */
-extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS];
-
-/* masks of each type of interrupt */
-extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES];
-
-/* interrupt numbers assigned to each timer interrupt */
-extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS];
-
-/*** Virtual interrupt prioritization: ***/
-
-/* Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities: */
-extern unsigned xthal_vpri_to_intlevel(unsigned vpri);
-extern unsigned xthal_intlevel_to_vpri(unsigned intlevel);
-
-/* Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints: */
-extern unsigned xthal_int_enable(unsigned);
-extern unsigned xthal_int_disable(unsigned);
-
-/* Set/get virtual priority of an interrupt: */
-extern int xthal_set_int_vpri(int intnum, int vpri);
-extern int xthal_get_int_vpri(int intnum);
-
-/* Set/get interrupt lockout level for exclusive access to virtual priority data structures: */
-extern void xthal_set_vpri_locklevel(unsigned intlevel);
-extern unsigned xthal_get_vpri_locklevel(void);
-
-/* Set/get current virtual interrupt priority: */
-extern unsigned xthal_set_vpri(unsigned vpri);
-extern unsigned xthal_get_vpri(unsigned vpri);
-extern unsigned xthal_set_vpri_intlevel(unsigned intlevel);
-extern unsigned xthal_set_vpri_lock(void);
-
-
-
-/*----------------------------------------------------------------------
- Generic Interrupt Trampolining Support
- ----------------------------------------------------------------------*/
-
-typedef void (XtHalVoidFunc)(void);
-
-/*
- * Bitmask of interrupts currently trampolining down:
- */
-extern unsigned Xthal_tram_pending;
-
-/*
- * Bitmask of which interrupts currently trampolining down
- * synchronously are actually enabled; this bitmask is necessary
- * because INTENABLE cannot hold that state (sync-trampolining
- * interrupts must be kept disabled while trampolining);
- * in the current implementation, any bit set here is not set
- * in INTENABLE, and vice-versa; once a sync-trampoline is
- * handled (at level one), its enable bit must be moved from
- * here to INTENABLE:
- */
-extern unsigned Xthal_tram_enabled;
-
-/*
- * Bitmask of interrupts configured for sync trampolining:
- */
-extern unsigned Xthal_tram_sync;
-
-
-/* Trampoline support functions: */
-extern unsigned xthal_tram_pending_to_service( void );
-extern void xthal_tram_done( unsigned serviced_mask );
-extern int xthal_tram_set_sync( int intnum, int sync );
-extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn );
-
-/* INTENABLE,INTREAD,INTSET,INTCLEAR register access functions: */
-extern unsigned xthal_get_intenable( void );
-extern void xthal_set_intenable( unsigned );
-extern unsigned xthal_get_intread( void );
-extern void xthal_set_intset( unsigned );
-extern void xthal_set_intclear( unsigned );
-
-
-/*----------------------------------------------------------------------
- Register Windows
- ----------------------------------------------------------------------*/
-
-/* number of registers in register window */
-extern const unsigned int Xthal_num_aregs;
-extern const unsigned char Xthal_num_aregs_log2;
-
-/* This spill any live register windows (other than the caller's): */
-extern void xthal_window_spill( void );
-
-
-/*----------------------------------------------------------------------
- Cache
- ----------------------------------------------------------------------*/
-
-/* size of the cache lines in log2(bytes) */
-extern const unsigned char Xthal_icache_linewidth;
-extern const unsigned char Xthal_dcache_linewidth;
-/* size of the cache lines in bytes */
-extern const unsigned short Xthal_icache_linesize;
-extern const unsigned short Xthal_dcache_linesize;
-/* number of cache sets in log2(lines per way) */
-extern const unsigned char Xthal_icache_setwidth;
-extern const unsigned char Xthal_dcache_setwidth;
-/* cache set associativity (number of ways) */
-extern const unsigned int Xthal_icache_ways;
-extern const unsigned int Xthal_dcache_ways;
-/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */
-extern const unsigned int Xthal_icache_size;
-extern const unsigned int Xthal_dcache_size;
-/* cache features */
-extern const unsigned char Xthal_dcache_is_writeback;
-extern const unsigned char Xthal_icache_line_lockable;
-extern const unsigned char Xthal_dcache_line_lockable;
-
-/* cache attribute register control (used by other HAL routines) */
-extern unsigned xthal_get_cacheattr( void );
-extern unsigned xthal_get_icacheattr( void );
-extern unsigned xthal_get_dcacheattr( void );
-extern void xthal_set_cacheattr( unsigned );
-extern void xthal_set_icacheattr( unsigned );
-extern void xthal_set_dcacheattr( unsigned );
-
-/* initialize cache support (must be called once at startup, before all other cache calls) */
-/*extern void xthal_cache_startinit( void );*/
-/* reset caches */
-/*extern void xthal_icache_reset( void );*/
-/*extern void xthal_dcache_reset( void );*/
-/* enable caches */
-extern void xthal_icache_enable( void ); /* DEPRECATED */
-extern void xthal_dcache_enable( void ); /* DEPRECATED */
-/* disable caches */
-extern void xthal_icache_disable( void ); /* DEPRECATED */
-extern void xthal_dcache_disable( void ); /* DEPRECATED */
-
-/* invalidate the caches */
-extern void xthal_icache_all_invalidate( void );
-extern void xthal_dcache_all_invalidate( void );
-extern void xthal_icache_region_invalidate( void *addr, unsigned size );
-extern void xthal_dcache_region_invalidate( void *addr, unsigned size );
-extern void xthal_icache_line_invalidate(void *addr);
-extern void xthal_dcache_line_invalidate(void *addr);
-/* write dirty data back */
-extern void xthal_dcache_all_writeback( void );
-extern void xthal_dcache_region_writeback( void *addr, unsigned size );
-extern void xthal_dcache_line_writeback(void *addr);
-/* write dirty data back and invalidate */
-extern void xthal_dcache_all_writeback_inv( void );
-extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size );
-extern void xthal_dcache_line_writeback_inv(void *addr);
-/* prefetch and lock specified memory range into cache */
-extern void xthal_icache_region_lock( void *addr, unsigned size );
-extern void xthal_dcache_region_lock( void *addr, unsigned size );
-extern void xthal_icache_line_lock(void *addr);
-extern void xthal_dcache_line_lock(void *addr);
-/* unlock from cache */
-extern void xthal_icache_all_unlock( void );
-extern void xthal_dcache_all_unlock( void );
-extern void xthal_icache_region_unlock( void *addr, unsigned size );
-extern void xthal_dcache_region_unlock( void *addr, unsigned size );
-extern void xthal_icache_line_unlock(void *addr);
-extern void xthal_dcache_line_unlock(void *addr);
-
-
-/* sync icache and memory */
-extern void xthal_icache_sync( void );
-/* sync dcache and memory */
-extern void xthal_dcache_sync( void );
-
-/*----------------------------------------------------------------------
- Debug
- ----------------------------------------------------------------------*/
-
-/* 1 if debug option configured, 0 if not: */
-extern const int Xthal_debug_configured;
-
-/* Number of instruction and data break registers: */
-extern const int Xthal_num_ibreak;
-extern const int Xthal_num_dbreak;
-
-/* Set (plant) and remove software breakpoint, both synchronizing cache: */
-extern unsigned int xthal_set_soft_break(void *addr);
-extern void xthal_remove_soft_break(void *addr, unsigned int);
-
-
-/*----------------------------------------------------------------------
- Disassembler
- ----------------------------------------------------------------------*/
-
-/* Max expected size of the return buffer for a disassembled instruction (hint only): */
-#define XTHAL_DISASM_BUFSIZE 80
-
-/* Disassembly option bits for selecting what to return: */
-#define XTHAL_DISASM_OPT_ADDR 0x0001 /* display address */
-#define XTHAL_DISASM_OPT_OPHEX 0x0002 /* display opcode bytes in hex */
-#define XTHAL_DISASM_OPT_OPCODE 0x0004 /* display opcode name (mnemonic) */
-#define XTHAL_DISASM_OPT_PARMS 0x0008 /* display parameters */
-#define XTHAL_DISASM_OPT_ALL 0x0FFF /* display everything */
-
-/* routine to get a string for the disassembled instruction */
-extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr,
- char *buffer, unsigned buflen, unsigned options );
-
-/* routine to get the size of the next instruction. Returns 0 for
- illegal instruction */
-extern int xthal_disassemble_size( unsigned char *instr_buf );
-
-
-/*----------------------------------------------------------------------
- Core Counter
- ----------------------------------------------------------------------*/
-
-/* counter info */
-extern const unsigned char Xthal_have_ccount; /* set if CCOUNT register present */
-extern const unsigned char Xthal_num_ccompare; /* number of CCOMPAREn registers */
-
-/* get CCOUNT register (if not present return 0) */
-extern unsigned xthal_get_ccount(void);
-
-/* set and get CCOMPAREn registers (if not present, get returns 0) */
-extern void xthal_set_ccompare(int, unsigned);
-extern unsigned xthal_get_ccompare(int);
-
-
-/*----------------------------------------------------------------------
- Instruction/Data RAM/ROM Access
- ----------------------------------------------------------------------*/
-
-extern void* xthal_memcpy(void *dst, const void *src, unsigned len);
-extern void* xthal_bcopy(const void *src, void *dst, unsigned len);
-
-/*----------------------------------------------------------------------
- MP Synchronization
- ----------------------------------------------------------------------*/
-extern int xthal_compare_and_set( int *addr, int test_val, int compare_val );
-extern unsigned xthal_get_prid( void );
-
-/*extern const char Xthal_have_s32c1i;*/
-extern const unsigned char Xthal_have_prid;
-
-
-/*----------------------------------------------------------------------
- Miscellaneous
- ----------------------------------------------------------------------*/
-
-extern const unsigned int Xthal_release_major;
-extern const unsigned int Xthal_release_minor;
-extern const char * const Xthal_release_name;
-extern const char * const Xthal_release_internal;
-
-extern const unsigned char Xthal_memory_order;
-extern const unsigned char Xthal_have_windowed;
-extern const unsigned char Xthal_have_density;
-extern const unsigned char Xthal_have_booleans;
-extern const unsigned char Xthal_have_loops;
-extern const unsigned char Xthal_have_nsa;
-extern const unsigned char Xthal_have_minmax;
-extern const unsigned char Xthal_have_sext;
-extern const unsigned char Xthal_have_clamps;
-extern const unsigned char Xthal_have_mac16;
-extern const unsigned char Xthal_have_mul16;
-extern const unsigned char Xthal_have_fp;
-extern const unsigned char Xthal_have_speculation;
-extern const unsigned char Xthal_have_exceptions;
-extern const unsigned char Xthal_xea_version;
-extern const unsigned char Xthal_have_interrupts;
-extern const unsigned char Xthal_have_highlevel_interrupts;
-extern const unsigned char Xthal_have_nmi;
-
-extern const unsigned short Xthal_num_writebuffer_entries;
-
-extern const unsigned int Xthal_build_unique_id;
-/* Release info for hardware targeted by software upgrades: */
-extern const unsigned int Xthal_hw_configid0;
-extern const unsigned int Xthal_hw_configid1;
-extern const unsigned int Xthal_hw_release_major;
-extern const unsigned int Xthal_hw_release_minor;
-extern const char * const Xthal_hw_release_name;
-extern const char * const Xthal_hw_release_internal;
-
-
-/* Internal memories... */
-
-extern const unsigned char Xthal_num_instrom;
-extern const unsigned char Xthal_num_instram;
-extern const unsigned char Xthal_num_datarom;
-extern const unsigned char Xthal_num_dataram;
-extern const unsigned char Xthal_num_xlmi;
-extern const unsigned int Xthal_instrom_vaddr[1];
-extern const unsigned int Xthal_instrom_paddr[1];
-extern const unsigned int Xthal_instrom_size [1];
-extern const unsigned int Xthal_instram_vaddr[1];
-extern const unsigned int Xthal_instram_paddr[1];
-extern const unsigned int Xthal_instram_size [1];
-extern const unsigned int Xthal_datarom_vaddr[1];
-extern const unsigned int Xthal_datarom_paddr[1];
-extern const unsigned int Xthal_datarom_size [1];
-extern const unsigned int Xthal_dataram_vaddr[1];
-extern const unsigned int Xthal_dataram_paddr[1];
-extern const unsigned int Xthal_dataram_size [1];
-extern const unsigned int Xthal_xlmi_vaddr[1];
-extern const unsigned int Xthal_xlmi_paddr[1];
-extern const unsigned int Xthal_xlmi_size [1];
-
-
-
-/*----------------------------------------------------------------------
- Memory Management Unit
- ----------------------------------------------------------------------*/
-
-extern const unsigned char Xthal_have_spanning_way;
-extern const unsigned char Xthal_have_identity_map;
-extern const unsigned char Xthal_have_mimic_cacheattr;
-extern const unsigned char Xthal_have_xlt_cacheattr;
-extern const unsigned char Xthal_have_cacheattr;
-extern const unsigned char Xthal_have_tlbs;
-
-extern const unsigned char Xthal_mmu_asid_bits; /* 0 .. 8 */
-extern const unsigned char Xthal_mmu_asid_kernel;
-extern const unsigned char Xthal_mmu_rings; /* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */
-extern const unsigned char Xthal_mmu_ring_bits;
-extern const unsigned char Xthal_mmu_sr_bits;
-extern const unsigned char Xthal_mmu_ca_bits;
-extern const unsigned int Xthal_mmu_max_pte_page_size;
-extern const unsigned int Xthal_mmu_min_pte_page_size;
-
-extern const unsigned char Xthal_itlb_way_bits;
-extern const unsigned char Xthal_itlb_ways;
-extern const unsigned char Xthal_itlb_arf_ways;
-extern const unsigned char Xthal_dtlb_way_bits;
-extern const unsigned char Xthal_dtlb_ways;
-extern const unsigned char Xthal_dtlb_arf_ways;
-
-/* Convert between virtual and physical addresses (through static maps only): */
-/*** WARNING: these two functions may go away in a future release; don't depend on them! ***/
-extern int xthal_static_v2p( unsigned vaddr, unsigned *paddrp );
-extern int xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached );
-
-#if 0
-/******************* EXPERIMENTAL AND TENTATIVE ONLY ********************/
-
-#define XTHAL_MMU_PAGESZ_COUNT_MAX 8 /* maximum number of different page sizes */
-extern const char Xthal_mmu_pagesz_count; /* 0 .. 8 number of different page sizes configured */
-
-/* Note: the following table doesn't necessarily have page sizes in increasing order: */
-extern const char Xthal_mmu_pagesz_log2[XTHAL_MMU_PAGESZ_COUNT_MAX]; /* 10 .. 28 (0 past count) */
-
-/* Sorted (increasing) table of page sizes, that indexes into the above table: */
-extern const char Xthal_mmu_pagesz_sorted[XTHAL_MMU_PAGESZ_COUNT_MAX]; /* 0 .. 7 (0 past count) */
-
-/*u32 Xthal_virtual_exceptions;*/ /* bitmask of which exceptions execute in virtual mode... */
-
-extern const char Xthal_mmu_pte_pagesz_log2_min; /* ?? minimum page size in PTEs */
-extern const char Xthal_mmu_pte_pagesz_log2_max; /* ?? maximum page size in PTEs */
-
-/* Cache Attribute Bits Implemented by the Cache (part of the cache abstraction) */
-extern const char Xthal_icache_fca_bits_implemented; /* ITLB/UTLB only! */
-extern const char Xthal_dcache_lca_bits_implemented; /* DTLB/UTLB only! */
-extern const char Xthal_dcache_sca_bits_implemented; /* DTLB/UTLB only! */
-
-/* Per TLB Parameters (Instruction, Data, Unified) */
-struct XtHalMmuTlb Xthal_itlb; /* description of MMU I-TLB generic features */
-struct XtHalMmuTlb Xthal_dtlb; /* description of MMU D-TLB generic features */
-struct XtHalMmuTlb Xthal_utlb; /* description of MMU U-TLB generic features */
-
-#define XTHAL_MMU_WAYS_MAX 8 /* maximum number of ways (associativities) for each TLB */
-
-/* Structure for common information described for each possible TLB (instruction, data and unified): */
-typedef struct XtHalMmuTlb {
- u8 va_bits; /* 32 (number of virtual address bits) */
- u8 pa_bits; /* 32 (number of physical address bits) */
- bool tlb_va_indexed; /* 1 (set if TLB is indexed by virtual address) */
- bool tlb_va_tagged; /* 0 (set if TLB is tagged by virtual address) */
- bool cache_va_indexed; /* 1 (set if cache is indexed by virtual address) */
- bool cache_va_tagged; /* 0 (set if cache is tagged by virtual address) */
- /*bool (whether page tables are traversed in vaddr sorted order, paddr sorted order, ...) */
- /*u8 (set of available page attribute bits, other than cache attribute bits defined above) */
- /*u32 (various masks for pages, MMU table/TLB entries, etc.) */
- u8 way_count; /* 0 .. 8 (number of ways, a.k.a. associativities, for this TLB) */
- XtHalMmuTlbWay * ways[XTHAL_MMU_WAYS_MAX]; /* pointers to per-way parms for each way */
-} XtHalMmuTlb;
-
-/* Per TLB Way (Per Associativity) Parameters */
-typedef struct XtHalMmuTlbWay {
- u32 index_count_log2; /* 0 .. 4 */
- u32 pagesz_mask; /* 0 .. 2^pagesz_count - 1 (each bit corresponds to a size */
- /* defined in the Xthal_mmu_pagesz_log2[] table) */
- u32 vpn_const_mask;
- u32 vpn_const_value;
- u64 ppn_const_mask; /* future may support pa_bits > 32 */
- u64 ppn_const_value;
- u32 ppn_id_mask; /* paddr bits taken directly from vaddr */
- bool backgnd_match; /* 0 or 1 */
- /* These are defined in terms of the XTHAL_CACHE_xxx bits: */
- u8 fca_const_mask; /* ITLB/UTLB only! */
- u8 fca_const_value; /* ITLB/UTLB only! */
- u8 lca_const_mask; /* DTLB/UTLB only! */
- u8 lca_const_value; /* DTLB/UTLB only! */
- u8 sca_const_mask; /* DTLB/UTLB only! */
- u8 sca_const_value; /* DTLB/UTLB only! */
- /* These define an encoding that map 5 bits in TLB and PTE entries to */
- /* 8 bits (FCA, ITLB), 16 bits (LCA+SCA, DTLB) or 24 bits (FCA+LCA+SCA, UTLB): */
- /* (they may be moved to struct XtHalMmuTlb) */
- u8 ca_bits; /* number of bits in TLB/PTE entries for cache attributes */
- u32 * ca_map; /* pointer to array of 2^ca_bits entries of FCA+LCA+SCA bits */
-} XtHalMmuTlbWay;
-
-/*
- * The way to determine whether protection support is present in core
- * is to [look at Xthal_mmu_rings ???].
- * Give info on memory requirements for MMU tables and other in-memory
- * data structures (globally, per task, base and per page, etc.) - whatever bounds can be calculated.
- */
-
-
-/* Default vectors: */
-xthal_immu_fetch_miss_vector
-xthal_dmmu_load_miss_vector
-xthal_dmmu_store_miss_vector
-
-/* Functions called when a fault is detected: */
-typedef void (XtHalMmuFaultFunc)( unsigned vaddr, ...context... );
-/* Or, */
-/* a? = vaddr */
-/* a? = context... */
-/* PS.xxx = xxx */
-XtHalMMuFaultFunc *Xthal_immu_fetch_fault_func;
-XtHalMMuFaultFunc *Xthal_dmmu_load_fault_func;
-XtHalMMuFaultFunc *Xthal_dmmu_store_fault_func;
-
-/* Default Handlers: */
-/* The user and/or kernel exception handlers may jump to these handlers to handle the relevant exceptions,
- * according to the value of EXCCAUSE. The exact register state on entry to these handlers is TBD. */
-/* When multiple TLB entries match (hit) on the same access: */
-xthal_immu_fetch_multihit_handler
-xthal_dmmu_load_multihit_handler
-xthal_dmmu_store_multihit_handler
-/* Protection violations according to cache attributes, and other cache attribute mismatches: */
-xthal_immu_fetch_attr_handler
-xthal_dmmu_load_attr_handler
-xthal_dmmu_store_attr_handler
-/* Protection violations due to insufficient ring level: */
-xthal_immu_fetch_priv_handler
-xthal_dmmu_load_priv_handler
-xthal_dmmu_store_priv_handler
-/* Alignment exception handlers (if supported by the particular Xtensa MMU configuration): */
-xthal_dmmu_load_align_handler
-xthal_dmmu_store_align_handler
-
-/* Or, alternatively, the OS user and/or kernel exception handlers may simply jump to the
- * following entry points which will handle any values of EXCCAUSE not handled by the OS: */
-xthal_user_exc_default_handler
-xthal_kernel_exc_default_handler
-
-#endif /*0*/
-
-#ifdef INCLUDE_DEPRECATED_HAL_CODE
-extern const unsigned char Xthal_have_old_exc_arch;
-extern const unsigned char Xthal_have_mmu;
-extern const unsigned int Xthal_num_regs;
-extern const unsigned char Xthal_num_iroms;
-extern const unsigned char Xthal_num_irams;
-extern const unsigned char Xthal_num_droms;
-extern const unsigned char Xthal_num_drams;
-extern const unsigned int Xthal_configid0;
-extern const unsigned int Xthal_configid1;
-#endif
-
-#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
-#define XTHAL_24_BIT_BREAK 0x80000000
-#define XTHAL_16_BIT_BREAK 0x40000000
-extern const unsigned short Xthal_ill_inst_16[16];
-#define XTHAL_DEST_REG 0xf0000000 /* Mask for destination register */
-#define XTHAL_DEST_REG_INST 0x08000000 /* Branch address is in register */
-#define XTHAL_DEST_REL_INST 0x04000000 /* Branch address is relative */
-#define XTHAL_RFW_INST 0x00000800
-#define XTHAL_RFUE_INST 0x00000400
-#define XTHAL_RFI_INST 0x00000200
-#define XTHAL_RFE_INST 0x00000100
-#define XTHAL_RET_INST 0x00000080
-#define XTHAL_BREAK_INST 0x00000040
-#define XTHAL_SYSCALL_INST 0x00000020
-#define XTHAL_LOOP_END 0x00000010 /* Not set by xthal_inst_type */
-#define XTHAL_JUMP_INST 0x00000008 /* Call or jump instruction */
-#define XTHAL_BRANCH_INST 0x00000004 /* Branch instruction */
-#define XTHAL_24_BIT_INST 0x00000002
-#define XTHAL_16_BIT_INST 0x00000001
-typedef struct xthal_state {
- unsigned pc;
- unsigned ar[16];
- unsigned lbeg;
- unsigned lend;
- unsigned lcount;
- unsigned extra_ptr;
- unsigned cpregs_ptr[XTHAL_MAX_CPS];
-} XTHAL_STATE;
-extern unsigned int xthal_inst_type(void *addr);
-extern unsigned int xthal_branch_addr(void *addr);
-extern unsigned int xthal_get_npc(XTHAL_STATE *user_state);
-#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
-
-#ifdef __cplusplus
-}
-#endif
-#endif /*!__ASSEMBLY__ */
-
-#endif /*XTENSA_HAL_H*/
-
diff --git a/include/asm-xtensa/xtensa/simcall.h b/include/asm-xtensa/xtensa/simcall.h
deleted file mode 100644
index a2b868929a4..00000000000
--- a/include/asm-xtensa/xtensa/simcall.h
+++ /dev/null
@@ -1,130 +0,0 @@
-#ifndef SIMCALL_INCLUDED
-#define SIMCALL_INCLUDED
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/simcall.h - Simulator call numbers
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-/*
- * System call like services offered by the simulator host.
- * These are modeled after the Linux 2.4 kernel system calls
- * for Xtensa processors. However not all system calls and
- * not all functionality of a given system call are implemented,
- * or necessarily have well defined or equivalent semantics in
- * the context of a simulation (as opposed to a Unix kernel).
- *
- * These services behave largely as if they had been invoked
- * as a task in the simulator host's operating system
- * (eg. files accessed are those of the simulator host).
- * However, these SIMCALLs model a virtual operating system
- * so that various definitions, bit assignments etc
- * (eg. open mode bits, errno values, etc) are independent
- * of the host operating system used to run the simulation.
- * Rather these definitions are specific to the Xtensa ISS.
- * This way Xtensa ISA code written to use these SIMCALLs
- * can (in principle) be simulated on any host.
- *
- * Up to 6 parameters are passed in registers a3 to a8
- * (note the 6th parameter isn't passed on the stack,
- * unlike windowed function calling conventions).
- * The return value is in a2. A negative value in the
- * range -4096 to -1 indicates a negated error code to be
- * reported in errno with a return value of -1, otherwise
- * the value in a2 is returned as is.
- */
-
-/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */
-
-#define SYS_nop 0 /* n/a - setup; used to flush register windows */
-#define SYS_exit 1 /*x*/
-#define SYS_fork 2
-#define SYS_read 3 /*x*/
-#define SYS_write 4 /*x*/
-#define SYS_open 5 /*x*/
-#define SYS_close 6 /*x*/
-#define SYS_rename 7 /*x 38 - waitpid */
-#define SYS_creat 8 /*x*/
-#define SYS_link 9 /*x (not implemented on WIN32) */
-#define SYS_unlink 10 /*x*/
-#define SYS_execv 11 /* n/a - execve */
-#define SYS_execve 12 /* 11 - chdir */
-#define SYS_pipe 13 /* 42 - time */
-#define SYS_stat 14 /* 106 - mknod */
-#define SYS_chmod 15
-#define SYS_chown 16 /* 202 - lchown */
-#define SYS_utime 17 /* 30 - break */
-#define SYS_wait 18 /* n/a - oldstat */
-#define SYS_lseek 19 /*x*/
-#define SYS_getpid 20
-#define SYS_isatty 21 /* n/a - mount */
-#define SYS_fstat 22 /* 108 - oldumount */
-#define SYS_time 23 /* 13 - setuid */
-#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */
-#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */
-#define SYS_socket 26
-#define SYS_sendto 27
-#define SYS_recvfrom 28
-#define SYS_select_one 29 /* not compitible select, one file descriptor at the time */
-#define SYS_bind 30
-#define SYS_ioctl 31
-
-/*
- * Other...
- */
-#define SYS_iss_argc 1000 /* returns value of argc */
-#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */
-#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */
-
-/*
- * SIMCALLs for the ferret memory debugger. All are invoked by
- * libferret.a ... ( Xtensa/Target-Libs/ferret )
- */
-#define SYS_ferret 1010
-#define SYS_malloc 1011
-#define SYS_free 1012
-#define SYS_more_heap 1013
-#define SYS_no_heap 1014
-
-
-/*
- * Extra SIMCALLs for GDB:
- */
-#define SYS_gdb_break -1 /* invoked by XTOS on user exceptions if EPC points
- to a break.n/break, regardless of cause! */
-#define SYS_xmon_out -2 /* invoked by XMON: ... */
-#define SYS_xmon_in -3 /* invoked by XMON: ... */
-#define SYS_xmon_flush -4 /* invoked by XMON: ... */
-#define SYS_gdb_abort -5 /* invoked by XTOS in _xtos_panic() */
-#define SYS_gdb_illegal_inst -6 /* invoked by XTOS for illegal instructions (too deeply) */
-#define SYS_xmon_init -7 /* invoked by XMON: ... */
-#define SYS_gdb_enter_sktloop -8 /* invoked by XTOS on debug exceptions */
-
-/*
- * SIMCALLs for vxWorks xtiss BSP:
- */
-#define SYS_setup_ppp_pipes -83
-#define SYS_log_msg -84
-
-/*
- * Test SIMCALLs:
- */
-#define SYS_test_write_state -100
-#define SYS_test_read_state -101
-
-/*
- * SYS_select_one specifiers
- */
-#define XTISS_SELECT_ONE_READ 1
-#define XTISS_SELECT_ONE_WRITE 2
-#define XTISS_SELECT_ONE_EXCEPT 3
-
-#endif /* !SIMCALL_INCLUDED */
diff --git a/include/asm-xtensa/xtensa/xt2000-uart.h b/include/asm-xtensa/xtensa/xt2000-uart.h
deleted file mode 100644
index 0154460f0ed..00000000000
--- a/include/asm-xtensa/xtensa/xt2000-uart.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef _uart_h_included_
-#define _uart_h_included_
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/xt2000-uart.h -- NatSemi PC16552D DUART
- * definitions
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/xt2000.h>
-
-
-/* 16550 UART DEVICE REGISTERS
- The XT2000 board aligns each register to a 32-bit word but the UART device only uses
- one byte of the word, which is the least-significant byte regardless of the
- endianness of the core (ie. byte offset 0 for little-endian and 3 for big-endian).
- So if using word accesses then endianness doesn't matter.
- The macros provided here do that.
-*/
-struct uart_dev_s {
- union {
- unsigned int rxb; /* DLAB=0: receive buffer, read-only */
- unsigned int txb; /* DLAB=0: transmit buffer, write-only */
- unsigned int dll; /* DLAB=1: divisor, least-significant byte latch (was write-only?) */
- } w0;
- union {
- unsigned int ier; /* DLAB=0: interrupt-enable register (was write-only?) */
- unsigned int dlm; /* DLAB=1: divisor, most-significant byte latch (was write-only?) */
- } w1;
-
- union {
- unsigned int isr; /* DLAB=0: interrupt status register, read-only */
- unsigned int fcr; /* DLAB=0: FIFO control register, write-only */
- unsigned int afr; /* DLAB=1: alternate function register */
- } w2;
-
- unsigned int lcr; /* line control-register, write-only */
- unsigned int mcr; /* modem control-regsiter, write-only */
- unsigned int lsr; /* line status register, read-only */
- unsigned int msr; /* modem status register, read-only */
- unsigned int scr; /* scratch regsiter, read/write */
-};
-
-#define _RXB(u) ((u)->w0.rxb)
-#define _TXB(u) ((u)->w0.txb)
-#define _DLL(u) ((u)->w0.dll)
-#define _IER(u) ((u)->w1.ier)
-#define _DLM(u) ((u)->w1.dlm)
-#define _ISR(u) ((u)->w2.isr)
-#define _FCR(u) ((u)->w2.fcr)
-#define _AFR(u) ((u)->w2.afr)
-#define _LCR(u) ((u)->lcr)
-#define _MCR(u) ((u)->mcr)
-#define _LSR(u) ((u)->lsr)
-#define _MSR(u) ((u)->msr)
-#define _SCR(u) ((u)->scr)
-
-typedef volatile struct uart_dev_s uart_dev_t;
-
-/* IER bits */
-#define RCVR_DATA_REG_INTENABLE 0x01
-#define XMIT_HOLD_REG_INTENABLE 0x02
-#define RCVR_STATUS_INTENABLE 0x04
-#define MODEM_STATUS_INTENABLE 0x08
-
-/* FCR bits */
-#define _FIFO_ENABLE 0x01
-#define RCVR_FIFO_RESET 0x02
-#define XMIT_FIFO_RESET 0x04
-#define DMA_MODE_SELECT 0x08
-#define RCVR_TRIGGER_LSB 0x40
-#define RCVR_TRIGGER_MSB 0x80
-
-/* AFR bits */
-#define AFR_CONC_WRITE 0x01
-#define AFR_BAUDOUT_SEL 0x02
-#define AFR_RXRDY_SEL 0x04
-
-/* ISR bits */
-#define INT_STATUS(r) ((r)&1)
-#define INT_PRIORITY(r) (((r)>>1)&0x7)
-
-/* LCR bits */
-#define WORD_LENGTH(n) (((n)-5)&0x3)
-#define STOP_BIT_ENABLE 0x04
-#define PARITY_ENABLE 0x08
-#define EVEN_PARITY 0x10
-#define FORCE_PARITY 0x20
-#define XMIT_BREAK 0x40
-#define DLAB_ENABLE 0x80
-
-/* MCR bits */
-#define _DTR 0x01
-#define _RTS 0x02
-#define _OP1 0x04
-#define _OP2 0x08
-#define LOOP_BACK 0x10
-
-/* LSR Bits */
-#define RCVR_DATA_READY 0x01
-#define OVERRUN_ERROR 0x02
-#define PARITY_ERROR 0x04
-#define FRAMING_ERROR 0x08
-#define BREAK_INTERRUPT 0x10
-#define XMIT_HOLD_EMPTY 0x20
-#define XMIT_EMPTY 0x40
-#define FIFO_ERROR 0x80
-#define RCVR_READY(u) (_LSR(u)&RCVR_DATA_READY)
-#define XMIT_READY(u) (_LSR(u)&XMIT_HOLD_EMPTY)
-
-/* MSR bits */
-#define _RDR 0x01
-#define DELTA_DSR 0x02
-#define DELTA_RI 0x04
-#define DELTA_CD 0x08
-#define _CTS 0x10
-#define _DSR 0x20
-#define _RI 0x40
-#define _CD 0x80
-
-/* prototypes */
-void uart_init( uart_dev_t *u, int bitrate );
-void uart_out( uart_dev_t *u, char c );
-void uart_puts( uart_dev_t *u, char *s );
-char uart_in( uart_dev_t *u );
-void uart_enable_rcvr_int( uart_dev_t *u );
-void uart_disable_rcvr_int( uart_dev_t *u );
-
-#ifdef DUART16552_1_VADDR
-/* DUART present. */
-#define DUART_1_BASE (*(uart_dev_t*)DUART16552_1_VADDR)
-#define DUART_2_BASE (*(uart_dev_t*)DUART16552_2_VADDR)
-#define UART1_PUTS(s) uart_puts( &DUART_1_BASE, s )
-#define UART2_PUTS(s) uart_puts( &DUART_2_BASE, s )
-#else
-/* DUART not configured, use dummy placeholders to allow compiles to work. */
-#define DUART_1_BASE (*(uart_dev_t*)0)
-#define DUART_2_BASE (*(uart_dev_t*)0)
-#define UART1_PUTS(s)
-#define UART2_PUTS(s)
-#endif
-
-/* Compute 16-bit divisor for baudrate generator, with rounding: */
-#define DUART_DIVISOR(crystal,speed) (((crystal)/16 + (speed)/2)/(speed))
-
-#endif /*_uart_h_included_*/
-
diff --git a/include/asm-xtensa/xtensa/xt2000.h b/include/asm-xtensa/xtensa/xt2000.h
deleted file mode 100644
index 703a45002f8..00000000000
--- a/include/asm-xtensa/xtensa/xt2000.h
+++ /dev/null
@@ -1,408 +0,0 @@
-#ifndef _INC_XT2000_H_
-#define _INC_XT2000_H_
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * include/asm-xtensa/xtensa/xt2000.h - Definitions specific to the
- * Tensilica XT2000 Emulation Board
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/config/core.h>
-#include <xtensa/config/system.h>
-
-
-/*
- * Default assignment of XT2000 devices to external interrupts.
- */
-
-/* Ethernet interrupt: */
-#ifdef XCHAL_EXTINT3_NUM
-#define SONIC83934_INTNUM XCHAL_EXTINT3_NUM
-#define SONIC83934_INTLEVEL XCHAL_EXTINT3_LEVEL
-#define SONIC83934_INTMASK XCHAL_EXTINT3_MASK
-#else
-#define SONIC83934_INTMASK 0
-#endif
-
-/* DUART channel 1 interrupt (P1 - console): */
-#ifdef XCHAL_EXTINT4_NUM
-#define DUART16552_1_INTNUM XCHAL_EXTINT4_NUM
-#define DUART16552_1_INTLEVEL XCHAL_EXTINT4_LEVEL
-#define DUART16552_1_INTMASK XCHAL_EXTINT4_MASK
-#else
-#define DUART16552_1_INTMASK 0
-#endif
-
-/* DUART channel 2 interrupt (P2 - 2nd serial port): */
-#ifdef XCHAL_EXTINT5_NUM
-#define DUART16552_2_INTNUM XCHAL_EXTINT5_NUM
-#define DUART16552_2_INTLEVEL XCHAL_EXTINT5_LEVEL
-#define DUART16552_2_INTMASK XCHAL_EXTINT5_MASK
-#else
-#define DUART16552_2_INTMASK 0
-#endif
-
-/* FPGA-combined PCI/etc interrupts: */
-#ifdef XCHAL_EXTINT6_NUM
-#define XT2000_FPGAPCI_INTNUM XCHAL_EXTINT6_NUM
-#define XT2000_FPGAPCI_INTLEVEL XCHAL_EXTINT6_LEVEL
-#define XT2000_FPGAPCI_INTMASK XCHAL_EXTINT6_MASK
-#else
-#define XT2000_FPGAPCI_INTMASK 0
-#endif
-
-
-
-/*
- * Device addresses.
- *
- * Note: for endianness-independence, use 32-bit loads and stores for all
- * register accesses to Ethernet, DUART and LED devices. Undefined bits
- * may need to be masked out if needed when reading if the actual register
- * size is smaller than 32 bits.
- *
- * Note: XT2000 bus byte lanes are defined in terms of msbyte and lsbyte
- * relative to the processor. So 32-bit registers are accessed consistently
- * from both big and little endian processors. However, this means byte
- * sequences are not consistent between big and little endian processors.
- * This is fine for RAM, and for ROM if ROM is created for a specific
- * processor (and thus has correct byte sequences). However this may be
- * unexpected for Flash, which might contain a file-system that one wants
- * to use for multiple processor configurations (eg. the Flash might contain
- * the Ethernet card's address, endianness-independent application data, etc).
- * That is, byte sequences written in Flash by a core of a given endianness
- * will be byte-swapped when seen by a core of the other endianness.
- * Someone implementing an endianness-independent Flash file system will
- * likely handle this byte-swapping issue in the Flash driver software.
- */
-
-#define DUART16552_XTAL_FREQ 18432000 /* crystal frequency in Hz */
-#define XTBOARD_FLASH_MAXSIZE 0x4000000 /* 64 MB (max; depends on what is socketed!) */
-#define XTBOARD_EPROM_MAXSIZE 0x0400000 /* 4 MB (max; depends on what is socketed!) */
-#define XTBOARD_EEPROM_MAXSIZE 0x0080000 /* 512 kB (max; depends on what is socketed!) */
-#define XTBOARD_ASRAM_SIZE 0x0100000 /* 1 MB */
-#define XTBOARD_PCI_MEM_SIZE 0x8000000 /* 128 MB (allocated) */
-#define XTBOARD_PCI_IO_SIZE 0x1000000 /* 16 MB (allocated) */
-
-#ifdef XSHAL_IOBLOCK_BYPASS_PADDR
-/* PCI memory space: */
-# define XTBOARD_PCI_MEM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0000000)
-/* Socketed Flash (eg. 2 x 16-bit devices): */
-# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x8000000)
-/* PCI I/O space: */
-# define XTBOARD_PCI_IO_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xC000000)
-/* V3 PCI interface chip register/config space: */
-# define XTBOARD_V3PCI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD000000)
-/* Bus Interface registers: */
-# define XTBOARD_BUSINT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD010000)
-/* FPGA registers: */
-# define XT2000_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD020000)
-/* SONIC SN83934 Ethernet controller/transceiver: */
-# define SONIC83934_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD030000)
-/* 8-character bitmapped LED display: */
-# define XTBOARD_LED_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD040000)
-/* National-Semi PC16552D DUART: */
-# define DUART16552_1_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050020) /* channel 1 (P1 - console) */
-# define DUART16552_2_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050000) /* channel 2 (P2) */
-/* Asynchronous Static RAM: */
-# define XTBOARD_ASRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD400000)
-/* 8-bit EEPROM: */
-# define XTBOARD_EEPROM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD600000)
-/* 2 x 16-bit EPROMs: */
-# define XTBOARD_EPROM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */
-
-/* These devices might be accessed cached: */
-#ifdef XSHAL_IOBLOCK_CACHED_PADDR
-# define XTBOARD_PCI_MEM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0000000)
-# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x8000000)
-# define XTBOARD_ASRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD400000)
-# define XTBOARD_EEPROM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD600000)
-# define XTBOARD_EPROM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_CACHED_PADDR */
-
-
-/*** Same thing over again, this time with virtual addresses: ***/
-
-#ifdef XSHAL_IOBLOCK_BYPASS_VADDR
-/* PCI memory space: */
-# define XTBOARD_PCI_MEM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0000000)
-/* Socketed Flash (eg. 2 x 16-bit devices): */
-# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x8000000)
-/* PCI I/O space: */
-# define XTBOARD_PCI_IO_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xC000000)
-/* V3 PCI interface chip register/config space: */
-# define XTBOARD_V3PCI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD000000)
-/* Bus Interface registers: */
-# define XTBOARD_BUSINT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD010000)
-/* FPGA registers: */
-# define XT2000_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD020000)
-/* SONIC SN83934 Ethernet controller/transceiver: */
-# define SONIC83934_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD030000)
-/* 8-character bitmapped LED display: */
-# define XTBOARD_LED_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD040000)
-/* National-Semi PC16552D DUART: */
-# define DUART16552_1_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050020) /* channel 1 (P1 - console) */
-# define DUART16552_2_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050000) /* channel 2 (P2) */
-/* Asynchronous Static RAM: */
-# define XTBOARD_ASRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD400000)
-/* 8-bit EEPROM: */
-# define XTBOARD_EEPROM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD600000)
-/* 2 x 16-bit EPROMs: */
-# define XTBOARD_EPROM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */
-
-/* These devices might be accessed cached: */
-#ifdef XSHAL_IOBLOCK_CACHED_VADDR
-# define XTBOARD_PCI_MEM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0000000)
-# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x8000000)
-# define XTBOARD_ASRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD400000)
-# define XTBOARD_EEPROM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD600000)
-# define XTBOARD_EPROM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD800000)
-#endif /* XSHAL_IOBLOCK_CACHED_VADDR */
-
-
-/* System ROM: */
-#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE
-#ifdef XSHAL_ROM_VADDR
-#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR
-#endif
-#ifdef XSHAL_ROM_PADDR
-#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR
-#endif
-
-/* System RAM: */
-#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE
-#ifdef XSHAL_RAM_VADDR
-#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR
-#endif
-#ifdef XSHAL_RAM_PADDR
-#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR
-#endif
-#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR
-#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR
-
-
-
-/*
- * Things that depend on device addresses.
- */
-
-
-#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK
-#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC
-#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU
-#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS
-#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT
-
-#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS
-#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS
-
-
-
-/*
- * BusLogic (FPGA) registers.
- * All these registers are normally accessed using 32-bit loads/stores.
- */
-
-/* Register offsets: */
-#define XT2000_DATECD_OFS 0x00 /* date code (read-only) */
-#define XT2000_STSREG_OFS 0x04 /* status (read-only) */
-#define XT2000_SYSLED_OFS 0x08 /* system LED */
-#define XT2000_WRPROT_OFS 0x0C /* write protect */
-#define XT2000_SWRST_OFS 0x10 /* software reset */
-#define XT2000_SYSRST_OFS 0x14 /* system (peripherals) reset */
-#define XT2000_IMASK_OFS 0x18 /* interrupt mask */
-#define XT2000_ISTAT_OFS 0x1C /* interrupt status */
-#define XT2000_V3CFG_OFS 0x20 /* V3 config (V320 PCI) */
-
-/* Physical register addresses: */
-#ifdef XT2000_FPGAREGS_PADDR
-#define XT2000_DATECD_PADDR (XT2000_FPGAREGS_PADDR+XT2000_DATECD_OFS)
-#define XT2000_STSREG_PADDR (XT2000_FPGAREGS_PADDR+XT2000_STSREG_OFS)
-#define XT2000_SYSLED_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SYSLED_OFS)
-#define XT2000_WRPROT_PADDR (XT2000_FPGAREGS_PADDR+XT2000_WRPROT_OFS)
-#define XT2000_SWRST_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SWRST_OFS)
-#define XT2000_SYSRST_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SYSRST_OFS)
-#define XT2000_IMASK_PADDR (XT2000_FPGAREGS_PADDR+XT2000_IMASK_OFS)
-#define XT2000_ISTAT_PADDR (XT2000_FPGAREGS_PADDR+XT2000_ISTAT_OFS)
-#define XT2000_V3CFG_PADDR (XT2000_FPGAREGS_PADDR+XT2000_V3CFG_OFS)
-#endif
-
-/* Virtual register addresses: */
-#ifdef XT2000_FPGAREGS_VADDR
-#define XT2000_DATECD_VADDR (XT2000_FPGAREGS_VADDR+XT2000_DATECD_OFS)
-#define XT2000_STSREG_VADDR (XT2000_FPGAREGS_VADDR+XT2000_STSREG_OFS)
-#define XT2000_SYSLED_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SYSLED_OFS)
-#define XT2000_WRPROT_VADDR (XT2000_FPGAREGS_VADDR+XT2000_WRPROT_OFS)
-#define XT2000_SWRST_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SWRST_OFS)
-#define XT2000_SYSRST_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SYSRST_OFS)
-#define XT2000_IMASK_VADDR (XT2000_FPGAREGS_VADDR+XT2000_IMASK_OFS)
-#define XT2000_ISTAT_VADDR (XT2000_FPGAREGS_VADDR+XT2000_ISTAT_OFS)
-#define XT2000_V3CFG_VADDR (XT2000_FPGAREGS_VADDR+XT2000_V3CFG_OFS)
-/* Register access (for C code): */
-#define XT2000_DATECD_REG (*(volatile unsigned*) XT2000_DATECD_VADDR)
-#define XT2000_STSREG_REG (*(volatile unsigned*) XT2000_STSREG_VADDR)
-#define XT2000_SYSLED_REG (*(volatile unsigned*) XT2000_SYSLED_VADDR)
-#define XT2000_WRPROT_REG (*(volatile unsigned*) XT2000_WRPROT_VADDR)
-#define XT2000_SWRST_REG (*(volatile unsigned*) XT2000_SWRST_VADDR)
-#define XT2000_SYSRST_REG (*(volatile unsigned*) XT2000_SYSRST_VADDR)
-#define XT2000_IMASK_REG (*(volatile unsigned*) XT2000_IMASK_VADDR)
-#define XT2000_ISTAT_REG (*(volatile unsigned*) XT2000_ISTAT_VADDR)
-#define XT2000_V3CFG_REG (*(volatile unsigned*) XT2000_V3CFG_VADDR)
-#endif
-
-/* DATECD (date code) bit fields: */
-
-/* BCD-coded month (01..12): */
-#define XT2000_DATECD_MONTH_SHIFT 24
-#define XT2000_DATECD_MONTH_BITS 8
-#define XT2000_DATECD_MONTH_MASK 0xFF000000
-/* BCD-coded day (01..31): */
-#define XT2000_DATECD_DAY_SHIFT 16
-#define XT2000_DATECD_DAY_BITS 8
-#define XT2000_DATECD_DAY_MASK 0x00FF0000
-/* BCD-coded year (2001..9999): */
-#define XT2000_DATECD_YEAR_SHIFT 0
-#define XT2000_DATECD_YEAR_BITS 16
-#define XT2000_DATECD_YEAR_MASK 0x0000FFFF
-
-/* STSREG (status) bit fields: */
-
-/* Switch SW3 setting bit fields (0=off/up, 1=on/down): */
-#define XT2000_STSREG_SW3_SHIFT 0
-#define XT2000_STSREG_SW3_BITS 4
-#define XT2000_STSREG_SW3_MASK 0x0000000F
-/* Boot-select bits of switch SW3: */
-#define XT2000_STSREG_BOOTSEL_SHIFT 0
-#define XT2000_STSREG_BOOTSEL_BITS 2
-#define XT2000_STSREG_BOOTSEL_MASK 0x00000003
-/* Boot-select values: */
-#define XT2000_STSREG_BOOTSEL_FLASH 0
-#define XT2000_STSREG_BOOTSEL_EPROM16 1
-#define XT2000_STSREG_BOOTSEL_PROM8 2
-#define XT2000_STSREG_BOOTSEL_ASRAM 3
-/* User-defined bits of switch SW3: */
-#define XT2000_STSREG_SW3_2_SHIFT 2
-#define XT2000_STSREG_SW3_2_MASK 0x00000004
-#define XT2000_STSREG_SW3_3_SHIFT 3
-#define XT2000_STSREG_SW3_3_MASK 0x00000008
-
-/* SYSLED (system LED) bit fields: */
-
-/* LED control bit (0=off, 1=on): */
-#define XT2000_SYSLED_LEDON_SHIFT 0
-#define XT2000_SYSLED_LEDON_MASK 0x00000001
-
-/* WRPROT (write protect) bit fields (0=writable, 1=write-protected [default]): */
-
-/* Flash write protect: */
-#define XT2000_WRPROT_FLWP_SHIFT 0
-#define XT2000_WRPROT_FLWP_MASK 0x00000001
-/* Reserved but present write protect bits: */
-#define XT2000_WRPROT_WRP_SHIFT 1
-#define XT2000_WRPROT_WRP_BITS 7
-#define XT2000_WRPROT_WRP_MASK 0x000000FE
-
-/* SWRST (software reset; allows s/w to generate power-on equivalent reset): */
-
-/* Software reset bits: */
-#define XT2000_SWRST_SWR_SHIFT 0
-#define XT2000_SWRST_SWR_BITS 16
-#define XT2000_SWRST_SWR_MASK 0x0000FFFF
-/* Software reset value -- writing this value resets the board: */
-#define XT2000_SWRST_RESETVALUE 0x0000DEAD
-
-/* SYSRST (system reset; controls reset of individual peripherals): */
-
-/* All-device reset: */
-#define XT2000_SYSRST_ALL_SHIFT 0
-#define XT2000_SYSRST_ALL_BITS 4
-#define XT2000_SYSRST_ALL_MASK 0x0000000F
-/* HDSP-2534 LED display reset (1=reset, 0=nothing): */
-#define XT2000_SYSRST_LED_SHIFT 0
-#define XT2000_SYSRST_LED_MASK 0x00000001
-/* Sonic DP83934 Ethernet controller reset (1=reset, 0=nothing): */
-#define XT2000_SYSRST_SONIC_SHIFT 1
-#define XT2000_SYSRST_SONIC_MASK 0x00000002
-/* DP16552 DUART reset (1=reset, 0=nothing): */
-#define XT2000_SYSRST_DUART_SHIFT 2
-#define XT2000_SYSRST_DUART_MASK 0x00000004
-/* V3 V320 PCI bridge controller reset (1=reset, 0=nothing): */
-#define XT2000_SYSRST_V3_SHIFT 3
-#define XT2000_SYSRST_V3_MASK 0x00000008
-
-/* IMASK (interrupt mask; 0=disable, 1=enable): */
-/* ISTAT (interrupt status; 0=inactive, 1=pending): */
-
-/* PCI INTP interrupt: */
-#define XT2000_INTMUX_PCI_INTP_SHIFT 2
-#define XT2000_INTMUX_PCI_INTP_MASK 0x00000004
-/* PCI INTS interrupt: */
-#define XT2000_INTMUX_PCI_INTS_SHIFT 3
-#define XT2000_INTMUX_PCI_INTS_MASK 0x00000008
-/* PCI INTD interrupt: */
-#define XT2000_INTMUX_PCI_INTD_SHIFT 4
-#define XT2000_INTMUX_PCI_INTD_MASK 0x00000010
-/* V320 PCI controller interrupt: */
-#define XT2000_INTMUX_V3_SHIFT 5
-#define XT2000_INTMUX_V3_MASK 0x00000020
-/* PCI ENUM interrupt: */
-#define XT2000_INTMUX_PCI_ENUM_SHIFT 6
-#define XT2000_INTMUX_PCI_ENUM_MASK 0x00000040
-/* PCI DEG interrupt: */
-#define XT2000_INTMUX_PCI_DEG_SHIFT 7
-#define XT2000_INTMUX_PCI_DEG_MASK 0x00000080
-
-/* V3CFG (V3 config, V320 PCI controller): */
-
-/* V3 address control (0=pass-thru, 1=V3 address bits 31:28 set to 4'b0001 [default]): */
-#define XT2000_V3CFG_V3ADC_SHIFT 0
-#define XT2000_V3CFG_V3ADC_MASK 0x00000001
-
-/* I2C Devices */
-
-#define XT2000_I2C_RTC_ID 0x68
-#define XT2000_I2C_NVRAM0_ID 0x56 /* 1st 256 byte block */
-#define XT2000_I2C_NVRAM1_ID 0x57 /* 2nd 256 byte block */
-
-/* NVRAM Board Info structure: */
-
-#define XT2000_NVRAM_SIZE 512
-
-#define XT2000_NVRAM_BINFO_START 0x100
-#define XT2000_NVRAM_BINFO_SIZE 0x20
-#define XT2000_NVRAM_BINFO_VERSION 0x10 /* version 1.0 */
-#if 0
-#define XT2000_NVRAM_BINFO_VERSION_OFFSET 0x00
-#define XT2000_NVRAM_BINFO_VERSION_SIZE 0x1
-#define XT2000_NVRAM_BINFO_ETH_ADDR_OFFSET 0x02
-#define XT2000_NVRAM_BINFO_ETH_ADDR_SIZE 0x6
-#define XT2000_NVRAM_BINFO_SN_OFFSET 0x10
-#define XT2000_NVRAM_BINFO_SN_SIZE 0xE
-#define XT2000_NVRAM_BINFO_CRC_OFFSET 0x1E
-#define XT2000_NVRAM_BINFO_CRC_SIZE 0x2
-#endif /*0*/
-
-#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
-typedef struct xt2000_nvram_binfo {
- unsigned char version;
- unsigned char reserved1;
- unsigned char eth_addr[6];
- unsigned char reserved8[8];
- unsigned char serialno[14];
- unsigned char crc[2]; /* 16-bit CRC */
-} xt2000_nvram_binfo;
-#endif /*!__ASSEMBLY__ && !_NOCLANGUAGE*/
-
-
-#endif /*_INC_XT2000_H_*/
-
diff --git a/include/asm-xtensa/xtensa/xtboard.h b/include/asm-xtensa/xtensa/xtboard.h
deleted file mode 100644
index 22469c17530..00000000000
--- a/include/asm-xtensa/xtensa/xtboard.h
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef _xtboard_h_included_
-#define _xtboard_h_included_
-
-/*
- * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
- *
- * xtboard.h -- Routines for getting useful information from the board.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002 Tensilica Inc.
- */
-
-
-#include <xtensa/xt2000.h>
-
-#define XTBOARD_RTC_ERROR -1
-#define XTBOARD_RTC_STOPPED -2
-
-
-/* xt2000-i2cdev.c: */
-typedef void XtboardDelayFunc( unsigned );
-extern XtboardDelayFunc* xtboard_set_nsdelay_func( XtboardDelayFunc *delay_fn );
-extern int xtboard_i2c_read (unsigned id, unsigned char *buf, unsigned addr, unsigned size);
-extern int xtboard_i2c_write(unsigned id, unsigned char *buf, unsigned addr, unsigned size);
-extern int xtboard_i2c_wait_nvram_ack(unsigned id, unsigned swtimer);
-
-/* xtboard.c: */
-extern int xtboard_nvram_read (unsigned addr, unsigned len, unsigned char *buf);
-extern int xtboard_nvram_write(unsigned addr, unsigned len, unsigned char *buf);
-extern int xtboard_nvram_binfo_read (xt2000_nvram_binfo *buf);
-extern int xtboard_nvram_binfo_write(xt2000_nvram_binfo *buf);
-extern int xtboard_nvram_binfo_valid(xt2000_nvram_binfo *buf);
-extern int xtboard_ethermac_get(unsigned char *buf);
-extern int xtboard_ethermac_set(unsigned char *buf);
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_get_rtc_time
-/
-/ Description: Get time stored in real-time clock.
-/
-/ Returns: time in seconds stored in real-time clock.
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_get_rtc_time(void);
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_set_rtc_time
-/
-/ Description: Set time stored in real-time clock.
-/
-/ Parameters: time -- time in seconds to store to real-time clock
-/
-/ Returns: 0 on success, xtboard_i2c_write() error code otherwise.
-/-**----------------------------------------------------------------------------*/
-
-extern int xtboard_set_rtc_time(unsigned time);
-
-
-/* xtfreq.c: */
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_measure_sys_clk
-/
-/ Description: Get frequency of system clock.
-/
-/ Parameters: none
-/
-/ Returns: frequency of system clock.
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_measure_sys_clk(void);
-
-
-#if 0 /* old stuff from xtboard.c: */
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_nvram valid
-/
-/ Description: Determines if data in NVRAM is valid.
-/
-/ Parameters: delay -- 10us delay function
-/
-/ Returns: 1 if NVRAM is valid, 0 otherwise
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_nvram_valid(void (*delay)( void ));
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_get_nvram_contents
-/
-/ Description: Returns contents of NVRAM.
-/
-/ Parameters: buf -- buffer to NVRAM contents.
-/ delay -- 10us delay function
-/
-/ Returns: 1 if NVRAM is valid, 0 otherwise
-/-**----------------------------------------------------------------------------*/
-
-extern unsigned xtboard_get_nvram_contents(unsigned char *buf, void (*delay)( void ));
-
-/*+*----------------------------------------------------------------------------
-/ Function: xtboard_get_ether_addr
-/
-/ Description: Returns ethernet address of board.
-/
-/ Parameters: buf -- buffer to store ethernet address
-/ delay -- 10us delay function
-/
-/ Returns: nothing.
-/-**----------------------------------------------------------------------------*/
-
-extern void xtboard_get_ether_addr(unsigned char *buf, void (*delay)( void ));
-
-#endif /*0*/
-
-
-#endif /*_xtboard_h_included_*/
-
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index e618b25b5ad..157db77a717 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -61,7 +61,6 @@ header-y += fd.h
header-y += fdreg.h
header-y += fib_rules.h
header-y += fuse.h
-header-y += futex.h
header-y += genetlink.h
header-y += gen_stats.h
header-y += gigaset_dev.h
@@ -70,7 +69,6 @@ header-y += hysdn_if.h
header-y += i2c-dev.h
header-y += i8k.h
header-y += icmp.h
-header-y += if_addr.h
header-y += if_arcnet.h
header-y += if_arp.h
header-y += if_bonding.h
@@ -80,7 +78,6 @@ header-y += if_fddi.h
header-y += if.h
header-y += if_hippi.h
header-y += if_infiniband.h
-header-y += if_link.h
header-y += if_packet.h
header-y += if_plip.h
header-y += if_ppp.h
@@ -120,7 +117,6 @@ header-y += nfs4_mount.h
header-y += nfs_mount.h
header-y += oom.h
header-y += param.h
-header-y += pci_ids.h
header-y += pci_regs.h
header-y += personality.h
header-y += pfkeyv2.h
@@ -131,7 +127,6 @@ header-y += posix_types.h
header-y += ppdev.h
header-y += prctl.h
header-y += ps2esdi.h
-header-y += qic117.h
header-y += qnxtypes.h
header-y += quotaio_v1.h
header-y += quotaio_v2.h
@@ -139,7 +134,6 @@ header-y += radeonfb.h
header-y += raw.h
header-y += resource.h
header-y += rose.h
-header-y += sctp.h
header-y += smbno.h
header-y += snmp.h
header-y += sockios.h
@@ -163,7 +157,6 @@ header-y += vt.h
header-y += wireless.h
header-y += xattr.h
header-y += x25.h
-header-y += zorro_ids.h
unifdef-y += acct.h
unifdef-y += adb.h
@@ -203,6 +196,7 @@ unifdef-y += fb.h
unifdef-y += fcntl.h
unifdef-y += filter.h
unifdef-y += flat.h
+unifdef-y += futex.h
unifdef-y += fs.h
unifdef-y += gameport.h
unifdef-y += generic_serial.h
@@ -217,6 +211,7 @@ unifdef-y += hpet.h
unifdef-y += i2c.h
unifdef-y += i2o-dev.h
unifdef-y += icmpv6.h
+unifdef-y += if_addr.h
unifdef-y += if_bridge.h
unifdef-y += if_ec.h
unifdef-y += if_eql.h
@@ -224,6 +219,7 @@ unifdef-y += if_ether.h
unifdef-y += if_fddi.h
unifdef-y += if_frad.h
unifdef-y += if_ltalk.h
+unifdef-y += if_link.h
unifdef-y += if_pppox.h
unifdef-y += if_shaper.h
unifdef-y += if_tr.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 2b0c955590f..91f1f236387 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -47,6 +47,7 @@ enum acpi_irq_model_id {
ACPI_IRQ_MODEL_PIC = 0,
ACPI_IRQ_MODEL_IOAPIC,
ACPI_IRQ_MODEL_IOSAPIC,
+ ACPI_IRQ_MODEL_PLATFORM,
ACPI_IRQ_MODEL_COUNT
};
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 3372ec6bf53..a30ef13c9e6 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -105,6 +105,7 @@ struct kiocb {
wait_queue_t ki_wait;
loff_t ki_pos;
+ atomic_t ki_bio_count; /* num bio used for this iocb */
void *private;
/* State that we remember to be able to restart/retry */
unsigned short ki_opcode;
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 75e91f5b6a0..a5cf1beacb4 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -54,7 +54,7 @@ struct backlight_device {
};
extern struct backlight_device *backlight_device_register(const char *name,
- void *devdata, struct backlight_properties *bp);
+ struct device *dev,void *devdata,struct backlight_properties *bp);
extern void backlight_device_unregister(struct backlight_device *bd);
#define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 092dbd0e765..08daf3272c0 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -309,6 +309,7 @@ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
gfp_t);
extern void bio_set_pages_dirty(struct bio *bio);
extern void bio_check_pages_dirty(struct bio *bio);
+extern void bio_release_pages(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);
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 5d1eabcde5d..638165f571d 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -31,9 +31,8 @@ static inline unsigned long hweight_long(unsigned long w)
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}
-/*
+/**
* rol32 - rotate a 32-bit value left
- *
* @word: value to rotate
* @shift: bits to roll
*/
@@ -42,9 +41,8 @@ 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
*/
diff --git a/include/linux/bitrev.h b/include/linux/bitrev.h
new file mode 100644
index 00000000000..05e540d6963
--- /dev/null
+++ b/include/linux/bitrev.h
@@ -0,0 +1,15 @@
+#ifndef _LINUX_BITREV_H
+#define _LINUX_BITREV_H
+
+#include <linux/types.h>
+
+extern u8 const byte_rev_table[256];
+
+static inline u8 bitrev8(u8 byte)
+{
+ return byte_rev_table[byte];
+}
+
+extern u32 bitrev32(u32 in);
+
+#endif /* _LINUX_BITREV_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index e1c7286165f..36a6eacefe2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -331,10 +331,6 @@ struct request_pm_state
#include <linux/elevator.h>
-typedef int (merge_request_fn) (request_queue_t *, struct request *,
- struct bio *);
-typedef int (merge_requests_fn) (request_queue_t *, struct request *,
- struct request *);
typedef void (request_fn_proc) (request_queue_t *q);
typedef int (make_request_fn) (request_queue_t *q, struct bio *bio);
typedef int (prep_rq_fn) (request_queue_t *, struct request *);
@@ -342,7 +338,6 @@ typedef void (unplug_fn) (request_queue_t *);
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 void (prepare_flush_fn) (request_queue_t *, struct request *);
typedef void (softirq_done_fn)(struct request *);
@@ -377,14 +372,10 @@ struct request_queue
struct request_list rq;
request_fn_proc *request_fn;
- merge_request_fn *back_merge_fn;
- merge_request_fn *front_merge_fn;
- merge_requests_fn *merge_requests_fn;
make_request_fn *make_request_fn;
prep_rq_fn *prep_rq_fn;
unplug_fn *unplug_fn;
merge_bvec_fn *merge_bvec_fn;
- activity_fn *activity_fn;
issue_flush_fn *issue_flush_fn;
prepare_flush_fn *prepare_flush_fn;
softirq_done_fn *softirq_done_fn;
@@ -411,8 +402,6 @@ struct request_queue
*/
void *queuedata;
- void *activity_data;
-
/*
* queue needs bounce pages for pages above this limit
*/
@@ -653,6 +642,11 @@ extern int sg_scsi_ioctl(struct file *, struct request_queue *,
struct gendisk *, struct scsi_ioctl_command __user *);
/*
+ * Temporary export, until SCSI gets fixed up.
+ */
+extern int ll_back_merge_fn(request_queue_t *, struct request *, struct bio *);
+
+/*
* A queue has just exitted congestion. Note this in the global counter of
* congested queues, and wake up anyone who was waiting for requests to be
* put back.
@@ -677,9 +671,8 @@ extern void blk_sync_queue(struct request_queue *q);
extern void __blk_stop_queue(request_queue_t *q);
extern void blk_run_queue(request_queue_t *);
extern void blk_start_queueing(request_queue_t *);
-extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long);
-extern int blk_rq_unmap_user(struct request *);
+extern int blk_rq_unmap_user(struct bio *);
extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
extern int blk_rq_map_user_iov(request_queue_t *, struct request *,
struct sg_iovec *, int, unsigned int);
diff --git a/include/linux/bug.h b/include/linux/bug.h
new file mode 100644
index 00000000000..42aa0a54b6f
--- /dev/null
+++ b/include/linux/bug.h
@@ -0,0 +1,47 @@
+#ifndef _LINUX_BUG_H
+#define _LINUX_BUG_H
+
+#include <linux/module.h>
+#include <asm/bug.h>
+
+enum bug_trap_type {
+ BUG_TRAP_TYPE_NONE = 0,
+ BUG_TRAP_TYPE_WARN = 1,
+ BUG_TRAP_TYPE_BUG = 2,
+};
+
+#ifdef CONFIG_GENERIC_BUG
+#include <asm-generic/bug.h>
+
+static inline int is_warning_bug(const struct bug_entry *bug)
+{
+ return bug->flags & BUGFLAG_WARNING;
+}
+
+const struct bug_entry *find_bug(unsigned long bugaddr);
+
+enum bug_trap_type report_bug(unsigned long bug_addr);
+
+int module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *,
+ struct module *);
+void module_bug_cleanup(struct module *);
+
+/* These are defined by the architecture */
+int is_valid_bugaddr(unsigned long addr);
+
+#else /* !CONFIG_GENERIC_BUG */
+
+static inline enum bug_trap_type report_bug(unsigned long bug_addr)
+{
+ return BUG_TRAP_TYPE_BUG;
+}
+static inline int module_bug_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *mod)
+{
+ return 0;
+}
+static inline void module_bug_cleanup(struct module *mod) {}
+
+#endif /* CONFIG_GENERIC_BUG */
+#endif /* _LINUX_BUG_H */
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index f309b00e986..1e29b13d006 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -6,6 +6,10 @@
#include <linux/kdev_t.h>
#include <linux/list.h>
+struct file_operations;
+struct inode;
+struct module;
+
struct cdev {
struct kobject kobj;
struct module *owner;
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index d852024ed09..1622d23a8dc 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -159,7 +159,7 @@ static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles)
* Unless you're the timekeeping code, you should not be using this!
*/
static inline void clocksource_calculate_interval(struct clocksource *c,
- unsigned long length_nsec)
+ unsigned long length_nsec)
{
u64 tmp;
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index be512cc9879..4c2632a8d31 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -64,7 +64,7 @@ void coda_sysctl_clean(void);
#define CODA_ALLOC(ptr, cast, size) do { \
if (size < PAGE_SIZE) \
- ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+ ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
else \
ptr = (cast)vmalloc((unsigned long) size); \
if (!ptr) \
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 538423d4a86..aca66984aaf 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -40,7 +40,7 @@ extern void __chk_io_ptr(void __iomem *);
#error no compiler-gcc.h file for this gcc version
#elif __GNUC__ == 4
# include <linux/compiler-gcc4.h>
-#elif __GNUC__ == 3
+#elif __GNUC__ == 3 && __GNUC_MINOR__ >= 2
# include <linux/compiler-gcc3.h>
#else
# error Sorry, your compiler is too old/not recognized.
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index a7f01502753..fef6f3d0a4a 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -160,31 +160,6 @@ struct configfs_group_operations {
void (*drop_item)(struct config_group *group, struct config_item *item);
};
-
-
-/**
- * Use these macros to make defining attributes easier. See include/linux/device.h
- * for examples..
- */
-
-#if 0
-#define __ATTR(_name,_mode,_show,_store) { \
- .attr = {.ca_name = __stringify(_name), .ca_mode = _mode, .ca_owner = THIS_MODULE }, \
- .show = _show, \
- .store = _store, \
-}
-
-#define __ATTR_RO(_name) { \
- .attr = { .ca_name = __stringify(_name), .ca_mode = 0444, .ca_owner = THIS_MODULE }, \
- .show = _name##_show, \
-}
-
-#define __ATTR_NULL { .attr = { .name = NULL } }
-
-#define attr_name(_attr) (_attr).attr.name
-#endif
-
-
struct configfs_subsystem {
struct config_group su_group;
struct semaphore su_sem;
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 3ea1cd58de9..10eb56b2940 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -133,7 +133,7 @@ struct cn_callback_data {
struct cn_callback_entry {
struct list_head callback_entry;
struct cn_callback *cb;
- struct delayed_work work;
+ struct work_struct work;
struct cn_queue_dev *pdev;
struct cn_callback_id id;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 4ea39fee99c..7f008f6bfdc 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -172,6 +172,8 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int relation);
+extern int cpufreq_driver_getavg(struct cpufreq_policy *policy);
+
int cpufreq_register_governor(struct cpufreq_governor *governor);
void cpufreq_unregister_governor(struct cpufreq_governor *governor);
@@ -204,6 +206,7 @@ struct cpufreq_driver {
unsigned int (*get) (unsigned int cpu);
/* optional */
+ unsigned int (*getavg) (unsigned int cpu);
int (*exit) (struct cpufreq_policy *policy);
int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg);
int (*resume) (struct cpufreq_policy *policy);
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 8821e1f75b4..fd404416f31 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -30,10 +30,19 @@ void cpuset_update_task_memory_state(void);
nodes_subset((nodes), current->mems_allowed)
int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
-extern int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask);
-static int inline cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+extern int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask);
+extern int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask);
+
+static int inline cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
+{
+ return number_of_cpusets <= 1 ||
+ __cpuset_zone_allowed_softwall(z, gfp_mask);
+}
+
+static int inline cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
{
- return number_of_cpusets <= 1 || __cpuset_zone_allowed(z, gfp_mask);
+ return number_of_cpusets <= 1 ||
+ __cpuset_zone_allowed_hardwall(z, gfp_mask);
}
extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
@@ -46,7 +55,7 @@ extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
extern int cpuset_memory_pressure_enabled;
extern void __cpuset_memory_pressure_bump(void);
-extern const struct file_operations proc_cpuset_operations;
+extern struct file_operations proc_cpuset_operations;
extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
extern void cpuset_lock(void);
@@ -94,7 +103,12 @@ static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
return 1;
}
-static inline int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+static inline int cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
+{
+ return 1;
+}
+
+static inline int cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
{
return 1;
}
diff --git a/include/linux/crc32.h b/include/linux/crc32.h
index 56c0645789a..e20dd1f9b40 100644
--- a/include/linux/crc32.h
+++ b/include/linux/crc32.h
@@ -6,10 +6,10 @@
#define _LINUX_CRC32_H
#include <linux/types.h>
+#include <linux/bitrev.h>
extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len);
extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len);
-extern u32 bitreverse(u32 in);
#define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data, length)
@@ -21,7 +21,7 @@ extern u32 bitreverse(u32 in);
* is in bit nr 0], thus it must be reversed before use. Except for
* nics that bit swap the result internally...
*/
-#define ether_crc(length, data) bitreverse(crc32_le(~0, data, length))
+#define ether_crc(length, data) bitrev32(crc32_le(~0, data, length))
#define ether_crc_le(length, data) crc32_le(~0, data, length)
#endif /* _LINUX_CRC32_H */
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index ed6cc8962d8..1cb054bd93f 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -176,20 +176,20 @@ enum {
};
/* DCCP features (RFC 4340 section 6.4) */
- enum {
- DCCPF_RESERVED = 0,
- DCCPF_CCID = 1,
+enum {
+ DCCPF_RESERVED = 0,
+ DCCPF_CCID = 1,
DCCPF_SHORT_SEQNOS = 2, /* XXX: not yet implemented */
- DCCPF_SEQUENCE_WINDOW = 3,
+ DCCPF_SEQUENCE_WINDOW = 3,
DCCPF_ECN_INCAPABLE = 4, /* XXX: not yet implemented */
- DCCPF_ACK_RATIO = 5,
- DCCPF_SEND_ACK_VECTOR = 6,
- DCCPF_SEND_NDP_COUNT = 7,
+ DCCPF_ACK_RATIO = 5,
+ DCCPF_SEND_ACK_VECTOR = 6,
+ DCCPF_SEND_NDP_COUNT = 7,
DCCPF_MIN_CSUM_COVER = 8,
DCCPF_DATA_CHECKSUM = 9, /* XXX: not yet implemented */
- /* 10-127 reserved */
- DCCPF_MIN_CCID_SPECIFIC = 128,
- DCCPF_MAX_CCID_SPECIFIC = 255,
+ /* 10-127 reserved */
+ DCCPF_MIN_CCID_SPECIFIC = 128,
+ DCCPF_MAX_CCID_SPECIFIC = 255,
};
/* this structure is argument to DCCP_SOCKOPT_CHANGE_X */
@@ -427,7 +427,7 @@ struct dccp_service_list {
};
#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1)
-#define DCCP_SERVICE_CODE_IS_ABSENT 0
+#define DCCP_SERVICE_CODE_IS_ABSENT 0
static inline int dccp_list_has_service(const struct dccp_service_list *sl,
const __be32 service)
@@ -436,7 +436,7 @@ static inline int dccp_list_has_service(const struct dccp_service_list *sl,
u32 i = sl->dccpsl_nr;
while (i--)
if (sl->dccpsl_list[i] == service)
- return 1;
+ return 1;
}
return 0;
}
@@ -511,7 +511,7 @@ struct dccp_sock {
__u8 dccps_hc_tx_insert_options:1;
struct timer_list dccps_xmit_timer;
};
-
+
static inline struct dccp_sock *dccp_sk(const struct sock *sk)
{
return (struct dccp_sock *)sk;
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index a1c10b0c4cf..1678a5de701 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -24,7 +24,7 @@ extern int debug_locks_off(void);
int __ret = 0; \
\
if (unlikely(c)) { \
- if (debug_locks_silent || debug_locks_off()) \
+ if (debug_locks_off() && !debug_locks_silent) \
WARN_ON(1); \
__ret = 1; \
} \
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 03ef41c1eaa..499f5373e21 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -39,7 +39,8 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti);
* The map function must return:
* < 0: error
* = 0: The target will handle the io by resubmitting it later
- * > 0: simple remap complete
+ * = 1: simple remap complete
+ * = 2: The target wants to push back the io
*/
typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
union map_info *map_context);
@@ -50,6 +51,7 @@ typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
* 0 : ended successfully
* 1 : for some reason the io has still not completed (eg,
* multipath target might want to requeue a failed io).
+ * 2 : The target wants to push back the io
*/
typedef int (*dm_endio_fn) (struct dm_target *ti,
struct bio *bio, int error,
@@ -173,7 +175,7 @@ void *dm_get_mdptr(struct mapped_device *md);
/*
* A device can still be used while suspended, but I/O is deferred.
*/
-int dm_suspend(struct mapped_device *md, int with_lockfs);
+int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
int dm_resume(struct mapped_device *md);
/*
@@ -188,6 +190,7 @@ int dm_wait_event(struct mapped_device *md, int event_nr);
const char *dm_device_name(struct mapped_device *md);
struct gendisk *dm_disk(struct mapped_device *md);
int dm_suspended(struct mapped_device *md);
+int dm_noflush_suspending(struct dm_target *ti);
/*
* Geometry functions.
diff --git a/include/linux/device.h b/include/linux/device.h
index 49ab53ce92d..f44247fe813 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -433,6 +433,8 @@ static inline int device_is_registered(struct device *dev)
return dev->is_registered;
}
+void driver_init(void);
+
/*
* High level routines for use by the bus drivers
*/
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index 8853fc4d1c5..b9348610782 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -285,9 +285,9 @@ typedef char ioctl_struct[308];
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 10
+#define DM_VERSION_MINOR 11
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2006-09-14)"
+#define DM_VERSION_EXTRA "-ioctl (2006-10-12)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -323,4 +323,9 @@ typedef char ioctl_struct[308];
*/
#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */
+/*
+ * Set this to suspend without flushing queued ios.
+ */
+#define DM_NOFLUSH_FLAG (1 << 11) /* In */
+
#endif /* _LINUX_DM_IOCTL_H */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index df1c91855f0..f8ebd7c1ddb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -301,7 +301,7 @@ extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource);
extern unsigned long efi_get_time(void);
-extern int __init efi_set_rtc_mmss(unsigned long nowtime);
+extern int efi_set_rtc_mmss(unsigned long nowtime);
extern int is_available_memory(efi_memory_desc_t * md);
extern struct efi_memory_map memmap;
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index a24931d2440..e88fcbc77f8 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -12,6 +12,8 @@ typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struc
typedef void (elevator_merged_fn) (request_queue_t *, struct request *, int);
+typedef int (elevator_allow_merge_fn) (request_queue_t *, struct request *, struct bio *);
+
typedef int (elevator_dispatch_fn) (request_queue_t *, int);
typedef void (elevator_add_req_fn) (request_queue_t *, struct request *);
@@ -33,6 +35,7 @@ struct elevator_ops
elevator_merge_fn *elevator_merge_fn;
elevator_merged_fn *elevator_merged_fn;
elevator_merge_req_fn *elevator_merge_req_fn;
+ elevator_allow_merge_fn *elevator_allow_merge_fn;
elevator_dispatch_fn *elevator_dispatch_fn;
elevator_add_req_fn *elevator_add_req_fn;
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h
new file mode 100644
index 00000000000..32368c4f032
--- /dev/null
+++ b/include/linux/fault-inject.h
@@ -0,0 +1,84 @@
+#ifndef _LINUX_FAULT_INJECT_H
+#define _LINUX_FAULT_INJECT_H
+
+#ifdef CONFIG_FAULT_INJECTION
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <asm/atomic.h>
+
+/*
+ * For explanation of the elements of this struct, see
+ * Documentation/fault-injection/fault-injection.txt
+ */
+struct fault_attr {
+ unsigned long probability;
+ unsigned long interval;
+ atomic_t times;
+ atomic_t space;
+ unsigned long verbose;
+ u32 task_filter;
+ unsigned long stacktrace_depth;
+ unsigned long require_start;
+ unsigned long require_end;
+ unsigned long reject_start;
+ unsigned long reject_end;
+
+ unsigned long count;
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+ struct {
+ struct dentry *dir;
+
+ struct dentry *probability_file;
+ struct dentry *interval_file;
+ struct dentry *times_file;
+ struct dentry *space_file;
+ struct dentry *verbose_file;
+ struct dentry *task_filter_file;
+ struct dentry *stacktrace_depth_file;
+ struct dentry *require_start_file;
+ struct dentry *require_end_file;
+ struct dentry *reject_start_file;
+ struct dentry *reject_end_file;
+ } dentries;
+
+#endif
+};
+
+#define FAULT_ATTR_INITIALIZER { \
+ .interval = 1, \
+ .times = ATOMIC_INIT(1), \
+ .require_end = ULONG_MAX, \
+ .stacktrace_depth = 32, \
+ .verbose = 2, \
+ }
+
+#define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER
+int setup_fault_attr(struct fault_attr *attr, char *str);
+void should_fail_srandom(unsigned long entropy);
+bool should_fail(struct fault_attr *attr, ssize_t size);
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+int init_fault_attr_dentries(struct fault_attr *attr, const char *name);
+void cleanup_fault_attr_dentries(struct fault_attr *attr);
+
+#else /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+static inline int init_fault_attr_dentries(struct fault_attr *attr,
+ const char *name)
+{
+ return -ENODEV;
+}
+
+static inline void cleanup_fault_attr_dentries(struct fault_attr *attr)
+{
+}
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+#endif /* CONFIG_FAULT_INJECTION */
+
+#endif /* _LINUX_FAULT_INJECT_H */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index fa23e0671bb..64177ec9a01 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -929,8 +929,6 @@ extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
#define FB_MODE_IS_FIRST 16
#define FB_MODE_IS_FROM_VAR 32
-extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
- const struct fb_info *fb_info);
extern int fbmon_dpms(const struct fb_info *fb_info);
extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
struct fb_info *info);
@@ -970,11 +968,11 @@ extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
extern void fb_dealloc_cmap(struct fb_cmap *cmap);
-extern int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to);
-extern int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to);
+extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to);
+extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to);
extern int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *fb_info);
extern int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *fb_info);
-extern struct fb_cmap *fb_default_cmap(int len);
+extern const struct fb_cmap *fb_default_cmap(int len);
extern void fb_invert_cmaps(void);
struct fb_videomode {
diff --git a/include/linux/file.h b/include/linux/file.h
index 6e77b9177f9..a59001e9ea5 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -26,19 +26,12 @@ struct embedded_fd_set {
unsigned long fds_bits[1];
};
-/*
- * More than this number of fds: we use a separately allocated fd_set
- */
-#define EMBEDDED_FD_SET_SIZE (BITS_PER_BYTE * sizeof(struct embedded_fd_set))
-
struct fdtable {
unsigned int max_fds;
- int max_fdset;
struct file ** fd; /* current fd array */
fd_set *close_on_exec;
fd_set *open_fds;
struct rcu_head rcu;
- struct files_struct *free_files;
struct fdtable *next;
};
@@ -83,16 +76,15 @@ extern int get_unused_fd(void);
extern void FASTCALL(put_unused_fd(unsigned int fd));
struct kmem_cache;
-extern struct file ** alloc_fd_array(int);
-extern void free_fd_array(struct file **, int);
-
-extern fd_set *alloc_fdset(int);
-extern void free_fdset(fd_set *, int);
-
extern int expand_files(struct files_struct *, int nr);
-extern void free_fdtable(struct fdtable *fdt);
+extern void free_fdtable_rcu(struct rcu_head *rcu);
extern void __init files_defer_init(void);
+static inline void free_fdtable(struct fdtable *fdt)
+{
+ call_rcu(&fdt->rcu, free_fdtable_rcu);
+}
+
static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
{
struct file * file = NULL;
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 6e05e3e7ce3..5e75e26d478 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -1,5 +1,7 @@
/* Freezer declarations */
+#include <linux/sched.h>
+
#ifdef CONFIG_PM
/*
* Check if a process has been frozen
@@ -14,16 +16,15 @@ static inline int frozen(struct task_struct *p)
*/
static inline int freezing(struct task_struct *p)
{
- return p->flags & PF_FREEZE;
+ return test_tsk_thread_flag(p, TIF_FREEZE);
}
/*
* Request that a process be frozen
- * FIXME: SMP problem. We may not modify other process' flags!
*/
static inline void freeze(struct task_struct *p)
{
- p->flags |= PF_FREEZE;
+ set_tsk_thread_flag(p, TIF_FREEZE);
}
/*
@@ -31,7 +32,7 @@ static inline void freeze(struct task_struct *p)
*/
static inline void do_not_freeze(struct task_struct *p)
{
- p->flags &= ~PF_FREEZE;
+ clear_tsk_thread_flag(p, TIF_FREEZE);
}
/*
@@ -52,7 +53,9 @@ static inline int thaw_process(struct task_struct *p)
*/
static inline void frozen_process(struct task_struct *p)
{
- p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+ p->flags |= PF_FROZEN;
+ wmb();
+ clear_tsk_thread_flag(p, TIF_FREEZE);
}
extern void refrigerator(void);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 70b99fbb560..1410e5330c8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -120,6 +120,7 @@ extern int dir_notify_enable;
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
+#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
@@ -269,6 +270,7 @@ extern int dir_notify_enable;
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/dcache.h>
+#include <linux/namei.h>
#include <linux/stat.h>
#include <linux/cache.h>
#include <linux/kobject.h>
@@ -424,6 +426,7 @@ struct address_space_operations {
/* migrate the contents of a page to the specified target */
int (*migratepage) (struct address_space *,
struct page *, struct page *);
+ int (*launder_page) (struct page *);
};
struct backing_dev_info;
@@ -456,7 +459,7 @@ struct block_device {
struct inode * bd_inode; /* will die */
int bd_openers;
struct mutex bd_mutex; /* open/close mutex */
- struct mutex bd_mount_mutex; /* mount mutex */
+ struct semaphore bd_mount_sem;
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
@@ -482,21 +485,6 @@ struct block_device {
};
/*
- * bdev->bd_mutex nesting subclasses for the lock validator:
- *
- * 0: normal
- * 1: 'whole'
- * 2: 'partition'
- */
-enum bdev_bd_mutex_lock_class
-{
- BD_MUTEX_NORMAL,
- BD_MUTEX_WHOLE,
- BD_MUTEX_PARTITION
-};
-
-
-/*
* Radix-tree tags, for tagging dirty and writeback pages within the pagecache
* radix trees
*/
@@ -726,8 +714,9 @@ struct file {
struct list_head fu_list;
struct rcu_head fu_rcuhead;
} f_u;
- struct dentry *f_dentry;
- struct vfsmount *f_vfsmnt;
+ struct path f_path;
+#define f_dentry f_path.dentry
+#define f_vfsmnt f_path.mnt
const struct file_operations *f_op;
atomic_t f_count;
unsigned int f_flags;
@@ -1239,7 +1228,7 @@ extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
static inline void file_accessed(struct file *file)
{
if (!(file->f_flags & O_NOATIME))
- touch_atime(file->f_vfsmnt, file->f_dentry);
+ touch_atime(file->f_path.mnt, file->f_path.dentry);
}
int sync_inode(struct inode *inode, struct writeback_control *wbc);
@@ -1499,7 +1488,6 @@ extern void bd_set_size(struct block_device *, loff_t size);
extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *);
extern struct block_device *open_by_devnum(dev_t, unsigned);
-extern struct block_device *open_partition_by_devnum(dev_t, unsigned);
extern const struct address_space_operations def_blk_aops;
#else
static inline void bd_forget(struct inode *inode) {}
@@ -1517,7 +1505,6 @@ extern int blkdev_driver_ioctl(struct inode *inode, struct file *file,
extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
extern int blkdev_get(struct block_device *, mode_t, unsigned);
extern int blkdev_put(struct block_device *);
-extern int blkdev_put_partition(struct block_device *);
extern int bd_claim(struct block_device *, void *);
extern void bd_release(struct block_device *);
#ifdef CONFIG_SYSFS
@@ -1632,7 +1619,7 @@ static inline void put_write_access(struct inode * inode)
static inline void allow_write_access(struct file *file)
{
if (file)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
+ atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
}
extern int do_pipe(int *);
extern struct file *create_read_pipe(struct file *f);
diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
new file mode 100644
index 00000000000..bb516ceeefc
--- /dev/null
+++ b/include/linux/fs_stack.h
@@ -0,0 +1,31 @@
+#ifndef _LINUX_FS_STACK_H
+#define _LINUX_FS_STACK_H
+
+/* This file defines generic functions used primarily by stackable
+ * filesystems; none of these functions require i_mutex to be held.
+ */
+
+#include <linux/fs.h>
+
+/* externs for fs/stack.c */
+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
+ int (*get_nlinks)(struct inode *));
+
+extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
+
+/* inlines */
+static inline void fsstack_copy_attr_atime(struct inode *dest,
+ const struct inode *src)
+{
+ dest->i_atime = src->i_atime;
+}
+
+static inline void fsstack_copy_attr_times(struct inode *dest,
+ const struct inode *src)
+{
+ dest->i_atime = src->i_atime;
+ dest->i_mtime = src->i_mtime;
+ dest->i_ctime = src->i_ctime;
+}
+
+#endif /* _LINUX_FS_STACK_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 3da29e2d524..abb64c437f6 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -19,6 +19,7 @@
#define _FSL_DEVICE_H_
#include <linux/types.h>
+#include <linux/phy.h>
/*
* Some conventions on how we handle peripherals on Freescale chips
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index d4f219ffaa5..dfc4e4f68da 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -164,7 +164,7 @@ static inline void fsnotify_open(struct dentry *dentry)
*/
static inline void fsnotify_close(struct file *file)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
const char *name = dentry->d_name.name;
mode_t mode = file->f_mode;
diff --git a/include/linux/futex.h b/include/linux/futex.h
index d097b5b72bc..3f153b4e156 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -93,6 +93,7 @@ struct robust_list_head {
*/
#define ROBUST_LIST_LIMIT 2048
+#ifdef __KERNEL__
long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
u32 __user *uaddr2, u32 val2, u32 val3);
@@ -110,6 +111,7 @@ static inline void exit_pi_state_list(struct task_struct *curr)
{
}
#endif
+#endif /* __KERNEL__ */
#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 2cdba0c2395..afad9527284 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -105,7 +105,7 @@ static inline void gameport_set_phys(struct gameport *gameport,
static inline struct gameport *gameport_allocate_port(void)
{
- struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
+ struct gameport *gameport = kzalloc(sizeof(struct gameport), GFP_KERNEL);
return gameport;
}
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
index e2538456195..5412da28fa4 100644
--- a/include/linux/generic_serial.h
+++ b/include/linux/generic_serial.h
@@ -91,7 +91,7 @@ void gs_hangup(struct tty_struct *tty);
int gs_block_til_ready(void *port, struct file *filp);
void gs_close(struct tty_struct *tty, struct file *filp);
void gs_set_termios (struct tty_struct * tty,
- struct termios * old_termios);
+ struct ktermios * old_termios);
int gs_init_port(struct gs_port *port);
int gs_setserial(struct gs_port *port, struct serial_struct __user *sp);
int gs_getserial(struct gs_port *port, struct serial_struct __user *sp);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 41f276fdd18..0a022b2f63f 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -83,6 +83,9 @@ struct hd_struct {
struct kobject *holder_dir;
unsigned ios[2], sectors[2]; /* READs and WRITEs */
int policy, partno;
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+ int make_it_fail;
+#endif
};
#define GENHD_FL_REMOVABLE 1
@@ -90,6 +93,7 @@ struct hd_struct {
#define GENHD_FL_CD 8
#define GENHD_FL_UP 16
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
+#define GENHD_FL_FAIL 64
struct disk_stats {
unsigned long sectors[2]; /* READs and WRITEs */
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index 2b54eac738e..818c6afc109 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -60,13 +60,15 @@
#define TAG_MASK 0xf8
#endif /* __KERNEL__ */
+#include <linux/types.h>
+
/*
* Command Header sizes for IOCTL commands
*/
-#define HDIO_DRIVE_CMD_HDR_SIZE (4 * sizeof(u8))
-#define HDIO_DRIVE_HOB_HDR_SIZE (8 * sizeof(u8))
-#define HDIO_DRIVE_TASK_HDR_SIZE (8 * sizeof(u8))
+#define HDIO_DRIVE_CMD_HDR_SIZE (4 * sizeof(__u8))
+#define HDIO_DRIVE_HOB_HDR_SIZE (8 * sizeof(__u8))
+#define HDIO_DRIVE_TASK_HDR_SIZE (8 * sizeof(__u8))
#define IDE_DRIVE_TASK_INVALID -1
#define IDE_DRIVE_TASK_NO_DATA 0
diff --git a/drivers/usb/input/hid-debug.h b/include/linux/hid-debug.h
index f04d6d75c09..8e4dbb51fc7 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/include/linux/hid-debug.h
@@ -700,9 +700,10 @@ static char *keys[KEY_MAX + 1] = {
static char *relatives[REL_MAX + 1] = {
[REL_X] = "X", [REL_Y] = "Y",
- [REL_Z] = "Z", [REL_HWHEEL] = "HWheel",
- [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel",
- [REL_MISC] = "Misc",
+ [REL_Z] = "Z", [REL_RX] = "Rx",
+ [REL_RY] = "Ry", [REL_RZ] = "Rz",
+ [REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial",
+ [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
};
static char *absolutes[ABS_MAX + 1] = {
diff --git a/drivers/usb/input/hid.h b/include/linux/hid.h
index 2a9bf07944c..342b4e639ac 100644
--- a/drivers/usb/input/hid.h
+++ b/include/linux/hid.h
@@ -6,6 +6,7 @@
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2001 Vojtech Pavlik
+ * Copyright (c) 2006 Jiri Kosina
*/
/*
@@ -33,6 +34,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <linux/input.h>
/*
* USB HID (Human Interface Device) interface class code
@@ -260,7 +262,8 @@ struct hid_item {
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
#define HID_QUIRK_INVERT_HWHEEL 0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
+#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
+#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
/*
* This is the global environment of the parser. This information is
@@ -400,42 +403,14 @@ struct hid_device { /* device report descriptor */
unsigned collection_size; /* Number of allocated hid_collections */
unsigned maxcollection; /* Number of parsed collections */
unsigned maxapplication; /* Number of applications */
+ unsigned short bus; /* BUS ID */
+ unsigned short vendor; /* Vendor ID */
+ unsigned short product; /* Product ID */
unsigned version; /* HID version */
unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES];
- struct usb_device *dev; /* USB device */
- struct usb_interface *intf; /* USB interface */
- int ifnum; /* USB interface number */
-
- unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
- struct timer_list io_retry; /* Retry timer */
- unsigned long stop_retry; /* Time to give up, in jiffies */
- unsigned int retry_delay; /* Delay length in ms */
- struct work_struct reset_work; /* Task context for resets */
-
- unsigned int bufsize; /* URB buffer size */
-
- struct urb *urbin; /* Input URB */
- char *inbuf; /* Input buffer */
- dma_addr_t inbuf_dma; /* Input buffer dma */
- spinlock_t inlock; /* Input fifo spinlock */
-
- struct urb *urbctrl; /* Control URB */
- struct usb_ctrlrequest *cr; /* Control request struct */
- dma_addr_t cr_dma; /* Control request struct dma */
- struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
- unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
- char *ctrlbuf; /* Control buffer */
- dma_addr_t ctrlbuf_dma; /* Control buffer dma */
- spinlock_t ctrllock; /* Control fifo spinlock */
-
- struct urb *urbout; /* Output URB */
- struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
- unsigned char outhead, outtail; /* Output pipe fifo head & tail */
- char *outbuf; /* Output buffer */
- dma_addr_t outbuf_dma; /* Output buffer dma */
- spinlock_t outlock; /* Output fifo spinlock */
+ struct device *dev; /* device */
unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */
@@ -451,6 +426,17 @@ struct hid_device { /* device report descriptor */
char phys[64]; /* Device physical location */
char uniq[64]; /* Device unique identifier (serial #) */
+ void *driver_data;
+
+ /* device-specific function pointers */
+ int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
+ int (*hidinput_open) (struct input_dev *);
+ void (*hidinput_close) (struct input_dev *);
+
+ /* hiddev event handler */
+ void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
+ struct hid_usage *, __s32);
+ void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
@@ -495,31 +481,23 @@ struct hid_descriptor {
#define resolv_event(a,b) do { } while (0)
#endif
-#endif
-
-#ifdef CONFIG_USB_HIDINPUT
/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
/* We ignore a few input applications that are not widely used */
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
+
+/* HID core API */
extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
extern int hidinput_connect(struct hid_device *);
extern void hidinput_disconnect(struct hid_device *);
-#else
-#define IS_INPUT_APPLICATION(a) (0)
-static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
-static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { }
-static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
-static inline void hidinput_disconnect(struct hid_device *hid) { }
-#endif
-int hid_open(struct hid_device *);
-void hid_close(struct hid_device *);
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_wait_io(struct hid_device* hid);
-
+int hid_input_report(struct hid_device *, int type, u8 *, int, int);
+int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
+void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);
+void hid_output_report(struct hid_report *report, __u8 *data);
+void hid_free_device(struct hid_device *device);
+struct hid_device *hid_parse_report(__u8 *start, unsigned size);
#ifdef CONFIG_HID_FF
int hid_ff_init(struct hid_device *hid);
@@ -536,4 +514,14 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
#else
static inline int hid_ff_init(struct hid_device *hid) { return -1; }
#endif
+#ifdef DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+ __FILE__ , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+ __FILE__ , ## arg)
+#endif
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 3d8768b619e..645d440807c 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -8,7 +8,7 @@
#include <asm/cacheflush.h>
#ifndef ARCH_HAS_FLUSH_ANON_PAGE
-static inline void flush_anon_page(struct page *page, unsigned long vmaddr)
+static inline void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
{
}
#endif
@@ -96,7 +96,10 @@ static inline void memclear_highpage_flush(struct page *page, unsigned int offse
kunmap_atomic(kaddr, KM_USER0);
}
-static inline void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr)
+#ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE
+
+static inline void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma)
{
char *vfrom, *vto;
@@ -109,6 +112,8 @@ static inline void copy_user_highpage(struct page *to, struct page *from, unsign
smp_wmb();
}
+#endif
+
static inline void copy_highpage(struct page *to, struct page *from)
{
char *vfrom, *vto;
diff --git a/include/linux/i2c-algo-bit.h b/include/linux/i2c-algo-bit.h
index c8f8df25c7e..937da70cb4c 100644
--- a/include/linux/i2c-algo-bit.h
+++ b/include/linux/i2c-algo-bit.h
@@ -26,9 +26,9 @@
/* --- Defines for bit-adapters --------------------------------------- */
/*
- * This struct contains the hw-dependent functions of bit-style adapters to
+ * This struct contains the hw-dependent functions of bit-style adapters to
* manipulate the line states, and to init any hw-specific features. This is
- * only used if you have more than one hw-type of adapter running.
+ * only used if you have more than one hw-type of adapter running.
*/
struct i2c_algo_bit_data {
void *data; /* private data for lowlevel routines */
@@ -44,6 +44,5 @@ struct i2c_algo_bit_data {
};
int i2c_bit_add_bus(struct i2c_adapter *);
-int i2c_bit_del_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_BIT_H */
diff --git a/include/linux/i2c-algo-ite.h b/include/linux/i2c-algo-ite.h
deleted file mode 100644
index 0073fe96c76..00000000000
--- a/include/linux/i2c-algo-ite.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/* i2c-algo-ite.h i2c driver algorithms for ITE IIC adapters */
-/* ------------------------------------------------------------------------- */
-/* Copyright (C) 1995-97 Simon G. Vogl
- 1998-99 Hans Berglund
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You 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. */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
- Frodo Looijaard <frodol@dds.nl> */
-
-/* Modifications by MontaVista Software, 2001
- Changes made to support the ITE IIC peripheral */
-
-
-#ifndef I2C_ALGO_ITE_H
-#define I2C_ALGO_ITE_H 1
-
-#include <linux/types.h>
-
-/* Example of a sequential read request:
- struct i2c_iic_msg s_msg;
-
- s_msg.addr=device_address;
- s_msg.len=length;
- s_msg.buf=buffer;
- s_msg.waddr=word_address;
- ioctl(file,I2C_SREAD, &s_msg);
- */
-#define I2C_SREAD 0x780 /* SREAD ioctl command */
-
-struct i2c_iic_msg {
- __u16 addr; /* device address */
- __u16 waddr; /* word address */
- short len; /* msg length */
- char *buf; /* pointer to msg data */
-};
-
-#ifdef __KERNEL__
-struct i2c_adapter;
-
-struct i2c_algo_iic_data {
- void *data; /* private data for lolevel routines */
- void (*setiic) (void *data, int ctl, int val);
- int (*getiic) (void *data, int ctl);
- int (*getown) (void *data);
- int (*getclock) (void *data);
- void (*waitforpin) (void);
-
- /* local settings */
- int udelay;
- int mdelay;
- int timeout;
-};
-
-int i2c_iic_add_bus(struct i2c_adapter *);
-int i2c_iic_del_bus(struct i2c_adapter *);
-#endif /* __KERNEL__ */
-#endif /* I2C_ALGO_ITE_H */
diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
index 226693e0d88..fce47c051bb 100644
--- a/include/linux/i2c-algo-pca.h
+++ b/include/linux/i2c-algo-pca.h
@@ -10,6 +10,5 @@ struct i2c_algo_pca_data {
};
int i2c_pca_add_bus(struct i2c_adapter *);
-int i2c_pca_del_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_PCA_H */
diff --git a/include/linux/i2c-algo-pcf.h b/include/linux/i2c-algo-pcf.h
index 9908f3fc483..994eb86f882 100644
--- a/include/linux/i2c-algo-pcf.h
+++ b/include/linux/i2c-algo-pcf.h
@@ -31,7 +31,7 @@ struct i2c_algo_pcf_data {
int (*getpcf) (void *data, int ctl);
int (*getown) (void *data);
int (*getclock) (void *data);
- void (*waitforpin) (void);
+ void (*waitforpin) (void);
/* local settings */
int udelay;
@@ -39,6 +39,5 @@ struct i2c_algo_pcf_data {
};
int i2c_pcf_add_bus(struct i2c_adapter *);
-int i2c_pcf_del_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_PCF_H */
diff --git a/include/linux/i2c-algo-sgi.h b/include/linux/i2c-algo-sgi.h
index 4a0113d6406..3b7715024e6 100644
--- a/include/linux/i2c-algo-sgi.h
+++ b/include/linux/i2c-algo-sgi.h
@@ -22,6 +22,5 @@ struct i2c_algo_sgi_data {
};
int i2c_sgi_add_bus(struct i2c_adapter *);
-int i2c_sgi_del_bus(struct i2c_adapter *);
#endif /* I2C_ALGO_SGI_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 0a8f750cbed..d38778f2fbe 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- */
-/* */
+/* */
/* i2c-id.h - identifier values for i2c drivers and adapters */
-/* */
+/* */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-1999 Simon G. Vogl
@@ -40,10 +40,10 @@
#define I2C_DRIVERID_SAA7120 11 /* video encoder */
#define I2C_DRIVERID_SAA7121 12 /* video encoder */
#define I2C_DRIVERID_SAA7185B 13 /* video encoder */
-#define I2C_DRIVERID_CH7003 14 /* digital pc to tv encoder */
+#define I2C_DRIVERID_CH7003 14 /* digital pc to tv encoder */
#define I2C_DRIVERID_PCF8574A 15 /* i2c expander - 8 bit in/out */
#define I2C_DRIVERID_PCF8582C 16 /* eeprom */
-#define I2C_DRIVERID_AT24Cxx 17 /* eeprom 1/2/4/8/16 K */
+#define I2C_DRIVERID_AT24Cxx 17 /* eeprom 1/2/4/8/16 K */
#define I2C_DRIVERID_TEA6300 18 /* audio mixer */
#define I2C_DRIVERID_BT829 19 /* pc to tv encoder */
#define I2C_DRIVERID_TDA9850 20 /* audio mixer */
@@ -82,9 +82,8 @@
#define I2C_DRIVERID_STM41T00 52 /* real time clock */
#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */
#define I2C_DRIVERID_ADV7170 54 /* video encoder */
-#define I2C_DRIVERID_RADEON 55 /* I2C bus on Radeon boards */
#define I2C_DRIVERID_MAX1617 56 /* temp sensor */
-#define I2C_DRIVERID_SAA7191 57 /* video encoder */
+#define I2C_DRIVERID_SAA7191 57 /* video decoder */
#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
#define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */
#define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */
@@ -132,7 +131,6 @@
#define I2C_DRIVERID_ADM1021 1008
#define I2C_DRIVERID_ADM9240 1009
#define I2C_DRIVERID_LTC1710 1010
-#define I2C_DRIVERID_ICSPLL 1012
#define I2C_DRIVERID_BT869 1013
#define I2C_DRIVERID_MAXILIFE 1014
#define I2C_DRIVERID_MATORB 1015
@@ -144,7 +142,6 @@
#define I2C_DRIVERID_MTP008 1023
#define I2C_DRIVERID_DS1621 1024
#define I2C_DRIVERID_ADM1024 1025
-#define I2C_DRIVERID_IT87 1026
#define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
#define I2C_DRIVERID_FSCPOS 1028
#define I2C_DRIVERID_FSCSCY 1029
@@ -159,12 +156,13 @@
#define I2C_DRIVERID_ASB100 1043
#define I2C_DRIVERID_FSCHER 1046
#define I2C_DRIVERID_W83L785TS 1047
+#define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */
/*
* ---- Adapter types ----------------------------------------------------
*/
-/* --- Bit algorithm adapters */
+/* --- Bit algorithm adapters */
#define I2C_HW_B_LP 0x010000 /* Parallel port Philips style */
#define I2C_HW_B_SER 0x010002 /* Serial line interface */
#define I2C_HW_B_BT848 0x010005 /* BT848 video boards */
@@ -212,9 +210,6 @@
/* --- MPC8xx PowerPC adapters */
#define I2C_HW_MPC8XX_EPON 0x110000 /* Eponymous MPC8xx I2C adapter */
-/* --- ITE based algorithms */
-#define I2C_HW_I_IIC 0x080000 /* controller on the ITE */
-
/* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */
@@ -250,6 +245,7 @@
#define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */
#define I2C_HW_SMBUS_OV519 0x040010 /* OV519 USB 1.1 webcam IC */
#define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */
+#define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */
/* --- ISA pseudo-adapter */
#define I2C_HW_ISA 0x050000
diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h
new file mode 100644
index 00000000000..e6e9c814da6
--- /dev/null
+++ b/include/linux/i2c-pnx.h
@@ -0,0 +1,43 @@
+/*
+ * Header file for I2C support on PNX010x/4008.
+ *
+ * Author: Dennis Kovalev <dkovalev@ru.mvista.com>
+ *
+ * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __I2C_PNX_H__
+#define __I2C_PNX_H__
+
+#include <asm/arch/i2c.h>
+
+struct i2c_pnx_mif {
+ int ret; /* Return value */
+ int mode; /* Interface mode */
+ struct completion complete; /* I/O completion */
+ struct timer_list timer; /* Timeout */
+ char * buf; /* Data buffer */
+ int len; /* Length of data buffer */
+};
+
+struct i2c_pnx_algo_data {
+ u32 base;
+ u32 ioaddr;
+ int irq;
+ struct i2c_pnx_mif mif;
+ int last;
+};
+
+struct i2c_pnx_data {
+ int (*suspend) (struct platform_device *pdev, pm_message_t state);
+ int (*resume) (struct platform_device *pdev);
+ u32 (*calculate_input_freq) (struct platform_device *pdev);
+ int (*set_clock_run) (struct platform_device *pdev);
+ int (*set_clock_stop) (struct platform_device *pdev);
+ struct i2c_adapter *adapter;
+};
+
+#endif /* __I2C_PNX_H__ */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 9b5d04768c2..71e50d3e492 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------- */
-/* */
+/* */
/* i2c.h - definitions for the i2c-bus interface */
-/* */
+/* */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-2000 Simon G. Vogl
@@ -27,7 +27,7 @@
#define _LINUX_I2C_H
#include <linux/types.h>
-#ifdef __KERNEL__
+#ifdef __KERNEL__
#include <linux/module.h>
#include <linux/i2c-id.h>
#include <linux/mod_devicetable.h>
@@ -53,8 +53,8 @@ union i2c_smbus_data;
/*
* The master routines are the ones normally used to transmit data to devices
- * on a bus (or read from them). Apart from two basic transfer functions to
- * transmit one message at a time, a more complex version can be used to
+ * on a bus (or read from them). Apart from two basic transfer functions to
+ * transmit one message at a time, a more complex version can be used to
* transmit an arbitrary number of messages without interruption.
*/
extern int i2c_master_send(struct i2c_client *,const char* ,int);
@@ -67,10 +67,10 @@ extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
/* This is the very generalized SMBus access routine. You probably do not
want to use this, though; one of the functions below may be much easier,
- and probably just as fast.
+ and probably just as fast.
Note that we use i2c_adapter here, because you do not need a specific
smbus adapter to call this function. */
-extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
+extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
unsigned short flags,
char read_write, u8 command, int size,
union i2c_smbus_data * data);
@@ -112,14 +112,14 @@ struct i2c_driver {
/* Notifies the driver that a new bus has appeared. This routine
* can be used by the driver to test if the bus meets its conditions
- * & seek for the presence of the chip(s) it supports. If found, it
+ * & seek for the presence of the chip(s) it supports. If found, it
* registers the client(s) that are on the bus to the i2c admin. via
* i2c_attach_client.
*/
int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);
- /* tells the driver that a client is about to be deleted & gives it
+ /* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private data. Also, if the client struct
* has been dynamically allocated by the driver in the function above,
* it must be freed here.
@@ -139,13 +139,13 @@ struct i2c_driver {
#define I2C_NAME_SIZE 50
/*
- * i2c_client identifies a single device (i.e. chip) that is connected to an
+ * i2c_client identifies a single device (i.e. chip) that is connected to an
* i2c bus. The behaviour is defined by the routines of the driver. This
* function is mainly used for lookup & other admin. functions.
*/
struct i2c_client {
unsigned int flags; /* div., see below */
- unsigned short addr; /* chip address - NOTE: 7bit */
+ unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
struct i2c_adapter *adapter; /* the adapter we sit on */
@@ -182,14 +182,14 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
*/
struct i2c_algorithm {
/* If an adapter algorithm can't do I2C-level access, set master_xfer
- to NULL. If an adapter algorithm can do SMBus access, set
+ 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 */
/* master_xfer should return the number of messages successfully
processed, or a negative value on error */
- 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,
+ int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data * data);
@@ -216,6 +216,7 @@ struct i2c_adapter {
int (*client_unregister)(struct i2c_client *);
/* data fields that are valid for all devices */
+ u8 level; /* nesting level for lockdep */
struct mutex bus_lock;
struct mutex clist_lock;
@@ -316,7 +317,7 @@ extern int i2c_check_addr (struct i2c_adapter *adapter, int addr);
* It will only call found_proc if some client is connected at the
* specific address (unless a 'force' matched);
*/
-extern int i2c_probe(struct i2c_adapter *adapter,
+extern int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
int (*found_proc) (struct i2c_adapter *, int, int));
@@ -352,15 +353,15 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
*/
struct i2c_msg {
__u16 addr; /* slave address */
- __u16 flags;
+ __u16 flags;
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
#define I2C_M_RD 0x01
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000
#define I2C_M_IGNORE_NAK 0x1000
#define I2C_M_NO_RD_ACK 0x0800
- __u16 len; /* msg length */
- __u8 *buf; /* pointer to msg data */
+ __u16 len; /* msg length */
+ __u8 *buf; /* pointer to msg data */
};
/* To determine what functionality is present */
@@ -370,16 +371,16 @@ struct i2c_msg {
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_QUICK 0x00010000
-#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
-#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
-#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
-#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
-#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
-#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
-#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
-#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define I2C_FUNC_SMBUS_QUICK 0x00010000
+#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
+#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
+#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
+#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */
@@ -406,10 +407,10 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK)
-/*
- * Data for SMBus Messages
+/*
+ * Data for SMBus Messages
*/
-#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
union i2c_smbus_data {
__u8 byte;
__u16 word;
@@ -421,11 +422,11 @@ union i2c_smbus_data {
#define I2C_SMBUS_READ 1
#define I2C_SMBUS_WRITE 0
-/* SMBus transaction types (size parameter in the above functions)
+/* SMBus transaction types (size parameter in the above functions)
Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
#define I2C_SMBUS_QUICK 0
#define I2C_SMBUS_BYTE 1
-#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_BYTE_DATA 2
#define I2C_SMBUS_WORD_DATA 3
#define I2C_SMBUS_PROC_CALL 4
#define I2C_SMBUS_BLOCK_DATA 5
@@ -434,15 +435,15 @@ union i2c_smbus_data {
/* ----- commands for the ioctl like i2c_command call:
- * note that additional calls are defined in the algorithm and hw
- * dependent layers - these can be listed here, or see the
+ * note that additional calls are defined in the algorithm and hw
+ * dependent layers - these can be listed here, or see the
* corresponding header files.
*/
/* -> bit-adapter specific ioctls */
#define I2C_RETRIES 0x0701 /* number of times a device address */
/* should be polled when not */
- /* acknowledging */
-#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
+ /* acknowledging */
+#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
/* this is for i2c-dev.c */
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index c2519df1b6d..a0b23dd4523 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -24,12 +24,13 @@
#define MAX_I2O_CONTROLLERS 32
#include <linux/ioctl.h>
+#include <linux/types.h>
/*
* I2O Control IOCTLs and structures
*/
#define I2O_MAGIC_NUMBER 'i'
-#define I2OGETIOPS _IOR(I2O_MAGIC_NUMBER,0,u8[MAX_I2O_CONTROLLERS])
+#define I2OGETIOPS _IOR(I2O_MAGIC_NUMBER,0,__u8[MAX_I2O_CONTROLLERS])
#define I2OHRTGET _IOWR(I2O_MAGIC_NUMBER,1,struct i2o_cmd_hrtlct)
#define I2OLCTGET _IOWR(I2O_MAGIC_NUMBER,2,struct i2o_cmd_hrtlct)
#define I2OPARMSET _IOWR(I2O_MAGIC_NUMBER,3,struct i2o_cmd_psetget)
@@ -37,7 +38,7 @@
#define I2OSWDL _IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
#define I2OSWUL _IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
#define I2OSWDEL _IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
-#define I2OVALIDATE _IOR(I2O_MAGIC_NUMBER,8,u32)
+#define I2OVALIDATE _IOR(I2O_MAGIC_NUMBER,8,__u32)
#define I2OHTML _IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
#define I2OEVTREG _IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
#define I2OEVTGET _IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 9c2050293f1..e26a03981a9 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -796,6 +796,7 @@ typedef struct hwif_s {
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
unsigned no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
unsigned err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
+ unsigned atapi_irq_bogon : 1; /* Generates spurious DMA interrupts in PIO mode */
struct device gendev;
struct completion gendev_rel_comp; /* To deal with device release() */
@@ -803,8 +804,6 @@ typedef struct hwif_s {
void *hwif_data; /* extra hwif data */
unsigned dma;
-
- void (*led_act)(void *data, int rw);
} ____cacheline_internodealigned_in_smp ide_hwif_t;
/*
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
index dbe8f6120a4..d557e4ce9b6 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -52,4 +52,10 @@ struct ifa_cacheinfo
__u32 tstamp; /* updated timestamp, hundredths of seconds */
};
+/* backwards compatibility for userspace */
+#ifndef __KERNEL__
+#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+#endif
+
#endif
diff --git a/include/linux/if_fddi.h b/include/linux/if_fddi.h
index e0a15004620..4aba6b0ad41 100644
--- a/include/linux/if_fddi.h
+++ b/include/linux/if_fddi.h
@@ -103,6 +103,8 @@ struct fddihdr
} __attribute__ ((packed));
#ifdef __KERNEL__
+#include <linux/netdevice.h>
+
/* Define FDDI statistics structure */
struct fddi_statistics {
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index e963a077e6f..35ed3b5467f 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -82,6 +82,12 @@ enum
#define IFLA_MAX (__IFLA_MAX - 1)
+/* backwards compatibility for userspace */
+#ifndef __KERNEL__
+#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
+#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
+#endif
+
/* ifi_flags.
IFF_* flags.
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 8de079ba110..660b5010c2d 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -1,6 +1,8 @@
#ifndef _IF_TUNNEL_H_
#define _IF_TUNNEL_H_
+#include <linux/types.h>
+
#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0)
#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1)
#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2)
diff --git a/include/linux/init.h b/include/linux/init.h
index 5eb5d24b768..5a593a1dec1 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -111,6 +111,7 @@ extern void setup_arch(char **);
#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
#define fs_initcall(fn) __define_initcall("5",fn,5)
#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
+#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn) __define_initcall("7",fn,7)
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 733790d4f7d..6383d2d83bb 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -7,16 +7,15 @@
#include <linux/utsname.h>
#include <linux/lockdep.h>
#include <linux/ipc.h>
+#include <linux/pid_namespace.h>
#define INIT_FDTABLE \
{ \
.max_fds = NR_OPEN_DEFAULT, \
- .max_fdset = EMBEDDED_FD_SET_SIZE, \
.fd = &init_files.fd_array[0], \
.close_on_exec = (fd_set *)&init_files.close_on_exec_init, \
.open_fds = (fd_set *)&init_files.open_fds_init, \
.rcu = RCU_HEAD_INIT, \
- .free_files = NULL, \
.next = NULL, \
}
@@ -57,25 +56,27 @@
.cpu_vm_mask = CPU_MASK_ALL, \
}
-#define INIT_SIGNALS(sig) { \
- .count = ATOMIC_INIT(1), \
+#define INIT_SIGNALS(sig) { \
+ .count = ATOMIC_INIT(1), \
.wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\
- .shared_pending = { \
+ .shared_pending = { \
.list = LIST_HEAD_INIT(sig.shared_pending.list), \
- .signal = {{0}}}, \
+ .signal = {{0}}}, \
.posix_timers = LIST_HEAD_INIT(sig.posix_timers), \
.cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \
.rlim = INIT_RLIMITS, \
.pgrp = 1, \
- .session = 1, \
+ .tty_old_pgrp = 0, \
+ { .__session = 1}, \
}
extern struct nsproxy init_nsproxy;
#define INIT_NSPROXY(nsproxy) { \
+ .pid_ns = &init_pid_ns, \
.count = ATOMIC_INIT(1), \
.nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \
.uts_ns = &init_uts_ns, \
- .namespace = NULL, \
+ .mnt_ns = NULL, \
INIT_IPC_NS(ipc_ns) \
}
diff --git a/include/linux/input.h b/include/linux/input.h
index c38507ba38b..bde65c8a351 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -491,6 +491,21 @@ struct input_absinfo {
#define KEY_DIGITS 0x19d
#define KEY_TEEN 0x19e
#define KEY_TWEN 0x19f
+#define KEY_VIDEOPHONE 0x1a0
+#define KEY_GAMES 0x1a1
+#define KEY_ZOOMIN 0x1a2
+#define KEY_ZOOMOUT 0x1a3
+#define KEY_ZOOMRESET 0x1a4
+#define KEY_WORDPROCESSOR 0x1a5
+#define KEY_EDITOR 0x1a6
+#define KEY_SPREADSHEET 0x1a7
+#define KEY_GRAPHICSEDITOR 0x1a8
+#define KEY_PRESENTATION 0x1a9
+#define KEY_DATABASE 0x1aa
+#define KEY_NEWS 0x1ab
+#define KEY_VOICEMAIL 0x1ac
+#define KEY_ADDRESSBOOK 0x1ad
+#define KEY_MESSENGER 0x1ae
#define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1
@@ -663,7 +678,7 @@ struct input_absinfo {
#define BUS_GSC 0x1A
/*
- * Values describing the status of an effect
+ * Values describing the status of a force-feedback effect
*/
#define FF_STATUS_STOPPED 0x00
#define FF_STATUS_PLAYING 0x01
@@ -680,7 +695,7 @@ struct input_absinfo {
*/
/**
- * struct ff_replay - defines scheduling of the effect
+ * struct ff_replay - defines scheduling of the force-feedback effect
* @length: duration of the effect
* @delay: delay before effect should start playing
*/
@@ -690,7 +705,7 @@ struct ff_replay {
};
/**
- * struct ff_trigger - defines what triggers the effect
+ * struct ff_trigger - defines what triggers the force-feedback effect
* @button: number of the button triggering the effect
* @interval: controls how soon the effect can be re-triggered
*/
@@ -700,7 +715,7 @@ struct ff_trigger {
};
/**
- * struct ff_envelope - generic effect envelope
+ * struct ff_envelope - generic force-feedback effect envelope
* @attack_length: duration of the attack (ms)
* @attack_level: level at the beginning of the attack
* @fade_length: duration of fade (ms)
@@ -719,7 +734,7 @@ struct ff_envelope {
};
/**
- * struct ff_constant_effect - defines parameters of a constant effect
+ * struct ff_constant_effect - defines parameters of a constant force-feedback effect
* @level: strength of the effect; may be negative
* @envelope: envelope data
*/
@@ -729,7 +744,7 @@ struct ff_constant_effect {
};
/**
- * struct ff_ramp_effect - defines parameters of a ramp effect
+ * struct ff_ramp_effect - defines parameters of a ramp force-feedback effect
* @start_level: beginning strength of the effect; may be negative
* @end_level: final strength of the effect; may be negative
* @envelope: envelope data
@@ -741,7 +756,7 @@ struct ff_ramp_effect {
};
/**
- * struct ff_condition_effect - defines a spring or friction effect
+ * struct ff_condition_effect - defines a spring or friction force-feedback effect
* @right_saturation: maximum level when joystick moved all way to the right
* @left_saturation: same for the left side
* @right_coeff: controls how fast the force grows when the joystick moves
@@ -762,7 +777,7 @@ struct ff_condition_effect {
};
/**
- * struct ff_periodic_effect - defines parameters of a periodic effect
+ * struct ff_periodic_effect - defines parameters of a periodic force-feedback effect
* @waveform: kind of the effect (wave)
* @period: period of the wave (ms)
* @magnitude: peak value
@@ -793,7 +808,7 @@ struct ff_periodic_effect {
};
/**
- * struct ff_rumble_effect - defines parameters of a periodic effect
+ * struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
* @strong_magnitude: magnitude of the heavy motor
* @weak_magnitude: magnitude of the light one
*
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index de7593f4e89..e36e86c869f 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -231,7 +231,8 @@ enum
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
- TASKLET_SOFTIRQ
+ TASKLET_SOFTIRQ,
+ SCHED_SOFTIRQ,
};
/* softirq mask and active fields moved to irq_cpustat_t in
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index cf8696d4a13..15228d79c5b 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -91,6 +91,9 @@ struct resource_list {
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */
#define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */
+/* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */
+#define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */
+
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource;
extern struct resource iomem_resource;
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 62991148d5a..3c7875b7ab5 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -511,8 +511,8 @@ typedef struct modem_info {
#endif
struct tty_struct *tty; /* Pointer to corresponding tty */
atemu emu; /* AT-emulator data */
- struct termios normal_termios; /* For saving termios structs */
- struct termios callout_termios;
+ struct ktermios normal_termios; /* For saving termios structs */
+ struct ktermios callout_termios;
wait_queue_head_t open_wait, close_wait;
struct semaphore write_sem;
spinlock_t readlock;
@@ -525,8 +525,8 @@ typedef struct _isdn_modem {
int refcount; /* Number of opens */
struct tty_driver *tty_modem; /* tty-device */
struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */
- struct termios *modem_termios[ISDN_MAX_CHANNELS];
- struct termios *modem_termios_locked[ISDN_MAX_CHANNELS];
+ struct ktermios *modem_termios[ISDN_MAX_CHANNELS];
+ struct ktermios *modem_termios_locked[ISDN_MAX_CHANNELS];
modem_info info[ISDN_MAX_CHANNELS]; /* Private data */
} isdn_modem_t;
diff --git a/include/linux/istallion.h b/include/linux/istallion.h
index b55e2a03560..106a5e85e5c 100644
--- a/include/linux/istallion.h
+++ b/include/linux/istallion.h
@@ -49,13 +49,13 @@
* communication with the slave board will always be on a per port
* basis.
*/
-typedef struct {
+struct stliport {
unsigned long magic;
- int portnr;
- int panelnr;
- int brdnr;
+ unsigned int portnr;
+ unsigned int panelnr;
+ unsigned int brdnr;
unsigned long state;
- int devnr;
+ unsigned int devnr;
int flags;
int baud_base;
int custom_divisor;
@@ -72,7 +72,7 @@ typedef struct {
wait_queue_head_t close_wait;
wait_queue_head_t raw_wait;
struct work_struct tqhangup;
- asysigs_t asig;
+ struct asysigs asig;
unsigned long addr;
unsigned long rxoffset;
unsigned long txoffset;
@@ -83,31 +83,31 @@ typedef struct {
unsigned char reqbit;
unsigned char portidx;
unsigned char portbit;
-} stliport_t;
+};
/*
* Use a structure of function pointers to do board level operations.
* These include, enable/disable, paging shared memory, interrupting, etc.
*/
-typedef struct stlibrd {
+struct stlibrd {
unsigned long magic;
- int brdnr;
- int brdtype;
- int state;
- int nrpanels;
- int nrports;
- int nrdevs;
+ unsigned int brdnr;
+ unsigned int brdtype;
+ unsigned int state;
+ unsigned int nrpanels;
+ unsigned int nrports;
+ unsigned int nrdevs;
unsigned int iobase;
int iosize;
unsigned long memaddr;
void __iomem *membase;
- int memsize;
+ unsigned long memsize;
int pagesize;
int hostoffset;
int slaveoffset;
int bitsize;
int enabval;
- int panels[STL_MAXPANELS];
+ unsigned int panels[STL_MAXPANELS];
int panelids[STL_MAXPANELS];
void (*init)(struct stlibrd *brdp);
void (*enable)(struct stlibrd *brdp);
@@ -116,8 +116,8 @@ typedef struct stlibrd {
void __iomem *(*getmemptr)(struct stlibrd *brdp, unsigned long offset, int line);
void (*intr)(struct stlibrd *brdp);
void (*reset)(struct stlibrd *brdp);
- stliport_t *ports[STL_MAXPORTS];
-} stlibrd_t;
+ struct stliport *ports[STL_MAXPORTS];
+};
/*
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 6738283ac38..63fb18dcac3 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -13,10 +13,12 @@
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/bitops.h>
+#include <linux/log2.h>
#include <asm/byteorder.h>
#include <asm/bug.h>
extern const char linux_banner[];
+extern const char linux_proc_banner[];
#define INT_MAX ((int)(~0U>>1))
#define INT_MIN (-INT_MAX - 1)
@@ -157,20 +159,6 @@ static inline int printk(const char *s, ...) { return 0; }
unsigned long int_sqrt(unsigned long);
-static inline int __attribute_pure__ long_log2(unsigned long x)
-{
- int r = 0;
- for (x >>= 1; x > 0; x >>= 1)
- r++;
- return r;
-}
-
-static inline unsigned long
-__attribute_const__ roundup_pow_of_two(unsigned long x)
-{
- return 1UL << fls_long(x - 1);
-}
-
extern int printk_ratelimit(void);
extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index d1c8d28fa92..76538fcf2c4 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -265,8 +265,8 @@ extern int __must_check subsys_create_file(struct subsystem * ,
struct subsys_attribute *);
#if defined(CONFIG_HOTPLUG)
-void kobject_uevent(struct kobject *kobj, enum kobject_action action);
-void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+int kobject_uevent(struct kobject *kobj, enum kobject_action action);
+int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp[]);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
@@ -274,11 +274,12 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
const char *format, ...)
__attribute__((format (printf, 7, 8)));
#else
-static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
-static inline void kobject_uevent_env(struct kobject *kobj,
+static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action)
+{ return 0; }
+static inline int kobject_uevent_env(struct kobject *kobj,
enum kobject_action action,
char *envp[])
-{ }
+{ return 0; }
static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
new file mode 100644
index 00000000000..1be148f0fce
--- /dev/null
+++ b/include/linux/kvm.h
@@ -0,0 +1,240 @@
+#ifndef __LINUX_KVM_H
+#define __LINUX_KVM_H
+
+/*
+ * Userspace interface for /dev/kvm - kernel based virtual machine
+ *
+ * Note: this interface is considered experimental and may change without
+ * notice.
+ */
+
+#include <asm/types.h>
+#include <linux/ioctl.h>
+
+#define KVM_API_VERSION 2
+
+/*
+ * Architectural interrupt line count, and the size of the bitmap needed
+ * to hold them.
+ */
+#define KVM_NR_INTERRUPTS 256
+#define KVM_IRQ_BITMAP_SIZE_BYTES ((KVM_NR_INTERRUPTS + 7) / 8)
+#define KVM_IRQ_BITMAP_SIZE(type) (KVM_IRQ_BITMAP_SIZE_BYTES / sizeof(type))
+
+
+/* for KVM_CREATE_MEMORY_REGION */
+struct kvm_memory_region {
+ __u32 slot;
+ __u32 flags;
+ __u64 guest_phys_addr;
+ __u64 memory_size; /* bytes */
+};
+
+/* for kvm_memory_region::flags */
+#define KVM_MEM_LOG_DIRTY_PAGES 1UL
+
+
+#define KVM_EXIT_TYPE_FAIL_ENTRY 1
+#define KVM_EXIT_TYPE_VM_EXIT 2
+
+enum kvm_exit_reason {
+ KVM_EXIT_UNKNOWN = 0,
+ KVM_EXIT_EXCEPTION = 1,
+ KVM_EXIT_IO = 2,
+ KVM_EXIT_CPUID = 3,
+ KVM_EXIT_DEBUG = 4,
+ KVM_EXIT_HLT = 5,
+ KVM_EXIT_MMIO = 6,
+ KVM_EXIT_IRQ_WINDOW_OPEN = 7,
+ KVM_EXIT_SHUTDOWN = 8,
+};
+
+/* for KVM_RUN */
+struct kvm_run {
+ /* in */
+ __u32 vcpu;
+ __u32 emulated; /* skip current instruction */
+ __u32 mmio_completed; /* mmio request completed */
+ __u8 request_interrupt_window;
+ __u8 padding1[3];
+
+ /* out */
+ __u32 exit_type;
+ __u32 exit_reason;
+ __u32 instruction_length;
+ __u8 ready_for_interrupt_injection;
+ __u8 if_flag;
+ __u16 padding2;
+ __u64 cr8;
+ __u64 apic_base;
+
+ union {
+ /* KVM_EXIT_UNKNOWN */
+ struct {
+ __u32 hardware_exit_reason;
+ } hw;
+ /* KVM_EXIT_EXCEPTION */
+ struct {
+ __u32 exception;
+ __u32 error_code;
+ } ex;
+ /* KVM_EXIT_IO */
+ struct {
+#define KVM_EXIT_IO_IN 0
+#define KVM_EXIT_IO_OUT 1
+ __u8 direction;
+ __u8 size; /* bytes */
+ __u8 string;
+ __u8 string_down;
+ __u8 rep;
+ __u8 pad;
+ __u16 port;
+ __u64 count;
+ union {
+ __u64 address;
+ __u32 value;
+ };
+ } io;
+ struct {
+ } debug;
+ /* KVM_EXIT_MMIO */
+ struct {
+ __u64 phys_addr;
+ __u8 data[8];
+ __u32 len;
+ __u8 is_write;
+ } mmio;
+ };
+};
+
+/* for KVM_GET_REGS and KVM_SET_REGS */
+struct kvm_regs {
+ /* in */
+ __u32 vcpu;
+ __u32 padding;
+
+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+ __u64 rax, rbx, rcx, rdx;
+ __u64 rsi, rdi, rsp, rbp;
+ __u64 r8, r9, r10, r11;
+ __u64 r12, r13, r14, r15;
+ __u64 rip, rflags;
+};
+
+struct kvm_segment {
+ __u64 base;
+ __u32 limit;
+ __u16 selector;
+ __u8 type;
+ __u8 present, dpl, db, s, l, g, avl;
+ __u8 unusable;
+ __u8 padding;
+};
+
+struct kvm_dtable {
+ __u64 base;
+ __u16 limit;
+ __u16 padding[3];
+};
+
+/* for KVM_GET_SREGS and KVM_SET_SREGS */
+struct kvm_sregs {
+ /* in */
+ __u32 vcpu;
+ __u32 padding;
+
+ /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
+ struct kvm_segment cs, ds, es, fs, gs, ss;
+ struct kvm_segment tr, ldt;
+ struct kvm_dtable gdt, idt;
+ __u64 cr0, cr2, cr3, cr4, cr8;
+ __u64 efer;
+ __u64 apic_base;
+ __u64 interrupt_bitmap[KVM_IRQ_BITMAP_SIZE(__u64)];
+};
+
+struct kvm_msr_entry {
+ __u32 index;
+ __u32 reserved;
+ __u64 data;
+};
+
+/* for KVM_GET_MSRS and KVM_SET_MSRS */
+struct kvm_msrs {
+ __u32 vcpu;
+ __u32 nmsrs; /* number of msrs in entries */
+
+ struct kvm_msr_entry entries[0];
+};
+
+/* for KVM_GET_MSR_INDEX_LIST */
+struct kvm_msr_list {
+ __u32 nmsrs; /* number of msrs in entries */
+ __u32 indices[0];
+};
+
+/* for KVM_TRANSLATE */
+struct kvm_translation {
+ /* in */
+ __u64 linear_address;
+ __u32 vcpu;
+ __u32 padding;
+
+ /* out */
+ __u64 physical_address;
+ __u8 valid;
+ __u8 writeable;
+ __u8 usermode;
+};
+
+/* for KVM_INTERRUPT */
+struct kvm_interrupt {
+ /* in */
+ __u32 vcpu;
+ __u32 irq;
+};
+
+struct kvm_breakpoint {
+ __u32 enabled;
+ __u32 padding;
+ __u64 address;
+};
+
+/* for KVM_DEBUG_GUEST */
+struct kvm_debug_guest {
+ /* int */
+ __u32 vcpu;
+ __u32 enabled;
+ struct kvm_breakpoint breakpoints[4];
+ __u32 singlestep;
+};
+
+/* for KVM_GET_DIRTY_LOG */
+struct kvm_dirty_log {
+ __u32 slot;
+ __u32 padding;
+ union {
+ void __user *dirty_bitmap; /* one bit per page */
+ __u64 padding;
+ };
+};
+
+#define KVMIO 0xAE
+
+#define KVM_GET_API_VERSION _IO(KVMIO, 1)
+#define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run)
+#define KVM_GET_REGS _IOWR(KVMIO, 3, struct kvm_regs)
+#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs)
+#define KVM_GET_SREGS _IOWR(KVMIO, 5, struct kvm_sregs)
+#define KVM_SET_SREGS _IOW(KVMIO, 6, struct kvm_sregs)
+#define KVM_TRANSLATE _IOWR(KVMIO, 7, struct kvm_translation)
+#define KVM_INTERRUPT _IOW(KVMIO, 8, struct kvm_interrupt)
+#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest)
+#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region)
+#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int /* vcpu_slot */)
+#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log)
+#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs)
+#define KVM_SET_MSRS _IOWR(KVMIO, 14, struct kvm_msrs)
+#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 15, struct kvm_msr_list)
+
+#endif
diff --git a/include/linux/libata.h b/include/linux/libata.h
index ab275483032..91bb8ceef0b 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -177,6 +177,7 @@ enum {
* Register FIS clearing BSY */
ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
+ ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
@@ -612,11 +613,11 @@ struct ata_port_operations {
void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap); /* obsolete */
- void (*set_mode) (struct ata_port *ap);
+ int (*set_mode) (struct ata_port *ap, struct ata_device **r_failed_dev);
void (*post_set_mode) (struct ata_port *ap);
- int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+ int (*check_atapi_dma) (struct ata_queued_cmd *qc);
void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc);
@@ -1053,6 +1054,8 @@ static inline void ata_pause(struct ata_port *ap)
/**
* ata_busy_wait - Wait for a port status register
* @ap: Port to wait for.
+ * @bits: bits that must be clear
+ * @max: number of 10uS waits to perform
*
* Waits up to max*10 microseconds for the selected bits in the port's
* status register to be cleared.
@@ -1143,12 +1146,15 @@ static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf)
static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
{
+ qc->dma_dir = DMA_NONE;
qc->__sg = NULL;
qc->flags = 0;
qc->cursect = qc->cursg = qc->cursg_ofs = 0;
qc->nsect = 0;
qc->nbytes = qc->curbytes = 0;
+ qc->n_elem = 0;
qc->err_mask = 0;
+ qc->pad_len = 0;
ata_tf_init(qc->dev, &qc->tf);
diff --git a/include/linux/list.h b/include/linux/list.h
index a9c90287c0f..611059d633f 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -227,13 +227,13 @@ static inline void list_replace_init(struct list_head *old,
INIT_LIST_HEAD(old);
}
-/*
+/**
* list_replace_rcu - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
- * The old entry will be replaced with the new entry atomically.
- * Note: 'old' should not be empty.
+ * The @old entry will be replaced with the @new entry atomically.
+ * Note: @old should not be empty.
*/
static inline void list_replace_rcu(struct list_head *old,
struct list_head *new)
@@ -680,12 +680,12 @@ static inline void hlist_del_init(struct hlist_node *n)
}
}
-/*
+/**
* hlist_replace_rcu - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
- * The old entry will be replaced with the new entry atomically.
+ * The @old entry will be replaced with the @new entry atomically.
*/
static inline void hlist_replace_rcu(struct hlist_node *old,
struct hlist_node *new)
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index aa50d89eacd..246de1d84a2 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -23,7 +23,7 @@ struct svc_rqst;
* This is the set of functions for lockd->nfsd communication
*/
struct nlmsvc_binding {
- u32 (*fopen)(struct svc_rqst *,
+ __be32 (*fopen)(struct svc_rqst *,
struct nfs_fh *,
struct file **);
void (*fclose)(struct file *);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 8c39654549d..ac25b5649c5 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -191,7 +191,7 @@ __be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
unsigned long nlmsvc_retry_blocked(void);
void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
nlm_host_match_fn_t match);
-void nlmsvc_grant_reply(struct nlm_cookie *, u32);
+void nlmsvc_grant_reply(struct nlm_cookie *, __be32);
/*
* File handling for the server personality
@@ -206,7 +206,7 @@ void nlmsvc_invalidate_all(void);
static __inline__ struct inode *
nlmsvc_file_inode(struct nlm_file *file)
{
- return file->f_file->f_dentry->d_inode;
+ return file->f_file->f_path.dentry->d_inode;
}
/*
diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
index fc61d40964d..22a645828f2 100644
--- a/include/linux/lockd/sm_inter.h
+++ b/include/linux/lockd/sm_inter.h
@@ -24,7 +24,7 @@
* Arguments for all calls to statd
*/
struct nsm_args {
- u32 addr; /* remote address */
+ __be32 addr; /* remote address */
u32 prog; /* RPC callback info */
u32 vers;
u32 proc;
diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h
index 29e7d9fc9da..83a1f9f6237 100644
--- a/include/linux/lockd/xdr.h
+++ b/include/linux/lockd/xdr.h
@@ -69,7 +69,7 @@ typedef struct nlm_args nlm_args;
*/
struct nlm_res {
struct nlm_cookie cookie;
- u32 status;
+ __be32 status;
struct nlm_lock lock;
};
@@ -80,9 +80,9 @@ struct nlm_reboot {
char * mon;
int len;
u32 state;
- u32 addr;
- u32 vers;
- u32 proto;
+ __be32 addr;
+ __be32 vers;
+ __be32 proto;
};
/*
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 498bfbd3b4e..ea097dddc44 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -281,15 +281,25 @@ struct lock_class_key { };
#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
extern void early_init_irq_lock_class(void);
#else
-# define early_init_irq_lock_class() do { } while (0)
+static inline void early_init_irq_lock_class(void)
+{
+}
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
extern void early_boot_irqs_off(void);
extern void early_boot_irqs_on(void);
+extern void print_irqtrace_events(struct task_struct *curr);
#else
-# define early_boot_irqs_off() do { } while (0)
-# define early_boot_irqs_on() do { } while (0)
+static inline void early_boot_irqs_off(void)
+{
+}
+static inline void early_boot_irqs_on(void)
+{
+}
+static inline void print_irqtrace_events(struct task_struct *curr)
+{
+}
#endif
/*
diff --git a/include/linux/log2.h b/include/linux/log2.h
new file mode 100644
index 00000000000..d02e1a547a7
--- /dev/null
+++ b/include/linux/log2.h
@@ -0,0 +1,157 @@
+/* Integer base 2 logarithm calculation
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_LOG2_H
+#define _LINUX_LOG2_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+/*
+ * deal with unrepresentable constant logarithms
+ */
+extern __attribute__((const, noreturn))
+int ____ilog2_NaN(void);
+
+/*
+ * non-constant log of base 2 calculators
+ * - the arch may override these in asm/bitops.h if they can be implemented
+ * more efficiently than using fls() and fls64()
+ * - the arch is not required to handle n==0 if implementing the fallback
+ */
+#ifndef CONFIG_ARCH_HAS_ILOG2_U32
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+ return fls(n) - 1;
+}
+#endif
+
+#ifndef CONFIG_ARCH_HAS_ILOG2_U64
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+ return fls64(n) - 1;
+}
+#endif
+
+/*
+ * round up to nearest power of two
+ */
+static inline __attribute__((const))
+unsigned long __roundup_pow_of_two(unsigned long n)
+{
+ return 1UL << fls_long(n - 1);
+}
+
+/**
+ * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
+ * @n - parameter
+ *
+ * constant-capable log of base 2 calculation
+ * - this can be used to initialise global variables from constant data, hence
+ * the massive ternary operator construction
+ *
+ * selects the appropriately-sized optimised version depending on sizeof(n)
+ */
+#define ilog2(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ (n) < 1 ? ____ilog2_NaN() : \
+ (n) & (1ULL << 63) ? 63 : \
+ (n) & (1ULL << 62) ? 62 : \
+ (n) & (1ULL << 61) ? 61 : \
+ (n) & (1ULL << 60) ? 60 : \
+ (n) & (1ULL << 59) ? 59 : \
+ (n) & (1ULL << 58) ? 58 : \
+ (n) & (1ULL << 57) ? 57 : \
+ (n) & (1ULL << 56) ? 56 : \
+ (n) & (1ULL << 55) ? 55 : \
+ (n) & (1ULL << 54) ? 54 : \
+ (n) & (1ULL << 53) ? 53 : \
+ (n) & (1ULL << 52) ? 52 : \
+ (n) & (1ULL << 51) ? 51 : \
+ (n) & (1ULL << 50) ? 50 : \
+ (n) & (1ULL << 49) ? 49 : \
+ (n) & (1ULL << 48) ? 48 : \
+ (n) & (1ULL << 47) ? 47 : \
+ (n) & (1ULL << 46) ? 46 : \
+ (n) & (1ULL << 45) ? 45 : \
+ (n) & (1ULL << 44) ? 44 : \
+ (n) & (1ULL << 43) ? 43 : \
+ (n) & (1ULL << 42) ? 42 : \
+ (n) & (1ULL << 41) ? 41 : \
+ (n) & (1ULL << 40) ? 40 : \
+ (n) & (1ULL << 39) ? 39 : \
+ (n) & (1ULL << 38) ? 38 : \
+ (n) & (1ULL << 37) ? 37 : \
+ (n) & (1ULL << 36) ? 36 : \
+ (n) & (1ULL << 35) ? 35 : \
+ (n) & (1ULL << 34) ? 34 : \
+ (n) & (1ULL << 33) ? 33 : \
+ (n) & (1ULL << 32) ? 32 : \
+ (n) & (1ULL << 31) ? 31 : \
+ (n) & (1ULL << 30) ? 30 : \
+ (n) & (1ULL << 29) ? 29 : \
+ (n) & (1ULL << 28) ? 28 : \
+ (n) & (1ULL << 27) ? 27 : \
+ (n) & (1ULL << 26) ? 26 : \
+ (n) & (1ULL << 25) ? 25 : \
+ (n) & (1ULL << 24) ? 24 : \
+ (n) & (1ULL << 23) ? 23 : \
+ (n) & (1ULL << 22) ? 22 : \
+ (n) & (1ULL << 21) ? 21 : \
+ (n) & (1ULL << 20) ? 20 : \
+ (n) & (1ULL << 19) ? 19 : \
+ (n) & (1ULL << 18) ? 18 : \
+ (n) & (1ULL << 17) ? 17 : \
+ (n) & (1ULL << 16) ? 16 : \
+ (n) & (1ULL << 15) ? 15 : \
+ (n) & (1ULL << 14) ? 14 : \
+ (n) & (1ULL << 13) ? 13 : \
+ (n) & (1ULL << 12) ? 12 : \
+ (n) & (1ULL << 11) ? 11 : \
+ (n) & (1ULL << 10) ? 10 : \
+ (n) & (1ULL << 9) ? 9 : \
+ (n) & (1ULL << 8) ? 8 : \
+ (n) & (1ULL << 7) ? 7 : \
+ (n) & (1ULL << 6) ? 6 : \
+ (n) & (1ULL << 5) ? 5 : \
+ (n) & (1ULL << 4) ? 4 : \
+ (n) & (1ULL << 3) ? 3 : \
+ (n) & (1ULL << 2) ? 2 : \
+ (n) & (1ULL << 1) ? 1 : \
+ (n) & (1ULL << 0) ? 0 : \
+ ____ilog2_NaN() \
+ ) : \
+ (sizeof(n) <= 4) ? \
+ __ilog2_u32(n) : \
+ __ilog2_u64(n) \
+ )
+
+/**
+ * roundup_pow_of_two - round the given value up to nearest power of two
+ * @n - parameter
+ *
+ * round the given balue up to the nearest power of two
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define roundup_pow_of_two(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ (n == 1) ? 0 : \
+ (1UL << (ilog2((n) - 1) + 1)) \
+ ) : \
+ __roundup_pow_of_two(n) \
+ )
+
+#endif /* _LINUX_LOG2_H */
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 156c40fc664..b78bbf42135 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -3,6 +3,7 @@
#define ADFS_SUPER_MAGIC 0xadf5
#define AFFS_SUPER_MAGIC 0xadff
+#define AFS_SUPER_MAGIC 0x5346414F
#define AUTOFS_SUPER_MAGIC 0x0187
#define CODA_SUPER_MAGIC 0x73757245
#define EFS_SUPER_MAGIC 0x414A53
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a17b147c61e..2d2c08d5f47 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -168,6 +168,7 @@ extern unsigned int kobjsize(const void *objp);
#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */
#define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
#define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
+#define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */
#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
@@ -978,7 +979,8 @@ extern int early_pfn_to_nid(unsigned long pfn);
#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
extern void set_dma_reserve(unsigned long new_dma_reserve);
-extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
+extern void memmap_init_zone(unsigned long, int, unsigned long,
+ unsigned long, enum memmap_context);
extern void setup_per_zone_pages_min(void);
extern void mem_init(void);
extern void show_mem(void);
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index a3594dfd696..bcf24909d67 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -42,7 +42,7 @@ struct mmc_command {
#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
-#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC)
+#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define mmc_resp_type(cmd) ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e339a7345f2..b262f47961f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -450,9 +450,13 @@ void build_all_zonelists(void);
void wakeup_kswapd(struct zone *zone, int order);
int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
int classzone_idx, int alloc_flags);
-
+enum memmap_context {
+ MEMMAP_EARLY,
+ MEMMAP_HOTPLUG,
+};
extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
- unsigned long size);
+ unsigned long size,
+ enum memmap_context context);
#ifdef CONFIG_HAVE_MEMORY_PRESENT
void memory_present(int nid, unsigned long start, unsigned long end);
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
new file mode 100644
index 00000000000..4af0b1fc282
--- /dev/null
+++ b/include/linux/mnt_namespace.h
@@ -0,0 +1,42 @@
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+#ifdef __KERNEL__
+
+#include <linux/mount.h>
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+
+struct mnt_namespace {
+ atomic_t count;
+ struct vfsmount * root;
+ struct list_head list;
+ wait_queue_head_t poll;
+ int event;
+};
+
+extern int copy_mnt_ns(int, struct task_struct *);
+extern void __put_mnt_ns(struct mnt_namespace *ns);
+extern struct mnt_namespace *dup_mnt_ns(struct task_struct *,
+ struct fs_struct *);
+
+static inline void put_mnt_ns(struct mnt_namespace *ns)
+{
+ if (atomic_dec_and_lock(&ns->count, &vfsmount_lock))
+ /* releases vfsmount_lock */
+ __put_mnt_ns(ns);
+}
+
+static inline void exit_mnt_ns(struct task_struct *p)
+{
+ struct mnt_namespace *ns = p->nsproxy->mnt_ns;
+ if (ns)
+ put_mnt_ns(ns);
+}
+
+static inline void get_mnt_ns(struct mnt_namespace *ns)
+{
+ atomic_inc(&ns->count);
+}
+
+#endif
+#endif
diff --git a/include/linux/module.h b/include/linux/module.h
index d33df2408e0..10f771a4999 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -319,6 +319,13 @@ struct module
unsigned int taints; /* same bits as kernel:tainted */
+#ifdef CONFIG_GENERIC_BUG
+ /* Support for BUG */
+ struct list_head bug_list;
+ struct bug_entry *bug_table;
+ unsigned num_bugs;
+#endif
+
#ifdef CONFIG_MODULE_UNLOAD
/* Reference counts */
struct module_ref ref[NR_CPUS];
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 403d1a97c51..1b7e178b0d8 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -20,13 +20,14 @@
struct super_block;
struct vfsmount;
struct dentry;
-struct namespace;
+struct mnt_namespace;
#define MNT_NOSUID 0x01
#define MNT_NODEV 0x02
#define MNT_NOEXEC 0x04
#define MNT_NOATIME 0x08
#define MNT_NODIRATIME 0x10
+#define MNT_RELATIME 0x20
#define MNT_SHRINKABLE 0x100
@@ -52,7 +53,7 @@ struct vfsmount {
struct list_head mnt_slave_list;/* list of slave mounts */
struct list_head mnt_slave; /* slave list entry */
struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
- struct namespace *mnt_namespace; /* containing namespace */
+ struct mnt_namespace *mnt_ns; /* containing namespace */
int mnt_pinned;
};
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index 72fc68c5ee9..9a6e2f953cb 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -24,7 +24,6 @@ struct mtd_blktrans_dev {
struct mtd_info *mtd;
struct mutex lock;
int devnum;
- int blksize;
unsigned long size;
int readonly;
void *blkcore_priv; /* gendisk in 2.5, devfs_handle in 2.4 */
@@ -36,6 +35,8 @@ struct mtd_blktrans_ops {
char *name;
int major;
int part_bits;
+ int blksize;
+ int blkshift;
/* Access functions */
int (*readsect)(struct mtd_blktrans_dev *dev,
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 94a443d4525..d644e57703a 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -23,7 +23,7 @@
#define MTD_CHAR_MAJOR 90
#define MTD_BLOCK_MAJOR 31
-#define MAX_MTD_DEVICES 16
+#define MAX_MTD_DEVICES 32
#define MTD_ERASE_PENDING 0x01
#define MTD_ERASING 0x02
@@ -75,15 +75,12 @@ typedef enum {
* struct mtd_oob_ops - oob operation operands
* @mode: operation mode
*
- * @len: number of bytes to write/read. When a data buffer is given
- * (datbuf != NULL) this is the number of data bytes. When
- * no data buffer is available this is the number of oob bytes.
+ * @len: number of data bytes to write/read
*
- * @retlen: number of bytes written/read. When a data buffer is given
- * (datbuf != NULL) this is the number of data bytes. When
- * no data buffer is available this is the number of oob bytes.
+ * @retlen: number of data bytes written/read
*
- * @ooblen: number of oob bytes per page
+ * @ooblen: number of oob bytes to write/read
+ * @oobretlen: number of oob bytes written/read
* @ooboffs: offset of oob data in the oob area (only relevant when
* mode = MTD_OOB_PLACE)
* @datbuf: data buffer - if NULL only oob data are read/written
@@ -94,6 +91,7 @@ struct mtd_oob_ops {
size_t len;
size_t retlen;
size_t ooblen;
+ size_t oobretlen;
uint32_t ooboffs;
uint8_t *datbuf;
uint8_t *oobbuf;
@@ -202,11 +200,20 @@ struct mtd_info {
/* ECC status information */
struct mtd_ecc_stats ecc_stats;
+ /* Subpage shift (NAND) */
+ int subpage_sft;
void *priv;
struct module *owner;
int usecount;
+
+ /* If the driver is something smart, like UBI, it may need to maintain
+ * its own reference counting. The below functions are only for driver.
+ * The driver may register its callbacks. These callbacks are not
+ * supposed to be called by MTD users */
+ int (*get_device) (struct mtd_info *mtd);
+ void (*put_device) (struct mtd_info *mtd);
};
@@ -216,6 +223,7 @@ extern int add_mtd_device(struct mtd_info *mtd);
extern int del_mtd_device (struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
+extern struct mtd_info *get_mtd_device_nm(const char *name);
extern void put_mtd_device(struct mtd_info *mtd);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8b3ef418721..2071b02f052 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -166,6 +166,9 @@ typedef enum {
* for all large page devices, as they do not support
* autoincrement.*/
#define NAND_NO_READRDY 0x00000100
+/* Chip does not allow subpage writes */
+#define NAND_NO_SUBPAGE_WRITE 0x00000200
+
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
@@ -193,6 +196,9 @@ typedef enum {
/* Nand scan has allocated controller struct */
#define NAND_CONTROLLER_ALLOC 0x80000000
+/* Cell info constants */
+#define NAND_CI_CHIPNR_MSK 0x03
+#define NAND_CI_CELLTYPE_MSK 0x0C
/*
* nand_state_t - chip states
@@ -286,9 +292,7 @@ struct nand_ecc_ctrl {
* struct nand_buffers - buffer structure for read/write
* @ecccalc: buffer for calculated ecc
* @ecccode: buffer for ecc read from flash
- * @oobwbuf: buffer for write oob data
* @databuf: buffer for data - dynamically sized
- * @oobrbuf: buffer to read oob data
*
* Do not change the order of buffers. databuf and oobrbuf must be in
* consecutive order.
@@ -296,9 +300,7 @@ struct nand_ecc_ctrl {
struct nand_buffers {
uint8_t ecccalc[NAND_MAX_OOBSIZE];
uint8_t ecccode[NAND_MAX_OOBSIZE];
- uint8_t oobwbuf[NAND_MAX_OOBSIZE];
- uint8_t databuf[NAND_MAX_PAGESIZE];
- uint8_t oobrbuf[NAND_MAX_OOBSIZE];
+ uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
};
/**
@@ -345,6 +347,7 @@ struct nand_buffers {
* @chipsize: [INTERN] the size of one chip for multichip arrays
* @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
* @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf
+ * @subpagesize: [INTERN] holds the subpagesize
* @ecclayout: [REPLACEABLE] the default ecc placement scheme
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
@@ -392,6 +395,8 @@ struct nand_chip {
unsigned long chipsize;
int pagemask;
int pagebuf;
+ int subpagesize;
+ uint8_t cellinfo;
int badblockpos;
nand_state_t state;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 6f045b586e7..f775a7af389 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -13,6 +13,7 @@
#define __LINUX_MTD_ONENAND_H
#include <linux/spinlock.h>
+#include <linux/completion.h>
#include <linux/mtd/onenand_regs.h>
#include <linux/mtd/bbm.h>
@@ -33,7 +34,6 @@ typedef enum {
FL_WRITING,
FL_ERASING,
FL_SYNCING,
- FL_UNLOCKING,
FL_LOCKING,
FL_RESETING,
FL_OTPING,
@@ -88,6 +88,7 @@ struct onenand_bufferram {
* operation is in progress
* @state: [INTERN] the current state of the OneNAND device
* @page_buf: data buffer
+ * @subpagesize: [INTERN] holds the subpagesize
* @ecclayout: [REPLACEABLE] the default ecc placement scheme
* @bbm: [REPLACEABLE] pointer to Bad Block Management
* @priv: [OPTIONAL] pointer to private chip date
@@ -120,11 +121,15 @@ struct onenand_chip {
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
int (*scan_bbt)(struct mtd_info *mtd);
+ struct completion complete;
+ int irq;
+
spinlock_t chip_lock;
wait_queue_head_t wq;
onenand_state_t state;
unsigned char *page_buf;
+ int subpagesize;
struct nand_ecclayout *ecclayout;
void *bbm;
@@ -138,6 +143,7 @@ struct onenand_chip {
#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
+#define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
#define ONENAND_GET_SYS_CFG1(this) \
(this->read_word(this->base + ONENAND_REG_SYS_CFG1))
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index 9e409fe6ded..e31c8f5d427 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -179,6 +179,7 @@
* ECC Status Reigser FF00h (R)
*/
#define ONENAND_ECC_1BIT (1 << 0)
+#define ONENAND_ECC_1BIT_ALL (0x5555)
#define ONENAND_ECC_2BIT (1 << 1)
#define ONENAND_ECC_2BIT_ALL (0xAAAA)
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index 8c66151821e..6f8d2d45a8f 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -10,7 +10,6 @@
#include <linux/types.h>
#include <linux/ioctl.h>
-#include <linux/qic117.h>
/*
* Structures and definitions for mag tape io control commands
@@ -116,32 +115,6 @@ struct mtget {
#define MT_ISFTAPE_UNKNOWN 0x800000 /* obsolete */
#define MT_ISFTAPE_FLAG 0x800000
-struct mt_tape_info {
- long t_type; /* device type id (mt_type) */
- char *t_name; /* descriptive name */
-};
-
-#define MT_TAPE_INFO { \
- {MT_ISUNKNOWN, "Unknown type of tape device"}, \
- {MT_ISQIC02, "Generic QIC-02 tape streamer"}, \
- {MT_ISWT5150, "Wangtek 5150, QIC-150"}, \
- {MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \
- {MT_ISCMSJ500, "CMS Jumbo 500"}, \
- {MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \
- {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \
- {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \
- {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \
- {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \
- {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \
- {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \
- {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \
- {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \
- {MT_ISONSTREAM_SC, "OnStream SC-, DI-, DP-, or USB tape drive"}, \
- {MT_ISSCSI1, "Generic SCSI-1 tape"}, \
- {MT_ISSCSI2, "Generic SCSI-2 tape"}, \
- {0, NULL} \
-}
-
/* structure for MTIOCPOS - mag tape get position command */
@@ -150,130 +123,11 @@ struct mtpos {
};
-/* structure for MTIOCVOLINFO, query information about the volume
- * currently positioned at (zftape)
- */
-struct mtvolinfo {
- unsigned int mt_volno; /* vol-number */
- unsigned int mt_blksz; /* blocksize used when recording */
- unsigned int mt_rawsize; /* raw tape space consumed, in kb */
- unsigned int mt_size; /* volume size after decompression, in kb */
- unsigned int mt_cmpr:1; /* this volume has been compressed */
-};
-
-/* raw access to a floppy drive, read and write an arbitrary segment.
- * For ftape/zftape to support formatting etc.
- */
-#define MT_FT_RD_SINGLE 0
-#define MT_FT_RD_AHEAD 1
-#define MT_FT_WR_ASYNC 0 /* start tape only when all buffers are full */
-#define MT_FT_WR_MULTI 1 /* start tape, continue until buffers are empty */
-#define MT_FT_WR_SINGLE 2 /* write a single segment and stop afterwards */
-#define MT_FT_WR_DELETE 3 /* write deleted data marks, one segment at time */
-
-struct mtftseg
-{
- unsigned mt_segno; /* the segment to read or write */
- unsigned mt_mode; /* modes for read/write (sync/async etc.) */
- int mt_result; /* result of r/w request, not of the ioctl */
- void __user *mt_data; /* User space buffer: must be 29kb */
-};
-
-/* get tape capacity (ftape/zftape)
- */
-struct mttapesize {
- unsigned long mt_capacity; /* entire, uncompressed capacity
- * of a cartridge
- */
- unsigned long mt_used; /* what has been used so far, raw
- * uncompressed amount
- */
-};
-
-/* possible values of the ftfmt_op field
- */
-#define FTFMT_SET_PARMS 1 /* set software parms */
-#define FTFMT_GET_PARMS 2 /* get software parms */
-#define FTFMT_FORMAT_TRACK 3 /* start formatting a tape track */
-#define FTFMT_STATUS 4 /* monitor formatting a tape track */
-#define FTFMT_VERIFY 5 /* verify the given segment */
-
-struct ftfmtparms {
- unsigned char ft_qicstd; /* QIC-40/QIC-80/QIC-3010/QIC-3020 */
- unsigned char ft_fmtcode; /* Refer to the QIC specs */
- unsigned char ft_fhm; /* floppy head max */
- unsigned char ft_ftm; /* floppy track max */
- unsigned short ft_spt; /* segments per track */
- unsigned short ft_tpc; /* tracks per cartridge */
-};
-
-struct ftfmttrack {
- unsigned int ft_track; /* track to format */
- unsigned char ft_gap3; /* size of gap3, for FORMAT_TRK */
-};
-
-struct ftfmtstatus {
- unsigned int ft_segment; /* segment currently being formatted */
-};
-
-struct ftfmtverify {
- unsigned int ft_segment; /* segment to verify */
- unsigned long ft_bsm; /* bsm as result of VERIFY cmd */
-};
-
-struct mtftformat {
- unsigned int fmt_op; /* operation to perform */
- union fmt_arg {
- struct ftfmtparms fmt_parms; /* format parameters */
- struct ftfmttrack fmt_track; /* ctrl while formatting */
- struct ftfmtstatus fmt_status;
- struct ftfmtverify fmt_verify; /* for verifying */
- } fmt_arg;
-};
-
-struct mtftcmd {
- unsigned int ft_wait_before; /* timeout to wait for drive to get ready
- * before command is sent. Milliseconds
- */
- qic117_cmd_t ft_cmd; /* command to send */
- unsigned char ft_parm_cnt; /* zero: no parm is sent. */
- unsigned char ft_parms[3]; /* parameter(s) to send to
- * the drive. The parms are nibbles
- * driver sends cmd + 2 step pulses */
- unsigned int ft_result_bits; /* if non zero, number of bits
- * returned by the tape drive
- */
- unsigned int ft_result; /* the result returned by the tape drive*/
- unsigned int ft_wait_after; /* timeout to wait for drive to get ready
- * after command is sent. 0: don't wait */
- int ft_status; /* status returned by ready wait
- * undefined if timeout was 0.
- */
- int ft_error; /* error code if error status was set by
- * command
- */
-};
-
/* mag tape io control commands */
#define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
#define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */
#define MTIOCPOS _IOR('m', 3, struct mtpos) /* get tape position */
-/* The next two are used by the QIC-02 driver for runtime reconfiguration.
- * See tpqic02.h for struct mtconfiginfo.
- */
-#define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) /* get tape config */
-#define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) /* set tape config */
-
-/* the next six are used by the floppy ftape drivers and its frontends
- * sorry, but MTIOCTOP commands are write only.
- */
-#define MTIOCRDFTSEG _IOWR('m', 6, struct mtftseg) /* read a segment */
-#define MTIOCWRFTSEG _IOWR('m', 7, struct mtftseg) /* write a segment */
-#define MTIOCVOLINFO _IOR('m', 8, struct mtvolinfo) /* info about volume */
-#define MTIOCGETSIZE _IOR('m', 9, struct mttapesize)/* get cartridge size*/
-#define MTIOCFTFORMAT _IOWR('m', 10, struct mtftformat) /* format ftape */
-#define MTIOCFTCMD _IOWR('m', 11, struct mtftcmd) /* send QIC-117 cmd */
/* Generic Mag Tape (device independent) status macros for examining
* mt_gstat -- HP-UX compatible.
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index b2b91c47756..b81bc2adaef 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -105,7 +105,7 @@ do { \
extern void __mutex_init(struct mutex *lock, const char *name,
struct lock_class_key *key);
-/***
+/**
* mutex_is_locked - is the mutex locked
* @lock: the mutex to be queried
*
@@ -125,8 +125,10 @@ extern int fastcall mutex_lock_interruptible(struct mutex *lock);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
+extern int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass);
#else
# define mutex_lock_nested(lock, subclass) mutex_lock(lock)
+# define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock)
#endif
/*
diff --git a/include/linux/n_r3964.h b/include/linux/n_r3964.h
index db4f3776978..de24af79ebd 100644
--- a/include/linux/n_r3964.h
+++ b/include/linux/n_r3964.h
@@ -116,7 +116,7 @@ struct r3964_message;
struct r3964_client_info {
spinlock_t lock;
- pid_t pid;
+ struct pid *pid;
unsigned int sig_flags;
struct r3964_client_info *next;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index f5f19606eff..d39a5a67e97 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -29,6 +29,11 @@ struct nameidata {
} intent;
};
+struct path {
+ struct vfsmount *mnt;
+ struct dentry *dentry;
+};
+
/*
* Type of the last component on LOOKUP_PARENT
*/
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
deleted file mode 100644
index d137009f0b2..00000000000
--- a/include/linux/namespace.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _NAMESPACE_H_
-#define _NAMESPACE_H_
-#ifdef __KERNEL__
-
-#include <linux/mount.h>
-#include <linux/sched.h>
-#include <linux/nsproxy.h>
-
-struct namespace {
- atomic_t count;
- struct vfsmount * root;
- struct list_head list;
- wait_queue_head_t poll;
- int event;
-};
-
-extern int copy_namespace(int, struct task_struct *);
-extern void __put_namespace(struct namespace *namespace);
-extern struct namespace *dup_namespace(struct task_struct *, struct fs_struct *);
-
-static inline void put_namespace(struct namespace *namespace)
-{
- if (atomic_dec_and_lock(&namespace->count, &vfsmount_lock))
- /* releases vfsmount_lock */
- __put_namespace(namespace);
-}
-
-static inline void exit_namespace(struct task_struct *p)
-{
- struct namespace *namespace = p->nsproxy->namespace;
- if (namespace) {
- put_namespace(namespace);
- }
-}
-
-static inline void get_namespace(struct namespace *namespace)
-{
- atomic_inc(&namespace->count);
-}
-
-#endif
-#endif
diff --git a/include/linux/ncp_mount.h b/include/linux/ncp_mount.h
index f46bddcdbd3..a2b549eb1ec 100644
--- a/include/linux/ncp_mount.h
+++ b/include/linux/ncp_mount.h
@@ -75,7 +75,7 @@ struct ncp_mount_data_kernel {
unsigned int int_flags; /* internal flags */
#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001
__kernel_uid32_t mounted_uid; /* Who may umount() this filesystem? */
- __kernel_pid_t wdog_pid; /* Who cares for our watchdog packets? */
+ struct pid *wdog_pid; /* Who cares for our watchdog packets? */
unsigned int ncp_fd; /* The socket to the ncp port */
unsigned int time_out; /* How long should I wait after
sending a NCP request? */
diff --git a/include/linux/net.h b/include/linux/net.h
index 6f0dfeba509..f28d8a2e2c9 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -19,7 +19,6 @@
#define _LINUX_NET_H
#include <linux/wait.h>
-#include <linux/random.h>
#include <asm/socket.h>
struct poll_table_struct;
@@ -57,6 +56,7 @@ typedef enum {
#ifdef __KERNEL__
#include <linux/stringify.h>
+#include <linux/random.h>
#define SOCK_ASYNC_NOSPACE 0
#define SOCK_ASYNC_WAITDATA 1
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c57088f575a..fea0d9db684 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -193,13 +193,20 @@ struct hh_cache
{
struct hh_cache *hh_next; /* Next entry */
atomic_t hh_refcnt; /* number of users */
- __be16 hh_type; /* protocol identifier, f.e ETH_P_IP
+/*
+ * We want hh_output, hh_len, hh_lock and hh_data be a in a separate
+ * cache line on SMP.
+ * They are mostly read, but hh_refcnt may be changed quite frequently,
+ * incurring cache line ping pongs.
+ */
+ __be16 hh_type ____cacheline_aligned_in_smp;
+ /* protocol identifier, f.e ETH_P_IP
* NOTE: For VLANs, this will be the
* encapuslated type. --BLG
*/
u16 hh_len; /* length of header */
int (*hh_output)(struct sk_buff *skb);
- rwlock_t hh_lock;
+ seqlock_t hh_lock;
/* cached hardware header; allow for machine alignment needs. */
#define HH_DATA_MOD 16
@@ -899,6 +906,7 @@ static inline void netif_poll_disable(struct net_device *dev)
static inline void netif_poll_enable(struct net_device *dev)
{
+ smp_mb__before_clear_bit();
clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
}
diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h
index 6b01ba29772..2f4e98b90cc 100644
--- a/include/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/linux/netfilter/nf_conntrack_tcp.h
@@ -25,7 +25,7 @@ enum tcp_conntrack {
#define IP_CT_TCP_FLAG_SACK_PERM 0x02
/* This sender sent FIN first */
-#define IP_CT_TCP_FLAG_CLOSE_INIT 0x03
+#define IP_CT_TCP_FLAG_CLOSE_INIT 0x04
#ifdef __KERNEL__
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 0be235418a2..24c8786d12e 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -190,6 +190,7 @@ struct arpt_replace
/* The argument to ARPT_SO_ADD_COUNTERS. */
#define arpt_counters_info xt_counters_info
+#define arpt_counters xt_counters
/* The argument to ARPT_SO_GET_ENTRIES. */
struct arpt_get_entries
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 6c4613f8ad7..55689f39f77 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -68,7 +68,6 @@ struct bridge_skb_cb {
} daddr;
};
-extern int brnf_deferred_hooks;
#else
#define nf_bridge_maybe_copy_header(skb) (0)
#define nf_bridge_pad(skb) (0)
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 5821eb5a0a3..ceae87a4c89 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -57,10 +57,8 @@ enum nf_ip_hook_priorities {
NF_IP_PRI_RAW = -300,
NF_IP_PRI_SELINUX_FIRST = -225,
NF_IP_PRI_CONNTRACK = -200,
- NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
NF_IP_PRI_MANGLE = -150,
NF_IP_PRI_NAT_DST = -100,
- NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_SELINUX_LAST = 225,
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 4f06dad0bde..98d566c5e32 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -28,7 +28,7 @@
#include <linux/netfilter/x_tables.h>
#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
-#define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
#define ipt_match xt_match
#define ipt_target xt_target
#define ipt_table xt_table
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index ab81a6dc94e..66ca8e3100d 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -62,10 +62,8 @@ enum nf_ip6_hook_priorities {
NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
NF_IP6_PRI_SELINUX_FIRST = -225,
NF_IP6_PRI_CONNTRACK = -200,
- NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
NF_IP6_PRI_MANGLE = -150,
NF_IP6_PRI_NAT_DST = -100,
- NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
NF_IP6_PRI_FILTER = 0,
NF_IP6_PRI_NAT_SRC = 100,
NF_IP6_PRI_SELINUX_LAST = 225,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 04963063e62..c5d4084773e 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -308,6 +308,7 @@ extern int nfs_attribute_timeout(struct inode *inode);
extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
+extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping);
extern int nfs_setattr(struct dentry *, struct iattr *);
extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
extern void nfs_begin_attr_update(struct inode *);
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index edb54c3171b..4b7c4b568f6 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -52,8 +52,6 @@
struct readdir_cd {
__be32 err; /* 0, nfserr, or nfserr_eof */
};
-typedef int (*encode_dent_fn)(struct readdir_cd *, const char *,
- int, loff_t, ino_t, unsigned int);
typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
extern struct svc_program nfsd_program;
@@ -117,7 +115,7 @@ __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
unsigned long size);
__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
- loff_t *, struct readdir_cd *, encode_dent_fn);
+ loff_t *, struct readdir_cd *, filldir_t);
__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct kstatfs *);
@@ -275,12 +273,12 @@ static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
* we might process an operation with side effects, and be unable to
* tell the client that the operation succeeded.
*
- * COMPOUND_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_SLACK_SPACE - this is the minimum bytes of buffer space
* needed to encode an "ordinary" _successful_ operation. (GETATTR,
* READ, READDIR, and READLINK have their own buffer checks.) if we
* fall below this level, we fail the next operation with NFS4ERR_RESOURCE.
*
- * COMPOUND_ERR_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_ERR_SLACK_SPACE - this is the minimum bytes of buffer space
* needed to encode an operation which has failed with NFS4ERR_RESOURCE.
* care is taken to ensure that we never fall below this level for any
* reason.
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index f3b51d62ec7..d9c6c382165 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -217,11 +217,7 @@ void fh_put(struct svc_fh *);
static __inline__ struct svc_fh *
fh_copy(struct svc_fh *dst, struct svc_fh *src)
{
- if (src->fh_dentry || src->fh_locked) {
- struct dentry *dentry = src->fh_dentry;
- printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
- }
+ WARN_ON(src->fh_dentry || src->fh_locked);
*dst = *src;
return dst;
@@ -300,10 +296,8 @@ fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
SVCFH_fmt(fhp), fhp->fh_locked);
- if (!fhp->fh_dentry) {
- printk(KERN_ERR "fh_lock: fh not verified!\n");
- return;
- }
+ BUG_ON(!dentry);
+
if (fhp->fh_locked) {
printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -328,8 +322,7 @@ fh_lock(struct svc_fh *fhp)
static inline void
fh_unlock(struct svc_fh *fhp)
{
- if (!fhp->fh_dentry)
- printk(KERN_ERR "fh_unlock: fh not verified!\n");
+ BUG_ON(!fhp->fh_dentry);
if (fhp->fh_locked) {
fill_post_wcc(fhp);
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index c3673f487e8..ab5c236bd9a 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -273,7 +273,6 @@ struct nfs4_stateid {
((err) != nfserr_stale_stateid) && \
((err) != nfserr_bad_stateid))
-extern __be32 nfsd4_renew(clientid_t *clid);
extern __be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
stateid_t *stateid, int flags, struct file **filp);
extern void nfs4_lock_state(void);
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index 877192d3ae7..67885d5e6e5 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -165,8 +165,8 @@ int nfssvc_encode_readres(struct svc_rqst *, __be32 *, struct nfsd_readres *);
int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *, struct nfsd_statfsres *);
int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *, struct nfsd_readdirres *);
-int nfssvc_encode_entry(struct readdir_cd *, const char *name,
- int namlen, loff_t offset, ino_t ino, unsigned int);
+int nfssvc_encode_entry(void *, const char *name,
+ int namlen, loff_t offset, u64 ino, unsigned int);
int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 79963867b0d..89d9d6061a6 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -331,11 +331,11 @@ int nfs3svc_release_fhandle(struct svc_rqst *, __be32 *,
struct nfsd3_attrstat *);
int nfs3svc_release_fhandle2(struct svc_rqst *, __be32 *,
struct nfsd3_fhandle_pair *);
-int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
- int namlen, loff_t offset, ino_t ino,
+int nfs3svc_encode_entry(void *, const char *name,
+ int namlen, loff_t offset, u64 ino,
unsigned int);
-int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
- int namlen, loff_t offset, ino_t ino,
+int nfs3svc_encode_entry_plus(void *, const char *name,
+ int namlen, loff_t offset, u64 ino,
unsigned int);
/* Helper functions for NFSv3 ACL code */
__be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p,
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 45ca01b5f84..09799bcee0a 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -44,6 +44,12 @@
#define NFSD4_MAX_TAGLEN 128
#define XDR_LEN(n) (((n) + 3) & ~3)
+struct nfsd4_compound_state {
+ struct svc_fh current_fh;
+ struct svc_fh save_fh;
+ struct nfs4_stateowner *replay_owner;
+};
+
struct nfsd4_change_info {
u32 atomic;
u32 before_ctime_sec;
@@ -430,35 +436,39 @@ __be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
struct dentry *dentry, __be32 *buffer, int *countp,
u32 *bmval, struct svc_rqst *);
extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_setclientid *setclid);
extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_setclientid_confirm *setclientid_confirm);
extern __be32 nfsd4_process_open1(struct nfsd4_open *open);
extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open *open);
extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
- struct nfs4_stateowner **);
-extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_close *close,
- struct nfs4_stateowner **replay_owner);
+ struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
+extern __be32 nfsd4_close(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
+ struct nfsd4_close *close);
extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
- struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_lock *lock,
- struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+ struct nfsd4_compound_state *,
+ struct nfsd4_open_downgrade *od);
+extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
+ struct nfsd4_lock *lock);
+extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_lockt *lockt);
-extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_locku *locku,
- struct nfs4_stateowner **replay_owner);
+extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
+ struct nfsd4_locku *locku);
extern __be32
nfsd4_release_lockowner(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *,
struct nfsd4_release_lockowner *rlockowner);
extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_delegreturn *dr);
+ struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
+extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
+ struct nfsd4_compound_state *, clientid_t *clid);
#endif
/*
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 971d1c6dfc4..0b9f0dc30d6 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -4,9 +4,10 @@
#include <linux/spinlock.h>
#include <linux/sched.h>
-struct namespace;
+struct mnt_namespace;
struct uts_namespace;
struct ipc_namespace;
+struct pid_namespace;
/*
* A structure to contain pointers to all per-process
@@ -25,7 +26,8 @@ struct nsproxy {
spinlock_t nslock;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
- struct namespace *namespace;
+ struct mnt_namespace *mnt_ns;
+ struct pid_namespace *pid_ns;
};
extern struct nsproxy init_nsproxy;
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 4830a3bedfb..350878a2d84 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -253,15 +253,11 @@ static inline void SetPageUptodate(struct page *page)
struct page; /* forward declaration */
-int test_clear_page_dirty(struct page *page);
+extern void cancel_dirty_page(struct page *page, unsigned int account_size);
+
int test_clear_page_writeback(struct page *page);
int test_set_page_writeback(struct page *page);
-static inline void clear_page_dirty(struct page *page)
-{
- test_clear_page_dirty(page);
-}
-
static inline void set_page_writeback(struct page *page)
{
test_set_page_writeback(page);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 01c707261f9..f3c617eabd8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -20,9 +20,6 @@
/* Include the pci register defines */
#include <linux/pci_regs.h>
-/* Include the ID list */
-#include <linux/pci_ids.h>
-
/*
* The PCI interface treats multi-function devices as independent
* devices. The slot/function address of each device is encoded
@@ -54,6 +51,9 @@
#include <asm/atomic.h>
#include <linux/device.h>
+/* Include the ID list */
+#include <linux/pci_ids.h>
+
/* File state for mmap()s on /proc/bus/pci/X/Y */
enum pci_mmap_state {
pci_mmap_io,
@@ -396,6 +396,21 @@ struct pci_driver {
*/
#define pci_module_init pci_register_driver
+/**
+ * PCI_VDEVICE - macro used to describe a specific pci device in short form
+ * @vend: the vendor name
+ * @dev: the 16 bit PCI Device ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific PCI device. The subvendor, and subdevice fields will be set
+ * to PCI_ANY_ID. The macro allows the next field to follow as the device
+ * private data.
+ */
+
+#define PCI_VDEVICE(vendor, device) \
+ PCI_VENDOR_ID_##vendor, (device), \
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0
+
/* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI
@@ -454,6 +469,8 @@ struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
int pci_find_capability (struct pci_dev *dev, int cap);
int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
int pci_find_ext_capability (struct pci_dev *dev, int cap);
+int pci_find_ht_capability (struct pci_dev *dev, int ht_cap);
+int pci_find_next_ht_capability (struct pci_dev *dev, int pos, int ht_cap);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
@@ -468,6 +485,7 @@ struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
int pci_dev_present(const struct pci_device_id *ids);
+const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
@@ -681,6 +699,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *
{ return NULL; }
#define pci_dev_present(ids) (0)
+#define pci_find_present(ids) (NULL)
#define pci_dev_put(dev) do { } while (0)
static inline void pci_set_master(struct pci_dev *dev) { }
@@ -783,6 +802,7 @@ enum pci_fixup_pass {
pci_fixup_header, /* After reading configuration header */
pci_fixup_final, /* Final phase of device fixups */
pci_fixup_enable, /* pci_enable_device() time */
+ pci_fixup_resume, /* pci_enable_device() time */
};
/* Anonymous variables would be nice... */
@@ -801,6 +821,9 @@ enum pci_fixup_pass {
#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \
vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook) \
+ DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume, \
+ resume##vendor##device##hook, vendor, device, hook)
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 4d972bbef31..3d1d21035de 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -104,6 +104,10 @@
#define PCI_CLASS_SERIAL_FIBER 0x0c04
#define PCI_CLASS_SERIAL_SMBUS 0x0c05
+#define PCI_BASE_CLASS_WIRELESS 0x0d
+#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10
+#define PCI_CLASS_WIRELESS_WHCI 0x0d1010
+
#define PCI_BASE_CLASS_INTELLIGENT 0x0e
#define PCI_CLASS_INTELLIGENT_I2O 0x0e00
@@ -1273,12 +1277,13 @@
#define PCI_DEVICE_ID_VIA_3296_0 0x0296
#define PCI_DEVICE_ID_VIA_8363_0 0x0305
#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314
+#define PCI_DEVICE_ID_VIA_P4M890 0x0327
+#define PCI_DEVICE_ID_VIA_VT3336 0x0336
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
#define PCI_DEVICE_ID_VIA_82C561 0x0561
#define PCI_DEVICE_ID_VIA_82C586_1 0x0571
#define PCI_DEVICE_ID_VIA_82C576 0x0576
-#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x0581
#define PCI_DEVICE_ID_VIA_82C586_0 0x0586
#define PCI_DEVICE_ID_VIA_82C596 0x0596
#define PCI_DEVICE_ID_VIA_82C597_0 0x0597
@@ -1321,6 +1326,8 @@
#define PCI_DEVICE_ID_VIA_8237 0x3227
#define PCI_DEVICE_ID_VIA_8251 0x3287
#define PCI_DEVICE_ID_VIA_8237A 0x3337
+#define PCI_DEVICE_ID_VIA_8237S 0x3372
+#define PCI_DEVICE_ID_VIA_SATA_EIDE 0x5324
#define PCI_DEVICE_ID_VIA_8231 0x8231
#define PCI_DEVICE_ID_VIA_8231_4 0x8235
#define PCI_DEVICE_ID_VIA_8365_1 0x8305
@@ -1785,14 +1792,17 @@
#define PCI_DEVICE_ID_MOXA_C104 0x1040
#define PCI_DEVICE_ID_MOXA_CP104U 0x1041
#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042
+#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043
#define PCI_DEVICE_ID_MOXA_CT114 0x1140
#define PCI_DEVICE_ID_MOXA_CP114 0x1141
#define PCI_DEVICE_ID_MOXA_CP118U 0x1180
+#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181
#define PCI_DEVICE_ID_MOXA_CP132 0x1320
#define PCI_DEVICE_ID_MOXA_CP132U 0x1321
#define PCI_DEVICE_ID_MOXA_CP134U 0x1340
#define PCI_DEVICE_ID_MOXA_C168 0x1680
#define PCI_DEVICE_ID_MOXA_CP168U 0x1681
+#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682
#define PCI_VENDOR_ID_CCD 0x1397
#define PCI_DEVICE_ID_CCD_2BD0 0x2bd0
@@ -2064,6 +2074,10 @@
#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366
#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368
+#define PCI_VENDOR_ID_KORENIX 0x1982
+#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600
+#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff
+
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 064b1dc71c2..7a6d34ee5ab 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -475,15 +475,32 @@
#define PCI_PWR_CAP 12 /* Capability */
#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
-/* Hypertransport sub capability types */
+/*
+ * Hypertransport sub capability types
+ *
+ * Unfortunately there are both 3 bit and 5 bit capability types defined
+ * in the HT spec, catering for that is a little messy. You probably don't
+ * want to use these directly, just use pci_find_ht_capability() and it
+ * will do the right thing for you.
+ */
+#define HT_3BIT_CAP_MASK 0xE0
#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */
#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */
+
+#define HT_5BIT_CAP_MASK 0xF8
#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */
#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */
#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */
#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */
#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */
#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */
+#define HT_MSI_FLAGS 0x02 /* Offset to flags */
+#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */
+#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */
+#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */
+#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */
+#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */
+#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */
#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */
#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */
#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 2c0007d1721..4dec047b183 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -35,8 +35,9 @@ enum pid_type
*
* Holding a reference to struct pid solves both of these problems.
* It is small so holding a reference does not consume a lot of
- * resources, and since a new struct pid is allocated when the numeric
- * pid value is reused we don't mistakenly refer to new processes.
+ * resources, and since a new struct pid is allocated when the numeric pid
+ * value is reused (when pids wrap around) we don't mistakenly refer to new
+ * processes.
*/
struct pid
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
new file mode 100644
index 00000000000..2833806d42c
--- /dev/null
+++ b/include/linux/pid_namespace.h
@@ -0,0 +1,45 @@
+#ifndef _LINUX_PID_NS_H
+#define _LINUX_PID_NS_H
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <linux/pid.h>
+#include <linux/nsproxy.h>
+#include <linux/kref.h>
+
+struct pidmap {
+ atomic_t nr_free;
+ void *page;
+};
+
+#define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
+
+struct pid_namespace {
+ struct kref kref;
+ struct pidmap pidmap[PIDMAP_ENTRIES];
+ int last_pid;
+ struct task_struct *child_reaper;
+};
+
+extern struct pid_namespace init_pid_ns;
+
+static inline void get_pid_ns(struct pid_namespace *ns)
+{
+ kref_get(&ns->kref);
+}
+
+extern int copy_pid_ns(int flags, struct task_struct *tsk);
+extern void free_pid_ns(struct kref *kref);
+
+static inline void put_pid_ns(struct pid_namespace *ns)
+{
+ kref_put(&ns->kref, free_pid_ns);
+}
+
+static inline struct task_struct *child_reaper(struct task_struct *tsk)
+{
+ return init_pid_ns.child_reaper;
+}
+
+#endif /* _LINUX_PID_NS_H */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index ea4f7cd7bfd..2e19478e9e8 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -12,7 +12,7 @@
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
- struct pipe_buf_operations *ops;
+ const struct pipe_buf_operations *ops;
unsigned int flags;
};
@@ -41,9 +41,7 @@ struct pipe_buf_operations {
struct pipe_inode_info {
wait_queue_head_t wait;
unsigned int nrbufs, curbuf;
- struct pipe_buffer bufs[PIPE_BUFFERS];
struct page *tmp_page;
- unsigned int start;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
@@ -52,6 +50,7 @@ struct pipe_inode_info {
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct inode *inode;
+ struct pipe_buffer bufs[PIPE_BUFFERS];
};
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 8a94c717c26..5ea4f05683f 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -111,6 +111,13 @@ struct pkt_ctrl_command {
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+/* default bio write queue congestion marks */
+#define PKT_WRITE_CONGESTION_ON 10000
+#define PKT_WRITE_CONGESTION_OFF 9000
+
struct packet_settings
{
@@ -241,6 +248,14 @@ struct packet_stacked_data
};
#define PSD_POOL_SIZE 64
+struct pktcdvd_kobj
+{
+ struct kobject kobj;
+ struct pktcdvd_device *pd;
+};
+#define to_pktcdvdkobj(_k) \
+ ((struct pktcdvd_kobj*)container_of(_k,struct pktcdvd_kobj,kobj))
+
struct pktcdvd_device
{
struct block_device *bdev; /* dev attached */
@@ -271,6 +286,16 @@ struct pktcdvd_device
struct packet_iosched iosched;
struct gendisk *disk;
+
+ int write_congestion_off;
+ int write_congestion_on;
+
+ struct class_device *clsdev; /* sysfs pktcdvd[0-7] class dev */
+ struct pktcdvd_kobj *kobj_stat; /* sysfs pktcdvd[0-7]/stat/ */
+ struct pktcdvd_kobj *kobj_wqueue; /* sysfs pktcdvd[0-7]/write_queue/ */
+
+ struct dentry *dfs_d_root; /* debugfs: devname directory */
+ struct dentry *dfs_f_info; /* debugfs: info file */
};
#endif /* __KERNEL__ */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 20f47b81d3f..8bbd459eafd 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -39,7 +39,7 @@ extern struct platform_device *platform_device_register_simple(char *, unsigned
extern struct platform_device *platform_device_alloc(const char *name, unsigned int id);
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
-extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
+extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size);
extern int platform_device_add(struct platform_device *pdev);
extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 5670b340c4e..eec48f5f934 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -15,6 +15,7 @@ extern int prof_on __read_mostly;
#define CPU_PROFILING 1
#define SCHED_PROFILING 2
#define SLEEP_PROFILING 3
+#define KVM_PROFILING 4
struct proc_dir_entry;
struct pt_regs;
diff --git a/include/linux/pspace.h b/include/linux/pspace.h
deleted file mode 100644
index 91d48b8b2d9..00000000000
--- a/include/linux/pspace.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _LINUX_PSPACE_H
-#define _LINUX_PSPACE_H
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/threads.h>
-#include <linux/pid.h>
-
-struct pidmap {
- atomic_t nr_free;
- void *page;
-};
-
-#define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
-
-struct pspace {
- struct pidmap pidmap[PIDMAP_ENTRIES];
- int last_pid;
-};
-
-extern struct pspace init_pspace;
-
-#endif /* _LINUX_PSPACE_H */
diff --git a/include/linux/qic117.h b/include/linux/qic117.h
deleted file mode 100644
index 07b537e5d35..00000000000
--- a/include/linux/qic117.h
+++ /dev/null
@@ -1,290 +0,0 @@
-#ifndef _QIC117_H
-#define _QIC117_H
-
-/*
- * Copyright (C) 1993-1996 Bas Laarhoven,
- * (C) 1997 Claus-Justus Heine.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- *
- * $Source: /homes/cvs/ftape-stacked/include/linux/qic117.h,v $
- * $Revision: 1.2 $
- * $Date: 1997/10/05 19:19:32 $
- *
- * This file contains QIC-117 spec. related definitions for the
- * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
- *
- * These data were taken from the Quarter-Inch Cartridge
- * Drive Standards, Inc. document titled:
- * `Common Command Set Interface Specification for Flexible
- * Disk Controller Based Minicartridge Tape Drives'
- * document QIC-117 Revision J, 28 Aug 96.
- * For more information, contact:
- * Quarter-Inch Cartridge Drive Standards, Inc.
- * 311 East Carrillo Street
- * Santa Barbara, California 93101
- * Telephone (805) 963-3853
- * Fax (805) 962-1541
- * WWW http://www.qic.org
- *
- * Current QIC standard revisions (of interest) are:
- * QIC-40-MC, Rev. M, 2 Sep 92.
- * QIC-80-MC, Rev. N, 20 Mar 96.
- * QIC-80-MC, Rev. K, 15 Dec 94.
- * QIC-113, Rev. G, 15 Jun 95.
- * QIC-117, Rev. J, 28 Aug 96.
- * QIC-122, Rev. B, 6 Mar 91.
- * QIC-130, Rev. C, 2 Sep 92.
- * QIC-3010-MC, Rev. F, 14 Jun 95.
- * QIC-3020-MC, Rev. G, 31 Aug 95.
- * QIC-CRF3, Rev. B, 15 Jun 95.
- * */
-
-/*
- * QIC-117 common command set rev. J.
- * These commands are sent to the tape unit
- * as number of pulses over the step line.
- */
-
-typedef enum {
- QIC_NO_COMMAND = 0,
- QIC_RESET = 1,
- QIC_REPORT_NEXT_BIT = 2,
- QIC_PAUSE = 3,
- QIC_MICRO_STEP_PAUSE = 4,
- QIC_ALTERNATE_TIMEOUT = 5,
- QIC_REPORT_DRIVE_STATUS = 6,
- QIC_REPORT_ERROR_CODE = 7,
- QIC_REPORT_DRIVE_CONFIGURATION = 8,
- QIC_REPORT_ROM_VERSION = 9,
- QIC_LOGICAL_FORWARD = 10,
- QIC_PHYSICAL_REVERSE = 11,
- QIC_PHYSICAL_FORWARD = 12,
- QIC_SEEK_HEAD_TO_TRACK = 13,
- QIC_SEEK_LOAD_POINT = 14,
- QIC_ENTER_FORMAT_MODE = 15,
- QIC_WRITE_REFERENCE_BURST = 16,
- QIC_ENTER_VERIFY_MODE = 17,
- QIC_STOP_TAPE = 18,
-/* commands 19-20: reserved */
- QIC_MICRO_STEP_HEAD_UP = 21,
- QIC_MICRO_STEP_HEAD_DOWN = 22,
- QIC_SOFT_SELECT = 23,
- QIC_SOFT_DESELECT = 24,
- QIC_SKIP_REVERSE = 25,
- QIC_SKIP_FORWARD = 26,
- QIC_SELECT_RATE = 27,
-/* command 27, in ccs2: Select Rate or Format */
- QIC_ENTER_DIAGNOSTIC_1 = 28,
- QIC_ENTER_DIAGNOSTIC_2 = 29,
- QIC_ENTER_PRIMARY_MODE = 30,
-/* command 31: vendor unique */
- QIC_REPORT_VENDOR_ID = 32,
- QIC_REPORT_TAPE_STATUS = 33,
- QIC_SKIP_EXTENDED_REVERSE = 34,
- QIC_SKIP_EXTENDED_FORWARD = 35,
- QIC_CALIBRATE_TAPE_LENGTH = 36,
- QIC_REPORT_FORMAT_SEGMENTS = 37,
- QIC_SET_FORMAT_SEGMENTS = 38,
-/* commands 39-45: reserved */
- QIC_PHANTOM_SELECT = 46,
- QIC_PHANTOM_DESELECT = 47
-} qic117_cmd_t;
-
-typedef enum {
- discretional = 0, required, ccs1, ccs2
-} qic_compatibility;
-
-typedef enum {
- unused, mode, motion, report
-} command_types;
-
-struct qic117_command_table {
- char *name;
- __u8 mask;
- __u8 state;
- __u8 cmd_type;
- __u8 non_intr;
- __u8 level;
-};
-
-#define QIC117_COMMANDS {\
-/* command mask state cmd_type */\
-/* | name | | | non_intr */\
-/* | | | | | | level */\
-/* 0*/ {NULL, 0x00, 0x00, mode, 0, discretional},\
-/* 1*/ {"soft reset", 0x00, 0x00, motion, 1, required},\
-/* 2*/ {"report next bit", 0x00, 0x00, report, 0, required},\
-/* 3*/ {"pause", 0x36, 0x24, motion, 1, required},\
-/* 4*/ {"micro step pause", 0x36, 0x24, motion, 1, required},\
-/* 5*/ {"alternate command timeout", 0x00, 0x00, mode, 0, required},\
-/* 6*/ {"report drive status", 0x00, 0x00, report, 0, required},\
-/* 7*/ {"report error code", 0x01, 0x01, report, 0, required},\
-/* 8*/ {"report drive configuration",0x00, 0x00, report, 0, required},\
-/* 9*/ {"report rom version", 0x00, 0x00, report, 0, required},\
-/*10*/ {"logical forward", 0x37, 0x25, motion, 0, required},\
-/*11*/ {"physical reverse", 0x17, 0x05, motion, 0, required},\
-/*12*/ {"physical forward", 0x17, 0x05, motion, 0, required},\
-/*13*/ {"seek head to track", 0x37, 0x25, motion, 0, required},\
-/*14*/ {"seek load point", 0x17, 0x05, motion, 1, required},\
-/*15*/ {"enter format mode", 0x1f, 0x05, mode, 0, required},\
-/*16*/ {"write reference burst", 0x1f, 0x05, motion, 1, required},\
-/*17*/ {"enter verify mode", 0x37, 0x25, mode, 0, required},\
-/*18*/ {"stop tape", 0x00, 0x00, motion, 1, required},\
-/*19*/ {"reserved (19)", 0x00, 0x00, unused, 0, discretional},\
-/*20*/ {"reserved (20)", 0x00, 0x00, unused, 0, discretional},\
-/*21*/ {"micro step head up", 0x02, 0x00, motion, 0, required},\
-/*22*/ {"micro step head down", 0x02, 0x00, motion, 0, required},\
-/*23*/ {"soft select", 0x00, 0x00, mode, 0, discretional},\
-/*24*/ {"soft deselect", 0x00, 0x00, mode, 0, discretional},\
-/*25*/ {"skip segments reverse", 0x36, 0x24, motion, 1, required},\
-/*26*/ {"skip segments forward", 0x36, 0x24, motion, 1, required},\
-/*27*/ {"select rate or format", 0x03, 0x01, mode, 0, required /* [ccs2] */},\
-/*28*/ {"enter diag mode 1", 0x00, 0x00, mode, 0, discretional},\
-/*29*/ {"enter diag mode 2", 0x00, 0x00, mode, 0, discretional},\
-/*30*/ {"enter primary mode", 0x00, 0x00, mode, 0, required},\
-/*31*/ {"vendor unique (31)", 0x00, 0x00, unused, 0, discretional},\
-/*32*/ {"report vendor id", 0x00, 0x00, report, 0, required},\
-/*33*/ {"report tape status", 0x04, 0x04, report, 0, ccs1},\
-/*34*/ {"skip extended reverse", 0x36, 0x24, motion, 1, ccs1},\
-/*35*/ {"skip extended forward", 0x36, 0x24, motion, 1, ccs1},\
-/*36*/ {"calibrate tape length", 0x17, 0x05, motion, 1, ccs2},\
-/*37*/ {"report format segments", 0x17, 0x05, report, 0, ccs2},\
-/*38*/ {"set format segments", 0x17, 0x05, mode, 0, ccs2},\
-/*39*/ {"reserved (39)", 0x00, 0x00, unused, 0, discretional},\
-/*40*/ {"vendor unique (40)", 0x00, 0x00, unused, 0, discretional},\
-/*41*/ {"vendor unique (41)", 0x00, 0x00, unused, 0, discretional},\
-/*42*/ {"vendor unique (42)", 0x00, 0x00, unused, 0, discretional},\
-/*43*/ {"vendor unique (43)", 0x00, 0x00, unused, 0, discretional},\
-/*44*/ {"vendor unique (44)", 0x00, 0x00, unused, 0, discretional},\
-/*45*/ {"vendor unique (45)", 0x00, 0x00, unused, 0, discretional},\
-/*46*/ {"phantom select", 0x00, 0x00, mode, 0, discretional},\
-/*47*/ {"phantom deselect", 0x00, 0x00, mode, 0, discretional},\
-}
-
-/*
- * Status bits returned by QIC_REPORT_DRIVE_STATUS
- */
-
-#define QIC_STATUS_READY 0x01 /* Drive is ready or idle. */
-#define QIC_STATUS_ERROR 0x02 /* Error detected, must read
- error code to clear this */
-#define QIC_STATUS_CARTRIDGE_PRESENT 0x04 /* Tape is present */
-#define QIC_STATUS_WRITE_PROTECT 0x08 /* Tape is write protected */
-#define QIC_STATUS_NEW_CARTRIDGE 0x10 /* New cartridge inserted, must
- read error status to clear. */
-#define QIC_STATUS_REFERENCED 0x20 /* Cartridge appears to have been
- formatted. */
-#define QIC_STATUS_AT_BOT 0x40 /* Cartridge is at physical
- beginning of tape. */
-#define QIC_STATUS_AT_EOT 0x80 /* Cartridge is at physical end
- of tape. */
-/*
- * Status bits returned by QIC_REPORT_DRIVE_CONFIGURATION
- */
-
-#define QIC_CONFIG_RATE_MASK 0x18
-#define QIC_CONFIG_RATE_SHIFT 3
-#define QIC_CONFIG_RATE_250 0
-#define QIC_CONFIG_RATE_500 2
-#define QIC_CONFIG_RATE_1000 3
-#define QIC_CONFIG_RATE_2000 1
-#define QIC_CONFIG_RATE_4000 0 /* since QIC-117 Rev. J */
-
-#define QIC_CONFIG_LONG 0x40 /* Extra Length Tape Detected */
-#define QIC_CONFIG_80 0x80 /* QIC-80 detected. */
-
-/*
- * Status bits returned by QIC_REPORT_TAPE_STATUS
- */
-
-#define QIC_TAPE_STD_MASK 0x0f
-#define QIC_TAPE_QIC40 0x01
-#define QIC_TAPE_QIC80 0x02
-#define QIC_TAPE_QIC3020 0x03
-#define QIC_TAPE_QIC3010 0x04
-
-#define QIC_TAPE_LEN_MASK 0x70
-#define QIC_TAPE_205FT 0x10
-#define QIC_TAPE_307FT 0x20
-#define QIC_TAPE_VARIABLE 0x30
-#define QIC_TAPE_1100FT 0x40
-#define QIC_TAPE_FLEX 0x60
-
-#define QIC_TAPE_WIDE 0x80
-
-/* Define a value (in feet) slightly higher than
- * the possible maximum tape length.
- */
-#define QIC_TOP_TAPE_LEN 1500
-
-/*
- * Errors: List of error codes, and their severity.
- */
-
-typedef struct {
- char *message; /* Text describing the error. */
- unsigned int fatal:1; /* Non-zero if the error is fatal. */
-} ftape_error;
-
-#define QIC117_ERRORS {\
- /* 0*/ { "No error", 0, },\
- /* 1*/ { "Command Received while Drive Not Ready", 0, },\
- /* 2*/ { "Cartridge Not Present or Removed", 1, },\
- /* 3*/ { "Motor Speed Error (not within 1%)", 1, },\
- /* 4*/ { "Motor Speed Fault (jammed, or gross speed error", 1, },\
- /* 5*/ { "Cartridge Write Protected", 1, },\
- /* 6*/ { "Undefined or Reserved Command Code", 1, },\
- /* 7*/ { "Illegal Track Address Specified for Seek", 1, },\
- /* 8*/ { "Illegal Command in Report Subcontext", 0, },\
- /* 9*/ { "Illegal Entry into a Diagnostic Mode", 1, },\
- /*10*/ { "Broken Tape Detected (based on hole sensor)", 1, },\
- /*11*/ { "Warning--Read Gain Setting Error", 1, },\
- /*12*/ { "Command Received While Error Status Pending (obs)", 1, },\
- /*13*/ { "Command Received While New Cartridge Pending", 1, },\
- /*14*/ { "Command Illegal or Undefined in Primary Mode", 1, },\
- /*15*/ { "Command Illegal or Undefined in Format Mode", 1, },\
- /*16*/ { "Command Illegal or Undefined in Verify Mode", 1, },\
- /*17*/ { "Logical Forward Not at Logical BOT or no Format Segments in Format Mode", 1, },\
- /*18*/ { "Logical EOT Before All Segments generated", 1, },\
- /*19*/ { "Command Illegal When Cartridge Not Referenced", 1, },\
- /*20*/ { "Self-Diagnostic Failed (cannot be cleared)", 1, },\
- /*21*/ { "Warning EEPROM Not Initialized, Defaults Set", 1, },\
- /*22*/ { "EEPROM Corrupted or Hardware Failure", 1, },\
- /*23*/ { "Motion Time-out Error", 1, },\
- /*24*/ { "Data Segment Too Long -- Logical Forward or Pause", 1, },\
- /*25*/ { "Transmit Overrun (obs)", 1, },\
- /*26*/ { "Power On Reset Occurred", 0, },\
- /*27*/ { "Software Reset Occurred", 0, },\
- /*28*/ { "Diagnostic Mode 1 Error", 1, },\
- /*29*/ { "Diagnostic Mode 2 Error", 1, },\
- /*30*/ { "Command Received During Non-Interruptible Process", 1, },\
- /*31*/ { "Rate or Format Selection Error", 1, },\
- /*32*/ { "Illegal Command While in High Speed Mode", 1, },\
- /*33*/ { "Illegal Seek Segment Value", 1, },\
- /*34*/ { "Invalid Media", 1, },\
- /*35*/ { "Head Positioning Failure", 1, },\
- /*36*/ { "Write Reference Burst Failure", 1, },\
- /*37*/ { "Prom Code Missing", 1, },\
- /*38*/ { "Invalid Format", 1, },\
- /*39*/ { "EOT/BOT System Failure", 1, },\
- /*40*/ { "Prom A Checksum Error", 1, },\
- /*41*/ { "Drive Wakeup Reset Occurred", 1, },\
- /*42*/ { "Prom B Checksum Error", 1, },\
- /*43*/ { "Illegal Entry into Format Mode", 1, },\
-}
-
-#endif /* _QIC117_H */
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index 866a1e2b0ce..fbaeda79b2e 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -94,7 +94,7 @@ extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
struct page *page, int rw);
extern void md_do_sync(mddev_t *mddev);
extern void md_new_event(mddev_t *mddev);
-
+extern void md_allow_write(mddev_t *mddev);
#endif /* CONFIG_MD */
#endif
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index 03636d7918f..d8286db60b9 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -227,7 +227,10 @@ struct raid5_private_data {
struct list_head handle_list; /* stripes needing handling */
struct list_head delayed_list; /* stripes that have plugged requests */
struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */
+ struct bio *retry_read_aligned; /* currently retrying aligned bios */
+ struct bio *retry_read_aligned_list; /* aligned bios retry list */
atomic_t preread_active_stripes; /* stripes with scheduled io */
+ atomic_t active_aligned_reads;
atomic_t reshape_stripes; /* stripes with pending writes for reshape */
/* unfortunately we need two cache names as we temporarily have
diff --git a/include/linux/reciprocal_div.h b/include/linux/reciprocal_div.h
new file mode 100644
index 00000000000..f9c90b33285
--- /dev/null
+++ b/include/linux/reciprocal_div.h
@@ -0,0 +1,32 @@
+#ifndef _LINUX_RECIPROCAL_DIV_H
+#define _LINUX_RECIPROCAL_DIV_H
+
+#include <linux/types.h>
+
+/*
+ * This file describes reciprocical division.
+ *
+ * This optimizes the (A/B) problem, when A and B are two u32
+ * and B is a known value (but not known at compile time)
+ *
+ * The math principle used is :
+ * Let RECIPROCAL_VALUE(B) be (((1LL << 32) + (B - 1))/ B)
+ * Then A / B = (u32)(((u64)(A) * (R)) >> 32)
+ *
+ * This replaces a divide by a multiply (and a shift), and
+ * is generally less expensive in CPU cycles.
+ */
+
+/*
+ * Computes the reciprocal value (R) for the value B of the divisor.
+ * Should not be called before each reciprocal_divide(),
+ * or else the performance is slower than a normal divide.
+ */
+extern u32 reciprocal_value(u32 B);
+
+
+static inline u32 reciprocal_divide(u32 A, u32 R)
+{
+ return (u32)(((u64)A * R) >> 32);
+}
+#endif
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index d0e4dce33ad..c3fc6caaad3 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1159,7 +1159,7 @@ znodes are the way! */
#define PATH_READA 0x1 /* do read ahead */
#define PATH_READA_BACK 0x2 /* read backwards */
-struct path {
+struct treepath {
int path_length; /* Length of the array above. */
int reada;
struct path_element path_elements[EXTENDED_MAX_HEIGHT]; /* Array of the path elements. */
@@ -1169,7 +1169,7 @@ struct path {
#define pos_in_item(path) ((path)->pos_in_item)
#define INITIALIZE_PATH(var) \
-struct path var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
+struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
/* Get path element by path and path position. */
#define PATH_OFFSET_PELEMENT(p_s_path,n_offset) ((p_s_path)->path_elements +(n_offset))
@@ -1327,7 +1327,7 @@ struct tree_balance {
int need_balance_dirty;
struct super_block *tb_sb;
struct reiserfs_transaction_handle *transaction_handle;
- struct path *tb_path;
+ struct treepath *tb_path;
struct buffer_head *L[MAX_HEIGHT]; /* array of left neighbors of nodes in the path */
struct buffer_head *R[MAX_HEIGHT]; /* array of right neighbors of nodes in the path */
struct buffer_head *FL[MAX_HEIGHT]; /* array of fathers of the left neighbors */
@@ -1793,41 +1793,41 @@ static inline void copy_key(struct reiserfs_key *to,
memcpy(to, from, KEY_SIZE);
}
-int comp_items(const struct item_head *stored_ih, const struct path *p_s_path);
-const struct reiserfs_key *get_rkey(const struct path *p_s_chk_path,
+int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path);
+const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
const struct super_block *p_s_sb);
int search_by_key(struct super_block *, const struct cpu_key *,
- struct path *, int);
+ struct treepath *, int);
#define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL)
int search_for_position_by_key(struct super_block *p_s_sb,
const struct cpu_key *p_s_cpu_key,
- struct path *p_s_search_path);
+ struct treepath *p_s_search_path);
extern void decrement_bcount(struct buffer_head *p_s_bh);
-void decrement_counters_in_path(struct path *p_s_search_path);
-void pathrelse(struct path *p_s_search_path);
-int reiserfs_check_path(struct path *p);
-void pathrelse_and_restore(struct super_block *s, struct path *p_s_search_path);
+void decrement_counters_in_path(struct treepath *p_s_search_path);
+void pathrelse(struct treepath *p_s_search_path);
+int reiserfs_check_path(struct treepath *p);
+void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path);
int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
- struct path *path,
+ struct treepath *path,
const struct cpu_key *key,
struct item_head *ih,
struct inode *inode, const char *body);
int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th,
- struct path *path,
+ struct treepath *path,
const struct cpu_key *key,
struct inode *inode,
const char *body, int paste_size);
int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
- struct path *path,
+ struct treepath *path,
struct cpu_key *key,
struct inode *inode,
struct page *page, loff_t new_file_size);
int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
- struct path *path,
+ struct treepath *path,
const struct cpu_key *key,
struct inode *inode, struct buffer_head *p_s_un_bh);
@@ -1858,7 +1858,7 @@ void padd_item(char *item, int total_length, int length);
#define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */
int restart_transaction(struct reiserfs_transaction_handle *th,
- struct inode *inode, struct path *path);
+ struct inode *inode, struct treepath *path);
void reiserfs_read_locked_inode(struct inode *inode,
struct reiserfs_iget_args *args);
int reiserfs_find_actor(struct inode *inode, void *p);
@@ -1905,7 +1905,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr);
/* namei.c */
void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
- struct path *path, struct reiserfs_dir_entry *de);
+ struct treepath *path, struct reiserfs_dir_entry *de);
struct dentry *reiserfs_get_parent(struct dentry *);
/* procfs.c */
@@ -1956,9 +1956,9 @@ extern const struct file_operations reiserfs_dir_operations;
/* tail_conversion.c */
int direct2indirect(struct reiserfs_transaction_handle *, struct inode *,
- struct path *, struct buffer_head *, loff_t);
+ struct treepath *, struct buffer_head *, loff_t);
int indirect2direct(struct reiserfs_transaction_handle *, struct inode *,
- struct page *, struct path *, const struct cpu_key *,
+ struct page *, struct treepath *, const struct cpu_key *,
loff_t, char *);
void reiserfs_unmap_buffer(struct buffer_head *);
@@ -2045,7 +2045,7 @@ struct __reiserfs_blocknr_hint {
struct inode *inode; /* inode passed to allocator, if we allocate unf. nodes */
long block; /* file offset, in blocks */
struct in_core_key key;
- struct path *path; /* search path, used by allocator to deternine search_start by
+ struct treepath *path; /* search path, used by allocator to deternine search_start by
* various ways */
struct reiserfs_transaction_handle *th; /* transaction handle is needed to log super blocks and
* bitmap blocks changes */
@@ -2101,7 +2101,7 @@ static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
*th, struct inode *inode,
b_blocknr_t * new_blocknrs,
- struct path *path, long block)
+ struct treepath *path, long block)
{
reiserfs_blocknr_hint_t hint = {
.th = th,
@@ -2118,7 +2118,7 @@ static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
*th, struct inode *inode,
b_blocknr_t * new_blocknrs,
- struct path *path, long block)
+ struct treepath *path, long block)
{
reiserfs_blocknr_hint_t hint = {
.th = th,
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index 5b3b297aa2c..ce3663fb010 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -25,6 +25,7 @@ typedef enum {
i_link_saved_truncate_mask = 0x0020,
i_has_xattr_dir = 0x0040,
i_data_log = 0x0080,
+ i_ever_mapped = 0x0100
} reiserfs_inode_flags;
struct reiserfs_inode_info {
@@ -52,6 +53,7 @@ struct reiserfs_inode_info {
** flushed */
unsigned long i_trans_id;
struct reiserfs_journal_list *i_jl;
+ struct mutex i_mmap;
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
struct posix_acl *i_acl_access;
struct posix_acl *i_acl_default;
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 36f850373d2..bdd277223af 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -72,7 +72,7 @@ void __anon_vma_link(struct vm_area_struct *);
void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
void page_add_file_rmap(struct page *);
-void page_remove_rmap(struct page *);
+void page_remove_rmap(struct page *, struct vm_area_struct *);
/**
* page_dup_rmap - duplicate pte mapping to a page
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 09ff4c3e271..5e22d4510d1 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -106,6 +106,7 @@ extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year
extern int rtc_valid_tm(struct rtc_time *tm);
extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
+extern void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm);
#include <linux/device.h>
#include <linux/seq_file.h>
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index b0090e9f788..382bb795116 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -16,7 +16,7 @@
#include <linux/plist.h>
#include <linux/spinlock_types.h>
-/*
+/**
* The rt_mutex structure
*
* @wait_lock: spinlock to protect the structure
@@ -71,7 +71,7 @@ struct hrtimer_sleeper;
#define DEFINE_RT_MUTEX(mutexname) \
struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)
-/***
+/**
* rt_mutex_is_locked - is the mutex locked
* @lock: the mutex to be queried
*
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 493297acdae..4a629ea70cc 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -3,6 +3,8 @@
#include <linux/netlink.h>
#include <linux/if_link.h>
+#include <linux/if_addr.h>
+#include <linux/neighbour.h>
/****
* Routing/neighbour discovery messages.
diff --git a/include/linux/sched.h b/include/linux/sched.h
index dede82c6344..44637353519 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -82,6 +82,7 @@ struct sched_param {
#include <linux/resource.h>
#include <linux/timer.h>
#include <linux/hrtimer.h>
+#include <linux/task_io_accounting.h>
#include <asm/processor.h>
@@ -436,7 +437,12 @@ struct signal_struct {
/* job control IDs */
pid_t pgrp;
pid_t tty_old_pgrp;
- pid_t session;
+
+ union {
+ pid_t session __deprecated;
+ pid_t __session;
+ };
+
/* boolean value for session group leader */
int leader;
@@ -642,6 +648,7 @@ enum idle_type
#define SD_SHARE_CPUPOWER 128 /* Domain members share cpu power */
#define SD_POWERSAVINGS_BALANCE 256 /* Balance for power savings */
#define SD_SHARE_PKG_RESOURCES 512 /* Domain members share cpu pkg resources */
+#define SD_SERIALIZE 1024 /* Only a single load balancing instance */
#define BALANCE_FOR_MC_POWER \
(sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
@@ -1008,6 +1015,7 @@ struct task_struct {
wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */
u64 rchar, wchar, syscr, syscw;
+ struct task_io_accounting ioac;
#if defined(CONFIG_TASK_XACCT)
u64 acct_rss_mem1; /* accumulated rss usage */
u64 acct_vm_mem1; /* accumulated virtual memory usage */
@@ -1040,6 +1048,9 @@ struct task_struct {
#ifdef CONFIG_TASK_DELAY_ACCT
struct task_delay_info *delays;
#endif
+#ifdef CONFIG_FAULT_INJECTION
+ int make_it_fail;
+#endif
};
static inline pid_t process_group(struct task_struct *tsk)
@@ -1047,6 +1058,21 @@ static inline pid_t process_group(struct task_struct *tsk)
return tsk->signal->pgrp;
}
+static inline pid_t signal_session(struct signal_struct *sig)
+{
+ return sig->__session;
+}
+
+static inline pid_t process_session(struct task_struct *tsk)
+{
+ return signal_session(tsk->signal);
+}
+
+static inline void set_signal_session(struct signal_struct *sig, pid_t session)
+{
+ sig->__session = session;
+}
+
static inline struct pid *task_pid(struct task_struct *task)
{
return task->pids[PIDTYPE_PID].pid;
@@ -1118,7 +1144,6 @@ static inline void put_task_struct(struct task_struct *t)
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_FLUSHER 0x00001000 /* responsible for disk writeback */
#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */
-#define PF_FREEZE 0x00004000 /* this task is being frozen for suspend now */
#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */
#define PF_FROZEN 0x00010000 /* frozen for system suspend */
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
@@ -1240,7 +1265,6 @@ extern struct mm_struct init_mm;
#define find_task_by_pid(nr) find_task_by_pid_type(PIDTYPE_PID, nr)
extern struct task_struct *find_task_by_pid_type(int type, int pid);
-extern void set_special_pids(pid_t session, pid_t pgrp);
extern void __set_special_pids(pid_t session, pid_t pgrp);
/* per-UID process charging. */
@@ -1381,7 +1405,6 @@ extern NORET_TYPE void do_group_exit(int);
extern void daemonize(const char *, ...);
extern int allow_signal(int);
extern int disallow_signal(int);
-extern struct task_struct *child_reaper;
extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *);
extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index 35108fe7a68..d4f86560bff 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -180,7 +180,7 @@ typedef enum {
SCTP_PARAM_ERR_CAUSE = __constant_htons(0xc003),
SCTP_PARAM_SET_PRIMARY = __constant_htons(0xc004),
SCTP_PARAM_SUCCESS_REPORT = __constant_htons(0xc005),
- SCTP_PARAM_ADAPTION_LAYER_IND = __constant_htons(0xc006),
+ SCTP_PARAM_ADAPTATION_LAYER_IND = __constant_htons(0xc006),
} sctp_param_t; /* enum */
@@ -281,11 +281,11 @@ typedef struct sctp_ecn_capable_param {
sctp_paramhdr_t param_hdr;
} __attribute__((packed)) sctp_ecn_capable_param_t;
-/* ADDIP Section 3.2.6 Adaption Layer Indication */
-typedef struct sctp_adaption_ind_param {
+/* ADDIP Section 3.2.6 Adaptation Layer Indication */
+typedef struct sctp_adaptation_ind_param {
struct sctp_paramhdr param_hdr;
- __be32 adaption_ind;
-} __attribute__((packed)) sctp_adaption_ind_param_t;
+ __be32 adaptation_ind;
+} __attribute__((packed)) sctp_adaptation_ind_param_t;
/* RFC 2960. Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
* The INIT ACK chunk is used to acknowledge the initiation of an SCTP
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 46000936f8f..6b0648cfdff 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -44,8 +44,11 @@ typedef struct {
#define SEQLOCK_UNLOCKED \
__SEQLOCK_UNLOCKED(old_style_seqlock_init)
-#define seqlock_init(x) \
- do { *(x) = (seqlock_t) __SEQLOCK_UNLOCKED(x); } while (0)
+#define seqlock_init(x) \
+ do { \
+ (x)->sequence = 0; \
+ spin_lock_init(&(x)->lock); \
+ } while (0)
#define DEFINE_SEQLOCK(x) \
seqlock_t x = __SEQLOCK_UNLOCKED(x)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 82767213664..cf23813cbec 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -166,8 +166,8 @@ struct uart_ops {
void (*break_ctl)(struct uart_port *, int ctl);
int (*startup)(struct uart_port *);
void (*shutdown)(struct uart_port *);
- void (*set_termios)(struct uart_port *, struct termios *new,
- struct termios *old);
+ void (*set_termios)(struct uart_port *, struct ktermios *new,
+ struct ktermios *old);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int oldstate);
int (*set_wake)(struct uart_port *, unsigned int state);
@@ -361,8 +361,8 @@ void uart_write_wakeup(struct uart_port *port);
*/
void uart_update_timeout(struct uart_port *port, unsigned int cflag,
unsigned int baud);
-unsigned int uart_get_baud_rate(struct uart_port *port, struct termios *termios,
- struct termios *old, unsigned int min,
+unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old, unsigned int min,
unsigned int max);
unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
diff --git a/include/linux/serio.h b/include/linux/serio.h
index b99c5ca9708..0f478a8791a 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -85,18 +85,8 @@ static inline void serio_register_port(struct serio *serio)
void serio_unregister_port(struct serio *serio);
void serio_unregister_child_port(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);
-}
+int 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)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 2271886744f..1ef822e31c7 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -1,7 +1,9 @@
/*
- * linux/include/linux/slab.h
- * Written by Mark Hemment, 1996.
- * (markhe@nextd.demon.co.uk)
+ * Written by Mark Hemment, 1996 (markhe@nextd.demon.co.uk).
+ *
+ * (C) SGI 2006, Christoph Lameter <clameter@sgi.com>
+ * Cleaned up and restructured to ease the addition of alternative
+ * implementations of SLAB allocators.
*/
#ifndef _LINUX_SLAB_H
@@ -10,64 +12,95 @@
#ifdef __KERNEL__
#include <linux/gfp.h>
-#include <linux/init.h>
#include <linux/types.h>
-#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
-#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
-#include <linux/compiler.h>
-/* kmem_cache_t exists for legacy reasons and is not used by code in mm */
typedef struct kmem_cache kmem_cache_t __deprecated;
-/* flags to pass to kmem_cache_create().
- * The first 3 are only valid when the allocator as been build
- * SLAB_DEBUG_SUPPORT.
+/*
+ * Flags to pass to kmem_cache_create().
+ * The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
*/
-#define SLAB_DEBUG_FREE 0x00000100UL /* Peform (expensive) checks on free */
-#define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */
-#define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */
-#define SLAB_POISON 0x00000800UL /* Poison objects */
-#define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */
-#define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */
-#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */
-#define SLAB_STORE_USER 0x00010000UL /* store the last owner for bug hunting */
-#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* track pages allocated to indicate
- what is reclaimable later*/
-#define SLAB_PANIC 0x00040000UL /* panic if kmem_cache_create() fails */
-#define SLAB_DESTROY_BY_RCU 0x00080000UL /* defer freeing pages to RCU */
+#define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */
+#define SLAB_DEBUG_INITIAL 0x00000200UL /* DEBUG: Call constructor (as verifier) */
+#define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
+#define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
+#define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
+#define SLAB_CACHE_DMA 0x00004000UL /* Use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* Force alignment even if debuggin is active */
+#define SLAB_STORE_USER 0x00010000UL /* DEBUG: Store the last owner for bug hunting */
+#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
+#define SLAB_PANIC 0x00040000UL /* Panic if kmem_cache_create() fails */
+#define SLAB_DESTROY_BY_RCU 0x00080000UL /* Defer freeing slabs to RCU */
#define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */
-/* flags passed to a constructor func */
-#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
-#define SLAB_CTOR_ATOMIC 0x002UL /* tell constructor it can't sleep */
-#define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */
+/* Flags passed to a constructor functions */
+#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* If not set, then deconstructor */
+#define SLAB_CTOR_ATOMIC 0x002UL /* Tell constructor it can't sleep */
+#define SLAB_CTOR_VERIFY 0x004UL /* Tell constructor it's a verify call */
-#ifndef CONFIG_SLOB
-
-/* prototypes */
-extern void __init kmem_cache_init(void);
+/*
+ * struct kmem_cache related prototypes
+ */
+void __init kmem_cache_init(void);
+extern int slab_is_available(void);
-extern struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
+struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
unsigned long,
void (*)(void *, struct kmem_cache *, unsigned long),
void (*)(void *, struct kmem_cache *, unsigned long));
-extern void kmem_cache_destroy(struct kmem_cache *);
-extern int kmem_cache_shrink(struct kmem_cache *);
-extern void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
-extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-extern void kmem_cache_free(struct kmem_cache *, void *);
-extern unsigned int kmem_cache_size(struct kmem_cache *);
-extern const char *kmem_cache_name(struct kmem_cache *);
+void kmem_cache_destroy(struct kmem_cache *);
+int kmem_cache_shrink(struct kmem_cache *);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
+void kmem_cache_free(struct kmem_cache *, void *);
+unsigned int kmem_cache_size(struct kmem_cache *);
+const char *kmem_cache_name(struct kmem_cache *);
+int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
+
+#ifdef CONFIG_NUMA
+extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+#else
+static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
+ gfp_t flags, int node)
+{
+ return kmem_cache_alloc(cachep, flags);
+}
+#endif
+
+/*
+ * Common kmalloc functions provided by all allocators
+ */
+void *__kmalloc(size_t, gfp_t);
+void *__kzalloc(size_t, gfp_t);
+void kfree(const void *);
+unsigned int ksize(const void *);
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+ if (n != 0 && size > ULONG_MAX / n)
+ return NULL;
+ return __kzalloc(n * size, flags);
+}
-/* Size description struct for general caches. */
-struct cache_sizes {
- size_t cs_size;
- struct kmem_cache *cs_cachep;
- struct kmem_cache *cs_dmacachep;
-};
-extern struct cache_sizes malloc_sizes[];
+/*
+ * Allocator specific definitions. These are mainly used to establish optimized
+ * ways to convert kmalloc() calls to kmem_cache_alloc() invocations by selecting
+ * the appropriate general cache at compile time.
+ */
-extern void *__kmalloc(size_t, gfp_t);
+#ifdef CONFIG_SLAB
+#include <linux/slab_def.h>
+#else
+/*
+ * Fallback definitions for an allocator not wanting to provide
+ * its own optimized kmalloc definitions (like SLOB).
+ */
/**
* kmalloc - allocate memory
@@ -116,46 +149,9 @@ extern void *__kmalloc(size_t, gfp_t);
*/
static inline void *kmalloc(size_t size, gfp_t flags)
{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kmalloc_that_much(void);
- __you_cannot_kmalloc_that_much();
- }
-found:
- return kmem_cache_alloc((flags & GFP_DMA) ?
- malloc_sizes[i].cs_dmacachep :
- malloc_sizes[i].cs_cachep, flags);
- }
return __kmalloc(size, flags);
}
-/*
- * kmalloc_track_caller is a special version of kmalloc that records the
- * calling function of the routine calling it for slab leak tracking instead
- * of just the calling function (confusing, eh?).
- * It's useful when the call to kmalloc comes from a widely-used standard
- * allocator where we care about the real place the memory allocation
- * request comes from.
- */
-#ifndef CONFIG_DEBUG_SLAB
-#define kmalloc_track_caller(size, flags) \
- __kmalloc(size, flags)
-#else
-extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
-#define kmalloc_track_caller(size, flags) \
- __kmalloc_track_caller(size, flags, __builtin_return_address(0))
-#endif
-
-extern void *__kzalloc(size_t, gfp_t);
-
/**
* kzalloc - allocate memory. The memory is set to zero.
* @size: how many bytes of memory are required.
@@ -163,72 +159,41 @@ extern void *__kzalloc(size_t, gfp_t);
*/
static inline void *kzalloc(size_t size, gfp_t flags)
{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kzalloc_that_much(void);
- __you_cannot_kzalloc_that_much();
- }
-found:
- return kmem_cache_zalloc((flags & GFP_DMA) ?
- malloc_sizes[i].cs_dmacachep :
- malloc_sizes[i].cs_cachep, flags);
- }
return __kzalloc(size, flags);
}
+#endif
-/**
- * kcalloc - allocate memory for an array. The memory is set to zero.
- * @n: number of elements.
- * @size: element size.
- * @flags: the type of memory to allocate.
- */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+#ifndef CONFIG_NUMA
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
- if (n != 0 && size > ULONG_MAX / n)
- return NULL;
- return kzalloc(n * size, flags);
+ return kmalloc(size, flags);
}
-extern void kfree(const void *);
-extern unsigned int ksize(const void *);
-extern int slab_is_available(void);
-
-#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
-extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
-
-static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+static inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
{
- if (__builtin_constant_p(size)) {
- int i = 0;
-#define CACHE(x) \
- if (size <= x) \
- goto found; \
- else \
- i++;
-#include "kmalloc_sizes.h"
-#undef CACHE
- {
- extern void __you_cannot_kmalloc_that_much(void);
- __you_cannot_kmalloc_that_much();
- }
-found:
- return kmem_cache_alloc_node((flags & GFP_DMA) ?
- malloc_sizes[i].cs_dmacachep :
- malloc_sizes[i].cs_cachep, flags, node);
- }
- return __kmalloc_node(size, flags, node);
+ return __kmalloc(size, flags);
}
+#endif /* !CONFIG_NUMA */
/*
+ * kmalloc_track_caller is a special version of kmalloc that records the
+ * calling function of the routine calling it for slab leak tracking instead
+ * of just the calling function (confusing, eh?).
+ * It's useful when the call to kmalloc comes from a widely-used standard
+ * allocator where we care about the real place the memory allocation
+ * request comes from.
+ */
+#ifdef CONFIG_DEBUG_SLAB
+extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
+#define kmalloc_track_caller(size, flags) \
+ __kmalloc_track_caller(size, flags, __builtin_return_address(0))
+#else
+#define kmalloc_track_caller(size, flags) \
+ __kmalloc(size, flags)
+#endif /* DEBUG_SLAB */
+
+#ifdef CONFIG_NUMA
+/*
* kmalloc_node_track_caller is a special version of kmalloc_node that
* records the calling function of the routine calling it for slab leak
* tracking instead of just the calling function (confusing, eh?).
@@ -236,70 +201,23 @@ found:
* standard allocator where we care about the real place the memory
* allocation request comes from.
*/
-#ifndef CONFIG_DEBUG_SLAB
-#define kmalloc_node_track_caller(size, flags, node) \
- __kmalloc_node(size, flags, node)
-#else
+#ifdef CONFIG_DEBUG_SLAB
extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *);
#define kmalloc_node_track_caller(size, flags, node) \
__kmalloc_node_track_caller(size, flags, node, \
__builtin_return_address(0))
+#else
+#define kmalloc_node_track_caller(size, flags, node) \
+ __kmalloc_node(size, flags, node)
#endif
+
#else /* CONFIG_NUMA */
-static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
- gfp_t flags, int node)
-{
- return kmem_cache_alloc(cachep, flags);
-}
-static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
-{
- return kmalloc(size, flags);
-}
#define kmalloc_node_track_caller(size, flags, node) \
kmalloc_track_caller(size, flags)
-#endif
-extern int FASTCALL(kmem_cache_reap(int));
-extern int FASTCALL(kmem_ptr_validate(struct kmem_cache *cachep, void *ptr));
-
-#else /* CONFIG_SLOB */
-
-/* SLOB allocator routines */
-
-void kmem_cache_init(void);
-struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
- unsigned long,
- void (*)(void *, struct kmem_cache *, unsigned long),
- void (*)(void *, struct kmem_cache *, unsigned long));
-void kmem_cache_destroy(struct kmem_cache *c);
-void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
-void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
-void kmem_cache_free(struct kmem_cache *c, void *b);
-const char *kmem_cache_name(struct kmem_cache *);
-void *kmalloc(size_t size, gfp_t flags);
-void *__kzalloc(size_t size, gfp_t flags);
-void kfree(const void *m);
-unsigned int ksize(const void *m);
-unsigned int kmem_cache_size(struct kmem_cache *c);
-
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
-{
- return __kzalloc(n * size, flags);
-}
-
-#define kmem_cache_shrink(d) (0)
-#define kmem_cache_reap(a)
-#define kmem_ptr_validate(a, b) (0)
-#define kmem_cache_alloc_node(c, f, n) kmem_cache_alloc(c, f)
-#define kmalloc_node(s, f, n) kmalloc(s, f)
-#define kzalloc(s, f) __kzalloc(s, f)
-#define kmalloc_track_caller kmalloc
-
-#define kmalloc_node_track_caller kmalloc_node
-
-#endif /* CONFIG_SLOB */
+#endif /* DEBUG_SLAB */
#endif /* __KERNEL__ */
-
#endif /* _LINUX_SLAB_H */
+
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
new file mode 100644
index 00000000000..4b463e66dde
--- /dev/null
+++ b/include/linux/slab_def.h
@@ -0,0 +1,100 @@
+#ifndef _LINUX_SLAB_DEF_H
+#define _LINUX_SLAB_DEF_H
+
+/*
+ * Definitions unique to the original Linux SLAB allocator.
+ *
+ * What we provide here is a way to optimize the frequent kmalloc
+ * calls in the kernel by selecting the appropriate general cache
+ * if kmalloc was called with a size that can be established at
+ * compile time.
+ */
+
+#include <linux/init.h>
+#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
+#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
+#include <linux/compiler.h>
+
+/* Size description struct for general caches. */
+struct cache_sizes {
+ size_t cs_size;
+ struct kmem_cache *cs_cachep;
+ struct kmem_cache *cs_dmacachep;
+};
+extern struct cache_sizes malloc_sizes[];
+
+static inline void *kmalloc(size_t size, gfp_t flags)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kmalloc_that_much(void);
+ __you_cannot_kmalloc_that_much();
+ }
+found:
+ return kmem_cache_alloc((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags);
+ }
+ return __kmalloc(size, flags);
+}
+
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kzalloc_that_much(void);
+ __you_cannot_kzalloc_that_much();
+ }
+found:
+ return kmem_cache_zalloc((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags);
+ }
+ return __kzalloc(size, flags);
+}
+
+#ifdef CONFIG_NUMA
+extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
+
+static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kmalloc_that_much(void);
+ __you_cannot_kmalloc_that_much();
+ }
+found:
+ return kmem_cache_alloc_node((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags, node);
+ }
+ return __kmalloc_node(size, flags, node);
+}
+
+#endif /* CONFIG_NUMA */
+
+#endif /* _LINUX_SLAB_DEF_H */
diff --git a/include/linux/smb_fs_sb.h b/include/linux/smb_fs_sb.h
index 5b4ae2cc445..3aa97aa4277 100644
--- a/include/linux/smb_fs_sb.h
+++ b/include/linux/smb_fs_sb.h
@@ -55,7 +55,7 @@ struct smb_sb_info {
* generation is incremented.
*/
unsigned int generation;
- pid_t conn_pid;
+ struct pid *conn_pid;
struct smb_conn_opt opt;
wait_queue_head_t conn_wq;
int conn_complete;
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index c8bb68099eb..176f6e36dbf 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -289,7 +289,7 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
* the data being transferred; that may reduce overhead, when the
* underlying driver uses dma.
*
- * If the transmit buffer is null, undefined data will be shifted out
+ * If the transmit buffer is null, zeroes will be shifted out
* while filling rx_buf. If the receive buffer is null, the data
* shifted in will be discarded. Only "len" bytes shift out (or in).
* It's an error to try to shift out a partial word. (For example, by
diff --git a/include/linux/stallion.h b/include/linux/stallion.h
index 13a37f137ea..4a0a329beaf 100644
--- a/include/linux/stallion.h
+++ b/include/linux/stallion.h
@@ -52,11 +52,11 @@
* protection - since "write" code only needs to change the head, and
* interrupt code only needs to change the tail.
*/
-typedef struct {
+struct stlrq {
char *buf;
char *head;
char *tail;
-} stlrq_t;
+};
/*
* Port, panel and board structures to hold status info about each.
@@ -67,14 +67,14 @@ typedef struct {
* is associated with, this makes it (fairly) easy to get back to the
* board/panel info for a port.
*/
-typedef struct stlport {
+struct stlport {
unsigned long magic;
- int portnr;
- int panelnr;
- int brdnr;
+ unsigned int portnr;
+ unsigned int panelnr;
+ unsigned int brdnr;
int ioaddr;
int uartaddr;
- int pagenr;
+ unsigned int pagenr;
long istate;
int flags;
int baud_base;
@@ -97,31 +97,31 @@ typedef struct stlport {
wait_queue_head_t close_wait;
struct work_struct tqueue;
comstats_t stats;
- stlrq_t tx;
-} stlport_t;
+ struct stlrq tx;
+};
-typedef struct stlpanel {
+struct stlpanel {
unsigned long magic;
- int panelnr;
- int brdnr;
- int pagenr;
- int nrports;
+ unsigned int panelnr;
+ unsigned int brdnr;
+ unsigned int pagenr;
+ unsigned int nrports;
int iobase;
void *uartp;
void (*isr)(struct stlpanel *panelp, unsigned int iobase);
unsigned int hwid;
unsigned int ackmask;
- stlport_t *ports[STL_PORTSPERPANEL];
-} stlpanel_t;
+ struct stlport *ports[STL_PORTSPERPANEL];
+};
-typedef struct stlbrd {
+struct stlbrd {
unsigned long magic;
- int brdnr;
- int brdtype;
- int state;
- int nrpanels;
- int nrports;
- int nrbnks;
+ unsigned int brdnr;
+ unsigned int brdtype;
+ unsigned int state;
+ unsigned int nrpanels;
+ unsigned int nrports;
+ unsigned int nrbnks;
int irq;
int irqtype;
int (*isr)(struct stlbrd *brdp);
@@ -136,9 +136,9 @@ typedef struct stlbrd {
unsigned long clk;
unsigned int bnkpageaddr[STL_MAXBANKS];
unsigned int bnkstataddr[STL_MAXBANKS];
- stlpanel_t *bnk2panel[STL_MAXBANKS];
- stlpanel_t *panels[STL_MAXPANELS];
-} stlbrd_t;
+ struct stlpanel *bnk2panel[STL_MAXBANKS];
+ struct stlpanel *panels[STL_MAXPANELS];
+};
/*
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 97c76165258..8b6ce60ea05 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -250,7 +250,6 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt,
int flags, const struct rpc_call_ops *ops,
void *data);
void rpc_put_task(struct rpc_task *);
-void rpc_release_task(struct rpc_task *);
void rpc_exit_task(struct rpc_task *);
void rpc_release_calldata(const struct rpc_call_ops *, void *);
void rpc_killall_tasks(struct rpc_clnt *);
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 965d6c20086..64f3d60c72a 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -144,8 +144,11 @@ extern u32 svc_max_payload(const struct svc_rqst *rqstp);
*
* Each request/reply pair can have at most one "payload", plus two pages,
* one for the request, and one for the reply.
+ * We using ->sendfile to return read data, we might need one extra page
+ * if the request is not page-aligned. So add another '1'.
*/
-#define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2)
+#define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE \
+ + 2 + 1)
static inline u32 svc_getnl(struct kvec *iov)
{
diff --git a/include/linux/swap.h b/include/linux/swap.h
index add51cebc8d..5423559a44a 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -245,7 +245,7 @@ extern int swap_duplicate(swp_entry_t);
extern int valid_swaphandles(swp_entry_t, unsigned long *);
extern void swap_free(swp_entry_t);
extern void free_swap_and_cache(swp_entry_t);
-extern int swap_type_of(dev_t, sector_t);
+extern int swap_type_of(dev_t, sector_t, struct block_device **);
extern unsigned int count_swap_pages(int, int);
extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t);
extern sector_t swapdev_block(int, pgoff_t);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 94316a98e0d..81480e61346 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -11,7 +11,7 @@
** the sysctl() binary interface. Do *NOT* change the
** numbering of any existing values here, and do not change
** any numbers within any one set of values. If you have to
- ** have to redefine an existing interface, use a new number for it.
+ ** redefine an existing interface, use a new number for it.
** The kernel will then return -ENOTDIR to any application using
** the old binary interface.
**
@@ -918,8 +918,7 @@ typedef struct ctl_table ctl_table;
typedef int ctl_handler (ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context);
+ void __user *newval, size_t newlen);
typedef int proc_handler (ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -950,7 +949,7 @@ extern int do_sysctl (int __user *name, int nlen,
extern int do_sysctl_strategy (ctl_table *table,
int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void ** context);
+ void __user *newval, size_t newlen);
extern ctl_handler sysctl_string;
extern ctl_handler sysctl_intvec;
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index 9df8833670c..98a1d8cfb73 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -37,23 +37,37 @@ struct sysrq_key_op {
#ifdef CONFIG_MAGIC_SYSRQ
+extern int sysrq_on(void);
+
+/*
+ * Do not use this one directly:
+ */
+extern int __sysrq_enabled;
+
/* Generic SysRq interface -- you may call it from any device driver, supplying
* ASCII code of the key, pointer to registers and kbd/tty structs (if they
* are available -- else NULL's).
*/
-void handle_sysrq(int, struct tty_struct *);
-void __handle_sysrq(int, struct tty_struct *, int check_mask);
-int register_sysrq_key(int, struct sysrq_key_op *);
-int unregister_sysrq_key(int, struct sysrq_key_op *);
+void handle_sysrq(int key, struct tty_struct *tty);
+void __handle_sysrq(int key, struct tty_struct *tty, int check_mask);
+int register_sysrq_key(int key, struct sysrq_key_op *op);
+int unregister_sysrq_key(int key, struct sysrq_key_op *op);
struct sysrq_key_op *__sysrq_get_key_op(int key);
#else
+static inline int sysrq_on(void)
+{
+ return 0;
+}
static inline int __reterr(void)
{
return -EINVAL;
}
+static inline void handle_sysrq(int key, struct tty_struct *tty)
+{
+}
#define register_sysrq_key(ig,nore) __reterr()
#define unregister_sysrq_key(ig,nore) __reterr()
diff --git a/include/linux/task_io_accounting.h b/include/linux/task_io_accounting.h
new file mode 100644
index 00000000000..44d00e9ccee
--- /dev/null
+++ b/include/linux/task_io_accounting.h
@@ -0,0 +1,37 @@
+/*
+ * task_io_accounting: a structure which is used for recording a single task's
+ * IO statistics.
+ *
+ * Don't include this header file directly - it is designed to be dragged in via
+ * sched.h.
+ *
+ * Blame akpm@osdl.org for all this.
+ */
+
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+struct task_io_accounting {
+ /*
+ * The number of bytes which this task has caused to be read from
+ * storage.
+ */
+ u64 read_bytes;
+
+ /*
+ * The number of bytes which this task has caused, or shall cause to be
+ * written to disk.
+ */
+ u64 write_bytes;
+
+ /*
+ * A task can cause "negative" IO too. If this task truncates some
+ * dirty pagecache, some IO which another task has been accounted for
+ * (in its write_bytes) will not be happening. We _could_ just
+ * subtract that from the truncating task's write_bytes, but there is
+ * information loss in doing that.
+ */
+ u64 cancelled_write_bytes;
+};
+#else
+struct task_io_accounting {
+};
+#endif
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
new file mode 100644
index 00000000000..df2a319106b
--- /dev/null
+++ b/include/linux/task_io_accounting_ops.h
@@ -0,0 +1,47 @@
+/*
+ * Task I/O accounting operations
+ */
+#ifndef __TASK_IO_ACCOUNTING_OPS_INCLUDED
+#define __TASK_IO_ACCOUNTING_OPS_INCLUDED
+
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+static inline void task_io_account_read(size_t bytes)
+{
+ current->ioac.read_bytes += bytes;
+}
+
+static inline void task_io_account_write(size_t bytes)
+{
+ current->ioac.write_bytes += bytes;
+}
+
+static inline void task_io_account_cancelled_write(size_t bytes)
+{
+ current->ioac.cancelled_write_bytes += bytes;
+}
+
+static inline void task_io_accounting_init(struct task_struct *tsk)
+{
+ memset(&tsk->ioac, 0, sizeof(tsk->ioac));
+}
+
+#else
+
+static inline void task_io_account_read(size_t bytes)
+{
+}
+
+static inline void task_io_account_write(size_t bytes)
+{
+}
+
+static inline void task_io_account_cancelled_write(size_t bytes)
+{
+}
+
+static inline void task_io_accounting_init(struct task_struct *tsk)
+{
+}
+
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
+#endif /* __TASK_IO_ACCOUNTING_OPS_INCLUDED */
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index 45248806ae9..3fced479825 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -31,7 +31,7 @@
*/
-#define TASKSTATS_VERSION 2
+#define TASKSTATS_VERSION 3
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */
@@ -115,31 +115,37 @@ struct taskstats {
__u64 ac_majflt; /* Major Page Fault Count */
/* Basic Accounting Fields end */
- /* Extended accounting fields start */
+ /* Extended accounting fields start */
/* Accumulated RSS usage in duration of a task, in MBytes-usecs.
* The current rss usage is added to this counter every time
* a tick is charged to a task's system time. So, at the end we
* will have memory usage multiplied by system time. Thus an
* average usage per system time unit can be calculated.
*/
- __u64 coremem; /* accumulated RSS usage in MB-usec */
+ __u64 coremem; /* accumulated RSS usage in MB-usec */
/* Accumulated virtual memory usage in duration of a task.
* Same as acct_rss_mem1 above except that we keep track of VM usage.
*/
- __u64 virtmem; /* accumulated VM usage in MB-usec */
+ __u64 virtmem; /* accumulated VM usage in MB-usec */
/* High watermark of RSS and virtual memory usage in duration of
* a task, in KBytes.
*/
- __u64 hiwater_rss; /* High-watermark of RSS usage, in KB */
- __u64 hiwater_vm; /* High-water VM usage, in KB */
+ __u64 hiwater_rss; /* High-watermark of RSS usage, in KB */
+ __u64 hiwater_vm; /* High-water VM usage, in KB */
/* The following four fields are I/O statistics of a task. */
- __u64 read_char; /* bytes read */
- __u64 write_char; /* bytes written */
- __u64 read_syscalls; /* read syscalls */
- __u64 write_syscalls; /* write syscalls */
- /* Extended accounting fields end */
+ __u64 read_char; /* bytes read */
+ __u64 write_char; /* bytes written */
+ __u64 read_syscalls; /* read syscalls */
+ __u64 write_syscalls; /* write syscalls */
+ /* Extended accounting fields end */
+
+#define TASKSTATS_HAS_IO_ACCOUNTING
+ /* Per-task storage I/O accounting starts */
+ __u64 read_bytes; /* bytes of read I/O */
+ __u64 write_bytes; /* bytes of write I/O */
+ __u64 cancelled_write_bytes; /* bytes of cancelled write I/O */
};
diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h
index 31a9b25276f..8a8462b4a4d 100644
--- a/include/linux/tfrc.h
+++ b/include/linux/tfrc.h
@@ -37,10 +37,14 @@ struct tfrc_rx_info {
* @tfrctx_p: current loss event rate (5.4)
* @tfrctx_rto: estimate of RTO, equals 4*RTT (4.3)
* @tfrctx_ipi: inter-packet interval (4.6)
+ *
+ * Note: X and X_recv are both maintained in units of 64 * bytes/second. This
+ * enables a finer resolution of sending rates and avoids problems with
+ * integer arithmetic; u32 is not sufficient as scaling consumes 6 bits.
*/
struct tfrc_tx_info {
- __u32 tfrctx_x;
- __u32 tfrctx_x_recv;
+ __u64 tfrctx_x;
+ __u64 tfrctx_x_recv;
__u32 tfrctx_x_calc;
__u32 tfrctx_rtt;
__u32 tfrctx_p;
diff --git a/include/linux/timer.h b/include/linux/timer.h
index c982304dbaf..fb5edaaf0eb 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -41,7 +41,7 @@ static inline void setup_timer(struct timer_list * timer,
init_timer(timer);
}
-/***
+/**
* timer_pending - is a timer pending?
* @timer: the timer in question
*
@@ -63,7 +63,7 @@ extern int mod_timer(struct timer_list *timer, unsigned long expires);
extern unsigned long next_timer_interrupt(void);
-/***
+/**
* add_timer - start a timer
* @timer: the timer to be added
*
@@ -98,4 +98,10 @@ extern void run_local_timers(void);
struct hrtimer;
extern int it_real_fn(struct hrtimer *);
+unsigned long __round_jiffies(unsigned long j, int cpu);
+unsigned long __round_jiffies_relative(unsigned long j, int cpu);
+unsigned long round_jiffies(unsigned long j);
+unsigned long round_jiffies_relative(unsigned long j);
+
+
#endif
diff --git a/include/linux/topology.h b/include/linux/topology.h
index da508d1998e..6c5a6e6e813 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -93,7 +93,7 @@
.groups = NULL, \
.min_interval = 1, \
.max_interval = 2, \
- .busy_factor = 8, \
+ .busy_factor = 64, \
.imbalance_pct = 110, \
.cache_nice_tries = 0, \
.per_cpu_gain = 25, \
@@ -194,7 +194,8 @@
.wake_idx = 0, /* unused */ \
.forkexec_idx = 0, /* unused */ \
.per_cpu_gain = 100, \
- .flags = SD_LOAD_BALANCE, \
+ .flags = SD_LOAD_BALANCE \
+ | SD_SERIALIZE, \
.last_balance = jiffies, \
.balance_interval = 64, \
.nr_balance_failed = 0, \
diff --git a/include/linux/tty.h b/include/linux/tty.h
index f717f089823..65cbcf22c31 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -175,7 +175,7 @@ struct tty_struct {
int index;
struct tty_ldisc ldisc;
struct mutex termios_mutex;
- struct termios *termios, *termios_locked;
+ struct ktermios *termios, *termios_locked;
char name[64];
int pgrp;
int session;
@@ -258,7 +258,7 @@ struct tty_struct {
extern void tty_write_flush(struct tty_struct *);
-extern struct termios tty_std_termios;
+extern struct ktermios tty_std_termios;
extern int kmsg_redirect;
@@ -293,8 +293,9 @@ extern int tty_hung_up_p(struct file * filp);
extern void do_SAK(struct tty_struct *tty);
extern void disassociate_ctty(int priv);
extern void tty_flip_buffer_push(struct tty_struct *tty);
-extern int tty_get_baud_rate(struct tty_struct *tty);
-extern int tty_termios_baud_rate(struct termios *termios);
+extern speed_t tty_get_baud_rate(struct tty_struct *tty);
+extern speed_t tty_termios_baud_rate(struct ktermios *termios);
+extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
extern void tty_ldisc_deref(struct tty_ldisc *);
@@ -309,6 +310,12 @@ extern void tty_ldisc_flush(struct tty_struct *tty);
extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
+extern dev_t tty_devnum(struct tty_struct *tty);
+extern void proc_clear_tty(struct task_struct *p);
+extern void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
+extern struct tty_struct *get_current_tty(void);
+
extern struct mutex tty_mutex;
/* n_tty.c */
@@ -335,10 +342,5 @@ extern void console_print(const char *);
extern int vt_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
-static inline dev_t tty_devnum(struct tty_struct *tty)
-{
- return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
-}
-
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 5c8473bb688..659487e3ebe 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -53,7 +53,7 @@
* device-specific ioctl's. If the ioctl number passed in cmd
* is not recognized by the driver, it should return ENOIOCTLCMD.
*
- * void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
*
* This routine allows the tty driver to be notified when
* device's termios settings have changed. Note that a
@@ -132,7 +132,7 @@ struct tty_operations {
int (*chars_in_buffer)(struct tty_struct *tty);
int (*ioctl)(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
- void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
void (*throttle)(struct tty_struct * tty);
void (*unthrottle)(struct tty_struct * tty);
void (*stop)(struct tty_struct *tty);
@@ -165,7 +165,7 @@ struct tty_driver {
int num; /* number of devices allocated */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
- struct termios init_termios; /* Initial termios */
+ struct ktermios init_termios; /* Initial termios */
int flags; /* tty driver flags */
int refcount; /* for loadable tty drivers */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
@@ -175,8 +175,8 @@ struct tty_driver {
* Pointer to the tty data structures
*/
struct tty_struct **ttys;
- struct termios **termios;
- struct termios **termios_locked;
+ struct ktermios **termios;
+ struct ktermios **termios_locked;
void *driver_state; /* only used for the PTY driver */
/*
@@ -193,7 +193,7 @@ struct tty_driver {
int (*chars_in_buffer)(struct tty_struct *tty);
int (*ioctl)(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
- void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
void (*throttle)(struct tty_struct * tty);
void (*unthrottle)(struct tty_struct * tty);
void (*stop)(struct tty_struct *tty);
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 83c6e6c10eb..d75932e2771 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -59,7 +59,7 @@
* low-level driver can "grab" an ioctl request before the line
* discpline has a chance to see it.
*
- * void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
*
* This function notifies the line discpline that a change has
* been made to the termios structure.
@@ -118,7 +118,7 @@ struct tty_ldisc {
const unsigned char * buf, size_t nr);
int (*ioctl)(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg);
- void (*set_termios)(struct tty_struct *tty, struct termios * old);
+ void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
unsigned int (*poll)(struct tty_struct *, struct file *,
struct poll_table_struct *);
int (*hangup)(struct tty_struct *tty);
diff --git a/include/linux/unwind.h b/include/linux/unwind.h
index 749928c161f..7760860fa17 100644
--- a/include/linux/unwind.h
+++ b/include/linux/unwind.h
@@ -14,63 +14,6 @@
struct module;
-#ifdef CONFIG_STACK_UNWIND
-
-#include <asm/unwind.h>
-
-#ifndef ARCH_UNWIND_SECTION_NAME
-#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
-#endif
-
-/*
- * Initialize unwind support.
- */
-extern void unwind_init(void);
-extern void unwind_setup(void);
-
-#ifdef CONFIG_MODULES
-
-extern void *unwind_add_table(struct module *,
- const void *table_start,
- unsigned long table_size);
-
-extern void unwind_remove_table(void *handle, int init_only);
-
-#endif
-
-extern int unwind_init_frame_info(struct unwind_frame_info *,
- struct task_struct *,
- /*const*/ struct pt_regs *);
-
-/*
- * Prepare to unwind a blocked task.
- */
-extern int unwind_init_blocked(struct unwind_frame_info *,
- struct task_struct *);
-
-/*
- * Prepare to unwind the currently running thread.
- */
-extern int unwind_init_running(struct unwind_frame_info *,
- asmlinkage int (*callback)(struct unwind_frame_info *,
- void *arg),
- void *arg);
-
-/*
- * Unwind to previous to frame. Returns 0 if successful, negative
- * number in case of an error.
- */
-extern int unwind(struct unwind_frame_info *);
-
-/*
- * Unwind until the return pointer is in user-land (or until an error
- * occurs). Returns 0 if successful, negative number in case of
- * error.
- */
-extern int unwind_to_user(struct unwind_frame_info *);
-
-#else
-
struct unwind_frame_info {};
static inline void unwind_init(void) {}
@@ -85,12 +28,12 @@ static inline void *unwind_add_table(struct module *mod,
return NULL;
}
-#endif
-
static inline void unwind_remove_table(void *handle, int init_only)
{
}
+#endif
+
static inline int unwind_init_frame_info(struct unwind_frame_info *info,
struct task_struct *tsk,
const struct pt_regs *regs)
@@ -122,6 +65,4 @@ static inline int unwind_to_user(struct unwind_frame_info *info)
return -ENOSYS;
}
-#endif
-
#endif /* _LINUX_UNWIND_H */
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 91b3ea2bbb1..10f99e5f1a9 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -218,7 +218,7 @@ struct usb_serial_driver {
int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count);
int (*write_room) (struct usb_serial_port *port);
int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
- void (*set_termios) (struct usb_serial_port *port, struct termios * old);
+ void (*set_termios) (struct usb_serial_port *port, struct ktermios * old);
void (*break_ctl) (struct usb_serial_port *port, int break_state);
int (*chars_in_buffer) (struct usb_serial_port *port);
void (*throttle) (struct usb_serial_port *port);
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index df5c4654360..d94e2683be5 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -244,6 +244,7 @@ struct v4l2_pix_format
#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */
#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 macroblocks */
+#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R','4','4','4') /* 16 xxxxrrrr ggggbbbb */
/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */
@@ -661,6 +662,15 @@ typedef __u64 v4l2_std_id;
#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
+/* FIXME:
+ Although std_id is 64 bits, there is an issue on PPC32 architecture that
+ makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding
+ this value to 32 bits.
+ As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide),
+ it should work fine. However, if needed to add more than two standards,
+ v4l2-common.c should be fixed.
+ */
+
/* some merged standards */
#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index c89df55f6e0..5e9803ed17f 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -10,8 +10,9 @@
/*
* Light weight per cpu counter implementation.
*
- * Counters should only be incremented and no critical kernel component
- * should rely on the counter values.
+ * Counters should only be incremented. You need to set EMBEDDED
+ * to disable VM_EVENT_COUNTERS. Things like procps (vmstat,
+ * top, etc) use /proc/vmstat and depend on these counters.
*
* Counters are handled completely inline. On many platforms the code
* generated will simply be the increment of a global address.
@@ -73,7 +74,13 @@ static inline void count_vm_events(enum vm_event_item item, long delta)
}
extern void all_vm_events(unsigned long *);
+#ifdef CONFIG_HOTPLUG
extern void vm_events_fold_cpu(int cpu);
+#else
+static inline void vm_events_fold_cpu(int cpu)
+{
+}
+#endif
#else
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index edef8d50b26..2a7b38d8701 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -8,16 +8,21 @@
#include <linux/timer.h>
#include <linux/linkage.h>
#include <linux/bitops.h>
+#include <asm/atomic.h>
struct workqueue_struct;
struct work_struct;
typedef void (*work_func_t)(struct work_struct *work);
+/*
+ * The first word is the work queue pointer and the flags rolled into
+ * one
+ */
+#define work_data_bits(work) ((unsigned long *)(&(work)->data))
+
struct work_struct {
- /* the first word is the work queue pointer and the flags rolled into
- * one */
- unsigned long management;
+ atomic_long_t data;
#define WORK_STRUCT_PENDING 0 /* T if work item pending execution */
#define WORK_STRUCT_NOAUTOREL 1 /* F if work item automatically released on exec */
#define WORK_STRUCT_FLAG_MASK (3UL)
@@ -26,6 +31,9 @@ struct work_struct {
work_func_t func;
};
+#define WORK_DATA_INIT(autorelease) \
+ ATOMIC_LONG_INIT((autorelease) << WORK_STRUCT_NOAUTOREL)
+
struct delayed_work {
struct work_struct work;
struct timer_list timer;
@@ -36,13 +44,13 @@ struct execute_work {
};
#define __WORK_INITIALIZER(n, f) { \
- .management = 0, \
+ .data = WORK_DATA_INIT(0), \
.entry = { &(n).entry, &(n).entry }, \
.func = (f), \
}
#define __WORK_INITIALIZER_NAR(n, f) { \
- .management = (1 << WORK_STRUCT_NOAUTOREL), \
+ .data = WORK_DATA_INIT(1), \
.entry = { &(n).entry, &(n).entry }, \
.func = (f), \
}
@@ -82,17 +90,21 @@ struct execute_work {
/*
* initialize all of a work item in one go
+ *
+ * NOTE! No point in using "atomic_long_set()": useing a direct
+ * assignment of the work data initializer allows the compiler
+ * to generate better code.
*/
#define INIT_WORK(_work, _func) \
do { \
- (_work)->management = 0; \
+ (_work)->data = (atomic_long_t) WORK_DATA_INIT(0); \
INIT_LIST_HEAD(&(_work)->entry); \
PREPARE_WORK((_work), (_func)); \
} while (0)
#define INIT_WORK_NAR(_work, _func) \
do { \
- (_work)->management = (1 << WORK_STRUCT_NOAUTOREL); \
+ (_work)->data = (atomic_long_t) WORK_DATA_INIT(1); \
INIT_LIST_HEAD(&(_work)->entry); \
PREPARE_WORK((_work), (_func)); \
} while (0)
@@ -114,15 +126,15 @@ struct execute_work {
* @work: The work item in question
*/
#define work_pending(work) \
- test_bit(WORK_STRUCT_PENDING, &(work)->management)
+ test_bit(WORK_STRUCT_PENDING, work_data_bits(work))
/**
* delayed_work_pending - Find out whether a delayable work item is currently
* pending
* @work: The work item in question
*/
-#define delayed_work_pending(work) \
- test_bit(WORK_STRUCT_PENDING, &(work)->work.management)
+#define delayed_work_pending(w) \
+ work_pending(&(w)->work)
/**
* work_release - Release a work item under execution
@@ -143,7 +155,7 @@ struct execute_work {
* This should also be used to release a delayed work item.
*/
#define work_release(work) \
- clear_bit(WORK_STRUCT_PENDING, &(work)->management)
+ clear_bit(WORK_STRUCT_PENDING, work_data_bits(work))
extern struct workqueue_struct *__create_workqueue(const char *name,
@@ -188,7 +200,7 @@ static inline int cancel_delayed_work(struct delayed_work *work)
ret = del_timer_sync(&work->timer);
if (ret)
- clear_bit(WORK_STRUCT_PENDING, &work->work.management);
+ work_release(&work->work);
return ret;
}
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 088ba8113f7..9529ea1ae39 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -357,7 +357,7 @@ struct xfrm_user_report {
#define XFRMGRP_EXPIRE 2
#define XFRMGRP_SA 4
#define XFRMGRP_POLICY 8
-#define XFRMGRP_REPORT 0x10
+#define XFRMGRP_REPORT 0x20
#endif
enum xfrm_nlgroups {
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
index d91d88f93c8..ecad55bf016 100644
--- a/include/media/cx2341x.h
+++ b/include/media/cx2341x.h
@@ -49,7 +49,7 @@ struct cx2341x_mpeg_params {
enum v4l2_mpeg_audio_mode_extension audio_mode_extension;
enum v4l2_mpeg_audio_emphasis audio_emphasis;
enum v4l2_mpeg_audio_crc audio_crc;
- u8 audio_properties;
+ u16 audio_properties;
/* video */
enum v4l2_mpeg_video_encoding video_encoding;
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 8f58406533c..4bb0ad81017 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -24,6 +24,7 @@
#define _IR_COMMON
#include <linux/input.h>
+#include <linux/workqueue.h>
#define IR_TYPE_RC5 1
#define IR_TYPE_PD 2 /* Pulse distance encoded IR */
@@ -92,6 +93,7 @@ extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
#endif
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index fee579f10b3..796bcf151a3 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -42,10 +42,6 @@ extern unsigned int saa7146_debug;
#define DEB_INT(x) if (0!=(DEBUG_VARIABLE&0x20)) { DEBUG_PROLOG; printk x; } /* interrupt debug messages */
#define DEB_CAP(x) if (0!=(DEBUG_VARIABLE&0x40)) { DEBUG_PROLOG; printk x; } /* capture debug messages */
-#define SAA7146_IER_DISABLE(x,y) \
- saa7146_write(x, IER, saa7146_read(x, IER) & ~(y));
-#define SAA7146_IER_ENABLE(x,y) \
- saa7146_write(x, IER, saa7146_read(x, IER) | (y));
#define SAA7146_ISR_CLEAR(x,y) \
saa7146_write(x, ISR, (y));
@@ -441,4 +437,20 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
#define SAA7146_I2C_BUS_BIT_RATE_80 (0x200)
#define SAA7146_I2C_BUS_BIT_RATE_60 (0x300)
+static inline void SAA7146_IER_DISABLE(struct saa7146_dev *x, unsigned y)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&x->int_slock, flags);
+ saa7146_write(x, IER, saa7146_read(x, IER) & ~y);
+ spin_unlock_irqrestore(&x->int_slock, flags);
+}
+
+static inline void SAA7146_IER_ENABLE(struct saa7146_dev *x, unsigned y)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&x->int_slock, flags);
+ saa7146_write(x, IER, saa7146_read(x, IER) | y);
+ spin_unlock_irqrestore(&x->int_slock, flags);
+}
+
#endif
diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h
index 37dad07a843..e5ad3fcfe98 100644
--- a/include/media/tuner-types.h
+++ b/include/media/tuner-types.h
@@ -50,6 +50,10 @@ struct tuner_params {
sensitivity. If this setting is 1, then set PORT2 to 1 to
get proper FM reception. */
unsigned int port2_fm_high_sensitivity:1;
+ /* Some Philips tuners use tda9887 cGainNormal to select the FM radio
+ sensitivity. If this setting is 1, e register will use cGainNormal
+ instead of cGainLow. */
+ unsigned int fm_gain_normal:1;
/* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners
use Intercarrier mode. If this setting is 1, then the tuner
needs to be set to intercarrier mode. */
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 3116e750132..99acf847365 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -145,6 +145,7 @@ extern int tuner_debug;
#define TDA9887_DEEMPHASIS_75 (3<<16)
#define TDA9887_AUTOMUTE (1<<18)
#define TDA9887_GATING_18 (1<<19)
+#define TDA9887_GAIN_NORMAL (1<<20)
#ifdef __KERNEL__
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h
index e9fc1a78549..5660ea24996 100644
--- a/include/media/tveeprom.h
+++ b/include/media/tveeprom.h
@@ -3,7 +3,7 @@
struct tveeprom {
u32 has_radio;
- u32 has_ir; /* 0: no IR, 1: IR present, 2: unknown */
+ u32 has_ir; /* bit 0: IR receiver present, bit 1: IR transmitter (blaster) present. -1 == unknown */
u32 has_MAC_address; /* 0: no MAC, 1: MAC present, 2: unknown */
u32 tuner_type;
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index aecc946980a..91b19921f95 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -144,6 +144,9 @@ enum v4l2_chip_ident {
V4L2_IDENT_CX25841 = 241,
V4L2_IDENT_CX25842 = 242,
V4L2_IDENT_CX25843 = 243,
+
+ /* OmniVision sensors - range 250-299 */
+ V4L2_IDENT_OV7670 = 250,
};
/* audio ioctls */
@@ -251,4 +254,8 @@ struct v4l2_crystal_freq {
If the frequency is not supported, then -EINVAL is returned. */
#define VIDIOC_INT_S_CRYSTAL_FREQ _IOW ('d', 113, struct v4l2_crystal_freq)
+/* Initialize the sensor registors to some sort of reasonable
+ default values. */
+#define VIDIOC_INT_INIT _IOW ('d', 114, u32)
+
#endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 6a11d772700..fb96472a1bd 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -43,6 +43,7 @@
/* Video standard functions */
extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
+extern char *v4l2_norm_to_name(v4l2_std_id id);
extern int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name);
@@ -81,12 +82,6 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
* This version moves redundant code from video device code to
* the common handler
*/
-struct v4l2_tvnorm {
- char *name;
- v4l2_std_id id;
-
- void *priv_data;
-};
struct video_device
{
@@ -104,9 +99,8 @@ struct video_device
int debug; /* Activates debug level*/
/* Video standard vars */
- int tvnormsize; /* Size of tvnorm array */
- v4l2_std_id current_norm; /* Current tvnorm */
- struct v4l2_tvnorm *tvnorms;
+ v4l2_std_id tvnorms; /* Supported tv norms */
+ v4l2_std_id current_norm; /* Current tvnorm */
/* callbacks */
void (*release)(struct video_device *vfd);
@@ -211,7 +205,7 @@ struct video_device
/* Standard handling
G_STD and ENUMSTD are handled by videodev.c
*/
- int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id a);
+ int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
/* Input handling */
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 69374cd1a85..5ae10dd2e32 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -277,20 +277,24 @@ struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
extern void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
extern void ax25_destroy_socket(ax25_cb *);
-extern ax25_cb *ax25_create_cb(void);
+extern ax25_cb * __must_check ax25_create_cb(void);
extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
/* ax25_addr.c */
-extern ax25_address null_ax25_address;
-extern char *ax2asc(char *buf, ax25_address *);
-extern void asc2ax(ax25_address *addr, char *callsign);
-extern int ax25cmp(ax25_address *, ax25_address *);
-extern int ax25digicmp(ax25_digi *, ax25_digi *);
-extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *);
-extern int ax25_addr_build(unsigned char *, ax25_address *, ax25_address *, ax25_digi *, int, int);
-extern int ax25_addr_size(ax25_digi *);
-extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
+extern const ax25_address ax25_bcast;
+extern const ax25_address ax25_defaddr;
+extern const ax25_address null_ax25_address;
+extern char *ax2asc(char *buf, const ax25_address *);
+extern void asc2ax(ax25_address *addr, const char *callsign);
+extern int ax25cmp(const ax25_address *, const ax25_address *);
+extern int ax25digicmp(const ax25_digi *, const ax25_digi *);
+extern const unsigned char *ax25_addr_parse(const unsigned char *, int,
+ ax25_address *, ax25_address *, ax25_digi *, int *, int *);
+extern int ax25_addr_build(unsigned char *, const ax25_address *,
+ const ax25_address *, const ax25_digi *, int, int);
+extern int ax25_addr_size(const ax25_digi *);
+extern void ax25_digi_invert(const ax25_digi *, ax25_digi *);
/* ax25_dev.c */
extern ax25_dev *ax25_dev_list;
@@ -329,11 +333,25 @@ extern void ax25_ds_t3timer_expiry(ax25_cb *);
extern void ax25_ds_idletimer_expiry(ax25_cb *);
/* ax25_iface.c */
-extern int ax25_protocol_register(unsigned int, int (*)(struct sk_buff *, ax25_cb *));
+
+struct ax25_protocol {
+ struct ax25_protocol *next;
+ unsigned int pid;
+ int (*func)(struct sk_buff *, ax25_cb *);
+};
+
+extern void ax25_register_pid(struct ax25_protocol *ap);
extern void ax25_protocol_release(unsigned int);
-extern int ax25_linkfail_register(void (*)(ax25_cb *, int));
-extern void ax25_linkfail_release(void (*)(ax25_cb *, int));
-extern int ax25_listen_register(ax25_address *, struct net_device *);
+
+struct ax25_linkfail {
+ struct hlist_node lf_node;
+ void (*func)(ax25_cb *, int);
+};
+
+extern void ax25_linkfail_register(struct ax25_linkfail *lf);
+extern void ax25_linkfail_release(struct ax25_linkfail *lf);
+extern int __must_check ax25_listen_register(ax25_address *,
+ struct net_device *);
extern void ax25_listen_release(ax25_address *, struct net_device *);
extern int (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
extern int ax25_listen_mine(ax25_address *, struct net_device *);
@@ -411,7 +429,7 @@ extern unsigned long ax25_display_timer(struct timer_list *);
/* ax25_uid.c */
extern int ax25_uid_policy;
extern ax25_uid_assoc *ax25_findbyuid(uid_t);
-extern int ax25_uid_ioctl(int, struct sockaddr_ax25 *);
+extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
extern struct file_operations ax25_uid_fops;
extern void ax25_uid_free(void);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 10a3eec191f..41456c14884 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -739,13 +739,13 @@ struct sockaddr_hci {
struct hci_filter {
unsigned long type_mask;
unsigned long event_mask[2];
- __u16 opcode;
+ __le16 opcode;
};
struct hci_ufilter {
__u32 type_mask;
__u32 event_mask[2];
- __u16 opcode;
+ __le16 opcode;
};
#define HCI_FLT_TYPE_BITS 31
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index e6af381e206..e02d85f56e6 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -218,7 +218,7 @@ struct ieee80211_snap_hdr {
#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
-#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ)
+#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 16aa96a6a53..f13ddc2543b 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -38,5 +38,5 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
-extern int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok);
+extern int inet6_csk_xmit(struct sk_buff *skb, int ipfragok);
#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index bf16d98d372..133cf30d2d7 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -37,8 +37,7 @@ struct tcp_congestion_ops;
* (i.e. things that depend on the address family)
*/
struct inet_connection_sock_af_ops {
- int (*queue_xmit)(struct sk_buff *skb, struct sock *sk,
- int ipfragok);
+ int (*queue_xmit)(struct sk_buff *skb, int ipfragok);
void (*send_check)(struct sock *sk, int len,
struct sk_buff *skb);
int (*rebuild_header)(struct sock *sk);
diff --git a/include/net/ip.h b/include/net/ip.h
index 83cb9ac5554..e79c3e3aa4f 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -97,7 +97,7 @@ extern int ip_mc_output(struct sk_buff *skb);
extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
extern int ip_do_nat(struct sk_buff *skb);
extern void ip_send_check(struct iphdr *ip);
-extern int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok);
+extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
extern void ip_init(void);
extern int ip_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
@@ -376,8 +376,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
size_t *lenp, loff_t *ppos);
int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context);
+ void __user *newval, size_t newlen);
#ifdef CONFIG_PROC_FS
extern int ip_misc_proc_init(void);
#endif
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
index 68e2b32cf1d..bc1b0fda2b0 100644
--- a/include/net/ip6_checksum.h
+++ b/include/net/ip6_checksum.h
@@ -87,7 +87,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
carry = (sum < uproto);
sum += carry;
- return csum_fold((__force __wsum)csum);
+ return csum_fold((__force __wsum)sum);
}
#endif
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index f9cde44f93b..7be4f4e3a0f 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -50,9 +50,9 @@ struct fib6_node
struct fib6_node *parent;
struct fib6_node *left;
struct fib6_node *right;
-
+#ifdef CONFIG_IPV6_SUBTREES
struct fib6_node *subtree;
-
+#endif
struct rt6_info *leaf;
__u16 fn_bit; /* bit key */
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 87699cb4ef8..8dabdd603fe 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -126,7 +126,7 @@ extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern void ircomm_tty_set_termios(struct tty_struct *tty,
- struct termios *old_termios);
+ struct ktermios *old_termios);
extern hashbin_t *ircomm_tty;
#endif
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 23967031ddb..3725b93c52f 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -309,6 +309,24 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
return 0;
}
+static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
+{
+ unsigned seq;
+ int hh_len;
+
+ do {
+ int hh_alen;
+
+ seq = read_seqbegin(&hh->hh_lock);
+ hh_len = hh->hh_len;
+ hh_alen = HH_DATA_ALIGN(hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
+ } while (read_seqretry(&hh->hh_lock, seq));
+
+ skb_push(skb, hh_len);
+ return hh->hh_output(skb);
+}
+
static inline struct neighbour *
__neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat)
{
diff --git a/include/net/netfilter/nf_conntrack_compat.h b/include/net/netfilter/nf_conntrack_compat.h
index f1b1482d720..6f84c1f7fcd 100644
--- a/include/net/netfilter/nf_conntrack_compat.h
+++ b/include/net/netfilter/nf_conntrack_compat.h
@@ -6,6 +6,7 @@
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/socket.h>
#ifdef CONFIG_IP_NF_CONNTRACK_MARK
static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
@@ -64,6 +65,16 @@ static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
return (ct != NULL);
}
+static inline int nf_ct_l3proto_try_module_get(unsigned short l3proto)
+{
+ need_conntrack();
+ return l3proto == PF_INET ? 0 : -1;
+}
+
+static inline void nf_ct_l3proto_module_put(unsigned short l3proto)
+{
+}
+
#else /* CONFIG_IP_NF_CONNTRACK */
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
diff --git a/include/net/rose.h b/include/net/rose.h
index 012b09ed240..4c05a88b921 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -188,13 +188,13 @@ extern void rose_kick(struct sock *);
extern void rose_enquiry_response(struct sock *);
/* rose_route.c */
-extern struct rose_neigh *rose_loopback_neigh;
+extern struct rose_neigh rose_loopback_neigh;
extern struct file_operations rose_neigh_fops;
extern struct file_operations rose_nodes_fops;
extern struct file_operations rose_routes_fops;
-extern int rose_add_loopback_neigh(void);
-extern int rose_add_loopback_node(rose_address *);
+extern void rose_add_loopback_neigh(void);
+extern int __must_check rose_add_loopback_node(rose_address *);
extern void rose_del_loopback_node(rose_address *);
extern void rose_rt_device_down(struct net_device *);
extern void rose_link_device_down(struct net_device *);
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 215461f18db..28af6805952 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -128,8 +128,6 @@ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
int flags);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
-int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
- void *ptr);
/*
* sctp/socket.c
@@ -368,7 +366,7 @@ static inline void sctp_sysctl_register(void) { return; }
static inline void sctp_sysctl_unregister(void) { return; }
static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context) {
+ void __user *newval, size_t newlen) {
return -ENOSYS;
}
#endif
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 3269ed1cc22..73cb9943c8a 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -134,6 +134,7 @@ sctp_state_fn_t sctp_sf_violation;
sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
+sctp_state_fn_t sctp_sf_do_5_2_3_initack;
sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index c089f93ba59..31a8e88f1a7 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -201,13 +201,12 @@ extern struct sctp_globals {
struct sctp_bind_hashbucket *port_hashtable;
/* This is the global local address list.
- * We actively maintain this complete list of interfaces on
- * the system by catching routing events.
+ * We actively maintain this complete list of addresses on
+ * the system by catching address add/delete events.
*
* It is a list of sctp_sockaddr_entry.
*/
struct list_head local_addr_list;
- spinlock_t local_addr_lock;
/* Flag to indicate if addip is enabled. */
int addip_enable;
@@ -243,7 +242,6 @@ extern struct sctp_globals {
#define sctp_port_alloc_lock (sctp_globals.port_alloc_lock)
#define sctp_port_hashtable (sctp_globals.port_hashtable)
#define sctp_local_addr_list (sctp_globals.local_addr_list)
-#define sctp_local_addr_lock (sctp_globals.local_addr_lock)
#define sctp_addip_enable (sctp_globals.addip_enable)
#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
@@ -277,6 +275,7 @@ struct sctp_sock {
__u16 default_flags;
__u32 default_context;
__u32 default_timetolive;
+ __u32 default_rcv_context;
/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
* the destination address every heartbeat interval. This value
@@ -307,7 +306,7 @@ struct sctp_sock {
__u8 disable_fragments;
__u8 pd_mode;
__u8 v4mapped;
- __u32 adaption_ind;
+ __u32 adaptation_ind;
/* Receive to here while partial delivery is in effect. */
struct sk_buff_head pd_lobby;
@@ -389,7 +388,7 @@ struct sctp_cookie {
/* Padding for future use */
__u8 padding;
- __u32 adaption_ind;
+ __u32 adaptation_ind;
/* This is a shim for my peer's INIT packet, followed by
@@ -432,7 +431,7 @@ union sctp_params {
struct sctp_ipv4addr_param *v4;
struct sctp_ipv6addr_param *v6;
union sctp_addr_param *addr;
- struct sctp_adaption_ind_param *aind;
+ struct sctp_adaptation_ind_param *aind;
};
/* RFC 2960. Section 3.3.5 Heartbeat.
@@ -1484,7 +1483,7 @@ struct sctp_association {
__u8 asconf_capable; /* Does peer support ADDIP? */
__u8 prsctp_capable; /* Can peer do PR-SCTP? */
- __u32 adaption_ind; /* Adaption Code point. */
+ __u32 adaptation_ind; /* Adaptation Code point. */
/* This mask is used to disable sending the ASCONF chunk
* with specified parameter to peer.
@@ -1659,6 +1658,9 @@ struct sctp_association {
__u32 default_context;
__u32 default_timetolive;
+ /* Default receive parameters */
+ __u32 default_rcv_context;
+
/* This tracks outbound ssn for a given stream. */
struct sctp_ssnmap *ssnmap;
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 1a4ddc1ec7d..2923e3d31a0 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -120,7 +120,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
const struct sctp_association *asoc,
__u32 indication, gfp_t gfp);
-struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
+struct sctp_ulpevent *sctp_ulpevent_make_adaptation_indication(
const struct sctp_association *asoc, gfp_t gfp);
struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 1b7aae6cdd8..67a30eb2b3a 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -75,8 +75,8 @@ enum sctp_optname {
#define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR
SCTP_PRIMARY_ADDR,
#define SCTP_PRIMARY_ADDR SCTP_PRIMARY_ADDR
- SCTP_ADAPTION_LAYER,
-#define SCTP_ADAPTION_LAYER SCTP_ADAPTION_LAYER
+ SCTP_ADAPTATION_LAYER,
+#define SCTP_ADAPTATION_LAYER SCTP_ADAPTATION_LAYER
SCTP_DISABLE_FRAGMENTS,
#define SCTP_DISABLE_FRAGMENTS SCTP_DISABLE_FRAGMENTS
SCTP_PEER_ADDR_PARAMS,
@@ -95,6 +95,8 @@ enum sctp_optname {
#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
SCTP_DELAYED_ACK_TIME,
#define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME
+ SCTP_CONTEXT, /* Receive Context */
+#define SCTP_CONTEXT SCTP_CONTEXT
/* Internal Socket Options. Some of the sctp library functions are
* implemented using these socket options.
@@ -329,17 +331,17 @@ struct sctp_shutdown_event {
};
/*
- * 5.3.1.6 SCTP_ADAPTION_INDICATION
+ * 5.3.1.6 SCTP_ADAPTATION_INDICATION
*
- * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * When a peer sends a Adaptation Layer Indication parameter , SCTP
* delivers this notification to inform the application
- * that of the peers requested adaption layer.
+ * that of the peers requested adaptation layer.
*/
-struct sctp_adaption_event {
+struct sctp_adaptation_event {
__u16 sai_type;
__u16 sai_flags;
__u32 sai_length;
- __u32 sai_adaption_ind;
+ __u32 sai_adaptation_ind;
sctp_assoc_t sai_assoc_id;
};
@@ -372,7 +374,7 @@ struct sctp_event_subscribe {
__u8 sctp_peer_error_event;
__u8 sctp_shutdown_event;
__u8 sctp_partial_delivery_event;
- __u8 sctp_adaption_layer_event;
+ __u8 sctp_adaptation_layer_event;
};
/*
@@ -393,7 +395,7 @@ union sctp_notification {
struct sctp_remote_error sn_remote_error;
struct sctp_send_failed sn_send_failed;
struct sctp_shutdown_event sn_shutdown_event;
- struct sctp_adaption_event sn_adaption_event;
+ struct sctp_adaptation_event sn_adaptation_event;
struct sctp_pdapi_event sn_pdapi_event;
};
@@ -410,7 +412,7 @@ enum sctp_sn_type {
SCTP_REMOTE_ERROR,
SCTP_SHUTDOWN_EVENT,
SCTP_PARTIAL_DELIVERY_EVENT,
- SCTP_ADAPTION_INDICATION,
+ SCTP_ADAPTATION_INDICATION,
};
/* Notification error codes used to fill up the error fields in some
@@ -486,13 +488,13 @@ struct sctp_prim {
} __attribute__((packed, aligned(4)));
/*
- * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
+ * 7.1.11 Set Adaptation Layer Indicator (SCTP_ADAPTATION_LAYER)
*
- * Requests that the local endpoint set the specified Adaption Layer
+ * Requests that the local endpoint set the specified Adaptation Layer
* Indication parameter for all future INIT and INIT-ACK exchanges.
*/
-struct sctp_setadaption {
- __u32 ssb_adaption_ind;
+struct sctp_setadaptation {
+ __u32 ssb_adaptation_ind;
};
/*
diff --git a/include/net/tcp.h b/include/net/tcp.h
index c99774f15eb..cd8fa0c858a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -244,12 +244,7 @@ static inline int before(__u32 seq1, __u32 seq2)
{
return (__s32)(seq1-seq2) < 0;
}
-
-static inline int after(__u32 seq1, __u32 seq2)
-{
- return (__s32)(seq2-seq1) < 0;
-}
-
+#define after(seq2, seq1) before(seq1, seq2)
/* is s2<=s1<=s3 ? */
static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
diff --git a/include/net/x25.h b/include/net/x25.h
index 0ad90ebcf86..e47fe440d9d 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -259,6 +259,7 @@ extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int
extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
/* x25_timer.c */
+extern void x25_init_timers(struct sock *sk);
extern void x25_start_heartbeat(struct sock *);
extern void x25_start_t2timer(struct sock *);
extern void x25_start_t21timer(struct sock *);
diff --git a/include/rdma/ib_marshall.h b/include/rdma/ib_marshall.h
index 66bf4d7d0df..db037205c9e 100644
--- a/include/rdma/ib_marshall.h
+++ b/include/rdma/ib_marshall.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005 Intel Corporation. All rights reserved.
+ * Copyright (c) 2005-2006 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -41,6 +41,9 @@
void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
struct ib_qp_attr *src);
+void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
+ struct ib_ah_attr *src);
+
void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
struct ib_sa_path_rec *src);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 8eacc351099..0bfa3328d68 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -43,6 +43,8 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
#include <asm/atomic.h>
#include <asm/scatterlist.h>
@@ -848,6 +850,49 @@ struct ib_cache {
u8 *lmc_cache;
};
+struct ib_dma_mapping_ops {
+ int (*mapping_error)(struct ib_device *dev,
+ u64 dma_addr);
+ u64 (*map_single)(struct ib_device *dev,
+ void *ptr, size_t size,
+ enum dma_data_direction direction);
+ void (*unmap_single)(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction);
+ u64 (*map_page)(struct ib_device *dev,
+ struct page *page, unsigned long offset,
+ size_t size,
+ enum dma_data_direction direction);
+ void (*unmap_page)(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction);
+ int (*map_sg)(struct ib_device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction direction);
+ void (*unmap_sg)(struct ib_device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction direction);
+ u64 (*dma_address)(struct ib_device *dev,
+ struct scatterlist *sg);
+ unsigned int (*dma_len)(struct ib_device *dev,
+ struct scatterlist *sg);
+ void (*sync_single_for_cpu)(struct ib_device *dev,
+ u64 dma_handle,
+ size_t size,
+ enum dma_data_direction dir);
+ void (*sync_single_for_device)(struct ib_device *dev,
+ u64 dma_handle,
+ size_t size,
+ enum dma_data_direction dir);
+ void *(*alloc_coherent)(struct ib_device *dev,
+ size_t size,
+ u64 *dma_handle,
+ gfp_t flag);
+ void (*free_coherent)(struct ib_device *dev,
+ size_t size, void *cpu_addr,
+ u64 dma_handle);
+};
+
struct iw_cm_verbs;
struct ib_device {
@@ -992,6 +1037,8 @@ struct ib_device {
struct ib_mad *in_mad,
struct ib_mad *out_mad);
+ struct ib_dma_mapping_ops *dma_ops;
+
struct module *owner;
struct class_device class_dev;
struct kobject ports_parent;
@@ -1395,10 +1442,231 @@ static inline int ib_req_ncomp_notif(struct ib_cq *cq, int wc_cnt)
* usable for DMA.
* @pd: The protection domain associated with the memory region.
* @mr_access_flags: Specifies the memory access rights.
+ *
+ * Note that the ib_dma_*() functions defined below must be used
+ * to create/destroy addresses used with the Lkey or Rkey returned
+ * by ib_get_dma_mr().
*/
struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags);
/**
+ * ib_dma_mapping_error - check a DMA addr for error
+ * @dev: The device for which the dma_addr was created
+ * @dma_addr: The DMA address to check
+ */
+static inline int ib_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->mapping_error(dev, dma_addr);
+ return dma_mapping_error(dma_addr);
+}
+
+/**
+ * ib_dma_map_single - Map a kernel virtual address to DMA address
+ * @dev: The device for which the dma_addr is to be created
+ * @cpu_addr: The kernel virtual address
+ * @size: The size of the region in bytes
+ * @direction: The direction of the DMA
+ */
+static inline u64 ib_dma_map_single(struct ib_device *dev,
+ void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->map_single(dev, cpu_addr, size, direction);
+ return dma_map_single(dev->dma_device, cpu_addr, size, direction);
+}
+
+/**
+ * ib_dma_unmap_single - Destroy a mapping created by ib_dma_map_single()
+ * @dev: The device for which the DMA address was created
+ * @addr: The DMA address
+ * @size: The size of the region in bytes
+ * @direction: The direction of the DMA
+ */
+static inline void ib_dma_unmap_single(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction)
+{
+ if (dev->dma_ops)
+ dev->dma_ops->unmap_single(dev, addr, size, direction);
+ else
+ dma_unmap_single(dev->dma_device, addr, size, direction);
+}
+
+/**
+ * ib_dma_map_page - Map a physical page to DMA address
+ * @dev: The device for which the dma_addr is to be created
+ * @page: The page to be mapped
+ * @offset: The offset within the page
+ * @size: The size of the region in bytes
+ * @direction: The direction of the DMA
+ */
+static inline u64 ib_dma_map_page(struct ib_device *dev,
+ struct page *page,
+ unsigned long offset,
+ size_t size,
+ enum dma_data_direction direction)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->map_page(dev, page, offset, size, direction);
+ return dma_map_page(dev->dma_device, page, offset, size, direction);
+}
+
+/**
+ * ib_dma_unmap_page - Destroy a mapping created by ib_dma_map_page()
+ * @dev: The device for which the DMA address was created
+ * @addr: The DMA address
+ * @size: The size of the region in bytes
+ * @direction: The direction of the DMA
+ */
+static inline void ib_dma_unmap_page(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction)
+{
+ if (dev->dma_ops)
+ dev->dma_ops->unmap_page(dev, addr, size, direction);
+ else
+ dma_unmap_page(dev->dma_device, addr, size, direction);
+}
+
+/**
+ * ib_dma_map_sg - Map a scatter/gather list to DMA addresses
+ * @dev: The device for which the DMA addresses are to be created
+ * @sg: The array of scatter/gather entries
+ * @nents: The number of scatter/gather entries
+ * @direction: The direction of the DMA
+ */
+static inline int ib_dma_map_sg(struct ib_device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->map_sg(dev, sg, nents, direction);
+ return dma_map_sg(dev->dma_device, sg, nents, direction);
+}
+
+/**
+ * ib_dma_unmap_sg - Unmap a scatter/gather list of DMA addresses
+ * @dev: The device for which the DMA addresses were created
+ * @sg: The array of scatter/gather entries
+ * @nents: The number of scatter/gather entries
+ * @direction: The direction of the DMA
+ */
+static inline void ib_dma_unmap_sg(struct ib_device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ if (dev->dma_ops)
+ dev->dma_ops->unmap_sg(dev, sg, nents, direction);
+ else
+ dma_unmap_sg(dev->dma_device, sg, nents, direction);
+}
+
+/**
+ * ib_sg_dma_address - Return the DMA address from a scatter/gather entry
+ * @dev: The device for which the DMA addresses were created
+ * @sg: The scatter/gather entry
+ */
+static inline u64 ib_sg_dma_address(struct ib_device *dev,
+ struct scatterlist *sg)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->dma_address(dev, sg);
+ return sg_dma_address(sg);
+}
+
+/**
+ * ib_sg_dma_len - Return the DMA length from a scatter/gather entry
+ * @dev: The device for which the DMA addresses were created
+ * @sg: The scatter/gather entry
+ */
+static inline unsigned int ib_sg_dma_len(struct ib_device *dev,
+ struct scatterlist *sg)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->dma_len(dev, sg);
+ return sg_dma_len(sg);
+}
+
+/**
+ * ib_dma_sync_single_for_cpu - Prepare DMA region to be accessed by CPU
+ * @dev: The device for which the DMA address was created
+ * @addr: The DMA address
+ * @size: The size of the region in bytes
+ * @dir: The direction of the DMA
+ */
+static inline void ib_dma_sync_single_for_cpu(struct ib_device *dev,
+ u64 addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev->dma_ops)
+ dev->dma_ops->sync_single_for_cpu(dev, addr, size, dir);
+ else
+ dma_sync_single_for_cpu(dev->dma_device, addr, size, dir);
+}
+
+/**
+ * ib_dma_sync_single_for_device - Prepare DMA region to be accessed by device
+ * @dev: The device for which the DMA address was created
+ * @addr: The DMA address
+ * @size: The size of the region in bytes
+ * @dir: The direction of the DMA
+ */
+static inline void ib_dma_sync_single_for_device(struct ib_device *dev,
+ u64 addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ if (dev->dma_ops)
+ dev->dma_ops->sync_single_for_device(dev, addr, size, dir);
+ else
+ dma_sync_single_for_device(dev->dma_device, addr, size, dir);
+}
+
+/**
+ * ib_dma_alloc_coherent - Allocate memory and map it for DMA
+ * @dev: The device for which the DMA address is requested
+ * @size: The size of the region to allocate in bytes
+ * @dma_handle: A pointer for returning the DMA address of the region
+ * @flag: memory allocator flags
+ */
+static inline void *ib_dma_alloc_coherent(struct ib_device *dev,
+ size_t size,
+ u64 *dma_handle,
+ gfp_t flag)
+{
+ if (dev->dma_ops)
+ return dev->dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+ else {
+ dma_addr_t handle;
+ void *ret;
+
+ ret = dma_alloc_coherent(dev->dma_device, size, &handle, flag);
+ *dma_handle = handle;
+ return ret;
+ }
+}
+
+/**
+ * ib_dma_free_coherent - Free memory allocated by ib_dma_alloc_coherent()
+ * @dev: The device for which the DMA addresses were allocated
+ * @size: The size of the region
+ * @cpu_addr: the address returned by ib_dma_alloc_coherent()
+ * @dma_handle: the DMA address returned by ib_dma_alloc_coherent()
+ */
+static inline void ib_dma_free_coherent(struct ib_device *dev,
+ size_t size, void *cpu_addr,
+ u64 dma_handle)
+{
+ if (dev->dma_ops)
+ dev->dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+ else
+ dma_free_coherent(dev->dma_device, size, cpu_addr, dma_handle);
+}
+
+/**
* ib_reg_phys_mr - Prepares a virtually addressed memory region for use
* by an HCA.
* @pd: The protection domain associated assigned to the registered region.
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index deb5a0a4cee..36cd8a8526a 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -77,11 +77,34 @@ struct rdma_route {
int num_paths;
};
+struct rdma_conn_param {
+ const void *private_data;
+ u8 private_data_len;
+ u8 responder_resources;
+ u8 initiator_depth;
+ u8 flow_control;
+ u8 retry_count; /* ignored when accepting */
+ u8 rnr_retry_count;
+ /* Fields below ignored if a QP is created on the rdma_cm_id. */
+ u8 srq;
+ u32 qp_num;
+};
+
+struct rdma_ud_param {
+ const void *private_data;
+ u8 private_data_len;
+ struct ib_ah_attr ah_attr;
+ u32 qp_num;
+ u32 qkey;
+};
+
struct rdma_cm_event {
enum rdma_cm_event_type event;
int status;
- void *private_data;
- u8 private_data_len;
+ union {
+ struct rdma_conn_param conn;
+ struct rdma_ud_param ud;
+ } param;
};
struct rdma_cm_id;
@@ -204,25 +227,17 @@ void rdma_destroy_qp(struct rdma_cm_id *id);
int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
int *qp_attr_mask);
-struct rdma_conn_param {
- const void *private_data;
- u8 private_data_len;
- u8 responder_resources;
- u8 initiator_depth;
- u8 flow_control;
- u8 retry_count; /* ignored when accepting */
- u8 rnr_retry_count;
- /* Fields below ignored if a QP is created on the rdma_cm_id. */
- u8 srq;
- u32 qp_num;
- enum ib_qp_type qp_type;
-};
-
/**
* rdma_connect - Initiate an active connection request.
+ * @id: Connection identifier to connect.
+ * @conn_param: Connection information used for connected QPs.
*
* Users must have resolved a route for the rdma_cm_id to connect with
* by having called rdma_resolve_route before calling this routine.
+ *
+ * This call will either connect to a remote QP or obtain remote QP
+ * information for unconnected rdma_cm_id's. The actual operation is
+ * based on the rdma_cm_id's port space.
*/
int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
@@ -253,6 +268,21 @@ int rdma_listen(struct rdma_cm_id *id, int backlog);
int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
/**
+ * rdma_notify - Notifies the RDMA CM of an asynchronous event that has
+ * occurred on the connection.
+ * @id: Connection identifier to transition to established.
+ * @event: Asynchronous event.
+ *
+ * This routine should be invoked by users to notify the CM of relevant
+ * communication events. Events that should be reported to the CM and
+ * when to report them are:
+ *
+ * IB_EVENT_COMM_EST - Used when a message is received on a connected
+ * QP before an RTU has been received.
+ */
+int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event);
+
+/**
* rdma_reject - Called to reject a connection request or response.
*/
int rdma_reject(struct rdma_cm_id *id, const void *private_data,
diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h
index e8c3af1804d..9b176df1d66 100644
--- a/include/rdma/rdma_cm_ib.h
+++ b/include/rdma/rdma_cm_ib.h
@@ -44,4 +44,7 @@
int rdma_set_ib_paths(struct rdma_cm_id *id,
struct ib_sa_path_rec *path_rec, int num_paths);
+/* Global qkey for UD QPs and multicast groups. */
+#define RDMA_UD_QKEY 0x01234567
+
#endif /* RDMA_CM_IB_H */
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
new file mode 100644
index 00000000000..9572ab8eeac
--- /dev/null
+++ b/include/rdma/rdma_user_cm.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2005-2006 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RDMA_USER_CM_H
+#define RDMA_USER_CM_H
+
+#include <linux/types.h>
+#include <linux/in6.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_user_sa.h>
+
+#define RDMA_USER_CM_ABI_VERSION 3
+
+#define RDMA_MAX_PRIVATE_DATA 256
+
+enum {
+ RDMA_USER_CM_CMD_CREATE_ID,
+ RDMA_USER_CM_CMD_DESTROY_ID,
+ RDMA_USER_CM_CMD_BIND_ADDR,
+ RDMA_USER_CM_CMD_RESOLVE_ADDR,
+ RDMA_USER_CM_CMD_RESOLVE_ROUTE,
+ RDMA_USER_CM_CMD_QUERY_ROUTE,
+ RDMA_USER_CM_CMD_CONNECT,
+ RDMA_USER_CM_CMD_LISTEN,
+ RDMA_USER_CM_CMD_ACCEPT,
+ RDMA_USER_CM_CMD_REJECT,
+ RDMA_USER_CM_CMD_DISCONNECT,
+ RDMA_USER_CM_CMD_INIT_QP_ATTR,
+ RDMA_USER_CM_CMD_GET_EVENT,
+ RDMA_USER_CM_CMD_GET_OPTION,
+ RDMA_USER_CM_CMD_SET_OPTION,
+ RDMA_USER_CM_CMD_NOTIFY
+};
+
+/*
+ * command ABI structures.
+ */
+struct rdma_ucm_cmd_hdr {
+ __u32 cmd;
+ __u16 in;
+ __u16 out;
+};
+
+struct rdma_ucm_create_id {
+ __u64 uid;
+ __u64 response;
+ __u16 ps;
+ __u8 reserved[6];
+};
+
+struct rdma_ucm_create_id_resp {
+ __u32 id;
+};
+
+struct rdma_ucm_destroy_id {
+ __u64 response;
+ __u32 id;
+ __u32 reserved;
+};
+
+struct rdma_ucm_destroy_id_resp {
+ __u32 events_reported;
+};
+
+struct rdma_ucm_bind_addr {
+ __u64 response;
+ struct sockaddr_in6 addr;
+ __u32 id;
+};
+
+struct rdma_ucm_resolve_addr {
+ struct sockaddr_in6 src_addr;
+ struct sockaddr_in6 dst_addr;
+ __u32 id;
+ __u32 timeout_ms;
+};
+
+struct rdma_ucm_resolve_route {
+ __u32 id;
+ __u32 timeout_ms;
+};
+
+struct rdma_ucm_query_route {
+ __u64 response;
+ __u32 id;
+ __u32 reserved;
+};
+
+struct rdma_ucm_query_route_resp {
+ __u64 node_guid;
+ struct ib_user_path_rec ib_route[2];
+ struct sockaddr_in6 src_addr;
+ struct sockaddr_in6 dst_addr;
+ __u32 num_paths;
+ __u8 port_num;
+ __u8 reserved[3];
+};
+
+struct rdma_ucm_conn_param {
+ __u32 qp_num;
+ __u32 reserved;
+ __u8 private_data[RDMA_MAX_PRIVATE_DATA];
+ __u8 private_data_len;
+ __u8 srq;
+ __u8 responder_resources;
+ __u8 initiator_depth;
+ __u8 flow_control;
+ __u8 retry_count;
+ __u8 rnr_retry_count;
+ __u8 valid;
+};
+
+struct rdma_ucm_ud_param {
+ __u32 qp_num;
+ __u32 qkey;
+ struct ib_uverbs_ah_attr ah_attr;
+ __u8 private_data[RDMA_MAX_PRIVATE_DATA];
+ __u8 private_data_len;
+ __u8 reserved[7];
+};
+
+struct rdma_ucm_connect {
+ struct rdma_ucm_conn_param conn_param;
+ __u32 id;
+ __u32 reserved;
+};
+
+struct rdma_ucm_listen {
+ __u32 id;
+ __u32 backlog;
+};
+
+struct rdma_ucm_accept {
+ __u64 uid;
+ struct rdma_ucm_conn_param conn_param;
+ __u32 id;
+ __u32 reserved;
+};
+
+struct rdma_ucm_reject {
+ __u32 id;
+ __u8 private_data_len;
+ __u8 reserved[3];
+ __u8 private_data[RDMA_MAX_PRIVATE_DATA];
+};
+
+struct rdma_ucm_disconnect {
+ __u32 id;
+};
+
+struct rdma_ucm_init_qp_attr {
+ __u64 response;
+ __u32 id;
+ __u32 qp_state;
+};
+
+struct rdma_ucm_notify {
+ __u32 id;
+ __u32 event;
+};
+
+struct rdma_ucm_get_event {
+ __u64 response;
+};
+
+struct rdma_ucm_event_resp {
+ __u64 uid;
+ __u32 id;
+ __u32 event;
+ __u32 status;
+ union {
+ struct rdma_ucm_conn_param conn;
+ struct rdma_ucm_ud_param ud;
+ } param;
+};
+
+#endif /* RDMA_USER_CM_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index a994bea09cd..521f036cce9 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -132,8 +132,10 @@ struct snd_card {
int shutdown; /* this card is going down */
int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep;
- struct device *parent;
- struct device *dev;
+ struct device *dev; /* device assigned to this card */
+#ifndef CONFIG_SYSFS_DEPRECATED
+ struct device *card_dev; /* cardX object for sysfs */
+#endif
#ifdef CONFIG_PM
unsigned int power_state; /* power state */
@@ -191,6 +193,16 @@ struct snd_minor {
struct device *dev; /* device for sysfs */
};
+/* return a device pointer linked to each sound device as a parent */
+static inline struct device *snd_card_get_device_link(struct snd_card *card)
+{
+#ifdef CONFIG_SYSFS_DEPRECATED
+ return card ? card->dev : NULL;
+#else
+ return card ? card->card_dev : NULL;
+#endif
+}
+
/* sound.c */
extern int snd_major;
@@ -257,7 +269,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
int snd_card_file_remove(struct snd_card *card, struct file *file);
#ifndef snd_card_set_dev
-#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr))
+#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
#endif
/* device.c */
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index c854647b6f3..1cd4f64cdf3 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -56,6 +56,7 @@ struct snd_pcm_oss_runtime {
size_t mmap_bytes;
char *buffer; /* vmallocated period */
size_t buffer_used; /* used length from period buffer */
+ struct mutex params_lock;
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
struct snd_pcm_plugin *plugin_first;
struct snd_pcm_plugin *plugin_last;
diff --git a/include/sound/version.h b/include/sound/version.h
index 17137f3a3b6..20f7babad51 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by alsa/ksync script. */
-#define CONFIG_SND_VERSION "1.0.13"
-#define CONFIG_SND_DATE " (Tue Nov 28 14:07:24 2006 UTC)"
+#define CONFIG_SND_VERSION "1.0.14rc1"
+#define CONFIG_SND_DATE " (Tue Jan 09 09:56:17 2007 UTC)"
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index d41cda97e95..f3514ee96bd 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -286,7 +286,7 @@ struct snd_ymfpci {
int irq;
unsigned int device_id; /* PCI device ID */
- unsigned int rev; /* PCI revision */
+ unsigned char rev; /* PCI revision */
unsigned long reg_area_phys;
void __iomem *reg_area_virt;
struct resource *res_reg_area;
@@ -345,7 +345,6 @@ struct snd_ymfpci {
struct snd_kcontrol *spdif_pcm_ctl;
int mode_dup4ch;
int rear_opened;
- int rear_swap;
int spdif_opened;
struct {
u16 left;
@@ -378,7 +377,7 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
-int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch, int rear_swap);
+int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch);
int snd_ymfpci_timer(struct snd_ymfpci *chip, int device);
#endif /* __SOUND_YMFPCI_H */
diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h
index 3bde0f5cd55..20b9002712e 100644
--- a/include/video/mbxfb.h
+++ b/include/video/mbxfb.h
@@ -1,6 +1,9 @@
#ifndef __MBX_FB_H
#define __MBX_FB_H
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
struct mbxfb_val {
unsigned int defval;
unsigned int min;
@@ -25,4 +28,32 @@ struct mbxfb_platform_data {
int (*remove)(struct fb_info *fb);
};
+/* planar */
+#define MBXFB_FMT_YUV12 0
+
+/* packed */
+#define MBXFB_FMT_UY0VY1 1
+#define MBXFB_FMT_VY0UY1 2
+#define MBXFB_FMT_Y0UY1V 3
+#define MBXFB_FMT_Y0VY1U 4
+struct mbxfb_overlaySetup {
+ __u32 enable;
+ __u32 x, y;
+ __u32 width, height;
+ __u32 alpha;
+ __u32 fmt;
+ __u32 mem_offset;
+ __u32 scaled_width;
+ __u32 scaled_height;
+
+ /* Filled by the driver */
+ __u32 U_offset;
+ __u32 V_offset;
+
+ __u16 Y_stride;
+ __u16 UV_stride;
+};
+
+#define MBXFB_IOCX_OVERLAY _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup)
+
#endif /* __MBX_FB_H */
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index ac021379ac4..94c7d2da90e 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -607,16 +607,16 @@
#define PM3FBDestReadModeOr 0xac98
#define PM3FBDestReadMode_ReadDisable 0<<0
#define PM3FBDestReadMode_ReadEnable 1<<0
- #define PM3FBDestReadMode_StripePitch(sp) (((sp)&0x7)<<2
- #define PM3FBDestReadMode_StripeHeight(sh) (((sh)&0x7)<<7
+ #define PM3FBDestReadMode_StripePitch(sp) (((sp)&0x7)<<2)
+ #define PM3FBDestReadMode_StripeHeight(sh) (((sh)&0x7)<<7)
#define PM3FBDestReadMode_Enable0 1<<8
#define PM3FBDestReadMode_Enable1 1<<9
#define PM3FBDestReadMode_Enable2 1<<10
#define PM3FBDestReadMode_Enable3 1<<11
- #define PM3FBDestReadMode_Layout0(l) (((l)&0x3)<<12
- #define PM3FBDestReadMode_Layout1(l) (((l)&0x3)<<14
- #define PM3FBDestReadMode_Layout2(l) (((l)&0x3)<<16
- #define PM3FBDestReadMode_Layout3(l) (((l)&0x3)<<18
+ #define PM3FBDestReadMode_Layout0(l) (((l)&0x3)<<12)
+ #define PM3FBDestReadMode_Layout1(l) (((l)&0x3)<<14)
+ #define PM3FBDestReadMode_Layout2(l) (((l)&0x3)<<16)
+ #define PM3FBDestReadMode_Layout3(l) (((l)&0x3)<<18)
#define PM3FBDestReadMode_Origin0 1<<20
#define PM3FBDestReadMode_Origin1 1<<21
#define PM3FBDestReadMode_Origin2 1<<22
@@ -640,16 +640,16 @@
#define PM3FBSourceReadModeOr 0xaca8
#define PM3FBSourceReadMode_ReadDisable (0<<0)
#define PM3FBSourceReadMode_ReadEnable (1<<0)
- #define PM3FBSourceReadMode_StripePitch(sp) (((sp)&0x7)<<2
- #define PM3FBSourceReadMode_StripeHeight(sh) (((sh)&0x7)<<7
- #define PM3FBSourceReadMode_Layout(l) (((l)&0x3)<<8
+ #define PM3FBSourceReadMode_StripePitch(sp) (((sp)&0x7)<<2)
+ #define PM3FBSourceReadMode_StripeHeight(sh) (((sh)&0x7)<<7)
+ #define PM3FBSourceReadMode_Layout(l) (((l)&0x3)<<8)
#define PM3FBSourceReadMode_Origin 1<<10
#define PM3FBSourceReadMode_Blocking 1<<11
#define PM3FBSourceReadMode_UserTexelCoord 1<<13
#define PM3FBSourceReadMode_WrapXEnable 1<<14
#define PM3FBSourceReadMode_WrapYEnable 1<<15
- #define PM3FBSourceReadMode_WrapX(w) (((w)&0xf)<<16
- #define PM3FBSourceReadMode_WrapY(w) (((w)&0xf)<<20
+ #define PM3FBSourceReadMode_WrapX(w) (((w)&0xf)<<16)
+ #define PM3FBSourceReadMode_WrapY(w) (((w)&0xf)<<20)
#define PM3FBSourceReadMode_ExternalSourceData 1<<24
#define PM3FBWriteBufferAddr0 0xb000
#define PM3FBWriteBufferAddr1 0xb008
@@ -942,7 +942,7 @@
#define PM3Window 0x8980
#define PM3Window_ForceLBUpdate 1<<3
#define PM3Window_LBUpdateSource 1<<4
- #define PM3Window_FrameCount(c) (((c)&0xff)<<9
+ #define PM3Window_FrameCount(c) (((c)&0xff)<<9)
#define PM3Window_StencilFCP 1<<17
#define PM3Window_DepthFCP 1<<18
#define PM3Window_OverrideWriteFiltering 1<<19
diff --git a/include/video/sstfb.h b/include/video/sstfb.h
index 5dbf5e7e50a..baa163f770a 100644
--- a/include/video/sstfb.h
+++ b/include/video/sstfb.h
@@ -119,7 +119,7 @@
#define BACKPORCH 0x0208
#define VIDEODIMENSIONS 0x020c
#define FBIINIT0 0x0210 /* misc+fifo controls */
-# define EN_VGA_PASSTHROUGH BIT(0)
+# define DIS_VGA_PASSTHROUGH BIT(0)
# define FBI_RESET BIT(1)
# define FIFO_RESET BIT(2)
#define FBIINIT1 0x0214 /* PCI + video controls */
@@ -251,7 +251,7 @@
# define DACREG_ICS_CLK1_A 0 /* bit4 */
/* sst default init registers */
-#define FBIINIT0_DEFAULT EN_VGA_PASSTHROUGH
+#define FBIINIT0_DEFAULT DIS_VGA_PASSTHROUGH
#define FBIINIT1_DEFAULT \
( \
@@ -296,6 +296,11 @@
*
*/
+/* ioctl to enable/disable VGA passthrough */
+#define SSTFB_SET_VGAPASS _IOW('F', 0xdd, __u32)
+#define SSTFB_GET_VGAPASS _IOR('F', 0xdd, __u32)
+
+
/* used to know witch clock to set */
enum {
VID_CLOCK=0,
@@ -317,7 +322,7 @@ struct pll_timing {
};
struct dac_switch {
- char * name;
+ const char *name;
int (*detect) (struct fb_info *info);
int (*set_pll) (struct fb_info *info, const struct pll_timing *t, const int clock);
void (*set_vidmod) (struct fb_info *info, const int bpp);
@@ -345,7 +350,7 @@ struct sstfb_par {
struct pci_dev *dev;
int type;
u8 revision;
- int gfx_clock; /* status */
+ u8 vgapass; /* VGA pass through: 1=enabled, 0=disabled */
};
#endif /* _SSTFB_H_ */
diff --git a/init/Kconfig b/init/Kconfig
index 14d484606fa..a3f83e2c825 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -304,6 +304,15 @@ config TASK_XACCT
Say N if unsure.
+config TASK_IO_ACCOUNTING
+ bool "Enable per-task storage I/O accounting (EXPERIMENTAL)"
+ depends on TASK_XACCT
+ help
+ Collect information on the number of bytes of storage I/O which this
+ task has caused.
+
+ Say N if unsure.
+
config SYSCTL
bool
@@ -339,7 +348,7 @@ config SYSCTL_SYSCALL
If unsure say Y here.
config KALLSYMS
- bool "Load all symbols for debugging/kksymoops" if EMBEDDED
+ bool "Load all symbols for debugging/ksymoops" if EMBEDDED
default y
help
Say Y here to let the kernel print out symbolic crash information and
@@ -441,7 +450,7 @@ config SHMEM
config SLAB
default y
- bool "Use full SLAB allocator" if EMBEDDED
+ bool "Use full SLAB allocator" if (EMBEDDED && !SMP && !SPARSEMEM)
help
Disabling this replaces the advanced SLAB allocator and
kmalloc support with the drastically simpler SLOB allocator.
@@ -452,10 +461,10 @@ config VM_EVENT_COUNTERS
default y
bool "Enable VM event counters for /proc/vmstat" if EMBEDDED
help
- VM event counters are only needed to for event counts to be
- shown. They have no function for the kernel itself. This
- option allows the disabling of the VM event counters.
- /proc/vmstat will only show page counts.
+ VM event counters are needed for event counts to be shown.
+ This option allows the disabling of the VM event counters
+ on EMBEDDED systems. /proc/vmstat will only show page counts
+ if VM event counters are disabled.
endmenu # General setup
diff --git a/init/initramfs.c b/init/initramfs.c
index 85f04037ade..4fa0f7977de 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -526,7 +526,7 @@ static void __init free_initrd(void)
#endif
-void __init populate_rootfs(void)
+static int __init populate_rootfs(void)
{
char *err = unpack_to_rootfs(__initramfs_start,
__initramfs_end - __initramfs_start, 0);
@@ -544,7 +544,7 @@ void __init populate_rootfs(void)
unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start, 0);
free_initrd();
- return;
+ return 0;
}
printk("it isn't (%s); looks like an initrd\n", err);
fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
@@ -565,4 +565,6 @@ void __init populate_rootfs(void)
#endif
}
#endif
+ return 0;
}
+rootfs_initcall(populate_rootfs);
diff --git a/init/main.c b/init/main.c
index 1174ae3aec8..8b4a7d76916 100644
--- a/init/main.c
+++ b/init/main.c
@@ -50,6 +50,8 @@
#include <linux/buffer_head.h>
#include <linux/debug_locks.h>
#include <linux/lockdep.h>
+#include <linux/pid_namespace.h>
+#include <linux/device.h>
#include <asm/io.h>
#include <asm/bugs.h>
@@ -91,8 +93,6 @@ extern void pidmap_init(void);
extern void prio_tree_init(void);
extern void radix_tree_init(void);
extern void free_initmem(void);
-extern void populate_rootfs(void);
-extern void driver_init(void);
extern void prepare_namespace(void);
#ifdef CONFIG_ACPI
extern void acpi_early_init(void);
@@ -530,6 +530,11 @@ asmlinkage void __init start_kernel(void)
parse_args("Booting kernel", command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
+ if (!irqs_disabled()) {
+ printk(KERN_WARNING "start_kernel(): bug: interrupts were "
+ "enabled *very* early, fixing it\n");
+ local_irq_disable();
+ }
sort_main_extable();
trap_init();
rcu_init();
@@ -624,8 +629,6 @@ static int __init initcall_debug_setup(char *str)
}
__setup("initcall_debug", initcall_debug_setup);
-struct task_struct *child_reaper = &init_task;
-
extern initcall_t __initcall_start[], __initcall_end[];
static void __init do_initcalls(void)
@@ -692,7 +695,7 @@ static void __init do_basic_setup(void)
do_initcalls();
}
-static void do_pre_smp_initcalls(void)
+static void __init do_pre_smp_initcalls(void)
{
extern int spawn_ksoftirqd(void);
#ifdef CONFIG_SMP
@@ -725,7 +728,7 @@ static int init(void * unused)
* assumptions about where in the task array this
* can be found.
*/
- child_reaper = current;
+ init_pid_ns.child_reaper = current;
cad_pid = task_pid(current);
@@ -738,12 +741,6 @@ static int init(void * unused)
cpuset_init_smp();
- /*
- * Do this before initcalls, because some drivers want to access
- * firmware files.
- */
- populate_rootfs();
-
do_basic_setup();
/*
diff --git a/init/version.c b/init/version.c
index 8f28344d9c7..6c01ec1cc48 100644
--- a/init/version.c
+++ b/init/version.c
@@ -34,6 +34,12 @@ struct uts_namespace init_uts_ns = {
};
EXPORT_SYMBOL_GPL(init_uts_ns);
+/* FIXED STRINGS! Don't touch! */
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+const char linux_proc_banner[] =
+ "%s version %s"
+ " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
+ " (" LINUX_COMPILER ") %s\n";
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 3acc1661e51..02717f71d8d 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -322,7 +322,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
size_t count, loff_t * off)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
char buffer[FILENT_SIZE];
size_t slen;
loff_t o;
@@ -354,13 +354,13 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
return -EFAULT;
*off = o + count;
- filp->f_dentry->d_inode->i_atime = filp->f_dentry->d_inode->i_ctime = CURRENT_TIME;
+ filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME;
return count;
}
static int mqueue_flush_file(struct file *filp, fl_owner_t id)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
spin_lock(&info->lock);
if (task_tgid(current) == info->notify_owner)
@@ -372,7 +372,7 @@ static int mqueue_flush_file(struct file *filp, fl_owner_t id)
static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
int retval = 0;
poll_wait(filp, &info->wait_q, poll_tab);
@@ -836,7 +836,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
if (unlikely(!filp))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@ -919,7 +919,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
if (unlikely(!filp))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@ -1056,7 +1056,7 @@ retry:
if (!filp)
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@ -1126,7 +1126,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
if (!filp)
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 0992616eeed..c82c215693d 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -36,7 +36,7 @@ struct msg_msg *load_msg(const void __user *src, int len)
if (alen > DATALEN_MSG)
alen = DATALEN_MSG;
- msg = (struct msg_msg *)kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
+ msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
if (msg == NULL)
return ERR_PTR(-ENOMEM);
@@ -56,7 +56,7 @@ struct msg_msg *load_msg(const void __user *src, int len)
alen = len;
if (alen > DATALEN_SEG)
alen = DATALEN_SEG;
- seg = (struct msg_msgseg *)kmalloc(sizeof(*seg) + alen,
+ seg = kmalloc(sizeof(*seg) + alen,
GFP_KERNEL);
if (seg == NULL) {
err = -ENOMEM;
diff --git a/ipc/shm.c b/ipc/shm.c
index d1198dd07a1..f8e10a25ad7 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -168,7 +168,7 @@ static inline void shm_inc(struct ipc_namespace *ns, int id)
static void shm_open(struct vm_area_struct *shmd)
{
shm_inc(shm_file_ns(shmd->vm_file),
- shmd->vm_file->f_dentry->d_inode->i_ino);
+ shmd->vm_file->f_path.dentry->d_inode->i_ino);
}
/*
@@ -187,7 +187,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 0, shp->mlock_user);
else
- user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
+ user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
shp->mlock_user);
fput (shp->shm_file);
security_shm_free(shp);
@@ -203,7 +203,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
static void shm_close (struct vm_area_struct *shmd)
{
struct file * file = shmd->vm_file;
- int id = file->f_dentry->d_inode->i_ino;
+ int id = file->f_path.dentry->d_inode->i_ino;
struct shmid_kernel *shp;
struct ipc_namespace *ns;
@@ -233,7 +233,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
vma->vm_ops = &shm_vm_ops;
if (!(vma->vm_flags & VM_WRITE))
vma->vm_flags &= ~VM_MAYWRITE;
- shm_inc(shm_file_ns(file), file->f_dentry->d_inode->i_ino);
+ shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino);
}
return ret;
@@ -279,7 +279,7 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
if (size < SHMMIN || size > ns->shm_ctlmax)
return -EINVAL;
- if (ns->shm_tot + numpages >= ns->shm_ctlall)
+ if (ns->shm_tot + numpages > ns->shm_ctlall)
return -ENOSPC;
shp = ipc_rcu_alloc(sizeof(*shp));
@@ -330,7 +330,7 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
shp->shm_nattch = 0;
shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
shp->shm_file = file;
- file->f_dentry->d_inode->i_ino = shp->id;
+ file->f_path.dentry->d_inode->i_ino = shp->id;
shm_file_ns(file) = get_ipc_ns(ns);
@@ -495,7 +495,7 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
if(!shp)
continue;
- inode = shp->shm_file->f_dentry->d_inode;
+ inode = shp->shm_file->f_path.dentry->d_inode;
if (is_file_hugepages(shp->shm_file)) {
struct address_space *mapping = inode->i_mapping;
@@ -843,7 +843,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
}
file = shp->shm_file;
- size = i_size_read(file->f_dentry->d_inode);
+ size = i_size_read(file->f_path.dentry->d_inode);
shp->shm_nattch++;
shm_unlock(shp);
@@ -948,7 +948,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
- size = vma->vm_file->f_dentry->d_inode->i_size;
+ size = vma->vm_file->f_path.dentry->d_inode->i_size;
do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
/*
* We discovered the size of the shm segment, so
diff --git a/kernel/Makefile b/kernel/Makefile
index 5e3f3b75563..14f4d45e0ae 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
-obj-$(CONFIG_STACK_UNWIND) += unwind.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
diff --git a/kernel/acct.c b/kernel/acct.c
index dc12db8600e..70d0d88e555 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -118,7 +118,7 @@ static int check_free_space(struct file *file)
spin_unlock(&acct_globals.lock);
/* May block */
- if (vfs_statfs(file->f_dentry, &sbuf))
+ if (vfs_statfs(file->f_path.dentry, &sbuf))
return res;
suspend = sbuf.f_blocks * SUSPEND;
resume = sbuf.f_blocks * RESUME;
@@ -194,7 +194,7 @@ static void acct_file_reopen(struct file *file)
add_timer(&acct_globals.timer);
}
if (old_acct) {
- mnt_unpin(old_acct->f_vfsmnt);
+ mnt_unpin(old_acct->f_path.mnt);
spin_unlock(&acct_globals.lock);
do_acct_process(old_acct);
filp_close(old_acct, NULL);
@@ -212,7 +212,7 @@ static int acct_on(char *name)
if (IS_ERR(file))
return PTR_ERR(file);
- if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
+ if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
filp_close(file, NULL);
return -EACCES;
}
@@ -229,11 +229,11 @@ static int acct_on(char *name)
}
spin_lock(&acct_globals.lock);
- mnt_pin(file->f_vfsmnt);
+ mnt_pin(file->f_path.mnt);
acct_file_reopen(file);
spin_unlock(&acct_globals.lock);
- mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */
+ mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
return 0;
}
@@ -283,7 +283,7 @@ asmlinkage long sys_acct(const char __user *name)
void acct_auto_close_mnt(struct vfsmount *m)
{
spin_lock(&acct_globals.lock);
- if (acct_globals.file && acct_globals.file->f_vfsmnt == m)
+ if (acct_globals.file && acct_globals.file->f_path.mnt == m)
acct_file_reopen(NULL);
spin_unlock(&acct_globals.lock);
}
@@ -299,7 +299,7 @@ void acct_auto_close(struct super_block *sb)
{
spin_lock(&acct_globals.lock);
if (acct_globals.file &&
- acct_globals.file->f_vfsmnt->mnt_sb == sb) {
+ acct_globals.file->f_path.mnt->mnt_sb == sb) {
acct_file_reopen(NULL);
}
spin_unlock(&acct_globals.lock);
@@ -428,6 +428,7 @@ static void do_acct_process(struct file *file)
u64 elapsed;
u64 run_time;
struct timespec uptime;
+ struct tty_struct *tty;
/*
* First check to see if there is enough free_space to continue
@@ -484,16 +485,9 @@ static void do_acct_process(struct file *file)
ac.ac_ppid = current->parent->tgid;
#endif
- mutex_lock(&tty_mutex);
- /* FIXME: Whoever is responsible for current->signal locking needs
- to use the same locking all over the kernel and document it */
- read_lock(&tasklist_lock);
- ac.ac_tty = current->signal->tty ?
- old_encode_dev(tty_devnum(current->signal->tty)) : 0;
- read_unlock(&tasklist_lock);
- mutex_unlock(&tty_mutex);
-
spin_lock_irq(&current->sighand->siglock);
+ tty = current->signal->tty;
+ ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0;
ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime)));
ac.ac_flag = pacct->ac_flag;
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 2e896f8ae29..9c8c23227c7 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -800,8 +800,8 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
/* our own copy of se_str */
se_str = kstrdup(sf->se_str, GFP_KERNEL);
- if (unlikely(IS_ERR(se_str)))
- return -ENOMEM;
+ if (unlikely(!se_str))
+ return -ENOMEM;
df->se_str = se_str;
/* our own (refreshed) copy of se_rule */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 40722e26de9..298897559ca 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -781,8 +781,8 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
if ((vma->vm_flags & VM_EXECUTABLE) &&
vma->vm_file) {
audit_log_d_path(ab, "exe=",
- vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
+ vma->vm_file->f_path.dentry,
+ vma->vm_file->f_path.mnt);
break;
}
vma = vma->vm_next;
@@ -826,10 +826,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
context->return_code);
mutex_lock(&tty_mutex);
+ read_lock(&tasklist_lock);
if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
tty = tsk->signal->tty->name;
else
tty = "(none)";
+ read_unlock(&tasklist_lock);
audit_log_format(ab,
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
" ppid=%d pid=%d auid=%u uid=%u gid=%u"
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 9124669f458..7406fe6966f 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -204,7 +204,7 @@ int cpu_down(unsigned int cpu)
#endif /*CONFIG_HOTPLUG_CPU*/
/* Requires cpu_add_remove_lock to be held */
-static int __devinit _cpu_up(unsigned int cpu)
+static int __cpuinit _cpu_up(unsigned int cpu)
{
int ret;
void *hcpu = (void *)(long)cpu;
@@ -239,7 +239,7 @@ out_notify:
return ret;
}
-int __devinit cpu_up(unsigned int cpu)
+int __cpuinit cpu_up(unsigned int cpu)
{
int err = 0;
@@ -258,7 +258,7 @@ static cpumask_t frozen_cpus;
int disable_nonboot_cpus(void)
{
- int cpu, first_cpu, error;
+ int cpu, first_cpu, error = 0;
mutex_lock(&cpu_add_remove_lock);
first_cpu = first_cpu(cpu_present_map);
@@ -294,7 +294,7 @@ int disable_nonboot_cpus(void)
/* Make sure the CPUs won't be enabled by someone else */
cpu_hotplug_disabled = 1;
} else {
- printk(KERN_ERR "Non-boot CPUs are not disabled");
+ printk(KERN_ERR "Non-boot CPUs are not disabled\n");
}
out:
mutex_unlock(&cpu_add_remove_lock);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 0a6b4d89f9a..6b05dc69c95 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -413,8 +413,8 @@ static struct file_system_type cpuset_fs_type = {
*
*
* 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
+ * - the cpuset to use in file->f_path.dentry->d_parent->d_fsdata
+ * - the 'cftype' of the file is file->f_path.dentry->d_fsdata
*/
struct cftype {
@@ -1284,8 +1284,8 @@ static ssize_t cpuset_common_file_write(struct file *file,
const char __user *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);
+ struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
+ struct cftype *cft = __d_cft(file->f_path.dentry);
cpuset_filetype_t type = cft->private;
char *buffer;
char *pathbuf = NULL;
@@ -1367,7 +1367,7 @@ static ssize_t cpuset_file_write(struct file *file, const char __user *buf,
size_t nbytes, loff_t *ppos)
{
ssize_t retval = 0;
- struct cftype *cft = __d_cft(file->f_dentry);
+ struct cftype *cft = __d_cft(file->f_path.dentry);
if (!cft)
return -ENODEV;
@@ -1417,8 +1417,8 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
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);
+ struct cftype *cft = __d_cft(file->f_path.dentry);
+ struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
cpuset_filetype_t type = cft->private;
char *page;
ssize_t retval = 0;
@@ -1476,7 +1476,7 @@ static ssize_t cpuset_file_read(struct file *file, char __user *buf, size_t nbyt
loff_t *ppos)
{
ssize_t retval = 0;
- struct cftype *cft = __d_cft(file->f_dentry);
+ struct cftype *cft = __d_cft(file->f_path.dentry);
if (!cft)
return -ENODEV;
@@ -1498,7 +1498,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file)
if (err)
return err;
- cft = __d_cft(file->f_dentry);
+ cft = __d_cft(file->f_path.dentry);
if (!cft)
return -ENODEV;
if (cft->open)
@@ -1511,7 +1511,7 @@ static int cpuset_file_open(struct inode *inode, struct file *file)
static int cpuset_file_release(struct inode *inode, struct file *file)
{
- struct cftype *cft = __d_cft(file->f_dentry);
+ struct cftype *cft = __d_cft(file->f_path.dentry);
if (cft->release)
return cft->release(inode, file);
return 0;
@@ -1700,7 +1700,7 @@ static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
*/
static int cpuset_tasks_open(struct inode *unused, struct file *file)
{
- struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+ struct cpuset *cs = __d_cs(file->f_path.dentry->d_parent);
struct ctr_struct *ctr;
pid_t *pidarray;
int npids;
@@ -2342,32 +2342,48 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
}
/**
- * cpuset_zone_allowed - Can we allocate memory on zone z's memory node?
+ * cpuset_zone_allowed_softwall - Can we allocate on zone z's memory node?
* @z: is this zone on an allowed node?
- * @gfp_mask: memory allocation flags (we use __GFP_HARDWALL)
+ * @gfp_mask: memory allocation flags
*
- * If we're in interrupt, yes, we can always allocate. If zone
+ * If we're in interrupt, yes, we can always allocate. If
+ * __GFP_THISNODE is set, yes, we can always allocate. If zone
* z's node is in our tasks mems_allowed, yes. If it's not a
* __GFP_HARDWALL request and this zone's nodes is in the nearest
* mem_exclusive cpuset ancestor to this tasks cpuset, yes.
* Otherwise, no.
*
+ * If __GFP_HARDWALL is set, cpuset_zone_allowed_softwall()
+ * reduces to cpuset_zone_allowed_hardwall(). Otherwise,
+ * cpuset_zone_allowed_softwall() might sleep, and might allow a zone
+ * from an enclosing cpuset.
+ *
+ * cpuset_zone_allowed_hardwall() only handles the simpler case of
+ * hardwall cpusets, and never sleeps.
+ *
+ * The __GFP_THISNODE placement logic is really handled elsewhere,
+ * by forcibly using a zonelist starting at a specified node, and by
+ * (in get_page_from_freelist()) refusing to consider the zones for
+ * any node on the zonelist except the first. By the time any such
+ * calls get to this routine, we should just shut up and say 'yes'.
+ *
* GFP_USER allocations are marked with the __GFP_HARDWALL bit,
* and do not allow allocations outside the current tasks cpuset.
* GFP_KERNEL allocations are not so marked, so can escape to the
- * nearest mem_exclusive ancestor cpuset.
+ * nearest enclosing mem_exclusive ancestor cpuset.
*
- * Scanning up parent cpusets requires callback_mutex. The __alloc_pages()
- * routine only calls here with __GFP_HARDWALL bit _not_ set if
- * it's a GFP_KERNEL allocation, and all nodes in the current tasks
- * mems_allowed came up empty on the first pass over the zonelist.
- * So only GFP_KERNEL allocations, if all nodes in the cpuset are
- * short of memory, might require taking the callback_mutex mutex.
+ * Scanning up parent cpusets requires callback_mutex. The
+ * __alloc_pages() routine only calls here with __GFP_HARDWALL bit
+ * _not_ set if it's a GFP_KERNEL allocation, and all nodes in the
+ * current tasks mems_allowed came up empty on the first pass over
+ * the zonelist. So only GFP_KERNEL allocations, if all nodes in the
+ * cpuset are short of memory, might require taking the callback_mutex
+ * mutex.
*
* The first call here from mm/page_alloc:get_page_from_freelist()
- * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets, so
- * no allocation on a node outside the cpuset is allowed (unless in
- * interrupt, of course).
+ * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets,
+ * so no allocation on a node outside the cpuset is allowed (unless
+ * in interrupt, of course).
*
* The second pass through get_page_from_freelist() doesn't even call
* here for GFP_ATOMIC calls. For those calls, the __alloc_pages()
@@ -2380,12 +2396,12 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
* GFP_USER - only nodes in current tasks mems allowed ok.
*
* Rule:
- * Don't call cpuset_zone_allowed() if you can't sleep, unless you
+ * Don't call cpuset_zone_allowed_softwall if you can't sleep, unless you
* pass in the __GFP_HARDWALL flag set in gfp_flag, which disables
* the code that might scan up ancestor cpusets and sleep.
- **/
+ */
-int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
{
int node; /* node that zone z is on */
const struct cpuset *cs; /* current cpuset ancestors */
@@ -2415,6 +2431,40 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
return allowed;
}
+/*
+ * cpuset_zone_allowed_hardwall - Can we allocate on zone z's memory node?
+ * @z: is this zone on an allowed node?
+ * @gfp_mask: memory allocation flags
+ *
+ * If we're in interrupt, yes, we can always allocate.
+ * If __GFP_THISNODE is set, yes, we can always allocate. If zone
+ * z's node is in our tasks mems_allowed, yes. Otherwise, no.
+ *
+ * The __GFP_THISNODE placement logic is really handled elsewhere,
+ * by forcibly using a zonelist starting at a specified node, and by
+ * (in get_page_from_freelist()) refusing to consider the zones for
+ * any node on the zonelist except the first. By the time any such
+ * calls get to this routine, we should just shut up and say 'yes'.
+ *
+ * Unlike the cpuset_zone_allowed_softwall() variant, above,
+ * this variant requires that the zone be in the current tasks
+ * mems_allowed or that we're in interrupt. It does not scan up the
+ * cpuset hierarchy for the nearest enclosing mem_exclusive cpuset.
+ * It never sleeps.
+ */
+
+int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask)
+{
+ int node; /* node that zone z is on */
+
+ if (in_interrupt() || (gfp_mask & __GFP_THISNODE))
+ return 1;
+ node = zone_to_nid(z);
+ if (node_isset(node, current->mems_allowed))
+ return 1;
+ return 0;
+}
+
/**
* cpuset_lock - lock out any changes to cpuset structures
*
@@ -2606,7 +2656,7 @@ static int cpuset_open(struct inode *inode, struct file *file)
return single_open(file, proc_cpuset_show, pid);
}
-const struct file_operations proc_cpuset_operations = {
+struct file_operations proc_cpuset_operations = {
.open = cpuset_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/kernel/exit.c b/kernel/exit.c
index 4e3f919edc4..fec12eb1247 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -13,7 +13,7 @@
#include <linux/completion.h>
#include <linux/personality.h>
#include <linux/tty.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/key.h>
#include <linux/security.h>
#include <linux/cpu.h>
@@ -22,6 +22,7 @@
#include <linux/file.h>
#include <linux/binfmts.h>
#include <linux/nsproxy.h>
+#include <linux/pid_namespace.h>
#include <linux/ptrace.h>
#include <linux/profile.h>
#include <linux/mount.h>
@@ -48,7 +49,6 @@
#include <asm/mmu_context.h>
extern void sem_exit (void);
-extern struct task_struct *child_reaper;
static void exit_mm(struct task_struct * tsk);
@@ -189,21 +189,18 @@ repeat:
int session_of_pgrp(int pgrp)
{
struct task_struct *p;
- int sid = -1;
+ int sid = 0;
read_lock(&tasklist_lock);
- do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
- if (p->signal->session > 0) {
- sid = p->signal->session;
- goto out;
- }
- } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
- p = find_task_by_pid(pgrp);
- if (p)
- sid = p->signal->session;
-out:
+
+ p = find_task_by_pid_type(PIDTYPE_PGID, pgrp);
+ if (p == NULL)
+ p = find_task_by_pid(pgrp);
+ if (p != NULL)
+ sid = process_session(p);
+
read_unlock(&tasklist_lock);
-
+
return sid;
}
@@ -225,8 +222,8 @@ static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task)
|| p->exit_state
|| is_init(p->real_parent))
continue;
- if (process_group(p->real_parent) != pgrp
- && p->real_parent->signal->session == p->signal->session) {
+ if (process_group(p->real_parent) != pgrp &&
+ process_session(p->real_parent) == process_session(p)) {
ret = 0;
break;
}
@@ -260,7 +257,8 @@ static int has_stopped_jobs(int pgrp)
}
/**
- * reparent_to_init - Reparent the calling kernel thread to the init task.
+ * reparent_to_init - Reparent the calling kernel thread to the init task
+ * of the pid space that the thread belongs to.
*
* If a kernel thread is launched as a result of a system call, or if
* it ever exits, it should generally reparent itself to init so that
@@ -278,8 +276,8 @@ static void reparent_to_init(void)
ptrace_unlink(current);
/* Reparent to init */
remove_parent(current);
- current->parent = child_reaper;
- current->real_parent = child_reaper;
+ current->parent = child_reaper(current);
+ current->real_parent = child_reaper(current);
add_parent(current);
/* Set the exit signal to SIGCHLD so we signal init on exit */
@@ -302,9 +300,9 @@ void __set_special_pids(pid_t session, pid_t pgrp)
{
struct task_struct *curr = current->group_leader;
- if (curr->signal->session != session) {
+ if (process_session(curr) != session) {
detach_pid(curr, PIDTYPE_SID);
- curr->signal->session = session;
+ set_signal_session(curr->signal, session);
attach_pid(curr, PIDTYPE_SID, session);
}
if (process_group(curr) != pgrp) {
@@ -314,7 +312,7 @@ void __set_special_pids(pid_t session, pid_t pgrp)
}
}
-void set_special_pids(pid_t session, pid_t pgrp)
+static void set_special_pids(pid_t session, pid_t pgrp)
{
write_lock_irq(&tasklist_lock);
__set_special_pids(session, pgrp);
@@ -384,9 +382,7 @@ void daemonize(const char *name, ...)
exit_mm(current);
set_special_pids(1, 1);
- mutex_lock(&tty_mutex);
- current->signal->tty = NULL;
- mutex_unlock(&tty_mutex);
+ proc_clear_tty(current);
/* Block and flush all signals */
sigfillset(&blocked);
@@ -429,7 +425,7 @@ static void close_files(struct files_struct * files)
for (;;) {
unsigned long set;
i = j * __NFDBITS;
- if (i >= fdt->max_fdset || i >= fdt->max_fds)
+ if (i >= fdt->max_fds)
break;
set = fdt->open_fds->fds_bits[j++];
while (set) {
@@ -470,9 +466,7 @@ void fastcall put_files_struct(struct files_struct *files)
* you can free files immediately.
*/
fdt = files_fdtable(files);
- if (fdt == &files->fdtab)
- fdt->free_files = files;
- else
+ if (fdt != &files->fdtab)
kmem_cache_free(files_cachep, files);
free_fdtable(fdt);
}
@@ -603,10 +597,6 @@ choose_new_parent(struct task_struct *p, struct task_struct *reaper)
static void
reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
{
- /* We don't want people slaying init. */
- if (p->exit_signal != -1)
- p->exit_signal = SIGCHLD;
-
if (p->pdeath_signal)
/* We already hold the tasklist_lock here. */
group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
@@ -626,13 +616,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
p->parent = p->real_parent;
add_parent(p);
- /* If we'd notified the old parent about this child's death,
- * also notify the new parent.
- */
- if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 &&
- thread_group_empty(p))
- do_notify_parent(p, p->exit_signal);
- else if (p->state == TASK_TRACED) {
+ if (p->state == TASK_TRACED) {
/*
* If it was at a trace stop, turn it into
* a normal stop since it's no longer being
@@ -642,6 +626,23 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
}
}
+ /* If this is a threaded reparent there is no need to
+ * notify anyone anything has happened.
+ */
+ if (p->real_parent->group_leader == father->group_leader)
+ return;
+
+ /* We don't want people slaying init. */
+ if (p->exit_signal != -1)
+ p->exit_signal = SIGCHLD;
+
+ /* If we'd notified the old parent about this child's death,
+ * also notify the new parent.
+ */
+ if (!traced && p->exit_state == EXIT_ZOMBIE &&
+ p->exit_signal != -1 && thread_group_empty(p))
+ do_notify_parent(p, p->exit_signal);
+
/*
* process group orphan check
* Case ii: Our child is in a different pgrp
@@ -649,10 +650,11 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
* outside, so the child pgrp is now orphaned.
*/
if ((process_group(p) != process_group(father)) &&
- (p->signal->session == father->signal->session)) {
+ (process_session(p) == process_session(father))) {
int pgrp = process_group(p);
- if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) {
+ if (will_become_orphaned_pgrp(pgrp, NULL) &&
+ has_stopped_jobs(pgrp)) {
__kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp);
__kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp);
}
@@ -663,7 +665,8 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
* When we die, we re-parent all our children.
* Try to give them to another thread in our thread
* group, and if no such member exists, give it to
- * the global child reaper process (ie "init")
+ * the child reaper process (ie "init") in our pid
+ * space.
*/
static void
forget_original_parent(struct task_struct *father, struct list_head *to_release)
@@ -674,7 +677,7 @@ forget_original_parent(struct task_struct *father, struct list_head *to_release)
do {
reaper = next_thread(reaper);
if (reaper == father) {
- reaper = child_reaper;
+ reaper = child_reaper(father);
break;
}
} while (reaper->exit_state);
@@ -786,7 +789,7 @@ static void exit_notify(struct task_struct *tsk)
t = tsk->real_parent;
if ((process_group(t) != process_group(tsk)) &&
- (t->signal->session == tsk->signal->session) &&
+ (process_session(t) == process_session(tsk)) &&
will_become_orphaned_pgrp(process_group(tsk), tsk) &&
has_stopped_jobs(process_group(tsk))) {
__kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk));
@@ -860,8 +863,13 @@ fastcall NORET_TYPE void do_exit(long code)
panic("Aiee, killing interrupt handler!");
if (unlikely(!tsk->pid))
panic("Attempted to kill the idle task!");
- if (unlikely(tsk == child_reaper))
- panic("Attempted to kill init!");
+ if (unlikely(tsk == child_reaper(tsk))) {
+ if (tsk->nsproxy->pid_ns != &init_pid_ns)
+ tsk->nsproxy->pid_ns->child_reaper = init_pid_ns.child_reaper;
+ else
+ panic("Attempted to kill init!");
+ }
+
if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
current->ptrace_message = code;
@@ -930,8 +938,8 @@ fastcall NORET_TYPE void do_exit(long code)
tsk->exit_code = code;
proc_exit_connector(tsk);
- exit_notify(tsk);
exit_task_namespaces(tsk);
+ exit_notify(tsk);
#ifdef CONFIG_NUMA
mpol_free(tsk->mempolicy);
tsk->mempolicy = NULL;
diff --git a/kernel/fork.c b/kernel/fork.c
index 7f2e31ba33a..d57118da73f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -18,7 +18,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/completion.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/personality.h>
#include <linux/mempolicy.h>
#include <linux/sem.h>
@@ -36,6 +36,7 @@
#include <linux/syscalls.h>
#include <linux/jiffies.h>
#include <linux/futex.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/rcupdate.h>
#include <linux/ptrace.h>
#include <linux/mount.h>
@@ -202,7 +203,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
struct mempolicy *pol;
down_write(&oldmm->mmap_sem);
- flush_cache_mm(oldmm);
+ flush_cache_dup_mm(oldmm);
/*
* Not linked in yet - no deadlock potential:
*/
@@ -252,7 +253,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
anon_vma_link(tmp);
file = tmp->vm_file;
if (file) {
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
get_file(file);
if (tmp->vm_flags & VM_DENYWRITE)
atomic_dec(&inode->i_writecount);
@@ -613,7 +614,7 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
static int count_open_files(struct fdtable *fdt)
{
- int size = fdt->max_fdset;
+ int size = fdt->max_fds;
int i;
/* Find the last open fd */
@@ -640,12 +641,10 @@ static struct files_struct *alloc_files(void)
newf->next_fd = 0;
fdt = &newf->fdtab;
fdt->max_fds = NR_OPEN_DEFAULT;
- fdt->max_fdset = EMBEDDED_FD_SET_SIZE;
fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init;
fdt->open_fds = (fd_set *)&newf->open_fds_init;
fdt->fd = &newf->fd_array[0];
INIT_RCU_HEAD(&fdt->rcu);
- fdt->free_files = NULL;
fdt->next = NULL;
rcu_assign_pointer(newf->fdt, fdt);
out:
@@ -661,7 +660,7 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
{
struct files_struct *newf;
struct file **old_fds, **new_fds;
- int open_files, size, i, expand;
+ int open_files, size, i;
struct fdtable *old_fdt, *new_fdt;
*errorp = -ENOMEM;
@@ -672,25 +671,14 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
spin_lock(&oldf->file_lock);
old_fdt = files_fdtable(oldf);
new_fdt = files_fdtable(newf);
- size = old_fdt->max_fdset;
open_files = count_open_files(old_fdt);
- expand = 0;
/*
- * Check whether we need to allocate a larger fd array or fd set.
- * Note: we're not a clone task, so the open count won't change.
+ * Check whether we need to allocate a larger fd array and fd set.
+ * Note: we're not a clone task, so the open count won't change.
*/
- if (open_files > new_fdt->max_fdset) {
- new_fdt->max_fdset = 0;
- expand = 1;
- }
if (open_files > new_fdt->max_fds) {
new_fdt->max_fds = 0;
- expand = 1;
- }
-
- /* if the old fdset gets grown now, we'll only copy up to "size" fds */
- if (expand) {
spin_unlock(&oldf->file_lock);
spin_lock(&newf->file_lock);
*errorp = expand_files(newf, open_files-1);
@@ -710,8 +698,10 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
old_fds = old_fdt->fd;
new_fds = new_fdt->fd;
- memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8);
- memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8);
+ memcpy(new_fdt->open_fds->fds_bits,
+ old_fdt->open_fds->fds_bits, open_files/8);
+ memcpy(new_fdt->close_on_exec->fds_bits,
+ old_fdt->close_on_exec->fds_bits, open_files/8);
for (i = open_files; i != 0; i--) {
struct file *f = *old_fds++;
@@ -736,22 +726,19 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
/* This is long word aligned thus could use a optimized version */
memset(new_fds, 0, size);
- if (new_fdt->max_fdset > open_files) {
- int left = (new_fdt->max_fdset-open_files)/8;
+ if (new_fdt->max_fds > open_files) {
+ int left = (new_fdt->max_fds-open_files)/8;
int start = open_files / (8 * sizeof(unsigned long));
memset(&new_fdt->open_fds->fds_bits[start], 0, left);
memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
}
-out:
return newf;
out_release:
- free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
- free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
- free_fd_array(new_fdt->fd, new_fdt->max_fds);
kmem_cache_free(files_cachep, newf);
+out:
return NULL;
}
@@ -1055,6 +1042,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->wchar = 0; /* I/O counter: bytes written */
p->syscr = 0; /* I/O counter: read syscalls */
p->syscw = 0; /* I/O counter: write syscalls */
+ task_io_accounting_init(p);
acct_clear_integrals(p);
p->it_virt_expires = cputime_zero;
@@ -1259,9 +1247,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (thread_group_leader(p)) {
p->signal->tty = current->signal->tty;
p->signal->pgrp = process_group(current);
- p->signal->session = current->signal->session;
+ set_signal_session(p->signal, process_session(current));
attach_pid(p, PIDTYPE_PGID, process_group(p));
- attach_pid(p, PIDTYPE_SID, p->signal->session);
+ attach_pid(p, PIDTYPE_SID, process_session(p));
list_add_tail_rcu(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
@@ -1325,7 +1313,7 @@ noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_re
return regs;
}
-struct task_struct * __devinit fork_idle(int cpu)
+struct task_struct * __cpuinit fork_idle(int cpu)
{
struct task_struct *task;
struct pt_regs regs;
@@ -1525,17 +1513,18 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
}
/*
- * Unshare the namespace structure if it is being shared
+ * Unshare the mnt_namespace structure if it is being shared
*/
-static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs)
+static int unshare_mnt_namespace(unsigned long unshare_flags,
+ struct mnt_namespace **new_nsp, struct fs_struct *new_fs)
{
- struct namespace *ns = current->nsproxy->namespace;
+ struct mnt_namespace *ns = current->nsproxy->mnt_ns;
if ((unshare_flags & CLONE_NEWNS) && ns) {
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- *new_nsp = dup_namespace(current, new_fs ? new_fs : current->fs);
+ *new_nsp = dup_mnt_ns(current, new_fs ? new_fs : current->fs);
if (!*new_nsp)
return -ENOMEM;
}
@@ -1544,15 +1533,13 @@ static int unshare_namespace(unsigned long unshare_flags, struct namespace **new
}
/*
- * Unsharing of sighand for tasks created with CLONE_SIGHAND is not
- * supported yet
+ * Unsharing of sighand is not supported yet
*/
static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp)
{
struct sighand_struct *sigh = current->sighand;
- if ((unshare_flags & CLONE_SIGHAND) &&
- (sigh && atomic_read(&sigh->count) > 1))
+ if ((unshare_flags & CLONE_SIGHAND) && atomic_read(&sigh->count) > 1)
return -EINVAL;
else
return 0;
@@ -1625,8 +1612,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
{
int err = 0;
struct fs_struct *fs, *new_fs = NULL;
- struct namespace *ns, *new_ns = NULL;
- struct sighand_struct *sigh, *new_sigh = NULL;
+ struct mnt_namespace *ns, *new_ns = NULL;
+ struct sighand_struct *new_sigh = NULL;
struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
struct files_struct *fd, *new_fd = NULL;
struct sem_undo_list *new_ulist = NULL;
@@ -1647,7 +1634,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
goto bad_unshare_out;
if ((err = unshare_fs(unshare_flags, &new_fs)))
goto bad_unshare_cleanup_thread;
- if ((err = unshare_namespace(unshare_flags, &new_ns, new_fs)))
+ if ((err = unshare_mnt_namespace(unshare_flags, &new_ns, new_fs)))
goto bad_unshare_cleanup_fs;
if ((err = unshare_sighand(unshare_flags, &new_sigh)))
goto bad_unshare_cleanup_ns;
@@ -1671,7 +1658,7 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
}
}
- if (new_fs || new_ns || new_sigh || new_mm || new_fd || new_ulist ||
+ if (new_fs || new_ns || new_mm || new_fd || new_ulist ||
new_uts || new_ipc) {
task_lock(current);
@@ -1688,17 +1675,11 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
}
if (new_ns) {
- ns = current->nsproxy->namespace;
- current->nsproxy->namespace = new_ns;
+ ns = current->nsproxy->mnt_ns;
+ current->nsproxy->mnt_ns = new_ns;
new_ns = ns;
}
- if (new_sigh) {
- sigh = current->sighand;
- rcu_assign_pointer(current->sighand, new_sigh);
- new_sigh = sigh;
- }
-
if (new_mm) {
mm = current->mm;
active_mm = current->active_mm;
@@ -1756,7 +1737,7 @@ bad_unshare_cleanup_sigh:
bad_unshare_cleanup_ns:
if (new_ns)
- put_namespace(new_ns);
+ put_mnt_ns(new_ns);
bad_unshare_cleanup_fs:
if (new_fs)
diff --git a/kernel/futex.c b/kernel/futex.c
index 95989a3b416..5a737de857d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -166,7 +166,7 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
/*
* Get parameters which are the keys for a futex.
*
- * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode,
+ * For shared mappings, it's (page->index, vma->vm_file->f_path.dentry->d_inode,
* offset_within_page). For private mappings, it's (uaddr, current->mm).
* We can usually work out the index without swapping in the page.
*
@@ -223,7 +223,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
/*
* Linear file mappings are also simple.
*/
- key->shared.inode = vma->vm_file->f_dentry->d_inode;
+ key->shared.inode = vma->vm_file->f_path.dentry->d_inode;
key->both.offset++; /* Bit 0 of offset indicates inode-based key. */
if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
@@ -1528,9 +1528,9 @@ static int futex_fd(u32 __user *uaddr, int signal)
goto out;
}
filp->f_op = &futex_fops;
- filp->f_vfsmnt = mntget(futex_mnt);
- filp->f_dentry = dget(futex_mnt->mnt_root);
- filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+ filp->f_path.mnt = mntget(futex_mnt);
+ filp->f_path.dentry = dget(futex_mnt->mnt_root);
+ filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
if (signal) {
err = __f_setown(filp, task_pid(current), PIDTYPE_PID, 1);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index ebfd24a4185..d27b2585574 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -517,10 +517,9 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
if (!handle)
handle = handle_bad_irq;
-
- if (desc->chip == &no_irq_chip) {
+ else if (desc->chip == &no_irq_chip) {
printk(KERN_WARNING "Trying to install %sinterrupt handler "
- "for IRQ%d\n", is_chained ? "chained " : " ", irq);
+ "for IRQ%d\n", is_chained ? "chained " : "", irq);
/*
* Some ARM implementations install a handler for really dumb
* interrupt hardware without setting an irq_chip. This worked
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index b385878c6e8..8b961adc3bd 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -315,6 +315,9 @@ int setup_irq(unsigned int irq, struct irqaction *new)
/* Undo nested disables: */
desc->depth = 1;
}
+ /* Reset broken irq detection when installing new handler */
+ desc->irq_count = 0;
+ desc->irqs_unhandled = 0;
spin_unlock_irqrestore(&desc->lock, flags);
new->irq = irq;
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 9a352667007..61f5c717a8f 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -54,7 +54,8 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
unsigned int irq = (int)(long)data, full_count = count, err;
cpumask_t new_value, tmp;
- if (!irq_desc[irq].chip->set_affinity || no_irq_affinity)
+ if (!irq_desc[irq].chip->set_affinity || no_irq_affinity ||
+ CHECK_IRQ_PER_CPU(irq_desc[irq].status))
return -EIO;
err = cpumask_parse_user(buffer, count, new_value);
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 543ea2e5ad9..9d8c79b4882 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -176,7 +176,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
int noirqdebug __read_mostly;
-int __init noirqdebug_setup(char *str)
+int noirqdebug_setup(char *str)
{
noirqdebug = 1;
printk(KERN_INFO "IRQ lockup detection disabled\n");
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index ab63cfc4299..6f294ff4f9e 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -31,14 +31,14 @@
#endif
/* These will be re-linked against their real values during the second link stage */
-extern unsigned long kallsyms_addresses[] __attribute__((weak));
-extern unsigned long kallsyms_num_syms __attribute__((weak,section("data")));
-extern u8 kallsyms_names[] __attribute__((weak));
+extern const unsigned long kallsyms_addresses[] __attribute__((weak));
+extern const unsigned long kallsyms_num_syms __attribute__((weak));
+extern const u8 kallsyms_names[] __attribute__((weak));
-extern u8 kallsyms_token_table[] __attribute__((weak));
-extern u16 kallsyms_token_index[] __attribute__((weak));
+extern const u8 kallsyms_token_table[] __attribute__((weak));
+extern const u16 kallsyms_token_index[] __attribute__((weak));
-extern unsigned long kallsyms_markers[] __attribute__((weak));
+extern const unsigned long kallsyms_markers[] __attribute__((weak));
static inline int is_kernel_inittext(unsigned long addr)
{
@@ -84,7 +84,7 @@ static int is_ksym_addr(unsigned long addr)
static unsigned int kallsyms_expand_symbol(unsigned int off, char *result)
{
int len, skipped_first = 0;
- u8 *tptr, *data;
+ const u8 *tptr, *data;
/* get the compressed symbol length from the first symbol byte */
data = &kallsyms_names[off];
@@ -132,7 +132,7 @@ static char kallsyms_get_symbol_type(unsigned int off)
* kallsyms array */
static unsigned int get_symbol_offset(unsigned long pos)
{
- u8 *name;
+ const u8 *name;
int i;
/* use the closest marker we have. We have markers every 256 positions,
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 8d2bea09a4e..3a7379aa31c 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -25,7 +25,7 @@
#include <linux/kmod.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/completion.h>
#include <linux/file.h>
#include <linux/workqueue.h>
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 17ec4afb099..6fcf8dd148d 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -87,6 +87,12 @@ struct kprobe_insn_page {
int ngarbage;
};
+enum kprobe_slot_state {
+ SLOT_CLEAN = 0,
+ SLOT_DIRTY = 1,
+ SLOT_USED = 2,
+};
+
static struct hlist_head kprobe_insn_pages;
static int kprobe_garbage_slots;
static int collect_garbage_slots(void);
@@ -130,8 +136,8 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
if (kip->nused < INSNS_PER_PAGE) {
int i;
for (i = 0; i < INSNS_PER_PAGE; i++) {
- if (!kip->slot_used[i]) {
- kip->slot_used[i] = 1;
+ if (kip->slot_used[i] == SLOT_CLEAN) {
+ kip->slot_used[i] = SLOT_USED;
kip->nused++;
return kip->insns + (i * MAX_INSN_SIZE);
}
@@ -163,8 +169,8 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
}
INIT_HLIST_NODE(&kip->hlist);
hlist_add_head(&kip->hlist, &kprobe_insn_pages);
- memset(kip->slot_used, 0, INSNS_PER_PAGE);
- kip->slot_used[0] = 1;
+ memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
+ kip->slot_used[0] = SLOT_USED;
kip->nused = 1;
kip->ngarbage = 0;
return kip->insns;
@@ -173,7 +179,7 @@ kprobe_opcode_t __kprobes *get_insn_slot(void)
/* Return 1 if all garbages are collected, otherwise 0. */
static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
{
- kip->slot_used[idx] = 0;
+ kip->slot_used[idx] = SLOT_CLEAN;
kip->nused--;
if (kip->nused == 0) {
/*
@@ -212,7 +218,7 @@ static int __kprobes collect_garbage_slots(void)
continue;
kip->ngarbage = 0; /* we will collect all garbages */
for (i = 0; i < INSNS_PER_PAGE; i++) {
- if (kip->slot_used[i] == -1 &&
+ if (kip->slot_used[i] == SLOT_DIRTY &&
collect_one_slot(kip, i))
break;
}
@@ -232,7 +238,7 @@ void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
int i = (slot - kip->insns) / MAX_INSN_SIZE;
if (dirty) {
- kip->slot_used[i] = -1;
+ kip->slot_used[i] = SLOT_DIRTY;
kip->ngarbage++;
} else {
collect_one_slot(kip, i);
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index b02032476dc..509efd49540 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -43,13 +43,49 @@
#include "lockdep_internals.h"
/*
- * hash_lock: protects the lockdep hashes and class/list/hash allocators.
+ * lockdep_lock: protects the lockdep graph, the hashes and the
+ * class/list/hash allocators.
*
* This is one of the rare exceptions where it's justified
* to use a raw spinlock - we really dont want the spinlock
- * code to recurse back into the lockdep code.
+ * code to recurse back into the lockdep code...
*/
-static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+static raw_spinlock_t lockdep_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+
+static int graph_lock(void)
+{
+ __raw_spin_lock(&lockdep_lock);
+ /*
+ * Make sure that if another CPU detected a bug while
+ * walking the graph we dont change it (while the other
+ * CPU is busy printing out stuff with the graph lock
+ * dropped already)
+ */
+ if (!debug_locks) {
+ __raw_spin_unlock(&lockdep_lock);
+ return 0;
+ }
+ return 1;
+}
+
+static inline int graph_unlock(void)
+{
+ __raw_spin_unlock(&lockdep_lock);
+ return 0;
+}
+
+/*
+ * Turn lock debugging off and return with 0 if it was off already,
+ * and also release the graph lock:
+ */
+static inline int debug_locks_off_graph_unlock(void)
+{
+ int ret = debug_locks_off();
+
+ __raw_spin_unlock(&lockdep_lock);
+
+ return ret;
+}
static int lockdep_initialized;
@@ -57,14 +93,15 @@ unsigned long nr_list_entries;
static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
/*
- * Allocate a lockdep entry. (assumes hash_lock held, returns
+ * Allocate a lockdep entry. (assumes the graph_lock held, returns
* with NULL on failure)
*/
static struct lock_list *alloc_list_entry(void)
{
if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) {
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
+ if (!debug_locks_off_graph_unlock())
+ return NULL;
+
printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
printk("turning off the locking correctness validator.\n");
return NULL;
@@ -145,9 +182,7 @@ EXPORT_SYMBOL(lockdep_on);
*/
#define VERBOSE 0
-#ifdef VERBOSE
-# define VERY_VERBOSE 0
-#endif
+#define VERY_VERBOSE 0
#if VERBOSE
# define HARDIRQ_VERBOSE 1
@@ -172,8 +207,8 @@ static int class_filter(struct lock_class *class)
!strcmp(class->name, "&struct->lockfield"))
return 1;
#endif
- /* Allow everything else. 0 would be filter everything else */
- return 1;
+ /* Filter everything else. 1 would be to allow everything else */
+ return 0;
}
#endif
@@ -207,7 +242,7 @@ static int softirq_verbose(struct lock_class *class)
/*
* Stack-trace: tightly packed array of stack backtrace
- * addresses. Protected by the hash_lock.
+ * addresses. Protected by the graph_lock.
*/
unsigned long nr_stack_trace_entries;
static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
@@ -226,18 +261,15 @@ static int save_trace(struct stack_trace *trace)
trace->max_entries = trace->nr_entries;
nr_stack_trace_entries += trace->nr_entries;
- if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) {
- __raw_spin_unlock(&hash_lock);
- return 0;
- }
if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) {
- __raw_spin_unlock(&hash_lock);
- if (debug_locks_off()) {
- printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
- printk("turning off the locking correctness validator.\n");
- dump_stack();
- }
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
+ printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
+ printk("turning off the locking correctness validator.\n");
+ dump_stack();
+
return 0;
}
@@ -526,9 +558,7 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth)
{
struct task_struct *curr = current;
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=======================================================\n");
@@ -556,12 +586,10 @@ static noinline int print_circular_bug_tail(void)
if (debug_locks_silent)
return 0;
- /* hash_lock unlocked by the header */
- __raw_spin_lock(&hash_lock);
this.class = check_source->class;
if (!save_trace(&this.trace))
return 0;
- __raw_spin_unlock(&hash_lock);
+
print_circular_bug_entry(&this, 0);
printk("\nother info that might help us debug this:\n\n");
@@ -577,8 +605,10 @@ static noinline int print_circular_bug_tail(void)
static int noinline print_infinite_recursion_bug(void)
{
- __raw_spin_unlock(&hash_lock);
- DEBUG_LOCKS_WARN_ON(1);
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
+ WARN_ON(1);
return 0;
}
@@ -713,9 +743,7 @@ print_bad_irq_dependency(struct task_struct *curr,
enum lock_usage_bit bit2,
const char *irqclass)
{
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n======================================================\n");
@@ -796,9 +824,7 @@ static int
print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
struct held_lock *next)
{
- debug_locks_off();
- __raw_spin_unlock(&hash_lock);
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=============================================\n");
@@ -974,14 +1000,14 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
* Debugging printouts:
*/
if (verbose(prev->class) || verbose(next->class)) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
printk("\n new dependency: ");
print_lock_name(prev->class);
printk(" => ");
print_lock_name(next->class);
printk("\n");
dump_stack();
- __raw_spin_lock(&hash_lock);
+ return graph_lock();
}
return 1;
}
@@ -1046,8 +1072,10 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
}
return 1;
out_bug:
- __raw_spin_unlock(&hash_lock);
- DEBUG_LOCKS_WARN_ON(1);
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
+ WARN_ON(1);
return 0;
}
@@ -1201,7 +1229,10 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
hash_head = classhashentry(key);
raw_local_irq_save(flags);
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock()) {
+ raw_local_irq_restore(flags);
+ return NULL;
+ }
/*
* We have to do the hash-walk again, to avoid races
* with another CPU:
@@ -1214,9 +1245,12 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
* the hash:
*/
if (nr_lock_classes >= MAX_LOCKDEP_KEYS) {
- __raw_spin_unlock(&hash_lock);
+ if (!debug_locks_off_graph_unlock()) {
+ raw_local_irq_restore(flags);
+ return NULL;
+ }
raw_local_irq_restore(flags);
- debug_locks_off();
+
printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
printk("turning off the locking correctness validator.\n");
return NULL;
@@ -1237,18 +1271,23 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
list_add_tail_rcu(&class->hash_entry, hash_head);
if (verbose(class)) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
raw_local_irq_restore(flags);
+
printk("\nnew class %p: %s", class->key, class->name);
if (class->name_version > 1)
printk("#%d", class->name_version);
printk("\n");
dump_stack();
+
raw_local_irq_save(flags);
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock()) {
+ raw_local_irq_restore(flags);
+ return NULL;
+ }
}
out_unlock_set:
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
raw_local_irq_restore(flags);
if (!subclass || force)
@@ -1264,7 +1303,7 @@ out_unlock_set:
* add it and return 0 - in this case the new dependency chain is
* validated. If the key is already hashed, return 1.
*/
-static inline int lookup_chain_cache(u64 chain_key)
+static inline int lookup_chain_cache(u64 chain_key, struct lock_class *class)
{
struct list_head *hash_head = chainhashentry(chain_key);
struct lock_chain *chain;
@@ -1278,34 +1317,36 @@ static inline int lookup_chain_cache(u64 chain_key)
if (chain->chain_key == chain_key) {
cache_hit:
debug_atomic_inc(&chain_lookup_hits);
- /*
- * In the debugging case, force redundant checking
- * by returning 1:
- */
-#ifdef CONFIG_DEBUG_LOCKDEP
- __raw_spin_lock(&hash_lock);
- return 1;
-#endif
+ if (very_verbose(class))
+ printk("\nhash chain already cached, key: "
+ "%016Lx tail class: [%p] %s\n",
+ (unsigned long long)chain_key,
+ class->key, class->name);
return 0;
}
}
+ if (very_verbose(class))
+ printk("\nnew hash chain, key: %016Lx tail class: [%p] %s\n",
+ (unsigned long long)chain_key, class->key, class->name);
/*
* Allocate a new chain entry from the static array, and add
* it to the hash:
*/
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock())
+ return 0;
/*
* We have to walk the chain again locked - to avoid duplicates:
*/
list_for_each_entry(chain, hash_head, entry) {
if (chain->chain_key == chain_key) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
goto cache_hit;
}
}
if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) {
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
+ if (!debug_locks_off_graph_unlock())
+ return 0;
+
printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
printk("turning off the locking correctness validator.\n");
return 0;
@@ -1381,9 +1422,7 @@ print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
struct held_lock *this, int forwards,
const char *irqclass)
{
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=========================================================\n");
@@ -1453,7 +1492,7 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this,
return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass);
}
-static inline void print_irqtrace_events(struct task_struct *curr)
+void print_irqtrace_events(struct task_struct *curr)
{
printk("irq event stamp: %u\n", curr->irq_events);
printk("hardirqs last enabled at (%u): ", curr->hardirq_enable_event);
@@ -1466,19 +1505,13 @@ static inline void print_irqtrace_events(struct task_struct *curr)
print_ip_sym(curr->softirq_disable_ip);
}
-#else
-static inline void print_irqtrace_events(struct task_struct *curr)
-{
-}
#endif
static int
print_usage_bug(struct task_struct *curr, struct held_lock *this,
enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit)
{
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
- if (debug_locks_silent)
+ if (!debug_locks_off_graph_unlock() || debug_locks_silent)
return 0;
printk("\n=================================\n");
@@ -1539,12 +1572,13 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
if (likely(this->class->usage_mask & new_mask))
return 1;
- __raw_spin_lock(&hash_lock);
+ if (!graph_lock())
+ return 0;
/*
* Make sure we didnt race:
*/
if (unlikely(this->class->usage_mask & new_mask)) {
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
return 1;
}
@@ -1730,16 +1764,16 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
debug_atomic_dec(&nr_unused_locks);
break;
default:
- __raw_spin_unlock(&hash_lock);
- debug_locks_off();
+ if (!debug_locks_off_graph_unlock())
+ return 0;
WARN_ON(1);
return 0;
}
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
/*
- * We must printk outside of the hash_lock:
+ * We must printk outside of the graph_lock:
*/
if (ret == 2) {
printk("\nmarked lock as {%s}:\n", usage_str[new_bit]);
@@ -2137,9 +2171,9 @@ out_calc_hash:
* We look up the chain_key and do the O(N^2) check and update of
* the dependencies only if this is a new dependency chain.
* (If lookup_chain_cache() returns with 1 it acquires
- * hash_lock for us)
+ * graph_lock for us)
*/
- if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) {
+ if (!trylock && (check == 2) && lookup_chain_cache(chain_key, class)) {
/*
* Check whether last held lock:
*
@@ -2170,7 +2204,7 @@ out_calc_hash:
if (!chain_head && ret != 2)
if (!check_prevs_add(curr, hlock))
return 0;
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
}
curr->lockdep_depth++;
check_chain_key(curr);
@@ -2433,6 +2467,7 @@ EXPORT_SYMBOL_GPL(lock_release);
void lockdep_reset(void)
{
unsigned long flags;
+ int i;
raw_local_irq_save(flags);
current->curr_chain_key = 0;
@@ -2443,6 +2478,8 @@ void lockdep_reset(void)
nr_softirq_chains = 0;
nr_process_chains = 0;
debug_locks = 1;
+ for (i = 0; i < CHAINHASH_SIZE; i++)
+ INIT_LIST_HEAD(chainhash_table + i);
raw_local_irq_restore(flags);
}
@@ -2479,7 +2516,7 @@ void lockdep_free_key_range(void *start, unsigned long size)
int i;
raw_local_irq_save(flags);
- __raw_spin_lock(&hash_lock);
+ graph_lock();
/*
* Unhash all classes that were created by this module:
@@ -2493,7 +2530,7 @@ void lockdep_free_key_range(void *start, unsigned long size)
zap_class(class);
}
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
raw_local_irq_restore(flags);
}
@@ -2521,20 +2558,20 @@ void lockdep_reset_lock(struct lockdep_map *lock)
* Debug check: in the end all mapped classes should
* be gone.
*/
- __raw_spin_lock(&hash_lock);
+ graph_lock();
for (i = 0; i < CLASSHASH_SIZE; i++) {
head = classhash_table + i;
if (list_empty(head))
continue;
list_for_each_entry_safe(class, next, head, hash_entry) {
if (unlikely(class == lock->class_cache)) {
- __raw_spin_unlock(&hash_lock);
- DEBUG_LOCKS_WARN_ON(1);
+ if (debug_locks_off_graph_unlock())
+ WARN_ON(1);
goto out_restore;
}
}
}
- __raw_spin_unlock(&hash_lock);
+ graph_unlock();
out_restore:
raw_local_irq_restore(flags);
diff --git a/kernel/module.c b/kernel/module.c
index d9eae45d014..d0f2260a021 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -824,9 +824,34 @@ static inline void module_unload_init(struct module *mod)
}
#endif /* CONFIG_MODULE_UNLOAD */
+static ssize_t show_initstate(struct module_attribute *mattr,
+ struct module *mod, char *buffer)
+{
+ const char *state = "unknown";
+
+ switch (mod->state) {
+ case MODULE_STATE_LIVE:
+ state = "live";
+ break;
+ case MODULE_STATE_COMING:
+ state = "coming";
+ break;
+ case MODULE_STATE_GOING:
+ state = "going";
+ break;
+ }
+ return sprintf(buffer, "%s\n", state);
+}
+
+static struct module_attribute initstate = {
+ .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+ .show = show_initstate,
+};
+
static struct module_attribute *modinfo_attrs[] = {
&modinfo_version,
&modinfo_srcversion,
+ &initstate,
#ifdef CONFIG_MODULE_UNLOAD
&refcnt,
#endif
@@ -1107,8 +1132,10 @@ static int mod_sysfs_setup(struct module *mod,
goto out;
mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
- if (!mod->drivers_dir)
+ if (!mod->drivers_dir) {
+ err = -ENOMEM;
goto out_unreg;
+ }
err = module_param_sysfs_setup(mod, kparam, num_params);
if (err)
@@ -1121,10 +1148,10 @@ static int mod_sysfs_setup(struct module *mod,
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
return 0;
-out_unreg_drivers:
- kobject_unregister(mod->drivers_dir);
out_unreg_param:
module_param_sysfs_remove(mod);
+out_unreg_drivers:
+ kobject_unregister(mod->drivers_dir);
out_unreg:
kobject_del(&mod->mkobj.kobj);
kobject_put(&mod->mkobj.kobj);
@@ -2300,8 +2327,22 @@ void print_modules(void)
printk("\n");
}
+static char *make_driver_name(struct device_driver *drv)
+{
+ char *driver_name;
+
+ driver_name = kmalloc(strlen(drv->name) + strlen(drv->bus->name) + 2,
+ GFP_KERNEL);
+ if (!driver_name)
+ return NULL;
+
+ sprintf(driver_name, "%s:%s", drv->bus->name, drv->name);
+ return driver_name;
+}
+
void module_add_driver(struct module *mod, struct device_driver *drv)
{
+ char *driver_name;
int no_warn;
if (!mod || !drv)
@@ -2309,17 +2350,31 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
/* Don't check return codes; these calls are idempotent */
no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
- no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, drv->name);
+ driver_name = make_driver_name(drv);
+ if (driver_name) {
+ no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj,
+ driver_name);
+ kfree(driver_name);
+ }
}
EXPORT_SYMBOL(module_add_driver);
void module_remove_driver(struct device_driver *drv)
{
+ char *driver_name;
+
if (!drv)
return;
+
sysfs_remove_link(&drv->kobj, "module");
- if (drv->owner && drv->owner->drivers_dir)
- sysfs_remove_link(drv->owner->drivers_dir, drv->name);
+ if (drv->owner && drv->owner->drivers_dir) {
+ driver_name = make_driver_name(drv);
+ if (driver_name) {
+ sysfs_remove_link(drv->owner->drivers_dir,
+ driver_name);
+ kfree(driver_name);
+ }
+ }
}
EXPORT_SYMBOL(module_remove_driver);
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 8c71cf72a49..e7cbbb82765 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -206,6 +206,15 @@ mutex_lock_nested(struct mutex *lock, unsigned int subclass)
}
EXPORT_SYMBOL_GPL(mutex_lock_nested);
+
+int __sched
+mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
+{
+ might_sleep();
+ return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass);
+}
+
+EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
#endif
/*
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 674aceb7335..f5b9ee6f6bb 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -17,8 +17,9 @@
#include <linux/version.h>
#include <linux/nsproxy.h>
#include <linux/init_task.h>
-#include <linux/namespace.h>
+#include <linux/mnt_namespace.h>
#include <linux/utsname.h>
+#include <linux/pid_namespace.h>
struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
@@ -60,12 +61,14 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
struct nsproxy *ns = clone_namespaces(orig);
if (ns) {
- if (ns->namespace)
- get_namespace(ns->namespace);
+ if (ns->mnt_ns)
+ get_mnt_ns(ns->mnt_ns);
if (ns->uts_ns)
get_uts_ns(ns->uts_ns);
if (ns->ipc_ns)
get_ipc_ns(ns->ipc_ns);
+ if (ns->pid_ns)
+ get_pid_ns(ns->pid_ns);
}
return ns;
@@ -97,7 +100,7 @@ int copy_namespaces(int flags, struct task_struct *tsk)
tsk->nsproxy = new_ns;
- err = copy_namespace(flags, tsk);
+ err = copy_mnt_ns(flags, tsk);
if (err)
goto out_ns;
@@ -109,16 +112,23 @@ int copy_namespaces(int flags, struct task_struct *tsk)
if (err)
goto out_ipc;
+ err = copy_pid_ns(flags, tsk);
+ if (err)
+ goto out_pid;
+
out:
put_nsproxy(old_ns);
return err;
+out_pid:
+ if (new_ns->ipc_ns)
+ put_ipc_ns(new_ns->ipc_ns);
out_ipc:
if (new_ns->uts_ns)
put_uts_ns(new_ns->uts_ns);
out_uts:
- if (new_ns->namespace)
- put_namespace(new_ns->namespace);
+ if (new_ns->mnt_ns)
+ put_mnt_ns(new_ns->mnt_ns);
out_ns:
tsk->nsproxy = old_ns;
kfree(new_ns);
@@ -127,11 +137,13 @@ out_ns:
void free_nsproxy(struct nsproxy *ns)
{
- if (ns->namespace)
- put_namespace(ns->namespace);
- if (ns->uts_ns)
- put_uts_ns(ns->uts_ns);
- if (ns->ipc_ns)
- put_ipc_ns(ns->ipc_ns);
- kfree(ns);
+ if (ns->mnt_ns)
+ put_mnt_ns(ns->mnt_ns);
+ if (ns->uts_ns)
+ put_uts_ns(ns->uts_ns);
+ if (ns->ipc_ns)
+ put_ipc_ns(ns->ipc_ns);
+ if (ns->pid_ns)
+ put_pid_ns(ns->pid_ns);
+ kfree(ns);
}
diff --git a/kernel/params.c b/kernel/params.c
index f406655d665..718945da8f5 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -143,9 +143,15 @@ int parse_args(const char *name,
while (*args) {
int ret;
+ int irq_was_disabled;
args = next_arg(args, &param, &val);
+ irq_was_disabled = irqs_disabled();
ret = parse_one(param, val, params, num, unknown);
+ if (irq_was_disabled && !irqs_disabled()) {
+ printk(KERN_WARNING "parse_args(): option '%s' enabled "
+ "irq's!\n", param);
+ }
switch (ret) {
case -ENOENT:
printk(KERN_ERR "%s: Unknown parameter `%s'\n",
diff --git a/kernel/pid.c b/kernel/pid.c
index a48879b0b92..78f2aee90f5 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -26,7 +26,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/hash.h>
-#include <linux/pspace.h>
+#include <linux/pid_namespace.h>
#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
static struct hlist_head *pid_hash;
@@ -43,9 +43,10 @@ int pid_max_max = PID_MAX_LIMIT;
#define BITS_PER_PAGE (PAGE_SIZE*8)
#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1)
-static inline int mk_pid(struct pspace *pspace, struct pidmap *map, int off)
+static inline int mk_pid(struct pid_namespace *pid_ns,
+ struct pidmap *map, int off)
{
- return (map - pspace->pidmap)*BITS_PER_PAGE + off;
+ return (map - pid_ns->pidmap)*BITS_PER_PAGE + off;
}
#define find_next_offset(map, off) \
@@ -57,11 +58,15 @@ static inline int mk_pid(struct pspace *pspace, struct pidmap *map, int off)
* value does not cause lots of bitmaps to be allocated, but
* the scheme scales to up to 4 million PIDs, runtime.
*/
-struct pspace init_pspace = {
+struct pid_namespace init_pid_ns = {
+ .kref = {
+ .refcount = ATOMIC_INIT(2),
+ },
.pidmap = {
[ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL }
},
- .last_pid = 0
+ .last_pid = 0,
+ .child_reaper = &init_task
};
/*
@@ -80,25 +85,25 @@ struct pspace init_pspace = {
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
-static fastcall void free_pidmap(struct pspace *pspace, int pid)
+static fastcall void free_pidmap(struct pid_namespace *pid_ns, int pid)
{
- struct pidmap *map = pspace->pidmap + pid / BITS_PER_PAGE;
+ struct pidmap *map = pid_ns->pidmap + pid / BITS_PER_PAGE;
int offset = pid & BITS_PER_PAGE_MASK;
clear_bit(offset, map->page);
atomic_inc(&map->nr_free);
}
-static int alloc_pidmap(struct pspace *pspace)
+static int alloc_pidmap(struct pid_namespace *pid_ns)
{
- int i, offset, max_scan, pid, last = pspace->last_pid;
+ int i, offset, max_scan, pid, last = pid_ns->last_pid;
struct pidmap *map;
pid = last + 1;
if (pid >= pid_max)
pid = RESERVED_PIDS;
offset = pid & BITS_PER_PAGE_MASK;
- map = &pspace->pidmap[pid/BITS_PER_PAGE];
+ map = &pid_ns->pidmap[pid/BITS_PER_PAGE];
max_scan = (pid_max + BITS_PER_PAGE - 1)/BITS_PER_PAGE - !offset;
for (i = 0; i <= max_scan; ++i) {
if (unlikely(!map->page)) {
@@ -120,11 +125,11 @@ static int alloc_pidmap(struct pspace *pspace)
do {
if (!test_and_set_bit(offset, map->page)) {
atomic_dec(&map->nr_free);
- pspace->last_pid = pid;
+ pid_ns->last_pid = pid;
return pid;
}
offset = find_next_offset(map, offset);
- pid = mk_pid(pspace, map, offset);
+ pid = mk_pid(pid_ns, map, offset);
/*
* find_next_offset() found a bit, the pid from it
* is in-bounds, and if we fell back to the last
@@ -135,34 +140,34 @@ static int alloc_pidmap(struct pspace *pspace)
(i != max_scan || pid < last ||
!((last+1) & BITS_PER_PAGE_MASK)));
}
- if (map < &pspace->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
+ if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
++map;
offset = 0;
} else {
- map = &pspace->pidmap[0];
+ map = &pid_ns->pidmap[0];
offset = RESERVED_PIDS;
if (unlikely(last == offset))
break;
}
- pid = mk_pid(pspace, map, offset);
+ pid = mk_pid(pid_ns, map, offset);
}
return -1;
}
-static int next_pidmap(struct pspace *pspace, int last)
+static int next_pidmap(struct pid_namespace *pid_ns, int last)
{
int offset;
struct pidmap *map, *end;
offset = (last + 1) & BITS_PER_PAGE_MASK;
- map = &pspace->pidmap[(last + 1)/BITS_PER_PAGE];
- end = &pspace->pidmap[PIDMAP_ENTRIES];
+ map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
+ end = &pid_ns->pidmap[PIDMAP_ENTRIES];
for (; map < end; map++, offset = 0) {
if (unlikely(!map->page))
continue;
offset = find_next_bit((map)->page, BITS_PER_PAGE, offset);
if (offset < BITS_PER_PAGE)
- return mk_pid(pspace, map, offset);
+ return mk_pid(pid_ns, map, offset);
}
return -1;
}
@@ -192,7 +197,7 @@ fastcall void free_pid(struct pid *pid)
hlist_del_rcu(&pid->pid_chain);
spin_unlock_irqrestore(&pidmap_lock, flags);
- free_pidmap(&init_pspace, pid->nr);
+ free_pidmap(&init_pid_ns, pid->nr);
call_rcu(&pid->rcu, delayed_put_pid);
}
@@ -206,7 +211,7 @@ struct pid *alloc_pid(void)
if (!pid)
goto out;
- nr = alloc_pidmap(&init_pspace);
+ nr = alloc_pidmap(current->nsproxy->pid_ns);
if (nr < 0)
goto out_free;
@@ -348,13 +353,33 @@ struct pid *find_ge_pid(int nr)
pid = find_pid(nr);
if (pid)
break;
- nr = next_pidmap(&init_pspace, nr);
+ nr = next_pidmap(current->nsproxy->pid_ns, nr);
} while (nr > 0);
return pid;
}
EXPORT_SYMBOL_GPL(find_get_pid);
+int copy_pid_ns(int flags, struct task_struct *tsk)
+{
+ struct pid_namespace *old_ns = tsk->nsproxy->pid_ns;
+ int err = 0;
+
+ if (!old_ns)
+ return 0;
+
+ get_pid_ns(old_ns);
+ return err;
+}
+
+void free_pid_ns(struct kref *kref)
+{
+ struct pid_namespace *ns;
+
+ ns = container_of(kref, struct pid_namespace, kref);
+ kfree(ns);
+}
+
/*
* The pid hash table is scaled according to the amount of memory in the
* machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or
@@ -382,10 +407,10 @@ void __init pidhash_init(void)
void __init pidmap_init(void)
{
- init_pspace.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ init_pid_ns.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
/* Reserve PID 0. We never call free_pidmap(0) */
- set_bit(0, init_pspace.pidmap[0].page);
- atomic_dec(&init_pspace.pidmap[0].nr_free);
+ set_bit(0, init_pid_ns.pidmap[0].page);
+ atomic_dec(&init_pid_ns.pidmap[0].nr_free);
pid_cachep = kmem_cache_create("pid", sizeof(struct pid),
__alignof__(struct pid),
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 710ed084e7c..ed296225dcd 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -20,13 +20,14 @@ config PM
sending the processor to sleep and saving power.
config PM_LEGACY
- bool "Legacy Power Management API"
+ bool "Legacy Power Management API (DEPRECATED)"
depends on PM
- default y
+ default n
---help---
- Support for pm_register() and friends.
+ Support for pm_register() and friends. This old API is obsoleted
+ by the driver model.
- If unsure, say Y.
+ If unsure, say N.
config PM_DEBUG
bool "Power Management Debug Support"
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 0b00f56c2ad..88fc5d7ac73 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -60,9 +60,11 @@ static void power_down(suspend_disk_method_t mode)
{
switch(mode) {
case PM_DISK_PLATFORM:
- kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
- pm_ops->enter(PM_SUSPEND_DISK);
- break;
+ if (pm_ops && pm_ops->enter) {
+ kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+ pm_ops->enter(PM_SUSPEND_DISK);
+ break;
+ }
case PM_DISK_SHUTDOWN:
kernel_power_off();
break;
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 500eb87f643..ff3a6182f5f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -29,7 +29,7 @@
DEFINE_MUTEX(pm_mutex);
struct pm_ops *pm_ops;
-suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
+suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM;
/**
* pm_set_ops - Set the global power method table.
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 99eeb119b06..6d566bf7085 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -28,8 +28,7 @@ static inline int freezeable(struct task_struct * p)
if ((p == current) ||
(p->flags & PF_NOFREEZE) ||
(p->exit_state == EXIT_ZOMBIE) ||
- (p->exit_state == EXIT_DEAD) ||
- (p->state == TASK_STOPPED))
+ (p->exit_state == EXIT_DEAD))
return 0;
return 1;
}
@@ -61,10 +60,16 @@ static inline void freeze_process(struct task_struct *p)
unsigned long flags;
if (!freezing(p)) {
- freeze(p);
- spin_lock_irqsave(&p->sighand->siglock, flags);
- signal_wake_up(p, 0);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ rmb();
+ if (!frozen(p)) {
+ if (p->state == TASK_STOPPED)
+ force_sig_specific(SIGSTOP, p);
+
+ freeze(p);
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ signal_wake_up(p, p->state == TASK_STOPPED);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ }
}
}
@@ -103,9 +108,7 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space)
if (frozen(p))
continue;
- if (p->state == TASK_TRACED &&
- (frozen(p->parent) ||
- p->parent->state == TASK_STOPPED)) {
+ if (p->state == TASK_TRACED && frozen(p->parent)) {
cancel_freezing(p);
continue;
}
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index f133d4a6d81..3581f8f86ac 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -165,14 +165,15 @@ static int swsusp_swap_check(void) /* This is called before saving image */
{
int res;
- res = swap_type_of(swsusp_resume_device, swsusp_resume_block);
+ res = swap_type_of(swsusp_resume_device, swsusp_resume_block,
+ &resume_bdev);
if (res < 0)
return res;
root_swap = res;
- resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_WRITE);
- if (IS_ERR(resume_bdev))
- return PTR_ERR(resume_bdev);
+ res = blkdev_get(resume_bdev, FMODE_WRITE, O_RDWR);
+ if (res)
+ return res;
res = set_blocksize(resume_bdev, PAGE_SIZE);
if (res < 0)
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 89443b85163..f7b7a785a5c 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -57,7 +57,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
memset(&data->handle, 0, sizeof(struct snapshot_handle));
if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
data->swap = swsusp_resume_device ?
- swap_type_of(swsusp_resume_device, 0) : -1;
+ swap_type_of(swsusp_resume_device, 0, NULL) : -1;
data->mode = O_RDONLY;
} else {
data->swap = -1;
@@ -268,7 +268,8 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
* so we need to recode them
*/
if (old_decode_dev(arg)) {
- data->swap = swap_type_of(old_decode_dev(arg), 0);
+ data->swap = swap_type_of(old_decode_dev(arg),
+ 0, NULL);
if (data->swap < 0)
error = -ENODEV;
} else {
@@ -365,7 +366,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
swdev = old_decode_dev(swap_area.dev);
if (swdev) {
offset = swap_area.offset;
- data->swap = swap_type_of(swdev, offset);
+ data->swap = swap_type_of(swdev, offset, NULL);
if (data->swap < 0)
error = -ENODEV;
} else {
diff --git a/kernel/printk.c b/kernel/printk.c
index 185bb45eacf..c770e1a4e88 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -335,7 +335,7 @@ static void __call_console_drivers(unsigned long start, unsigned long end)
static int __read_mostly ignore_loglevel;
-int __init ignore_loglevel_setup(char *str)
+static int __init ignore_loglevel_setup(char *str)
{
ignore_loglevel = 1;
printk(KERN_INFO "debug: ignoring loglevel setting.\n");
diff --git a/kernel/profile.c b/kernel/profile.c
index fb5e03d57e9..d6579d51106 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -40,7 +40,10 @@ int (*timer_hook)(struct pt_regs *) __read_mostly;
static atomic_t *prof_buffer;
static unsigned long prof_len, prof_shift;
+
int prof_on __read_mostly;
+EXPORT_SYMBOL_GPL(prof_on);
+
static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
#ifdef CONFIG_SMP
static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
@@ -52,6 +55,7 @@ static int __init profile_setup(char * str)
{
static char __initdata schedstr[] = "schedule";
static char __initdata sleepstr[] = "sleep";
+ static char __initdata kvmstr[] = "kvm";
int par;
if (!strncmp(str, sleepstr, strlen(sleepstr))) {
@@ -63,7 +67,7 @@ static int __init profile_setup(char * str)
printk(KERN_INFO
"kernel sleep profiling enabled (shift: %ld)\n",
prof_shift);
- } else if (!strncmp(str, sleepstr, strlen(sleepstr))) {
+ } else if (!strncmp(str, schedstr, strlen(schedstr))) {
prof_on = SCHED_PROFILING;
if (str[strlen(schedstr)] == ',')
str += strlen(schedstr) + 1;
@@ -72,6 +76,15 @@ static int __init profile_setup(char * str)
printk(KERN_INFO
"kernel schedule profiling enabled (shift: %ld)\n",
prof_shift);
+ } else if (!strncmp(str, kvmstr, strlen(kvmstr))) {
+ prof_on = KVM_PROFILING;
+ if (str[strlen(kvmstr)] == ',')
+ str += strlen(kvmstr) + 1;
+ if (get_option(&str, &par))
+ prof_shift = par;
+ printk(KERN_INFO
+ "kernel KVM profiling enabled (shift: %ld)\n",
+ prof_shift);
} else if (get_option(&str, &par)) {
prof_shift = par;
prof_on = CPU_PROFILING;
@@ -387,6 +400,8 @@ void profile_hits(int type, void *__pc, unsigned int nr_hits)
}
#endif /* !CONFIG_SMP */
+EXPORT_SYMBOL_GPL(profile_hits);
+
void profile_tick(int type)
{
struct pt_regs *regs = get_irq_regs();
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index c52f981ea00..482b11ff65c 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -522,6 +522,7 @@ rcu_torture_writer(void *arg)
VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
set_user_nice(current, 19);
+ current->flags |= PF_NOFREEZE;
do {
schedule_timeout_uninterruptible(1);
@@ -561,6 +562,7 @@ rcu_torture_fakewriter(void *arg)
VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
set_user_nice(current, 19);
+ current->flags |= PF_NOFREEZE;
do {
schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
@@ -591,6 +593,7 @@ rcu_torture_reader(void *arg)
VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
set_user_nice(current, 19);
+ current->flags |= PF_NOFREEZE;
do {
idx = cur_ops->readlock();
diff --git a/kernel/relay.c b/kernel/relay.c
index 75a3a9a7efc..284e2e8b4ee 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -138,7 +138,7 @@ depopulate:
*/
struct rchan_buf *relay_create_buf(struct rchan *chan)
{
- struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
+ struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
if (!buf)
return NULL;
@@ -302,7 +302,7 @@ static struct rchan_callbacks default_channel_callbacks = {
/**
* wakeup_readers - wake up readers waiting on a channel
- * @private: the channel buffer
+ * @work: work struct that contains the the channel buffer
*
* This is the work function used to defer reader waking. The
* reason waking is deferred is that calling directly from write
@@ -322,7 +322,7 @@ static void wakeup_readers(struct work_struct *work)
*
* See relay_reset for description of effect.
*/
-static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
+static void __relay_reset(struct rchan_buf *buf, unsigned int init)
{
size_t i;
@@ -418,7 +418,7 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan,
* The channel buffer and channel buffer data structure are then freed
* automatically when the last reference is given up.
*/
-static inline void relay_close_buf(struct rchan_buf *buf)
+static void relay_close_buf(struct rchan_buf *buf)
{
buf->finalized = 1;
cancel_delayed_work(&buf->wake_readers);
@@ -426,7 +426,7 @@ static inline void relay_close_buf(struct rchan_buf *buf)
kref_put(&buf->kref, relay_remove_buf);
}
-static inline void setup_callbacks(struct rchan *chan,
+static void setup_callbacks(struct rchan *chan,
struct rchan_callbacks *cb)
{
if (!cb) {
@@ -479,7 +479,7 @@ struct rchan *relay_open(const char *base_filename,
if (!(subbuf_size && n_subbufs))
return NULL;
- chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
+ chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
if (!chan)
return NULL;
@@ -946,11 +946,10 @@ typedef int (*subbuf_actor_t) (size_t read_start,
/*
* relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
*/
-static inline ssize_t relay_file_read_subbufs(struct file *filp,
- loff_t *ppos,
- subbuf_actor_t subbuf_actor,
- read_actor_t actor,
- read_descriptor_t *desc)
+static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos,
+ subbuf_actor_t subbuf_actor,
+ read_actor_t actor,
+ read_descriptor_t *desc)
{
struct rchan_buf *buf = filp->private_data;
size_t read_start, avail;
@@ -959,7 +958,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp,
if (!desc->count)
return 0;
- mutex_lock(&filp->f_dentry->d_inode->i_mutex);
+ mutex_lock(&filp->f_path.dentry->d_inode->i_mutex);
do {
if (!relay_file_read_avail(buf, *ppos))
break;
@@ -979,7 +978,7 @@ static inline ssize_t relay_file_read_subbufs(struct file *filp,
*ppos = relay_file_read_end_pos(buf, read_start, ret);
}
} while (desc->count && ret);
- mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex);
return desc->written;
}
diff --git a/kernel/sched.c b/kernel/sched.c
index f385eff4682..cca93cc0dd7 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -225,8 +225,10 @@ struct rq {
unsigned long nr_uninterruptible;
unsigned long expired_timestamp;
- unsigned long long timestamp_last_tick;
+ /* Cached timestamp set by update_cpu_clock() */
+ unsigned long long most_recent_timestamp;
struct task_struct *curr, *idle;
+ unsigned long next_balance;
struct mm_struct *prev_mm;
struct prio_array *active, *expired, arrays[2];
int best_expired_prio;
@@ -426,7 +428,7 @@ static inline void task_rq_unlock(struct rq *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 12
+#define SCHEDSTAT_VERSION 14
static int show_schedstat(struct seq_file *seq, void *v)
{
@@ -464,7 +466,8 @@ static int show_schedstat(struct seq_file *seq, void *v)
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 %lu %lu %lu",
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+ "%lu",
sd->lb_cnt[itype],
sd->lb_balanced[itype],
sd->lb_failed[itype],
@@ -474,11 +477,13 @@ static int show_schedstat(struct seq_file *seq, void *v)
sd->lb_nobusyq[itype],
sd->lb_nobusyg[itype]);
}
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+ " %lu %lu %lu\n",
sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
- sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance);
+ sd->ttwu_wake_remote, sd->ttwu_move_affine,
+ sd->ttwu_move_balance);
}
preempt_enable();
#endif
@@ -547,7 +552,7 @@ rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
#endif
/*
- * rq_lock - lock a given runqueue and disable interrupts.
+ * this_rq_lock - lock this runqueue and disable interrupts.
*/
static inline struct rq *this_rq_lock(void)
__acquires(rq->lock)
@@ -938,13 +943,16 @@ static void activate_task(struct task_struct *p, struct rq *rq, int local)
{
unsigned long long now;
+ if (rt_task(p))
+ goto out;
+
now = sched_clock();
#ifdef CONFIG_SMP
if (!local) {
/* Compensate for drifting sched_clock */
struct rq *this_rq = this_rq();
- now = (now - this_rq->timestamp_last_tick)
- + rq->timestamp_last_tick;
+ now = (now - this_rq->most_recent_timestamp)
+ + rq->most_recent_timestamp;
}
#endif
@@ -959,8 +967,7 @@ static void activate_task(struct task_struct *p, struct rq *rq, int local)
(now - p->timestamp) >> 20);
}
- if (!rt_task(p))
- p->prio = recalc_task_prio(p, now);
+ p->prio = recalc_task_prio(p, now);
/*
* This checks to make sure it's not an uninterruptible task
@@ -985,7 +992,7 @@ static void activate_task(struct task_struct *p, struct rq *rq, int local)
}
}
p->timestamp = now;
-
+out:
__activate_task(p, rq);
}
@@ -1450,7 +1457,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
if (this_sd->flags & SD_WAKE_AFFINE) {
unsigned long tl = this_load;
- unsigned long tl_per_task = cpu_avg_load_per_task(this_cpu);
+ unsigned long tl_per_task;
+
+ tl_per_task = cpu_avg_load_per_task(this_cpu);
/*
* If sync wakeup then subtract the (maximum possible)
@@ -1558,6 +1567,7 @@ int fastcall wake_up_state(struct task_struct *p, unsigned int state)
return try_to_wake_up(p, state, 0);
}
+static void task_running_tick(struct rq *rq, struct task_struct *p);
/*
* Perform scheduler related setup for a newly forked process p.
* p is forked by current.
@@ -1618,7 +1628,7 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
* runqueue lock is not a problem.
*/
current->time_slice = 1;
- scheduler_tick();
+ task_running_tick(cpu_rq(cpu), current);
}
local_irq_enable();
put_cpu();
@@ -1688,8 +1698,8 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
* Not the local CPU - must adjust timestamp. This should
* get optimised away in the !CONFIG_SMP case.
*/
- p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
- + rq->timestamp_last_tick;
+ p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
+ + rq->most_recent_timestamp;
__activate_task(p, rq);
if (TASK_PREEMPTS_CURR(p, rq))
resched_task(rq->curr);
@@ -1952,6 +1962,7 @@ static void double_rq_lock(struct rq *rq1, struct rq *rq2)
__acquires(rq1->lock)
__acquires(rq2->lock)
{
+ BUG_ON(!irqs_disabled());
if (rq1 == rq2) {
spin_lock(&rq1->lock);
__acquire(rq2->lock); /* Fake it out ;) */
@@ -1991,6 +2002,11 @@ static void double_lock_balance(struct rq *this_rq, struct rq *busiest)
__acquires(busiest->lock)
__acquires(this_rq->lock)
{
+ if (unlikely(!irqs_disabled())) {
+ /* printk() doesn't work good under rq->lock */
+ spin_unlock(&this_rq->lock);
+ BUG_ON(1);
+ }
if (unlikely(!spin_trylock(&busiest->lock))) {
if (busiest < this_rq) {
spin_unlock(&this_rq->lock);
@@ -2061,8 +2077,8 @@ static void pull_task(struct rq *src_rq, struct prio_array *src_array,
set_task_cpu(p, this_cpu);
inc_nr_running(p, this_rq);
enqueue_task(p, this_array);
- p->timestamp = (p->timestamp - src_rq->timestamp_last_tick)
- + this_rq->timestamp_last_tick;
+ p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
+ + this_rq->most_recent_timestamp;
/*
* Note that idle threads have a prio of MAX_PRIO, for this test
* to be always true for them.
@@ -2098,10 +2114,15 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
* 2) too many balance attempts have failed.
*/
- if (sd->nr_balance_failed > sd->cache_nice_tries)
+ if (sd->nr_balance_failed > sd->cache_nice_tries) {
+#ifdef CONFIG_SCHEDSTATS
+ if (task_hot(p, rq->most_recent_timestamp, sd))
+ schedstat_inc(sd, lb_hot_gained[idle]);
+#endif
return 1;
+ }
- if (task_hot(p, rq->timestamp_last_tick, sd))
+ if (task_hot(p, rq->most_recent_timestamp, sd))
return 0;
return 1;
}
@@ -2199,11 +2220,6 @@ skip_queue:
goto skip_bitmap;
}
-#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++;
rem_load_move -= tmp->load_weight;
@@ -2241,7 +2257,7 @@ out:
static struct sched_group *
find_busiest_group(struct sched_domain *sd, int this_cpu,
unsigned long *imbalance, enum idle_type idle, int *sd_idle,
- cpumask_t *cpus)
+ cpumask_t *cpus, int *balance)
{
struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
unsigned long max_load, avg_load, total_load, this_load, total_pwr;
@@ -2270,10 +2286,14 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
unsigned long load, group_capacity;
int local_group;
int i;
+ unsigned int balance_cpu = -1, first_idle_cpu = 0;
unsigned long sum_nr_running, sum_weighted_load;
local_group = cpu_isset(this_cpu, group->cpumask);
+ if (local_group)
+ balance_cpu = first_cpu(group->cpumask);
+
/* Tally up the load of all CPUs in the group */
sum_weighted_load = sum_nr_running = avg_load = 0;
@@ -2289,9 +2309,14 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
*sd_idle = 0;
/* Bias balancing toward cpus of our domain */
- if (local_group)
+ if (local_group) {
+ if (idle_cpu(i) && !first_idle_cpu) {
+ first_idle_cpu = 1;
+ balance_cpu = i;
+ }
+
load = target_load(i, load_idx);
- else
+ } else
load = source_load(i, load_idx);
avg_load += load;
@@ -2299,6 +2324,16 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
sum_weighted_load += rq->raw_weighted_load;
}
+ /*
+ * First idle cpu or the first cpu(busiest) in this sched group
+ * is eligible for doing load balancing at this and above
+ * domains.
+ */
+ if (local_group && balance_cpu != this_cpu && balance) {
+ *balance = 0;
+ goto ret;
+ }
+
total_load += avg_load;
total_pwr += group->cpu_power;
@@ -2458,18 +2493,21 @@ small_imbalance:
pwr_now /= SCHED_LOAD_SCALE;
/* Amount of load we'd subtract */
- tmp = busiest_load_per_task*SCHED_LOAD_SCALE/busiest->cpu_power;
+ tmp = busiest_load_per_task * SCHED_LOAD_SCALE /
+ busiest->cpu_power;
if (max_load > tmp)
pwr_move += busiest->cpu_power *
min(busiest_load_per_task, max_load - tmp);
/* Amount of load we'd add */
- if (max_load*busiest->cpu_power <
- busiest_load_per_task*SCHED_LOAD_SCALE)
- tmp = max_load*busiest->cpu_power/this->cpu_power;
+ if (max_load * busiest->cpu_power <
+ busiest_load_per_task * SCHED_LOAD_SCALE)
+ tmp = max_load * busiest->cpu_power / this->cpu_power;
else
- tmp = busiest_load_per_task*SCHED_LOAD_SCALE/this->cpu_power;
- pwr_move += this->cpu_power*min(this_load_per_task, this_load + tmp);
+ tmp = busiest_load_per_task * SCHED_LOAD_SCALE /
+ this->cpu_power;
+ pwr_move += this->cpu_power *
+ min(this_load_per_task, this_load + tmp);
pwr_move /= SCHED_LOAD_SCALE;
/* Move if we gain throughput */
@@ -2490,8 +2528,8 @@ out_balanced:
*imbalance = min_load_per_task;
return group_min;
}
-ret:
#endif
+ret:
*imbalance = 0;
return NULL;
}
@@ -2540,17 +2578,17 @@ static inline unsigned long minus_1_or_zero(unsigned long n)
/*
* Check this_cpu to ensure it is balanced within domain. Attempt to move
* tasks if there is an imbalance.
- *
- * Called with this_rq unlocked.
*/
static int load_balance(int this_cpu, struct rq *this_rq,
- struct sched_domain *sd, enum idle_type idle)
+ struct sched_domain *sd, enum idle_type idle,
+ int *balance)
{
int nr_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
struct sched_group *group;
unsigned long imbalance;
struct rq *busiest;
cpumask_t cpus = CPU_MASK_ALL;
+ unsigned long flags;
/*
* When power savings policy is enabled for the parent domain, idle
@@ -2566,7 +2604,11 @@ static int load_balance(int this_cpu, struct rq *this_rq,
redo:
group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
- &cpus);
+ &cpus, balance);
+
+ if (*balance == 0)
+ goto out_balanced;
+
if (!group) {
schedstat_inc(sd, lb_nobusyg[idle]);
goto out_balanced;
@@ -2590,11 +2632,13 @@ redo:
* still unbalanced. nr_moved simply stays zero, so it is
* correctly treated as an imbalance.
*/
+ local_irq_save(flags);
double_rq_lock(this_rq, busiest);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
minus_1_or_zero(busiest->nr_running),
imbalance, sd, idle, &all_pinned);
double_rq_unlock(this_rq, busiest);
+ local_irq_restore(flags);
/* All tasks on this runqueue were pinned by CPU affinity */
if (unlikely(all_pinned)) {
@@ -2611,13 +2655,13 @@ redo:
if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
- spin_lock(&busiest->lock);
+ spin_lock_irqsave(&busiest->lock, flags);
/* don't kick the migration_thread, if the curr
* task on busiest cpu can't be moved to this_cpu
*/
if (!cpu_isset(this_cpu, busiest->curr->cpus_allowed)) {
- spin_unlock(&busiest->lock);
+ spin_unlock_irqrestore(&busiest->lock, flags);
all_pinned = 1;
goto out_one_pinned;
}
@@ -2627,7 +2671,7 @@ redo:
busiest->push_cpu = this_cpu;
active_balance = 1;
}
- spin_unlock(&busiest->lock);
+ spin_unlock_irqrestore(&busiest->lock, flags);
if (active_balance)
wake_up_process(busiest->migration_thread);
@@ -2706,7 +2750,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
redo:
group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE,
- &sd_idle, &cpus);
+ &sd_idle, &cpus, NULL);
if (!group) {
schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
goto out_balanced;
@@ -2766,14 +2810,28 @@ out_balanced:
static void idle_balance(int this_cpu, struct rq *this_rq)
{
struct sched_domain *sd;
+ int pulled_task = 0;
+ unsigned long next_balance = jiffies + 60 * HZ;
for_each_domain(this_cpu, sd) {
if (sd->flags & SD_BALANCE_NEWIDLE) {
/* If we've pulled tasks over stop searching: */
- if (load_balance_newidle(this_cpu, this_rq, sd))
+ pulled_task = load_balance_newidle(this_cpu,
+ this_rq, sd);
+ if (time_after(next_balance,
+ sd->last_balance + sd->balance_interval))
+ next_balance = sd->last_balance
+ + sd->balance_interval;
+ if (pulled_task)
break;
}
}
+ if (!pulled_task)
+ /*
+ * We are going idle. next_balance may be set based on
+ * a busy processor. So reset next_balance.
+ */
+ this_rq->next_balance = next_balance;
}
/*
@@ -2826,26 +2884,9 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
spin_unlock(&target_rq->lock);
}
-/*
- * rebalance_tick will get called every timer tick, on every CPU.
- *
- * It checks each scheduling domain to see if it is due to be balanced,
- * and initiates a balancing operation if so.
- *
- * Balancing parameters are set up in arch_init_sched_domains.
- */
-
-/* Don't have all balancing operations going off at once: */
-static inline unsigned long cpu_offset(int cpu)
-{
- return jiffies + cpu * HZ / NR_CPUS;
-}
-
-static void
-rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
+static void update_load(struct rq *this_rq)
{
- unsigned long this_load, interval, j = cpu_offset(this_cpu);
- struct sched_domain *sd;
+ unsigned long this_load;
int i, scale;
this_load = this_rq->raw_weighted_load;
@@ -2865,6 +2906,32 @@ rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
new_load += scale-1;
this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
}
+}
+
+/*
+ * run_rebalance_domains is triggered when needed from the scheduler tick.
+ *
+ * It checks each scheduling domain to see if it is due to be balanced,
+ * and initiates a balancing operation if so.
+ *
+ * Balancing parameters are set up in arch_init_sched_domains.
+ */
+static DEFINE_SPINLOCK(balancing);
+
+static void run_rebalance_domains(struct softirq_action *h)
+{
+ int this_cpu = smp_processor_id(), balance = 1;
+ struct rq *this_rq = cpu_rq(this_cpu);
+ unsigned long interval;
+ struct sched_domain *sd;
+ /*
+ * We are idle if there are no processes running. This
+ * is valid even if we are the idle process (SMT).
+ */
+ enum idle_type idle = !this_rq->nr_running ?
+ SCHED_IDLE : NOT_IDLE;
+ /* Earliest time when we have to call run_rebalance_domains again */
+ unsigned long next_balance = jiffies + 60*HZ;
for_each_domain(this_cpu, sd) {
if (!(sd->flags & SD_LOAD_BALANCE))
@@ -2879,8 +2946,13 @@ rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
if (unlikely(!interval))
interval = 1;
- if (j - sd->last_balance >= interval) {
- if (load_balance(this_cpu, this_rq, sd, idle)) {
+ if (sd->flags & SD_SERIALIZE) {
+ if (!spin_trylock(&balancing))
+ goto out;
+ }
+
+ if (time_after_eq(jiffies, sd->last_balance + interval)) {
+ if (load_balance(this_cpu, this_rq, sd, idle, &balance)) {
/*
* We've pulled tasks over so either we're no
* longer idle, or one of our SMT siblings is
@@ -2888,39 +2960,48 @@ rebalance_tick(int this_cpu, struct rq *this_rq, enum idle_type idle)
*/
idle = NOT_IDLE;
}
- sd->last_balance += interval;
+ sd->last_balance = jiffies;
}
+ if (sd->flags & SD_SERIALIZE)
+ spin_unlock(&balancing);
+out:
+ if (time_after(next_balance, sd->last_balance + interval))
+ next_balance = sd->last_balance + interval;
+
+ /*
+ * Stop the load balance at this level. There is another
+ * CPU in our sched group which is doing load balancing more
+ * actively.
+ */
+ if (!balance)
+ break;
}
+ this_rq->next_balance = next_balance;
}
#else
/*
* on UP we do not need to balance between CPUs:
*/
-static inline void rebalance_tick(int cpu, struct rq *rq, enum idle_type idle)
-{
-}
static inline void idle_balance(int cpu, struct rq *rq)
{
}
#endif
-static inline int wake_priority_sleeper(struct rq *rq)
+static inline void wake_priority_sleeper(struct rq *rq)
{
- int ret = 0;
-
#ifdef CONFIG_SCHED_SMT
+ if (!rq->nr_running)
+ return;
+
spin_lock(&rq->lock);
/*
* If an SMT sibling task has been put to sleep for priority
* reasons reschedule the idle task to see if it can now run.
*/
- if (rq->nr_running) {
+ if (rq->nr_running)
resched_task(rq->idle);
- ret = 1;
- }
spin_unlock(&rq->lock);
#endif
- return ret;
}
DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -2934,7 +3015,8 @@ EXPORT_PER_CPU_SYMBOL(kstat);
static inline void
update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
{
- p->sched_time += now - max(p->timestamp, rq->timestamp_last_tick);
+ p->sched_time += now - p->last_ran;
+ p->last_ran = rq->most_recent_timestamp = now;
}
/*
@@ -2947,8 +3029,7 @@ unsigned long long current_sched_time(const struct task_struct *p)
unsigned long flags;
local_irq_save(flags);
- ns = max(p->timestamp, task_rq(p)->timestamp_last_tick);
- ns = p->sched_time + sched_clock() - ns;
+ ns = p->sched_time + sched_clock() - p->last_ran;
local_irq_restore(flags);
return ns;
@@ -3048,35 +3129,12 @@ void account_steal_time(struct task_struct *p, cputime_t steal)
cpustat->steal = cputime64_add(cpustat->steal, tmp);
}
-/*
- * This function gets called by the timer code, with HZ frequency.
- * We call it with interrupts disabled.
- *
- * It also gets called by the fork code, when changing the parent's
- * timeslices.
- */
-void scheduler_tick(void)
+static void task_running_tick(struct rq *rq, struct task_struct *p)
{
- unsigned long long now = sched_clock();
- struct task_struct *p = current;
- int cpu = smp_processor_id();
- struct rq *rq = cpu_rq(cpu);
-
- update_cpu_clock(p, rq, now);
-
- rq->timestamp_last_tick = now;
-
- if (p == rq->idle) {
- if (wake_priority_sleeper(rq))
- goto out;
- rebalance_tick(cpu, rq, SCHED_IDLE);
- return;
- }
-
- /* Task might have expired already, but not scheduled off yet */
if (p->array != rq->active) {
+ /* Task has expired but was not scheduled yet */
set_tsk_need_resched(p);
- goto out;
+ return;
}
spin_lock(&rq->lock);
/*
@@ -3144,8 +3202,34 @@ void scheduler_tick(void)
}
out_unlock:
spin_unlock(&rq->lock);
-out:
- rebalance_tick(cpu, rq, NOT_IDLE);
+}
+
+/*
+ * This function gets called by the timer code, with HZ frequency.
+ * We call it with interrupts disabled.
+ *
+ * It also gets called by the fork code, when changing the parent's
+ * timeslices.
+ */
+void scheduler_tick(void)
+{
+ unsigned long long now = sched_clock();
+ struct task_struct *p = current;
+ int cpu = smp_processor_id();
+ struct rq *rq = cpu_rq(cpu);
+
+ update_cpu_clock(p, rq, now);
+
+ if (p == rq->idle)
+ /* Task on the idle queue */
+ wake_priority_sleeper(rq);
+ else
+ task_running_tick(rq, p);
+#ifdef CONFIG_SMP
+ update_load(rq);
+ if (time_after_eq(jiffies, rq->next_balance))
+ raise_softirq(SCHED_SOFTIRQ);
+#endif
}
#ifdef CONFIG_SCHED_SMT
@@ -3291,7 +3375,8 @@ void fastcall add_preempt_count(int val)
/*
* Spinlock count overflowing soon?
*/
- DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= PREEMPT_MASK-10);
+ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
+ PREEMPT_MASK - 10);
}
EXPORT_SYMBOL(add_preempt_count);
@@ -3345,6 +3430,8 @@ asmlinkage void __sched schedule(void)
"%s/0x%08x/%d\n",
current->comm, preempt_count(), current->pid);
debug_show_held_locks(current);
+ if (irqs_disabled())
+ print_irqtrace_events(current);
dump_stack();
}
profile_hit(SCHED_PROFILING, __builtin_return_address(0));
@@ -4530,15 +4617,6 @@ asmlinkage long sys_sched_yield(void)
return 0;
}
-static inline int __resched_legal(int expected_preempt_count)
-{
- if (unlikely(preempt_count() != expected_preempt_count))
- return 0;
- if (unlikely(system_state != SYSTEM_RUNNING))
- return 0;
- return 1;
-}
-
static void __cond_resched(void)
{
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -4558,7 +4636,8 @@ static void __cond_resched(void)
int __sched cond_resched(void)
{
- if (need_resched() && __resched_legal(0)) {
+ if (need_resched() && !(preempt_count() & PREEMPT_ACTIVE) &&
+ system_state == SYSTEM_RUNNING) {
__cond_resched();
return 1;
}
@@ -4584,7 +4663,7 @@ int cond_resched_lock(spinlock_t *lock)
ret = 1;
spin_lock(lock);
}
- if (need_resched() && __resched_legal(1)) {
+ if (need_resched() && system_state == SYSTEM_RUNNING) {
spin_release(&lock->dep_map, 1, _THIS_IP_);
_raw_spin_unlock(lock);
preempt_enable_no_resched();
@@ -4600,7 +4679,7 @@ int __sched cond_resched_softirq(void)
{
BUG_ON(!in_softirq());
- if (need_resched() && __resched_legal(0)) {
+ if (need_resched() && system_state == SYSTEM_RUNNING) {
raw_local_irq_disable();
_local_bh_enable();
raw_local_irq_enable();
@@ -4990,8 +5069,8 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
* afterwards, and pretending it was a local activate.
* This way is cleaner and logically correct.
*/
- p->timestamp = p->timestamp - rq_src->timestamp_last_tick
- + rq_dest->timestamp_last_tick;
+ p->timestamp = p->timestamp - rq_src->most_recent_timestamp
+ + rq_dest->most_recent_timestamp;
deactivate_task(p, rq_src);
__activate_task(p, rq_dest);
if (TASK_PREEMPTS_CURR(p, rq_dest))
@@ -5067,7 +5146,10 @@ wait_to_die:
}
#ifdef CONFIG_HOTPLUG_CPU
-/* Figure out where task on dead CPU should go, use force if neccessary. */
+/*
+ * Figure out where task on dead CPU should go, use force if neccessary.
+ * NOTE: interrupts should be disabled by the caller
+ */
static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
{
unsigned long flags;
@@ -5187,6 +5269,7 @@ void idle_task_exit(void)
mmdrop(mm);
}
+/* called under rq->lock with disabled interrupts */
static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
{
struct rq *rq = cpu_rq(dead_cpu);
@@ -5203,10 +5286,11 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
* Drop lock around migration; if someone else moves it,
* that's OK. No task can be added to this CPU, so iteration is
* fine.
+ * NOTE: interrupts should be left disabled --dev@
*/
- spin_unlock_irq(&rq->lock);
+ spin_unlock(&rq->lock);
move_task_off_dead_cpu(dead_cpu, p);
- spin_lock_irq(&rq->lock);
+ spin_lock(&rq->lock);
put_task_struct(p);
}
@@ -5359,16 +5443,19 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
if (!(sd->flags & SD_LOAD_BALANCE)) {
printk("does not load-balance\n");
if (sd->parent)
- printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain has parent");
+ printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain"
+ " has parent");
break;
}
printk("span %s\n", str);
if (!cpu_isset(cpu, sd->span))
- printk(KERN_ERR "ERROR: domain->span does not contain CPU%d\n", cpu);
+ printk(KERN_ERR "ERROR: domain->span does not contain "
+ "CPU%d\n", cpu);
if (!cpu_isset(cpu, group->cpumask))
- printk(KERN_ERR "ERROR: domain->groups does not contain CPU%d\n", cpu);
+ printk(KERN_ERR "ERROR: domain->groups does not contain"
+ " CPU%d\n", cpu);
printk(KERN_DEBUG);
for (i = 0; i < level + 2; i++)
@@ -5383,7 +5470,8 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
if (!group->cpu_power) {
printk("\n");
- printk(KERN_ERR "ERROR: domain->cpu_power not set\n");
+ printk(KERN_ERR "ERROR: domain->cpu_power not "
+ "set\n");
}
if (!cpus_weight(group->cpumask)) {
@@ -5406,15 +5494,17 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
printk("\n");
if (!cpus_equal(sd->span, groupmask))
- printk(KERN_ERR "ERROR: groups don't span domain->span\n");
+ printk(KERN_ERR "ERROR: groups don't span "
+ "domain->span\n");
level++;
sd = sd->parent;
+ if (!sd)
+ continue;
- if (sd) {
- if (!cpus_subset(groupmask, sd->span))
- printk(KERN_ERR "ERROR: parent span is not a superset of domain->span\n");
- }
+ if (!cpus_subset(groupmask, sd->span))
+ printk(KERN_ERR "ERROR: parent span is not a superset "
+ "of domain->span\n");
} while (sd);
}
@@ -5510,7 +5600,7 @@ static void cpu_attach_domain(struct sched_domain *sd, int cpu)
}
/* cpus with isolated domains */
-static cpumask_t __cpuinitdata cpu_isolated_map = CPU_MASK_NONE;
+static cpumask_t cpu_isolated_map = CPU_MASK_NONE;
/* Setup the mask of cpus configured for isolated domains */
static int __init isolated_cpu_setup(char *str)
@@ -5528,28 +5618,27 @@ static int __init isolated_cpu_setup(char *str)
__setup ("isolcpus=", isolated_cpu_setup);
/*
- * init_sched_build_groups takes an array of groups, the cpumask we wish
- * to span, and a pointer to a function which identifies what group a CPU
- * belongs to. The return value of group_fn must be a valid index into the
- * groups[] array, and must be >= 0 and < NR_CPUS (due to the fact that we
- * keep track of groups covered with a cpumask_t).
+ * init_sched_build_groups takes the cpumask we wish to span, and a pointer
+ * to a function which identifies what group(along with sched group) a CPU
+ * belongs to. The return value of group_fn must be a >= 0 and < NR_CPUS
+ * (due to the fact that we keep track of groups covered with a cpumask_t).
*
* init_sched_build_groups will build a circular linked list of the groups
* covered by the given span, and will set each group's ->cpumask correctly,
* and ->cpu_power to 0.
*/
static void
-init_sched_build_groups(struct sched_group groups[], cpumask_t span,
- const cpumask_t *cpu_map,
- int (*group_fn)(int cpu, const cpumask_t *cpu_map))
+init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
+ int (*group_fn)(int cpu, const cpumask_t *cpu_map,
+ struct sched_group **sg))
{
struct sched_group *first = NULL, *last = NULL;
cpumask_t covered = CPU_MASK_NONE;
int i;
for_each_cpu_mask(i, span) {
- int group = group_fn(i, cpu_map);
- struct sched_group *sg = &groups[group];
+ struct sched_group *sg;
+ int group = group_fn(i, cpu_map, &sg);
int j;
if (cpu_isset(i, covered))
@@ -5559,7 +5648,7 @@ init_sched_build_groups(struct sched_group groups[], cpumask_t span,
sg->cpu_power = 0;
for_each_cpu_mask(j, span) {
- if (group_fn(j, cpu_map) != group)
+ if (group_fn(j, cpu_map, NULL) != group)
continue;
cpu_set(j, covered);
@@ -5733,8 +5822,9 @@ __setup("max_cache_size=", setup_max_cache_size);
*/
static void touch_cache(void *__cache, unsigned long __size)
{
- unsigned long size = __size/sizeof(long), chunk1 = size/3,
- chunk2 = 2*size/3;
+ unsigned long size = __size / sizeof(long);
+ unsigned long chunk1 = size / 3;
+ unsigned long chunk2 = 2 * size / 3;
unsigned long *cache = __cache;
int i;
@@ -5843,11 +5933,11 @@ measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
*/
measure_one(cache, size, cpu1, cpu2);
for (i = 0; i < ITERATIONS; i++)
- cost1 += measure_one(cache, size - i*1024, cpu1, cpu2);
+ cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
measure_one(cache, size, cpu2, cpu1);
for (i = 0; i < ITERATIONS; i++)
- cost1 += measure_one(cache, size - i*1024, cpu2, cpu1);
+ cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
/*
* (We measure the non-migrating [cached] cost on both
@@ -5857,17 +5947,17 @@ measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
measure_one(cache, size, cpu1, cpu1);
for (i = 0; i < ITERATIONS; i++)
- cost2 += measure_one(cache, size - i*1024, cpu1, cpu1);
+ cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
measure_one(cache, size, cpu2, cpu2);
for (i = 0; i < ITERATIONS; i++)
- cost2 += measure_one(cache, size - i*1024, cpu2, cpu2);
+ cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
/*
* Get the per-iteration migration cost:
*/
- do_div(cost1, 2*ITERATIONS);
- do_div(cost2, 2*ITERATIONS);
+ do_div(cost1, 2 * ITERATIONS);
+ do_div(cost2, 2 * ITERATIONS);
return cost1 - cost2;
}
@@ -5905,7 +5995,7 @@ static unsigned long long measure_migration_cost(int cpu1, int cpu2)
*/
cache = vmalloc(max_size);
if (!cache) {
- printk("could not vmalloc %d bytes for cache!\n", 2*max_size);
+ printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
return 1000000; /* return 1 msec on very small boxen */
}
@@ -5930,7 +6020,8 @@ static unsigned long long measure_migration_cost(int cpu1, int cpu2)
avg_fluct = (avg_fluct + fluct)/2;
if (migration_debug)
- printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): (%8Ld %8Ld)\n",
+ printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
+ "(%8Ld %8Ld)\n",
cpu1, cpu2, size,
(long)cost / 1000000,
((long)cost / 100000) % 10,
@@ -6025,20 +6116,18 @@ static void calibrate_migration_costs(const cpumask_t *cpu_map)
-1
#endif
);
- if (system_state == SYSTEM_BOOTING) {
- if (num_online_cpus() > 1) {
- printk("migration_cost=");
- for (distance = 0; distance <= max_distance; distance++) {
- if (distance)
- printk(",");
- printk("%ld", (long)migration_cost[distance] / 1000);
- }
- printk("\n");
+ if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
+ printk("migration_cost=");
+ for (distance = 0; distance <= max_distance; distance++) {
+ if (distance)
+ printk(",");
+ printk("%ld", (long)migration_cost[distance] / 1000);
}
+ printk("\n");
}
j1 = jiffies;
if (migration_debug)
- printk("migration: %ld seconds\n", (j1-j0)/HZ);
+ printk("migration: %ld seconds\n", (j1-j0) / HZ);
/*
* Move back to the original CPU. NUMA-Q gets confused
@@ -6135,10 +6224,13 @@ int sched_smt_power_savings = 0, sched_mc_power_savings = 0;
*/
#ifdef CONFIG_SCHED_SMT
static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static struct sched_group sched_group_cpus[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_cpus);
-static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map,
+ struct sched_group **sg)
{
+ if (sg)
+ *sg = &per_cpu(sched_group_cpus, cpu);
return cpu;
}
#endif
@@ -6148,39 +6240,52 @@ static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map)
*/
#ifdef CONFIG_SCHED_MC
static DEFINE_PER_CPU(struct sched_domain, core_domains);
-static struct sched_group sched_group_core[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_core);
#endif
#if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
-static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map,
+ struct sched_group **sg)
{
+ int group;
cpumask_t mask = cpu_sibling_map[cpu];
cpus_and(mask, mask, *cpu_map);
- return first_cpu(mask);
+ group = first_cpu(mask);
+ if (sg)
+ *sg = &per_cpu(sched_group_core, group);
+ return group;
}
#elif defined(CONFIG_SCHED_MC)
-static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map,
+ struct sched_group **sg)
{
+ if (sg)
+ *sg = &per_cpu(sched_group_core, cpu);
return cpu;
}
#endif
static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static struct sched_group sched_group_phys[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_phys);
-static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map,
+ struct sched_group **sg)
{
+ int group;
#ifdef CONFIG_SCHED_MC
cpumask_t mask = cpu_coregroup_map(cpu);
cpus_and(mask, mask, *cpu_map);
- return first_cpu(mask);
+ group = first_cpu(mask);
#elif defined(CONFIG_SCHED_SMT)
cpumask_t mask = cpu_sibling_map[cpu];
cpus_and(mask, mask, *cpu_map);
- return first_cpu(mask);
+ group = first_cpu(mask);
#else
- return cpu;
+ group = cpu;
#endif
+ if (sg)
+ *sg = &per_cpu(sched_group_phys, group);
+ return group;
}
#ifdef CONFIG_NUMA
@@ -6193,12 +6298,22 @@ static DEFINE_PER_CPU(struct sched_domain, node_domains);
static struct sched_group **sched_group_nodes_bycpu[NR_CPUS];
static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
-static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS];
+static DEFINE_PER_CPU(struct sched_group, sched_group_allnodes);
-static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map)
+static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map,
+ struct sched_group **sg)
{
- return cpu_to_node(cpu);
+ cpumask_t nodemask = node_to_cpumask(cpu_to_node(cpu));
+ int group;
+
+ cpus_and(nodemask, nodemask, *cpu_map);
+ group = first_cpu(nodemask);
+
+ if (sg)
+ *sg = &per_cpu(sched_group_allnodes, group);
+ return group;
}
+
static void init_numa_sched_groups_power(struct sched_group *group_head)
{
struct sched_group *sg = group_head;
@@ -6234,16 +6349,9 @@ static void free_sched_groups(const cpumask_t *cpu_map)
int cpu, i;
for_each_cpu_mask(cpu, *cpu_map) {
- struct sched_group *sched_group_allnodes
- = sched_group_allnodes_bycpu[cpu];
struct sched_group **sched_group_nodes
= sched_group_nodes_bycpu[cpu];
- if (sched_group_allnodes) {
- kfree(sched_group_allnodes);
- sched_group_allnodes_bycpu[cpu] = NULL;
- }
-
if (!sched_group_nodes)
continue;
@@ -6337,7 +6445,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
struct sched_domain *sd;
#ifdef CONFIG_NUMA
struct sched_group **sched_group_nodes = NULL;
- struct sched_group *sched_group_allnodes = NULL;
+ int sd_allnodes = 0;
/*
* Allocate the per-node list of sched groups
@@ -6355,7 +6463,6 @@ static int build_sched_domains(const cpumask_t *cpu_map)
* Set up domains for cpus specified by the cpu_map.
*/
for_each_cpu_mask(i, *cpu_map) {
- int group;
struct sched_domain *sd = NULL, *p;
cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
@@ -6364,26 +6471,12 @@ static int build_sched_domains(const cpumask_t *cpu_map)
#ifdef CONFIG_NUMA
if (cpus_weight(*cpu_map)
> SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
- if (!sched_group_allnodes) {
- sched_group_allnodes
- = kmalloc_node(sizeof(struct sched_group)
- * MAX_NUMNODES,
- GFP_KERNEL,
- cpu_to_node(i));
- if (!sched_group_allnodes) {
- printk(KERN_WARNING
- "Can not alloc allnodes sched group\n");
- goto error;
- }
- sched_group_allnodes_bycpu[i]
- = sched_group_allnodes;
- }
sd = &per_cpu(allnodes_domains, i);
*sd = SD_ALLNODES_INIT;
sd->span = *cpu_map;
- group = cpu_to_allnodes_group(i, cpu_map);
- sd->groups = &sched_group_allnodes[group];
+ cpu_to_allnodes_group(i, cpu_map, &sd->groups);
p = sd;
+ sd_allnodes = 1;
} else
p = NULL;
@@ -6398,36 +6491,33 @@ static int build_sched_domains(const cpumask_t *cpu_map)
p = sd;
sd = &per_cpu(phys_domains, i);
- group = cpu_to_phys_group(i, cpu_map);
*sd = SD_CPU_INIT;
sd->span = nodemask;
sd->parent = p;
if (p)
p->child = sd;
- sd->groups = &sched_group_phys[group];
+ cpu_to_phys_group(i, cpu_map, &sd->groups);
#ifdef CONFIG_SCHED_MC
p = sd;
sd = &per_cpu(core_domains, i);
- group = cpu_to_core_group(i, cpu_map);
*sd = SD_MC_INIT;
sd->span = cpu_coregroup_map(i);
cpus_and(sd->span, sd->span, *cpu_map);
sd->parent = p;
p->child = sd;
- sd->groups = &sched_group_core[group];
+ cpu_to_core_group(i, cpu_map, &sd->groups);
#endif
#ifdef CONFIG_SCHED_SMT
p = sd;
sd = &per_cpu(cpu_domains, i);
- group = cpu_to_cpu_group(i, cpu_map);
*sd = SD_SIBLING_INIT;
sd->span = cpu_sibling_map[i];
cpus_and(sd->span, sd->span, *cpu_map);
sd->parent = p;
p->child = sd;
- sd->groups = &sched_group_cpus[group];
+ cpu_to_cpu_group(i, cpu_map, &sd->groups);
#endif
}
@@ -6439,8 +6529,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
if (i != first_cpu(this_sibling_map))
continue;
- init_sched_build_groups(sched_group_cpus, this_sibling_map,
- cpu_map, &cpu_to_cpu_group);
+ init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group);
}
#endif
@@ -6451,8 +6540,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
cpus_and(this_core_map, this_core_map, *cpu_map);
if (i != first_cpu(this_core_map))
continue;
- init_sched_build_groups(sched_group_core, this_core_map,
- cpu_map, &cpu_to_core_group);
+ init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group);
}
#endif
@@ -6465,15 +6553,13 @@ static int build_sched_domains(const cpumask_t *cpu_map)
if (cpus_empty(nodemask))
continue;
- init_sched_build_groups(sched_group_phys, nodemask,
- cpu_map, &cpu_to_phys_group);
+ init_sched_build_groups(nodemask, cpu_map, &cpu_to_phys_group);
}
#ifdef CONFIG_NUMA
/* Set up node groups */
- if (sched_group_allnodes)
- init_sched_build_groups(sched_group_allnodes, *cpu_map,
- cpu_map, &cpu_to_allnodes_group);
+ if (sd_allnodes)
+ init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group);
for (i = 0; i < MAX_NUMNODES; i++) {
/* Set up node groups */
@@ -6565,10 +6651,10 @@ static int build_sched_domains(const cpumask_t *cpu_map)
for (i = 0; i < MAX_NUMNODES; i++)
init_numa_sched_groups_power(sched_group_nodes[i]);
- if (sched_group_allnodes) {
- int group = cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map);
- struct sched_group *sg = &sched_group_allnodes[group];
+ if (sd_allnodes) {
+ struct sched_group *sg;
+ cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg);
init_numa_sched_groups_power(sg);
}
#endif
@@ -6779,7 +6865,7 @@ void __init sched_init_smp(void)
lock_cpu_hotplug();
arch_init_sched_domains(&cpu_online_map);
- cpus_andnot(non_isolated_cpus, cpu_online_map, cpu_isolated_map);
+ cpus_andnot(non_isolated_cpus, cpu_possible_map, cpu_isolated_map);
if (cpus_empty(non_isolated_cpus))
cpu_set(smp_processor_id(), non_isolated_cpus);
unlock_cpu_hotplug();
@@ -6847,6 +6933,10 @@ void __init sched_init(void)
set_load_weight(&init_task);
+#ifdef CONFIG_SMP
+ open_softirq(SCHED_SOFTIRQ, run_rebalance_domains, NULL);
+#endif
+
#ifdef CONFIG_RT_MUTEXES
plist_head_init(&init_task.pi_waiters, &init_task.pi_lock);
#endif
@@ -6882,6 +6972,8 @@ void __might_sleep(char *file, int line)
printk("in_atomic():%d, irqs_disabled():%d\n",
in_atomic(), irqs_disabled());
debug_show_held_locks(current);
+ if (irqs_disabled())
+ print_irqtrace_events(current);
dump_stack();
}
#endif
diff --git a/kernel/signal.c b/kernel/signal.c
index ec81defde33..5630255d2e2 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -24,6 +24,9 @@
#include <linux/signal.h>
#include <linux/capability.h>
#include <linux/freezer.h>
+#include <linux/pid_namespace.h>
+#include <linux/nsproxy.h>
+
#include <asm/param.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -583,7 +586,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
error = -EPERM;
if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
&& ((sig != SIGCONT) ||
- (current->signal->session != t->signal->session))
+ (process_session(current) != process_session(t)))
&& (current->euid ^ t->suid) && (current->euid ^ t->uid)
&& (current->uid ^ t->suid) && (current->uid ^ t->uid)
&& !capable(CAP_KILL))
@@ -1702,7 +1705,9 @@ finish_stop(int stop_count)
read_unlock(&tasklist_lock);
}
- schedule();
+ do {
+ schedule();
+ } while (try_to_freeze());
/*
* Now we don't run again until continued.
*/
@@ -1877,8 +1882,12 @@ relock:
if (sig_kernel_ignore(signr)) /* Default is nothing. */
continue;
- /* Init gets no signals it doesn't want. */
- if (current == child_reaper)
+ /*
+ * Init of a pid space gets no signals it doesn't want from
+ * within that pid space. It can of course get signals from
+ * its parent pid space.
+ */
+ if (current == child_reaper(current))
continue;
if (sig_kernel_stop(signr)) {
diff --git a/kernel/sys.c b/kernel/sys.c
index a0c1a29a507..6e2101dec0f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -323,11 +323,18 @@ EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
unsigned long val, void *v)
{
- int ret;
+ int ret = NOTIFY_DONE;
- down_read(&nh->rwsem);
- ret = notifier_call_chain(&nh->head, val, v);
- up_read(&nh->rwsem);
+ /*
+ * We check the head outside the lock, but if this access is
+ * racy then it does not matter what the result of the test
+ * is, we re-check the list after having taken the lock anyway:
+ */
+ if (rcu_dereference(nh->head)) {
+ down_read(&nh->rwsem);
+ ret = notifier_call_chain(&nh->head, val, v);
+ up_read(&nh->rwsem);
+ }
return ret;
}
@@ -1381,7 +1388,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
if (p->real_parent == group_leader) {
err = -EPERM;
- if (p->signal->session != group_leader->signal->session)
+ if (process_session(p) != process_session(group_leader))
goto out;
err = -EACCES;
if (p->did_exec)
@@ -1397,16 +1404,13 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
goto out;
if (pgid != pid) {
- struct task_struct *p;
+ struct task_struct *g =
+ find_task_by_pid_type(PIDTYPE_PGID, pgid);
- do_each_task_pid(pgid, PIDTYPE_PGID, p) {
- if (p->signal->session == group_leader->signal->session)
- goto ok_pgid;
- } while_each_task_pid(pgid, PIDTYPE_PGID, p);
- goto out;
+ if (!g || process_session(g) != process_session(group_leader))
+ goto out;
}
-ok_pgid:
err = security_task_setpgid(p, pgid);
if (err)
goto out;
@@ -1459,7 +1463,7 @@ asmlinkage long sys_getpgrp(void)
asmlinkage long sys_getsid(pid_t pid)
{
if (!pid)
- return current->signal->session;
+ return process_session(current);
else {
int retval;
struct task_struct *p;
@@ -1471,7 +1475,7 @@ asmlinkage long sys_getsid(pid_t pid)
if (p) {
retval = security_task_getsid(p);
if (!retval)
- retval = p->signal->session;
+ retval = process_session(p);
}
read_unlock(&tasklist_lock);
return retval;
@@ -1484,7 +1488,6 @@ asmlinkage long sys_setsid(void)
pid_t session;
int err = -EPERM;
- mutex_lock(&tty_mutex);
write_lock_irq(&tasklist_lock);
/* Fail if I am already a session leader */
@@ -1504,12 +1507,15 @@ asmlinkage long sys_setsid(void)
group_leader->signal->leader = 1;
__set_special_pids(session, session);
+
+ spin_lock(&group_leader->sighand->siglock);
group_leader->signal->tty = NULL;
group_leader->signal->tty_old_pgrp = 0;
+ spin_unlock(&group_leader->sighand->siglock);
+
err = process_group(group_leader);
out:
write_unlock_irq(&tasklist_lock);
- mutex_unlock(&tty_mutex);
return err;
}
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8e9f00fd6d1..600b33358de 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -65,7 +65,6 @@ extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern int sysctl_panic_on_oom;
extern int max_threads;
-extern int sysrq_enabled;
extern int core_uses_pid;
extern int suid_dumpable;
extern char core_pattern[];
@@ -92,7 +91,9 @@ extern char modprobe_path[];
extern int sg_big_buff;
#endif
#ifdef CONFIG_SYSVIPC
-static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
@@ -131,12 +132,22 @@ extern int max_lock_depth;
#ifdef CONFIG_SYSCTL_SYSCALL
static int parse_table(int __user *, int, void __user *, size_t __user *,
- void __user *, size_t, ctl_table *, void **);
+ void __user *, size_t, ctl_table *);
#endif
static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen);
+
+#ifdef CONFIG_SYSVIPC
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen);
+#endif
+
#ifdef CONFIG_PROC_SYSCTL
static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -163,6 +174,40 @@ extern ctl_table inotify_table[];
int sysctl_legacy_va_layout;
#endif
+static void *get_uts(ctl_table *table, int write)
+{
+ char *which = table->data;
+#ifdef CONFIG_UTS_NS
+ struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
+ which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
+#endif
+ if (!write)
+ down_read(&uts_sem);
+ else
+ down_write(&uts_sem);
+ return which;
+}
+
+static void put_uts(ctl_table *table, int write, void *which)
+{
+ if (!write)
+ up_read(&uts_sem);
+ else
+ up_write(&uts_sem);
+}
+
+#ifdef CONFIG_SYSVIPC
+static void *get_ipc(ctl_table *table, int write)
+{
+ char *which = table->data;
+ struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+ which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
+ return which;
+}
+#else
+#define get_ipc(T,W) ((T)->data)
+#endif
+
/* /proc declarations: */
#ifdef CONFIG_PROC_SYSCTL
@@ -229,7 +274,6 @@ static ctl_table root_table[] = {
};
static ctl_table kern_table[] = {
-#ifndef CONFIG_UTS_NS
{
.ctl_name = KERN_OSTYPE,
.procname = "ostype",
@@ -237,7 +281,7 @@ static ctl_table kern_table[] = {
.maxlen = sizeof(init_uts_ns.name.sysname),
.mode = 0444,
.proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
+ .strategy = &sysctl_uts_string,
},
{
.ctl_name = KERN_OSRELEASE,
@@ -246,7 +290,7 @@ static ctl_table kern_table[] = {
.maxlen = sizeof(init_uts_ns.name.release),
.mode = 0444,
.proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
+ .strategy = &sysctl_uts_string,
},
{
.ctl_name = KERN_VERSION,
@@ -255,7 +299,7 @@ static ctl_table kern_table[] = {
.maxlen = sizeof(init_uts_ns.name.version),
.mode = 0444,
.proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
+ .strategy = &sysctl_uts_string,
},
{
.ctl_name = KERN_NODENAME,
@@ -264,7 +308,7 @@ static ctl_table kern_table[] = {
.maxlen = sizeof(init_uts_ns.name.nodename),
.mode = 0644,
.proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
+ .strategy = &sysctl_uts_string,
},
{
.ctl_name = KERN_DOMAINNAME,
@@ -273,56 +317,8 @@ static ctl_table kern_table[] = {
.maxlen = sizeof(init_uts_ns.name.domainname),
.mode = 0644,
.proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
- },
-#else /* !CONFIG_UTS_NS */
- {
- .ctl_name = KERN_OSTYPE,
- .procname = "ostype",
- .data = NULL,
- /* could maybe use __NEW_UTS_LEN here? */
- .maxlen = FIELD_SIZEOF(struct new_utsname, sysname),
- .mode = 0444,
- .proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
- },
- {
- .ctl_name = KERN_OSRELEASE,
- .procname = "osrelease",
- .data = NULL,
- .maxlen = FIELD_SIZEOF(struct new_utsname, release),
- .mode = 0444,
- .proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
- },
- {
- .ctl_name = KERN_VERSION,
- .procname = "version",
- .data = NULL,
- .maxlen = FIELD_SIZEOF(struct new_utsname, version),
- .mode = 0444,
- .proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
- },
- {
- .ctl_name = KERN_NODENAME,
- .procname = "hostname",
- .data = NULL,
- .maxlen = FIELD_SIZEOF(struct new_utsname, nodename),
- .mode = 0644,
- .proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
- },
- {
- .ctl_name = KERN_DOMAINNAME,
- .procname = "domainname",
- .data = NULL,
- .maxlen = FIELD_SIZEOF(struct new_utsname, domainname),
- .mode = 0644,
- .proc_handler = &proc_do_uts_string,
- .strategy = &sysctl_string,
+ .strategy = &sysctl_uts_string,
},
-#endif /* !CONFIG_UTS_NS */
{
.ctl_name = KERN_PANIC,
.procname = "panic",
@@ -481,65 +477,72 @@ static ctl_table kern_table[] = {
{
.ctl_name = KERN_SHMMAX,
.procname = "shmmax",
- .data = NULL,
- .maxlen = sizeof (size_t),
+ .data = &init_ipc_ns.shm_ctlmax,
+ .maxlen = sizeof (init_ipc_ns.shm_ctlmax),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_doulongvec_minmax,
+ .strategy = sysctl_ipc_data,
},
{
.ctl_name = KERN_SHMALL,
.procname = "shmall",
- .data = NULL,
- .maxlen = sizeof (size_t),
+ .data = &init_ipc_ns.shm_ctlall,
+ .maxlen = sizeof (init_ipc_ns.shm_ctlall),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_doulongvec_minmax,
+ .strategy = sysctl_ipc_data,
},
{
.ctl_name = KERN_SHMMNI,
.procname = "shmmni",
- .data = NULL,
- .maxlen = sizeof (int),
+ .data = &init_ipc_ns.shm_ctlmni,
+ .maxlen = sizeof (init_ipc_ns.shm_ctlmni),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_dointvec,
+ .strategy = sysctl_ipc_data,
},
{
.ctl_name = KERN_MSGMAX,
.procname = "msgmax",
- .data = NULL,
- .maxlen = sizeof (int),
+ .data = &init_ipc_ns.msg_ctlmax,
+ .maxlen = sizeof (init_ipc_ns.msg_ctlmax),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_dointvec,
+ .strategy = sysctl_ipc_data,
},
{
.ctl_name = KERN_MSGMNI,
.procname = "msgmni",
- .data = NULL,
- .maxlen = sizeof (int),
+ .data = &init_ipc_ns.msg_ctlmni,
+ .maxlen = sizeof (init_ipc_ns.msg_ctlmni),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_dointvec,
+ .strategy = sysctl_ipc_data,
},
{
.ctl_name = KERN_MSGMNB,
.procname = "msgmnb",
- .data = NULL,
- .maxlen = sizeof (int),
+ .data = &init_ipc_ns.msg_ctlmnb,
+ .maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_dointvec,
+ .strategy = sysctl_ipc_data,
},
{
.ctl_name = KERN_SEM,
.procname = "sem",
- .data = NULL,
+ .data = &init_ipc_ns.sem_ctls,
.maxlen = 4*sizeof (int),
.mode = 0644,
- .proc_handler = &proc_do_ipc_string,
+ .proc_handler = &proc_ipc_dointvec,
+ .strategy = sysctl_ipc_data,
},
#endif
#ifdef CONFIG_MAGIC_SYSRQ
{
.ctl_name = KERN_SYSRQ,
.procname = "sysrq",
- .data = &sysrq_enabled,
+ .data = &__sysrq_enabled,
.maxlen = sizeof (int),
.mode = 0644,
.proc_handler = &proc_dointvec,
@@ -1239,7 +1242,6 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
do {
struct ctl_table_header *head =
list_entry(tmp, struct ctl_table_header, ctl_entry);
- void *context = NULL;
if (!use_table(head))
continue;
@@ -1247,9 +1249,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
spin_unlock(&sysctl_lock);
error = parse_table(name, nlen, oldval, oldlenp,
- newval, newlen, head->ctl_table,
- &context);
- kfree(context);
+ newval, newlen, head->ctl_table);
spin_lock(&sysctl_lock);
unuse_table(head);
@@ -1305,7 +1305,7 @@ static inline int ctl_perm(ctl_table *table, int op)
static int parse_table(int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen,
- ctl_table *table, void **context)
+ ctl_table *table)
{
int n;
repeat:
@@ -1325,7 +1325,7 @@ repeat:
error = table->strategy(
table, name, nlen,
oldval, oldlenp,
- newval, newlen, context);
+ newval, newlen);
if (error)
return error;
}
@@ -1336,7 +1336,7 @@ repeat:
}
error = do_sysctl_strategy(table, name, nlen,
oldval, oldlenp,
- newval, newlen, context);
+ newval, newlen);
return error;
}
}
@@ -1347,7 +1347,7 @@ repeat:
int do_sysctl_strategy (ctl_table *table,
int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
int op = 0, rc;
size_t len;
@@ -1361,7 +1361,7 @@ int do_sysctl_strategy (ctl_table *table,
if (table->strategy) {
rc = table->strategy(table, name, nlen, oldval, oldlenp,
- newval, newlen, context);
+ newval, newlen);
if (rc < 0)
return rc;
if (rc > 0)
@@ -1614,7 +1614,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
int op;
- struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
struct ctl_table *table;
size_t res;
ssize_t error = -ENOTDIR;
@@ -1753,66 +1753,17 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
* Special case of dostring for the UTS structure. This has locks
* to observe. Should this be in kernel/sys.c ????
*/
-
-#ifndef CONFIG_UTS_NS
-static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- if (!write) {
- down_read(&uts_sem);
- r=proc_dostring(table,0,filp,buffer,lenp, ppos);
- up_read(&uts_sem);
- } else {
- down_write(&uts_sem);
- r=proc_dostring(table,1,filp,buffer,lenp, ppos);
- up_write(&uts_sem);
- }
- return r;
-}
-#else /* !CONFIG_UTS_NS */
static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int r;
- struct uts_namespace* uts_ns = current->nsproxy->uts_ns;
- char* which;
-
- switch (table->ctl_name) {
- case KERN_OSTYPE:
- which = uts_ns->name.sysname;
- break;
- case KERN_NODENAME:
- which = uts_ns->name.nodename;
- break;
- case KERN_OSRELEASE:
- which = uts_ns->name.release;
- break;
- case KERN_VERSION:
- which = uts_ns->name.version;
- break;
- case KERN_DOMAINNAME:
- which = uts_ns->name.domainname;
- break;
- default:
- r = -EINVAL;
- goto out;
- }
-
- if (!write) {
- down_read(&uts_sem);
- r=_proc_do_string(which,table->maxlen,0,filp,buffer,lenp, ppos);
- up_read(&uts_sem);
- } else {
- down_write(&uts_sem);
- r=_proc_do_string(which,table->maxlen,1,filp,buffer,lenp, ppos);
- up_write(&uts_sem);
- }
- out:
+ void *which;
+ which = get_uts(table, write);
+ r = _proc_do_string(which, table->maxlen,write,filp,buffer,lenp, ppos);
+ put_uts(table, write, which);
return r;
}
-#endif /* !CONFIG_UTS_NS */
static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
int *valp,
@@ -1976,9 +1927,6 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
#define OP_SET 0
#define OP_AND 1
-#define OP_OR 2
-#define OP_MAX 3
-#define OP_MIN 4
static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
int *valp,
@@ -1990,13 +1938,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
switch(op) {
case OP_SET: *valp = val; break;
case OP_AND: *valp &= val; break;
- case OP_OR: *valp |= val; break;
- case OP_MAX: if(*valp < val)
- *valp = val;
- break;
- case OP_MIN: if(*valp > val)
- *valp = val;
- break;
}
} else {
int val = *valp;
@@ -2391,46 +2332,24 @@ int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
}
#ifdef CONFIG_SYSVIPC
-static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
{
- void *data;
- struct ipc_namespace *ns;
-
- ns = current->nsproxy->ipc_ns;
-
- switch (table->ctl_name) {
- case KERN_SHMMAX:
- data = &ns->shm_ctlmax;
- goto proc_minmax;
- case KERN_SHMALL:
- data = &ns->shm_ctlall;
- goto proc_minmax;
- case KERN_SHMMNI:
- data = &ns->shm_ctlmni;
- break;
- case KERN_MSGMAX:
- data = &ns->msg_ctlmax;
- break;
- case KERN_MSGMNI:
- data = &ns->msg_ctlmni;
- break;
- case KERN_MSGMNB:
- data = &ns->msg_ctlmnb;
- break;
- case KERN_SEM:
- data = &ns->sem_ctls;
- break;
- default:
- return -EINVAL;
- }
-
- return __do_proc_dointvec(data, table, write, filp, buffer,
+ void *which;
+ which = get_ipc(table, write);
+ return __do_proc_dointvec(which, table, write, filp, buffer,
lenp, ppos, NULL, NULL);
-proc_minmax:
- return __do_proc_doulongvec_minmax(data, table, write, filp, buffer,
+}
+
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+ struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ void *which;
+ which = get_ipc(table, write);
+ return __do_proc_doulongvec_minmax(which, table, write, filp, buffer,
lenp, ppos, 1l, 1l);
}
+
#endif
static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
@@ -2475,6 +2394,17 @@ static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
{
return -ENOSYS;
}
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ return -ENOSYS;
+}
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+ struct file *filp, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ return -ENOSYS;
+}
#endif
int proc_dointvec(ctl_table *table, int write, struct file *filp,
@@ -2539,7 +2469,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
/* The generic string strategy routine: */
int sysctl_string(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
if (!table->data || !table->maxlen)
return -ENOTDIR;
@@ -2585,7 +2515,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
*/
int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
if (newval && newlen) {
@@ -2621,7 +2551,7 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
/* Strategy function to convert jiffies to seconds */
int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
if (oldval) {
size_t olen;
@@ -2649,7 +2579,7 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
/* 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)
+ void __user *newval, size_t newlen)
{
if (oldval) {
size_t olen;
@@ -2674,6 +2604,64 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
return 1;
}
+
+/* The generic string strategy routine: */
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ struct ctl_table uts_table;
+ int r, write;
+ write = newval && newlen;
+ memcpy(&uts_table, table, sizeof(uts_table));
+ uts_table.data = get_uts(table, write);
+ r = sysctl_string(&uts_table, name, nlen,
+ oldval, oldlenp, newval, newlen);
+ put_uts(table, write, uts_table.data);
+ return r;
+}
+
+#ifdef CONFIG_SYSVIPC
+/* The generic sysctl ipc data routine. */
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ size_t len;
+ void *data;
+
+ /* Get out of I don't have a variable */
+ if (!table->data || !table->maxlen)
+ return -ENOTDIR;
+
+ data = get_ipc(table, 1);
+ if (!data)
+ return -ENOTDIR;
+
+ if (oldval && oldlenp) {
+ if (get_user(len, oldlenp))
+ return -EFAULT;
+ if (len) {
+ if (len > table->maxlen)
+ len = table->maxlen;
+ if (copy_to_user(oldval, data, len))
+ return -EFAULT;
+ if (put_user(len, oldlenp))
+ return -EFAULT;
+ }
+ }
+
+ if (newval && newlen) {
+ if (newlen > table->maxlen)
+ newlen = table->maxlen;
+
+ if (copy_from_user(data, newval, newlen))
+ return -EFAULT;
+ }
+ return 1;
+}
+#endif
+
#else /* CONFIG_SYSCTL_SYSCALL */
@@ -2712,32 +2700,44 @@ out:
int sysctl_string(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
return -ENOSYS;
}
int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
return -ENOSYS;
}
int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
+ void __user *newval, size_t newlen)
{
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)
+ void __user *newval, size_t newlen)
{
return -ENOSYS;
}
+static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ return -ENOSYS;
+}
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ return -ENOSYS;
+}
#endif /* CONFIG_SYSCTL_SYSCALL */
/*
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 74eca5939bd..22504afc0d3 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -156,7 +156,7 @@ int clocksource_register(struct clocksource *c)
/* check if clocksource is already registered */
if (is_registered_source(c)) {
printk("register_clocksource: Cannot register %s. "
- "Already registered!", c->name);
+ "Already registered!", c->name);
ret = -EBUSY;
} else {
/* register it */
@@ -186,6 +186,7 @@ void clocksource_reselect(void)
}
EXPORT_SYMBOL(clocksource_reselect);
+#ifdef CONFIG_SYSFS
/**
* sysfs_show_current_clocksources - sysfs interface for current clocksource
* @dev: unused
@@ -275,10 +276,10 @@ sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
* Sysfs setup bits:
*/
static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources,
- sysfs_override_clocksource);
+ sysfs_override_clocksource);
static SYSDEV_ATTR(available_clocksource, 0600,
- sysfs_show_available_clocksources, NULL);
+ sysfs_show_available_clocksources, NULL);
static struct sysdev_class clocksource_sysclass = {
set_kset_name("clocksource"),
@@ -307,6 +308,7 @@ static int __init init_clocksource_sysfs(void)
}
device_initcall(init_clocksource_sysfs);
+#endif /* CONFIG_SYSFS */
/**
* boot_override_clocksource - boot clock override
diff --git a/kernel/timer.c b/kernel/timer.c
index c1c7fbcffec..c2a8ccfc288 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -80,6 +80,138 @@ tvec_base_t boot_tvec_bases;
EXPORT_SYMBOL(boot_tvec_bases);
static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
+/**
+ * __round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long __round_jiffies(unsigned long j, int cpu)
+{
+ int rem;
+ unsigned long original = j;
+
+ /*
+ * We don't want all cpus firing their timers at once hitting the
+ * same lock or cachelines, so we skew each extra cpu with an extra
+ * 3 jiffies. This 3 jiffies came originally from the mm/ code which
+ * already did this.
+ * The skew is done by adding 3*cpunr, then round, then subtract this
+ * extra offset again.
+ */
+ j += cpu * 3;
+
+ rem = j % HZ;
+
+ /*
+ * If the target jiffie is just after a whole second (which can happen
+ * due to delays of the timer irq, long irq off times etc etc) then
+ * we should round down to the whole second, not up. Use 1/4th second
+ * as cutoff for this rounding as an extreme upper bound for this.
+ */
+ if (rem < HZ/4) /* round down */
+ j = j - rem;
+ else /* round up */
+ j = j - rem + HZ;
+
+ /* now that we have rounded, subtract the extra skew again */
+ j -= cpu * 3;
+
+ if (j <= jiffies) /* rounding ate our timeout entirely; */
+ return original;
+ return j;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies);
+
+/**
+ * __round_jiffies_relative - function to round jiffies to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies_relative rounds a time delta in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long __round_jiffies_relative(unsigned long j, int cpu)
+{
+ /*
+ * In theory the following code can skip a jiffy in case jiffies
+ * increments right between the addition and the later subtraction.
+ * However since the entire point of this function is to use approximate
+ * timeouts, it's entirely ok to not handle that.
+ */
+ return __round_jiffies(j + jiffies, cpu) - jiffies;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies_relative);
+
+/**
+ * round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ *
+ * round_jiffies rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long round_jiffies(unsigned long j)
+{
+ return __round_jiffies(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies);
+
+/**
+ * round_jiffies_relative - function to round jiffies to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ *
+ * round_jiffies_relative rounds a time delta in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long round_jiffies_relative(unsigned long j)
+{
+ return __round_jiffies_relative(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies_relative);
+
+
static inline void set_running_timer(tvec_base_t *base,
struct timer_list *timer)
{
@@ -714,7 +846,7 @@ static int change_clocksource(void)
clock = new;
clock->cycle_last = now;
printk(KERN_INFO "Time: %s clocksource has been installed.\n",
- clock->name);
+ clock->name);
return 1;
} else if (clock->update_callback) {
return clock->update_callback();
@@ -722,7 +854,10 @@ static int change_clocksource(void)
return 0;
}
#else
-#define change_clocksource() (0)
+static inline int change_clocksource(void)
+{
+ return 0;
+}
#endif
/**
@@ -820,7 +955,8 @@ device_initcall(timekeeping_init_device);
* If the error is already larger, we look ahead even further
* to compensate for late or lost adjustments.
*/
-static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, s64 *offset)
+static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
+ s64 *offset)
{
s64 tick_error, i;
u32 look_ahead, adj;
@@ -844,7 +980,8 @@ static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, s64 *
* Now calculate the error in (1 << look_ahead) ticks, but first
* remove the single look ahead already included in the error.
*/
- tick_error = current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1);
+ tick_error = current_tick_length() >>
+ (TICK_LENGTH_SHIFT - clock->shift + 1);
tick_error -= clock->xtime_interval >> 1;
error = ((error - tick_error) >> look_ahead) + tick_error;
@@ -896,7 +1033,8 @@ static void clocksource_adjust(struct clocksource *clock, s64 offset)
clock->mult += adj;
clock->xtime_interval += interval;
clock->xtime_nsec -= offset;
- clock->error -= (interval - offset) << (TICK_LENGTH_SHIFT - clock->shift);
+ clock->error -= (interval - offset) <<
+ (TICK_LENGTH_SHIFT - clock->shift);
}
/**
@@ -1008,11 +1146,15 @@ static inline void calc_load(unsigned long ticks)
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;
- active_tasks = count_active_tasks();
- for (count -= ticks; count < 0; count += LOAD_FREQ) {
- CALC_LOAD(avenrun[0], EXP_1, active_tasks);
- CALC_LOAD(avenrun[1], EXP_5, active_tasks);
- CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+ count -= ticks;
+ if (unlikely(count < 0)) {
+ active_tasks = count_active_tasks();
+ do {
+ CALC_LOAD(avenrun[0], EXP_1, active_tasks);
+ CALC_LOAD(avenrun[1], EXP_5, active_tasks);
+ CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+ count += LOAD_FREQ;
+ } while (count < 0);
}
}
@@ -1202,11 +1344,10 @@ fastcall signed long __sched schedule_timeout(signed long timeout)
* should never happens anyway). You just have the printk()
* that will tell you if something is gone wrong and where.
*/
- if (timeout < 0)
- {
+ if (timeout < 0) {
printk(KERN_ERR "schedule_timeout: wrong timeout "
- "value %lx from %p\n", timeout,
- __builtin_return_address(0));
+ "value %lx\n", timeout);
+ dump_stack();
current->state = TASK_RUNNING;
goto out;
}
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 96f77013d3f..baacc369141 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -96,6 +96,15 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
stats->write_char = p->wchar;
stats->read_syscalls = p->syscr;
stats->write_syscalls = p->syscw;
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+ stats->read_bytes = p->ioac.read_bytes;
+ stats->write_bytes = p->ioac.write_bytes;
+ stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes;
+#else
+ stats->read_bytes = 0;
+ stats->write_bytes = 0;
+ stats->cancelled_write_bytes = 0;
+#endif
}
#undef KB
#undef MB
diff --git a/kernel/unwind.c b/kernel/unwind.c
deleted file mode 100644
index 09c26132924..00000000000
--- a/kernel/unwind.c
+++ /dev/null
@@ -1,1305 +0,0 @@
-/*
- * Copyright (C) 2002-2006 Novell, Inc.
- * Jan Beulich <jbeulich@novell.com>
- * This code is released under version 2 of the GNU GPL.
- *
- * A simple API for unwinding kernel stacks. This is used for
- * debugging and error reporting purposes. The kernel doesn't need
- * full-blown stack unwinding with all the bells and whistles, so there
- * is not much point in implementing the full Dwarf2 unwind API.
- */
-
-#include <linux/unwind.h>
-#include <linux/module.h>
-#include <linux/bootmem.h>
-#include <linux/sort.h>
-#include <linux/stop_machine.h>
-#include <linux/uaccess.h>
-#include <asm/sections.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-
-extern const char __start_unwind[], __end_unwind[];
-extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
-
-#define MAX_STACK_DEPTH 8
-
-#define EXTRA_INFO(f) { \
- BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
- % FIELD_SIZEOF(struct unwind_frame_info, f)) \
- + offsetof(struct unwind_frame_info, f) \
- / FIELD_SIZEOF(struct unwind_frame_info, f), \
- FIELD_SIZEOF(struct unwind_frame_info, f) \
- }
-#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
-
-static const struct {
- unsigned offs:BITS_PER_LONG / 2;
- unsigned width:BITS_PER_LONG / 2;
-} reg_info[] = {
- UNW_REGISTER_INFO
-};
-
-#undef PTREGS_INFO
-#undef EXTRA_INFO
-
-#ifndef REG_INVALID
-#define REG_INVALID(r) (reg_info[r].width == 0)
-#endif
-
-#define DW_CFA_nop 0x00
-#define DW_CFA_set_loc 0x01
-#define DW_CFA_advance_loc1 0x02
-#define DW_CFA_advance_loc2 0x03
-#define DW_CFA_advance_loc4 0x04
-#define DW_CFA_offset_extended 0x05
-#define DW_CFA_restore_extended 0x06
-#define DW_CFA_undefined 0x07
-#define DW_CFA_same_value 0x08
-#define DW_CFA_register 0x09
-#define DW_CFA_remember_state 0x0a
-#define DW_CFA_restore_state 0x0b
-#define DW_CFA_def_cfa 0x0c
-#define DW_CFA_def_cfa_register 0x0d
-#define DW_CFA_def_cfa_offset 0x0e
-#define DW_CFA_def_cfa_expression 0x0f
-#define DW_CFA_expression 0x10
-#define DW_CFA_offset_extended_sf 0x11
-#define DW_CFA_def_cfa_sf 0x12
-#define DW_CFA_def_cfa_offset_sf 0x13
-#define DW_CFA_val_offset 0x14
-#define DW_CFA_val_offset_sf 0x15
-#define DW_CFA_val_expression 0x16
-#define DW_CFA_lo_user 0x1c
-#define DW_CFA_GNU_window_save 0x2d
-#define DW_CFA_GNU_args_size 0x2e
-#define DW_CFA_GNU_negative_offset_extended 0x2f
-#define DW_CFA_hi_user 0x3f
-
-#define DW_EH_PE_FORM 0x07
-#define DW_EH_PE_native 0x00
-#define DW_EH_PE_leb128 0x01
-#define DW_EH_PE_data2 0x02
-#define DW_EH_PE_data4 0x03
-#define DW_EH_PE_data8 0x04
-#define DW_EH_PE_signed 0x08
-#define DW_EH_PE_ADJUST 0x70
-#define DW_EH_PE_abs 0x00
-#define DW_EH_PE_pcrel 0x10
-#define DW_EH_PE_textrel 0x20
-#define DW_EH_PE_datarel 0x30
-#define DW_EH_PE_funcrel 0x40
-#define DW_EH_PE_aligned 0x50
-#define DW_EH_PE_indirect 0x80
-#define DW_EH_PE_omit 0xff
-
-typedef unsigned long uleb128_t;
-typedef signed long sleb128_t;
-#define sleb128abs __builtin_labs
-
-static struct unwind_table {
- struct {
- unsigned long pc;
- unsigned long range;
- } core, init;
- const void *address;
- unsigned long size;
- const unsigned char *header;
- unsigned long hdrsz;
- struct unwind_table *link;
- const char *name;
-} root_table;
-
-struct unwind_item {
- enum item_location {
- Nowhere,
- Memory,
- Register,
- Value
- } where;
- uleb128_t value;
-};
-
-struct unwind_state {
- uleb128_t loc, org;
- const u8 *cieStart, *cieEnd;
- uleb128_t codeAlign;
- sleb128_t dataAlign;
- struct cfa {
- uleb128_t reg, offs;
- } cfa;
- struct unwind_item regs[ARRAY_SIZE(reg_info)];
- unsigned stackDepth:8;
- unsigned version:8;
- const u8 *label;
- const u8 *stack[MAX_STACK_DEPTH];
-};
-
-static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
-
-static unsigned unwind_debug;
-static int __init unwind_debug_setup(char *s)
-{
- unwind_debug = simple_strtoul(s, NULL, 0);
- return 1;
-}
-__setup("unwind_debug=", unwind_debug_setup);
-#define dprintk(lvl, fmt, args...) \
- ((void)(lvl > unwind_debug \
- || printk(KERN_DEBUG "unwind: " fmt "\n", ##args)))
-
-static struct unwind_table *find_table(unsigned long pc)
-{
- struct unwind_table *table;
-
- for (table = &root_table; table; table = table->link)
- if ((pc >= table->core.pc
- && pc < table->core.pc + table->core.range)
- || (pc >= table->init.pc
- && pc < table->init.pc + table->init.range))
- break;
-
- return table;
-}
-
-static unsigned long read_pointer(const u8 **pLoc,
- const void *end,
- signed ptrType,
- unsigned long text_base,
- unsigned long data_base);
-
-static void init_unwind_table(struct unwind_table *table,
- const char *name,
- const void *core_start,
- unsigned long core_size,
- const void *init_start,
- unsigned long init_size,
- const void *table_start,
- unsigned long table_size,
- const u8 *header_start,
- unsigned long header_size)
-{
- const u8 *ptr = header_start + 4;
- const u8 *end = header_start + header_size;
-
- table->core.pc = (unsigned long)core_start;
- table->core.range = core_size;
- table->init.pc = (unsigned long)init_start;
- table->init.range = init_size;
- table->address = table_start;
- table->size = table_size;
- /* See if the linker provided table looks valid. */
- if (header_size <= 4
- || header_start[0] != 1
- || (void *)read_pointer(&ptr, end, header_start[1], 0, 0)
- != table_start
- || !read_pointer(&ptr, end, header_start[2], 0, 0)
- || !read_pointer(&ptr, end, header_start[3], 0,
- (unsigned long)header_start)
- || !read_pointer(&ptr, end, header_start[3], 0,
- (unsigned long)header_start))
- header_start = NULL;
- table->hdrsz = header_size;
- smp_wmb();
- table->header = header_start;
- table->link = NULL;
- table->name = name;
-}
-
-void __init unwind_init(void)
-{
- init_unwind_table(&root_table, "kernel",
- _text, _end - _text,
- NULL, 0,
- __start_unwind, __end_unwind - __start_unwind,
- __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
-}
-
-static const u32 bad_cie, not_fde;
-static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
-static signed fde_pointer_type(const u32 *cie);
-
-struct eh_frame_hdr_table_entry {
- unsigned long start, fde;
-};
-
-static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
-{
- const struct eh_frame_hdr_table_entry *e1 = p1;
- const struct eh_frame_hdr_table_entry *e2 = p2;
-
- return (e1->start > e2->start) - (e1->start < e2->start);
-}
-
-static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
-{
- struct eh_frame_hdr_table_entry *e1 = p1;
- struct eh_frame_hdr_table_entry *e2 = p2;
- unsigned long v;
-
- v = e1->start;
- e1->start = e2->start;
- e2->start = v;
- v = e1->fde;
- e1->fde = e2->fde;
- e2->fde = v;
-}
-
-static void __init setup_unwind_table(struct unwind_table *table,
- void *(*alloc)(unsigned long))
-{
- const u8 *ptr;
- unsigned long tableSize = table->size, hdrSize;
- unsigned n;
- const u32 *fde;
- struct {
- u8 version;
- u8 eh_frame_ptr_enc;
- u8 fde_count_enc;
- u8 table_enc;
- unsigned long eh_frame_ptr;
- unsigned int fde_count;
- struct eh_frame_hdr_table_entry table[];
- } __attribute__((__packed__)) *header;
-
- if (table->header)
- return;
-
- if (table->hdrsz)
- printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
- table->name);
-
- if (tableSize & (sizeof(*fde) - 1))
- return;
-
- for (fde = table->address, n = 0;
- tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
- tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
- const u32 *cie = cie_for_fde(fde, table);
- signed ptrType;
-
- if (cie == &not_fde)
- continue;
- if (cie == NULL
- || cie == &bad_cie
- || (ptrType = fde_pointer_type(cie)) < 0)
- return;
- ptr = (const u8 *)(fde + 2);
- if (!read_pointer(&ptr,
- (const u8 *)(fde + 1) + *fde,
- ptrType, 0, 0))
- return;
- ++n;
- }
-
- if (tableSize || !n)
- return;
-
- hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
- + 2 * n * sizeof(unsigned long);
- dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize);
- header = alloc(hdrSize);
- if (!header)
- return;
- header->version = 1;
- header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
- header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4;
- header->table_enc = DW_EH_PE_abs|DW_EH_PE_native;
- put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
- BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
- % __alignof(typeof(header->fde_count)));
- header->fde_count = n;
-
- BUILD_BUG_ON(offsetof(typeof(*header), table)
- % __alignof(typeof(*header->table)));
- for (fde = table->address, tableSize = table->size, n = 0;
- tableSize;
- tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
- const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
-
- if (!fde[1])
- continue; /* this is a CIE */
- ptr = (const u8 *)(fde + 2);
- header->table[n].start = read_pointer(&ptr,
- (const u8 *)(fde + 1) + *fde,
- fde_pointer_type(cie), 0, 0);
- header->table[n].fde = (unsigned long)fde;
- ++n;
- }
- WARN_ON(n != header->fde_count);
-
- sort(header->table,
- n,
- sizeof(*header->table),
- cmp_eh_frame_hdr_table_entries,
- swap_eh_frame_hdr_table_entries);
-
- table->hdrsz = hdrSize;
- smp_wmb();
- table->header = (const void *)header;
-}
-
-static void *__init balloc(unsigned long sz)
-{
- return __alloc_bootmem_nopanic(sz,
- sizeof(unsigned int),
- __pa(MAX_DMA_ADDRESS));
-}
-
-void __init unwind_setup(void)
-{
- setup_unwind_table(&root_table, balloc);
-}
-
-#ifdef CONFIG_MODULES
-
-static struct unwind_table *last_table;
-
-/* Must be called with module_mutex held. */
-void *unwind_add_table(struct module *module,
- const void *table_start,
- unsigned long table_size)
-{
- struct unwind_table *table;
-
- if (table_size <= 0)
- return NULL;
-
- table = kmalloc(sizeof(*table), GFP_KERNEL);
- if (!table)
- return NULL;
-
- init_unwind_table(table, module->name,
- module->module_core, module->core_size,
- module->module_init, module->init_size,
- table_start, table_size,
- NULL, 0);
-
- if (last_table)
- last_table->link = table;
- else
- root_table.link = table;
- last_table = table;
-
- return table;
-}
-
-struct unlink_table_info
-{
- struct unwind_table *table;
- int init_only;
-};
-
-static int unlink_table(void *arg)
-{
- struct unlink_table_info *info = arg;
- struct unwind_table *table = info->table, *prev;
-
- for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
- ;
-
- if (prev->link) {
- if (info->init_only) {
- table->init.pc = 0;
- table->init.range = 0;
- info->table = NULL;
- } else {
- prev->link = table->link;
- if (!prev->link)
- last_table = prev;
- }
- } else
- info->table = NULL;
-
- return 0;
-}
-
-/* Must be called with module_mutex held. */
-void unwind_remove_table(void *handle, int init_only)
-{
- struct unwind_table *table = handle;
- struct unlink_table_info info;
-
- if (!table || table == &root_table)
- return;
-
- if (init_only && table == last_table) {
- table->init.pc = 0;
- table->init.range = 0;
- return;
- }
-
- info.table = table;
- info.init_only = init_only;
- stop_machine_run(unlink_table, &info, NR_CPUS);
-
- if (info.table)
- kfree(table);
-}
-
-#endif /* CONFIG_MODULES */
-
-static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
-{
- const u8 *cur = *pcur;
- uleb128_t value;
- unsigned shift;
-
- for (shift = 0, value = 0; cur < end; shift += 7) {
- if (shift + 7 > 8 * sizeof(value)
- && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
- cur = end + 1;
- break;
- }
- value |= (uleb128_t)(*cur & 0x7f) << shift;
- if (!(*cur++ & 0x80))
- break;
- }
- *pcur = cur;
-
- return value;
-}
-
-static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
-{
- const u8 *cur = *pcur;
- sleb128_t value;
- unsigned shift;
-
- for (shift = 0, value = 0; cur < end; shift += 7) {
- if (shift + 7 > 8 * sizeof(value)
- && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
- cur = end + 1;
- break;
- }
- value |= (sleb128_t)(*cur & 0x7f) << shift;
- if (!(*cur & 0x80)) {
- value |= -(*cur++ & 0x40) << shift;
- break;
- }
- }
- *pcur = cur;
-
- return value;
-}
-
-static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
-{
- const u32 *cie;
-
- if (!*fde || (*fde & (sizeof(*fde) - 1)))
- return &bad_cie;
- if (!fde[1])
- return &not_fde; /* this is a CIE */
- if ((fde[1] & (sizeof(*fde) - 1))
- || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
- return NULL; /* this is not a valid FDE */
- cie = fde + 1 - fde[1] / sizeof(*fde);
- if (*cie <= sizeof(*cie) + 4
- || *cie >= fde[1] - sizeof(*fde)
- || (*cie & (sizeof(*cie) - 1))
- || cie[1])
- return NULL; /* this is not a (valid) CIE */
- return cie;
-}
-
-static unsigned long read_pointer(const u8 **pLoc,
- const void *end,
- signed ptrType,
- unsigned long text_base,
- unsigned long data_base)
-{
- unsigned long value = 0;
- union {
- const u8 *p8;
- const u16 *p16u;
- const s16 *p16s;
- const u32 *p32u;
- const s32 *p32s;
- const unsigned long *pul;
- } ptr;
-
- if (ptrType < 0 || ptrType == DW_EH_PE_omit) {
- dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end);
- return 0;
- }
- ptr.p8 = *pLoc;
- switch(ptrType & DW_EH_PE_FORM) {
- case DW_EH_PE_data2:
- if (end < (const void *)(ptr.p16u + 1)) {
- dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end);
- return 0;
- }
- if(ptrType & DW_EH_PE_signed)
- value = get_unaligned(ptr.p16s++);
- else
- value = get_unaligned(ptr.p16u++);
- break;
- case DW_EH_PE_data4:
-#ifdef CONFIG_64BIT
- if (end < (const void *)(ptr.p32u + 1)) {
- dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end);
- return 0;
- }
- if(ptrType & DW_EH_PE_signed)
- value = get_unaligned(ptr.p32s++);
- else
- value = get_unaligned(ptr.p32u++);
- break;
- case DW_EH_PE_data8:
- BUILD_BUG_ON(sizeof(u64) != sizeof(value));
-#else
- BUILD_BUG_ON(sizeof(u32) != sizeof(value));
-#endif
- case DW_EH_PE_native:
- if (end < (const void *)(ptr.pul + 1)) {
- dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end);
- return 0;
- }
- value = get_unaligned(ptr.pul++);
- break;
- case DW_EH_PE_leb128:
- BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
- value = ptrType & DW_EH_PE_signed
- ? get_sleb128(&ptr.p8, end)
- : get_uleb128(&ptr.p8, end);
- if ((const void *)ptr.p8 > end) {
- dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end);
- return 0;
- }
- break;
- default:
- dprintk(2, "Cannot decode pointer type %02X (%p,%p).",
- ptrType, ptr.p8, end);
- return 0;
- }
- switch(ptrType & DW_EH_PE_ADJUST) {
- case DW_EH_PE_abs:
- break;
- case DW_EH_PE_pcrel:
- value += (unsigned long)*pLoc;
- break;
- case DW_EH_PE_textrel:
- if (likely(text_base)) {
- value += text_base;
- break;
- }
- dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.",
- ptrType, *pLoc, end);
- return 0;
- case DW_EH_PE_datarel:
- if (likely(data_base)) {
- value += data_base;
- break;
- }
- dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.",
- ptrType, *pLoc, end);
- return 0;
- default:
- dprintk(2, "Cannot adjust pointer type %02X (%p,%p).",
- ptrType, *pLoc, end);
- return 0;
- }
- if ((ptrType & DW_EH_PE_indirect)
- && probe_kernel_address((unsigned long *)value, value)) {
- dprintk(1, "Cannot read indirect value %lx (%p,%p).",
- value, *pLoc, end);
- return 0;
- }
- *pLoc = ptr.p8;
-
- return value;
-}
-
-static signed fde_pointer_type(const u32 *cie)
-{
- const u8 *ptr = (const u8 *)(cie + 2);
- unsigned version = *ptr;
-
- if (version != 1)
- return -1; /* unsupported */
- if (*++ptr) {
- const char *aug;
- const u8 *end = (const u8 *)(cie + 1) + *cie;
- uleb128_t len;
-
- /* check if augmentation size is first (and thus present) */
- if (*ptr != 'z')
- return -1;
- /* check if augmentation string is nul-terminated */
- if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
- return -1;
- ++ptr; /* skip terminator */
- get_uleb128(&ptr, end); /* skip code alignment */
- get_sleb128(&ptr, end); /* skip data alignment */
- /* skip return address column */
- version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
- len = get_uleb128(&ptr, end); /* augmentation length */
- if (ptr + len < ptr || ptr + len > end)
- return -1;
- end = ptr + len;
- while (*++aug) {
- if (ptr >= end)
- return -1;
- switch(*aug) {
- case 'L':
- ++ptr;
- break;
- case 'P': {
- signed ptrType = *ptr++;
-
- if (!read_pointer(&ptr, end, ptrType, 0, 0)
- || ptr > end)
- return -1;
- }
- break;
- case 'R':
- return *ptr;
- default:
- return -1;
- }
- }
- }
- return DW_EH_PE_native|DW_EH_PE_abs;
-}
-
-static int advance_loc(unsigned long delta, struct unwind_state *state)
-{
- state->loc += delta * state->codeAlign;
-
- return delta > 0;
-}
-
-static void set_rule(uleb128_t reg,
- enum item_location where,
- uleb128_t value,
- struct unwind_state *state)
-{
- if (reg < ARRAY_SIZE(state->regs)) {
- state->regs[reg].where = where;
- state->regs[reg].value = value;
- }
-}
-
-static int processCFI(const u8 *start,
- const u8 *end,
- unsigned long targetLoc,
- signed ptrType,
- struct unwind_state *state)
-{
- union {
- const u8 *p8;
- const u16 *p16;
- const u32 *p32;
- } ptr;
- int result = 1;
-
- if (start != state->cieStart) {
- state->loc = state->org;
- result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
- if (targetLoc == 0 && state->label == NULL)
- return result;
- }
- for (ptr.p8 = start; result && ptr.p8 < end; ) {
- switch(*ptr.p8 >> 6) {
- uleb128_t value;
-
- case 0:
- switch(*ptr.p8++) {
- case DW_CFA_nop:
- break;
- case DW_CFA_set_loc:
- state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0);
- if (state->loc == 0)
- result = 0;
- break;
- case DW_CFA_advance_loc1:
- result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
- break;
- case DW_CFA_advance_loc2:
- result = ptr.p8 <= end + 2
- && advance_loc(*ptr.p16++, state);
- break;
- case DW_CFA_advance_loc4:
- result = ptr.p8 <= end + 4
- && advance_loc(*ptr.p32++, state);
- break;
- case DW_CFA_offset_extended:
- value = get_uleb128(&ptr.p8, end);
- set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
- break;
- case DW_CFA_val_offset:
- value = get_uleb128(&ptr.p8, end);
- set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
- break;
- case DW_CFA_offset_extended_sf:
- value = get_uleb128(&ptr.p8, end);
- set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
- break;
- case DW_CFA_val_offset_sf:
- value = get_uleb128(&ptr.p8, end);
- set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
- break;
- case DW_CFA_restore_extended:
- case DW_CFA_undefined:
- case DW_CFA_same_value:
- set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
- break;
- case DW_CFA_register:
- value = get_uleb128(&ptr.p8, end);
- set_rule(value,
- Register,
- get_uleb128(&ptr.p8, end), state);
- break;
- case DW_CFA_remember_state:
- if (ptr.p8 == state->label) {
- state->label = NULL;
- return 1;
- }
- if (state->stackDepth >= MAX_STACK_DEPTH) {
- dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end);
- return 0;
- }
- state->stack[state->stackDepth++] = ptr.p8;
- break;
- case DW_CFA_restore_state:
- if (state->stackDepth) {
- const uleb128_t loc = state->loc;
- const u8 *label = state->label;
-
- state->label = state->stack[state->stackDepth - 1];
- memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
- memset(state->regs, 0, sizeof(state->regs));
- state->stackDepth = 0;
- result = processCFI(start, end, 0, ptrType, state);
- state->loc = loc;
- state->label = label;
- } else {
- dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end);
- return 0;
- }
- break;
- case DW_CFA_def_cfa:
- state->cfa.reg = get_uleb128(&ptr.p8, end);
- /*nobreak*/
- case DW_CFA_def_cfa_offset:
- state->cfa.offs = get_uleb128(&ptr.p8, end);
- break;
- case DW_CFA_def_cfa_sf:
- state->cfa.reg = get_uleb128(&ptr.p8, end);
- /*nobreak*/
- case DW_CFA_def_cfa_offset_sf:
- state->cfa.offs = get_sleb128(&ptr.p8, end)
- * state->dataAlign;
- break;
- case DW_CFA_def_cfa_register:
- state->cfa.reg = get_uleb128(&ptr.p8, end);
- break;
- /*todo case DW_CFA_def_cfa_expression: */
- /*todo case DW_CFA_expression: */
- /*todo case DW_CFA_val_expression: */
- case DW_CFA_GNU_args_size:
- get_uleb128(&ptr.p8, end);
- break;
- case DW_CFA_GNU_negative_offset_extended:
- value = get_uleb128(&ptr.p8, end);
- set_rule(value,
- Memory,
- (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
- break;
- case DW_CFA_GNU_window_save:
- default:
- dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end);
- result = 0;
- break;
- }
- break;
- case 1:
- result = advance_loc(*ptr.p8++ & 0x3f, state);
- break;
- case 2:
- value = *ptr.p8++ & 0x3f;
- set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
- break;
- case 3:
- set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
- break;
- }
- if (ptr.p8 > end) {
- dprintk(1, "Data overrun (%p,%p).", ptr.p8, end);
- result = 0;
- }
- if (result && targetLoc != 0 && targetLoc < state->loc)
- return 1;
- }
-
- if (result && ptr.p8 < end)
- dprintk(1, "Data underrun (%p,%p).", ptr.p8, end);
-
- return result
- && ptr.p8 == end
- && (targetLoc == 0
- || (/*todo While in theory this should apply, gcc in practice omits
- everything past the function prolog, and hence the location
- never reaches the end of the function.
- targetLoc < state->loc &&*/ state->label == NULL));
-}
-
-/* Unwind to previous to frame. Returns 0 if successful, negative
- * number in case of an error. */
-int unwind(struct unwind_frame_info *frame)
-{
-#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
- const u32 *fde = NULL, *cie = NULL;
- const u8 *ptr = NULL, *end = NULL;
- unsigned long pc = UNW_PC(frame) - frame->call_frame, sp;
- unsigned long startLoc = 0, endLoc = 0, cfa;
- unsigned i;
- signed ptrType = -1;
- uleb128_t retAddrReg = 0;
- const struct unwind_table *table;
- struct unwind_state state;
-
- if (UNW_PC(frame) == 0)
- return -EINVAL;
- if ((table = find_table(pc)) != NULL
- && !(table->size & (sizeof(*fde) - 1))) {
- const u8 *hdr = table->header;
- unsigned long tableSize;
-
- smp_rmb();
- if (hdr && hdr[0] == 1) {
- switch(hdr[3] & DW_EH_PE_FORM) {
- case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
- case DW_EH_PE_data2: tableSize = 2; break;
- case DW_EH_PE_data4: tableSize = 4; break;
- case DW_EH_PE_data8: tableSize = 8; break;
- default: tableSize = 0; break;
- }
- ptr = hdr + 4;
- end = hdr + table->hdrsz;
- if (tableSize
- && read_pointer(&ptr, end, hdr[1], 0, 0)
- == (unsigned long)table->address
- && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0
- && i == (end - ptr) / (2 * tableSize)
- && !((end - ptr) % (2 * tableSize))) {
- do {
- const u8 *cur = ptr + (i / 2) * (2 * tableSize);
-
- startLoc = read_pointer(&cur,
- cur + tableSize,
- hdr[3], 0,
- (unsigned long)hdr);
- if (pc < startLoc)
- i /= 2;
- else {
- ptr = cur - tableSize;
- i = (i + 1) / 2;
- }
- } while (startLoc && i > 1);
- if (i == 1
- && (startLoc = read_pointer(&ptr,
- ptr + tableSize,
- hdr[3], 0,
- (unsigned long)hdr)) != 0
- && pc >= startLoc)
- fde = (void *)read_pointer(&ptr,
- ptr + tableSize,
- hdr[3], 0,
- (unsigned long)hdr);
- }
- }
- if(hdr && !fde)
- dprintk(3, "Binary lookup for %lx failed.", pc);
-
- if (fde != NULL) {
- cie = cie_for_fde(fde, table);
- ptr = (const u8 *)(fde + 2);
- if(cie != NULL
- && cie != &bad_cie
- && cie != &not_fde
- && (ptrType = fde_pointer_type(cie)) >= 0
- && read_pointer(&ptr,
- (const u8 *)(fde + 1) + *fde,
- ptrType, 0, 0) == startLoc) {
- if (!(ptrType & DW_EH_PE_indirect))
- ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
- endLoc = startLoc
- + read_pointer(&ptr,
- (const u8 *)(fde + 1) + *fde,
- ptrType, 0, 0);
- if(pc >= endLoc)
- fde = NULL;
- } else
- fde = NULL;
- if(!fde)
- dprintk(1, "Binary lookup result for %lx discarded.", pc);
- }
- if (fde == NULL) {
- for (fde = table->address, tableSize = table->size;
- cie = NULL, tableSize > sizeof(*fde)
- && tableSize - sizeof(*fde) >= *fde;
- tableSize -= sizeof(*fde) + *fde,
- fde += 1 + *fde / sizeof(*fde)) {
- cie = cie_for_fde(fde, table);
- if (cie == &bad_cie) {
- cie = NULL;
- break;
- }
- if (cie == NULL
- || cie == &not_fde
- || (ptrType = fde_pointer_type(cie)) < 0)
- continue;
- ptr = (const u8 *)(fde + 2);
- startLoc = read_pointer(&ptr,
- (const u8 *)(fde + 1) + *fde,
- ptrType, 0, 0);
- if (!startLoc)
- continue;
- if (!(ptrType & DW_EH_PE_indirect))
- ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
- endLoc = startLoc
- + read_pointer(&ptr,
- (const u8 *)(fde + 1) + *fde,
- ptrType, 0, 0);
- if (pc >= startLoc && pc < endLoc)
- break;
- }
- if(!fde)
- dprintk(3, "Linear lookup for %lx failed.", pc);
- }
- }
- if (cie != NULL) {
- memset(&state, 0, sizeof(state));
- state.cieEnd = ptr; /* keep here temporarily */
- ptr = (const u8 *)(cie + 2);
- end = (const u8 *)(cie + 1) + *cie;
- frame->call_frame = 1;
- if ((state.version = *ptr) != 1)
- cie = NULL; /* unsupported version */
- else if (*++ptr) {
- /* check if augmentation size is first (and thus present) */
- if (*ptr == 'z') {
- while (++ptr < end && *ptr) {
- switch(*ptr) {
- /* check for ignorable (or already handled)
- * nul-terminated augmentation string */
- case 'L':
- case 'P':
- case 'R':
- continue;
- case 'S':
- frame->call_frame = 0;
- continue;
- default:
- break;
- }
- break;
- }
- }
- if (ptr >= end || *ptr)
- cie = NULL;
- }
- if(!cie)
- dprintk(1, "CIE unusable (%p,%p).", ptr, end);
- ++ptr;
- }
- if (cie != NULL) {
- /* get code aligment factor */
- state.codeAlign = get_uleb128(&ptr, end);
- /* get data aligment factor */
- state.dataAlign = get_sleb128(&ptr, end);
- if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
- cie = NULL;
- else if (UNW_PC(frame) % state.codeAlign
- || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
- dprintk(1, "Input pointer(s) misaligned (%lx,%lx).",
- UNW_PC(frame), UNW_SP(frame));
- return -EPERM;
- } else {
- retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
- /* skip augmentation */
- if (((const char *)(cie + 2))[1] == 'z') {
- uleb128_t augSize = get_uleb128(&ptr, end);
-
- ptr += augSize;
- }
- if (ptr > end
- || retAddrReg >= ARRAY_SIZE(reg_info)
- || REG_INVALID(retAddrReg)
- || reg_info[retAddrReg].width != sizeof(unsigned long))
- cie = NULL;
- }
- if(!cie)
- dprintk(1, "CIE validation failed (%p,%p).", ptr, end);
- }
- if (cie != NULL) {
- state.cieStart = ptr;
- ptr = state.cieEnd;
- state.cieEnd = end;
- end = (const u8 *)(fde + 1) + *fde;
- /* skip augmentation */
- if (((const char *)(cie + 2))[1] == 'z') {
- uleb128_t augSize = get_uleb128(&ptr, end);
-
- if ((ptr += augSize) > end)
- fde = NULL;
- }
- if(!fde)
- dprintk(1, "FDE validation failed (%p,%p).", ptr, end);
- }
- if (cie == NULL || fde == NULL) {
-#ifdef CONFIG_FRAME_POINTER
- unsigned long top, bottom;
-
- if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long))
- return -EPERM;
- top = STACK_TOP(frame->task);
- bottom = STACK_BOTTOM(frame->task);
-# if FRAME_RETADDR_OFFSET < 0
- if (UNW_SP(frame) < top
- && UNW_FP(frame) <= UNW_SP(frame)
- && bottom < UNW_FP(frame)
-# else
- if (UNW_SP(frame) > top
- && UNW_FP(frame) >= UNW_SP(frame)
- && bottom > UNW_FP(frame)
-# endif
- && !((UNW_SP(frame) | UNW_FP(frame))
- & (sizeof(unsigned long) - 1))) {
- unsigned long link;
-
- if (!probe_kernel_address(
- (unsigned long *)(UNW_FP(frame)
- + FRAME_LINK_OFFSET),
- link)
-# if FRAME_RETADDR_OFFSET < 0
- && link > bottom && link < UNW_FP(frame)
-# else
- && link > UNW_FP(frame) && link < bottom
-# endif
- && !(link & (sizeof(link) - 1))
- && !probe_kernel_address(
- (unsigned long *)(UNW_FP(frame)
- + FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
- UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
-# if FRAME_RETADDR_OFFSET < 0
- -
-# else
- +
-# endif
- sizeof(UNW_PC(frame));
- UNW_FP(frame) = link;
- return 0;
- }
- }
-#endif
- return -ENXIO;
- }
- state.org = startLoc;
- memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
- /* process instructions */
- if (!processCFI(ptr, end, pc, ptrType, &state)
- || state.loc > endLoc
- || state.regs[retAddrReg].where == Nowhere
- || state.cfa.reg >= ARRAY_SIZE(reg_info)
- || reg_info[state.cfa.reg].width != sizeof(unsigned long)
- || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long)
- || state.cfa.offs % sizeof(unsigned long)) {
- dprintk(1, "Unusable unwind info (%p,%p).", ptr, end);
- return -EIO;
- }
- /* update frame */
-#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
- if(frame->call_frame
- && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
- frame->call_frame = 0;
-#endif
- cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
- startLoc = min((unsigned long)UNW_SP(frame), cfa);
- endLoc = max((unsigned long)UNW_SP(frame), cfa);
- if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
- startLoc = min(STACK_LIMIT(cfa), cfa);
- endLoc = max(STACK_LIMIT(cfa), cfa);
- }
-#ifndef CONFIG_64BIT
-# define CASES CASE(8); CASE(16); CASE(32)
-#else
-# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
-#endif
- pc = UNW_PC(frame);
- sp = UNW_SP(frame);
- for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
- if (REG_INVALID(i)) {
- if (state.regs[i].where == Nowhere)
- continue;
- dprintk(1, "Cannot restore register %u (%d).",
- i, state.regs[i].where);
- return -EIO;
- }
- switch(state.regs[i].where) {
- default:
- break;
- case Register:
- if (state.regs[i].value >= ARRAY_SIZE(reg_info)
- || REG_INVALID(state.regs[i].value)
- || reg_info[i].width > reg_info[state.regs[i].value].width) {
- dprintk(1, "Cannot restore register %u from register %lu.",
- i, state.regs[i].value);
- return -EIO;
- }
- switch(reg_info[state.regs[i].value].width) {
-#define CASE(n) \
- case sizeof(u##n): \
- state.regs[i].value = FRAME_REG(state.regs[i].value, \
- const u##n); \
- break
- CASES;
-#undef CASE
- default:
- dprintk(1, "Unsupported register size %u (%lu).",
- reg_info[state.regs[i].value].width,
- state.regs[i].value);
- return -EIO;
- }
- break;
- }
- }
- for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
- if (REG_INVALID(i))
- continue;
- switch(state.regs[i].where) {
- case Nowhere:
- if (reg_info[i].width != sizeof(UNW_SP(frame))
- || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
- != &UNW_SP(frame))
- continue;
- UNW_SP(frame) = cfa;
- break;
- case Register:
- switch(reg_info[i].width) {
-#define CASE(n) case sizeof(u##n): \
- FRAME_REG(i, u##n) = state.regs[i].value; \
- break
- CASES;
-#undef CASE
- default:
- dprintk(1, "Unsupported register size %u (%u).",
- reg_info[i].width, i);
- return -EIO;
- }
- break;
- case Value:
- if (reg_info[i].width != sizeof(unsigned long)) {
- dprintk(1, "Unsupported value size %u (%u).",
- reg_info[i].width, i);
- return -EIO;
- }
- FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
- * state.dataAlign;
- break;
- case Memory: {
- unsigned long addr = cfa + state.regs[i].value
- * state.dataAlign;
-
- if ((state.regs[i].value * state.dataAlign)
- % sizeof(unsigned long)
- || addr < startLoc
- || addr + sizeof(unsigned long) < addr
- || addr + sizeof(unsigned long) > endLoc) {
- dprintk(1, "Bad memory location %lx (%lx).",
- addr, state.regs[i].value);
- return -EIO;
- }
- switch(reg_info[i].width) {
-#define CASE(n) case sizeof(u##n): \
- probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
- break
- CASES;
-#undef CASE
- default:
- dprintk(1, "Unsupported memory size %u (%u).",
- reg_info[i].width, i);
- return -EIO;
- }
- }
- break;
- }
- }
-
- if (UNW_PC(frame) % state.codeAlign
- || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
- dprintk(1, "Output pointer(s) misaligned (%lx,%lx).",
- UNW_PC(frame), UNW_SP(frame));
- return -EIO;
- }
- if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) {
- dprintk(1, "No progress (%lx,%lx).", pc, sp);
- return -EIO;
- }
-
- return 0;
-#undef CASES
-#undef FRAME_REG
-}
-EXPORT_SYMBOL(unwind);
-
-int unwind_init_frame_info(struct unwind_frame_info *info,
- struct task_struct *tsk,
- /*const*/ struct pt_regs *regs)
-{
- info->task = tsk;
- info->call_frame = 0;
- arch_unw_init_frame_info(info, regs);
-
- return 0;
-}
-EXPORT_SYMBOL(unwind_init_frame_info);
-
-/*
- * Prepare to unwind a blocked task.
- */
-int unwind_init_blocked(struct unwind_frame_info *info,
- struct task_struct *tsk)
-{
- info->task = tsk;
- info->call_frame = 0;
- arch_unw_init_blocked(info);
-
- return 0;
-}
-EXPORT_SYMBOL(unwind_init_blocked);
-
-/*
- * Prepare to unwind the currently running thread.
- */
-int unwind_init_running(struct unwind_frame_info *info,
- asmlinkage int (*callback)(struct unwind_frame_info *,
- void *arg),
- void *arg)
-{
- info->task = current;
- info->call_frame = 0;
-
- return arch_unwind_init_running(info, callback, arg);
-}
-EXPORT_SYMBOL(unwind_init_running);
-
-/*
- * Unwind until the return pointer is in user-land (or until an error
- * occurs). Returns 0 if successful, negative number in case of
- * error.
- */
-int unwind_to_user(struct unwind_frame_info *info)
-{
- while (!arch_unw_user_mode(info)) {
- int err = unwind(info);
-
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(unwind_to_user);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 6b186750e9b..a3da07c5af2 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -85,27 +85,24 @@ static inline int is_single_threaded(struct workqueue_struct *wq)
return list_empty(&wq->list);
}
+/*
+ * Set the workqueue on which a work item is to be run
+ * - Must *only* be called if the pending flag is set
+ */
static inline void set_wq_data(struct work_struct *work, void *wq)
{
- unsigned long new, old, res;
+ unsigned long new;
+
+ BUG_ON(!work_pending(work));
- /* assume the pending flag is already set and that the task has already
- * been queued on this workqueue */
new = (unsigned long) wq | (1UL << WORK_STRUCT_PENDING);
- res = work->management;
- if (res != new) {
- do {
- old = res;
- new = (unsigned long) wq;
- new |= (old & WORK_STRUCT_FLAG_MASK);
- res = cmpxchg(&work->management, old, new);
- } while (res != old);
- }
+ new |= WORK_STRUCT_FLAG_MASK & *work_data_bits(work);
+ atomic_long_set(&work->data, new);
}
static inline void *get_wq_data(struct work_struct *work)
{
- return (void *) (work->management & WORK_STRUCT_WQ_DATA_MASK);
+ return (void *) (atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK);
}
static int __run_work(struct cpu_workqueue_struct *cwq, struct work_struct *work)
@@ -136,7 +133,7 @@ static int __run_work(struct cpu_workqueue_struct *cwq, struct work_struct *work
list_del_init(&work->entry);
spin_unlock_irqrestore(&cwq->lock, flags);
- if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management))
+ if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work)))
work_release(work);
f(work);
@@ -209,7 +206,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work)
{
int ret = 0, cpu = get_cpu();
- if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) {
+ if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
if (unlikely(is_single_threaded(wq)))
cpu = singlethread_cpu;
BUG_ON(!list_empty(&work->entry));
@@ -236,7 +233,7 @@ static void delayed_work_timer_fn(unsigned long __data)
/**
* queue_delayed_work - queue work on a workqueue after delay
* @wq: workqueue to use
- * @work: delayable work to queue
+ * @dwork: delayable work to queue
* @delay: number of jiffies to wait before queueing
*
* Returns 0 if @work was already on a queue, non-zero otherwise.
@@ -251,7 +248,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq,
if (delay == 0)
return queue_work(wq, work);
- if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) {
+ if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
BUG_ON(timer_pending(timer));
BUG_ON(!list_empty(&work->entry));
@@ -271,7 +268,7 @@ EXPORT_SYMBOL_GPL(queue_delayed_work);
* queue_delayed_work_on - queue work on specific CPU after delay
* @cpu: CPU number to execute work on
* @wq: workqueue to use
- * @work: work to queue
+ * @dwork: work to queue
* @delay: number of jiffies to wait before queueing
*
* Returns 0 if @work was already on a queue, non-zero otherwise.
@@ -283,7 +280,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct timer_list *timer = &dwork->timer;
struct work_struct *work = &dwork->work;
- if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) {
+ if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
BUG_ON(timer_pending(timer));
BUG_ON(!list_empty(&work->entry));
@@ -324,7 +321,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
spin_unlock_irqrestore(&cwq->lock, flags);
BUG_ON(get_wq_data(work) != cwq);
- if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management))
+ if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work)))
work_release(work);
f(work);
@@ -640,9 +637,11 @@ int schedule_on_each_cpu(work_func_t func)
mutex_lock(&workqueue_mutex);
for_each_online_cpu(cpu) {
- INIT_WORK(per_cpu_ptr(works, cpu), func);
- __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu),
- per_cpu_ptr(works, cpu));
+ struct work_struct *work = per_cpu_ptr(works, cpu);
+
+ INIT_WORK(work, func);
+ set_bit(WORK_STRUCT_PENDING, work_data_bits(work));
+ __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), work);
}
mutex_unlock(&workqueue_mutex);
flush_workqueue(keventd_wq);
diff --git a/lib/Kconfig b/lib/Kconfig
index 734ce95a93d..9b03581cdec 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -4,6 +4,9 @@
menu "Library routines"
+config BITREVERSE
+ tristate
+
config CRC_CCITT
tristate "CRC-CCITT functions"
help
@@ -23,6 +26,7 @@ config CRC16
config CRC32
tristate "CRC32 functions"
default y
+ select BITREVERSE
help
This option is provided for the case where no in-kernel-tree
modules require CRC32 functions, but a module built outside the
@@ -97,4 +101,9 @@ config TEXTSEARCH_FSM
config PLIST
boolean
+config IOMAP_COPY
+ boolean
+ depends on !UML
+ default y
+
endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b75fed737f2..5c2681875b9 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -47,6 +47,30 @@ config UNUSED_SYMBOLS
you really need it, and what the merge plan to the mainline kernel for
your module is.
+config DEBUG_FS
+ bool "Debug Filesystem"
+ depends on SYSFS
+ help
+ debugfs is a virtual file system that kernel developers use to put
+ debugging files into. Enable this option to be able to read and
+ write to these files.
+
+ If unsure, say N.
+
+config HEADERS_CHECK
+ bool "Run 'make headers_check' when building vmlinux"
+ depends on !UML
+ help
+ This option will extract the user-visible kernel headers whenever
+ building the kernel, and will run basic sanity checks on them to
+ ensure that exported files do not attempt to include files which
+ were not exported, etc.
+
+ If you're making modifications to header files which are
+ relevant for userspace, say 'Y', and check the headers
+ exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
+ your build tree), to make sure they're suitable.
+
config DEBUG_KERNEL
bool "Kernel debugging"
help
@@ -285,7 +309,7 @@ config DEBUG_HIGHMEM
config DEBUG_BUGVERBOSE
bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
depends on BUG
- depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH
+ depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG
default !EMBEDDED
help
Say Y here to make BUG() panics output the file name and line number
@@ -302,16 +326,6 @@ config DEBUG_INFO
If unsure, say N.
-config DEBUG_FS
- bool "Debug Filesystem"
- depends on SYSFS
- help
- debugfs is a virtual file system that kernel developers use to put
- debugging files into. Enable this option to be able to read and
- write to these files.
-
- If unsure, say N.
-
config DEBUG_VM
bool "Debug VM"
depends on DEBUG_KERNEL
@@ -340,24 +354,6 @@ config FRAME_POINTER
some architectures or if you use external debuggers.
If you don't debug the kernel, you can say N.
-config UNWIND_INFO
- bool "Compile the kernel with frame unwind information"
- depends on !IA64 && !PARISC && !ARM
- depends on !MODULES || !(MIPS || PPC || SUPERH || V850)
- help
- If you say Y here the resulting kernel image will be slightly larger
- but not slower, and it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame unwind information or frame pointers.
-
-config STACK_UNWIND
- bool "Stack unwind support"
- depends on UNWIND_INFO
- depends on X86
- help
- This enables more precise stack traces, omitting all unrelated
- occurrences of pointers into kernel code from the dump.
-
config FORCED_INLINING
bool "Force gcc to inline functions marked 'inline'"
depends on DEBUG_KERNEL
@@ -372,20 +368,6 @@ config FORCED_INLINING
become the default in the future, until then this option is there to
test gcc for this.
-config HEADERS_CHECK
- bool "Run 'make headers_check' when building vmlinux"
- depends on !UML
- help
- This option will extract the user-visible kernel headers whenever
- building the kernel, and will run basic sanity checks on them to
- ensure that exported files do not attempt to include files which
- were not exported, etc.
-
- If you're making modifications to header files which are
- relevant for userspace, say 'Y', and check the headers
- exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
- your build tree), to make sure they're suitable.
-
config RCU_TORTURE_TEST
tristate "torture tests for RCU"
depends on DEBUG_KERNEL
@@ -402,6 +384,7 @@ config RCU_TORTURE_TEST
config LKDTM
tristate "Linux Kernel Dump Test Tool Module"
+ depends on DEBUG_KERNEL
depends on KPROBES
default n
help
@@ -413,3 +396,36 @@ config LKDTM
Documentation on how to use the module can be found in
drivers/misc/lkdtm.c
+
+config FAULT_INJECTION
+ bool "Fault-injection framework"
+ depends on DEBUG_KERNEL
+ depends on STACKTRACE
+ select FRAME_POINTER
+ help
+ Provide fault-injection framework.
+ For more details, see Documentation/fault-injection/.
+
+config FAILSLAB
+ bool "Fault-injection capability for kmalloc"
+ depends on FAULT_INJECTION
+ help
+ Provide fault-injection capability for kmalloc.
+
+config FAIL_PAGE_ALLOC
+ bool "Fault-injection capabilitiy for alloc_pages()"
+ depends on FAULT_INJECTION
+ help
+ Provide fault-injection capability for alloc_pages().
+
+config FAIL_MAKE_REQUEST
+ bool "Fault-injection capability for disk IO"
+ depends on FAULT_INJECTION
+ help
+ Provide fault-injection capability for disk IO.
+
+config FAULT_INJECTION_DEBUG_FS
+ bool "Debugfs entries for fault-injection capabilities"
+ depends on FAULT_INJECTION && SYSFS && DEBUG_FS
+ help
+ Enable configuration of fault-injection capabilities via debugfs.
diff --git a/lib/Makefile b/lib/Makefile
index fea8f9035f0..77b4bad7d44 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,20 +5,21 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
- sha1.o irq_regs.o
+ sha1.o irq_regs.o reciprocal_div.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o kobject_uevent.o klist.o
-obj-y += sort.o parser.o halfmd4.o iomap_copy.o debug_locks.o random32.o
+obj-y += sort.o parser.o halfmd4.o debug_locks.o random32.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
CFLAGS_kobject_uevent.o += -DDEBUG
endif
+obj-$(CONFIG_IOMAP_COPY) += iomap_copy.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
@@ -35,6 +36,7 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
lib-y += dec_and_lock.o
endif
+obj-$(CONFIG_BITREVERSE) += bitrev.o
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
obj-$(CONFIG_CRC16) += crc16.o
obj-$(CONFIG_CRC32) += crc32.o
@@ -54,6 +56,9 @@ obj-$(CONFIG_SMP) += percpu_counter.o
obj-$(CONFIG_AUDIT_GENERIC) += audit.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o
+obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
+
+lib-$(CONFIG_GENERIC_BUG) += bug.o
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/bitrev.c b/lib/bitrev.c
new file mode 100644
index 00000000000..989aff73f88
--- /dev/null
+++ b/lib/bitrev.c
@@ -0,0 +1,58 @@
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/bitrev.h>
+
+MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
+MODULE_DESCRIPTION("Bit ordering reversal functions");
+MODULE_LICENSE("GPL");
+
+const u8 byte_rev_table[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,
+};
+EXPORT_SYMBOL_GPL(byte_rev_table);
+
+static __always_inline u16 bitrev16(u16 x)
+{
+ return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
+}
+
+/**
+ * bitrev32 - reverse the order of bits in a u32 value
+ * @x: value to be bit-reversed
+ */
+u32 bitrev32(u32 x)
+{
+ return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
+}
+EXPORT_SYMBOL(bitrev32);
diff --git a/lib/bug.c b/lib/bug.c
new file mode 100644
index 00000000000..014b582c5c4
--- /dev/null
+++ b/lib/bug.c
@@ -0,0 +1,163 @@
+/*
+ Generic support for BUG()
+
+ This respects the following config options:
+
+ CONFIG_BUG - emit BUG traps. Nothing happens without this.
+ CONFIG_GENERIC_BUG - enable this code.
+ CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
+
+ CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
+ (though they're generally always on).
+
+ CONFIG_GENERIC_BUG is set by each architecture using this code.
+
+ To use this, your architecture must:
+
+ 1. Set up the config options:
+ - Enable CONFIG_GENERIC_BUG if CONFIG_BUG
+
+ 2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
+ - Define HAVE_ARCH_BUG
+ - Implement BUG() to generate a faulting instruction
+ - NOTE: struct bug_entry does not have "file" or "line" entries
+ when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
+ the values accordingly.
+
+ 3. Implement the trap
+ - In the illegal instruction trap handler (typically), verify
+ that the fault was in kernel mode, and call report_bug()
+ - report_bug() will return whether it was a false alarm, a warning,
+ or an actual bug.
+ - You must implement the is_valid_bugaddr(bugaddr) callback which
+ returns true if the eip is a real kernel address, and it points
+ to the expected BUG trap instruction.
+
+ Jeremy Fitzhardinge <jeremy@goop.org> 2006
+ */
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/bug.h>
+
+extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
+
+#ifdef CONFIG_MODULES
+static LIST_HEAD(module_bug_list);
+
+static const struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+ struct module *mod;
+
+ list_for_each_entry(mod, &module_bug_list, bug_list) {
+ const struct bug_entry *bug = mod->bug_table;
+ unsigned i;
+
+ for (i = 0; i < mod->num_bugs; ++i, ++bug)
+ if (bugaddr == bug->bug_addr)
+ return bug;
+ }
+ return NULL;
+}
+
+int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ struct module *mod)
+{
+ char *secstrings;
+ unsigned int i;
+
+ mod->bug_table = NULL;
+ mod->num_bugs = 0;
+
+ /* Find the __bug_table section, if present */
+ secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
+ continue;
+ mod->bug_table = (void *) sechdrs[i].sh_addr;
+ mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
+ break;
+ }
+
+ /*
+ * Strictly speaking this should have a spinlock to protect against
+ * traversals, but since we only traverse on BUG()s, a spinlock
+ * could potentially lead to deadlock and thus be counter-productive.
+ */
+ list_add(&mod->bug_list, &module_bug_list);
+
+ return 0;
+}
+
+void module_bug_cleanup(struct module *mod)
+{
+ list_del(&mod->bug_list);
+}
+
+#else
+
+static inline const struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+ return NULL;
+}
+#endif
+
+const struct bug_entry *find_bug(unsigned long bugaddr)
+{
+ const struct bug_entry *bug;
+
+ for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
+ if (bugaddr == bug->bug_addr)
+ return bug;
+
+ return module_find_bug(bugaddr);
+}
+
+enum bug_trap_type report_bug(unsigned long bugaddr)
+{
+ const struct bug_entry *bug;
+ const char *file;
+ unsigned line, warning;
+
+ if (!is_valid_bugaddr(bugaddr))
+ return BUG_TRAP_TYPE_NONE;
+
+ bug = find_bug(bugaddr);
+
+ printk(KERN_EMERG "------------[ cut here ]------------\n");
+
+ file = NULL;
+ line = 0;
+ warning = 0;
+
+ if (bug) {
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+ file = bug->file;
+ line = bug->line;
+#endif
+ warning = (bug->flags & BUGFLAG_WARNING) != 0;
+ }
+
+ if (warning) {
+ /* this is a WARN_ON rather than BUG/BUG_ON */
+ if (file)
+ printk(KERN_ERR "Badness at %s:%u\n",
+ file, line);
+ else
+ printk(KERN_ERR "Badness at %p "
+ "[verbose debug info unavailable]\n",
+ (void *)bugaddr);
+
+ dump_stack();
+ return BUG_TRAP_TYPE_WARN;
+ }
+
+ if (file)
+ printk(KERN_CRIT "kernel BUG at %s:%u!\n",
+ file, line);
+ else
+ printk(KERN_CRIT "Kernel BUG at %p "
+ "[verbose debug info unavailable]\n",
+ (void *)bugaddr);
+
+ return BUG_TRAP_TYPE_BUG;
+}
diff --git a/lib/crc32.c b/lib/crc32.c
index 285fd9bc61b..bfc33314c72 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -235,23 +235,8 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
}
#endif
-/**
- * bitreverse - reverse the order of bits in a u32 value
- * @x: value to be bit-reversed
- */
-u32 bitreverse(u32 x)
-{
- x = (x >> 16) | (x << 16);
- x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
- x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
- x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
- x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
- return x;
-}
-
EXPORT_SYMBOL(crc32_le);
EXPORT_SYMBOL(crc32_be);
-EXPORT_SYMBOL(bitreverse);
/*
* A brief CRC tutorial.
@@ -400,10 +385,7 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len)
static void bytereverse(unsigned char *buf, size_t len)
{
while (len--) {
- unsigned char x = *buf;
- x = (x >> 4) | (x << 4);
- x = (x >> 2 & 0x33) | (x << 2 & 0xcc);
- x = (x >> 1 & 0x55) | (x << 1 & 0xaa);
+ unsigned char x = bitrev8(*buf);
*buf++ = x;
}
}
@@ -460,11 +442,11 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len)
/* Now swap it around for the other test */
bytereverse(buf, len + 4);
- init = bitreverse(init);
- crc2 = bitreverse(crc1);
- if (crc1 != bitreverse(crc2))
+ init = bitrev32(init);
+ crc2 = bitrev32(crc1);
+ if (crc1 != bitrev32(crc2))
printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n",
- crc1, crc2, bitreverse(crc2));
+ crc1, crc2, bitrev32(crc2));
crc1 = crc32_le(init, buf, len);
if (crc1 != crc2)
printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1,
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
new file mode 100644
index 00000000000..b5a90fc056d
--- /dev/null
+++ b/lib/fault-inject.c
@@ -0,0 +1,306 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/unwind.h>
+#include <linux/stacktrace.h>
+#include <linux/kallsyms.h>
+#include <linux/fault-inject.h>
+
+/*
+ * setup_fault_attr() is a helper function for various __setup handlers, so it
+ * returns 0 on error, because that is what __setup handlers do.
+ */
+int __init setup_fault_attr(struct fault_attr *attr, char *str)
+{
+ unsigned long probability;
+ unsigned long interval;
+ int times;
+ int space;
+
+ /* "<interval>,<probability>,<space>,<times>" */
+ if (sscanf(str, "%lu,%lu,%d,%d",
+ &interval, &probability, &space, &times) < 4) {
+ printk(KERN_WARNING
+ "FAULT_INJECTION: failed to parse arguments\n");
+ return 0;
+ }
+
+ attr->probability = probability;
+ attr->interval = interval;
+ atomic_set(&attr->times, times);
+ atomic_set(&attr->space, space);
+
+ return 1;
+}
+
+static void fail_dump(struct fault_attr *attr)
+{
+ if (attr->verbose > 0)
+ printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n");
+ if (attr->verbose > 1)
+ dump_stack();
+}
+
+#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
+
+static bool fail_task(struct fault_attr *attr, struct task_struct *task)
+{
+ return !in_interrupt() && task->make_it_fail;
+}
+
+#define MAX_STACK_TRACE_DEPTH 32
+
+#if defined(CONFIG_STACKTRACE)
+
+static bool fail_stacktrace(struct fault_attr *attr)
+{
+ struct stack_trace trace;
+ int depth = attr->stacktrace_depth;
+ unsigned long entries[MAX_STACK_TRACE_DEPTH];
+ int n;
+ bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
+
+ if (depth == 0)
+ return found;
+
+ trace.nr_entries = 0;
+ trace.entries = entries;
+ trace.max_entries = depth;
+ trace.skip = 1;
+ trace.all_contexts = 0;
+
+ save_stack_trace(&trace, NULL);
+ for (n = 0; n < trace.nr_entries; n++) {
+ if (attr->reject_start <= entries[n] &&
+ entries[n] < attr->reject_end)
+ return false;
+ if (attr->require_start <= entries[n] &&
+ entries[n] < attr->require_end)
+ found = true;
+ }
+ return found;
+}
+
+#else
+
+static inline bool fail_stacktrace(struct fault_attr *attr)
+{
+ static bool firsttime = true;
+
+ if (firsttime) {
+ printk(KERN_WARNING
+ "This architecture does not implement save_stack_trace()\n");
+ firsttime = false;
+ }
+ return false;
+}
+
+#endif
+
+/*
+ * This code is stolen from failmalloc-1.0
+ * http://www.nongnu.org/failmalloc/
+ */
+
+bool should_fail(struct fault_attr *attr, ssize_t size)
+{
+ if (attr->task_filter && !fail_task(attr, current))
+ return false;
+
+ if (atomic_read(&attr->times) == 0)
+ return false;
+
+ if (atomic_read(&attr->space) > size) {
+ atomic_sub(size, &attr->space);
+ return false;
+ }
+
+ if (attr->interval > 1) {
+ attr->count++;
+ if (attr->count % attr->interval)
+ return false;
+ }
+
+ if (attr->probability <= random32() % 100)
+ return false;
+
+ if (!fail_stacktrace(attr))
+ return false;
+
+ fail_dump(attr);
+
+ if (atomic_read(&attr->times) != -1)
+ atomic_dec_not_zero(&attr->times);
+
+ return true;
+}
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+static void debugfs_ul_set(void *data, u64 val)
+{
+ *(unsigned long *)data = val;
+}
+
+static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
+{
+ *(unsigned long *)data =
+ val < MAX_STACK_TRACE_DEPTH ?
+ val : MAX_STACK_TRACE_DEPTH;
+}
+
+static u64 debugfs_ul_get(void *data)
+{
+ return *(unsigned long *)data;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n");
+
+static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
+ struct dentry *parent, unsigned long *value)
+{
+ return debugfs_create_file(name, mode, parent, value, &fops_ul);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
+ debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
+
+static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
+ const char *name, mode_t mode,
+ struct dentry *parent, unsigned long *value)
+{
+ return debugfs_create_file(name, mode, parent, value,
+ &fops_ul_MAX_STACK_TRACE_DEPTH);
+}
+
+static void debugfs_atomic_t_set(void *data, u64 val)
+{
+ atomic_set((atomic_t *)data, val);
+}
+
+static u64 debugfs_atomic_t_get(void *data)
+{
+ return atomic_read((atomic_t *)data);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
+ debugfs_atomic_t_set, "%lld\n");
+
+static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
+ struct dentry *parent, atomic_t *value)
+{
+ return debugfs_create_file(name, mode, parent, value, &fops_atomic_t);
+}
+
+void cleanup_fault_attr_dentries(struct fault_attr *attr)
+{
+ debugfs_remove(attr->dentries.probability_file);
+ attr->dentries.probability_file = NULL;
+
+ debugfs_remove(attr->dentries.interval_file);
+ attr->dentries.interval_file = NULL;
+
+ debugfs_remove(attr->dentries.times_file);
+ attr->dentries.times_file = NULL;
+
+ debugfs_remove(attr->dentries.space_file);
+ attr->dentries.space_file = NULL;
+
+ debugfs_remove(attr->dentries.verbose_file);
+ attr->dentries.verbose_file = NULL;
+
+ debugfs_remove(attr->dentries.task_filter_file);
+ attr->dentries.task_filter_file = NULL;
+
+ debugfs_remove(attr->dentries.stacktrace_depth_file);
+ attr->dentries.stacktrace_depth_file = NULL;
+
+ debugfs_remove(attr->dentries.require_start_file);
+ attr->dentries.require_start_file = NULL;
+
+ debugfs_remove(attr->dentries.require_end_file);
+ attr->dentries.require_end_file = NULL;
+
+ debugfs_remove(attr->dentries.reject_start_file);
+ attr->dentries.reject_start_file = NULL;
+
+ debugfs_remove(attr->dentries.reject_end_file);
+ attr->dentries.reject_end_file = NULL;
+
+ if (attr->dentries.dir)
+ WARN_ON(!simple_empty(attr->dentries.dir));
+
+ debugfs_remove(attr->dentries.dir);
+ attr->dentries.dir = NULL;
+}
+
+int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
+{
+ mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+ struct dentry *dir;
+
+ memset(&attr->dentries, 0, sizeof(attr->dentries));
+
+ dir = debugfs_create_dir(name, NULL);
+ if (!dir)
+ goto fail;
+ attr->dentries.dir = dir;
+
+ attr->dentries.probability_file =
+ debugfs_create_ul("probability", mode, dir, &attr->probability);
+
+ attr->dentries.interval_file =
+ debugfs_create_ul("interval", mode, dir, &attr->interval);
+
+ attr->dentries.times_file =
+ debugfs_create_atomic_t("times", mode, dir, &attr->times);
+
+ attr->dentries.space_file =
+ debugfs_create_atomic_t("space", mode, dir, &attr->space);
+
+ attr->dentries.verbose_file =
+ debugfs_create_ul("verbose", mode, dir, &attr->verbose);
+
+ attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
+ mode, dir, &attr->task_filter);
+
+ attr->dentries.stacktrace_depth_file =
+ debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
+ "stacktrace-depth", mode, dir, &attr->stacktrace_depth);
+
+ attr->dentries.require_start_file =
+ debugfs_create_ul("require-start", mode, dir, &attr->require_start);
+
+ attr->dentries.require_end_file =
+ debugfs_create_ul("require-end", mode, dir, &attr->require_end);
+
+ attr->dentries.reject_start_file =
+ debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
+
+ attr->dentries.reject_end_file =
+ debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
+
+
+ if (!attr->dentries.probability_file || !attr->dentries.interval_file
+ || !attr->dentries.times_file || !attr->dentries.space_file
+ || !attr->dentries.verbose_file || !attr->dentries.task_filter_file
+ || !attr->dentries.stacktrace_depth_file
+ || !attr->dentries.require_start_file
+ || !attr->dentries.require_end_file
+ || !attr->dentries.reject_start_file
+ || !attr->dentries.reject_end_file
+ )
+ goto fail;
+
+ return 0;
+fail:
+ cleanup_fault_attr_dentries(attr);
+ return -ENOMEM;
+}
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 99fa277f9f7..a9e4415b02d 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -5,7 +5,6 @@
*
* (C) Copyright 1995 1996 Linus Torvalds
*/
-#include <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index a1922765ff3..84272ed77f0 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -63,8 +63,11 @@ static char *action_to_string(enum kobject_action action)
* @action: action that is happening (usually KOBJ_MOVE)
* @kobj: struct kobject that the action is happening to
* @envp_ext: pointer to environmental data
+ *
+ * Returns 0 if kobject_uevent() is completed with success or the
+ * corresponding error when it fails.
*/
-void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp_ext[])
{
char **envp;
@@ -79,14 +82,16 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
u64 seq;
char *seq_buff;
int i = 0;
- int retval;
+ int retval = 0;
int j;
pr_debug("%s\n", __FUNCTION__);
action_string = action_to_string(action);
- if (!action_string)
- return;
+ if (!action_string) {
+ pr_debug("kobject attempted to send uevent without action_string!\n");
+ return -EINVAL;
+ }
/* search the kset we belong to */
top_kobj = kobj;
@@ -95,31 +100,39 @@ void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
top_kobj = top_kobj->parent;
} while (!top_kobj->kset && top_kobj->parent);
}
- if (!top_kobj->kset)
- return;
+ if (!top_kobj->kset) {
+ pr_debug("kobject attempted to send uevent without kset!\n");
+ return -EINVAL;
+ }
kset = top_kobj->kset;
uevent_ops = kset->uevent_ops;
/* skip the event, if the filter returns zero. */
if (uevent_ops && uevent_ops->filter)
- if (!uevent_ops->filter(kset, kobj))
- return;
+ if (!uevent_ops->filter(kset, kobj)) {
+ pr_debug("kobject filter function caused the event to drop!\n");
+ return 0;
+ }
/* environment index */
envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
if (!envp)
- return;
+ return -ENOMEM;
/* environment values */
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
- if (!buffer)
+ if (!buffer) {
+ retval = -ENOMEM;
goto exit;
+ }
/* complete object path */
devpath = kobject_get_path(kobj, GFP_KERNEL);
- if (!devpath)
+ if (!devpath) {
+ retval = -ENOENT;
goto exit;
+ }
/* originating subsystem */
if (uevent_ops && uevent_ops->name)
@@ -204,7 +217,7 @@ exit:
kfree(devpath);
kfree(buffer);
kfree(envp);
- return;
+ return retval;
}
EXPORT_SYMBOL_GPL(kobject_uevent_env);
@@ -214,10 +227,13 @@ EXPORT_SYMBOL_GPL(kobject_uevent_env);
*
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
* @kobj: struct kobject that the action is happening to
+ *
+ * Returns 0 if kobject_uevent() is completed with success or the
+ * corresponding error when it fails.
*/
-void kobject_uevent(struct kobject *kobj, enum kobject_action action)
+int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{
- kobject_uevent_env(kobj, action, NULL);
+ return kobject_uevent_env(kobj, action, NULL);
}
EXPORT_SYMBOL_GPL(kobject_uevent);
diff --git a/lib/kref.c b/lib/kref.c
index 4a467faf136..0d07cc31c81 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -52,12 +52,7 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref))
WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree);
- /*
- * if current count is one, we are the last user and can release object
- * right now, avoiding an atomic operation on 'refcount'
- */
- if ((atomic_read(&kref->refcount) == 1) ||
- (atomic_dec_and_test(&kref->refcount))) {
+ if (atomic_dec_and_test(&kref->refcount)) {
release(kref);
return 1;
}
diff --git a/lib/reciprocal_div.c b/lib/reciprocal_div.c
new file mode 100644
index 00000000000..6a3bd48fa2a
--- /dev/null
+++ b/lib/reciprocal_div.c
@@ -0,0 +1,9 @@
+#include <asm/div64.h>
+#include <linux/reciprocal_div.h>
+
+u32 reciprocal_value(u32 k)
+{
+ u64 val = (1LL << 32) + (k - 1);
+ do_div(val, k);
+ return (u32)val;
+}
diff --git a/mm/bounce.c b/mm/bounce.c
index e4b62d2a402..643efbe8240 100644
--- a/mm/bounce.c
+++ b/mm/bounce.c
@@ -237,6 +237,8 @@ static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig,
if (!bio)
return;
+ blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE);
+
/*
* at least one page was bounced, fill in possible non-highmem
* pages
@@ -291,8 +293,6 @@ void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig)
pool = isa_page_pool;
}
- blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE);
-
/*
* slow path
*/
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 168c78a121b..0df4c899e97 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -38,7 +38,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
if (!file)
return -EBADF;
- if (S_ISFIFO(file->f_dentry->d_inode->i_mode)) {
+ if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) {
ret = -ESPIPE;
goto out;
}
diff --git a/mm/filemap.c b/mm/filemap.c
index af7e2f5caea..8332c77b1bd 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1181,8 +1181,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
if (pos < size) {
retval = generic_file_direct_IO(READ, iocb,
iov, pos, nr_segs);
- if (retval > 0 && !is_sync_kiocb(iocb))
- retval = -EIOCBQUEUED;
if (retval > 0)
*ppos = pos + retval;
}
@@ -2047,15 +2045,14 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
* Sync the fs metadata but not the minor inode changes and
* of course not the data as we did direct DMA for the IO.
* i_mutex is held, which protects generic_osync_inode() from
- * livelocking.
+ * livelocking. AIO O_DIRECT ops attempt to sync metadata here.
*/
- if (written >= 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+ if ((written >= 0 || written == -EIOCBQUEUED) &&
+ ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err = generic_osync_inode(inode, mapping, OSYNC_METADATA);
if (err < 0)
written = err;
}
- if (written == count && !is_sync_kiocb(iocb))
- written = -EIOCBQUEUED;
return written;
}
EXPORT_SYMBOL(generic_file_direct_write);
@@ -2269,7 +2266,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
if (count == 0)
goto out;
- err = remove_suid(file->f_dentry);
+ err = remove_suid(file->f_path.dentry);
if (err)
goto out;
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index b4fd0d7c9bf..9dd9fbb7513 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -183,13 +183,13 @@ __xip_unmap (struct address_space * mapping,
address = vma->vm_start +
((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
BUG_ON(address < vma->vm_start || address >= vma->vm_end);
- page = ZERO_PAGE(address);
+ page = ZERO_PAGE(0);
pte = page_check_address(page, mm, address, &ptl);
if (pte) {
/* Nuke the page table entry. */
flush_cache_page(vma, address, pte_pfn(*pte));
pteval = ptep_clear_flush(vma, address, pte);
- page_remove_rmap(page);
+ page_remove_rmap(page, vma);
dec_mm_counter(mm, file_rss);
BUG_ON(pte_dirty(pteval));
pte_unmap_unlock(pte, ptl);
@@ -246,7 +246,7 @@ xip_file_nopage(struct vm_area_struct * area,
__xip_unmap(mapping, pgoff);
} else {
/* not shared and writable, use ZERO_PAGE() */
- page = ZERO_PAGE(address);
+ page = ZERO_PAGE(0);
}
out:
@@ -379,7 +379,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
if (count == 0)
goto out_backing;
- ret = remove_suid(filp->f_dentry);
+ ret = remove_suid(filp->f_path.dentry);
if (ret)
goto out_backing;
diff --git a/mm/fremap.c b/mm/fremap.c
index b77a002c335..4e3f53dd5fd 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -33,7 +33,7 @@ static int zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
if (page) {
if (pte_dirty(pte))
set_page_dirty(page);
- page_remove_rmap(page);
+ page_remove_rmap(page, vma);
page_cache_release(page);
}
} else {
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 0ccc7f23025..cb362f761f1 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -44,14 +44,14 @@ static void clear_huge_page(struct page *page, unsigned long addr)
}
static void copy_huge_page(struct page *dst, struct page *src,
- unsigned long addr)
+ unsigned long addr, struct vm_area_struct *vma)
{
int i;
might_sleep();
for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++) {
cond_resched();
- copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE);
+ copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE, vma);
}
}
@@ -73,7 +73,7 @@ static struct page *dequeue_huge_page(struct vm_area_struct *vma,
for (z = zonelist->zones; *z; z++) {
nid = zone_to_nid(*z);
- if (cpuset_zone_allowed(*z, GFP_HIGHUSER) &&
+ if (cpuset_zone_allowed_softwall(*z, GFP_HIGHUSER) &&
!list_empty(&hugepage_freelists[nid]))
break;
}
@@ -442,7 +442,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
}
spin_unlock(&mm->page_table_lock);
- copy_huge_page(new_page, old_page, address);
+ copy_huge_page(new_page, old_page, address, vma);
spin_lock(&mm->page_table_lock);
ptep = huge_pte_offset(mm, address & HPAGE_MASK);
diff --git a/mm/memory.c b/mm/memory.c
index 4198df0dff1..ef09f0acb1d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -681,7 +681,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
mark_page_accessed(page);
file_rss--;
}
- page_remove_rmap(page);
+ page_remove_rmap(page, vma);
tlb_remove_page(tlb, page);
continue;
}
@@ -1091,7 +1091,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
if (pages) {
pages[i] = page;
- flush_anon_page(page, start);
+ flush_anon_page(vma, page, start);
flush_dcache_page(page);
}
if (vmas)
@@ -1110,23 +1110,29 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
{
pte_t *pte;
spinlock_t *ptl;
+ int err = 0;
pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
if (!pte)
- return -ENOMEM;
+ return -EAGAIN;
arch_enter_lazy_mmu_mode();
do {
struct page *page = ZERO_PAGE(addr);
pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
+
+ if (unlikely(!pte_none(*pte))) {
+ err = -EEXIST;
+ pte++;
+ break;
+ }
page_cache_get(page);
page_add_file_rmap(page);
inc_mm_counter(mm, file_rss);
- BUG_ON(!pte_none(*pte));
set_pte_at(mm, addr, pte, zero_pte);
} while (pte++, addr += PAGE_SIZE, addr != end);
arch_leave_lazy_mmu_mode();
pte_unmap_unlock(pte - 1, ptl);
- return 0;
+ return err;
}
static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
@@ -1134,16 +1140,18 @@ static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
{
pmd_t *pmd;
unsigned long next;
+ int err;
pmd = pmd_alloc(mm, pud, addr);
if (!pmd)
- return -ENOMEM;
+ return -EAGAIN;
do {
next = pmd_addr_end(addr, end);
- if (zeromap_pte_range(mm, pmd, addr, next, prot))
- return -ENOMEM;
+ err = zeromap_pte_range(mm, pmd, addr, next, prot);
+ if (err)
+ break;
} while (pmd++, addr = next, addr != end);
- return 0;
+ return err;
}
static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
@@ -1151,16 +1159,18 @@ static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
{
pud_t *pud;
unsigned long next;
+ int err;
pud = pud_alloc(mm, pgd, addr);
if (!pud)
- return -ENOMEM;
+ return -EAGAIN;
do {
next = pud_addr_end(addr, end);
- if (zeromap_pmd_range(mm, pud, addr, next, prot))
- return -ENOMEM;
+ err = zeromap_pmd_range(mm, pud, addr, next, prot);
+ if (err)
+ break;
} while (pud++, addr = next, addr != end);
- return 0;
+ return err;
}
int zeromap_page_range(struct vm_area_struct *vma,
@@ -1431,7 +1441,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
return pte;
}
-static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va)
+static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
{
/*
* If the source page was a PFN mapping, we don't have
@@ -1454,9 +1464,9 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
kunmap_atomic(kaddr, KM_USER0);
flush_dcache_page(dst);
return;
-
+
}
- copy_user_highpage(dst, src, va);
+ copy_user_highpage(dst, src, va, vma);
}
/*
@@ -1567,7 +1577,7 @@ gotten:
new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
if (!new_page)
goto oom;
- cow_user_page(new_page, old_page, address);
+ cow_user_page(new_page, old_page, address, vma);
}
/*
@@ -1576,7 +1586,7 @@ gotten:
page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
if (likely(pte_same(*page_table, orig_pte))) {
if (old_page) {
- page_remove_rmap(old_page);
+ page_remove_rmap(old_page, vma);
if (!PageAnon(old_page)) {
dec_mm_counter(mm, file_rss);
inc_mm_counter(mm, anon_rss);
@@ -2190,7 +2200,7 @@ retry:
page = alloc_page_vma(GFP_HIGHUSER, vma, address);
if (!page)
goto oom;
- copy_user_highpage(page, new_page, address);
+ copy_user_highpage(page, new_page, address, vma);
page_cache_release(new_page);
new_page = page;
anon = 1;
@@ -2596,8 +2606,15 @@ static int __init gate_vma_init(void)
gate_vma.vm_mm = NULL;
gate_vma.vm_start = FIXADDR_USER_START;
gate_vma.vm_end = FIXADDR_USER_END;
- gate_vma.vm_page_prot = PAGE_READONLY;
- gate_vma.vm_flags = 0;
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+ gate_vma.vm_page_prot = __P101;
+ /*
+ * Make sure the vDSO gets into every core dump.
+ * Dumping its contents makes post-mortem fully interpretable later
+ * without matching up the same kernel and hardware config to see
+ * what PC values meant.
+ */
+ gate_vma.vm_flags |= VM_ALWAYSDUMP;
return 0;
}
__initcall(gate_vma_init);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 0c055a090f4..84279127fcd 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -67,11 +67,13 @@ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
zone_type = zone - pgdat->node_zones;
if (!populated_zone(zone)) {
int ret = 0;
- ret = init_currently_empty_zone(zone, phys_start_pfn, nr_pages);
+ ret = init_currently_empty_zone(zone, phys_start_pfn,
+ nr_pages, MEMMAP_HOTPLUG);
if (ret < 0)
return ret;
}
- memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn);
+ memmap_init_zone(nr_pages, nid, zone_type,
+ phys_start_pfn, MEMMAP_HOTPLUG);
return 0;
}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index b917d6fdc1b..c2aec0e1090 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -884,6 +884,10 @@ asmlinkage long sys_mbind(unsigned long start, unsigned long len,
err = get_nodes(&nodes, nmask, maxnode);
if (err)
return err;
+#ifdef CONFIG_CPUSETS
+ /* Restrict the nodes to the allowed nodes in the cpuset */
+ nodes_and(nodes, nodes, current->mems_allowed);
+#endif
return do_mbind(start, len, mode, &nodes, flags);
}
@@ -1857,7 +1861,7 @@ int show_numa_map(struct seq_file *m, void *v)
if (file) {
seq_printf(m, " file=");
- seq_path(m, file->f_vfsmnt, file->f_dentry, "\n\t= ");
+ seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n\t= ");
} else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
seq_printf(m, " heap");
} else if (vma->vm_start <= mm->start_stack &&
diff --git a/mm/mincore.c b/mm/mincore.c
index 72890780c1c..8aca6f7167b 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -1,7 +1,7 @@
/*
* linux/mm/mincore.c
*
- * Copyright (C) 1994-1999 Linus Torvalds
+ * Copyright (C) 1994-2006 Linus Torvalds
*/
/*
@@ -38,46 +38,51 @@ static unsigned char mincore_page(struct vm_area_struct * vma,
return present;
}
-static long mincore_vma(struct vm_area_struct * vma,
- unsigned long start, unsigned long end, unsigned char __user * vec)
+/*
+ * Do a chunk of "sys_mincore()". We've already checked
+ * all the arguments, we hold the mmap semaphore: we should
+ * just return the amount of info we're asked for.
+ */
+static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pages)
{
- long error, i, remaining;
- unsigned char * tmp;
-
- error = -ENOMEM;
- if (!vma->vm_file)
- return error;
-
- start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
- if (end > vma->vm_end)
- end = vma->vm_end;
- end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+ unsigned long i, nr, pgoff;
+ struct vm_area_struct *vma = find_vma(current->mm, addr);
- error = -EAGAIN;
- tmp = (unsigned char *) __get_free_page(GFP_KERNEL);
- if (!tmp)
- return error;
+ /*
+ * find_vma() didn't find anything above us, or we're
+ * in an unmapped hole in the address space: ENOMEM.
+ */
+ if (!vma || addr < vma->vm_start)
+ return -ENOMEM;
- /* (end - start) is # of pages, and also # of bytes in "vec */
- remaining = (end - start),
+ /*
+ * Ok, got it. But check whether it's a segment we support
+ * mincore() on. Right now, we don't do any anonymous mappings.
+ *
+ * FIXME: This is just stupid. And returning ENOMEM is
+ * stupid too. We should just look at the page tables. But
+ * this is what we've traditionally done, so we'll just
+ * continue doing it.
+ */
+ if (!vma->vm_file)
+ return -ENOMEM;
- error = 0;
- for (i = 0; remaining > 0; remaining -= PAGE_SIZE, i++) {
- int j = 0;
- long thispiece = (remaining < PAGE_SIZE) ?
- remaining : PAGE_SIZE;
+ /*
+ * Calculate how many pages there are left in the vma, and
+ * what the pgoff is for our address.
+ */
+ nr = (vma->vm_end - addr) >> PAGE_SHIFT;
+ if (nr > pages)
+ nr = pages;
- while (j < thispiece)
- tmp[j++] = mincore_page(vma, start++);
+ pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
+ pgoff += vma->vm_pgoff;
- if (copy_to_user(vec + PAGE_SIZE * i, tmp, thispiece)) {
- error = -EFAULT;
- break;
- }
- }
+ /* And then we just fill the sucker in.. */
+ for (i = 0 ; i < nr; i++, pgoff++)
+ vec[i] = mincore_page(vma, pgoff);
- free_page((unsigned long) tmp);
- return error;
+ return nr;
}
/*
@@ -107,82 +112,50 @@ static long mincore_vma(struct vm_area_struct * vma,
asmlinkage long sys_mincore(unsigned long start, size_t len,
unsigned char __user * vec)
{
- int index = 0;
- unsigned long end, limit;
- struct vm_area_struct * vma;
- size_t max;
- int unmapped_error = 0;
- long error;
-
- /* check the arguments */
- if (start & ~PAGE_CACHE_MASK)
- goto einval;
-
- limit = TASK_SIZE;
- if (start >= limit)
- goto enomem;
-
- if (!len)
- return 0;
-
- max = limit - start;
- len = PAGE_CACHE_ALIGN(len);
- if (len > max || !len)
- goto enomem;
+ long retval;
+ unsigned long pages;
+ unsigned char *tmp;
- end = start + len;
+ /* Check the start address: needs to be page-aligned.. */
+ if (start & ~PAGE_CACHE_MASK)
+ return -EINVAL;
- /* check the output buffer whilst holding the lock */
- error = -EFAULT;
- down_read(&current->mm->mmap_sem);
+ /* ..and we need to be passed a valid user-space range */
+ if (!access_ok(VERIFY_READ, (void __user *) start, len))
+ return -ENOMEM;
- if (!access_ok(VERIFY_WRITE, vec, len >> PAGE_SHIFT))
- goto out;
+ /* This also avoids any overflows on PAGE_CACHE_ALIGN */
+ pages = len >> PAGE_SHIFT;
+ pages += (len & ~PAGE_MASK) != 0;
- /*
- * If the interval [start,end) covers some unmapped address
- * ranges, just ignore them, but return -ENOMEM at the end.
- */
- error = 0;
-
- vma = find_vma(current->mm, start);
- while (vma) {
- /* Here start < vma->vm_end. */
- if (start < vma->vm_start) {
- unmapped_error = -ENOMEM;
- start = vma->vm_start;
- }
+ if (!access_ok(VERIFY_WRITE, vec, pages))
+ return -EFAULT;
- /* Here vma->vm_start <= start < vma->vm_end. */
- if (end <= vma->vm_end) {
- if (start < end) {
- error = mincore_vma(vma, start, end,
- &vec[index]);
- if (error)
- goto out;
- }
- error = unmapped_error;
- goto out;
+ tmp = (void *) __get_free_page(GFP_USER);
+ if (!tmp)
+ return -EAGAIN;
+
+ retval = 0;
+ while (pages) {
+ /*
+ * Do at most PAGE_SIZE entries per iteration, due to
+ * the temporary buffer size.
+ */
+ down_read(&current->mm->mmap_sem);
+ retval = do_mincore(start, tmp, min(pages, PAGE_SIZE));
+ up_read(&current->mm->mmap_sem);
+
+ if (retval <= 0)
+ break;
+ if (copy_to_user(vec, tmp, retval)) {
+ retval = -EFAULT;
+ break;
}
-
- /* Here vma->vm_start <= start < vma->vm_end < end. */
- error = mincore_vma(vma, start, vma->vm_end, &vec[index]);
- if (error)
- goto out;
- index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT;
- start = vma->vm_end;
- vma = vma->vm_next;
+ pages -= retval;
+ vec += retval;
+ start += retval << PAGE_SHIFT;
+ retval = 0;
}
-
- /* we found a hole in the area queried if we arrive here */
- error = -ENOMEM;
-
-out:
- up_read(&current->mm->mmap_sem);
- return error;
-
-einval:
- return -EINVAL;
-enomem:
- return -ENOMEM;
+ free_page((unsigned long) tmp);
+ return retval;
}
diff --git a/mm/mmap.c b/mm/mmap.c
index 7be110e98d4..cc3a2081945 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -188,7 +188,7 @@ static void __remove_shared_vm_struct(struct vm_area_struct *vma,
struct file *file, struct address_space *mapping)
{
if (vma->vm_flags & VM_DENYWRITE)
- atomic_inc(&file->f_dentry->d_inode->i_writecount);
+ atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
if (vma->vm_flags & VM_SHARED)
mapping->i_mmap_writable--;
@@ -399,7 +399,7 @@ static inline void __vma_link_file(struct vm_area_struct *vma)
struct address_space *mapping = file->f_mapping;
if (vma->vm_flags & VM_DENYWRITE)
- atomic_dec(&file->f_dentry->d_inode->i_writecount);
+ atomic_dec(&file->f_path.dentry->d_inode->i_writecount);
if (vma->vm_flags & VM_SHARED)
mapping->i_mmap_writable++;
@@ -907,7 +907,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
* mounted, in which case we dont add PROT_EXEC.)
*/
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
- if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
+ if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC)))
prot |= PROT_EXEC;
if (!len)
@@ -960,7 +960,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
return -EAGAIN;
}
- inode = file ? file->f_dentry->d_inode : NULL;
+ inode = file ? file->f_path.dentry->d_inode : NULL;
if (file) {
switch (flags & MAP_TYPE) {
@@ -989,7 +989,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
case MAP_PRIVATE:
if (!(file->f_mode & FMODE_READ))
return -EACCES;
- if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+ if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
if (vm_flags & VM_EXEC)
return -EPERM;
vm_flags &= ~VM_MAYEXEC;
@@ -1477,6 +1477,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
{
struct mm_struct *mm = vma->vm_mm;
struct rlimit *rlim = current->signal->rlim;
+ unsigned long new_start;
/* address space limit tests */
if (!may_expand_vm(mm, grow))
@@ -1496,6 +1497,12 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
return -ENOMEM;
}
+ /* Check to ensure the stack will not grow into a hugetlb-only region */
+ new_start = (vma->vm_flags & VM_GROWSUP) ? vma->vm_start :
+ vma->vm_end - size;
+ if (is_hugepage_only_range(vma->vm_mm, new_start, size))
+ return -EFAULT;
+
/*
* Overcommit.. This must be the final test, as it will
* update security statistics.
diff --git a/mm/mremap.c b/mm/mremap.c
index 9c769fa29f3..5d4bd4f95b8 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -105,7 +105,6 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
if (pte_none(*old_pte))
continue;
pte = ptep_clear_flush(vma, old_addr, old_pte);
- /* ZERO_PAGE can be dependant on virtual addr */
pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
set_pte_at(mm, new_addr, new_pte, pte);
}
diff --git a/mm/nommu.c b/mm/nommu.c
index af874569d0f..23fb033e596 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -523,7 +523,7 @@ static int validate_mmap_request(struct file *file,
*/
mapping = file->f_mapping;
if (!mapping)
- mapping = file->f_dentry->d_inode->i_mapping;
+ mapping = file->f_path.dentry->d_inode->i_mapping;
capabilities = 0;
if (mapping && mapping->backing_dev_info)
@@ -532,7 +532,7 @@ static int validate_mmap_request(struct file *file,
if (!capabilities) {
/* no explicit capabilities set, so assume some
* defaults */
- switch (file->f_dentry->d_inode->i_mode & S_IFMT) {
+ switch (file->f_path.dentry->d_inode->i_mode & S_IFMT) {
case S_IFREG:
case S_IFBLK:
capabilities = BDI_CAP_MAP_COPY;
@@ -563,11 +563,11 @@ static int validate_mmap_request(struct file *file,
!(file->f_mode & FMODE_WRITE))
return -EACCES;
- if (IS_APPEND(file->f_dentry->d_inode) &&
+ if (IS_APPEND(file->f_path.dentry->d_inode) &&
(file->f_mode & FMODE_WRITE))
return -EACCES;
- if (locks_verify_locked(file->f_dentry->d_inode))
+ if (locks_verify_locked(file->f_path.dentry->d_inode))
return -EAGAIN;
if (!(capabilities & BDI_CAP_MAP_DIRECT))
@@ -598,7 +598,7 @@ static int validate_mmap_request(struct file *file,
/* handle executable mappings and implied executable
* mappings */
- if (file->f_vfsmnt->mnt_flags & MNT_NOEXEC) {
+ if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) {
if (prot & PROT_EXEC)
return -EPERM;
}
@@ -833,7 +833,7 @@ unsigned long do_mmap_pgoff(struct file *file,
continue;
/* search for overlapping mappings on the same file */
- if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode)
+ if (vma->vm_file->f_path.dentry->d_inode != file->f_path.dentry->d_inode)
continue;
if (vma->vm_pgoff >= pgoff + pglen)
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 223d9ccb7d6..b278b8d60ee 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -61,12 +61,6 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
}
/*
- * swapoff can easily use up all memory, so kill those first.
- */
- if (p->flags & PF_SWAPOFF)
- return ULONG_MAX;
-
- /*
* The memory size of the process is the basis for the badness.
*/
points = mm->total_vm;
@@ -77,6 +71,12 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
task_unlock(p);
/*
+ * swapoff can easily use up all memory, so kill those first.
+ */
+ if (p->flags & PF_SWAPOFF)
+ return ULONG_MAX;
+
+ /*
* Processes which fork a lot of child processes are likely
* a good choice. We add half the vmsize of the children if they
* have an own mm. This prevents forking servers to flood the
@@ -174,10 +174,15 @@ static inline int constrained_alloc(struct zonelist *zonelist, gfp_t gfp_mask)
{
#ifdef CONFIG_NUMA
struct zone **z;
- nodemask_t nodes = node_online_map;
+ nodemask_t nodes;
+ int node;
+ /* node has memory ? */
+ for_each_online_node(node)
+ if (NODE_DATA(node)->node_present_pages)
+ node_set(node, nodes);
for (z = zonelist->zones; *z; z++)
- if (cpuset_zone_allowed(*z, gfp_mask))
+ if (cpuset_zone_allowed_softwall(*z, gfp_mask))
node_clear(zone_to_nid(*z), nodes);
else
return CONSTRAINT_CPUSET;
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 8d9b19f239c..be0efbde499 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -21,6 +21,7 @@
#include <linux/writeback.h>
#include <linux/init.h>
#include <linux/backing-dev.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/blkdev.h>
#include <linux/mpage.h>
#include <linux/rmap.h>
@@ -132,11 +133,9 @@ get_dirty_limits(long *pbackground, long *pdirty,
#ifdef CONFIG_HIGHMEM
/*
- * If this mapping can only allocate from low memory,
- * we exclude high memory from our count.
+ * We always exclude high memory from our count.
*/
- if (mapping && !(mapping_gfp_mask(mapping) & __GFP_HIGHMEM))
- available_memory -= totalhigh_pages;
+ available_memory -= totalhigh_pages;
#endif
@@ -525,28 +524,25 @@ static struct notifier_block __cpuinitdata ratelimit_nb = {
};
/*
- * If the machine has a large highmem:lowmem ratio then scale back the default
- * dirty memory thresholds: allowing too much dirty highmem pins an excessive
- * number of buffer_heads.
+ * Called early on to tune the page writeback dirty limits.
+ *
+ * We used to scale dirty pages according to how total memory
+ * related to pages that could be allocated for buffers (by
+ * comparing nr_free_buffer_pages() to vm_total_pages.
+ *
+ * However, that was when we used "dirty_ratio" to scale with
+ * all memory, and we don't do that any more. "dirty_ratio"
+ * is now applied to total non-HIGHPAGE memory (by subtracting
+ * totalhigh_pages from vm_total_pages), and as such we can't
+ * get into the old insane situation any more where we had
+ * large amounts of dirty pages compared to a small amount of
+ * non-HIGHMEM memory.
+ *
+ * But we might still want to scale the dirty_ratio by how
+ * much memory the box has..
*/
void __init page_writeback_init(void)
{
- long buffer_pages = nr_free_buffer_pages();
- long correction;
-
- correction = (100 * 4 * buffer_pages) / vm_total_pages;
-
- if (correction < 100) {
- dirty_background_ratio *= correction;
- dirty_background_ratio /= 100;
- vm_dirty_ratio *= correction;
- vm_dirty_ratio /= 100;
-
- if (dirty_background_ratio <= 0)
- dirty_background_ratio = 1;
- if (vm_dirty_ratio <= 0)
- vm_dirty_ratio = 1;
- }
mod_timer(&wb_timer, jiffies + dirty_writeback_interval);
writeback_set_ratelimit();
register_cpu_notifier(&ratelimit_nb);
@@ -761,23 +757,24 @@ int __set_page_dirty_nobuffers(struct page *page)
struct address_space *mapping = page_mapping(page);
struct address_space *mapping2;
- if (mapping) {
- write_lock_irq(&mapping->tree_lock);
- mapping2 = page_mapping(page);
- if (mapping2) { /* Race with truncate? */
- BUG_ON(mapping2 != mapping);
- if (mapping_cap_account_dirty(mapping))
- __inc_zone_page_state(page,
- NR_FILE_DIRTY);
- radix_tree_tag_set(&mapping->page_tree,
- page_index(page), PAGECACHE_TAG_DIRTY);
- }
- write_unlock_irq(&mapping->tree_lock);
- if (mapping->host) {
- /* !PageAnon && !swapper_space */
- __mark_inode_dirty(mapping->host,
- I_DIRTY_PAGES);
+ if (!mapping)
+ return 1;
+
+ write_lock_irq(&mapping->tree_lock);
+ mapping2 = page_mapping(page);
+ if (mapping2) { /* Race with truncate? */
+ BUG_ON(mapping2 != mapping);
+ if (mapping_cap_account_dirty(mapping)) {
+ __inc_zone_page_state(page, NR_FILE_DIRTY);
+ task_io_account_write(PAGE_CACHE_SIZE);
}
+ radix_tree_tag_set(&mapping->page_tree,
+ page_index(page), PAGECACHE_TAG_DIRTY);
+ }
+ write_unlock_irq(&mapping->tree_lock);
+ if (mapping->host) {
+ /* !PageAnon && !swapper_space */
+ __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
}
return 1;
}
@@ -843,39 +840,6 @@ int set_page_dirty_lock(struct page *page)
EXPORT_SYMBOL(set_page_dirty_lock);
/*
- * Clear a page's dirty flag, while caring for dirty memory accounting.
- * Returns true if the page was previously dirty.
- */
-int test_clear_page_dirty(struct page *page)
-{
- struct address_space *mapping = page_mapping(page);
- unsigned long flags;
-
- if (mapping) {
- write_lock_irqsave(&mapping->tree_lock, flags);
- if (TestClearPageDirty(page)) {
- radix_tree_tag_clear(&mapping->page_tree,
- page_index(page),
- PAGECACHE_TAG_DIRTY);
- write_unlock_irqrestore(&mapping->tree_lock, flags);
- /*
- * We can continue to use `mapping' here because the
- * page is locked, which pins the address_space
- */
- if (mapping_cap_account_dirty(mapping)) {
- page_mkclean(page);
- dec_zone_page_state(page, NR_FILE_DIRTY);
- }
- return 1;
- }
- write_unlock_irqrestore(&mapping->tree_lock, flags);
- return 0;
- }
- return TestClearPageDirty(page);
-}
-EXPORT_SYMBOL(test_clear_page_dirty);
-
-/*
* Clear a page's dirty flag, while caring for dirty memory accounting.
* Returns true if the page was previously dirty.
*
@@ -893,12 +857,41 @@ int clear_page_dirty_for_io(struct page *page)
{
struct address_space *mapping = page_mapping(page);
- if (mapping) {
+ if (mapping && mapping_cap_account_dirty(mapping)) {
+ /*
+ * Yes, Virginia, this is indeed insane.
+ *
+ * We use this sequence to make sure that
+ * (a) we account for dirty stats properly
+ * (b) we tell the low-level filesystem to
+ * mark the whole page dirty if it was
+ * dirty in a pagetable. Only to then
+ * (c) clean the page again and return 1 to
+ * cause the writeback.
+ *
+ * This way we avoid all nasty races with the
+ * dirty bit in multiple places and clearing
+ * them concurrently from different threads.
+ *
+ * Note! Normally the "set_page_dirty(page)"
+ * has no effect on the actual dirty bit - since
+ * that will already usually be set. But we
+ * need the side effects, and it can help us
+ * avoid races.
+ *
+ * We basically use the page "master dirty bit"
+ * as a serialization point for all the different
+ * threads doing their things.
+ *
+ * FIXME! We still have a race here: if somebody
+ * adds the page back to the page tables in
+ * between the "page_mkclean()" and the "TestClearPageDirty()",
+ * we might have it mapped without the dirty bit set.
+ */
+ if (page_mkclean(page))
+ set_page_dirty(page);
if (TestClearPageDirty(page)) {
- if (mapping_cap_account_dirty(mapping)) {
- page_mkclean(page);
- dec_zone_page_state(page, NR_FILE_DIRTY);
- }
+ dec_zone_page_state(page, NR_FILE_DIRTY);
return 1;
}
return 0;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index cace22b3ac2..2c606cc922a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -40,6 +40,7 @@
#include <linux/sort.h>
#include <linux/pfn.h>
#include <linux/backing-dev.h>
+#include <linux/fault-inject.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -710,6 +711,9 @@ static void __drain_pages(unsigned int cpu)
for_each_zone(zone) {
struct per_cpu_pageset *pset;
+ if (!populated_zone(zone))
+ continue;
+
pset = zone_pcp(zone, cpu);
for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
struct per_cpu_pages *pcp;
@@ -892,6 +896,91 @@ failed:
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
#define ALLOC_CPUSET 0x40 /* check for correct cpuset */
+#ifdef CONFIG_FAIL_PAGE_ALLOC
+
+static struct fail_page_alloc_attr {
+ struct fault_attr attr;
+
+ u32 ignore_gfp_highmem;
+ u32 ignore_gfp_wait;
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+ struct dentry *ignore_gfp_highmem_file;
+ struct dentry *ignore_gfp_wait_file;
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+} fail_page_alloc = {
+ .attr = FAULT_ATTR_INITIALIZER,
+ .ignore_gfp_wait = 1,
+ .ignore_gfp_highmem = 1,
+};
+
+static int __init setup_fail_page_alloc(char *str)
+{
+ return setup_fault_attr(&fail_page_alloc.attr, str);
+}
+__setup("fail_page_alloc=", setup_fail_page_alloc);
+
+static int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+{
+ if (gfp_mask & __GFP_NOFAIL)
+ return 0;
+ if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM))
+ return 0;
+ if (fail_page_alloc.ignore_gfp_wait && (gfp_mask & __GFP_WAIT))
+ return 0;
+
+ return should_fail(&fail_page_alloc.attr, 1 << order);
+}
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+static int __init fail_page_alloc_debugfs(void)
+{
+ mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+ struct dentry *dir;
+ int err;
+
+ err = init_fault_attr_dentries(&fail_page_alloc.attr,
+ "fail_page_alloc");
+ if (err)
+ return err;
+ dir = fail_page_alloc.attr.dentries.dir;
+
+ fail_page_alloc.ignore_gfp_wait_file =
+ debugfs_create_bool("ignore-gfp-wait", mode, dir,
+ &fail_page_alloc.ignore_gfp_wait);
+
+ fail_page_alloc.ignore_gfp_highmem_file =
+ debugfs_create_bool("ignore-gfp-highmem", mode, dir,
+ &fail_page_alloc.ignore_gfp_highmem);
+
+ if (!fail_page_alloc.ignore_gfp_wait_file ||
+ !fail_page_alloc.ignore_gfp_highmem_file) {
+ err = -ENOMEM;
+ debugfs_remove(fail_page_alloc.ignore_gfp_wait_file);
+ debugfs_remove(fail_page_alloc.ignore_gfp_highmem_file);
+ cleanup_fault_attr_dentries(&fail_page_alloc.attr);
+ }
+
+ return err;
+}
+
+late_initcall(fail_page_alloc_debugfs);
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+#else /* CONFIG_FAIL_PAGE_ALLOC */
+
+static inline int should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
+{
+ return 0;
+}
+
+#endif /* CONFIG_FAIL_PAGE_ALLOC */
+
/*
* Return 1 if free pages are above 'mark'. This takes into account the order
* of the allocation.
@@ -900,8 +989,7 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
int classzone_idx, int alloc_flags)
{
/* free_pages my go negative - that's OK */
- unsigned long min = mark;
- long free_pages = z->free_pages - (1 << order) + 1;
+ long min = mark, free_pages = z->free_pages - (1 << order) + 1;
int o;
if (alloc_flags & ALLOC_HIGH)
@@ -1076,7 +1164,7 @@ zonelist_scan:
zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
break;
if ((alloc_flags & ALLOC_CPUSET) &&
- !cpuset_zone_allowed(zone, gfp_mask))
+ !cpuset_zone_allowed_softwall(zone, gfp_mask))
goto try_next_zone;
if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {
@@ -1136,6 +1224,9 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order,
might_sleep_if(wait);
+ if (should_fail_alloc_page(gfp_mask, order))
+ return NULL;
+
restart:
z = zonelist->zones; /* the list of zones suitable for gfp_mask */
@@ -1864,17 +1955,24 @@ static inline unsigned long wait_table_bits(unsigned long size)
* done. Non-atomic initialization, single-pass.
*/
void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
- unsigned long start_pfn)
+ unsigned long start_pfn, enum memmap_context context)
{
struct page *page;
unsigned long end_pfn = start_pfn + size;
unsigned long pfn;
for (pfn = start_pfn; pfn < end_pfn; pfn++) {
- if (!early_pfn_valid(pfn))
- continue;
- if (!early_pfn_in_nid(pfn, nid))
- continue;
+ /*
+ * There can be holes in boot-time mem_map[]s
+ * handed to this function. They do not
+ * exist on hotplugged memory.
+ */
+ if (context == MEMMAP_EARLY) {
+ if (!early_pfn_valid(pfn))
+ continue;
+ if (!early_pfn_in_nid(pfn, nid))
+ continue;
+ }
page = pfn_to_page(pfn);
set_page_links(page, zone, nid, pfn);
init_page_count(page);
@@ -1901,7 +1999,7 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
#ifndef __HAVE_ARCH_MEMMAP_INIT
#define memmap_init(size, nid, zone, start_pfn) \
- memmap_init_zone((size), (nid), (zone), (start_pfn))
+ memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
#endif
static int __cpuinit zone_batchsize(struct zone *zone)
@@ -2147,7 +2245,8 @@ static __meminit void zone_pcp_init(struct zone *zone)
__meminit int init_currently_empty_zone(struct zone *zone,
unsigned long zone_start_pfn,
- unsigned long size)
+ unsigned long size,
+ enum memmap_context context)
{
struct pglist_data *pgdat = zone->zone_pgdat;
int ret;
@@ -2591,7 +2690,8 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
if (!size)
continue;
- ret = init_currently_empty_zone(zone, zone_start_pfn, size);
+ ret = init_currently_empty_zone(zone, zone_start_pfn,
+ size, MEMMAP_EARLY);
BUG_ON(ret);
zone_start_pfn += size;
}
@@ -3232,6 +3332,10 @@ void *__init alloc_large_system_hash(const char *tablename,
numentries >>= (scale - PAGE_SHIFT);
else
numentries <<= (PAGE_SHIFT - scale);
+
+ /* Make sure we've got at least a 0-order allocation.. */
+ if (unlikely((numentries * bucketsize) < PAGE_SIZE))
+ numentries = PAGE_SIZE / bucketsize;
}
numentries = roundup_pow_of_two(numentries);
@@ -3244,7 +3348,7 @@ void *__init alloc_large_system_hash(const char *tablename,
if (numentries > max)
numentries = max;
- log2qty = long_log2(numentries);
+ log2qty = ilog2(numentries);
do {
size = bucketsize << log2qty;
@@ -3266,7 +3370,7 @@ void *__init alloc_large_system_hash(const char *tablename,
printk("%s hash table entries: %d (order: %d, %lu bytes)\n",
tablename,
(1U << log2qty),
- long_log2(size) - PAGE_SHIFT,
+ ilog2(size) - PAGE_SHIFT,
size);
if (_hash_shift)
diff --git a/mm/readahead.c b/mm/readahead.c
index a386f2b6b33..0f539e8e827 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/pagevec.h>
void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
@@ -151,6 +152,7 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
put_pages_list(pages);
break;
}
+ task_io_account_read(PAGE_CACHE_SIZE);
}
pagevec_lru_add(&lru_pvec);
return ret;
@@ -450,7 +452,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp,
*
* Note that @filp is purely used for passing on to the ->readpage[s]()
* handler: it may refer to a different file from @mapping (so we may not use
- * @filp->f_mapping or @filp->f_dentry->d_inode here).
+ * @filp->f_mapping or @filp->f_path.dentry->d_inode here).
* Also, @ra may not be equal to &@filp->f_ra.
*
*/
diff --git a/mm/rmap.c b/mm/rmap.c
index d8a842a586d..669acb22b57 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -47,6 +47,7 @@
#include <linux/rmap.h>
#include <linux/rcupdate.h>
#include <linux/module.h>
+#include <linux/kallsyms.h>
#include <asm/tlbflush.h>
@@ -432,7 +433,7 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long address;
- pte_t *pte, entry;
+ pte_t *pte;
spinlock_t *ptl;
int ret = 0;
@@ -444,17 +445,18 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
if (!pte)
goto out;
- if (!pte_dirty(*pte) && !pte_write(*pte))
- goto unlock;
+ if (pte_dirty(*pte) || pte_write(*pte)) {
+ pte_t entry;
- entry = ptep_get_and_clear(mm, address, pte);
- entry = pte_mkclean(entry);
- entry = pte_wrprotect(entry);
- ptep_establish(vma, address, pte, entry);
- lazy_mmu_prot_update(entry);
- ret = 1;
+ flush_cache_page(vma, address, pte_pfn(*pte));
+ entry = ptep_clear_flush(vma, address, pte);
+ entry = pte_wrprotect(entry);
+ entry = pte_mkclean(entry);
+ set_pte_at(mm, address, pte, entry);
+ lazy_mmu_prot_update(entry);
+ ret = 1;
+ }
-unlock:
pte_unmap_unlock(pte, ptl);
out:
return ret;
@@ -489,6 +491,8 @@ int page_mkclean(struct page *page)
if (mapping)
ret = page_mkclean_file(mapping, page);
}
+ if (page_test_and_clear_dirty(page))
+ ret = 1;
return ret;
}
@@ -567,14 +571,20 @@ void page_add_file_rmap(struct page *page)
*
* The caller needs to hold the pte lock.
*/
-void page_remove_rmap(struct page *page)
+void page_remove_rmap(struct page *page, struct vm_area_struct *vma)
{
if (atomic_add_negative(-1, &page->_mapcount)) {
if (unlikely(page_mapcount(page) < 0)) {
printk (KERN_EMERG "Eeek! page_mapcount(page) went negative! (%d)\n", page_mapcount(page));
+ printk (KERN_EMERG " page pfn = %lx\n", page_to_pfn(page));
printk (KERN_EMERG " page->flags = %lx\n", page->flags);
printk (KERN_EMERG " page->count = %x\n", page_count(page));
printk (KERN_EMERG " page->mapping = %p\n", page->mapping);
+ print_symbol (KERN_EMERG " vma->vm_ops = %s\n", (unsigned long)vma->vm_ops);
+ if (vma->vm_ops)
+ print_symbol (KERN_EMERG " vma->vm_ops->nopage = %s\n", (unsigned long)vma->vm_ops->nopage);
+ if (vma->vm_file && vma->vm_file->f_op)
+ print_symbol (KERN_EMERG " vma->vm_file->f_op->mmap = %s\n", (unsigned long)vma->vm_file->f_op->mmap);
BUG();
}
@@ -679,7 +689,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
dec_mm_counter(mm, file_rss);
- page_remove_rmap(page);
+ page_remove_rmap(page, vma);
page_cache_release(page);
out_unmap:
@@ -769,7 +779,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
if (pte_dirty(pteval))
set_page_dirty(page);
- page_remove_rmap(page);
+ page_remove_rmap(page, vma);
page_cache_release(page);
dec_mm_counter(mm, file_rss);
(*mapcount)--;
diff --git a/mm/shmem.c b/mm/shmem.c
index c820b4f77b8..70da7a0981b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -515,7 +515,12 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
size = SHMEM_NR_DIRECT;
nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size);
}
- if (!topdir)
+
+ /*
+ * If there are no indirect blocks or we are punching a hole
+ * below indirect blocks, nothing to be done.
+ */
+ if (!topdir || (punch_hole && (limit <= SHMEM_NR_DIRECT)))
goto done2;
BUG_ON(limit <= SHMEM_NR_DIRECT);
@@ -1225,7 +1230,7 @@ failed:
struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
{
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
struct page *page = NULL;
unsigned long idx;
int error;
@@ -1248,7 +1253,7 @@ static int shmem_populate(struct vm_area_struct *vma,
unsigned long addr, unsigned long len,
pgprot_t prot, unsigned long pgoff, int nonblock)
{
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
+ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
struct mm_struct *mm = vma->vm_mm;
enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
unsigned long size;
@@ -1293,14 +1298,14 @@ static int shmem_populate(struct vm_area_struct *vma,
#ifdef CONFIG_NUMA
int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
{
- struct inode *i = vma->vm_file->f_dentry->d_inode;
+ struct inode *i = vma->vm_file->f_path.dentry->d_inode;
return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
}
struct mempolicy *
shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
{
- struct inode *i = vma->vm_file->f_dentry->d_inode;
+ struct inode *i = vma->vm_file->f_path.dentry->d_inode;
unsigned long idx;
idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
@@ -1310,7 +1315,7 @@ shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
int shmem_lock(struct file *file, int lock, struct user_struct *user)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct shmem_inode_info *info = SHMEM_I(inode);
int retval = -ENOMEM;
@@ -1422,7 +1427,7 @@ shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsig
static ssize_t
shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
loff_t pos;
unsigned long written;
ssize_t err;
@@ -1442,7 +1447,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
if (err || !count)
goto out;
- err = remove_suid(file->f_dentry);
+ err = remove_suid(file->f_path.dentry);
if (err)
goto out;
@@ -1524,7 +1529,7 @@ out:
static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
unsigned long index, offset;
@@ -2493,8 +2498,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
d_instantiate(dentry, inode);
inode->i_size = size;
inode->i_nlink = 0; /* It is unlinked */
- file->f_vfsmnt = mntget(shm_mnt);
- file->f_dentry = dentry;
+ file->f_path.mnt = mntget(shm_mnt);
+ file->f_path.dentry = dentry;
file->f_mapping = inode->i_mapping;
file->f_op = &shmem_file_operations;
file->f_mode = FMODE_WRITE | FMODE_READ;
diff --git a/mm/slab.c b/mm/slab.c
index 068cb4503c1..c6100628a6e 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -107,7 +107,9 @@
#include <linux/nodemask.h>
#include <linux/mempolicy.h>
#include <linux/mutex.h>
+#include <linux/fault-inject.h>
#include <linux/rtmutex.h>
+#include <linux/reciprocal_div.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -385,6 +387,7 @@ struct kmem_cache {
unsigned int shared;
unsigned int buffer_size;
+ u32 reciprocal_buffer_size;
/* 3) touched by every alloc & free from the backend */
struct kmem_list3 *nodelists[MAX_NUMNODES];
@@ -626,10 +629,17 @@ static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab,
return slab->s_mem + cache->buffer_size * idx;
}
-static inline unsigned int obj_to_index(struct kmem_cache *cache,
- struct slab *slab, void *obj)
+/*
+ * We want to avoid an expensive divide : (offset / cache->buffer_size)
+ * Using the fact that buffer_size is a constant for a particular cache,
+ * we can replace (offset / cache->buffer_size) by
+ * reciprocal_divide(offset, cache->reciprocal_buffer_size)
+ */
+static inline unsigned int obj_to_index(const struct kmem_cache *cache,
+ const struct slab *slab, void *obj)
{
- return (unsigned)(obj - slab->s_mem) / cache->buffer_size;
+ u32 offset = (obj - slab->s_mem);
+ return reciprocal_divide(offset, cache->reciprocal_buffer_size);
}
/*
@@ -945,7 +955,8 @@ static void __devinit start_cpu_timer(int cpu)
if (keventd_up() && reap_work->work.func == NULL) {
init_reap_node(cpu);
INIT_DELAYED_WORK(reap_work, cache_reap);
- schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
+ schedule_delayed_work_on(cpu, reap_work,
+ __round_jiffies_relative(HZ, cpu));
}
}
@@ -1425,6 +1436,8 @@ void __init kmem_cache_init(void)
cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
cache_line_size());
+ cache_cache.reciprocal_buffer_size =
+ reciprocal_value(cache_cache.buffer_size);
for (order = 0; order < MAX_ORDER; order++) {
cache_estimate(order, cache_cache.buffer_size,
@@ -2311,6 +2324,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
if (flags & SLAB_CACHE_DMA)
cachep->gfpflags |= GFP_DMA;
cachep->buffer_size = size;
+ cachep->reciprocal_buffer_size = reciprocal_value(size);
if (flags & CFLGS_OFF_SLAB) {
cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
@@ -3088,12 +3102,89 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
#define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
#endif
+#ifdef CONFIG_FAILSLAB
+
+static struct failslab_attr {
+
+ struct fault_attr attr;
+
+ u32 ignore_gfp_wait;
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+ struct dentry *ignore_gfp_wait_file;
+#endif
+
+} failslab = {
+ .attr = FAULT_ATTR_INITIALIZER,
+ .ignore_gfp_wait = 1,
+};
+
+static int __init setup_failslab(char *str)
+{
+ return setup_fault_attr(&failslab.attr, str);
+}
+__setup("failslab=", setup_failslab);
+
+static int should_failslab(struct kmem_cache *cachep, gfp_t flags)
+{
+ if (cachep == &cache_cache)
+ return 0;
+ if (flags & __GFP_NOFAIL)
+ return 0;
+ if (failslab.ignore_gfp_wait && (flags & __GFP_WAIT))
+ return 0;
+
+ return should_fail(&failslab.attr, obj_size(cachep));
+}
+
+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+
+static int __init failslab_debugfs(void)
+{
+ mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+ struct dentry *dir;
+ int err;
+
+ err = init_fault_attr_dentries(&failslab.attr, "failslab");
+ if (err)
+ return err;
+ dir = failslab.attr.dentries.dir;
+
+ failslab.ignore_gfp_wait_file =
+ debugfs_create_bool("ignore-gfp-wait", mode, dir,
+ &failslab.ignore_gfp_wait);
+
+ if (!failslab.ignore_gfp_wait_file) {
+ err = -ENOMEM;
+ debugfs_remove(failslab.ignore_gfp_wait_file);
+ cleanup_fault_attr_dentries(&failslab.attr);
+ }
+
+ return err;
+}
+
+late_initcall(failslab_debugfs);
+
+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+
+#else /* CONFIG_FAILSLAB */
+
+static inline int should_failslab(struct kmem_cache *cachep, gfp_t flags)
+{
+ return 0;
+}
+
+#endif /* CONFIG_FAILSLAB */
+
static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
{
void *objp;
struct array_cache *ac;
check_irq_off();
+
+ if (should_failslab(cachep, flags))
+ return NULL;
+
ac = cpu_cache_get(cachep);
if (likely(ac->avail)) {
STATS_INC_ALLOCHIT(cachep);
@@ -3173,6 +3264,7 @@ void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
struct zone **z;
void *obj = NULL;
int nid;
+ gfp_t local_flags = (flags & GFP_LEVEL_MASK);
retry:
/*
@@ -3182,21 +3274,26 @@ retry:
for (z = zonelist->zones; *z && !obj; z++) {
nid = zone_to_nid(*z);
- if (cpuset_zone_allowed(*z, flags) &&
+ if (cpuset_zone_allowed_hardwall(*z, flags) &&
cache->nodelists[nid] &&
cache->nodelists[nid]->free_objects)
obj = ____cache_alloc_node(cache,
flags | GFP_THISNODE, nid);
}
- if (!obj) {
+ if (!obj && !(flags & __GFP_NO_GROW)) {
/*
* This allocation will be performed within the constraints
* of the current cpuset / memory policy requirements.
* We may trigger various forms of reclaim on the allowed
* set and go into memory reserves if necessary.
*/
+ if (local_flags & __GFP_WAIT)
+ local_irq_enable();
+ kmem_flagcheck(cache, flags);
obj = kmem_getpages(cache, flags, -1);
+ if (local_flags & __GFP_WAIT)
+ local_irq_disable();
if (obj) {
/*
* Insert into the appropriate per node queues
@@ -3213,7 +3310,7 @@ retry:
*/
goto retry;
} else {
- kmem_freepages(cache, obj);
+ /* cache_grow already freed obj */
obj = NULL;
}
}
@@ -3456,7 +3553,7 @@ EXPORT_SYMBOL(kmem_cache_zalloc);
*
* Currently only used for dentry validation.
*/
-int fastcall kmem_ptr_validate(struct kmem_cache *cachep, void *ptr)
+int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr)
{
unsigned long addr = (unsigned long)ptr;
unsigned long min_addr = PAGE_OFFSET;
@@ -3490,6 +3587,7 @@ out:
* @cachep: The cache to allocate from.
* @flags: See kmalloc().
* @nodeid: node number of the target node.
+ * @caller: return address of caller, used for debug information
*
* Identical to kmem_cache_alloc but it will allocate memory on the given
* node, which can improve the performance for cpu bound structures.
@@ -3928,7 +4026,7 @@ static void cache_reap(struct work_struct *unused)
if (!mutex_trylock(&cache_chain_mutex)) {
/* Give up. Setup the next iteration. */
schedule_delayed_work(&__get_cpu_var(reap_work),
- REAPTIMEOUT_CPUC);
+ round_jiffies_relative(REAPTIMEOUT_CPUC));
return;
}
@@ -3974,7 +4072,8 @@ next:
next_reap_node();
refresh_cpu_vm_stats(smp_processor_id());
/* Set up the next iteration */
- schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
+ schedule_delayed_work(&__get_cpu_var(reap_work),
+ round_jiffies_relative(REAPTIMEOUT_CPUC));
}
#ifdef CONFIG_PROC_FS
diff --git a/mm/slob.c b/mm/slob.c
index 542394184a5..5adc29cb58d 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -60,6 +60,8 @@ static DEFINE_SPINLOCK(slob_lock);
static DEFINE_SPINLOCK(block_lock);
static void slob_free(void *b, int size);
+static void slob_timer_cbk(void);
+
static void *slob_alloc(size_t size, gfp_t gfp, int align)
{
@@ -157,7 +159,7 @@ static int fastcall find_order(int size)
return order;
}
-void *kmalloc(size_t size, gfp_t gfp)
+void *__kmalloc(size_t size, gfp_t gfp)
{
slob_t *m;
bigblock_t *bb;
@@ -186,8 +188,7 @@ void *kmalloc(size_t size, gfp_t gfp)
slob_free(bb, sizeof(bigblock_t));
return 0;
}
-
-EXPORT_SYMBOL(kmalloc);
+EXPORT_SYMBOL(__kmalloc);
void kfree(const void *block)
{
@@ -327,9 +328,25 @@ const char *kmem_cache_name(struct kmem_cache *c)
EXPORT_SYMBOL(kmem_cache_name);
static struct timer_list slob_timer = TIMER_INITIALIZER(
- (void (*)(unsigned long))kmem_cache_init, 0, 0);
+ (void (*)(unsigned long))slob_timer_cbk, 0, 0);
+
+int kmem_cache_shrink(struct kmem_cache *d)
+{
+ return 0;
+}
+EXPORT_SYMBOL(kmem_cache_shrink);
+
+int kmem_ptr_validate(struct kmem_cache *a, const void *b)
+{
+ return 0;
+}
+
+void __init kmem_cache_init(void)
+{
+ slob_timer_cbk();
+}
-void kmem_cache_init(void)
+static void slob_timer_cbk(void)
{
void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index c5431072f42..a2d9bb4e80d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -434,7 +434,7 @@ void free_swap_and_cache(swp_entry_t entry)
*
* This is needed for the suspend to disk (aka swsusp).
*/
-int swap_type_of(dev_t device, sector_t offset)
+int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
{
struct block_device *bdev = NULL;
int i;
@@ -450,6 +450,9 @@ int swap_type_of(dev_t device, sector_t offset)
continue;
if (!bdev) {
+ if (bdev_p)
+ *bdev_p = sis->bdev;
+
spin_unlock(&swap_lock);
return i;
}
@@ -459,6 +462,9 @@ int swap_type_of(dev_t device, sector_t offset)
se = list_entry(sis->extent_list.next,
struct swap_extent, list);
if (se->start_block == offset) {
+ if (bdev_p)
+ *bdev_p = sis->bdev;
+
spin_unlock(&swap_lock);
bdput(bdev);
return i;
@@ -1357,10 +1363,10 @@ static int swap_show(struct seq_file *swap, void *v)
}
file = ptr->swap_file;
- len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\");
+ len = seq_path(swap, file->f_path.mnt, file->f_path.dentry, " \t\n\\");
seq_printf(swap, "%*s%s\t%u\t%u\t%d\n",
len < 40 ? 40 - len : 1, " ",
- S_ISBLK(file->f_dentry->d_inode->i_mode) ?
+ S_ISBLK(file->f_path.dentry->d_inode->i_mode) ?
"partition" : "file\t",
ptr->pages << (PAGE_SHIFT - 10),
ptr->inuse_pages << (PAGE_SHIFT - 10),
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
index 5f2cbf0f153..c7f6e1914bc 100644
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -79,8 +79,8 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
d_instantiate(dentry, inode);
inode->i_nlink = 0; /* It is unlinked */
- file->f_vfsmnt = mntget(shm_mnt);
- file->f_dentry = dentry;
+ file->f_path.mnt = mntget(shm_mnt);
+ file->f_path.dentry = dentry;
file->f_mapping = inode->i_mapping;
file->f_op = &ramfs_file_operations;
file->f_mode = FMODE_WRITE | FMODE_READ;
diff --git a/mm/truncate.c b/mm/truncate.c
index e07b1e682c3..5df947de765 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/pagevec.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/buffer_head.h> /* grr. try_to_release_page,
do_invalidatepage */
@@ -51,6 +52,33 @@ static inline void truncate_partial_page(struct page *page, unsigned partial)
}
/*
+ * This cancels just the dirty bit on the kernel page itself, it
+ * does NOT actually remove dirty bits on any mmap's that may be
+ * around. It also leaves the page tagged dirty, so any sync
+ * activity will still find it on the dirty lists, and in particular,
+ * clear_page_dirty_for_io() will still look at the dirty bits in
+ * the VM.
+ *
+ * Doing this should *normally* only ever be done when a page
+ * is truncated, and is not actually mapped anywhere at all. However,
+ * fs/buffer.c does this when it notices that somebody has cleaned
+ * out all the buffers on a page without actually doing it through
+ * the VM. Can you say "ext3 is horribly ugly"? Tought you could.
+ */
+void cancel_dirty_page(struct page *page, unsigned int account_size)
+{
+ if (TestClearPageDirty(page)) {
+ struct address_space *mapping = page->mapping;
+ if (mapping && mapping_cap_account_dirty(mapping)) {
+ dec_zone_page_state(page, NR_FILE_DIRTY);
+ if (account_size)
+ task_io_account_cancelled_write(account_size);
+ }
+ }
+}
+EXPORT_SYMBOL(cancel_dirty_page);
+
+/*
* If truncate cannot remove the fs-private metadata from the page, the page
* becomes anonymous. It will be left on the LRU and may even be mapped into
* user pagetables if we're racing with filemap_nopage().
@@ -66,10 +94,11 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
if (page->mapping != mapping)
return;
+ cancel_dirty_page(page, PAGE_CACHE_SIZE);
+
if (PagePrivate(page))
do_invalidatepage(page, 0);
- clear_page_dirty(page);
ClearPageUptodate(page);
ClearPageMappedToDisk(page);
remove_from_page_cache(page);
@@ -319,6 +348,15 @@ failed:
return 0;
}
+static int do_launder_page(struct address_space *mapping, struct page *page)
+{
+ if (!PageDirty(page))
+ return 0;
+ if (page->mapping != mapping || mapping->a_ops->launder_page == NULL)
+ return 0;
+ return mapping->a_ops->launder_page(page);
+}
+
/**
* invalidate_inode_pages2_range - remove range of pages from an address_space
* @mapping: the address_space
@@ -348,7 +386,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
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) {
@@ -384,18 +421,14 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
PAGE_CACHE_SIZE, 0);
}
}
- was_dirty = test_clear_page_dirty(page);
- if (!invalidate_complete_page2(mapping, page)) {
- if (was_dirty)
- set_page_dirty(page);
+ ret = do_launder_page(mapping, page);
+ if (ret == 0 && !invalidate_complete_page2(mapping, page))
ret = -EIO;
- }
unlock_page(page);
}
pagevec_release(&pvec);
cond_resched();
}
- WARN_ON_ONCE(ret);
return ret;
}
EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 093f5fe6dd7..7430df68cb6 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -692,7 +692,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
__count_vm_events(KSWAPD_STEAL, nr_freed);
} else
__count_zone_vm_events(PGSCAN_DIRECT, zone, nr_scan);
- __count_vm_events(PGACTIVATE, nr_freed);
+ __count_zone_vm_events(PGSTEAL, zone, nr_freed);
if (nr_taken == 0)
goto done;
@@ -984,7 +984,7 @@ static unsigned long shrink_zones(int priority, struct zone **zones,
if (!populated_zone(zone))
continue;
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
note_zone_scanning_priority(zone, priority);
@@ -1034,7 +1034,7 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
for (i = 0; zones[i] != NULL; i++) {
struct zone *zone = zones[i];
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
lru_pages += zone->nr_active + zone->nr_inactive;
@@ -1089,7 +1089,7 @@ out:
for (i = 0; zones[i] != 0; i++) {
struct zone *zone = zones[i];
- if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
zone->prev_priority = priority;
@@ -1354,7 +1354,7 @@ 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, __GFP_HARDWALL))
+ if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
return;
if (!waitqueue_active(&pgdat->kswapd_wait))
return;
@@ -1369,8 +1369,8 @@ void wakeup_kswapd(struct zone *zone, int order)
*
* For pass > 3 we also try to shrink the LRU lists that contain a few pages
*/
-static unsigned long shrink_all_zones(unsigned long nr_pages, int pass,
- int prio, struct scan_control *sc)
+static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
+ int pass, struct scan_control *sc)
{
struct zone *zone;
unsigned long nr_to_scan, ret = 0;
@@ -1406,6 +1406,16 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int pass,
return ret;
}
+static unsigned long count_lru_pages(void)
+{
+ struct zone *zone;
+ unsigned long ret = 0;
+
+ for_each_zone(zone)
+ ret += zone->nr_active + zone->nr_inactive;
+ return ret;
+}
+
/*
* Try to free `nr_pages' of memory, system-wide, and return the number of
* freed pages.
@@ -1420,7 +1430,6 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
unsigned long ret = 0;
int pass;
struct reclaim_state reclaim_state;
- struct zone *zone;
struct scan_control sc = {
.gfp_mask = GFP_KERNEL,
.may_swap = 0,
@@ -1431,10 +1440,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
current->reclaim_state = &reclaim_state;
- lru_pages = 0;
- for_each_zone(zone)
- lru_pages += zone->nr_active + zone->nr_inactive;
-
+ lru_pages = count_lru_pages();
nr_slab = global_page_state(NR_SLAB_RECLAIMABLE);
/* If slab caches are huge, it's better to hit them first */
while (nr_slab >= lru_pages) {
@@ -1461,13 +1467,6 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
for (pass = 0; pass < 5; pass++) {
int prio;
- /* Needed for shrinking slab caches later on */
- if (!lru_pages)
- for_each_zone(zone) {
- lru_pages += zone->nr_active;
- lru_pages += zone->nr_inactive;
- }
-
/* Force reclaiming mapped pages in the passes #3 and #4 */
if (pass > 2) {
sc.may_swap = 1;
@@ -1483,7 +1482,8 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
goto out;
reclaim_state.reclaimed_slab = 0;
- shrink_slab(sc.nr_scanned, sc.gfp_mask, lru_pages);
+ shrink_slab(sc.nr_scanned, sc.gfp_mask,
+ count_lru_pages());
ret += reclaim_state.reclaimed_slab;
if (ret >= nr_pages)
goto out;
@@ -1491,20 +1491,19 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
if (sc.nr_scanned && prio < DEF_PRIORITY - 2)
congestion_wait(WRITE, HZ / 10);
}
-
- lru_pages = 0;
}
/*
* If ret = 0, we could not shrink LRUs, but there may be something
* in slab caches
*/
- if (!ret)
+ if (!ret) {
do {
reclaim_state.reclaimed_slab = 0;
- shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
+ shrink_slab(nr_pages, sc.gfp_mask, count_lru_pages());
ret += reclaim_state.reclaimed_slab;
} while (ret < nr_pages && reclaim_state.reclaimed_slab > 0);
+ }
out:
current->reclaim_state = NULL;
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 91fe5f53ff1..739866bfe9e 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -393,7 +393,7 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
if (count == 0) return 0;
page = get_zeroed_page(GFP_KERNEL);
if (!page) return -ENOMEM;
- dev = PDE(file->f_dentry->d_inode)->data;
+ dev = PDE(file->f_path.dentry->d_inode)->data;
if (!dev->ops->proc_read)
length = -EINVAL;
else {
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 6cabf6d8a75..42233df2b09 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1088,8 +1088,8 @@ out:
/*
* FIXME: nonblock behaviour looks like it may have a bug.
*/
-static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags)
+static int __must_check ax25_connect(struct socket *sock,
+ struct sockaddr *uaddr, int addr_len, int flags)
{
struct sock *sk = sock->sk;
ax25_cb *ax25 = ax25_sk(sk), *ax25t;
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 5f0896ad004..97a49c79c60 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -29,17 +29,26 @@
#include <linux/interrupt.h>
/*
- * The null address is defined as a callsign of all spaces with an
- * SSID of zero.
+ * The default broadcast address of an interface is QST-0; the default address
+ * is LINUX-1. The null address is defined as a callsign of all spaces with
+ * an SSID of zero.
*/
-ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
+const ax25_address ax25_bcast =
+ {{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};
+const ax25_address ax25_defaddr =
+ {{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, 1 << 1}};
+const ax25_address null_ax25_address =
+ {{' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, ' ' << 1, 0 << 1}};
+
+EXPORT_SYMBOL_GPL(ax25_bcast);
+EXPORT_SYMBOL_GPL(ax25_defaddr);
EXPORT_SYMBOL(null_ax25_address);
/*
* ax25 -> ascii conversion
*/
-char *ax2asc(char *buf, ax25_address *a)
+char *ax2asc(char *buf, const ax25_address *a)
{
char c, *s;
int n;
@@ -72,9 +81,9 @@ EXPORT_SYMBOL(ax2asc);
/*
* ascii -> ax25 conversion
*/
-void asc2ax(ax25_address *addr, char *callsign)
+void asc2ax(ax25_address *addr, const char *callsign)
{
- char *s;
+ const char *s;
int n;
for (s = callsign, n = 0; n < 6; n++) {
@@ -107,7 +116,7 @@ EXPORT_SYMBOL(asc2ax);
/*
* Compare two ax.25 addresses
*/
-int ax25cmp(ax25_address *a, ax25_address *b)
+int ax25cmp(const ax25_address *a, const ax25_address *b)
{
int ct = 0;
@@ -128,7 +137,7 @@ EXPORT_SYMBOL(ax25cmp);
/*
* Compare two AX.25 digipeater paths.
*/
-int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2)
+int ax25digicmp(const ax25_digi *digi1, const ax25_digi *digi2)
{
int i;
@@ -149,7 +158,9 @@ int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2)
* Given an AX.25 address pull of to, from, digi list, command/response and the start of data
*
*/
-unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags, int *dama)
+const unsigned char *ax25_addr_parse(const unsigned char *buf, int len,
+ ax25_address *src, ax25_address *dest, ax25_digi *digi, int *flags,
+ int *dama)
{
int d = 0;
@@ -204,7 +215,8 @@ unsigned char *ax25_addr_parse(unsigned char *buf, int len, ax25_address *src, a
/*
* Assemble an AX.25 header from the bits
*/
-int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, ax25_digi *d, int flag, int modulus)
+int ax25_addr_build(unsigned char *buf, const ax25_address *src,
+ const ax25_address *dest, const ax25_digi *d, int flag, int modulus)
{
int len = 0;
int ct = 0;
@@ -261,7 +273,7 @@ int ax25_addr_build(unsigned char *buf, ax25_address *src, ax25_address *dest, a
return len;
}
-int ax25_addr_size(ax25_digi *dp)
+int ax25_addr_size(const ax25_digi *dp)
{
if (dp == NULL)
return 2 * AX25_ADDR_LEN;
@@ -272,7 +284,7 @@ int ax25_addr_size(ax25_digi *dp)
/*
* Reverse Digipeat List. May not pass both parameters as same struct
*/
-void ax25_digi_invert(ax25_digi *in, ax25_digi *out)
+void ax25_digi_invert(const ax25_digi *in, ax25_digi *out)
{
int ct;
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index 07ac0207eb6..aff3e652c2d 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -29,17 +29,10 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
-static struct protocol_struct {
- struct protocol_struct *next;
- unsigned int pid;
- int (*func)(struct sk_buff *, ax25_cb *);
-} *protocol_list = NULL;
+static struct ax25_protocol *protocol_list;
static DEFINE_RWLOCK(protocol_list_lock);
-static struct linkfail_struct {
- struct linkfail_struct *next;
- void (*func)(ax25_cb *, int);
-} *linkfail_list = NULL;
+static HLIST_HEAD(ax25_linkfail_list);
static DEFINE_SPINLOCK(linkfail_lock);
static struct listen_struct {
@@ -49,36 +42,23 @@ static struct listen_struct {
} *listen_list = NULL;
static DEFINE_SPINLOCK(listen_lock);
-int ax25_protocol_register(unsigned int pid,
- int (*func)(struct sk_buff *, ax25_cb *))
+/*
+ * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT,
+ * AX25_P_IP or AX25_P_ARP ...
+ */
+void ax25_register_pid(struct ax25_protocol *ap)
{
- struct protocol_struct *protocol;
-
- if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
- return 0;
-#ifdef CONFIG_INET
- if (pid == AX25_P_IP || pid == AX25_P_ARP)
- return 0;
-#endif
- if ((protocol = kmalloc(sizeof(*protocol), GFP_ATOMIC)) == NULL)
- return 0;
-
- protocol->pid = pid;
- protocol->func = func;
-
write_lock_bh(&protocol_list_lock);
- protocol->next = protocol_list;
- protocol_list = protocol;
+ ap->next = protocol_list;
+ protocol_list = ap;
write_unlock_bh(&protocol_list_lock);
-
- return 1;
}
-EXPORT_SYMBOL(ax25_protocol_register);
+EXPORT_SYMBOL_GPL(ax25_register_pid);
void ax25_protocol_release(unsigned int pid)
{
- struct protocol_struct *s, *protocol;
+ struct ax25_protocol *s, *protocol;
write_lock_bh(&protocol_list_lock);
protocol = protocol_list;
@@ -110,54 +90,19 @@ void ax25_protocol_release(unsigned int pid)
EXPORT_SYMBOL(ax25_protocol_release);
-int ax25_linkfail_register(void (*func)(ax25_cb *, int))
+void ax25_linkfail_register(struct ax25_linkfail *lf)
{
- struct linkfail_struct *linkfail;
-
- if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL)
- return 0;
-
- linkfail->func = func;
-
spin_lock_bh(&linkfail_lock);
- linkfail->next = linkfail_list;
- linkfail_list = linkfail;
+ hlist_add_head(&lf->lf_node, &ax25_linkfail_list);
spin_unlock_bh(&linkfail_lock);
-
- return 1;
}
EXPORT_SYMBOL(ax25_linkfail_register);
-void ax25_linkfail_release(void (*func)(ax25_cb *, int))
+void ax25_linkfail_release(struct ax25_linkfail *lf)
{
- struct linkfail_struct *s, *linkfail;
-
spin_lock_bh(&linkfail_lock);
- linkfail = linkfail_list;
- if (linkfail == NULL) {
- spin_unlock_bh(&linkfail_lock);
- return;
- }
-
- if (linkfail->func == func) {
- linkfail_list = linkfail->next;
- spin_unlock_bh(&linkfail_lock);
- kfree(linkfail);
- return;
- }
-
- while (linkfail != NULL && linkfail->next != NULL) {
- if (linkfail->next->func == func) {
- s = linkfail->next;
- linkfail->next = linkfail->next->next;
- spin_unlock_bh(&linkfail_lock);
- kfree(s);
- return;
- }
-
- linkfail = linkfail->next;
- }
+ hlist_del_init(&lf->lf_node);
spin_unlock_bh(&linkfail_lock);
}
@@ -171,7 +116,7 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
return 0;
if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL)
- return 0;
+ return -ENOMEM;
listen->callsign = *callsign;
listen->dev = dev;
@@ -181,7 +126,7 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
listen_list = listen;
spin_unlock_bh(&listen_lock);
- return 1;
+ return 0;
}
EXPORT_SYMBOL(ax25_listen_register);
@@ -223,7 +168,7 @@ EXPORT_SYMBOL(ax25_listen_release);
int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{
int (*res)(struct sk_buff *, ax25_cb *) = NULL;
- struct protocol_struct *protocol;
+ struct ax25_protocol *protocol;
read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
@@ -242,7 +187,8 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
spin_lock_bh(&listen_lock);
for (listen = listen_list; listen != NULL; listen = listen->next)
- if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL)) {
+ if (ax25cmp(&listen->callsign, callsign) == 0 &&
+ (listen->dev == dev || listen->dev == NULL)) {
spin_unlock_bh(&listen_lock);
return 1;
}
@@ -253,17 +199,18 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
void ax25_link_failed(ax25_cb *ax25, int reason)
{
- struct linkfail_struct *linkfail;
+ struct ax25_linkfail *lf;
+ struct hlist_node *node;
spin_lock_bh(&linkfail_lock);
- for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
- (linkfail->func)(ax25, reason);
+ hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node)
+ lf->func(ax25, reason);
spin_unlock_bh(&linkfail_lock);
}
int ax25_protocol_is_registered(unsigned int pid)
{
- struct protocol_struct *protocol;
+ struct ax25_protocol *protocol;
int res = 0;
read_lock_bh(&protocol_list_lock);
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 8580356ace5..0a0381622b1 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -71,7 +71,7 @@ void ax25_rt_device_down(struct net_device *dev)
write_unlock(&ax25_route_lock);
}
-static int ax25_rt_add(struct ax25_routes_struct *route)
+static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
{
ax25_route *ax25_rt;
ax25_dev *ax25_dev;
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index be04e9fb11f..ab166b48ce8 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
switch (CAPIMSG_SUBCOMMAND(skb->data)) {
case CAPI_CONF:
+ if (skb->len < CAPI_MSG_BASELEN + 10)
+ break;
+
func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_FUNCTION_GET_PROFILE:
+ if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
+ break;
+
controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
msgnum = CAPIMSG_MSGID(skb->data);
@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_FUNCTION_GET_MANUFACTURER:
+ if (skb->len < CAPI_MSG_BASELEN + 15)
+ break;
+
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
if (!info && ctrl) {
+ int len = min_t(uint, CAPI_MANUFACTURER_LEN,
+ skb->data[CAPI_MSG_BASELEN + 14]);
+
+ memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
strncpy(ctrl->manu,
- skb->data + CAPI_MSG_BASELEN + 15,
- skb->data[CAPI_MSG_BASELEN + 14]);
+ skb->data + CAPI_MSG_BASELEN + 15, len);
}
break;
case CAPI_FUNCTION_GET_VERSION:
+ if (skb->len < CAPI_MSG_BASELEN + 32)
+ break;
+
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
if (!info && ctrl) {
@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_FUNCTION_GET_SERIAL_NUMBER:
+ if (skb->len < CAPI_MSG_BASELEN + 17)
+ break;
+
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
if (!info && ctrl) {
+ int len = min_t(uint, CAPI_SERIAL_LEN,
+ skb->data[CAPI_MSG_BASELEN + 16]);
+
memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
strncpy(ctrl->serial,
- skb->data + CAPI_MSG_BASELEN + 17,
- skb->data[CAPI_MSG_BASELEN + 16]);
+ skb->data + CAPI_MSG_BASELEN + 17, len);
}
break;
@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_IND:
+ if (skb->len < CAPI_MSG_BASELEN + 6)
+ break;
+
func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
if (func == CAPI_FUNCTION_LOOPBACK) {
+ int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
+ skb->data[CAPI_MSG_BASELEN + 5]);
appl = CAPIMSG_APPID(skb->data);
msgnum = CAPIMSG_MSGID(skb->data);
cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
- skb->data + CAPI_MSG_BASELEN + 6,
- skb->data[CAPI_MSG_BASELEN + 5]);
+ skb->data + CAPI_MSG_BASELEN + 6, len);
}
break;
@@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
+ if (skb->len < CAPI_MSG_BASELEN)
+ return;
+
if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
cmtp_recv_interopmsg(session, skb);
return;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 711a085eca5..dbf98c49dba 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -123,10 +123,10 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (flt->opcode &&
((evt == HCI_EV_CMD_COMPLETE &&
flt->opcode !=
- get_unaligned((__u16 *)(skb->data + 3))) ||
+ get_unaligned((__le16 *)(skb->data + 3))) ||
(evt == HCI_EV_CMD_STATUS &&
flt->opcode !=
- get_unaligned((__u16 *)(skb->data + 4)))))
+ get_unaligned((__le16 *)(skb->data + 4)))))
continue;
}
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index d4c935692cc..801d687ea4e 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -242,7 +242,7 @@ static void add_conn(struct work_struct *work)
struct hci_conn *conn = container_of(work, struct hci_conn, work);
int i;
- if (device_register(&conn->dev) < 0) {
+ if (device_add(&conn->dev) < 0) {
BT_ERR("Failed to register connection device");
return;
}
@@ -272,6 +272,8 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
dev_set_drvdata(&conn->dev, conn);
+ device_initialize(&conn->dev);
+
INIT_WORK(&conn->work, add_conn);
schedule_work(&conn->work);
@@ -287,6 +289,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
{
BT_DBG("conn %p", conn);
+ if (!device_is_registered(&conn->dev))
+ return;
+
INIT_WORK(&conn->work, del_conn);
schedule_work(&conn->work);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 29a8fa4d372..f8c25d50015 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -585,6 +585,12 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
goto done;
}
+ if (la->l2_psm > 0 && btohs(la->l2_psm) < 0x1001 &&
+ !capable(CAP_NET_BIND_SERVICE)) {
+ err = -EACCES;
+ goto done;
+ }
+
write_lock_bh(&l2cap_sk_list.lock);
if (la->l2_psm && __l2cap_get_sock_by_addr(la->l2_psm, &la->l2_bdaddr)) {
@@ -2150,8 +2156,8 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n",
batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
- sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu,
- pi->omtu, pi->link_mode);
+ sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid,
+ pi->imtu, pi->omtu, pi->link_mode);
}
read_unlock_bh(&l2cap_sk_list.lock);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 544d65b7baa..cb7e855f082 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -557,7 +557,6 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct sock *sk = sock->sk;
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
struct sk_buff *skb;
- int err;
int sent = 0;
if (msg->msg_flags & MSG_OOB)
@@ -572,6 +571,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
while (len) {
size_t size = min_t(size_t, len, d->mtu);
+ int err;
skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
msg->msg_flags & MSG_DONTWAIT, &err);
@@ -582,13 +582,16 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err) {
kfree_skb(skb);
- sent = err;
+ if (sent == 0)
+ sent = err;
break;
}
err = rfcomm_dlc_send(d, skb);
if (err < 0) {
kfree_skb(skb);
+ if (sent == 0)
+ sent = err;
break;
}
@@ -598,7 +601,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
release_sock(sk);
- return sent ? sent : err;
+ return sent;
}
static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 1fb5d42f37a..eb2b52484c7 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -697,9 +697,13 @@ static int rfcomm_tty_write_room(struct tty_struct *tty)
BT_DBG("tty %p", tty);
+ if (!dev || !dev->dlc)
+ return 0;
+
room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
if (room < 0)
room = 0;
+
return room;
}
@@ -752,9 +756,9 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
return -ENOIOCTLCMD;
}
-static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old)
+static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
- struct termios *new = (struct termios *) tty->termios;
+ struct ktermios *new = tty->termios;
int old_baud_rate = tty_termios_baud_rate(old);
int new_baud_rate = tty_termios_baud_rate(new);
@@ -915,12 +919,14 @@ static void rfcomm_tty_unthrottle(struct tty_struct *tty)
static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
- struct rfcomm_dlc *dlc = dev->dlc;
BT_DBG("tty %p dev %p", tty, dev);
- if (!skb_queue_empty(&dlc->tx_queue))
- return dlc->mtu;
+ if (!dev || !dev->dlc)
+ return 0;
+
+ if (!skb_queue_empty(&dev->dlc->tx_queue))
+ return dev->dlc->mtu;
return 0;
}
@@ -928,11 +934,12 @@ static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
static void rfcomm_tty_flush_buffer(struct tty_struct *tty)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
- if (!dev)
- return;
BT_DBG("tty %p dev %p", tty, dev);
+ if (!dev || !dev->dlc)
+ return;
+
skb_queue_purge(&dev->dlc->tx_queue);
if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && tty->ldisc.write_wakeup)
@@ -952,11 +959,12 @@ static void rfcomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
static void rfcomm_tty_hangup(struct tty_struct *tty)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
- if (!dev)
- return;
BT_DBG("tty %p dev %p", tty, dev);
+ if (!dev)
+ return;
+
rfcomm_tty_flush_buffer(tty);
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index bd221ad52ea..ea3337ad0ed 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -61,9 +61,6 @@ static int brnf_filter_vlan_tagged __read_mostly = 1;
#define brnf_filter_vlan_tagged 1
#endif
-int brnf_deferred_hooks;
-EXPORT_SYMBOL_GPL(brnf_deferred_hooks);
-
static __be16 inline vlan_proto(const struct sk_buff *skb)
{
return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
@@ -685,110 +682,50 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
return NF_STOLEN;
}
-/* PF_BRIDGE/LOCAL_OUT ***********************************************/
-static int br_nf_local_out_finish(struct sk_buff *skb)
-{
- if (skb->protocol == htons(ETH_P_8021Q)) {
- skb_push(skb, VLAN_HLEN);
- skb->nh.raw -= VLAN_HLEN;
- }
-
- NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
- br_forward_finish, NF_BR_PRI_FIRST + 1);
-
- return 0;
-}
-
-/* This function sees both locally originated IP packets and forwarded
+/* PF_BRIDGE/LOCAL_OUT ***********************************************
+ *
+ * This function sees both locally originated IP packets and forwarded
* IP packets (in both cases the destination device is a bridge
* device). It also sees bridged-and-DNAT'ed packets.
- * To be able to filter on the physical bridge devices (with the physdev
- * module), we steal packets destined to a bridge device away from the
- * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
- * when we have determined the real output device. This is done in here.
*
* If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged
* and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
* will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority
* NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
* will be executed.
- * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched
- * this packet before, and so the packet was locally originated. We fake
- * the PF_INET/LOCAL_OUT hook.
- * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
- * so we fake the PF_INET/FORWARD hook. ip_sabotage_out() makes sure
- * even routed packets that didn't arrive on a bridge interface have their
- * nf_bridge->physindev set. */
+ */
static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct net_device *realindev, *realoutdev;
+ struct net_device *realindev;
struct sk_buff *skb = *pskb;
struct nf_bridge_info *nf_bridge;
- int pf;
if (!skb->nf_bridge)
return NF_ACCEPT;
- if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
- pf = PF_INET;
- else
- pf = PF_INET6;
-
nf_bridge = skb->nf_bridge;
- nf_bridge->physoutdev = skb->dev;
- realindev = nf_bridge->physindev;
+ if (!(nf_bridge->mask & BRNF_BRIDGED_DNAT))
+ return NF_ACCEPT;
/* Bridged, take PF_BRIDGE/FORWARD.
* (see big note in front of br_nf_pre_routing_finish) */
- if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
- if (nf_bridge->mask & BRNF_PKT_TYPE) {
- skb->pkt_type = PACKET_OTHERHOST;
- nf_bridge->mask ^= BRNF_PKT_TYPE;
- }
- if (skb->protocol == htons(ETH_P_8021Q)) {
- skb_push(skb, VLAN_HLEN);
- skb->nh.raw -= VLAN_HLEN;
- }
+ nf_bridge->physoutdev = skb->dev;
+ realindev = nf_bridge->physindev;
- NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
- skb->dev, br_forward_finish);
- goto out;
+ if (nf_bridge->mask & BRNF_PKT_TYPE) {
+ skb->pkt_type = PACKET_OTHERHOST;
+ nf_bridge->mask ^= BRNF_PKT_TYPE;
}
- realoutdev = bridge_parent(skb->dev);
- if (!realoutdev)
- return NF_DROP;
-
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- /* iptables should match -o br0.x */
- if (nf_bridge->netoutdev)
- realoutdev = nf_bridge->netoutdev;
-#endif
if (skb->protocol == htons(ETH_P_8021Q)) {
- skb_pull(skb, VLAN_HLEN);
- (*pskb)->nh.raw += VLAN_HLEN;
- }
- /* IP forwarded traffic has a physindev, locally
- * generated traffic hasn't. */
- if (realindev != NULL) {
- if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT)) {
- struct net_device *parent = bridge_parent(realindev);
- if (parent)
- realindev = parent;
- }
-
- NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
- realoutdev, br_nf_local_out_finish,
- NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
- } else {
- NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
- realoutdev, br_nf_local_out_finish,
- NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
+ skb_push(skb, VLAN_HLEN);
+ skb->nh.raw -= VLAN_HLEN;
}
-out:
+ NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
+ br_forward_finish);
return NF_STOLEN;
}
@@ -894,69 +831,6 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
return NF_ACCEPT;
}
-/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT
- * and PF_INET(6)/POST_ROUTING until we have done the forwarding
- * decision in the bridge code and have determined nf_bridge->physoutdev. */
-static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct sk_buff *skb = *pskb;
-
- if ((out->hard_start_xmit == br_dev_xmit &&
- okfn != br_nf_forward_finish &&
- okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- || ((out->priv_flags & IFF_802_1Q_VLAN) &&
- VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
-#endif
- ) {
- struct nf_bridge_info *nf_bridge;
-
- if (!skb->nf_bridge) {
-#ifdef CONFIG_SYSCTL
- /* This code is executed while in the IP(v6) stack,
- the version should be 4 or 6. We can't use
- skb->protocol because that isn't set on
- PF_INET(6)/LOCAL_OUT. */
- struct iphdr *ip = skb->nh.iph;
-
- if (ip->version == 4 && !brnf_call_iptables)
- return NF_ACCEPT;
- else if (ip->version == 6 && !brnf_call_ip6tables)
- return NF_ACCEPT;
- else if (!brnf_deferred_hooks)
- return NF_ACCEPT;
-#endif
- if (hook == NF_IP_POST_ROUTING)
- return NF_ACCEPT;
- if (!nf_bridge_alloc(skb))
- return NF_DROP;
- }
-
- nf_bridge = skb->nf_bridge;
-
- /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we
- * will need the indev then. For a brouter, the real indev
- * can be a bridge port, so we make sure br_nf_local_out()
- * doesn't use the bridge parent of the indev by using
- * the BRNF_DONT_TAKE_PARENT mask. */
- if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
- nf_bridge->mask |= BRNF_DONT_TAKE_PARENT;
- nf_bridge->physindev = (struct net_device *)in;
- }
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- /* the iptables outdev is br0.x, not br0 */
- if (out->priv_flags & IFF_802_1Q_VLAN)
- nf_bridge->netoutdev = (struct net_device *)out;
-#endif
- return NF_STOP;
- }
-
- return NF_ACCEPT;
-}
-
/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
* PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
@@ -1002,36 +876,6 @@ static struct nf_hook_ops br_nf_ops[] = {
.pf = PF_INET6,
.hooknum = NF_IP6_PRE_ROUTING,
.priority = NF_IP6_PRI_FIRST, },
- { .hook = ip_sabotage_out,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_FORWARD,
- .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
- { .hook = ip_sabotage_out,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_FORWARD,
- .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, },
- { .hook = ip_sabotage_out,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
- { .hook = ip_sabotage_out,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_LOCAL_OUT,
- .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
- { .hook = ip_sabotage_out,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_FIRST, },
- { .hook = ip_sabotage_out,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_IP6_POST_ROUTING,
- .priority = NF_IP6_PRI_FIRST, },
};
#ifdef CONFIG_SYSCTL
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index bee558a4180..6c84ccb8c9d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -610,7 +610,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
struct ebt_entry_target *t;
struct ebt_target *target;
unsigned int i, j, hook = 0, hookmask = 0;
- size_t gap = e->next_offset - e->target_offset;
+ size_t gap;
int ret;
/* don't mess with the struct ebt_entries */
@@ -660,6 +660,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
if (ret != 0)
goto cleanup_watchers;
t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
+ gap = e->next_offset - e->target_offset;
target = find_target_lock(t->u.name, &ret, &ebt_mutex);
if (!target)
goto cleanup_watchers;
diff --git a/net/core/flow.c b/net/core/flow.c
index d137f971f97..5d25697920b 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -231,22 +231,16 @@ nocache:
err = resolver(key, family, dir, &obj, &obj_ref);
- if (fle) {
- if (err) {
- /* Force security policy check on next lookup */
- *head = fle->next;
- flow_entry_kill(cpu, fle);
- } else {
- fle->genid = atomic_read(&flow_cache_genid);
-
- if (fle->object)
- atomic_dec(fle->object_ref);
-
- fle->object = obj;
- fle->object_ref = obj_ref;
- if (obj)
- atomic_inc(fle->object_ref);
- }
+ if (fle && !err) {
+ fle->genid = atomic_read(&flow_cache_genid);
+
+ if (fle->object)
+ atomic_dec(fle->object_ref);
+
+ fle->object = obj;
+ fle->object_ref = obj_ref;
+ if (obj)
+ atomic_inc(fle->object_ref);
}
local_bh_enable();
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0ab1987b934..e7300b6b407 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -577,9 +577,10 @@ void neigh_destroy(struct neighbour *neigh)
while ((hh = neigh->hh) != NULL) {
neigh->hh = hh->hh_next;
hh->hh_next = NULL;
- write_lock_bh(&hh->hh_lock);
+
+ write_seqlock_bh(&hh->hh_lock);
hh->hh_output = neigh_blackhole;
- write_unlock_bh(&hh->hh_lock);
+ write_sequnlock_bh(&hh->hh_lock);
if (atomic_dec_and_test(&hh->hh_refcnt))
kfree(hh);
}
@@ -897,9 +898,9 @@ static void neigh_update_hhs(struct neighbour *neigh)
if (update) {
for (hh = neigh->hh; hh; hh = hh->hh_next) {
- write_lock_bh(&hh->hh_lock);
+ write_seqlock_bh(&hh->hh_lock);
update(hh, neigh->dev, neigh->ha);
- write_unlock_bh(&hh->hh_lock);
+ write_sequnlock_bh(&hh->hh_lock);
}
}
}
@@ -1089,7 +1090,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
break;
if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
- rwlock_init(&hh->hh_lock);
+ seqlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
hh->hh_next = NULL;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index b3c559b9ac3..823215d8e90 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -55,6 +55,7 @@ static void queue_process(struct work_struct *work)
struct netpoll_info *npinfo =
container_of(work, struct netpoll_info, tx_work.work);
struct sk_buff *skb;
+ unsigned long flags;
while ((skb = skb_dequeue(&npinfo->txq))) {
struct net_device *dev = skb->dev;
@@ -64,15 +65,19 @@ static void queue_process(struct work_struct *work)
continue;
}
- netif_tx_lock_bh(dev);
+ local_irq_save(flags);
+ netif_tx_lock(dev);
if (netif_queue_stopped(dev) ||
dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
skb_queue_head(&npinfo->txq, skb);
- netif_tx_unlock_bh(dev);
+ netif_tx_unlock(dev);
+ local_irq_restore(flags);
schedule_delayed_work(&npinfo->tx_work, HZ/10);
return;
}
+ netif_tx_unlock(dev);
+ local_irq_restore(flags);
}
}
@@ -242,22 +247,28 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
/* don't get messages out of order, and no recursion */
if (skb_queue_len(&npinfo->txq) == 0 &&
- npinfo->poll_owner != smp_processor_id() &&
- netif_tx_trylock(dev)) {
- /* try until next clock tick */
- for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) {
- if (!netif_queue_stopped(dev))
- status = dev->hard_start_xmit(skb, dev);
+ npinfo->poll_owner != smp_processor_id()) {
+ unsigned long flags;
- if (status == NETDEV_TX_OK)
- break;
+ local_irq_save(flags);
+ if (netif_tx_trylock(dev)) {
+ /* try until next clock tick */
+ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+ tries > 0; --tries) {
+ if (!netif_queue_stopped(dev))
+ status = dev->hard_start_xmit(skb, dev);
- /* tickle device maybe there is some cleanup */
- netpoll_poll(np);
+ if (status == NETDEV_TX_OK)
+ break;
+
+ /* tickle device maybe there is some cleanup */
+ netpoll_poll(np);
- udelay(USEC_PER_POLL);
+ udelay(USEC_PER_POLL);
+ }
+ netif_tx_unlock(dev);
}
- netif_tx_unlock(dev);
+ local_irq_restore(flags);
}
if (status != NETDEV_TX_OK) {
@@ -330,6 +341,7 @@ static void arp_reply(struct sk_buff *skb)
unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
__be32 sip, tip;
+ unsigned char *sha;
struct sk_buff *send_skb;
struct netpoll *np = NULL;
@@ -356,9 +368,14 @@ static void arp_reply(struct sk_buff *skb)
arp->ar_op != htons(ARPOP_REQUEST))
return;
- arp_ptr = (unsigned char *)(arp+1) + skb->dev->addr_len;
+ arp_ptr = (unsigned char *)(arp+1);
+ /* save the location of the src hw addr */
+ sha = arp_ptr;
+ arp_ptr += skb->dev->addr_len;
memcpy(&sip, arp_ptr, 4);
- arp_ptr += 4 + skb->dev->addr_len;
+ arp_ptr += 4;
+ /* if we actually cared about dst hw addr, it would get copied here */
+ arp_ptr += skb->dev->addr_len;
memcpy(&tip, arp_ptr, 4);
/* Should we ignore arp? */
@@ -381,7 +398,7 @@ static void arp_reply(struct sk_buff *skb)
if (np->dev->hard_header &&
np->dev->hard_header(send_skb, skb->dev, ptype,
- np->remote_mac, np->local_mac,
+ sha, np->local_mac,
send_skb->len) < 0) {
kfree_skb(send_skb);
return;
@@ -405,7 +422,7 @@ static void arp_reply(struct sk_buff *skb)
arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &tip, 4);
arp_ptr += 4;
- memcpy(arp_ptr, np->remote_mac, np->dev->addr_len);
+ memcpy(arp_ptr, sha, np->dev->addr_len);
arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &sip, 4);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 1897a3a385d..04d4b93c68e 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -148,6 +148,7 @@
#include <linux/seq_file.h>
#include <linux/wait.h>
#include <linux/etherdevice.h>
+#include <linux/kthread.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
@@ -360,8 +361,7 @@ struct pktgen_thread {
spinlock_t if_lock;
struct list_head if_list; /* All device here */
struct list_head th_list;
- int removed;
- char name[32];
+ struct task_struct *tsk;
char result[512];
u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
@@ -1689,7 +1689,7 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
BUG_ON(!t);
seq_printf(seq, "Name: %s max_before_softirq: %d\n",
- t->name, t->max_before_softirq);
+ t->tsk->comm, t->max_before_softirq);
seq_printf(seq, "Running: ");
@@ -3112,7 +3112,7 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
{
/* Remove from the thread list */
- remove_proc_entry(t->name, pg_proc_dir);
+ remove_proc_entry(t->tsk->comm, pg_proc_dir);
mutex_lock(&pktgen_thread_lock);
@@ -3260,58 +3260,40 @@ out:;
* Main loop of the thread goes here
*/
-static void pktgen_thread_worker(struct pktgen_thread *t)
+static int pktgen_thread_worker(void *arg)
{
DEFINE_WAIT(wait);
+ struct pktgen_thread *t = arg;
struct pktgen_dev *pkt_dev = NULL;
int cpu = t->cpu;
- sigset_t tmpsig;
u32 max_before_softirq;
u32 tx_since_softirq = 0;
- daemonize("pktgen/%d", cpu);
-
- /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
-
- spin_lock_irq(&current->sighand->siglock);
- tmpsig = current->blocked;
- siginitsetinv(&current->blocked,
- sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGTERM));
-
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- /* Migrate to the right CPU */
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu)
- BUG();
+ BUG_ON(smp_processor_id() != cpu);
init_waitqueue_head(&t->queue);
- t->control &= ~(T_TERMINATE);
- t->control &= ~(T_RUN);
- t->control &= ~(T_STOP);
- t->control &= ~(T_REMDEVALL);
- t->control &= ~(T_REMDEV);
-
t->pid = current->pid;
PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid));
max_before_softirq = t->max_before_softirq;
- __set_current_state(TASK_INTERRUPTIBLE);
- mb();
+ set_current_state(TASK_INTERRUPTIBLE);
- while (1) {
-
- __set_current_state(TASK_RUNNING);
+ while (!kthread_should_stop()) {
+ pkt_dev = next_to_run(t);
- /*
- * Get next dev to xmit -- if any.
- */
+ if (!pkt_dev &&
+ (t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV))
+ == 0) {
+ prepare_to_wait(&(t->queue), &wait,
+ TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ / 10);
+ finish_wait(&(t->queue), &wait);
+ }
- pkt_dev = next_to_run(t);
+ __set_current_state(TASK_RUNNING);
if (pkt_dev) {
@@ -3329,21 +3311,8 @@ 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);
}
- /*
- * Back from sleep, either due to the timeout or signal.
- * We check if we have any "posted" work for us.
- */
-
- if (t->control & T_TERMINATE || signal_pending(current))
- /* we received a request to terminate ourself */
- break;
-
if (t->control & T_STOP) {
pktgen_stop(t);
t->control &= ~(T_STOP);
@@ -3364,20 +3333,19 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
t->control &= ~(T_REMDEV);
}
- if (need_resched())
- schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
}
- PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
+ PG_DEBUG(printk("pktgen: %s stopping all device\n", t->tsk->comm));
pktgen_stop(t);
- PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
+ PG_DEBUG(printk("pktgen: %s removing all device\n", t->tsk->comm));
pktgen_rem_all_ifs(t);
- PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
+ PG_DEBUG(printk("pktgen: %s removing thread.\n", t->tsk->comm));
pktgen_rem_thread(t);
- t->removed = 1;
+ return 0;
}
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
@@ -3495,37 +3463,11 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
return add_dev_to_thread(t, pkt_dev);
}
-static struct pktgen_thread *__init pktgen_find_thread(const char *name)
+static int __init pktgen_create_thread(int cpu)
{
struct pktgen_thread *t;
-
- mutex_lock(&pktgen_thread_lock);
-
- list_for_each_entry(t, &pktgen_threads, th_list)
- if (strcmp(t->name, name) == 0) {
- mutex_unlock(&pktgen_thread_lock);
- return t;
- }
-
- mutex_unlock(&pktgen_thread_lock);
- return NULL;
-}
-
-static int __init pktgen_create_thread(const char *name, int cpu)
-{
- int err;
- struct pktgen_thread *t = NULL;
struct proc_dir_entry *pe;
-
- if (strlen(name) > 31) {
- printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n");
- return -EINVAL;
- }
-
- if (pktgen_find_thread(name)) {
- printk("pktgen: ERROR: thread: %s already exists\n", name);
- return -EINVAL;
- }
+ struct task_struct *p;
t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
if (!t) {
@@ -3533,14 +3475,29 @@ static int __init pktgen_create_thread(const char *name, int cpu)
return -ENOMEM;
}
- strcpy(t->name, name);
spin_lock_init(&t->if_lock);
t->cpu = cpu;
- pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+ INIT_LIST_HEAD(&t->if_list);
+
+ list_add_tail(&t->th_list, &pktgen_threads);
+
+ p = kthread_create(pktgen_thread_worker, t, "kpktgend_%d", cpu);
+ if (IS_ERR(p)) {
+ printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
+ list_del(&t->th_list);
+ kfree(t);
+ return PTR_ERR(p);
+ }
+ kthread_bind(p, cpu);
+ t->tsk = p;
+
+ pe = create_proc_entry(t->tsk->comm, 0600, pg_proc_dir);
if (!pe) {
printk("pktgen: cannot create %s/%s procfs entry.\n",
- PG_PROC_DIR, t->name);
+ PG_PROC_DIR, t->tsk->comm);
+ kthread_stop(p);
+ list_del(&t->th_list);
kfree(t);
return -EINVAL;
}
@@ -3548,21 +3505,7 @@ static int __init pktgen_create_thread(const char *name, int cpu)
pe->proc_fops = &pktgen_thread_fops;
pe->data = t;
- INIT_LIST_HEAD(&t->if_list);
-
- list_add_tail(&t->th_list, &pktgen_threads);
-
- t->removed = 0;
-
- err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (err < 0) {
- printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
- remove_proc_entry(t->name, pg_proc_dir);
- list_del(&t->th_list);
- kfree(t);
- return err;
- }
+ wake_up_process(p);
return 0;
}
@@ -3643,10 +3586,8 @@ static int __init pg_init(void)
for_each_online_cpu(cpu) {
int err;
- char buf[30];
- sprintf(buf, "kpktgend_%i", cpu);
- err = pktgen_create_thread(buf, cpu);
+ err = pktgen_create_thread(cpu);
if (err)
printk("pktgen: WARNING: Cannot create thread for cpu %d (%d)\n",
cpu, err);
@@ -3674,9 +3615,8 @@ static void __exit pg_cleanup(void)
list_for_each_safe(q, n, &pktgen_threads) {
t = list_entry(q, struct pktgen_thread, th_list);
- t->control |= (T_TERMINATE);
-
- wait_event_interruptible_timeout(queue, (t->removed == 1), HZ);
+ kthread_stop(t->tsk);
+ kfree(t);
}
/* Un-register us from receiving netdevice events */
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 1f4727ddbdb..a086c6312d3 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -223,7 +223,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
gap = -new_head;
}
new_head += DCCP_MAX_ACKVEC_LEN;
- }
+ }
av->dccpav_buf_head = new_head;
@@ -336,7 +336,7 @@ out_duplicate:
void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
{
dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len,
- (unsigned long long)ackno);
+ (unsigned long long)ackno);
while (len--) {
const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index bcc2d12ae81..c65cb2453e4 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -43,8 +43,6 @@ struct ccid_operations {
unsigned char* value);
int (*ccid_hc_rx_insert_options)(struct sock *sk,
struct sk_buff *skb);
- int (*ccid_hc_tx_insert_options)(struct sock *sk,
- struct sk_buff *skb);
void (*ccid_hc_tx_packet_recv)(struct sock *sk,
struct sk_buff *skb);
int (*ccid_hc_tx_parse_options)(struct sock *sk,
@@ -146,14 +144,6 @@ static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
return rc;
}
-static inline int ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
- struct sk_buff *skb)
-{
- if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
- return ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb);
- return 0;
-}
-
static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
struct sk_buff *skb)
{
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 2555be8f479..fd38b05d6f7 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -351,7 +351,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
while (seqp != hctx->ccid2hctx_seqh) {
ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
- (unsigned long long)seqp->ccid2s_seq,
+ (unsigned long long)seqp->ccid2s_seq,
seqp->ccid2s_acked, seqp->ccid2s_sent);
seqp = seqp->ccid2s_next;
}
@@ -473,7 +473,7 @@ static inline void ccid2_new_ack(struct sock *sk,
/* first measurement */
if (hctx->ccid2hctx_srtt == -1) {
ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
- r, jiffies,
+ r, jiffies,
(unsigned long long)seqp->ccid2s_seq);
ccid2_change_srtt(hctx, r);
hctx->ccid2hctx_rttvar = r >> 1;
@@ -518,8 +518,8 @@ static inline void ccid2_new_ack(struct sock *sk,
hctx->ccid2hctx_lastrtt = jiffies;
ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
- hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
- hctx->ccid2hctx_rto, HZ, r);
+ hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
+ hctx->ccid2hctx_rto, HZ, r);
hctx->ccid2hctx_sent = 0;
}
@@ -667,9 +667,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
/* new packet received or marked */
if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
!seqp->ccid2s_acked) {
- if (state ==
+ if (state ==
DCCP_ACKVEC_STATE_ECN_MARKED) {
- ccid2_congestion_event(hctx,
+ ccid2_congestion_event(hctx,
seqp);
} else
ccid2_new_ack(sk, seqp,
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 66a27b9688c..40402c59506 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -41,27 +41,6 @@
#include "lib/tfrc.h"
#include "ccid3.h"
-/*
- * Reason for maths here is to avoid 32 bit overflow when a is big.
- * With this we get close to the limit.
- */
-static u32 usecs_div(const u32 a, const u32 b)
-{
- const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 :
- a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 :
- a < (UINT_MAX / (USEC_PER_SEC / 100)) ? 100 :
- a < (UINT_MAX / (USEC_PER_SEC / 500)) ? 500 :
- a < (UINT_MAX / (USEC_PER_SEC / 1000)) ? 1000 :
- a < (UINT_MAX / (USEC_PER_SEC / 5000)) ? 5000 :
- a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
- a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
- 100000;
- const u32 tmp = a * (USEC_PER_SEC / div);
- return (b >= 2 * div) ? tmp / (b / div) : tmp;
-}
-
-
-
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static int ccid3_debug;
#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a)
@@ -108,8 +87,9 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
{
timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
- /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
- hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x);
+ /* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
+ hctx->ccid3hctx_t_ipi = scaled_div(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_x >> 6);
/* Update nominal send time with regard to the new t_ipi */
timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
@@ -128,40 +108,44 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
* X = max(min(2 * X, 2 * X_recv), s / R);
* tld = now;
*
+ * Note: X and X_recv are both stored in units of 64 * bytes/second, to support
+ * fine-grained resolution of sending rates. This requires scaling by 2^6
+ * throughout the code. Only X_calc is unscaled (in bytes/second).
+ *
* If X has changed, we also update the scheduled send time t_now,
* the inter-packet interval t_ipi, and the delta value.
- */
+ */
static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
{
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
- const __u32 old_x = hctx->ccid3hctx_x;
+ const __u64 old_x = hctx->ccid3hctx_x;
if (hctx->ccid3hctx_p > 0) {
- hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
- hctx->ccid3hctx_rtt,
- hctx->ccid3hctx_p);
- hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc,
- hctx->ccid3hctx_x_recv * 2),
- hctx->ccid3hctx_s / TFRC_T_MBI);
-
- } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >=
- hctx->ccid3hctx_rtt) {
- hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv,
- hctx->ccid3hctx_x ) * 2,
- usecs_div(hctx->ccid3hctx_s,
- hctx->ccid3hctx_rtt) );
+
+ hctx->ccid3hctx_x = min(((__u64)hctx->ccid3hctx_x_calc) << 6,
+ hctx->ccid3hctx_x_recv * 2);
+ hctx->ccid3hctx_x = max(hctx->ccid3hctx_x,
+ (((__u64)hctx->ccid3hctx_s) << 6) /
+ TFRC_T_MBI);
+
+ } else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) -
+ (suseconds_t)hctx->ccid3hctx_rtt >= 0) {
+
+ hctx->ccid3hctx_x =
+ max(2 * min(hctx->ccid3hctx_x, hctx->ccid3hctx_x_recv),
+ scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
+ hctx->ccid3hctx_rtt));
hctx->ccid3hctx_t_ld = *now;
- } else
- ccid3_pr_debug("Not changing X\n");
+ }
if (hctx->ccid3hctx_x != old_x)
ccid3_update_send_time(hctx);
}
/*
- * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1)
- * @len: DCCP packet payload size in bytes
+ * Track the mean packet size `s' (cf. RFC 4342, 5.3 and RFC 3448, 4.1)
+ * @len: DCCP packet payload size in bytes
*/
static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
{
@@ -178,6 +162,33 @@ static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
*/
}
+/*
+ * Update Window Counter using the algorithm from [RFC 4342, 8.1].
+ * The algorithm is not applicable if RTT < 4 microseconds.
+ */
+static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
+ struct timeval *now)
+{
+ suseconds_t delta;
+ u32 quarter_rtts;
+
+ if (unlikely(hctx->ccid3hctx_rtt < 4)) /* avoid divide-by-zero */
+ return;
+
+ delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
+ DCCP_BUG_ON(delta < 0);
+
+ quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+
+ if (quarter_rtts > 0) {
+ hctx->ccid3hctx_t_last_win_count = *now;
+ hctx->ccid3hctx_last_win_count += min_t(u32, quarter_rtts, 5);
+ hctx->ccid3hctx_last_win_count &= 0xF; /* mod 16 */
+
+ ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
+ }
+}
+
static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
struct sock *sk = (struct sock *)data;
@@ -191,20 +202,20 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
goto restart_timer;
}
- ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
+ ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state));
-
+
switch (hctx->ccid3hctx_state) {
case TFRC_SSTATE_NO_FBACK:
/* RFC 3448, 4.4: Halve send rate directly */
- hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2,
- hctx->ccid3hctx_s / TFRC_T_MBI);
+ hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2,
+ (((__u64)hctx->ccid3hctx_s) << 6) /
+ TFRC_T_MBI);
- ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
- "bytes/s\n",
- dccp_role(sk), sk,
+ ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u "
+ "bytes/s\n", dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state),
- hctx->ccid3hctx_x);
+ (unsigned)(hctx->ccid3hctx_x >> 6));
/* The value of R is still undefined and so we can not recompute
* the timout value. Keep initial value as per [RFC 4342, 5]. */
t_nfb = TFRC_INITIAL_TIMEOUT;
@@ -213,34 +224,46 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
case TFRC_SSTATE_FBACK:
/*
* Check if IDLE since last timeout and recv rate is less than
- * 4 packets per RTT
+ * 4 packets (in units of 64*bytes/sec) per RTT
*/
if (!hctx->ccid3hctx_idle ||
- (hctx->ccid3hctx_x_recv >=
- 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
+ (hctx->ccid3hctx_x_recv >= 4 *
+ scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
+ hctx->ccid3hctx_rtt))) {
struct timeval now;
- ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
+ ccid3_pr_debug("%s(%p, state=%s), not idle\n",
dccp_role(sk), sk,
- ccid3_tx_state_name(hctx->ccid3hctx_state));
- /* Halve sending rate */
+ ccid3_tx_state_name(hctx->ccid3hctx_state));
- /* If (p == 0 || X_calc > 2 * X_recv)
+ /*
+ * Modify the cached value of X_recv [RFC 3448, 4.4]
+ *
+ * If (p == 0 || X_calc > 2 * X_recv)
* X_recv = max(X_recv / 2, s / (2 * t_mbi));
* Else
* X_recv = X_calc / 4;
+ *
+ * Note that X_recv is scaled by 2^6 while X_calc is not
*/
BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);
if (hctx->ccid3hctx_p == 0 ||
- hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
- hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
- hctx->ccid3hctx_s / (2 * TFRC_T_MBI));
- else
- hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
-
- /* Update sending rate */
- dccp_timestamp(sk, &now);
+ (hctx->ccid3hctx_x_calc >
+ (hctx->ccid3hctx_x_recv >> 5))) {
+
+ hctx->ccid3hctx_x_recv =
+ max(hctx->ccid3hctx_x_recv / 2,
+ (((__u64)hctx->ccid3hctx_s) << 6) /
+ (2 * TFRC_T_MBI));
+
+ if (hctx->ccid3hctx_p == 0)
+ dccp_timestamp(sk, &now);
+ } else {
+ hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;
+ hctx->ccid3hctx_x_recv <<= 4;
+ }
+ /* Now recalculate X [RFC 3448, 4.3, step (4)] */
ccid3_hc_tx_update_x(sk, &now);
}
/*
@@ -251,7 +274,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
break;
case TFRC_SSTATE_NO_SENT:
- DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk);
+ DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk);
/* fall through */
case TFRC_SSTATE_TERM:
goto out;
@@ -277,9 +300,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
- struct dccp_tx_hist_entry *new_packet;
struct timeval now;
- long delay;
+ suseconds_t delay;
BUG_ON(hctx == NULL);
@@ -291,34 +313,21 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
if (unlikely(skb->len == 0))
return -EBADMSG;
- /* See if last packet allocated was not sent */
- new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
- if (new_packet == NULL || new_packet->dccphtx_sent) {
- new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
- GFP_ATOMIC);
-
- if (unlikely(new_packet == NULL)) {
- DCCP_WARN("%s, sk=%p, not enough mem to add to history,"
- "send refused\n", dccp_role(sk), sk);
- return -ENOBUFS;
- }
-
- dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
- }
-
dccp_timestamp(sk, &now);
switch (hctx->ccid3hctx_state) {
case TFRC_SSTATE_NO_SENT:
sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
- jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
+ (jiffies +
+ usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
hctx->ccid3hctx_last_win_count = 0;
hctx->ccid3hctx_t_last_win_count = now;
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
- /* Set initial sending rate to 1 packet per second */
+ /* Set initial sending rate X/s to 1pps (X is scaled by 2^6) */
ccid3_hc_tx_update_s(hctx, skb->len);
- hctx->ccid3hctx_x = hctx->ccid3hctx_s;
+ hctx->ccid3hctx_x = hctx->ccid3hctx_s;
+ hctx->ccid3hctx_x <<= 6;
/* First timeout, according to [RFC 3448, 4.2], is 1 second */
hctx->ccid3hctx_t_ipi = USEC_PER_SEC;
@@ -332,77 +341,57 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
case TFRC_SSTATE_FBACK:
delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
/*
- * Scheduling of packet transmissions [RFC 3448, 4.6]
+ * Scheduling of packet transmissions [RFC 3448, 4.6]
*
* if (t_now > t_nom - delta)
* // send the packet now
* else
* // send the packet in (t_nom - t_now) milliseconds.
*/
- if (delay - (long)hctx->ccid3hctx_delta >= 0)
+ if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
return delay / 1000L;
+
+ ccid3_hc_tx_update_win_count(hctx, &now);
break;
case TFRC_SSTATE_TERM:
- DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+ DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
return -EINVAL;
}
/* prepare to send now (add options etc.) */
dp->dccps_hc_tx_insert_options = 1;
- new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval =
- hctx->ccid3hctx_last_win_count;
+ DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
+
+ /* set the nominal send time for the next following packet */
timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
return 0;
}
-static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
+static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
+ unsigned int len)
{
- const struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
struct timeval now;
- unsigned long quarter_rtt;
struct dccp_tx_hist_entry *packet;
BUG_ON(hctx == NULL);
- dccp_timestamp(sk, &now);
-
ccid3_hc_tx_update_s(hctx, len);
- packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
+ packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
if (unlikely(packet == NULL)) {
- DCCP_WARN("packet doesn't exist in history!\n");
- return;
- }
- if (unlikely(packet->dccphtx_sent)) {
- DCCP_WARN("no unsent packet in history!\n");
+ DCCP_CRIT("packet history - out of memory!");
return;
}
- packet->dccphtx_tstamp = now;
- packet->dccphtx_seqno = dp->dccps_gss;
- /*
- * Check if win_count have changed
- * Algorithm in "8.1. Window Counter Value" in RFC 4342.
- */
- quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
- if (likely(hctx->ccid3hctx_rtt > 8))
- quarter_rtt /= hctx->ccid3hctx_rtt / 4;
-
- if (quarter_rtt > 0) {
- hctx->ccid3hctx_t_last_win_count = now;
- hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count +
- min_t(unsigned long, quarter_rtt, 5)) % 16;
- ccid3_pr_debug("%s, sk=%p, window changed from "
- "%u to %u!\n",
- dccp_role(sk), sk,
- packet->dccphtx_ccval,
- hctx->ccid3hctx_last_win_count);
- }
+ dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);
- hctx->ccid3hctx_idle = 0;
- packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
- packet->dccphtx_sent = 1;
+ dccp_timestamp(sk, &now);
+ packet->dccphtx_tstamp = now;
+ packet->dccphtx_seqno = dccp_sk(sk)->dccps_gss;
+ packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
+ packet->dccphtx_sent = 1;
+ hctx->ccid3hctx_idle = 0;
}
static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -414,7 +403,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
struct timeval now;
unsigned long t_nfb;
u32 pinv;
- long r_sample, t_elapsed;
+ suseconds_t r_sample, t_elapsed;
BUG_ON(hctx == NULL);
@@ -430,44 +419,44 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
case TFRC_SSTATE_FBACK:
/* get packet from history to look up t_recvdata */
packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
- DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
if (unlikely(packet == NULL)) {
DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist "
"in history!\n", dccp_role(sk), sk,
(unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
- dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+ dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
return;
}
- /* Update receive rate */
+ /* Update receive rate in units of 64 * bytes/second */
hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;
+ hctx->ccid3hctx_x_recv <<= 6;
/* Update loss event rate */
pinv = opt_recv->ccid3or_loss_event_rate;
- if (pinv == ~0U || pinv == 0)
+ if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */
hctx->ccid3hctx_p = 0;
- else
- hctx->ccid3hctx_p = 1000000 / pinv;
+ else /* can not exceed 100% */
+ hctx->ccid3hctx_p = 1000000 / pinv;
dccp_timestamp(sk, &now);
/*
* Calculate new round trip sample as per [RFC 3448, 4.3] by
- * R_sample = (now - t_recvdata) - t_elapsed
+ * R_sample = (now - t_recvdata) - t_elapsed
*/
r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
- if (unlikely(r_sample <= 0)) {
- DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample);
- r_sample = 0;
- } else if (unlikely(r_sample <= t_elapsed))
- DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n",
- r_sample, t_elapsed);
+ DCCP_BUG_ON(r_sample < 0);
+ if (unlikely(r_sample <= t_elapsed))
+ DCCP_WARN("WARNING: r_sample=%dus <= t_elapsed=%dus\n",
+ (int)r_sample, (int)t_elapsed);
else
r_sample -= t_elapsed;
+ CCID3_RTT_SANITY_CHECK(r_sample);
- /* Update RTT estimate by
+ /* Update RTT estimate by
* If (No feedback recv)
* R = R_sample;
* Else
@@ -476,34 +465,45 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
* q is a constant, RFC 3448 recomments 0.9
*/
if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
- /* Use Larger Initial Windows [RFC 4342, sec. 5]
- * We deviate in that we use `s' instead of `MSS'. */
- u16 w_init = max( 4 * hctx->ccid3hctx_s,
- max(2 * hctx->ccid3hctx_s, 4380));
+ /*
+ * Larger Initial Windows [RFC 4342, sec. 5]
+ * We deviate in that we use `s' instead of `MSS'.
+ */
+ __u64 w_init = min(4 * hctx->ccid3hctx_s,
+ max(2 * hctx->ccid3hctx_s, 4380));
hctx->ccid3hctx_rtt = r_sample;
- hctx->ccid3hctx_x = usecs_div(w_init, r_sample);
+ hctx->ccid3hctx_x = scaled_div(w_init << 6, r_sample);
hctx->ccid3hctx_t_ld = now;
ccid3_update_send_time(hctx);
- ccid3_pr_debug("%s(%p), s=%u, w_init=%u, "
- "R_sample=%ldus, X=%u\n", dccp_role(sk),
- sk, hctx->ccid3hctx_s, w_init, r_sample,
- hctx->ccid3hctx_x);
+ ccid3_pr_debug("%s(%p), s=%u, w_init=%llu, "
+ "R_sample=%dus, X=%u\n", dccp_role(sk),
+ sk, hctx->ccid3hctx_s, w_init,
+ (int)r_sample,
+ (unsigned)(hctx->ccid3hctx_x >> 6));
ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
} else {
hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt +
- (u32)r_sample ) / 10;
-
+ (u32)r_sample) / 10;
+
+ /* Update sending rate (step 4 of [RFC 3448, 4.3]) */
+ if (hctx->ccid3hctx_p > 0)
+ hctx->ccid3hctx_x_calc =
+ tfrc_calc_x(hctx->ccid3hctx_s,
+ hctx->ccid3hctx_rtt,
+ hctx->ccid3hctx_p);
ccid3_hc_tx_update_x(sk, &now);
- ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, "
- "p=%u, X_calc=%u, X=%u\n", dccp_role(sk),
- sk, hctx->ccid3hctx_rtt, r_sample,
+ ccid3_pr_debug("%s(%p), RTT=%uus (sample=%dus), s=%u, "
+ "p=%u, X_calc=%u, X_recv=%u, X=%u\n",
+ dccp_role(sk),
+ sk, hctx->ccid3hctx_rtt, (int)r_sample,
hctx->ccid3hctx_s, hctx->ccid3hctx_p,
hctx->ccid3hctx_x_calc,
- hctx->ccid3hctx_x);
+ (unsigned)(hctx->ccid3hctx_x_recv >> 6),
+ (unsigned)(hctx->ccid3hctx_x >> 6));
}
/* unschedule no feedback timer */
@@ -513,57 +513,48 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
dccp_tx_hist_purge_older(ccid3_tx_hist,
&hctx->ccid3hctx_hist, packet);
/*
- * As we have calculated new ipi, delta, t_nom it is possible that
- * we now can send a packet, so wake up dccp_wait_for_ccid
+ * As we have calculated new ipi, delta, t_nom it is possible
+ * that we now can send a packet, so wake up dccp_wait_for_ccid
*/
sk->sk_write_space(sk);
/*
* Update timeout interval for the nofeedback timer.
* We use a configuration option to increase the lower bound.
- * This can help avoid triggering the nofeedback timer too often
- * ('spinning') on LANs with small RTTs.
+ * This can help avoid triggering the nofeedback timer too
+ * often ('spinning') on LANs with small RTTs.
*/
hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
CONFIG_IP_DCCP_CCID3_RTO *
- (USEC_PER_SEC/1000) );
+ (USEC_PER_SEC/1000));
/*
* Schedule no feedback timer to expire in
* max(t_RTO, 2 * s/X) = max(t_RTO, 2 * t_ipi)
*/
t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
-
- ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
+
+ ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "
"expire in %lu jiffies (%luus)\n",
- dccp_role(sk), sk,
- usecs_to_jiffies(t_nfb), t_nfb);
+ dccp_role(sk),
+ sk, usecs_to_jiffies(t_nfb), t_nfb);
- sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
+ sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
jiffies + usecs_to_jiffies(t_nfb));
/* set idle flag */
- hctx->ccid3hctx_idle = 1;
+ hctx->ccid3hctx_idle = 1;
break;
case TFRC_SSTATE_NO_SENT:
- if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT)
- DCCP_WARN("Illegal ACK received - no packet sent\n");
+ /*
+ * XXX when implementing bidirectional rx/tx check this again
+ */
+ DCCP_WARN("Illegal ACK received - no packet sent\n");
/* fall through */
case TFRC_SSTATE_TERM: /* ignore feedback when closing */
break;
}
}
-static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
-{
- const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-
- BUG_ON(hctx == NULL);
-
- if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
- DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
- return 0;
-}
-
static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
unsigned char len, u16 idx,
unsigned char *value)
@@ -588,13 +579,14 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
switch (option) {
case TFRC_OPT_LOSS_EVENT_RATE:
if (unlikely(len != 4)) {
- DCCP_WARN("%s, sk=%p, invalid len %d "
+ DCCP_WARN("%s(%p), invalid len %d "
"for TFRC_OPT_LOSS_EVENT_RATE\n",
dccp_role(sk), sk, len);
rc = -EINVAL;
} else {
- opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
- ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
+ opt_recv->ccid3or_loss_event_rate =
+ ntohl(*(__be32 *)value);
+ ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
dccp_role(sk), sk,
opt_recv->ccid3or_loss_event_rate);
}
@@ -602,20 +594,21 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
case TFRC_OPT_LOSS_INTERVALS:
opt_recv->ccid3or_loss_intervals_idx = idx;
opt_recv->ccid3or_loss_intervals_len = len;
- ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n",
+ ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
dccp_role(sk), sk,
opt_recv->ccid3or_loss_intervals_idx,
opt_recv->ccid3or_loss_intervals_len);
break;
case TFRC_OPT_RECEIVE_RATE:
if (unlikely(len != 4)) {
- DCCP_WARN("%s, sk=%p, invalid len %d "
+ DCCP_WARN("%s(%p), invalid len %d "
"for TFRC_OPT_RECEIVE_RATE\n",
dccp_role(sk), sk, len);
rc = -EINVAL;
} else {
- opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
- ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
+ opt_recv->ccid3or_receive_rate =
+ ntohl(*(__be32 *)value);
+ ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
dccp_role(sk), sk,
opt_recv->ccid3or_receive_rate);
}
@@ -630,10 +623,12 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
hctx->ccid3hctx_s = 0;
+ hctx->ccid3hctx_rtt = 0;
hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
- hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
+ hctx->ccid3hctx_no_feedback_timer.function =
+ ccid3_hc_tx_no_feedback_timer;
hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk;
init_timer(&hctx->ccid3hctx_no_feedback_timer);
@@ -698,8 +693,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
struct dccp_sock *dp = dccp_sk(sk);
struct dccp_rx_hist_entry *packet;
struct timeval now;
+ suseconds_t delta;
- ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+ ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
dccp_timestamp(sk, &now);
@@ -707,21 +703,21 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
case TFRC_RSTATE_NO_DATA:
hcrx->ccid3hcrx_x_recv = 0;
break;
- case TFRC_RSTATE_DATA: {
- const u32 delta = timeval_delta(&now,
- &hcrx->ccid3hcrx_tstamp_last_feedback);
- hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
- delta);
- }
+ case TFRC_RSTATE_DATA:
+ delta = timeval_delta(&now,
+ &hcrx->ccid3hcrx_tstamp_last_feedback);
+ DCCP_BUG_ON(delta < 0);
+ hcrx->ccid3hcrx_x_recv =
+ scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
break;
case TFRC_RSTATE_TERM:
- DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+ DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
return;
}
packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
if (unlikely(packet == NULL)) {
- DCCP_WARN("%s, sk=%p, no data packet in history!\n",
+ DCCP_WARN("%s(%p), no data packet in history!\n",
dccp_role(sk), sk);
return;
}
@@ -730,13 +726,19 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval;
hcrx->ccid3hcrx_bytes_recv = 0;
- /* Convert to multiples of 10us */
- hcrx->ccid3hcrx_elapsed_time =
- timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
+ /* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */
+ delta = timeval_delta(&now, &packet->dccphrx_tstamp);
+ DCCP_BUG_ON(delta < 0);
+ hcrx->ccid3hcrx_elapsed_time = delta / 10;
+
if (hcrx->ccid3hcrx_p == 0)
- hcrx->ccid3hcrx_pinv = ~0;
- else
+ hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */
+ else if (hcrx->ccid3hcrx_p > 1000000) {
+ DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p);
+ hcrx->ccid3hcrx_pinv = 1; /* use 100% in this case */
+ } else
hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
+
dp->dccps_hc_rx_insert_options = 1;
dccp_send_ack(sk);
}
@@ -764,9 +766,9 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
hcrx->ccid3hcrx_elapsed_time)) ||
dccp_insert_option_timestamp(sk, skb) ||
dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
- &pinv, sizeof(pinv)) ||
+ &pinv, sizeof(pinv)) ||
dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
- &x_recv, sizeof(x_recv)))
+ &x_recv, sizeof(x_recv)))
return -1;
return 0;
@@ -780,12 +782,13 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
- u32 rtt, delta, x_recv, fval, p, tmp2;
+ u32 x_recv, p;
+ suseconds_t rtt, delta;
struct timeval tstamp = { 0, };
int interval = 0;
int win_count = 0;
int step = 0;
- u64 tmp1;
+ u64 fval;
list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
dccphrx_node) {
@@ -810,13 +813,13 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
}
if (unlikely(step == 0)) {
- DCCP_WARN("%s, sk=%p, packet history has no data packets!\n",
+ DCCP_WARN("%s(%p), packet history has no data packets!\n",
dccp_role(sk), sk);
return ~0;
}
if (unlikely(interval == 0)) {
- DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0."
+ DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
"Defaulting to 1\n", dccp_role(sk), sk);
interval = 1;
}
@@ -825,41 +828,51 @@ found:
DCCP_CRIT("tail is null\n");
return ~0;
}
- rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
- ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
- dccp_role(sk), sk, rtt);
- if (rtt == 0) {
- DCCP_WARN("RTT==0, setting to 1\n");
- rtt = 1;
+ delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+ DCCP_BUG_ON(delta < 0);
+
+ rtt = delta * 4 / interval;
+ ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
+ dccp_role(sk), sk, (int)rtt);
+
+ /*
+ * Determine the length of the first loss interval via inverse lookup.
+ * Assume that X_recv can be computed by the throughput equation
+ * s
+ * X_recv = --------
+ * R * fval
+ * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
+ */
+ if (rtt == 0) { /* would result in divide-by-zero */
+ DCCP_WARN("RTT==0\n");
+ return ~0;
}
dccp_timestamp(sk, &tstamp);
delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
- x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
-
- if (x_recv == 0)
- x_recv = hcrx->ccid3hcrx_x_recv;
-
- tmp1 = (u64)x_recv * (u64)rtt;
- do_div(tmp1,10000000);
- tmp2 = (u32)tmp1;
-
- if (!tmp2) {
- DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt);
- return ~0;
+ DCCP_BUG_ON(delta <= 0);
+
+ x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
+ if (x_recv == 0) { /* would also trigger divide-by-zero */
+ DCCP_WARN("X_recv==0\n");
+ if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
+ DCCP_BUG("stored value of X_recv is zero");
+ return ~0;
+ }
}
- fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
- /* do not alter order above or you will get overflow on 32 bit */
+ fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
+ fval = scaled_div32(fval, x_recv);
p = tfrc_calc_x_reverse_lookup(fval);
- ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
+
+ ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
"loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
if (p == 0)
return ~0;
else
- return 1000000 / p;
+ return 1000000 / p;
}
static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
@@ -913,7 +926,8 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
struct dccp_rx_hist_entry *packet)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
+ struct dccp_rx_hist_entry *rx_hist =
+ dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
u64 seqno = packet->dccphrx_seqno;
u64 tmp_seqno;
int loss = 0;
@@ -941,7 +955,7 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
dccp_inc_seqno(&tmp_seqno);
while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
tmp_seqno, &ccval)) {
- hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+ hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
hcrx->ccid3hcrx_ccval_nonloss = ccval;
dccp_inc_seqno(&tmp_seqno);
}
@@ -967,7 +981,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
const struct dccp_options_received *opt_recv;
struct dccp_rx_hist_entry *packet;
struct timeval now;
- u32 p_prev, rtt_prev, r_sample, t_elapsed;
+ u32 p_prev, rtt_prev;
+ suseconds_t r_sample, t_elapsed;
int loss, payload_size;
BUG_ON(hcrx == NULL);
@@ -987,11 +1002,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
r_sample = timeval_usecs(&now);
t_elapsed = opt_recv->dccpor_elapsed_time * 10;
+ DCCP_BUG_ON(r_sample < 0);
if (unlikely(r_sample <= t_elapsed))
- DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n",
+ DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
r_sample, t_elapsed);
else
r_sample -= t_elapsed;
+ CCID3_RTT_SANITY_CHECK(r_sample);
if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
hcrx->ccid3hcrx_rtt = r_sample;
@@ -1000,8 +1017,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
r_sample / 10;
if (rtt_prev != hcrx->ccid3hcrx_rtt)
- ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
- dccp_role(sk), hcrx->ccid3hcrx_rtt,
+ ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",
+ dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
opt_recv->dccpor_elapsed_time);
break;
case DCCP_PKT_DATA:
@@ -1013,7 +1030,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
skb, GFP_ATOMIC);
if (unlikely(packet == NULL)) {
- DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet "
+ DCCP_WARN("%s(%p), Not enough mem to add rx packet "
"to history, consider it lost!\n", dccp_role(sk), sk);
return;
}
@@ -1028,9 +1045,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
switch (hcrx->ccid3hcrx_state) {
case TFRC_RSTATE_NO_DATA:
- ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
- "feedback\n",
- dccp_role(sk), sk,
+ ccid3_pr_debug("%s(%p, state=%s), skb=%p, sending initial "
+ "feedback\n", dccp_role(sk), sk,
dccp_state_name(sk->sk_state), skb);
ccid3_hc_rx_send_feedback(sk);
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
@@ -1041,19 +1057,19 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
break;
dccp_timestamp(sk, &now);
- if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
- hcrx->ccid3hcrx_rtt) {
+ if ((timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) -
+ (suseconds_t)hcrx->ccid3hcrx_rtt) >= 0) {
hcrx->ccid3hcrx_tstamp_last_ack = now;
ccid3_hc_rx_send_feedback(sk);
}
return;
case TFRC_RSTATE_TERM:
- DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
+ DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
return;
}
/* Dealing with packet loss */
- ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
+ ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",
dccp_role(sk), sk, dccp_state_name(sk->sk_state));
p_prev = hcrx->ccid3hcrx_p;
@@ -1078,7 +1094,7 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
- ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
+ ccid3_pr_debug("entry\n");
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
@@ -1086,7 +1102,7 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
hcrx->ccid3hcrx_s = 0;
- hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
+ hcrx->ccid3hcrx_rtt = 0;
return 0;
}
@@ -1115,9 +1131,9 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
BUG_ON(hcrx == NULL);
- info->tcpi_ca_state = hcrx->ccid3hcrx_state;
- info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
- info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;
+ info->tcpi_ca_state = hcrx->ccid3hcrx_state;
+ info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
+ info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;
}
static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1198,7 +1214,6 @@ static struct ccid_operations ccid3 = {
.ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
.ccid_hc_tx_packet_sent = ccid3_hc_tx_packet_sent,
.ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
- .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
.ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
.ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock),
.ccid_hc_rx_init = ccid3_hc_rx_init,
@@ -1210,7 +1225,7 @@ static struct ccid_operations ccid3 = {
.ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt,
.ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt,
};
-
+
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
@@ -1233,7 +1248,7 @@ static __init int ccid3_module_init(void)
goto out_free_tx;
rc = ccid_register(&ccid3);
- if (rc != 0)
+ if (rc != 0)
goto out_free_loss_interval_history;
out:
return rc;
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 07596d704ef..15776a88c09 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -51,6 +51,16 @@
/* Parameter t_mbi from [RFC 3448, 4.3]: backoff interval in seconds */
#define TFRC_T_MBI 64
+/* What we think is a reasonable upper limit on RTT values */
+#define CCID3_SANE_RTT_MAX ((suseconds_t)(4 * USEC_PER_SEC))
+
+#define CCID3_RTT_SANITY_CHECK(rtt) do { \
+ if (rtt > CCID3_SANE_RTT_MAX) { \
+ DCCP_CRIT("RTT (%d) too large, substituting %d", \
+ (int)rtt, (int)CCID3_SANE_RTT_MAX); \
+ rtt = CCID3_SANE_RTT_MAX; \
+ } } while (0)
+
enum ccid3_options {
TFRC_OPT_LOSS_EVENT_RATE = 192,
TFRC_OPT_LOSS_INTERVALS = 193,
@@ -67,7 +77,7 @@ struct ccid3_options_received {
/* TFRC sender states */
enum ccid3_hc_tx_states {
- TFRC_SSTATE_NO_SENT = 1,
+ TFRC_SSTATE_NO_SENT = 1,
TFRC_SSTATE_NO_FBACK,
TFRC_SSTATE_FBACK,
TFRC_SSTATE_TERM,
@@ -75,23 +85,23 @@ enum ccid3_hc_tx_states {
/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket
*
- * @ccid3hctx_x - Current sending rate
- * @ccid3hctx_x_recv - Receive rate
- * @ccid3hctx_x_calc - Calculated send rate (RFC 3448, 3.1)
+ * @ccid3hctx_x - Current sending rate in 64 * bytes per second
+ * @ccid3hctx_x_recv - Receive rate in 64 * bytes per second
+ * @ccid3hctx_x_calc - Calculated rate in bytes per second
* @ccid3hctx_rtt - Estimate of current round trip time in usecs
* @ccid3hctx_p - Current loss event rate (0-1) scaled by 1000000
- * @ccid3hctx_s - Packet size
- * @ccid3hctx_t_rto - Retransmission Timeout (RFC 3448, 3.1)
- * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6)
+ * @ccid3hctx_s - Packet size in bytes
+ * @ccid3hctx_t_rto - Nofeedback Timer setting in usecs
+ * @ccid3hctx_t_ipi - Interpacket (send) interval (RFC 3448, 4.6) in usecs
* @ccid3hctx_state - Sender state, one of %ccid3_hc_tx_states
* @ccid3hctx_last_win_count - Last window counter sent
* @ccid3hctx_t_last_win_count - Timestamp of earliest packet
- * with last_win_count value sent
+ * with last_win_count value sent
* @ccid3hctx_no_feedback_timer - Handle to no feedback timer
* @ccid3hctx_idle - Flag indicating that sender is idling
* @ccid3hctx_t_ld - Time last doubled during slow start
* @ccid3hctx_t_nom - Nominal send time of next packet
- * @ccid3hctx_delta - Send timer delta
+ * @ccid3hctx_delta - Send timer delta (RFC 3448, 4.6) in usecs
* @ccid3hctx_hist - Packet history
* @ccid3hctx_options_received - Parsed set of retrieved options
*/
@@ -105,7 +115,7 @@ struct ccid3_hc_tx_sock {
#define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto
#define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi
u16 ccid3hctx_s;
- enum ccid3_hc_tx_states ccid3hctx_state:8;
+ enum ccid3_hc_tx_states ccid3hctx_state:8;
u8 ccid3hctx_last_win_count;
u8 ccid3hctx_idle;
struct timeval ccid3hctx_t_last_win_count;
@@ -119,7 +129,7 @@ struct ccid3_hc_tx_sock {
/* TFRC receiver states */
enum ccid3_hc_rx_states {
- TFRC_RSTATE_NO_DATA = 1,
+ TFRC_RSTATE_NO_DATA = 1,
TFRC_RSTATE_DATA,
TFRC_RSTATE_TERM = 127,
};
@@ -147,18 +157,18 @@ struct ccid3_hc_rx_sock {
#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv
#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt
#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p
- u64 ccid3hcrx_seqno_nonloss:48,
+ u64 ccid3hcrx_seqno_nonloss:48,
ccid3hcrx_ccval_nonloss:4,
ccid3hcrx_ccval_last_counter:4;
enum ccid3_hc_rx_states ccid3hcrx_state:8;
- u32 ccid3hcrx_bytes_recv;
- struct timeval ccid3hcrx_tstamp_last_feedback;
- struct timeval ccid3hcrx_tstamp_last_ack;
+ u32 ccid3hcrx_bytes_recv;
+ struct timeval ccid3hcrx_tstamp_last_feedback;
+ struct timeval ccid3hcrx_tstamp_last_ack;
struct list_head ccid3hcrx_hist;
struct list_head ccid3hcrx_li_hist;
- u16 ccid3hcrx_s;
- u32 ccid3hcrx_pinv;
- u32 ccid3hcrx_elapsed_time;
+ u16 ccid3hcrx_s;
+ u32 ccid3hcrx_pinv;
+ u32 ccid3hcrx_elapsed_time;
};
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index b876c9c81c6..2e8ef42721e 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -36,9 +36,100 @@
#include <linux/module.h>
#include <linux/string.h>
-
#include "packet_history.h"
+/*
+ * Transmitter History Routines
+ */
+struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
+{
+ struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
+ static const char dccp_tx_hist_mask[] = "tx_hist_%s";
+ char *slab_name;
+
+ if (hist == NULL)
+ goto out;
+
+ slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
+ GFP_ATOMIC);
+ if (slab_name == NULL)
+ goto out_free_hist;
+
+ sprintf(slab_name, dccp_tx_hist_mask, name);
+ hist->dccptxh_slab = kmem_cache_create(slab_name,
+ sizeof(struct dccp_tx_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (hist->dccptxh_slab == NULL)
+ goto out_free_slab_name;
+out:
+ return hist;
+out_free_slab_name:
+ kfree(slab_name);
+out_free_hist:
+ kfree(hist);
+ hist = NULL;
+ goto out;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
+
+void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
+{
+ const char* name = kmem_cache_name(hist->dccptxh_slab);
+
+ kmem_cache_destroy(hist->dccptxh_slab);
+ kfree(name);
+ kfree(hist);
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
+
+struct dccp_tx_hist_entry *
+ dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
+{
+ struct dccp_tx_hist_entry *packet = NULL, *entry;
+
+ list_for_each_entry(entry, list, dccphtx_node)
+ if (entry->dccphtx_seqno == seq) {
+ packet = entry;
+ break;
+ }
+
+ return packet;
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
+
+void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
+{
+ struct dccp_tx_hist_entry *entry, *next;
+
+ list_for_each_entry_safe(entry, next, list, dccphtx_node) {
+ list_del_init(&entry->dccphtx_node);
+ dccp_tx_hist_entry_delete(hist, entry);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
+
+void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
+ struct list_head *list,
+ struct dccp_tx_hist_entry *packet)
+{
+ struct dccp_tx_hist_entry *next;
+
+ list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
+ list_del_init(&packet->dccphtx_node);
+ dccp_tx_hist_entry_delete(hist, packet);
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
+
+/*
+ * Receiver History Routines
+ */
struct dccp_rx_hist *dccp_rx_hist_new(const char *name)
{
struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
@@ -83,18 +174,24 @@ void dccp_rx_hist_delete(struct dccp_rx_hist *hist)
EXPORT_SYMBOL_GPL(dccp_rx_hist_delete);
-void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
+int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+ u8 *ccval)
{
- struct dccp_rx_hist_entry *entry, *next;
+ struct dccp_rx_hist_entry *packet = NULL, *entry;
- list_for_each_entry_safe(entry, next, list, dccphrx_node) {
- list_del_init(&entry->dccphrx_node);
- kmem_cache_free(hist->dccprxh_slab, entry);
- }
-}
+ list_for_each_entry(entry, list, dccphrx_node)
+ if (entry->dccphrx_seqno == seq) {
+ packet = entry;
+ break;
+ }
-EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
+ if (packet)
+ *ccval = packet->dccphrx_ccval;
+ return packet != NULL;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
struct dccp_rx_hist_entry *
dccp_rx_hist_find_data_packet(const struct list_head *list)
{
@@ -184,110 +281,18 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
-struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
-{
- struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
- static const char dccp_tx_hist_mask[] = "tx_hist_%s";
- char *slab_name;
-
- if (hist == NULL)
- goto out;
-
- slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
- GFP_ATOMIC);
- if (slab_name == NULL)
- goto out_free_hist;
-
- sprintf(slab_name, dccp_tx_hist_mask, name);
- hist->dccptxh_slab = kmem_cache_create(slab_name,
- sizeof(struct dccp_tx_hist_entry),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (hist->dccptxh_slab == NULL)
- goto out_free_slab_name;
-out:
- return hist;
-out_free_slab_name:
- kfree(slab_name);
-out_free_hist:
- kfree(hist);
- hist = NULL;
- goto out;
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
-
-void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
-{
- const char* name = kmem_cache_name(hist->dccptxh_slab);
-
- kmem_cache_destroy(hist->dccptxh_slab);
- kfree(name);
- kfree(hist);
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
-
-struct dccp_tx_hist_entry *
- dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq)
-{
- struct dccp_tx_hist_entry *packet = NULL, *entry;
-
- list_for_each_entry(entry, list, dccphtx_node)
- if (entry->dccphtx_seqno == seq) {
- packet = entry;
- break;
- }
-
- return packet;
-}
-
-EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
-
-int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
- u8 *ccval)
-{
- struct dccp_rx_hist_entry *packet = NULL, *entry;
-
- list_for_each_entry(entry, list, dccphrx_node)
- if (entry->dccphrx_seqno == seq) {
- packet = entry;
- break;
- }
-
- if (packet)
- *ccval = packet->dccphrx_ccval;
-
- return packet != NULL;
-}
-
-EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
-
-void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
- struct list_head *list,
- struct dccp_tx_hist_entry *packet)
+void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
{
- struct dccp_tx_hist_entry *next;
+ struct dccp_rx_hist_entry *entry, *next;
- list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
- list_del_init(&packet->dccphtx_node);
- dccp_tx_hist_entry_delete(hist, packet);
+ list_for_each_entry_safe(entry, next, list, dccphrx_node) {
+ list_del_init(&entry->dccphrx_node);
+ kmem_cache_free(hist->dccprxh_slab, entry);
}
}
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
-
-void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
-{
- struct dccp_tx_hist_entry *entry, *next;
-
- list_for_each_entry_safe(entry, next, list, dccphtx_node) {
- list_del_init(&entry->dccphtx_node);
- dccp_tx_hist_entry_delete(hist, entry);
- }
-}
+EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
"Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 9a8bcf224aa..1f960c19ea1 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -49,43 +49,27 @@
#define TFRC_WIN_COUNT_PER_RTT 4
#define TFRC_WIN_COUNT_LIMIT 16
+/*
+ * Transmitter History data structures and declarations
+ */
struct dccp_tx_hist_entry {
struct list_head dccphtx_node;
u64 dccphtx_seqno:48,
- dccphtx_ccval:4,
dccphtx_sent:1;
u32 dccphtx_rtt;
struct timeval dccphtx_tstamp;
};
-struct dccp_rx_hist_entry {
- struct list_head dccphrx_node;
- u64 dccphrx_seqno:48,
- dccphrx_ccval:4,
- dccphrx_type:4;
- u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
- struct timeval dccphrx_tstamp;
-};
-
struct dccp_tx_hist {
struct kmem_cache *dccptxh_slab;
};
extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name);
-extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist);
-
-struct dccp_rx_hist {
- struct kmem_cache *dccprxh_slab;
-};
-
-extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
-extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
-extern struct dccp_rx_hist_entry *
- dccp_rx_hist_find_data_packet(const struct list_head *list);
+extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist);
static inline struct dccp_tx_hist_entry *
- dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
- const gfp_t prio)
+ dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
+ const gfp_t prio)
{
struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab,
prio);
@@ -96,18 +80,20 @@ static inline struct dccp_tx_hist_entry *
return entry;
}
-static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
- struct dccp_tx_hist_entry *entry)
+static inline struct dccp_tx_hist_entry *
+ dccp_tx_hist_head(struct list_head *list)
{
- if (entry != NULL)
- kmem_cache_free(hist->dccptxh_slab, entry);
+ struct dccp_tx_hist_entry *head = NULL;
+
+ if (!list_empty(list))
+ head = list_entry(list->next, struct dccp_tx_hist_entry,
+ dccphtx_node);
+ return head;
}
extern struct dccp_tx_hist_entry *
dccp_tx_hist_find_entry(const struct list_head *list,
const u64 seq);
-extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
- u8 *ccval);
static inline void dccp_tx_hist_add_entry(struct list_head *list,
struct dccp_tx_hist_entry *entry)
@@ -115,30 +101,45 @@ static inline void dccp_tx_hist_add_entry(struct list_head *list,
list_add(&entry->dccphtx_node, list);
}
+static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
+ struct dccp_tx_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(hist->dccptxh_slab, entry);
+}
+
+extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
+ struct list_head *list);
+
extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
struct list_head *list,
struct dccp_tx_hist_entry *next);
-extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
- struct list_head *list);
+/*
+ * Receiver History data structures and declarations
+ */
+struct dccp_rx_hist_entry {
+ struct list_head dccphrx_node;
+ u64 dccphrx_seqno:48,
+ dccphrx_ccval:4,
+ dccphrx_type:4;
+ u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
+ struct timeval dccphrx_tstamp;
+};
-static inline struct dccp_tx_hist_entry *
- dccp_tx_hist_head(struct list_head *list)
-{
- struct dccp_tx_hist_entry *head = NULL;
+struct dccp_rx_hist {
+ struct kmem_cache *dccprxh_slab;
+};
- if (!list_empty(list))
- head = list_entry(list->next, struct dccp_tx_hist_entry,
- dccphtx_node);
- return head;
-}
+extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
+extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
static inline struct dccp_rx_hist_entry *
- dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
- const struct sock *sk,
- const u32 ndp,
- const struct sk_buff *skb,
- const gfp_t prio)
+ dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
+ const struct sock *sk,
+ const u32 ndp,
+ const struct sk_buff *skb,
+ const gfp_t prio)
{
struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab,
prio);
@@ -156,18 +157,8 @@ static inline struct dccp_rx_hist_entry *
return entry;
}
-static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
- struct dccp_rx_hist_entry *entry)
-{
- if (entry != NULL)
- kmem_cache_free(hist->dccprxh_slab, entry);
-}
-
-extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
- struct list_head *list);
-
static inline struct dccp_rx_hist_entry *
- dccp_rx_hist_head(struct list_head *list)
+ dccp_rx_hist_head(struct list_head *list)
{
struct dccp_rx_hist_entry *head = NULL;
@@ -177,6 +168,27 @@ static inline struct dccp_rx_hist_entry *
return head;
}
+extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+ u8 *ccval);
+extern struct dccp_rx_hist_entry *
+ dccp_rx_hist_find_data_packet(const struct list_head *list);
+
+extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+ struct list_head *rx_list,
+ struct list_head *li_list,
+ struct dccp_rx_hist_entry *packet,
+ u64 nonloss_seqno);
+
+static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
+ struct dccp_rx_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(hist->dccprxh_slab, entry);
+}
+
+extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
+ struct list_head *list);
+
static inline int
dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
{
@@ -184,12 +196,6 @@ static inline int
entry->dccphrx_type == DCCP_PKT_DATAACK;
}
-extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
- struct list_head *rx_list,
- struct list_head *li_list,
- struct dccp_rx_hist_entry *packet,
- u64 nonloss_seqno);
-
extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
struct list_head *li_list, u8 *win_loss);
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 45f30f59ea2..faf5f7e219e 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -13,8 +13,29 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
#include <linux/types.h>
+#include <asm/div64.h>
+
+/* integer-arithmetic divisions of type (a * 1000000)/b */
+static inline u64 scaled_div(u64 a, u32 b)
+{
+ BUG_ON(b==0);
+ a *= 1000000;
+ do_div(a, b);
+ return a;
+}
+
+static inline u32 scaled_div32(u64 a, u32 b)
+{
+ u64 result = scaled_div(a, b);
+
+ if (result > UINT_MAX) {
+ DCCP_CRIT("Overflow: a(%llu)/b(%u) > ~0U",
+ (unsigned long long)a, b);
+ return UINT_MAX;
+ }
+ return result;
+}
extern u32 tfrc_calc_x(u16 s, u32 R, u32 p);
extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index ddac2c511e2..90009fd77e1 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -13,7 +13,6 @@
*/
#include <linux/module.h>
-#include <asm/div64.h>
#include "../../dccp.h"
#include "tfrc.h"
@@ -616,15 +615,12 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small)
* @R: RTT scaled by 1000000 (i.e., microseconds)
* @p: loss ratio estimate scaled by 1000000
* Returns X_calc in bytes per second (not scaled).
- *
- * Note: DO NOT alter this code unless you run test cases against it,
- * as the code has been optimized to stop underflow/overflow.
*/
u32 tfrc_calc_x(u16 s, u32 R, u32 p)
{
- int index;
+ u16 index;
u32 f;
- u64 tmp1, tmp2;
+ u64 result;
/* check against invalid parameters and divide-by-zero */
BUG_ON(p > 1000000); /* p must not exceed 100% */
@@ -650,15 +646,17 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p)
f = tfrc_calc_x_lookup[index][0];
}
- /* The following computes X = s/(R*f(p)) in bytes per second. Since f(p)
- * and R are both scaled by 1000000, we need to multiply by 1000000^2.
- * ==> DO NOT alter this unless you test against overflow on 32 bit */
- tmp1 = ((u64)s * 100000000);
- tmp2 = ((u64)R * (u64)f);
- do_div(tmp2, 10000);
- do_div(tmp1, tmp2);
-
- return (u32)tmp1;
+ /*
+ * Compute X = s/(R*f(p)) in bytes per second.
+ * Since f(p) and R are both scaled by 1000000, we need to multiply by
+ * 1000000^2. To avoid overflow, the result is computed in two stages.
+ * This works under almost all reasonable operational conditions, for a
+ * wide range of parameters. Yet, should some strange combination of
+ * parameters result in overflow, the use of scaled_div32 will catch
+ * this and return UINT_MAX - which is a logically adequate consequence.
+ */
+ result = scaled_div(s, R);
+ return scaled_div32(result, f);
}
EXPORT_SYMBOL_GPL(tfrc_calc_x);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 68886986c8e..a0900bf98e6 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -80,8 +80,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
-#define DCCP_XMIT_TIMEO 30000 /* Time/msecs for blocking transmit per packet */
-
/* sysctl variables for DCCP */
extern int sysctl_dccp_request_retries;
extern int sysctl_dccp_retries1;
@@ -434,6 +432,7 @@ static inline void timeval_sub_usecs(struct timeval *tv,
tv->tv_sec--;
tv->tv_usec += USEC_PER_SEC;
}
+ DCCP_BUG_ON(tv->tv_sec < 0);
}
#ifdef CONFIG_SYSCTL
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 4dc487f27a1..95b6927ec65 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -329,7 +329,7 @@ static void dccp_feat_empty_confirm(struct dccp_minisock *dmsk,
switch (type) {
case DCCPO_CHANGE_L: opt->dccpop_type = DCCPO_CONFIRM_R; break;
case DCCPO_CHANGE_R: opt->dccpop_type = DCCPO_CONFIRM_L; break;
- default: DCCP_WARN("invalid type %d\n", type); return;
+ default: DCCP_WARN("invalid type %d\n", type); return;
}
opt->dccpop_feat = feature;
@@ -427,7 +427,7 @@ int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
switch (type) {
case DCCPO_CONFIRM_L: t = DCCPO_CHANGE_R; break;
case DCCPO_CONFIRM_R: t = DCCPO_CHANGE_L; break;
- default: DCCP_WARN("invalid type %d\n", type);
+ default: DCCP_WARN("invalid type %d\n", type);
return 1;
}
@@ -610,7 +610,7 @@ const char *dccp_feat_typename(const u8 type)
case DCCPO_CHANGE_R: return("ChangeR");
case DCCPO_CONFIRM_R: return("ConfirmR");
/* the following case must not appear in feature negotation */
- default: dccp_pr_debug("unknown type %d [BUG!]\n", type);
+ default: dccp_pr_debug("unknown type %d [BUG!]\n", type);
}
return NULL;
}
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 7371a2f3acf..565bc80557c 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -1,6 +1,6 @@
/*
* net/dccp/input.c
- *
+ *
* An implementation of the DCCP protocol
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
@@ -82,7 +82,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
* Otherwise,
* Drop packet and return
*/
- if (dh->dccph_type == DCCP_PKT_SYNC ||
+ if (dh->dccph_type == DCCP_PKT_SYNC ||
dh->dccph_type == DCCP_PKT_SYNCACK) {
if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
dp->dccps_awl, dp->dccps_awh) &&
@@ -185,8 +185,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
dccp_rcv_close(sk, skb);
return 0;
case DCCP_PKT_REQUEST:
- /* Step 7
- * or (S.is_server and P.type == Response)
+ /* Step 7
+ * or (S.is_server and P.type == Response)
* or (S.is_client and P.type == Request)
* or (S.state >= OPEN and P.type == Request
* and P.seqno >= S.OSR)
@@ -248,8 +248,18 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
DCCP_ACKVEC_STATE_RECEIVED))
goto discard;
- ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
- ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+ /*
+ * Deliver to the CCID module in charge.
+ * FIXME: Currently DCCP operates one-directional only, i.e. a listening
+ * server is not at the same time a connecting client. There is
+ * not much sense in delivering to both rx/tx sides at the moment
+ * (only one is active at a time); when moving to bidirectional
+ * service, this needs to be revised.
+ */
+ if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+ ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+ else
+ ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
return __dccp_rcv_established(sk, skb, dh, len);
discard:
@@ -264,7 +274,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
const struct dccp_hdr *dh,
const unsigned len)
{
- /*
+ /*
* Step 4: Prepare sequence numbers in REQUEST
* If S.state == REQUEST,
* If (P.type == Response or P.type == Reset)
@@ -332,7 +342,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
* from the Response * /
* S.state := PARTOPEN
* Set PARTOPEN timer
- * Continue with S.state == PARTOPEN
+ * Continue with S.state == PARTOPEN
* / * Step 12 will send the Ack completing the
* three-way handshake * /
*/
@@ -363,7 +373,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
*/
__kfree_skb(skb);
return 0;
- }
+ }
dccp_send_ack(sk);
return -1;
}
@@ -371,7 +381,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
out_invalid_packet:
/* dccp_v4_do_rcv will send a reset */
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
- return 1;
+ return 1;
}
static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
@@ -478,14 +488,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_event_ack_recv(sk, skb);
- if (dccp_msk(sk)->dccpms_send_ack_vector &&
+ if (dccp_msk(sk)->dccpms_send_ack_vector &&
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
- DCCP_SKB_CB(skb)->dccpd_seq,
- DCCP_ACKVEC_STATE_RECEIVED))
- goto discard;
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKVEC_STATE_RECEIVED))
+ goto discard;
- ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
- ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+ /* XXX see the comments in dccp_rcv_established about this */
+ if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER)
+ ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+ else
+ ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
}
/*
@@ -567,7 +580,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
}
}
- if (!queued) {
+ if (!queued) {
discard:
__kfree_skb(skb);
}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index ff81679c9f1..90c74b4adb7 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -157,7 +157,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
/* We don't check in the destentry if pmtu discovery is forbidden
* on this route. We just assume that no packet_to_big packets
* are send back when pmtu discovery is not active.
- * There is a small race when the user changes this flag in the
+ * There is a small race when the user changes this flag in the
* route, but I think that's acceptable.
*/
if ((dst = __sk_dst_check(sk, 0)) == NULL)
@@ -467,7 +467,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
.uli_u = { .ports =
{ .sport = dccp_hdr(skb)->dccph_dport,
.dport = dccp_hdr(skb)->dccph_sport }
- }
+ }
};
security_skb_classify_flow(skb, &fl);
@@ -595,7 +595,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
struct inet_request_sock *ireq;
struct request_sock *req;
struct dccp_request_sock *dreq;
- const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+ const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
@@ -609,7 +609,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (dccp_bad_service_code(sk, service)) {
reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
goto drop;
- }
+ }
/*
* TW buckets are converted to open requests without
* limitations, they conserve resources and peer is
@@ -644,7 +644,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
ireq->rmt_addr = skb->nh.iph->saddr;
ireq->opt = NULL;
- /*
+ /*
* Step 3: Process LISTEN state
*
* Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
@@ -846,15 +846,15 @@ static int dccp_v4_rcv(struct sk_buff *skb)
}
/* Step 2:
- * Look up flow ID in table and get corresponding socket */
+ * Look up flow ID in table and get corresponding socket */
sk = __inet_lookup(&dccp_hashinfo,
skb->nh.iph->saddr, dh->dccph_sport,
skb->nh.iph->daddr, dh->dccph_dport,
inet_iif(skb));
- /*
+ /*
* Step 2:
- * If no socket ...
+ * If no socket ...
*/
if (sk == NULL) {
dccp_pr_debug("failed to look up flow ID in table and "
@@ -862,9 +862,9 @@ static int dccp_v4_rcv(struct sk_buff *skb)
goto no_dccp_socket;
}
- /*
+ /*
* Step 2:
- * ... or S.state == TIMEWAIT,
+ * ... or S.state == TIMEWAIT,
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
@@ -876,8 +876,8 @@ static int dccp_v4_rcv(struct sk_buff *skb)
/*
* RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
- * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
- * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+ * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+ * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
*/
min_cov = dccp_sk(sk)->dccps_pcrlen;
if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
@@ -900,7 +900,7 @@ no_dccp_socket:
goto discard_it;
/*
* Step 2:
- * If no socket ...
+ * If no socket ...
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index c7aaa2574f5..6b91a9dd041 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -77,7 +77,7 @@ static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
}
static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
- __be16 sport, __be16 dport )
+ __be16 sport, __be16 dport )
{
return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
}
@@ -329,7 +329,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
GFP_ATOMIC);
if (skb == NULL)
- return;
+ return;
skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);
@@ -353,7 +353,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
dccp_csum_outgoing(skb);
dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
- &rxskb->nh.ipv6h->daddr);
+ &rxskb->nh.ipv6h->daddr);
memset(&fl, 0, sizeof(fl));
ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
@@ -424,7 +424,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
struct dccp_request_sock *dreq;
struct inet6_request_sock *ireq6;
struct ipv6_pinfo *np = inet6_sk(sk);
- const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
+ const __be32 service = dccp_hdr_request(skb)->dccph_req_service;
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
@@ -437,7 +437,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (dccp_bad_service_code(sk, service)) {
reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
goto drop;
- }
+ }
/*
* There are no SYN attacks on IPv6, yet...
*/
@@ -787,7 +787,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
* otherwise we just shortcircuit this and continue with
* the new socket..
*/
- if (nsk != sk) {
+ if (nsk != sk) {
if (dccp_child_process(sk, nsk, skb))
goto reset;
if (opt_skb != NULL)
@@ -843,14 +843,14 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
/* Step 2:
- * Look up flow ID in table and get corresponding socket */
+ * Look up flow ID in table and get corresponding socket */
sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
dh->dccph_sport,
&skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
inet6_iif(skb));
/*
* Step 2:
- * If no socket ...
+ * If no socket ...
*/
if (sk == NULL) {
dccp_pr_debug("failed to look up flow ID in table and "
@@ -860,7 +860,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
/*
* Step 2:
- * ... or S.state == TIMEWAIT,
+ * ... or S.state == TIMEWAIT,
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
@@ -872,8 +872,8 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
/*
* RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
- * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
- * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
+ * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
+ * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
*/
min_cov = dccp_sk(sk)->dccps_pcrlen;
if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
@@ -893,7 +893,7 @@ no_dccp_socket:
goto discard_it;
/*
* Step 2:
- * If no socket ...
+ * If no socket ...
* Generate Reset(No Connection) unless P.type == Reset
* Drop packet and return
*/
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 4c9e26775f7..6656bb497c7 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -182,7 +182,7 @@ out_free:
EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
-/*
+/*
* Process an incoming packet for RESPOND sockets represented
* as an request_sock.
*/
diff --git a/net/dccp/options.c b/net/dccp/options.c
index f398b43bc05..c03ba61eb6d 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -557,11 +557,6 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
return -1;
dp->dccps_hc_rx_insert_options = 0;
}
- if (dp->dccps_hc_tx_insert_options) {
- if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
- return -1;
- dp->dccps_hc_tx_insert_options = 0;
- }
/* Feature negotiation */
/* Data packets can't do feat negotiation */
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 400c30b6fca..3435542e965 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -1,6 +1,6 @@
/*
* net/dccp/output.c
- *
+ *
* An implementation of the DCCP protocol
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
@@ -124,7 +124,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
+ err = icsk->icsk_af_ops->queue_xmit(skb, 0);
return net_xmit_eval(err);
}
return -ENOBUFS;
@@ -175,14 +175,12 @@ void dccp_write_space(struct sock *sk)
/**
* dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet
* @sk: socket to wait for
- * @timeo: for how long
*/
-static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
- long *timeo)
+static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
DEFINE_WAIT(wait);
- long delay;
+ unsigned long delay;
int rc;
while (1) {
@@ -190,8 +188,6 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
if (sk->sk_err)
goto do_error;
- if (!*timeo)
- goto do_nonblock;
if (signal_pending(current))
goto do_interrupted;
@@ -199,12 +195,9 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
if (rc <= 0)
break;
delay = msecs_to_jiffies(rc);
- if (delay > *timeo || delay < 0)
- goto do_nonblock;
-
sk->sk_write_pending++;
release_sock(sk);
- *timeo -= schedule_timeout(delay);
+ schedule_timeout(delay);
lock_sock(sk);
sk->sk_write_pending--;
}
@@ -215,11 +208,8 @@ out:
do_error:
rc = -EPIPE;
goto out;
-do_nonblock:
- rc = -EAGAIN;
- goto out;
do_interrupted:
- rc = sock_intr_errno(*timeo);
+ rc = -EINTR;
goto out;
}
@@ -240,8 +230,6 @@ void dccp_write_xmit(struct sock *sk, int block)
{
struct dccp_sock *dp = dccp_sk(sk);
struct sk_buff *skb;
- long timeo = DCCP_XMIT_TIMEO; /* If a packet is taking longer than
- this we have other issues */
while ((skb = skb_peek(&sk->sk_write_queue))) {
int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
@@ -251,11 +239,9 @@ void dccp_write_xmit(struct sock *sk, int block)
sk_reset_timer(sk, &dp->dccps_xmit_timer,
msecs_to_jiffies(err)+jiffies);
break;
- } else {
- err = dccp_wait_for_ccid(sk, skb, &timeo);
- timeo = DCCP_XMIT_TIMEO;
- }
- if (err)
+ } else
+ err = dccp_wait_for_ccid(sk, skb);
+ if (err && err != -EINTR)
DCCP_BUG("err=%d after dccp_wait_for_ccid", err);
}
@@ -281,8 +267,10 @@ void dccp_write_xmit(struct sock *sk, int block)
if (err)
DCCP_BUG("err=%d after ccid_hc_tx_packet_sent",
err);
- } else
+ } else {
+ dccp_pr_debug("packet discarded\n");
kfree(skb);
+ }
}
}
@@ -350,7 +338,6 @@ EXPORT_SYMBOL_GPL(dccp_make_response);
static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
const enum dccp_reset_codes code)
-
{
struct dccp_hdr *dh;
struct dccp_sock *dp = dccp_sk(sk);
@@ -409,7 +396,7 @@ int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
code);
if (skb != NULL) {
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0);
+ err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0);
return net_xmit_eval(err);
}
}
@@ -431,14 +418,14 @@ static inline void dccp_connect_init(struct sock *sk)
dccp_sync_mss(sk, dst_mtu(dst));
- /*
+ /*
* SWL and AWL are initially adjusted so that they are not less than
* the initial Sequence Numbers received and sent, respectively:
* SWL := max(GSR + 1 - floor(W/4), ISR),
* AWL := max(GSS - W' + 1, ISS).
* These adjustments MUST be applied only at the beginning of the
* connection.
- */
+ */
dccp_update_gss(sk, dp->dccps_iss);
dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 5ec47d9ee44..63b3fa20e14 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -196,7 +196,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
sk, GFP_KERNEL);
dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
sk, GFP_KERNEL);
- if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
+ if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
dp->dccps_hc_tx_ccid == NULL)) {
ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
@@ -390,7 +390,7 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
struct dccp_sock *dp = dccp_sk(sk);
struct dccp_service_list *sl = NULL;
- if (service == DCCP_SERVICE_INVALID_VALUE ||
+ if (service == DCCP_SERVICE_INVALID_VALUE ||
optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32))
return -EINVAL;
@@ -830,7 +830,7 @@ EXPORT_SYMBOL_GPL(inet_dccp_listen);
static const unsigned char dccp_new_state[] = {
/* current state: new state: action: */
[0] = DCCP_CLOSED,
- [DCCP_OPEN] = DCCP_CLOSING | DCCP_ACTION_FIN,
+ [DCCP_OPEN] = DCCP_CLOSING | DCCP_ACTION_FIN,
[DCCP_REQUESTING] = DCCP_CLOSED,
[DCCP_PARTOPEN] = DCCP_CLOSING | DCCP_ACTION_FIN,
[DCCP_LISTEN] = DCCP_CLOSED,
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index e8f519e7f48..e5348f369c6 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -1,6 +1,6 @@
/*
* net/dccp/timer.c
- *
+ *
* An implementation of the DCCP protocol
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
@@ -102,13 +102,13 @@ static void dccp_retransmit_timer(struct sock *sk)
* sk->sk_send_head has to have one skb with
* DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
* packet types. The only packets eligible for retransmission are:
- * -- Requests in client-REQUEST state (sec. 8.1.1)
- * -- Acks in client-PARTOPEN state (sec. 8.1.5)
- * -- CloseReq in server-CLOSEREQ state (sec. 8.3)
- * -- Close in node-CLOSING state (sec. 8.3) */
+ * -- Requests in client-REQUEST state (sec. 8.1.1)
+ * -- Acks in client-PARTOPEN state (sec. 8.1.5)
+ * -- CloseReq in server-CLOSEREQ state (sec. 8.3)
+ * -- Close in node-CLOSING state (sec. 8.3) */
BUG_TRAP(sk->sk_send_head != NULL);
- /*
+ /*
* More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
* sent, no need to retransmit, this sock is dead.
*/
@@ -200,7 +200,7 @@ static void dccp_keepalive_timer(unsigned long data)
/* Only process if socket is not in use. */
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
- /* Try again later. */
+ /* Try again later. */
inet_csk_reset_keepalive_timer(sk, HZ / 20);
goto out;
}
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 0b9d4c95515..ed083ab455b 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -167,8 +167,7 @@ static int dn_forwarding_proc(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context);
+ void __user *newval, size_t newlen);
static struct dn_dev_sysctl_table {
struct ctl_table_header *sysctl_header;
@@ -347,8 +346,7 @@ static int dn_forwarding_proc(ctl_table *table, int write,
static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
#ifdef CONFIG_DECNET_ROUTER
struct net_device *dev = table->extra1;
@@ -1147,16 +1145,23 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
init_timer(&dn_db->timer);
dn_db->uptime = jiffies;
+
+ dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
+ if (!dn_db->neigh_parms) {
+ dev->dn_ptr = NULL;
+ kfree(dn_db);
+ return NULL;
+ }
+
if (dn_db->parms.up) {
if (dn_db->parms.up(dev) < 0) {
+ neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
dev->dn_ptr = NULL;
kfree(dn_db);
return NULL;
}
}
- dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
-
dn_dev_sysctl_register(dev, &dn_db->parms);
dn_dev_set_timer(dev);
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index e246f054f36..a4065eb1341 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -134,8 +134,7 @@ static int parse_addr(__le16 *addr, char *str)
static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
size_t len;
__le16 addr;
@@ -220,8 +219,7 @@ static int dn_node_address_handler(ctl_table *table, int write,
static int dn_def_dev_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
size_t len;
struct net_device *dev;
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index eec1a1dd91d..a824852909e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -167,7 +167,7 @@ static void
ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
- ieee80211softmac_assoc_work((void*)mac);
+ ieee80211softmac_assoc_work(&mac->associnfo.work.work);
}
static void
@@ -177,7 +177,7 @@ ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void
switch (event_type) {
case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
- ieee80211softmac_assoc_work((void*)mac);
+ ieee80211softmac_assoc_work(&mac->associnfo.work.work);
break;
case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
@@ -438,7 +438,7 @@ ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac)
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1;
- schedule_work(&mac->associnfo.work);
+ schedule_delayed_work(&mac->associnfo.work, 0);
spin_unlock_irqrestore(&mac->lock, flags);
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 480d72c7a42..fa2f7da606a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -463,7 +463,7 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
err = -E2BIG;
}
spin_unlock_irqrestore(&mac->lock, flags);
- mutex_lock(&mac->associnfo.mutex);
+ mutex_unlock(&mac->associnfo.mutex);
return err;
}
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 1144900d37f..86400964367 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -305,7 +305,7 @@ lookup_protocol:
sk->sk_reuse = 1;
inet = inet_sk(sk);
- inet->is_icsk = INET_PROTOSW_ICSK & answer_flags;
+ inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
if (SOCK_RAW == sock->type) {
inet->num = protocol;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 2fd899160f8..480ace9819f 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -165,9 +165,8 @@ struct in_device *inetdev_init(struct net_device *dev)
NET_IPV4_NEIGH, "ipv4", NULL, NULL);
#endif
- /* Account for reference dev->ip_ptr */
+ /* Account for reference dev->ip_ptr (below) */
in_dev_hold(in_dev);
- rcu_assign_pointer(dev->ip_ptr, in_dev);
#ifdef CONFIG_SYSCTL
devinet_sysctl_register(in_dev, &in_dev->cnf);
@@ -175,6 +174,9 @@ struct in_device *inetdev_init(struct net_device *dev)
ip_mc_init_dev(in_dev);
if (dev->flags & IFF_UP)
ip_mc_up(in_dev);
+
+ /* we can receive as soon as ip_ptr is set -- do this last */
+ rcu_assign_pointer(dev->ip_ptr, in_dev);
out:
return in_dev;
out_kfree:
@@ -1303,8 +1305,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
int *valp = table->data;
int new;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index cfb249cc0a5..1e589b91605 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1989,6 +1989,10 @@ static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
unsigned cindex = iter->index;
struct tnode *p;
+ /* A single entry routing table */
+ if (!tn)
+ return NULL;
+
pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
iter->tnode, iter->index, iter->depth);
rescan:
@@ -2037,11 +2041,18 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
if(!iter)
return NULL;
- if (n && IS_TNODE(n)) {
- iter->tnode = (struct tnode *) n;
- iter->trie = t;
- iter->index = 0;
- iter->depth = 1;
+ if (n) {
+ if (IS_TNODE(n)) {
+ iter->tnode = (struct tnode *) n;
+ iter->trie = t;
+ iter->index = 0;
+ iter->depth = 1;
+ } else {
+ iter->tnode = NULL;
+ iter->trie = t;
+ iter->index = 0;
+ iter->depth = 0;
+ }
return n;
}
return NULL;
@@ -2279,16 +2290,17 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN)
return 0;
+ if (!NODE_PARENT(n)) {
+ if (iter->trie == trie_local)
+ seq_puts(seq, "<local>:\n");
+ else
+ seq_puts(seq, "<main>:\n");
+ }
+
if (IS_TNODE(n)) {
struct tnode *tn = (struct tnode *) n;
__be32 prf = htonl(MASK_PFX(tn->key, tn->pos));
- if (!NODE_PARENT(n)) {
- if (iter->trie == trie_local)
- seq_puts(seq, "<local>:\n");
- else
- seq_puts(seq, "<main>:\n");
- }
seq_indent(seq, iter->depth-1);
seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n",
NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 74046efdf87..8ce00d3703d 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -565,7 +565,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
} else {
struct sk_buff *free_it = next;
- /* Old fragmnet is completely overridden with
+ /* Old fragment is completely overridden with
* new one drop it.
*/
next = next->next;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a35209d517a..a0f2008584b 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -164,7 +164,6 @@ EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
static inline int ip_finish_output2(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
- struct hh_cache *hh = dst->hh;
struct net_device *dev = dst->dev;
int hh_len = LL_RESERVED_SPACE(dev);
@@ -183,16 +182,9 @@ static inline int ip_finish_output2(struct sk_buff *skb)
skb = skb2;
}
- if (hh) {
- int hh_alen;
-
- read_lock_bh(&hh->hh_lock);
- hh_alen = HH_DATA_ALIGN(hh->hh_len);
- memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
- read_unlock_bh(&hh->hh_lock);
- skb_push(skb, hh->hh_len);
- return hh->hh_output(skb);
- } else if (dst->neighbour)
+ if (dst->hh)
+ return neigh_hh_output(dst->hh, skb);
+ else if (dst->neighbour)
return dst->neighbour->output(skb);
if (net_ratelimit())
@@ -289,8 +281,9 @@ int ip_output(struct sk_buff *skb)
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
-int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
+int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
{
+ struct sock *sk = skb->sk;
struct inet_sock *inet = inet_sk(sk);
struct ip_options *opt = inet->opt;
struct rtable *rt;
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 91a075edd68..7ea2d981a93 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -657,7 +657,7 @@ static void sync_master_loop(void)
if (stop_master_sync)
break;
- ssleep(1);
+ msleep_interruptible(1000);
}
/* clean up the sync_buff queue */
@@ -714,7 +714,7 @@ static void sync_backup_loop(void)
if (stop_backup_sync)
break;
- ssleep(1);
+ msleep_interruptible(1000);
}
/* release the sending multicast socket */
@@ -826,7 +826,7 @@ static int fork_sync_thread(void *startup)
if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
IP_VS_ERR("could not create sync_thread due to %d... "
"retrying.\n", pid);
- ssleep(1);
+ msleep_interruptible(1000);
goto repeat;
}
@@ -849,10 +849,12 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
ip_vs_sync_state |= state;
if (state == IP_VS_STATE_MASTER) {
- strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn));
+ strlcpy(ip_vs_master_mcast_ifn, mcast_ifn,
+ sizeof(ip_vs_master_mcast_ifn));
ip_vs_master_syncid = syncid;
} else {
- strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn));
+ strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn,
+ sizeof(ip_vs_backup_mcast_ifn));
ip_vs_backup_syncid = syncid;
}
@@ -860,7 +862,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
IP_VS_ERR("could not create fork_sync_thread due to %d... "
"retrying.\n", pid);
- ssleep(1);
+ msleep_interruptible(1000);
goto repeat;
}
@@ -880,7 +882,8 @@ int stop_sync_thread(int state)
IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
IP_VS_INFO("stopping sync thread %d ...\n",
- (state == IP_VS_STATE_MASTER) ? sync_master_pid : sync_backup_pid);
+ (state == IP_VS_STATE_MASTER) ?
+ sync_master_pid : sync_backup_pid);
__set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&stop_sync_wait, &wait);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index a68966059b5..c47ce7076bd 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -15,16 +15,19 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
struct flowi fl = {};
struct dst_entry *odst;
unsigned int hh_len;
+ unsigned int type;
+ type = inet_addr_type(iph->saddr);
if (addr_type == RTN_UNSPEC)
- addr_type = inet_addr_type(iph->saddr);
+ addr_type = type;
/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
* packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
*/
if (addr_type == RTN_LOCAL) {
fl.nl_u.ip4_u.daddr = iph->daddr;
- fl.nl_u.ip4_u.saddr = iph->saddr;
+ if (type == RTN_LOCAL)
+ fl.nl_u.ip4_u.saddr = iph->saddr;
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
fl.mark = (*pskb)->mark;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 363df9976c9..47bd3ad18b7 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -6,8 +6,8 @@ menu "IP: Netfilter Configuration"
depends on INET && NETFILTER
config NF_CONNTRACK_IPV4
- tristate "IPv4 connection tracking support (required for NAT) (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ tristate "IPv4 connection tracking support (required for NAT)"
+ depends on NF_CONNTRACK
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
@@ -401,7 +401,7 @@ config IP_NF_NAT
# NAT + specific targets: nf_conntrack
config NF_NAT
tristate "Full NAT"
- depends on IP_NF_IPTABLES && NF_CONNTRACK
+ depends on IP_NF_IPTABLES && NF_CONNTRACK_IPV4
help
The Full NAT option allows masquerading, port forwarding and other
forms of full Network Address Port Translation. It is controlled by
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 15e741aeb29..16d177b71bf 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -4,6 +4,14 @@
# objects for the standalone - connection tracking / NAT
ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
+# objects for l3 independent conntrack
+nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
+ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
+ifeq ($(CONFIG_PROC_FS),y)
+nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
+endif
+endif
+
ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
ifneq ($(CONFIG_NF_NAT),)
@@ -20,6 +28,8 @@ ip_nat_h323-objs := ip_nat_helper_h323.o
# connection tracking
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
+obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
+
obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
obj-$(CONFIG_NF_NAT) += nf_nat.o
@@ -106,13 +116,3 @@ obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
-# objects for l3 independent conntrack
-nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
-ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
-ifeq ($(CONFIG_PROC_FS),y)
-nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
-endif
-endif
-
-# l3 independent conntrack
-obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 71b76ade00e..9aa22398b3d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -358,6 +358,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
for (;;) {
struct arpt_standard_target *t
= (void *)arpt_get_target(e);
+ int visited = e->comefrom & (1 << hook);
if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) {
printk("arptables: loop hook %u pos %u %08X.\n",
@@ -368,11 +369,11 @@ static int mark_source_chains(struct xt_table_info *newinfo,
|= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
/* Unconditional return/END. */
- if (e->target_offset == sizeof(struct arpt_entry)
+ if ((e->target_offset == sizeof(struct arpt_entry)
&& (strcmp(t->target.u.user.name,
ARPT_STANDARD_TARGET) == 0)
&& t->verdict < 0
- && unconditional(&e->arp)) {
+ && unconditional(&e->arp)) || visited) {
unsigned int oldpos, size;
if (t->verdict < -NF_MAX_VERDICT - 1) {
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 5fcf91d617c..7f70b0886b8 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -374,9 +374,11 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
&& ctnetlink_dump_helpinfo(skb, ct) < 0)
goto nfattr_failure;
+#ifdef CONFIG_IP_NF_CONNTRACK_MARK
if ((events & IPCT_MARK || ct->mark)
&& ctnetlink_dump_mark(skb, ct) < 0)
goto nfattr_failure;
+#endif
if (events & IPCT_COUNTER_FILLING &&
(ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
@@ -959,7 +961,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
if (cda[CTA_PROTOINFO-1]) {
err = ctnetlink_change_protoinfo(ct, cda);
if (err < 0)
- return err;
+ goto err;
}
#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index 3a26d63eed8..11c588a10e6 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -283,10 +283,16 @@ static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
{
int s = *shift;
- for (; dptr <= limit && *dptr != '@'; dptr++)
+ /* Search for @, but stop at the end of the line.
+ * We are inside a sip: URI, so we don't need to worry about
+ * continuation lines. */
+ while (dptr <= limit &&
+ *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
(*shift)++;
+ dptr++;
+ }
- if (*dptr == '@') {
+ if (dptr <= limit && *dptr == '@') {
dptr++;
(*shift)++;
} else
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 0ff2956d35e..fc1f153c86b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -384,6 +384,7 @@ mark_source_chains(struct xt_table_info *newinfo,
for (;;) {
struct ipt_standard_target *t
= (void *)ipt_get_target(e);
+ int visited = e->comefrom & (1 << hook);
if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
printk("iptables: loop hook %u pos %u %08X.\n",
@@ -394,11 +395,11 @@ mark_source_chains(struct xt_table_info *newinfo,
|= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
/* Unconditional return/END. */
- if (e->target_offset == sizeof(struct ipt_entry)
+ if ((e->target_offset == sizeof(struct ipt_entry)
&& (strcmp(t->target.u.user.name,
IPT_STANDARD_TARGET) == 0)
&& t->verdict < 0
- && unconditional(&e->ip)) {
+ && unconditional(&e->ip)) || visited) {
unsigned int oldpos, size;
if (t->verdict < -NF_MAX_VERDICT - 1) {
@@ -484,7 +485,47 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
}
static inline int
-check_match(struct ipt_entry_match *m,
+check_entry(struct ipt_entry *e, const char *name)
+{
+ struct ipt_entry_target *t;
+
+ if (!ip_checkentry(&e->ip)) {
+ duprintf("ip_tables: ip check failed %p %s.\n", e, name);
+ return -EINVAL;
+ }
+
+ if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
+ return -EINVAL;
+
+ t = ipt_get_target(e);
+ if (e->target_offset + t->u.target_size > e->next_offset)
+ return -EINVAL;
+
+ return 0;
+}
+
+static inline int check_match(struct ipt_entry_match *m, const char *name,
+ const struct ipt_ip *ip, unsigned int hookmask)
+{
+ struct ipt_match *match;
+ int ret;
+
+ match = m->u.kernel.match;
+ ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
+ name, hookmask, ip->proto,
+ ip->invflags & IPT_INV_PROTO);
+ if (!ret && m->u.kernel.match->checkentry
+ && !m->u.kernel.match->checkentry(name, ip, match, m->data,
+ hookmask)) {
+ duprintf("ip_tables: check failed for `%s'.\n",
+ m->u.kernel.match->name);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static inline int
+find_check_match(struct ipt_entry_match *m,
const char *name,
const struct ipt_ip *ip,
unsigned int hookmask,
@@ -497,26 +538,15 @@ check_match(struct ipt_entry_match *m,
m->u.user.revision),
"ipt_%s", m->u.user.name);
if (IS_ERR(match) || !match) {
- duprintf("check_match: `%s' not found\n", m->u.user.name);
+ duprintf("find_check_match: `%s' not found\n", m->u.user.name);
return match ? PTR_ERR(match) : -ENOENT;
}
m->u.kernel.match = match;
- ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
- name, hookmask, ip->proto,
- ip->invflags & IPT_INV_PROTO);
+ ret = check_match(m, name, ip, hookmask);
if (ret)
goto err;
- if (m->u.kernel.match->checkentry
- && !m->u.kernel.match->checkentry(name, ip, match, m->data,
- hookmask)) {
- duprintf("ip_tables: check failed for `%s'.\n",
- m->u.kernel.match->name);
- ret = -EINVAL;
- goto err;
- }
-
(*i)++;
return 0;
err:
@@ -524,10 +554,29 @@ err:
return ret;
}
-static struct ipt_target ipt_standard_target;
+static inline int check_target(struct ipt_entry *e, const char *name)
+{
+ struct ipt_entry_target *t;
+ struct ipt_target *target;
+ int ret;
+
+ t = ipt_get_target(e);
+ target = t->u.kernel.target;
+ ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+ name, e->comefrom, e->ip.proto,
+ e->ip.invflags & IPT_INV_PROTO);
+ if (!ret && t->u.kernel.target->checkentry
+ && !t->u.kernel.target->checkentry(name, e, target,
+ t->data, e->comefrom)) {
+ duprintf("ip_tables: check failed for `%s'.\n",
+ t->u.kernel.target->name);
+ ret = -EINVAL;
+ }
+ return ret;
+}
static inline int
-check_entry(struct ipt_entry *e, const char *name, unsigned int size,
+find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
unsigned int *i)
{
struct ipt_entry_target *t;
@@ -535,49 +584,32 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
int ret;
unsigned int j;
- if (!ip_checkentry(&e->ip)) {
- duprintf("ip_tables: ip check failed %p %s.\n", e, name);
- return -EINVAL;
- }
-
- if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
- return -EINVAL;
+ ret = check_entry(e, name);
+ if (ret)
+ return ret;
j = 0;
- ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
+ ret = IPT_MATCH_ITERATE(e, find_check_match, name, &e->ip,
+ e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ipt_get_target(e);
- ret = -EINVAL;
- if (e->target_offset + t->u.target_size > e->next_offset)
- goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
- duprintf("check_entry: `%s' not found\n", t->u.user.name);
+ duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
goto cleanup_matches;
}
t->u.kernel.target = target;
- ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
- name, e->comefrom, e->ip.proto,
- e->ip.invflags & IPT_INV_PROTO);
+ ret = check_target(e, name);
if (ret)
goto err;
- if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- e->comefrom)) {
- duprintf("ip_tables: check failed for `%s'.\n",
- t->u.kernel.target->name);
- ret = -EINVAL;
- goto err;
- }
-
(*i)++;
return 0;
err:
@@ -712,7 +744,7 @@ translate_table(const char *name,
/* Finally, each sanity check must pass */
i = 0;
ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
- check_entry, name, size, &i);
+ find_check_entry, name, size, &i);
if (ret != 0) {
IPT_ENTRY_ITERATE(entry0, newinfo->size,
@@ -887,13 +919,13 @@ copy_entries_to_user(unsigned int total_size,
#ifdef CONFIG_COMPAT
struct compat_delta {
struct compat_delta *next;
- u_int16_t offset;
+ unsigned int offset;
short delta;
};
static struct compat_delta *compat_offsets = NULL;
-static int compat_add_offset(u_int16_t offset, short delta)
+static int compat_add_offset(unsigned int offset, short delta)
{
struct compat_delta *tmp;
@@ -925,7 +957,7 @@ static void compat_flush_offsets(void)
}
}
-static short compat_calc_jump(u_int16_t offset)
+static short compat_calc_jump(unsigned int offset)
{
struct compat_delta *tmp;
short delta;
@@ -965,7 +997,7 @@ static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
void *base, struct xt_table_info *newinfo)
{
struct ipt_entry_target *t;
- u_int16_t entry_offset;
+ unsigned int entry_offset;
int off, i, ret;
off = 0;
@@ -1435,7 +1467,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
{
struct ipt_entry_target *t;
struct ipt_target *target;
- u_int16_t entry_offset;
+ unsigned int entry_offset;
int ret, off, h, j;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
@@ -1452,14 +1484,9 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
return -EINVAL;
}
- if (!ip_checkentry(&e->ip)) {
- duprintf("ip_tables: ip check failed %p %s.\n", e, name);
- return -EINVAL;
- }
-
- if (e->target_offset + sizeof(struct compat_xt_entry_target) >
- e->next_offset)
- return -EINVAL;
+ ret = check_entry(e, name);
+ if (ret)
+ return ret;
off = 0;
entry_offset = (void *)e - (void *)base;
@@ -1470,15 +1497,13 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
goto cleanup_matches;
t = ipt_get_target(e);
- ret = -EINVAL;
- if (e->target_offset + t->u.target_size > e->next_offset)
- goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
- duprintf("check_entry: `%s' not found\n", t->u.user.name);
+ duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
+ t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
goto cleanup_matches;
}
@@ -1555,57 +1580,15 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
return ret;
}
-static inline int compat_check_match(struct ipt_entry_match *m, const char *name,
- const struct ipt_ip *ip, unsigned int hookmask)
-{
- struct ipt_match *match;
- int ret;
-
- match = m->u.kernel.match;
- ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
- name, hookmask, ip->proto,
- ip->invflags & IPT_INV_PROTO);
- if (!ret && m->u.kernel.match->checkentry
- && !m->u.kernel.match->checkentry(name, ip, match, m->data,
- hookmask)) {
- duprintf("ip_tables: compat: check failed for `%s'.\n",
- m->u.kernel.match->name);
- ret = -EINVAL;
- }
- return ret;
-}
-
-static inline int compat_check_target(struct ipt_entry *e, const char *name)
-{
- struct ipt_entry_target *t;
- struct ipt_target *target;
- int ret;
-
- t = ipt_get_target(e);
- target = t->u.kernel.target;
- ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
- name, e->comefrom, e->ip.proto,
- e->ip.invflags & IPT_INV_PROTO);
- if (!ret && t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target,
- t->data, e->comefrom)) {
- duprintf("ip_tables: compat: check failed for `%s'.\n",
- t->u.kernel.target->name);
- ret = -EINVAL;
- }
- return ret;
-}
-
static inline int compat_check_entry(struct ipt_entry *e, const char *name)
{
int ret;
- ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip,
- e->comefrom);
+ ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom);
if (ret)
return ret;
- return compat_check_target(e, name);
+ return check_target(e, name);
}
static int
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 09836506223..b1c11160b9d 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -447,6 +447,12 @@ checkentry(const char *tablename,
cipinfo->config = config;
}
+ if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%d\n", target->family);
+ return 0;
+ }
+
return 1;
}
@@ -460,6 +466,8 @@ static void destroy(const struct xt_target *target, void *targinfo)
clusterip_config_entry_put(cipinfo->config);
clusterip_config_put(cipinfo->config);
+
+ nf_ct_l3proto_module_put(target->family);
}
static struct ipt_target clusterip_tgt = {
@@ -683,7 +691,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
{
#define PROC_WRITELEN 10
char buffer[PROC_WRITELEN+1];
- struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
struct clusterip_config *c = pde->data;
unsigned long nodenum;
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 28b9233956b..d669685afd0 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -127,10 +127,13 @@ masquerade_target(struct sk_buff **pskb,
static inline int
device_cmp(struct ip_conntrack *i, void *ifindex)
{
+ int ret;
#ifdef CONFIG_NF_NAT_NEEDED
struct nf_conn_nat *nat = nfct_nat(i);
+
+ if (!nat)
+ return 0;
#endif
- int ret;
read_lock_bh(&masq_lock);
#ifdef CONFIG_NF_NAT_NEEDED
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 126db44e71a..4db0e73c56f 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -401,7 +401,7 @@ static int recent_seq_open(struct inode *inode, struct file *file)
static ssize_t recent_proc_write(struct file *file, const char __user *input,
size_t size, loff_t *loff)
{
- struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+ struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
struct recent_table *t = pde->data;
struct recent_entry *e;
char buf[sizeof("+255.255.255.255")], *c = buf;
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 0ae45b79a4e..5df4fcae3ab 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -72,9 +72,9 @@ static void pptp_nat_expected(struct nf_conn *ct,
DEBUGP("we are PAC->PNS\n");
/* build tuple for PNS->PAC */
t.src.l3num = AF_INET;
- t.src.u3.ip = master->tuplehash[exp->dir].tuple.src.u3.ip;
+ t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
t.src.u.gre.key = nat_pptp_info->pns_call_id;
- t.dst.u3.ip = master->tuplehash[exp->dir].tuple.dst.u3.ip;
+ t.dst.u3.ip = master->tuplehash[!exp->dir].tuple.dst.u3.ip;
t.dst.u.gre.key = nat_pptp_info->pac_call_id;
t.dst.protonum = IPPROTO_GRE;
}
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 730a7a44c88..00d6dea9f7f 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -123,7 +123,7 @@ nf_nat_fn(unsigned int hooknum,
nat = nfct_nat(ct);
if (!nat)
- return NF_DROP;
+ return NF_ACCEPT;
switch (ctinfo) {
case IP_CT_RELATED:
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 11c167118e8..2daa0dc19d3 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1325,7 +1325,8 @@ void ip_rt_send_redirect(struct sk_buff *skb)
/* Check for load limit; set rate_last to the latest sent
* redirect.
*/
- if (time_after(jiffies,
+ if (rt->u.dst.rate_tokens == 0 ||
+ time_after(jiffies,
(rt->u.dst.rate_last +
(ip_rt_redirect_load << rt->u.dst.rate_tokens)))) {
icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
@@ -2872,8 +2873,7 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
void __user *oldval,
size_t __user *oldlenp,
void __user *newval,
- size_t newlen,
- void **context)
+ size_t newlen)
{
int delay;
if (newlen != sizeof(int))
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index dfcf47f10f8..fabf69a9108 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -51,8 +51,7 @@ int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
static int ipv4_sysctl_forward_strategy(ctl_table *table,
int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
int *valp = table->data;
int new;
@@ -111,8 +110,7 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file *
static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
int nlen, void __user *oldval,
size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
char val[TCP_CA_NAME_MAX];
ctl_table tbl = {
@@ -122,8 +120,7 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
int ret;
tcp_get_default_congestion_control(val);
- ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
- context);
+ ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
if (ret == 0 && newval && newlen)
ret = tcp_set_default_congestion_control(val);
return ret;
@@ -169,8 +166,8 @@ static int proc_allowed_congestion_control(ctl_table *ctl,
static int strategy_allowed_congestion_control(ctl_table *table, int __user *name,
int nlen, void __user *oldval,
size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval,
+ size_t newlen)
{
ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
int ret;
@@ -180,8 +177,7 @@ static int strategy_allowed_congestion_control(ctl_table *table, int __user *nam
return -ENOMEM;
tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
- ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
- context);
+ ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
if (ret == 0 && newval && newlen)
ret = tcp_set_allowed_congestion_control(tbl.data);
kfree(tbl.data);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 090c690627e..b67e0dd743b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2364,8 +2364,9 @@ struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
EXPORT_SYMBOL(__tcp_get_md5sig_pool);
-void __tcp_put_md5sig_pool(void) {
- __tcp_free_md5sig_pool(tcp_md5sig_pool);
+void __tcp_put_md5sig_pool(void)
+{
+ tcp_free_md5sig_pool();
}
EXPORT_SYMBOL(__tcp_put_md5sig_pool);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c701f6abbfc..c26076fb890 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1011,10 +1011,11 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
for (j = 0; j < i; j++){
if (after(ntohl(sp[j].start_seq),
ntohl(sp[j+1].start_seq))){
- sp[j].start_seq = htonl(tp->recv_sack_cache[j+1].start_seq);
- sp[j].end_seq = htonl(tp->recv_sack_cache[j+1].end_seq);
- sp[j+1].start_seq = htonl(tp->recv_sack_cache[j].start_seq);
- sp[j+1].end_seq = htonl(tp->recv_sack_cache[j].end_seq);
+ struct tcp_sack_block_wire tmp;
+
+ tmp = sp[j];
+ sp[j] = sp[j+1];
+ sp[j+1] = tmp;
}
}
@@ -4420,9 +4421,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* But, this leaves one open to an easy denial of
* service attack, and SYN cookies can't defend
* against this problem. So, we drop the data
- * in the interest of security over speed.
+ * in the interest of security over speed unless
+ * it's still in use.
*/
- goto discard;
+ kfree_skb(skb);
+ return 0;
}
goto discard;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a1222d6968c..12de90a5047 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -648,7 +648,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
TCPOLEN_TIMESTAMP);
rep.opt[1] = htonl(tcp_time_stamp);
rep.opt[2] = htonl(ts);
- arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED;
+ arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
}
/* Swap the send and the receive. */
@@ -928,6 +928,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
if (tp->md5sig_info->entries4 == 0) {
kfree(tp->md5sig_info->keys4);
tp->md5sig_info->keys4 = NULL;
+ tp->md5sig_info->alloced4 = 0;
} else if (tp->md5sig_info->entries4 != i) {
/* Need to do some manipulation */
memcpy(&tp->md5sig_info->keys4[i],
@@ -1185,7 +1186,7 @@ done_opts:
return 0;
if (hash_expected && !hash_location) {
- LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
+ LIMIT_NETDEBUG(KERN_INFO "MD5 Hash expected but NOT found "
"(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
NIPQUAD(iph->saddr), ntohs(th->source),
NIPQUAD(iph->daddr), ntohs(th->dest));
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 32c1a972fa3..975f4472af2 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -467,6 +467,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
th = (struct tcphdr *) skb_push(skb, tcp_header_size);
skb->h.th = th;
+ skb_set_owner_w(skb, sk);
/* Build TCP header and checksum it. */
th->source = inet->sport;
@@ -540,7 +541,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
TCP_INC_STATS(TCP_MIB_OUTSEGS);
- err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
+ err = icsk->icsk_af_ops->queue_xmit(skb, 0);
if (likely(err <= 0))
return err;
@@ -1650,7 +1651,8 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
- skb->ip_summed = next_skb->ip_summed;
+ if (next_skb->ip_summed == CHECKSUM_PARTIAL)
+ skb->ip_summed = CHECKSUM_PARTIAL;
if (skb->ip_summed != CHECKSUM_PARTIAL)
skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size);
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index f230eeecf09..41c15784818 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -30,7 +30,7 @@
#include <net/tcp.h>
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_DESCRIPTION("TCP cwnd snooper");
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 035915fc9ed..cfff930f2ba 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -165,11 +165,14 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
goto gotit;
}
size = 0;
- sk_for_each(sk2, node, head)
- if (++size < best_size_so_far) {
- best_size_so_far = size;
- best = result;
- }
+ sk_for_each(sk2, node, head) {
+ if (++size >= best_size_so_far)
+ goto next;
+ }
+ best_size_so_far = size;
+ best = result;
+ next:
+ ;
}
result = best;
for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a5e8d207a51..e3854696988 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -341,6 +341,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
{
struct inet6_dev *ndev;
+ struct in6_addr maddr;
ASSERT_RTNL();
@@ -413,8 +414,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
if (netif_carrier_ok(dev))
ndev->if_flags |= IF_READY;
- /* protected by rtnl_lock */
- rcu_assign_pointer(dev->ip6_ptr, ndev);
ipv6_mc_init_dev(ndev);
ndev->tstamp = jiffies;
@@ -425,6 +424,13 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
NULL);
addrconf_sysctl_register(ndev, &ndev->cnf);
#endif
+ /* protected by rtnl_lock */
+ rcu_assign_pointer(dev->ip6_ptr, ndev);
+
+ /* Join all-node multicast group */
+ ipv6_addr_all_nodes(&maddr);
+ ipv6_dev_mc_inc(dev, &maddr);
+
return ndev;
}
@@ -3387,7 +3393,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
#ifdef CONFIG_IPV6_ROUTER_PREF
array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
-#ifdef CONFIV_IPV6_ROUTE_INFO
+#ifdef CONFIG_IPV6_ROUTE_INFO
array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
#endif
#endif
@@ -3656,8 +3662,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
int __user *name, int nlen,
void __user *oldval,
size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- void **context)
+ void __user *newval, size_t newlen)
{
int *valp = table->data;
int new;
@@ -3893,7 +3898,7 @@ static struct addrconf_sysctl_table
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
-#ifdef CONFIV_IPV6_ROUTE_INFO
+#ifdef CONFIG_IPV6_ROUTE_INFO
{
.ctl_name = NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN,
.procname = "accept_ra_rt_info_max_plen",
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e5cd83b2205..0e0e4262f4d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -171,7 +171,7 @@ lookup_protocol:
sk->sk_reuse = 1;
inet = inet_sk(sk);
- inet->is_icsk = INET_PROTOSW_ICSK & answer_flags;
+ inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
if (SOCK_RAW == sock->type) {
inet->num = protocol;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index c700302ad51..116f94a4907 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -139,8 +139,9 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
-int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
+int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
{
+ struct sock *sk = skb->sk;
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index e9212c7ff5c..7b7bd44fbf4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -72,20 +72,11 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f
static inline int ip6_output_finish(struct sk_buff *skb)
{
-
struct dst_entry *dst = skb->dst;
- struct hh_cache *hh = dst->hh;
-
- if (hh) {
- int hh_alen;
-
- read_lock_bh(&hh->hh_lock);
- hh_alen = HH_DATA_ALIGN(hh->hh_len);
- memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
- read_unlock_bh(&hh->hh_lock);
- skb_push(skb, hh->hh_len);
- return hh->hh_output(skb);
- } else if (dst->neighbour)
+
+ if (dst->hh)
+ return neigh_hh_output(dst->hh, skb);
+ else if (dst->neighbour)
return dst->neighbour->output(skb);
IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 1eafcfc95e8..352690e2ab8 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -978,12 +978,27 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
break;
case IPV6_UNICAST_HOPS:
- val = np->hop_limit;
- break;
-
case IPV6_MULTICAST_HOPS:
- val = np->mcast_hops;
+ {
+ struct dst_entry *dst;
+
+ if (optname == IPV6_UNICAST_HOPS)
+ val = np->hop_limit;
+ else
+ val = np->mcast_hops;
+
+ dst = sk_dst_get(sk);
+ if (dst) {
+ if (val < 0)
+ val = dst_metric(dst, RTAX_HOPLIMIT);
+ if (val < 0)
+ val = ipv6_get_hoplimit(dst->dev);
+ dst_release(dst);
+ }
+ if (val < 0)
+ val = ipv6_devconf.hop_limit;
break;
+ }
case IPV6_MULTICAST_LOOP:
val = np->mc_loop;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a1c231a04ac..882cde4b404 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2258,8 +2258,6 @@ void ipv6_mc_up(struct inet6_dev *idev)
void ipv6_mc_init_dev(struct inet6_dev *idev)
{
- struct in6_addr maddr;
-
write_lock_bh(&idev->lock);
rwlock_init(&idev->mc_lock);
idev->mc_gq_running = 0;
@@ -2275,10 +2273,6 @@ void ipv6_mc_init_dev(struct inet6_dev *idev)
idev->mc_maxdelay = IGMP6_UNSOLICITED_IVAL;
idev->mc_v1_seen = 0;
write_unlock_bh(&idev->lock);
-
- /* Add all-nodes address. */
- ipv6_addr_all_nodes(&maddr);
- ipv6_dev_mc_inc(idev->dev, &maddr);
}
/*
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 56ea9283730..39bb658f3c4 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1413,6 +1413,13 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
return;
}
+ if (!ipv6_addr_equal(&skb->nh.ipv6h->daddr, target) &&
+ !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+ ND_PRINTK2(KERN_WARNING
+ "ICMPv6 Redirect: target address is not link-local.\n");
+ return;
+ }
+
ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr,
dev->ifindex);
@@ -1667,8 +1674,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f
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)
+ void __user *newval, size_t newlen)
{
struct net_device *dev = ctl->extra1;
struct inet6_dev *idev;
@@ -1681,14 +1687,12 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
switch (ctl->ctl_name) {
case NET_NEIGH_REACHABLE_TIME:
ret = sysctl_jiffies(ctl, name, nlen,
- oldval, oldlenp, newval, newlen,
- context);
+ oldval, oldlenp, newval, newlen);
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);
+ oldval, oldlenp, newval, newlen);
break;
default:
ret = 0;
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index fc3e5eb4bc3..adcd6131df2 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -7,7 +7,7 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)"
config NF_CONNTRACK_IPV6
tristate "IPv6 connection tracking support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on INET && IPV6 && EXPERIMENTAL && NF_CONNTRACK
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
@@ -21,6 +21,7 @@ config NF_CONNTRACK_IPV6
config IP6_NF_QUEUE
tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)"
+ depends on INET && IPV6 && NETFILTER && EXPERIMENTAL
---help---
This option adds a queue handler to the kernel for IPv6
@@ -41,7 +42,7 @@ config IP6_NF_QUEUE
config IP6_NF_IPTABLES
tristate "IP6 tables support (required for filtering)"
- depends on NETFILTER_XTABLES
+ depends on INET && IPV6 && EXPERIMENTAL && NETFILTER_XTABLES
help
ip6tables is a general, extensible packet identification framework.
Currently only the packet filtering and packet mangling subsystem
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4eec4b3988b..99502c5da4c 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -413,6 +413,7 @@ mark_source_chains(struct xt_table_info *newinfo,
unsigned int pos = newinfo->hook_entry[hook];
struct ip6t_entry *e
= (struct ip6t_entry *)(entry0 + pos);
+ int visited = e->comefrom & (1 << hook);
if (!(valid_hooks & (1 << hook)))
continue;
@@ -433,11 +434,11 @@ mark_source_chains(struct xt_table_info *newinfo,
|= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
/* Unconditional return/END. */
- if (e->target_offset == sizeof(struct ip6t_entry)
+ if ((e->target_offset == sizeof(struct ip6t_entry)
&& (strcmp(t->target.u.user.name,
IP6T_STANDARD_TARGET) == 0)
&& t->verdict < 0
- && unconditional(&e->ipv6)) {
+ && unconditional(&e->ipv6)) || visited) {
unsigned int oldpos, size;
if (t->verdict < -NF_MAX_VERDICT - 1) {
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 37e5fca923a..d9c15402ba6 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -835,6 +835,8 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
s->nfct_reasm = skb;
s2 = s->next;
+ s->next = NULL;
+
NF_HOOK_THRESH(PF_INET6, hooknum, s, in, out, okfn,
NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
s = s2;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 9f80518aacb..5f0043c30b7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -494,7 +494,7 @@ do { \
goto out; \
pn = fn->parent; \
if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
- fn = fib6_lookup(pn->subtree, NULL, saddr); \
+ fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); \
else \
fn = pn; \
if (fn->fn_flags & RTN_RTINFO) \
@@ -2017,6 +2017,7 @@ static inline size_t rt6_nlmsg_size(void)
+ nla_total_size(4) /* RTA_IIF */
+ nla_total_size(4) /* RTA_OIF */
+ nla_total_size(4) /* RTA_PRIORITY */
+ + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
+ nla_total_size(sizeof(struct rta_cacheinfo));
}
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index 197e3e7ed7e..75e39ea599d 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -146,7 +146,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
* do something rational.
*/
void ircomm_tty_set_termios(struct tty_struct *tty,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
unsigned int cflag = tty->termios->c_cflag;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3a66878a182..80107d4909c 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -1,5 +1,5 @@
menu "Core Netfilter Configuration"
- depends on NET && NETFILTER
+ depends on NET && INET && NETFILTER
config NETFILTER_NETLINK
tristate "Netfilter netlink interface"
@@ -44,8 +44,7 @@ choice
depends on NF_CONNTRACK_ENABLED
config NF_CONNTRACK_SUPPORT
- bool "Layer 3 Independent Connection tracking (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "Layer 3 Independent Connection tracking"
help
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
@@ -122,7 +121,7 @@ config NF_CONNTRACK_EVENTS
config NF_CT_PROTO_GRE
tristate
- depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on NF_CONNTRACK
config NF_CT_PROTO_SCTP
tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
@@ -136,8 +135,8 @@ config NF_CT_PROTO_SCTP
Documentation/modules.txt. If unsure, say `N'.
config NF_CONNTRACK_AMANDA
- tristate "Amanda backup protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ tristate "Amanda backup protocol support"
+ depends on NF_CONNTRACK
select TEXTSEARCH
select TEXTSEARCH_KMP
help
@@ -151,8 +150,8 @@ config NF_CONNTRACK_AMANDA
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_FTP
- tristate "FTP protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ tristate "FTP protocol support"
+ depends on NF_CONNTRACK
help
Tracking FTP connections is problematic: special helpers are
required for tracking them, and doing masquerading and other forms
@@ -166,7 +165,7 @@ config NF_CONNTRACK_FTP
config NF_CONNTRACK_H323
tristate "H.323 protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on EXPERIMENTAL && NF_CONNTRACK && (IPV6 || IPV6=n)
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
important VoIP protocols, it is widely used by voice hardware and
@@ -184,8 +183,8 @@ config NF_CONNTRACK_H323
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_IRC
- tristate "IRC protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ tristate "IRC protocol support"
+ depends on NF_CONNTRACK
help
There is a commonly-used extension to IRC called
Direct Client-to-Client Protocol (DCC). This enables users to send
@@ -218,8 +217,8 @@ config NF_CONNTRACK_NETBIOS_NS
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_PPTP
- tristate "PPtP protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ tristate "PPtP protocol support"
+ depends on NF_CONNTRACK
select NF_CT_PROTO_GRE
help
This module adds support for PPTP (Point to Point Tunnelling
@@ -249,8 +248,8 @@ config NF_CONNTRACK_SIP
To compile it as a module, choose M here. If unsure, say N.
config NF_CONNTRACK_TFTP
- tristate "TFTP protocol support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && NF_CONNTRACK
+ tristate "TFTP protocol support"
+ depends on NF_CONNTRACK
help
TFTP connection tracking helper, this is required depending
on how restrictive your ruleset is.
@@ -629,7 +628,7 @@ config NETFILTER_XT_MATCH_TCPMSS
config NETFILTER_XT_MATCH_HASHLIMIT
tristate '"hashlimit" match support'
- depends on NETFILTER_XTABLES
+ depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
help
This option adds a `hashlimit' match.
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index a5b234e444d..2a48efdf0d6 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -89,6 +89,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
exp->expectfn = NULL;
exp->flags = NF_CT_EXPECT_PERMANENT;
+ exp->helper = NULL;
nf_conntrack_expect_related(exp);
nf_conntrack_expect_put(exp);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index bd1d2de75e4..c64f029f705 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -389,9 +389,11 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
&& ctnetlink_dump_helpinfo(skb, ct) < 0)
goto nfattr_failure;
+#ifdef CONFIG_NF_CONNTRACK_MARK
if ((events & IPCT_MARK || ct->mark)
&& ctnetlink_dump_mark(skb, ct) < 0)
goto nfattr_failure;
+#endif
if (events & IPCT_COUNTER_FILLING &&
(ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
@@ -981,7 +983,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
if (cda[CTA_PROTOINFO-1]) {
err = ctnetlink_change_protoinfo(ct, cda);
if (err < 0)
- return err;
+ goto err;
}
#if defined(CONFIG_NF_CONNTRACK_MARK)
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index f0ff00e0d05..c59df3bc2bb 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -113,7 +113,7 @@ static void pptp_expectfn(struct nf_conn *ct,
rcu_read_lock();
nf_nat_pptp_expectfn = rcu_dereference(nf_nat_pptp_hook_expectfn);
- if (nf_nat_pptp_expectfn && ct->status & IPS_NAT_MASK)
+ if (nf_nat_pptp_expectfn && ct->master->status & IPS_NAT_MASK)
nf_nat_pptp_expectfn(ct, exp);
else {
struct nf_conntrack_tuple inv_t;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index eb2a2411f97..9dec1153467 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -303,10 +303,16 @@ static int skp_epaddr_len(struct nf_conn *ct, const char *dptr,
{
int s = *shift;
- for (; dptr <= limit && *dptr != '@'; dptr++)
+ /* Search for @, but stop at the end of the line.
+ * We are inside a sip: URI, so we don't need to worry about
+ * continuation lines. */
+ while (dptr <= limit &&
+ *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
(*shift)++;
+ dptr++;
+ }
- if (*dptr == '@') {
+ if (dptr <= limit && *dptr == '@') {
dptr++;
(*shift)++;
} else
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index b5548239d41..0534bfa65cc 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -96,6 +96,11 @@ checkentry(const char *tablename,
{
struct xt_connmark_target_info *matchinfo = targinfo;
+ if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%d\n", target->family);
+ return 0;
+ }
if (matchinfo->mode == XT_CONNMARK_RESTORE) {
if (strcmp(tablename, "mangle") != 0) {
printk(KERN_WARNING "CONNMARK: restore can only be "
@@ -111,6 +116,12 @@ checkentry(const char *tablename,
return 1;
}
+static void
+destroy(const struct xt_target *target, void *targinfo)
+{
+ nf_ct_l3proto_module_put(target->family);
+}
+
#ifdef CONFIG_COMPAT
struct compat_xt_connmark_target_info {
compat_ulong_t mark, mask;
@@ -147,6 +158,7 @@ static struct xt_target xt_connmark_target[] = {
.name = "CONNMARK",
.family = AF_INET,
.checkentry = checkentry,
+ .destroy = destroy,
.target = target,
.targetsize = sizeof(struct xt_connmark_target_info),
#ifdef CONFIG_COMPAT
@@ -160,6 +172,7 @@ static struct xt_target xt_connmark_target[] = {
.name = "CONNMARK",
.family = AF_INET6,
.checkentry = checkentry,
+ .destroy = destroy,
.target = target,
.targetsize = sizeof(struct xt_connmark_target_info),
.me = THIS_MODULE
@@ -168,7 +181,6 @@ static struct xt_target xt_connmark_target[] = {
static int __init xt_connmark_init(void)
{
- need_conntrack();
return xt_register_targets(xt_connmark_target,
ARRAY_SIZE(xt_connmark_target));
}
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 46738626667..a3fe3c334b0 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -93,6 +93,11 @@ static int checkentry(const char *tablename, const void *entry,
{
struct xt_connsecmark_target_info *info = targinfo;
+ if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%d\n", target->family);
+ return 0;
+ }
switch (info->mode) {
case CONNSECMARK_SAVE:
case CONNSECMARK_RESTORE:
@@ -106,11 +111,18 @@ static int checkentry(const char *tablename, const void *entry,
return 1;
}
+static void
+destroy(const struct xt_target *target, void *targinfo)
+{
+ nf_ct_l3proto_module_put(target->family);
+}
+
static struct xt_target xt_connsecmark_target[] = {
{
.name = "CONNSECMARK",
.family = AF_INET,
.checkentry = checkentry,
+ .destroy = destroy,
.target = target,
.targetsize = sizeof(struct xt_connsecmark_target_info),
.table = "mangle",
@@ -120,6 +132,7 @@ static struct xt_target xt_connsecmark_target[] = {
.name = "CONNSECMARK",
.family = AF_INET6,
.checkentry = checkentry,
+ .destroy = destroy,
.target = target,
.targetsize = sizeof(struct xt_connsecmark_target_info),
.table = "mangle",
@@ -129,7 +142,6 @@ static struct xt_target xt_connsecmark_target[] = {
static int __init xt_connsecmark_init(void)
{
- need_conntrack();
return xt_register_targets(xt_connsecmark_target,
ARRAY_SIZE(xt_connsecmark_target));
}
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index dcc497ea818..5e32dfa2668 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -52,6 +52,8 @@ match(const struct sk_buff *skb,
{
const struct xt_connbytes_info *sinfo = matchinfo;
u_int64_t what = 0; /* initialize to make gcc happy */
+ u_int64_t bytes = 0;
+ u_int64_t pkts = 0;
const struct ip_conntrack_counter *counters;
if (!(counters = nf_ct_get_counters(skb)))
@@ -89,29 +91,22 @@ match(const struct sk_buff *skb,
case XT_CONNBYTES_AVGPKT:
switch (sinfo->direction) {
case XT_CONNBYTES_DIR_ORIGINAL:
- what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
- counters[IP_CT_DIR_ORIGINAL].packets);
+ bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
+ pkts = counters[IP_CT_DIR_ORIGINAL].packets;
break;
case XT_CONNBYTES_DIR_REPLY:
- what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
- counters[IP_CT_DIR_REPLY].packets);
+ bytes = counters[IP_CT_DIR_REPLY].bytes;
+ pkts = counters[IP_CT_DIR_REPLY].packets;
break;
case XT_CONNBYTES_DIR_BOTH:
- {
- u_int64_t bytes;
- u_int64_t pkts;
- bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
- counters[IP_CT_DIR_REPLY].bytes;
- pkts = counters[IP_CT_DIR_ORIGINAL].packets+
- counters[IP_CT_DIR_REPLY].packets;
-
- /* FIXME_THEORETICAL: what to do if sum
- * overflows ? */
-
- what = div64_64(bytes, pkts);
- }
+ bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
+ counters[IP_CT_DIR_REPLY].bytes;
+ pkts = counters[IP_CT_DIR_ORIGINAL].packets +
+ counters[IP_CT_DIR_REPLY].packets;
break;
}
+ if (pkts != 0)
+ what = div64_64(bytes, pkts);
break;
}
@@ -139,15 +134,28 @@ static int check(const char *tablename,
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
return 0;
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%d\n", match->family);
+ return 0;
+ }
+
return 1;
}
+static void
+destroy(const struct xt_match *match, void *matchinfo)
+{
+ nf_ct_l3proto_module_put(match->family);
+}
+
static struct xt_match xt_connbytes_match[] = {
{
.name = "connbytes",
.family = AF_INET,
.checkentry = check,
.match = match,
+ .destroy = destroy,
.matchsize = sizeof(struct xt_connbytes_info),
.me = THIS_MODULE
},
@@ -156,6 +164,7 @@ static struct xt_match xt_connbytes_match[] = {
.family = AF_INET6,
.checkentry = check,
.match = match,
+ .destroy = destroy,
.matchsize = sizeof(struct xt_connbytes_info),
.me = THIS_MODULE
},
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index a8f03057dbd..36c2defff23 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -63,22 +63,18 @@ checkentry(const char *tablename,
printk(KERN_WARNING "connmark: only support 32bit mark\n");
return 0;
}
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
- printk(KERN_WARNING "can't load nf_conntrack support for "
+ printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
return 0;
}
-#endif
return 1;
}
static void
destroy(const struct xt_match *match, void *matchinfo)
{
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
-#endif
}
#ifdef CONFIG_COMPAT
@@ -140,7 +136,6 @@ static struct xt_match xt_connmark_match[] = {
static int __init xt_connmark_init(void)
{
- need_conntrack();
return xt_register_matches(xt_connmark_match,
ARRAY_SIZE(xt_connmark_match));
}
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 0ea501a2fda..3dc2357b8de 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -20,6 +20,7 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_conntrack.h>
+#include <net/netfilter/nf_conntrack_compat.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
@@ -228,21 +229,17 @@ checkentry(const char *tablename,
void *matchinfo,
unsigned int hook_mask)
{
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
- printk(KERN_WARNING "can't load nf_conntrack support for "
+ printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
return 0;
}
-#endif
return 1;
}
static void destroy(const struct xt_match *match, void *matchinfo)
{
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
-#endif
}
static struct xt_match conntrack_match = {
@@ -257,7 +254,6 @@ static struct xt_match conntrack_match = {
static int __init xt_conntrack_init(void)
{
- need_conntrack();
return xt_register_match(&conntrack_match);
}
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index a5a6e192ac2..f28bf69d3d4 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -745,7 +745,7 @@ static int __init xt_hashlimit_init(void)
}
hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
if (!hashlimit_procdir6) {
- printk(KERN_ERR "xt_hashlimit: tnable to create proc dir "
+ printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
"entry\n");
goto err4;
}
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 5d7818b73e3..04bc32ba719 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -24,6 +24,7 @@
#endif
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_helper.h>
+#include <net/netfilter/nf_conntrack_compat.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
@@ -143,13 +144,11 @@ static int check(const char *tablename,
{
struct xt_helper_info *info = matchinfo;
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
- printk(KERN_WARNING "can't load nf_conntrack support for "
+ printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
return 0;
}
-#endif
info->name[29] = '\0';
return 1;
}
@@ -157,9 +156,7 @@ static int check(const char *tablename,
static void
destroy(const struct xt_match *match, void *matchinfo)
{
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
-#endif
}
static struct xt_match xt_helper_match[] = {
@@ -185,7 +182,6 @@ static struct xt_match xt_helper_match[] = {
static int __init xt_helper_init(void)
{
- need_conntrack();
return xt_register_matches(xt_helper_match,
ARRAY_SIZE(xt_helper_match));
}
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index fd8f954cded..b9b3ffc5451 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -113,20 +113,16 @@ checkentry(const char *tablename,
if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
info->bitmask & ~XT_PHYSDEV_OP_MASK)
return 0;
- if (brnf_deferred_hooks == 0 &&
- info->bitmask & XT_PHYSDEV_OP_OUT &&
+ if (info->bitmask & XT_PHYSDEV_OP_OUT &&
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
(1 << NF_IP_POST_ROUTING))) {
printk(KERN_WARNING "physdev match: using --physdev-out in the "
"OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
- "traffic is deprecated and breaks other things, it will "
- "be removed in January 2007. See Documentation/"
- "feature-removal-schedule.txt for details. This doesn't "
- "affect you in case you're using it for purely bridged "
- "traffic.\n");
- brnf_deferred_hooks = 1;
+ "traffic is not supported anymore.\n");
+ if (hook_mask & (1 << NF_IP_LOCAL_OUT))
+ return 0;
}
return 1;
}
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index d9010b16a1f..df37b912163 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -50,22 +50,18 @@ static int check(const char *tablename,
void *matchinfo,
unsigned int hook_mask)
{
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
- printk(KERN_WARNING "can't load nf_conntrack support for "
+ printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
return 0;
}
-#endif
return 1;
}
static void
destroy(const struct xt_match *match, void *matchinfo)
{
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
-#endif
}
static struct xt_match xt_state_match[] = {
@@ -91,7 +87,6 @@ static struct xt_match xt_state_match[] = {
static int __init xt_state_init(void)
{
- need_conntrack();
return xt_register_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
}
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 743b05734a4..73e0ff469bf 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -130,12 +130,12 @@ static int netlbl_cipsov4_add_common(struct genl_info *info,
nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
- if (iter > CIPSO_V4_TAG_MAXCNT)
+ if (iter >= CIPSO_V4_TAG_MAXCNT)
return -EINVAL;
doi_def->tags[iter++] = nla_get_u8(nla);
}
- if (iter < CIPSO_V4_TAG_MAXCNT)
- doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
+ while (iter < CIPSO_V4_TAG_MAXCNT)
+ doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
return 0;
}
@@ -162,6 +162,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
struct nlattr *nla_b;
int nla_a_rem;
int nla_b_rem;
+ u32 iter;
if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
!info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
@@ -185,20 +186,31 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
ret_val = netlbl_cipsov4_add_common(info, doi_def);
if (ret_val != 0)
goto add_std_failure;
+ ret_val = -EINVAL;
nla_for_each_nested(nla_a,
info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
nla_a_rem)
if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
+ if (nla_validate_nested(nla_a,
+ NLBL_CIPSOV4_A_MAX,
+ netlbl_cipsov4_genl_policy) != 0)
+ goto add_std_failure;
nla_for_each_nested(nla_b, nla_a, nla_b_rem)
switch (nla_b->nla_type) {
case NLBL_CIPSOV4_A_MLSLVLLOC:
+ if (nla_get_u32(nla_b) >
+ CIPSO_V4_MAX_LOC_LVLS)
+ goto add_std_failure;
if (nla_get_u32(nla_b) >=
doi_def->map.std->lvl.local_size)
doi_def->map.std->lvl.local_size =
nla_get_u32(nla_b) + 1;
break;
case NLBL_CIPSOV4_A_MLSLVLREM:
+ if (nla_get_u32(nla_b) >
+ CIPSO_V4_MAX_REM_LVLS)
+ goto add_std_failure;
if (nla_get_u32(nla_b) >=
doi_def->map.std->lvl.cipso_size)
doi_def->map.std->lvl.cipso_size =
@@ -206,9 +218,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
break;
}
}
- if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS ||
- doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
- goto add_std_failure;
doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
sizeof(u32),
GFP_KERNEL);
@@ -223,6 +232,10 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
ret_val = -ENOMEM;
goto add_std_failure;
}
+ for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
+ doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
+ for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
+ doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
nla_for_each_nested(nla_a,
info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
nla_a_rem)
@@ -230,11 +243,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
struct nlattr *lvl_loc;
struct nlattr *lvl_rem;
- if (nla_validate_nested(nla_a,
- NLBL_CIPSOV4_A_MAX,
- netlbl_cipsov4_genl_policy) != 0)
- goto add_std_failure;
-
lvl_loc = nla_find_nested(nla_a,
NLBL_CIPSOV4_A_MLSLVLLOC);
lvl_rem = nla_find_nested(nla_a,
@@ -264,12 +272,18 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
nla_for_each_nested(nla_b, nla_a, nla_b_rem)
switch (nla_b->nla_type) {
case NLBL_CIPSOV4_A_MLSCATLOC:
+ if (nla_get_u32(nla_b) >
+ CIPSO_V4_MAX_LOC_CATS)
+ goto add_std_failure;
if (nla_get_u32(nla_b) >=
doi_def->map.std->cat.local_size)
doi_def->map.std->cat.local_size =
nla_get_u32(nla_b) + 1;
break;
case NLBL_CIPSOV4_A_MLSCATREM:
+ if (nla_get_u32(nla_b) >
+ CIPSO_V4_MAX_REM_CATS)
+ goto add_std_failure;
if (nla_get_u32(nla_b) >=
doi_def->map.std->cat.cipso_size)
doi_def->map.std->cat.cipso_size =
@@ -277,9 +291,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
break;
}
}
- if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS ||
- doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
- goto add_std_failure;
doi_def->map.std->cat.local = kcalloc(
doi_def->map.std->cat.local_size,
sizeof(u32),
@@ -296,6 +307,10 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
ret_val = -ENOMEM;
goto add_std_failure;
}
+ for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
+ doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
+ for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
+ doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
nla_for_each_nested(nla_a,
info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
nla_a_rem)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 3baafb10f8f..383dd4e82ee 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -472,8 +472,7 @@ static int netlink_release(struct socket *sock)
NETLINK_URELEASE, &n);
}
- if (nlk->module)
- module_put(nlk->module);
+ module_put(nlk->module);
netlink_table_grab();
if (nlk->flags & NETLINK_KERNEL_SOCKET) {
@@ -699,7 +698,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
struct sock *netlink_getsockbyfilp(struct file *filp)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct sock *sock;
if (!S_ISSOCK(inode->i_mode))
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 1d50f801f18..43bbe2c9e49 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1377,6 +1377,15 @@ static struct notifier_block nr_dev_notifier = {
static struct net_device **dev_nr;
+static struct ax25_protocol nr_pid = {
+ .pid = AX25_P_NETROM,
+ .func = nr_route_frame
+};
+
+static struct ax25_linkfail nr_linkfail_notifier = {
+ .func = nr_link_failed,
+};
+
static int __init nr_proto_init(void)
{
int i;
@@ -1424,8 +1433,8 @@ static int __init nr_proto_init(void)
register_netdevice_notifier(&nr_dev_notifier);
- ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
- ax25_linkfail_register(nr_link_failed);
+ ax25_register_pid(&nr_pid);
+ ax25_linkfail_register(&nr_linkfail_notifier);
#ifdef CONFIG_SYSCTL
nr_register_sysctl();
@@ -1474,7 +1483,7 @@ static void __exit nr_exit(void)
nr_unregister_sysctl();
#endif
- ax25_linkfail_release(nr_link_failed);
+ ax25_linkfail_release(&nr_linkfail_notifier);
ax25_protocol_release(AX25_P_NETROM);
unregister_netdevice_notifier(&nr_dev_notifier);
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 9b8eb54971a..4700d5225b7 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -128,25 +128,37 @@ static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short
return -37;
}
-static int nr_set_mac_address(struct net_device *dev, void *addr)
+static int __must_check nr_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sa = addr;
+ int err;
+
+ if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
+ return 0;
+
+ if (dev->flags & IFF_UP) {
+ err = ax25_listen_register((ax25_address *)sa->sa_data, NULL);
+ if (err)
+ return err;
- if (dev->flags & IFF_UP)
ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
+ }
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
- if (dev->flags & IFF_UP)
- ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
-
return 0;
}
static int nr_open(struct net_device *dev)
{
+ int err;
+
+ err = ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
+ if (err)
+ return err;
+
netif_start_queue(dev);
- ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
+
return 0;
}
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 0096105bcd4..8f88964099e 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -87,8 +87,9 @@ static void nr_remove_neigh(struct nr_neigh *);
* Add a new route to a node, and in the process add the node and the
* neighbour if it is new.
*/
-static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax25,
- ax25_digi *ax25_digi, struct net_device *dev, int quality, int obs_count)
+static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
+ ax25_address *ax25, ax25_digi *ax25_digi, struct net_device *dev,
+ int quality, int obs_count)
{
struct nr_node *nr_node;
struct nr_neigh *nr_neigh;
@@ -406,7 +407,8 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
/*
* Lock a neighbour with a quality.
*/
-static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
+static int __must_check nr_add_neigh(ax25_address *callsign,
+ ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
{
struct nr_neigh *nr_neigh;
@@ -777,9 +779,13 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
nr_src = (ax25_address *)(skb->data + 0);
nr_dest = (ax25_address *)(skb->data + 7);
- if (ax25 != NULL)
- nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
- ax25->ax25_dev->dev, 0, sysctl_netrom_obsolescence_count_initialiser);
+ if (ax25 != NULL) {
+ ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
+ ax25->ax25_dev->dev, 0,
+ sysctl_netrom_obsolescence_count_initialiser);
+ if (ret)
+ return ret;
+ }
if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */
if (ax25 == NULL) /* Its from me */
@@ -844,6 +850,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
ret = (nr_neigh->ax25 != NULL);
nr_node_unlock(nr_node);
nr_node_put(nr_node);
+
return ret;
}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index da73e8a8c18..6dc01bdeb76 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -359,6 +359,10 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
if (dev == NULL)
goto out_unlock;
+ err = -ENETDOWN;
+ if (!(dev->flags & IFF_UP))
+ goto out_unlock;
+
/*
* You may not queue a frame bigger than the mtu. This is the lowest level
* raw protocol and you must do your own fragmentation at this level.
@@ -407,10 +411,6 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
if (err)
goto out_free;
- err = -ENETDOWN;
- if (!(dev->flags & IFF_UP))
- goto out_free;
-
/*
* Now send it
*/
@@ -428,24 +428,18 @@ out_unlock:
}
#endif
-static inline int run_filter(struct sk_buff *skb, struct sock *sk,
- unsigned *snaplen)
+static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
+ unsigned int res)
{
struct sk_filter *filter;
- int err = 0;
rcu_read_lock_bh();
filter = rcu_dereference(sk->sk_filter);
- if (filter != NULL) {
- err = sk_run_filter(skb, filter->insns, filter->len);
- if (!err)
- err = -EPERM;
- else if (*snaplen > err)
- *snaplen = err;
- }
+ if (filter != NULL)
+ res = sk_run_filter(skb, filter->insns, filter->len);
rcu_read_unlock_bh();
- return err;
+ return res;
}
/*
@@ -467,7 +461,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
struct packet_sock *po;
u8 * skb_head = skb->data;
int skb_len = skb->len;
- unsigned snaplen;
+ unsigned int snaplen, res;
if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;
@@ -495,8 +489,11 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
snaplen = skb->len;
- if (run_filter(skb, sk, &snaplen) < 0)
+ res = run_filter(skb, sk, snaplen);
+ if (!res)
goto drop_n_restore;
+ if (snaplen > res)
+ snaplen = res;
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
(unsigned)sk->sk_rcvbuf)
@@ -568,7 +565,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct tpacket_hdr *h;
u8 * skb_head = skb->data;
int skb_len = skb->len;
- unsigned snaplen;
+ unsigned int snaplen, res;
unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER;
unsigned short macoff, netoff;
struct sk_buff *copy_skb = NULL;
@@ -592,8 +589,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
snaplen = skb->len;
- if (run_filter(skb, sk, &snaplen) < 0)
+ res = run_filter(skb, sk, snaplen);
+ if (!res)
goto drop_n_restore;
+ if (snaplen > res)
+ snaplen = res;
if (sk->sk_type == SOCK_DGRAM) {
macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
@@ -738,6 +738,10 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
if (sock->type == SOCK_RAW)
reserve = dev->hard_header_len;
+ err = -ENETDOWN;
+ if (!(dev->flags & IFF_UP))
+ goto out_unlock;
+
err = -EMSGSIZE;
if (len > dev->mtu+reserve)
goto out_unlock;
@@ -770,10 +774,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
skb->dev = dev;
skb->priority = sk->sk_priority;
- err = -ENETDOWN;
- if (!(dev->flags & IFF_UP))
- goto out_free;
-
/*
* Now send it
*/
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 08a54285565..9e279464c9d 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1314,7 +1314,8 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (copy_from_user(&rose_callsign, argp, sizeof(ax25_address)))
return -EFAULT;
if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
- ax25_listen_register(&rose_callsign, NULL);
+ return ax25_listen_register(&rose_callsign, NULL);
+
return 0;
case SIOCRSGL2CALL:
@@ -1481,6 +1482,15 @@ static struct notifier_block rose_dev_notifier = {
static struct net_device **dev_rose;
+static struct ax25_protocol rose_pid = {
+ .pid = AX25_P_ROSE,
+ .func = rose_route_frame
+};
+
+static struct ax25_linkfail rose_linkfail_notifier = {
+ .func = rose_link_failed
+};
+
static int __init rose_proto_init(void)
{
int i;
@@ -1530,8 +1540,8 @@ static int __init rose_proto_init(void)
sock_register(&rose_family_ops);
register_netdevice_notifier(&rose_dev_notifier);
- ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
- ax25_linkfail_register(rose_link_failed);
+ ax25_register_pid(&rose_pid);
+ ax25_linkfail_register(&rose_linkfail_notifier);
#ifdef CONFIG_SYSCTL
rose_register_sysctl();
@@ -1579,7 +1589,7 @@ static void __exit rose_exit(void)
rose_rt_free();
ax25_protocol_release(AX25_P_ROSE);
- ax25_linkfail_release(rose_link_failed);
+ ax25_linkfail_release(&rose_linkfail_notifier);
if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
ax25_listen_release(&rose_callsign, NULL);
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 7c279e2659e..50824d345fa 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -93,20 +93,34 @@ static int rose_rebuild_header(struct sk_buff *skb)
static int rose_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sa = addr;
+ int err;
- rose_del_loopback_node((rose_address *)dev->dev_addr);
+ if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
+ return 0;
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+ if (dev->flags & IFF_UP) {
+ err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+ if (err)
+ return err;
+
+ rose_del_loopback_node((rose_address *)dev->dev_addr);
+ }
- rose_add_loopback_node((rose_address *)dev->dev_addr);
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
return 0;
}
static int rose_open(struct net_device *dev)
{
+ int err;
+
+ err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+ if (err)
+ return err;
+
netif_start_queue(dev);
- rose_add_loopback_node((rose_address *)dev->dev_addr);
+
return 0;
}
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c
index 103b4d38f88..3e41bd93ab9 100644
--- a/net/rose/rose_loopback.c
+++ b/net/rose/rose_loopback.c
@@ -79,7 +79,8 @@ static void rose_loopback_timer(unsigned long param)
skb->h.raw = skb->data;
- if ((sk = rose_find_socket(lci_o, rose_loopback_neigh)) != NULL) {
+ sk = rose_find_socket(lci_o, &rose_loopback_neigh);
+ if (sk) {
if (rose_process_rx_frame(sk, skb) == 0)
kfree_skb(skb);
continue;
@@ -87,7 +88,7 @@ static void rose_loopback_timer(unsigned long param)
if (frametype == ROSE_CALL_REQUEST) {
if ((dev = rose_dev_get(dest)) != NULL) {
- if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0)
+ if (rose_rx_call_request(skb, dev, &rose_loopback_neigh, lci_o) == 0)
kfree_skb(skb);
} else {
kfree_skb(skb);
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 7252344779a..8028c0d425d 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -46,13 +46,13 @@ static DEFINE_SPINLOCK(rose_neigh_list_lock);
static struct rose_route *rose_route_list;
static DEFINE_SPINLOCK(rose_route_list_lock);
-struct rose_neigh *rose_loopback_neigh;
+struct rose_neigh rose_loopback_neigh;
/*
* Add a new route to a node, and in the process add the node and the
* neighbour if it is new.
*/
-static int rose_add_node(struct rose_route_struct *rose_route,
+static int __must_check rose_add_node(struct rose_route_struct *rose_route,
struct net_device *dev)
{
struct rose_node *rose_node, *rose_tmpn, *rose_tmpp;
@@ -361,33 +361,30 @@ out:
/*
* Add the loopback neighbour.
*/
-int rose_add_loopback_neigh(void)
+void rose_add_loopback_neigh(void)
{
- if ((rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_ATOMIC)) == NULL)
- return -ENOMEM;
+ struct rose_neigh *sn = &rose_loopback_neigh;
- rose_loopback_neigh->callsign = null_ax25_address;
- rose_loopback_neigh->digipeat = NULL;
- rose_loopback_neigh->ax25 = NULL;
- rose_loopback_neigh->dev = NULL;
- rose_loopback_neigh->count = 0;
- rose_loopback_neigh->use = 0;
- rose_loopback_neigh->dce_mode = 1;
- rose_loopback_neigh->loopback = 1;
- rose_loopback_neigh->number = rose_neigh_no++;
- rose_loopback_neigh->restarted = 1;
+ sn->callsign = null_ax25_address;
+ sn->digipeat = NULL;
+ sn->ax25 = NULL;
+ sn->dev = NULL;
+ sn->count = 0;
+ sn->use = 0;
+ sn->dce_mode = 1;
+ sn->loopback = 1;
+ sn->number = rose_neigh_no++;
+ sn->restarted = 1;
- skb_queue_head_init(&rose_loopback_neigh->queue);
+ skb_queue_head_init(&sn->queue);
- init_timer(&rose_loopback_neigh->ftimer);
- init_timer(&rose_loopback_neigh->t0timer);
+ init_timer(&sn->ftimer);
+ init_timer(&sn->t0timer);
spin_lock_bh(&rose_neigh_list_lock);
- rose_loopback_neigh->next = rose_neigh_list;
- rose_neigh_list = rose_loopback_neigh;
+ sn->next = rose_neigh_list;
+ rose_neigh_list = sn;
spin_unlock_bh(&rose_neigh_list_lock);
-
- return 0;
}
/*
@@ -421,13 +418,13 @@ int rose_add_loopback_node(rose_address *address)
rose_node->mask = 10;
rose_node->count = 1;
rose_node->loopback = 1;
- rose_node->neighbour[0] = rose_loopback_neigh;
+ rose_node->neighbour[0] = &rose_loopback_neigh;
/* Insert at the head of list. Address is always mask=10 */
rose_node->next = rose_node_list;
rose_node_list = rose_node;
- rose_loopback_neigh->count++;
+ rose_loopback_neigh.count++;
out:
spin_unlock_bh(&rose_node_list_lock);
@@ -458,7 +455,7 @@ void rose_del_loopback_node(rose_address *address)
rose_remove_node(rose_node);
- rose_loopback_neigh->count--;
+ rose_loopback_neigh.count--;
out:
spin_unlock_bh(&rose_node_list_lock);
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index a9608064a4c..01e69138578 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -55,7 +55,8 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
struct ipt_target *target;
int ret = 0;
- target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision);
+ target = xt_request_find_target(AF_INET, t->u.user.name,
+ t->u.user.revision);
if (!target)
return -ENOENT;
@@ -63,9 +64,10 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
table, hook, 0, 0);
- if (ret)
+ if (ret) {
+ module_put(t->u.kernel.target->me);
return ret;
-
+ }
if (t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(table, NULL,
t->u.kernel.target, t->data,
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index ba82dfab604..f79a4f3d0a9 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -371,8 +371,6 @@ static void cbq_deactivate_class(struct cbq_class *this)
return;
}
}
-
- cl = cl_prev->next_alive;
return;
}
} while ((cl_prev = cl) != q->active[prio]);
@@ -1258,6 +1256,8 @@ static unsigned int cbq_drop(struct Qdisc* sch)
do {
if (cl->q->ops->drop && (len = cl->q->ops->drop(cl->q))) {
sch->q.qlen--;
+ if (!cl->q->q.qlen)
+ cbq_deactivate_class(cl);
return len;
}
} while ((cl = cl->next_alive) != cl_head);
@@ -1685,8 +1685,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
#endif
}
sch_tree_lock(sch);
- *old = cl->q;
- cl->q = new;
+ *old = xchg(&cl->q, new);
qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
qdisc_reset(*old);
sch_tree_unlock(sch);
@@ -1704,6 +1703,14 @@ cbq_leaf(struct Qdisc *sch, unsigned long arg)
return cl ? cl->q : NULL;
}
+static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+ struct cbq_class *cl = (struct cbq_class *)arg;
+
+ if (cl->q->q.qlen == 0)
+ cbq_deactivate_class(cl);
+}
+
static unsigned long cbq_get(struct Qdisc *sch, u32 classid)
{
struct cbq_sched_data *q = qdisc_priv(sch);
@@ -1988,12 +1995,17 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
{
struct cbq_sched_data *q = qdisc_priv(sch);
struct cbq_class *cl = (struct cbq_class*)arg;
+ unsigned int qlen;
if (cl->filters || cl->children || cl == &q->link)
return -EBUSY;
sch_tree_lock(sch);
+ qlen = cl->q->q.qlen;
+ qdisc_reset(cl->q);
+ qdisc_tree_decrease_qlen(cl->q, qlen);
+
if (cl->next_alive)
cbq_deactivate_class(cl);
@@ -2084,6 +2096,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
static struct Qdisc_class_ops cbq_class_ops = {
.graft = cbq_graft,
.leaf = cbq_leaf,
+ .qlen_notify = cbq_qlen_notify,
.get = cbq_get,
.put = cbq_put,
.change = cbq_change_class,
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 215e68c2b61..15f23c5511a 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -147,6 +147,10 @@ struct htb_class {
psched_tdiff_t mbuffer; /* max wait time */
long tokens, ctokens; /* current number of tokens */
psched_time_t t_c; /* checkpoint time */
+
+ int prio; /* For parent to leaf return possible here */
+ int quantum; /* we do backup. Finally full replacement */
+ /* of un.leaf originals should be done. */
};
/* TODO: maybe compute rate when size is too large .. or drop ? */
@@ -1271,6 +1275,38 @@ static void htb_destroy_filters(struct tcf_proto **fl)
}
}
+static inline int htb_parent_last_child(struct htb_class *cl)
+{
+ if (!cl->parent)
+ /* the root class */
+ return 0;
+
+ if (!(cl->parent->children.next == &cl->sibling &&
+ cl->parent->children.prev == &cl->sibling))
+ /* not the last child */
+ return 0;
+
+ return 1;
+}
+
+static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q)
+{
+ struct htb_class *parent = cl->parent;
+
+ BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
+
+ parent->level = 0;
+ memset(&parent->un.inner, 0, sizeof(parent->un.inner));
+ INIT_LIST_HEAD(&parent->un.leaf.drop_list);
+ parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
+ parent->un.leaf.quantum = parent->quantum;
+ parent->un.leaf.prio = parent->prio;
+ parent->tokens = parent->buffer;
+ parent->ctokens = parent->cbuffer;
+ PSCHED_GET_TIME(parent->t_c);
+ parent->cmode = HTB_CAN_SEND;
+}
+
static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
{
struct htb_sched *q = qdisc_priv(sch);
@@ -1328,6 +1364,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
struct htb_sched *q = qdisc_priv(sch);
struct htb_class *cl = (struct htb_class *)arg;
unsigned int qlen;
+ struct Qdisc *new_q = NULL;
+ int last_child = 0;
// TODO: why don't allow to delete subtree ? references ? does
// tc subsys quarantee us that in htb_destroy it holds no class
@@ -1335,6 +1373,12 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
if (!list_empty(&cl->children) || cl->filter_cnt)
return -EBUSY;
+ if (!cl->level && htb_parent_last_child(cl)) {
+ new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ cl->parent->classid);
+ last_child = 1;
+ }
+
sch_tree_lock(sch);
/* delete from hash and active; remainder in destroy_class */
@@ -1349,6 +1393,9 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
if (cl->prio_activity)
htb_deactivate(q, cl);
+ if (last_child)
+ htb_parent_to_leaf(cl, new_q);
+
if (--cl->refcnt == 0)
htb_destroy_class(sch, cl);
@@ -1483,6 +1530,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
cl->un.leaf.quantum = hopt->quantum;
if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO)
cl->un.leaf.prio = TC_HTB_NUMPRIO - 1;
+
+ /* backup for htb_parent_to_leaf */
+ cl->quantum = cl->un.leaf.quantum;
+ cl->prio = cl->un.leaf.prio;
}
cl->buffer = hopt->buffer;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index ad0057db0f9..5db95caed0a 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -298,6 +298,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->default_flags = sp->default_flags;
asoc->default_context = sp->default_context;
asoc->default_timetolive = sp->default_timetolive;
+ asoc->default_rcv_context = sp->default_rcv_context;
return asoc;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 3c3e560087c..ef36be073a1 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -78,8 +78,44 @@
#include <asm/uaccess.h>
+/* Event handler for inet6 address addition/deletion events. */
+static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
+ void *ptr)
+{
+ struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+ struct sctp_sockaddr_entry *addr;
+ struct list_head *pos, *temp;
+
+ switch (ev) {
+ case NETDEV_UP:
+ addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+ if (addr) {
+ addr->a.v6.sin6_family = AF_INET6;
+ addr->a.v6.sin6_port = 0;
+ memcpy(&addr->a.v6.sin6_addr, &ifa->addr,
+ sizeof(struct in6_addr));
+ addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
+ list_add_tail(&addr->list, &sctp_local_addr_list);
+ }
+ break;
+ case NETDEV_DOWN:
+ list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ if (ipv6_addr_equal(&addr->a.v6.sin6_addr, &ifa->addr)) {
+ list_del(pos);
+ kfree(addr);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static struct notifier_block sctp_inet6addr_notifier = {
- .notifier_call = sctp_inetaddr_event,
+ .notifier_call = sctp_inet6addr_event,
};
/* ICMP error handler. */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index f2ba8615895..0ef48126b11 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -163,7 +163,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
/* Extract our IP addresses from the system and stash them in the
* protocol structure.
*/
-static void __sctp_get_local_addr_list(void)
+static void sctp_get_local_addr_list(void)
{
struct net_device *dev;
struct list_head *pos;
@@ -179,17 +179,8 @@ static void __sctp_get_local_addr_list(void)
read_unlock(&dev_base_lock);
}
-static void sctp_get_local_addr_list(void)
-{
- unsigned long flags;
-
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- __sctp_get_local_addr_list();
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
-}
-
/* Free the existing local addresses. */
-static void __sctp_free_local_addr_list(void)
+static void sctp_free_local_addr_list(void)
{
struct sctp_sockaddr_entry *addr;
struct list_head *pos, *temp;
@@ -201,27 +192,15 @@ static void __sctp_free_local_addr_list(void)
}
}
-/* Free the existing local addresses. */
-static void sctp_free_local_addr_list(void)
-{
- unsigned long flags;
-
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- __sctp_free_local_addr_list();
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
-}
-
/* Copy the local addresses which are valid for 'scope' into 'bp'. */
int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
gfp_t gfp, int copy_flags)
{
struct sctp_sockaddr_entry *addr;
int error = 0;
- struct list_head *pos;
- unsigned long flags;
+ struct list_head *pos, *temp;
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- list_for_each(pos, &sctp_local_addr_list) {
+ list_for_each_safe(pos, temp, &sctp_local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if (sctp_in_scope(&addr->a, scope)) {
/* Now that the address is in scope, check to see if
@@ -242,7 +221,6 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
}
end_copy:
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
return error;
}
@@ -622,18 +600,36 @@ static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr));
}
-/* Event handler for inet address addition/deletion events.
- * Basically, whenever there is an event, we re-build our local address list.
- */
-int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
- void *ptr)
+/* Event handler for inet address addition/deletion events. */
+static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
+ void *ptr)
{
- unsigned long flags;
+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+ struct sctp_sockaddr_entry *addr;
+ struct list_head *pos, *temp;
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- __sctp_free_local_addr_list();
- __sctp_get_local_addr_list();
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
+ switch (ev) {
+ case NETDEV_UP:
+ addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+ if (addr) {
+ addr->a.v4.sin_family = AF_INET;
+ addr->a.v4.sin_port = 0;
+ addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
+ list_add_tail(&addr->list, &sctp_local_addr_list);
+ }
+ break;
+ case NETDEV_DOWN:
+ list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) {
+ list_del(pos);
+ kfree(addr);
+ break;
+ }
+ }
+
+ break;
+ }
return NOTIFY_DONE;
}
@@ -808,7 +804,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
- return ip_queue_xmit(skb, skb->sk, ipfragok);
+ return ip_queue_xmit(skb, ipfragok);
}
static struct sctp_af sctp_ipv4_specific;
@@ -1172,13 +1168,12 @@ SCTP_STATIC __init int sctp_init(void)
/* Initialize the local address list. */
INIT_LIST_HEAD(&sctp_local_addr_list);
- spin_lock_init(&sctp_local_addr_lock);
+
+ sctp_get_local_addr_list();
/* Register notifier for inet address additions/deletions. */
register_inetaddr_notifier(&sctp_inetaddr_notifier);
- sctp_get_local_addr_list();
-
__unsafe(THIS_MODULE);
status = 0;
out:
@@ -1263,6 +1258,7 @@ module_exit(sctp_exit);
* __stringify doesn't likes enums, so use IPPROTO_SCTP value (132) directly.
*/
MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
+MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132");
MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
MODULE_LICENSE("GPL");
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 30927d3a597..0b1ddb1005a 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -124,8 +124,8 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
padlen = len % 4;
err.length = htons(len);
len += padlen;
- sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
- chunk->subh.err_hdr = sctp_addto_chunk(chunk, paylen, payload);
+ chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
+ sctp_addto_chunk(chunk, paylen, payload);
}
/* 3.3.2 Initiation (INIT) (1)
@@ -184,7 +184,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
struct sctp_sock *sp;
sctp_supported_addrs_param_t sat;
__be16 types[2];
- sctp_adaption_ind_param_t aiparam;
+ sctp_adaptation_ind_param_t aiparam;
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
@@ -249,9 +249,9 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
if (sctp_prsctp_enable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
- aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+ aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND;
aiparam.param_hdr.length = htons(sizeof(aiparam));
- aiparam.adaption_ind = htonl(sp->adaption_ind);
+ aiparam.adaptation_ind = htonl(sp->adaptation_ind);
sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
nodata:
kfree(addrs.v);
@@ -269,7 +269,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
sctp_cookie_param_t *cookie;
int cookie_len;
size_t chunksize;
- sctp_adaption_ind_param_t aiparam;
+ sctp_adaptation_ind_param_t aiparam;
retval = NULL;
@@ -323,9 +323,9 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
if (asoc->peer.prsctp_capable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
- aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+ aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND;
aiparam.param_hdr.length = htons(sizeof(aiparam));
- aiparam.adaption_ind = htonl(sctp_sk(asoc->base.sk)->adaption_ind);
+ aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind);
sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
/* We need to remove the const qualifier at this point. */
@@ -1300,8 +1300,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
/* Remember PR-SCTP capability. */
cookie->c.prsctp_capable = asoc->peer.prsctp_capable;
- /* Save adaption indication in the cookie. */
- cookie->c.adaption_ind = asoc->peer.adaption_ind;
+ /* Save adaptation indication in the cookie. */
+ cookie->c.adaptation_ind = asoc->peer.adaptation_ind;
/* Set an expiration time for the cookie. */
do_gettimeofday(&cookie->c.expiration);
@@ -1512,7 +1512,7 @@ no_hmac:
retval->addip_serial = retval->c.initial_tsn;
retval->adv_peer_ack_point = retval->ctsn_ack_point;
retval->peer.prsctp_capable = retval->c.prsctp_capable;
- retval->peer.adaption_ind = retval->c.adaption_ind;
+ retval->peer.adaptation_ind = retval->c.adaptation_ind;
/* The INIT stuff will be done by the side effects. */
return retval;
@@ -1562,7 +1562,7 @@ static int sctp_process_missing_param(const struct sctp_association *asoc,
if (*errp) {
report.num_missing = htonl(1);
report.type = paramtype;
- sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM,
+ sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
&report, sizeof(report));
}
@@ -1743,7 +1743,7 @@ static int sctp_verify_param(const struct sctp_association *asoc,
case SCTP_PARAM_HEARTBEAT_INFO:
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
- case SCTP_PARAM_ADAPTION_LAYER_IND:
+ case SCTP_PARAM_ADAPTATION_LAYER_IND:
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
@@ -1775,7 +1775,9 @@ int sctp_verify_init(const struct sctp_association *asoc,
/* Verify stream values are non-zero. */
if ((0 == peer_init->init_hdr.num_outbound_streams) ||
- (0 == peer_init->init_hdr.num_inbound_streams)) {
+ (0 == peer_init->init_hdr.num_inbound_streams) ||
+ (0 == peer_init->init_hdr.init_tag) ||
+ (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
sctp_process_inv_mandatory(asoc, chunk, errp);
return 0;
@@ -2098,8 +2100,8 @@ static int sctp_process_param(struct sctp_association *asoc,
asoc->peer.ecn_capable = 1;
break;
- case SCTP_PARAM_ADAPTION_LAYER_IND:
- asoc->peer.adaption_ind = param.aind->adaption_ind;
+ case SCTP_PARAM_ADAPTATION_LAYER_IND:
+ asoc->peer.adaptation_ind = param.aind->adaptation_ind;
break;
case SCTP_PARAM_FWD_TSN_SUPPORT:
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 7bbc6156e45..6db77d1329f 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -217,7 +217,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
asoc->peer.sack_needed = 0;
- error = sctp_outq_tail(&asoc->outqueue, sack);
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack));
/* Stop the SACK timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -621,7 +621,13 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* The receiver of the HEARTBEAT ACK should also perform an
* RTT measurement for that destination transport address
* using the time value carried in the HEARTBEAT ACK chunk.
+ * If the transport's rto_pending variable has been cleared,
+ * it was most likely due to a retransmit. However, we want
+ * to re-enable it to properly update the rto.
*/
+ if (t->rto_pending == 0)
+ t->rto_pending = 1;
+
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at));
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 27cc444aaf1..fbbc9e6a3b7 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -440,7 +440,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
sctp_init_chunk_t *initchunk;
- __u32 init_tag;
struct sctp_chunk *err_chunk;
struct sctp_packet *packet;
sctp_error_t error;
@@ -462,24 +461,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
- init_tag = ntohl(chunk->subh.init_hdr->init_tag);
-
- /* Verification Tag: 3.3.3
- * If the value of the Initiate Tag in a received INIT ACK
- * chunk is found to be 0, the receiver MUST treat it as an
- * error and close the association by transmitting an ABORT.
- */
- if (!init_tag) {
- struct sctp_chunk *reply = sctp_make_abort(asoc, chunk, 0);
- if (!reply)
- goto nomem;
-
- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
- return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM,
- ECONNREFUSED, asoc,
- chunk->transport);
- }
-
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -550,9 +531,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
SCTP_CHUNK(err_chunk));
return SCTP_DISPOSITION_CONSUME;
-
-nomem:
- return SCTP_DISPOSITION_NOMEM;
}
/*
@@ -688,12 +666,12 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
goto nomem_ev;
/* Sockets API Draft Section 5.3.1.6
- * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * When a peer sends a Adaptation Layer Indication parameter , SCTP
* delivers this notification to inform the application that of the
- * peers requested adaption layer.
+ * peers requested adaptation layer.
*/
- if (new_asoc->peer.adaption_ind) {
- ai_ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+ if (new_asoc->peer.adaptation_ind) {
+ ai_ev = sctp_ulpevent_make_adaptation_indication(new_asoc,
GFP_ATOMIC);
if (!ai_ev)
goto nomem_aiev;
@@ -820,12 +798,12 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
/* Sockets API Draft Section 5.3.1.6
- * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * When a peer sends a Adaptation Layer Indication parameter , SCTP
* delivers this notification to inform the application that of the
- * peers requested adaption layer.
+ * peers requested adaptation layer.
*/
- if (asoc->peer.adaption_ind) {
- ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+ if (asoc->peer.adaptation_ind) {
+ ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
if (!ev)
goto nomem;
@@ -1553,6 +1531,28 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep,
}
+/*
+ * Unexpected INIT-ACK handler.
+ *
+ * Section 5.2.3
+ * If an INIT ACK received by an endpoint in any state other than the
+ * COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk.
+ * An unexpected INIT ACK usually indicates the processing of an old or
+ * duplicated INIT chunk.
+*/
+sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg, sctp_cmd_seq_t *commands)
+{
+ /* Per the above section, we'll discard the chunk if we have an
+ * endpoint. If this is an OOTB INIT-ACK, treat it as such.
+ */
+ if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
+ return sctp_sf_ootb(ep, asoc, type, arg, commands);
+ else
+ return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
+}
/* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A')
*
@@ -1698,12 +1698,12 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
/* Sockets API Draft Section 5.3.1.6
- * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * When a peer sends a Adaptation Layer Indication parameter , SCTP
* delivers this notification to inform the application that of the
- * peers requested adaption layer.
+ * peers requested adaptation layer.
*/
- if (asoc->peer.adaption_ind) {
- ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+ if (asoc->peer.adaptation_ind) {
+ ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
if (!ev)
goto nomem_ev;
@@ -1791,12 +1791,12 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
goto nomem;
/* Sockets API Draft Section 5.3.1.6
- * When a peer sends a Adaption Layer Indication parameter,
+ * When a peer sends a Adaptation Layer Indication parameter,
* SCTP delivers this notification to inform the application
- * that of the peers requested adaption layer.
+ * that of the peers requested adaptation layer.
*/
- if (asoc->peer.adaption_ind) {
- ai_ev = sctp_ulpevent_make_adaption_indication(asoc,
+ if (asoc->peer.adaptation_ind) {
+ ai_ev = sctp_ulpevent_make_adaptation_indication(asoc,
GFP_ATOMIC);
if (!ai_ev)
goto nomem;
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 733dd87b3a7..5f6cc7aa661 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -152,7 +152,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_EMPTY */ \
TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
+ TYPE_SCTP_FUNC(sctp_sf_do_5_2_3_initack), \
/* SCTP_STATE_COOKIE_WAIT */ \
TYPE_SCTP_FUNC(sctp_sf_do_5_1C_ack), \
/* SCTP_STATE_COOKIE_ECHOED */ \
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1e8132b8c4d..388d0fb1a37 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2731,17 +2731,57 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
return err;
}
-static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
+static int sctp_setsockopt_adaptation_layer(struct sock *sk, char __user *optval,
int optlen)
{
- struct sctp_setadaption adaption;
+ struct sctp_setadaptation adaptation;
- if (optlen != sizeof(struct sctp_setadaption))
+ if (optlen != sizeof(struct sctp_setadaptation))
return -EINVAL;
- if (copy_from_user(&adaption, optval, optlen))
+ if (copy_from_user(&adaptation, optval, optlen))
return -EFAULT;
- sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind;
+ sctp_sk(sk)->adaptation_ind = adaptation.ssb_adaptation_ind;
+
+ return 0;
+}
+
+/*
+ * 7.1.29. Set or Get the default context (SCTP_CONTEXT)
+ *
+ * The context field in the sctp_sndrcvinfo structure is normally only
+ * used when a failed message is retrieved holding the value that was
+ * sent down on the actual send call. This option allows the setting of
+ * a default context on an association basis that will be received on
+ * reading messages from the peer. This is especially helpful in the
+ * one-2-many model for an application to keep some reference to an
+ * internal state machine that is processing messages on the
+ * association. Note that the setting of this value only effects
+ * received messages from the peer and does not effect the value that is
+ * saved with outbound messages.
+ */
+static int sctp_setsockopt_context(struct sock *sk, char __user *optval,
+ int optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_sock *sp;
+ struct sctp_association *asoc;
+
+ if (optlen != sizeof(struct sctp_assoc_value))
+ return -EINVAL;
+ if (copy_from_user(&params, optval, optlen))
+ return -EFAULT;
+
+ sp = sctp_sk(sk);
+
+ if (params.assoc_id != 0) {
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc)
+ return -EINVAL;
+ asoc->default_rcv_context = params.assoc_value;
+ } else {
+ sp->default_rcv_context = params.assoc_value;
+ }
return 0;
}
@@ -2854,8 +2894,11 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_MAXSEG:
retval = sctp_setsockopt_maxseg(sk, optval, optlen);
break;
- case SCTP_ADAPTION_LAYER:
- retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
+ case SCTP_ADAPTATION_LAYER:
+ retval = sctp_setsockopt_adaptation_layer(sk, optval, optlen);
+ break;
+ case SCTP_CONTEXT:
+ retval = sctp_setsockopt_context(sk, optval, optlen);
break;
default:
@@ -3016,6 +3059,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp->default_context = 0;
sp->default_timetolive = 0;
+ sp->default_rcv_context = 0;
+
/* Initialize default setup parameters. These parameters
* can be modified with the SCTP_INITMSG socket option or
* overridden by the SCTP_INIT CMSG.
@@ -3078,7 +3123,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* User specified fragmentation limit. */
sp->user_frag = 0;
- sp->adaption_ind = 0;
+ sp->adaptation_ind = 0;
sp->pf = sctp_get_pf_specific(sk->sk_family);
@@ -3821,10 +3866,9 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
sctp_assoc_t id;
struct sctp_bind_addr *bp;
struct sctp_association *asoc;
- struct list_head *pos;
+ struct list_head *pos, *temp;
struct sctp_sockaddr_entry *addr;
rwlock_t *addr_lock;
- unsigned long flags;
int cnt = 0;
if (len != sizeof(sctp_assoc_t))
@@ -3859,8 +3903,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list);
if (sctp_is_any(&addr->a)) {
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- list_for_each(pos, &sctp_local_addr_list) {
+ list_for_each_safe(pos, temp, &sctp_local_addr_list) {
addr = list_entry(pos,
struct sctp_sockaddr_entry,
list);
@@ -3869,8 +3912,6 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
continue;
cnt++;
}
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
- flags);
} else {
cnt = 1;
}
@@ -3892,15 +3933,13 @@ done:
static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs,
void __user *to)
{
- struct list_head *pos;
+ struct list_head *pos, *next;
struct sctp_sockaddr_entry *addr;
- unsigned long flags;
union sctp_addr temp;
int cnt = 0;
int addrlen;
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- list_for_each(pos, &sctp_local_addr_list) {
+ list_for_each_safe(pos, next, &sctp_local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if ((PF_INET == sk->sk_family) &&
(AF_INET6 == addr->a.sa.sa_family))
@@ -3909,16 +3948,13 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
&temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
- if (copy_to_user(to, &temp, addrlen)) {
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
- flags);
+ if (copy_to_user(to, &temp, addrlen))
return -EFAULT;
- }
+
to += addrlen;
cnt ++;
if (cnt >= max_addrs) break;
}
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
return cnt;
}
@@ -3926,15 +3962,13 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add
static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
void __user **to, size_t space_left)
{
- struct list_head *pos;
+ struct list_head *pos, *next;
struct sctp_sockaddr_entry *addr;
- unsigned long flags;
union sctp_addr temp;
int cnt = 0;
int addrlen;
- sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
- list_for_each(pos, &sctp_local_addr_list) {
+ list_for_each_safe(pos, next, &sctp_local_addr_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
if ((PF_INET == sk->sk_family) &&
(AF_INET6 == addr->a.sa.sa_family))
@@ -3945,16 +3979,13 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
if(space_left<addrlen)
return -ENOMEM;
- if (copy_to_user(*to, &temp, addrlen)) {
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
- flags);
+ if (copy_to_user(*to, &temp, addrlen))
return -EFAULT;
- }
+
*to += addrlen;
cnt ++;
space_left -= addrlen;
}
- sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
return cnt;
}
@@ -4179,21 +4210,21 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
}
/*
- * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
+ * 7.1.11 Set Adaptation Layer Indicator (SCTP_ADAPTATION_LAYER)
*
- * Requests that the local endpoint set the specified Adaption Layer
+ * Requests that the local endpoint set the specified Adaptation Layer
* Indication parameter for all future INIT and INIT-ACK exchanges.
*/
-static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
+static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct sctp_setadaption adaption;
+ struct sctp_setadaptation adaptation;
- if (len != sizeof(struct sctp_setadaption))
+ if (len != sizeof(struct sctp_setadaptation))
return -EINVAL;
- adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind;
- if (copy_to_user(optval, &adaption, len))
+ adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind;
+ if (copy_to_user(optval, &adaptation, len))
return -EFAULT;
return 0;
@@ -4435,6 +4466,42 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
}
/*
+ * 7.1.29. Set or Get the default context (SCTP_CONTEXT)
+ * (chapter and verse is quoted at sctp_setsockopt_context())
+ */
+static int sctp_getsockopt_context(struct sock *sk, int len,
+ char __user *optval, int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_sock *sp;
+ struct sctp_association *asoc;
+
+ if (len != sizeof(struct sctp_assoc_value))
+ return -EINVAL;
+
+ if (copy_from_user(&params, optval, len))
+ return -EFAULT;
+
+ sp = sctp_sk(sk);
+
+ if (params.assoc_id != 0) {
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc)
+ return -EINVAL;
+ params.assoc_value = asoc->default_rcv_context;
+ } else {
+ params.assoc_value = sp->default_rcv_context;
+ }
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &params, len))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
* 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
*
* This socket option specifies the maximum size to put in any outgoing
@@ -4568,10 +4635,13 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_peer_addr_info(sk, len, optval,
optlen);
break;
- case SCTP_ADAPTION_LAYER:
- retval = sctp_getsockopt_adaption_layer(sk, len, optval,
+ case SCTP_ADAPTATION_LAYER:
+ retval = sctp_getsockopt_adaptation_layer(sk, len, optval,
optlen);
break;
+ case SCTP_CONTEXT:
+ retval = sctp_getsockopt_context(sk, len, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index e255a709f1b..445e07a7ac4 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -609,31 +609,31 @@ fail:
return NULL;
}
-/* Create and initialize a SCTP_ADAPTION_INDICATION notification.
+/* Create and initialize a SCTP_ADAPTATION_INDICATION notification.
*
* Socket Extensions for SCTP
- * 5.3.1.6 SCTP_ADAPTION_INDICATION
+ * 5.3.1.6 SCTP_ADAPTATION_INDICATION
*/
-struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
+struct sctp_ulpevent *sctp_ulpevent_make_adaptation_indication(
const struct sctp_association *asoc, gfp_t gfp)
{
struct sctp_ulpevent *event;
- struct sctp_adaption_event *sai;
+ struct sctp_adaptation_event *sai;
struct sk_buff *skb;
- event = sctp_ulpevent_new(sizeof(struct sctp_adaption_event),
+ event = sctp_ulpevent_new(sizeof(struct sctp_adaptation_event),
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
skb = sctp_event2skb(event);
- sai = (struct sctp_adaption_event *)
- skb_put(skb, sizeof(struct sctp_adaption_event));
+ sai = (struct sctp_adaptation_event *)
+ skb_put(skb, sizeof(struct sctp_adaptation_event));
- sai->sai_type = SCTP_ADAPTION_INDICATION;
+ sai->sai_type = SCTP_ADAPTATION_INDICATION;
sai->sai_flags = 0;
- sai->sai_length = sizeof(struct sctp_adaption_event);
- sai->sai_adaption_ind = asoc->peer.adaption_ind;
+ sai->sai_length = sizeof(struct sctp_adaptation_event);
+ sai->sai_adaptation_ind = asoc->peer.adaptation_ind;
sctp_ulpevent_set_owner(event, asoc);
sai->sai_assoc_id = sctp_assoc2id(asoc);
@@ -849,8 +849,10 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
*/
sinfo.sinfo_assoc_id = sctp_assoc2id(event->asoc);
+ /* context value that is set via SCTP_CONTEXT socket option. */
+ sinfo.sinfo_context = event->asoc->default_rcv_context;
+
/* These fields are not used while receiving. */
- sinfo.sinfo_context = 0;
sinfo.sinfo_timetolive = 0;
put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV,
diff --git a/net/socket.c b/net/socket.c
index 29ea1de43ec..4e396312f8d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -362,20 +362,20 @@ static int sock_attach_fd(struct socket *sock, struct file *file)
this.name = name;
this.hash = 0;
- file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
- if (unlikely(!file->f_dentry))
+ file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
+ if (unlikely(!file->f_path.dentry))
return -ENOMEM;
- file->f_dentry->d_op = &sockfs_dentry_operations;
+ file->f_path.dentry->d_op = &sockfs_dentry_operations;
/*
* We dont want to push this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on sockets
*/
- file->f_dentry->d_flags &= ~DCACHE_UNHASHED;
- d_instantiate(file->f_dentry, SOCK_INODE(sock));
- file->f_vfsmnt = mntget(sock_mnt);
- file->f_mapping = file->f_dentry->d_inode->i_mapping;
+ file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
+ d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
+ file->f_path.mnt = mntget(sock_mnt);
+ file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
sock->file = file;
file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
@@ -413,7 +413,7 @@ static struct socket *sock_from_file(struct file *file, int *err)
if (file->f_op == &socket_file_ops)
return file->private_data; /* set in sock_map_fd */
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (!S_ISSOCK(inode->i_mode)) {
*err = -ENOTSOCK;
return NULL;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index a02ecc1f230..e1a104abb78 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -501,7 +501,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
if (!buf)
goto out;
- clnt = RPC_I(filp->f_dentry->d_inode)->private;
+ clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
err = -EFAULT;
if (copy_from_user(buf, src, mlen))
goto err;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 41465072d0b..8ef3f1c1943 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -228,7 +228,7 @@ static int __init init_spkm3_module(void)
status = gss_mech_register(&gss_spkm3_mech);
if (status)
printk("Failed to register spkm3 gss mechanism!\n");
- return 0;
+ return status;
}
static void __exit cleanup_spkm3_module(void)
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 700353b330f..066c64a97fd 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -804,19 +804,19 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
integ_len = svc_getnl(&buf->head[0]);
if (integ_len & 3)
- goto out;
+ return stat;
if (integ_len > buf->len)
- goto out;
+ return stat;
if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len))
BUG();
/* copy out mic... */
if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
BUG();
if (mic.len > RPC_MAX_AUTH_SIZE)
- goto out;
+ return stat;
mic.data = kmalloc(mic.len, GFP_KERNEL);
if (!mic.data)
- goto out;
+ return stat;
if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
goto out;
maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
@@ -826,6 +826,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
goto out;
stat = 0;
out:
+ kfree(mic.data);
return stat;
}
@@ -1065,7 +1066,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
}
switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
case -EAGAIN:
- goto drop;
+ case -ETIMEDOUT:
case -ENOENT:
goto drop;
case 0:
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index d96fd466a9a..14274490f92 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -34,7 +34,7 @@
#define RPCDBG_FACILITY RPCDBG_CACHE
-static void cache_defer_req(struct cache_req *req, struct cache_head *item);
+static int cache_defer_req(struct cache_req *req, struct cache_head *item);
static void cache_revisit_request(struct cache_head *item);
static void cache_init(struct cache_head *h)
@@ -185,6 +185,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
*
* Returns 0 if the cache_head can be used, or cache_puts it and returns
* -EAGAIN if upcall is pending,
+ * -ETIMEDOUT if upcall failed and should be retried,
* -ENOENT if cache entry was negative
*/
int cache_check(struct cache_detail *detail,
@@ -236,7 +237,8 @@ int cache_check(struct cache_detail *detail,
}
if (rv == -EAGAIN)
- cache_defer_req(rqstp, h);
+ if (cache_defer_req(rqstp, h) != 0)
+ rv = -ETIMEDOUT;
if (rv)
cache_put(h, detail);
@@ -523,14 +525,21 @@ static LIST_HEAD(cache_defer_list);
static struct list_head cache_defer_hash[DFR_HASHSIZE];
static int cache_defer_cnt;
-static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+static int cache_defer_req(struct cache_req *req, struct cache_head *item)
{
struct cache_deferred_req *dreq;
int hash = DFR_HASH(item);
+ if (cache_defer_cnt >= DFR_MAX) {
+ /* too much in the cache, randomly drop this one,
+ * or continue and drop the oldest below
+ */
+ if (net_random()&1)
+ return -ETIMEDOUT;
+ }
dreq = req->defer(req);
if (dreq == NULL)
- return;
+ return -ETIMEDOUT;
dreq->item = item;
dreq->recv_time = get_seconds();
@@ -546,17 +555,8 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
/* it is in, now maybe clean up */
dreq = NULL;
if (++cache_defer_cnt > DFR_MAX) {
- /* too much in the cache, randomly drop
- * first or last
- */
- if (net_random()&1)
- dreq = list_entry(cache_defer_list.next,
- struct cache_deferred_req,
- recent);
- else
- dreq = list_entry(cache_defer_list.prev,
- struct cache_deferred_req,
- recent);
+ dreq = list_entry(cache_defer_list.prev,
+ struct cache_deferred_req, recent);
list_del(&dreq->recent);
list_del(&dreq->hash);
cache_defer_cnt--;
@@ -571,6 +571,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
/* must have just been validated... */
cache_revisit_request(item);
}
+ return 0;
}
static void cache_revisit_request(struct cache_head *item)
@@ -670,7 +671,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
struct cache_reader *rp = filp->private_data;
struct cache_request *rq;
- struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
+ struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
int err;
if (count == 0)
@@ -747,7 +748,7 @@ cache_write(struct file *filp, const char __user *buf, size_t count,
loff_t *ppos)
{
int err;
- struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
+ struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
if (count == 0)
return 0;
@@ -778,7 +779,7 @@ cache_poll(struct file *filp, poll_table *wait)
unsigned int mask;
struct cache_reader *rp = filp->private_data;
struct cache_queue *cq;
- struct cache_detail *cd = PDE(filp->f_dentry->d_inode)->data;
+ struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data;
poll_wait(filp, &queue_wait, wait);
@@ -1254,7 +1255,7 @@ static struct file_operations content_file_operations = {
static ssize_t read_flush(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
+ struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data;
char tbuf[20];
unsigned long p = *ppos;
int len;
@@ -1275,7 +1276,7 @@ static ssize_t read_flush(struct file *file, char __user *buf,
static ssize_t write_flush(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
- struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
+ struct cache_detail *cd = PDE(file->f_path.dentry->d_inode)->data;
char tbuf[20];
char *ep;
long flushtime;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index aba528b9ae7..16c9fbc1db6 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -490,16 +490,14 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
/* Set up the call info struct and execute the task */
status = task->tk_status;
- if (status != 0) {
- rpc_release_task(task);
+ if (status != 0)
goto out;
- }
atomic_inc(&task->tk_count);
status = rpc_execute(task);
if (status == 0)
status = task->tk_status;
- rpc_put_task(task);
out:
+ rpc_put_task(task);
rpc_restore_sigmask(&oldset);
return status;
}
@@ -537,7 +535,7 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
if (status == 0)
rpc_execute(task);
else
- rpc_release_task(task);
+ rpc_put_task(task);
rpc_restore_sigmask(&oldset);
return status;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 19703aa9659..89273d35e0c 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -214,7 +214,7 @@ out:
static ssize_t
rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct rpc_inode *rpci = RPC_I(inode);
struct rpc_pipe_msg *msg;
int res = 0;
@@ -257,7 +257,7 @@ out_unlock:
static ssize_t
rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct rpc_inode *rpci = RPC_I(inode);
int res;
@@ -275,7 +275,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
struct rpc_inode *rpci;
unsigned int mask = 0;
- rpci = RPC_I(filp->f_dentry->d_inode);
+ rpci = RPC_I(filp->f_path.dentry->d_inode);
poll_wait(filp, &rpci->waitq, wait);
mask = POLLOUT | POLLWRNORM;
@@ -290,7 +290,7 @@ static int
rpc_pipe_ioctl(struct inode *ino, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+ struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
int len;
switch (cmd) {
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 79bc4cdf5d4..fc083f0b354 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -42,6 +42,7 @@ static mempool_t *rpc_buffer_mempool __read_mostly;
static void __rpc_default_timer(struct rpc_task *task);
static void rpciod_killall(void);
static void rpc_async_schedule(struct work_struct *);
+static void rpc_release_task(struct rpc_task *task);
/*
* RPC tasks sit here while waiting for conditions to improve.
@@ -896,7 +897,7 @@ void rpc_put_task(struct rpc_task *task)
}
EXPORT_SYMBOL(rpc_put_task);
-void rpc_release_task(struct rpc_task *task)
+static void rpc_release_task(struct rpc_task *task)
{
#ifdef RPC_DEBUG
BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index eb44ec929ca..4c161121111 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -26,7 +26,6 @@
#include <linux/sunrpc/clnt.h>
#define RPCDBG_FACILITY RPCDBG_SVCDSP
-#define RPC_PARANOIA 1
/*
* Mode for mapping cpus to pools.
@@ -308,7 +307,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
serv->sv_nrpools = npools;
serv->sv_pools =
- kcalloc(sizeof(struct svc_pool), serv->sv_nrpools,
+ kcalloc(serv->sv_nrpools, sizeof(struct svc_pool),
GFP_KERNEL);
if (!serv->sv_pools) {
kfree(serv);
@@ -872,15 +871,15 @@ svc_process(struct svc_rqst *rqstp)
return 0;
err_short_len:
-#ifdef RPC_PARANOIA
- printk("svc: short len %Zd, dropping request\n", argv->iov_len);
-#endif
+ if (net_ratelimit())
+ printk("svc: short len %Zd, dropping request\n", argv->iov_len);
+
goto dropit; /* drop request */
err_bad_dir:
-#ifdef RPC_PARANOIA
- printk("svc: bad direction %d, dropping request\n", dir);
-#endif
+ if (net_ratelimit())
+ printk("svc: bad direction %d, dropping request\n", dir);
+
serv->sv_stats->rpcbadfmt++;
goto dropit; /* drop request */
@@ -909,9 +908,10 @@ err_bad_prog:
goto sendit;
err_bad_vers:
-#ifdef RPC_PARANOIA
- printk("svc: unknown version (%d)\n", vers);
-#endif
+ if (net_ratelimit())
+ printk("svc: unknown version (%d for prog %d, %s)\n",
+ vers, prog, progp->pg_name);
+
serv->sv_stats->rpcbadfmt++;
svc_putnl(resv, RPC_PROG_MISMATCH);
svc_putnl(resv, progp->pg_lovers);
@@ -919,17 +919,17 @@ err_bad_vers:
goto sendit;
err_bad_proc:
-#ifdef RPC_PARANOIA
- printk("svc: unknown procedure (%d)\n", proc);
-#endif
+ if (net_ratelimit())
+ printk("svc: unknown procedure (%d)\n", proc);
+
serv->sv_stats->rpcbadfmt++;
svc_putnl(resv, RPC_PROC_UNAVAIL);
goto sendit;
err_garbage:
-#ifdef RPC_PARANOIA
- printk("svc: failed to decode args\n");
-#endif
+ if (net_ratelimit())
+ printk("svc: failed to decode args\n");
+
rpc_stat = rpc_garbage_args;
err_bad:
serv->sv_stats->rpcbadfmt++;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index a0a953a430c..0d1e8fb83b9 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -53,6 +53,10 @@ struct auth_domain *unix_domain_find(char *name)
return NULL;
kref_init(&new->h.ref);
new->h.name = kstrdup(name, GFP_KERNEL);
+ if (new->h.name == NULL) {
+ kfree(new);
+ return NULL;
+ }
new->h.flavour = &svcauth_unix;
new->addr_changes = 0;
rv = auth_domain_lookup(name, &new->h);
@@ -435,6 +439,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
default:
BUG();
case -EAGAIN:
+ case -ETIMEDOUT:
return SVC_DROP;
case -ENOENT:
return SVC_DENIED;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 99f54fb6d66..ff1f8bf680a 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1062,15 +1062,19 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
* bit set in the fragment length header.
* But apparently no known nfs clients send fragmented
* records. */
- printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx (non-terminal)\n",
- (unsigned long) svsk->sk_reclen);
+ if (net_ratelimit())
+ printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+ " (non-terminal)\n",
+ (unsigned long) svsk->sk_reclen);
goto err_delete;
}
svsk->sk_reclen &= 0x7fffffff;
dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
if (svsk->sk_reclen > serv->sv_max_mesg) {
- printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx (large)\n",
- (unsigned long) svsk->sk_reclen);
+ if (net_ratelimit())
+ printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+ " (large)\n",
+ (unsigned long) svsk->sk_reclen);
goto err_delete;
}
}
@@ -1278,6 +1282,8 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
schedule_timeout_uninterruptible(msecs_to_jiffies(500));
rqstp->rq_pages[i] = p;
}
+ rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */
+ BUG_ON(pages >= RPCSVC_MAXPAGES);
/* Make arg->head point to first page and arg->pages point to rest */
arg = &rqstp->rq_arg;
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 458a2c46cef..baf55c459c8 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -208,7 +208,7 @@ static void cfg_cmd_event(struct tipc_cmd_msg *msg,
if (mng.link_subscriptions > 64)
break;
- sub = (struct subscr_data *)kmalloc(sizeof(*sub),
+ sub = kmalloc(sizeof(*sub),
GFP_ATOMIC);
if (sub == NULL) {
warn("Memory squeeze; dropped remote link subscription\n");
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 746c2f4a5fa..f14ad6635fc 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -96,7 +96,7 @@ atomic_t unix_tot_inflight = ATOMIC_INIT(0);
static struct sock *unix_get_socket(struct file *filp)
{
struct sock *u_sock = NULL;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
/*
* Socket ?
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 52a2726d327..b5c80b18990 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -484,8 +484,6 @@ out:
return sk;
}
-void x25_init_timers(struct sock *sk);
-
static int x25_create(struct socket *sock, int protocol)
{
struct sock *sk;
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 47b68a30167..328d80f000a 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -56,6 +56,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb)
sk_add_backlog(sk, skb);
}
bh_unlock_sock(sk);
+ sock_put(sk);
return queued;
}
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 9f42b9c9de3..27f5cc7966f 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -254,7 +254,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
* They want reverse charging, we won't accept it.
*/
if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
- SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
+ SOCK_DEBUG(sk, "X.25: rejecting reverse charging request\n");
return -1;
}
@@ -262,29 +262,29 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
if (theirs.throughput) {
if (theirs.throughput < ours->throughput) {
- SOCK_DEBUG(sk, "X.25: throughput negotiated down");
+ SOCK_DEBUG(sk, "X.25: throughput negotiated down\n");
new->throughput = theirs.throughput;
}
}
if (theirs.pacsize_in && theirs.pacsize_out) {
if (theirs.pacsize_in < ours->pacsize_in) {
- SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down");
+ SOCK_DEBUG(sk, "X.25: packet size inwards negotiated down\n");
new->pacsize_in = theirs.pacsize_in;
}
if (theirs.pacsize_out < ours->pacsize_out) {
- SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down");
+ SOCK_DEBUG(sk, "X.25: packet size outwards negotiated down\n");
new->pacsize_out = theirs.pacsize_out;
}
}
if (theirs.winsize_in && theirs.winsize_out) {
if (theirs.winsize_in < ours->winsize_in) {
- SOCK_DEBUG(sk, "X.25: window size inwards negotiated down");
+ SOCK_DEBUG(sk, "X.25: window size inwards negotiated down\n");
new->winsize_in = theirs.winsize_in;
}
if (theirs.winsize_out < ours->winsize_out) {
- SOCK_DEBUG(sk, "X.25: window size outwards negotiated down");
+ SOCK_DEBUG(sk, "X.25: window size outwards negotiated down\n");
new->winsize_out = theirs.winsize_out;
}
}
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 6b381fc0383..f1cf3402e75 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -399,7 +399,8 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
if (!probe)
break;
- status = crypto_has_alg(name, type, mask | CRYPTO_ALG_ASYNC);
+ status = crypto_has_alg(list[i].name, type,
+ mask | CRYPTO_ALG_ASYNC);
if (!status)
break;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index bebd40e5a62..b7e537fe2d7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -650,19 +650,18 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
struct xfrm_policy *pol;
struct xfrm_policy *delpol;
struct hlist_head *chain;
- struct hlist_node *entry, *newpos, *last;
+ struct hlist_node *entry, *newpos;
struct dst_entry *gc_list;
write_lock_bh(&xfrm_policy_lock);
chain = policy_hash_bysel(&policy->selector, policy->family, dir);
delpol = NULL;
newpos = NULL;
- last = NULL;
hlist_for_each_entry(pol, entry, chain, bydst) {
- if (!delpol &&
- pol->type == policy->type &&
+ if (pol->type == policy->type &&
!selector_cmp(&pol->selector, &policy->selector) &&
- xfrm_sec_ctx_match(pol->security, policy->security)) {
+ xfrm_sec_ctx_match(pol->security, policy->security) &&
+ !WARN_ON(delpol)) {
if (excl) {
write_unlock_bh(&xfrm_policy_lock);
return -EEXIST;
@@ -671,17 +670,12 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
if (policy->priority > pol->priority)
continue;
} else if (policy->priority >= pol->priority) {
- last = &pol->bydst;
+ newpos = &pol->bydst;
continue;
}
- if (!newpos)
- newpos = &pol->bydst;
if (delpol)
break;
- last = &pol->bydst;
}
- if (!newpos)
- newpos = last;
if (newpos)
hlist_add_after(newpos, &policy->bydst);
else
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index e5372b11fc8..82f36d396fc 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -434,18 +434,19 @@ error_no_put:
return NULL;
}
-static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
struct xfrm_state *x;
int err;
struct km_event c;
- err = verify_newsa_info(p, (struct rtattr **)xfrma);
+ err = verify_newsa_info(p, xfrma);
if (err)
return err;
- x = xfrm_state_construct(p, (struct rtattr **)xfrma, &err);
+ x = xfrm_state_construct(p, xfrma, &err);
if (!x)
return err;
@@ -507,14 +508,15 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
return x;
}
-static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_state *x;
int err = -ESRCH;
struct km_event c;
struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
- x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err);
+ x = xfrm_user_state_lookup(p, xfrma, &err);
if (x == NULL)
return err;
@@ -672,14 +674,15 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
return skb;
}
-static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
struct xfrm_state *x;
struct sk_buff *resp_skb;
int err = -ESRCH;
- x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err);
+ x = xfrm_user_state_lookup(p, xfrma, &err);
if (x == NULL)
goto out_noput;
@@ -718,7 +721,8 @@ static int verify_userspi_info(struct xfrm_userspi_info *p)
return 0;
}
-static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_state *x;
struct xfrm_userspi_info *p;
@@ -1013,7 +1017,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p,
return NULL;
}
-static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
struct xfrm_policy *xp;
@@ -1024,11 +1029,11 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
err = verify_newpolicy_info(p);
if (err)
return err;
- err = verify_sec_ctx_len((struct rtattr **)xfrma);
+ err = verify_sec_ctx_len(xfrma);
if (err)
return err;
- xp = xfrm_policy_construct(p, (struct rtattr **)xfrma, &err);
+ xp = xfrm_policy_construct(p, xfrma, &err);
if (!xp)
return err;
@@ -1227,7 +1232,8 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
return skb;
}
-static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_policy *xp;
struct xfrm_userpolicy_id *p;
@@ -1239,7 +1245,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
p = NLMSG_DATA(nlh);
delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;
- err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
+ err = copy_from_user_policy_type(&type, xfrma);
if (err)
return err;
@@ -1250,11 +1256,10 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
if (p->index)
xp = xfrm_policy_byid(type, p->dir, p->index, delete);
else {
- struct rtattr **rtattrs = (struct rtattr **)xfrma;
- struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+ struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
struct xfrm_policy tmp;
- err = verify_sec_ctx_len(rtattrs);
+ err = verify_sec_ctx_len(xfrma);
if (err)
return err;
@@ -1302,7 +1307,8 @@ out:
return err;
}
-static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct km_event c;
struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
@@ -1367,7 +1373,8 @@ nlmsg_failure:
return -1;
}
-static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_state *x;
struct sk_buff *r_skb;
@@ -1415,7 +1422,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
return err;
}
-static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_state *x;
struct km_event c;
@@ -1439,7 +1447,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
goto out;
spin_lock_bh(&x->lock);
- err = xfrm_update_ae_params(x,(struct rtattr **)xfrma);
+ err = xfrm_update_ae_params(x, xfrma);
spin_unlock_bh(&x->lock);
if (err < 0)
goto out;
@@ -1455,14 +1463,15 @@ out:
return err;
}
-static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct km_event c;
u8 type = XFRM_POLICY_TYPE_MAIN;
int err;
struct xfrm_audit audit_info;
- err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
+ err = copy_from_user_policy_type(&type, xfrma);
if (err)
return err;
@@ -1477,7 +1486,8 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x
return 0;
}
-static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_policy *xp;
struct xfrm_user_polexpire *up = NLMSG_DATA(nlh);
@@ -1485,18 +1495,17 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void *
u8 type = XFRM_POLICY_TYPE_MAIN;
int err = -ENOENT;
- err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
+ err = copy_from_user_policy_type(&type, xfrma);
if (err)
return err;
if (p->index)
xp = xfrm_policy_byid(type, p->dir, p->index, 0);
else {
- struct rtattr **rtattrs = (struct rtattr **)xfrma;
- struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+ struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
struct xfrm_policy tmp;
- err = verify_sec_ctx_len(rtattrs);
+ err = verify_sec_ctx_len(xfrma);
if (err)
return err;
@@ -1537,7 +1546,8 @@ out:
return err;
}
-static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_state *x;
int err;
@@ -1568,7 +1578,8 @@ out:
return err;
}
-static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct rtattr **xfrma)
{
struct xfrm_policy *xp;
struct xfrm_user_tmpl *ut;
@@ -1647,7 +1658,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
#undef XMSGSIZE
static struct xfrm_link {
- int (*doit)(struct sk_buff *, struct nlmsghdr *, void **);
+ int (*doit)(struct sk_buff *, struct nlmsghdr *, struct rtattr **);
int (*dump)(struct sk_buff *, struct netlink_callback *);
} xfrm_dispatch[XFRM_NR_MSGTYPES] = {
[XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa },
@@ -1735,7 +1746,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err
if (link->doit == NULL)
goto err_einval;
- *errp = link->doit(skb, nlh, (void **) &xfrma);
+ *errp = link->doit(skb, nlh, xfrma);
return *errp;
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 4f5ff19b992..f01f8c07285 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -56,6 +56,9 @@ endef
# gcc support functions
# See documentation in Documentation/kbuild/makefiles.txt
+# output directory for tests below
+TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+
# as-option
# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
@@ -66,9 +69,11 @@ as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
# as-instr
# Usage: cflags-y += $(call as-instr, instr, option1, option2)
-as-instr = $(shell if echo -e "$(1)" | $(AS) >/dev/null 2>&1 -W -Z -o astest$$$$.out ; \
- then echo "$(2)"; else echo "$(3)"; fi; \
- rm -f astest$$$$.out)
+as-instr = $(shell if echo -e "$(1)" | \
+ $(CC) $(AFLAGS) -c -xassembler - \
+ -o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \
+ then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \
+ else echo "$(3)"; fi)
# cc-option
# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
@@ -97,10 +102,10 @@ cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
# ld-option
# Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
-ld-option = $(shell if $(CC) $(1) \
- -nostdlib -o ldtest$$$$.out -xc /dev/null \
- > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi; \
- rm -f ldtest$$$$.out)
+ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
+ -o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \
+ then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \
+ else echo "$(2)"; fi)
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 4241e0dfeea..f7b6705fd6a 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -109,7 +109,7 @@ quiet_cmd_mkdir = MKDIR $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
quiet_cmd_gen = GEN $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
cmd_gen = \
FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@) \
-STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z. A-Z_`; \
+STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z.- A-Z__`; \
(echo "/* File autogenerated by 'make headers_install' */" ; \
echo "\#ifndef $$STUBDEF" ; \
echo "\#define $$STUBDEF" ; \
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index f359b730c2c..8b809b264d1 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -265,7 +265,7 @@ static void write_src(void)
printf("#define ALGN .align 4\n");
printf("#endif\n");
- printf(".data\n");
+ printf("\t.section .rodata, \"a\"\n");
/* Provide proper symbols relocatability by their '_text'
* relativeness. The symbol names cannot be used to construct
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 4dcb8867b5f..124b341a18c 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -600,7 +600,7 @@ int main(int ac, char **av)
input_mode = ask_silent;
valid_stdin = 1;
}
- } else if (sym_change_count) {
+ } else if (conf_get_changed()) {
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 66b15ef0293..664fe29dace 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -100,7 +100,7 @@ int conf_read_simple(const char *name, int def)
in = zconf_fopen(name);
if (in)
goto load;
- sym_change_count++;
+ sym_add_change_count(1);
if (!sym_defconfig_list)
return 1;
@@ -312,7 +312,7 @@ int conf_read(const char *name)
struct expr *e;
int i, flags;
- sym_change_count = 0;
+ sym_set_change_count(0);
if (conf_read_simple(name, S_DEF_USER))
return 1;
@@ -364,7 +364,7 @@ int conf_read(const char *name)
sym->flags &= flags | ~SYMBOL_DEF_USER;
}
- sym_change_count += conf_warnings || conf_unsaved;
+ sym_add_change_count(conf_warnings || conf_unsaved);
return 0;
}
@@ -432,7 +432,7 @@ int conf_write(const char *name)
use_timestamp ? "# " : "",
use_timestamp ? ctime(&now) : "");
- if (!sym_change_count)
+ if (!conf_get_changed())
sym_clear_all_valid();
menu = rootmenu.list;
@@ -528,7 +528,7 @@ int conf_write(const char *name)
"# configuration written to %s\n"
"#\n"), newname);
- sym_change_count = 0;
+ sym_set_change_count(0);
return 0;
}
@@ -765,3 +765,30 @@ int conf_write_autoconf(void)
return 0;
}
+
+static int sym_change_count;
+static void (*conf_changed_callback)(void);
+
+void sym_set_change_count(int count)
+{
+ int _sym_change_count = sym_change_count;
+ sym_change_count = count;
+ if (conf_changed_callback &&
+ (bool)_sym_change_count != (bool)count)
+ conf_changed_callback();
+}
+
+void sym_add_change_count(int count)
+{
+ sym_set_change_count(count + sym_change_count);
+}
+
+bool conf_get_changed(void)
+{
+ return sym_change_count;
+}
+
+void conf_set_changed_callback(void (*fn)(void))
+{
+ conf_changed_callback = fn;
+}
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 7b0d3a93d5c..61d8166166e 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -38,8 +38,6 @@ static gboolean show_all = FALSE;
static gboolean show_debug = FALSE;
static gboolean resizeable = FALSE;
-static gboolean config_changed = FALSE;
-
static char nohelp_text[] =
N_("Sorry, no help available for this option yet.\n");
@@ -50,6 +48,8 @@ GtkWidget *text_w = NULL;
GtkWidget *hpaned = NULL;
GtkWidget *vpaned = NULL;
GtkWidget *back_btn = NULL;
+GtkWidget *save_btn = NULL;
+GtkWidget *save_menu_item = NULL;
GtkTextTag *tag1, *tag2;
GdkColor color;
@@ -75,7 +75,7 @@ static void display_tree_part(void);
static void update_tree(struct menu *src, GtkTreeIter * dst);
static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
static gchar **fill_row(struct menu *menu);
-
+static void conf_changed(void);
/* Helping/Debugging Functions */
@@ -224,6 +224,10 @@ void init_main_window(const gchar * glade_file)
gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget,
show_value);
+ save_btn = glade_xml_get_widget(xml, "button3");
+ save_menu_item = glade_xml_get_widget(xml, "save1");
+ conf_set_changed_callback(conf_changed);
+
style = gtk_widget_get_style(main_wnd);
widget = glade_xml_get_widget(xml, "toolbar1");
@@ -512,14 +516,14 @@ static void text_insert_msg(const char *title, const char *message)
/* Main Windows Callbacks */
-void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data);
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data);
gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
gpointer user_data)
{
GtkWidget *dialog, *label;
gint result;
- if (config_changed == FALSE)
+ if (!conf_get_changed())
return FALSE;
dialog = gtk_dialog_new_with_buttons(_("Warning !"),
@@ -543,7 +547,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
result = gtk_dialog_run(GTK_DIALOG(dialog));
switch (result) {
case GTK_RESPONSE_YES:
- on_save1_activate(NULL, NULL);
+ on_save_activate(NULL, NULL);
return FALSE;
case GTK_RESPONSE_NO:
return FALSE;
@@ -621,12 +625,10 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
}
-void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
+void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
{
if (conf_write(NULL))
text_insert_msg(_("Error"), _("Unable to save configuration !"));
-
- config_changed = FALSE;
}
@@ -819,12 +821,6 @@ void on_load_clicked(GtkButton * button, gpointer user_data)
}
-void on_save_clicked(GtkButton * button, gpointer user_data)
-{
- on_save1_activate(NULL, user_data);
-}
-
-
void on_single_clicked(GtkButton * button, gpointer user_data)
{
view_mode = SINGLE_VIEW;
@@ -899,7 +895,6 @@ static void renderer_edited(GtkCellRendererText * cell,
sym_set_string_value(sym, new_def);
- config_changed = TRUE;
update_tree(&rootmenu, NULL);
gtk_tree_path_free(path);
@@ -930,7 +925,6 @@ static void change_sym_value(struct menu *menu, gint col)
if (!sym_tristate_within_range(sym, newval))
newval = yes;
sym_set_tristate_value(sym, newval);
- config_changed = TRUE;
if (view_mode == FULL_VIEW)
update_tree(&rootmenu, NULL);
else if (view_mode == SPLIT_VIEW) {
@@ -1633,3 +1627,10 @@ int main(int ac, char *av[])
return 0;
}
+
+static void conf_changed(void)
+{
+ bool changed = conf_get_changed();
+ gtk_widget_set_sensitive(save_btn, changed);
+ gtk_widget_set_sensitive(save_menu_item, changed);
+}
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index f8744ed6496..803233fdd6d 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -70,7 +70,7 @@
<property name="tooltip" translatable="yes">Save the config in .config</property>
<property name="label" translatable="yes">_Save</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_save1_activate"/>
+ <signal name="activate" handler="on_save_activate"/>
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
@@ -380,7 +380,7 @@
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
- <signal name="clicked" handler="on_save_clicked"/>
+ <signal name="clicked" handler="on_save_activate"/>
</widget>
<packing>
<property name="expand">False</property>
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 2628023a1fe..9b2706a4154 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -65,6 +65,8 @@ char *zconf_curname(void);
/* confdata.c */
char *conf_get_default_confname(void);
+void sym_set_change_count(int count);
+void sym_add_change_count(int count);
/* kconfig_load.c */
void kconfig_load(void);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index a263746cfa7..15030770d1a 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -5,6 +5,8 @@ P(conf_read,int,(const char *name));
P(conf_read_simple,int,(const char *name, int));
P(conf_write,int,(const char *name));
P(conf_write_autoconf,int,(void));
+P(conf_get_changed,bool,(void));
+P(conf_set_changed_callback, void,(void (*fn)(void)));
/* menu.c */
P(rootmenu,struct menu,);
@@ -16,7 +18,6 @@ P(menu_get_parent_menu,struct menu *,(struct menu *menu));
/* symbol.c */
P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
-P(sym_change_count,int,);
P(sym_lookup,struct symbol *,(const char *name, int isconst));
P(sym_find,struct symbol *,(const char *name));
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 08a4c7af93e..3f9a1321b3e 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -890,14 +890,19 @@ int main(int ac, char **av)
do {
conf(&rootmenu);
dialog_clear();
- res = dialog_yesno(NULL,
- _("Do you wish to save your "
- "new kernel configuration?\n"
- "<ESC><ESC> to continue."),
- 6, 60);
+ if (conf_get_changed())
+ res = dialog_yesno(NULL,
+ _("Do you wish to save your "
+ "new kernel configuration?\n"
+ "<ESC><ESC> to continue."),
+ 6, 60);
+ else
+ res = -1;
} while (res == KEY_ESC);
end_dialog();
- if (res == 0) {
+
+ switch (res) {
+ case 0:
if (conf_write(NULL)) {
fprintf(stderr, _("\n\n"
"Error during writing of the kernel configuration.\n"
@@ -905,11 +910,13 @@ int main(int ac, char **av)
"\n\n"));
return 1;
}
+ case -1:
printf(_("\n\n"
"*** End of Linux kernel configuration.\n"
"*** Execute 'make' to build the kernel or try 'make help'."
"\n\n"));
- } else {
+ break;
+ default:
fprintf(stderr, _("\n\n"
"Your kernel configuration changes were NOT saved."
"\n\n"));
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index f5628c57640..c0ae0a7ddb4 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -38,6 +38,8 @@
static QApplication *configApp;
static ConfigSettings *configSettings;
+QAction *ConfigMainWindow::saveAction;
+
static inline QString qgettext(const char* str)
{
return QString::fromLocal8Bit(gettext(str));
@@ -915,7 +917,7 @@ void ConfigView::updateListAll(void)
}
ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
- : Parent(parent, name), menu(0)
+ : Parent(parent, name), menu(0), sym(0)
{
if (name) {
configSettings->beginGroup(name);
@@ -951,6 +953,7 @@ void ConfigInfoView::setInfo(struct menu *m)
if (menu == m)
return;
menu = m;
+ sym = NULL;
if (!menu)
clear();
else
@@ -1306,8 +1309,11 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(quitAction, SIGNAL(activated()), SLOT(close()));
QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
- QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
+ saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+ conf_set_changed_callback(conf_changed);
+ // Set saveAction's initial state
+ conf_changed();
QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this);
@@ -1585,7 +1591,7 @@ void ConfigMainWindow::showFullView(void)
*/
void ConfigMainWindow::closeEvent(QCloseEvent* e)
{
- if (!sym_change_count) {
+ if (!conf_get_changed()) {
e->accept();
return;
}
@@ -1658,6 +1664,12 @@ void ConfigMainWindow::saveSettings(void)
configSettings->writeSizes("/split2", split2->sizes());
}
+void ConfigMainWindow::conf_changed(void)
+{
+ if (saveAction)
+ saveAction->setEnabled(conf_get_changed());
+}
+
void fixup_rootmenu(struct menu *menu)
{
struct menu *child;
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 6a9e3b14c22..6fc1c5f1442 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -297,6 +297,9 @@ protected:
class ConfigMainWindow : public QMainWindow {
Q_OBJECT
+
+ static QAction *saveAction;
+ static void conf_changed(void);
public:
ConfigMainWindow(void);
public slots:
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index ee225ced2ce..8f06c474d80 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -30,7 +30,6 @@ struct symbol symbol_yes = {
.flags = SYMBOL_VALID,
};
-int sym_change_count;
struct symbol *sym_defconfig_list;
struct symbol *modules_sym;
tristate modules_val;
@@ -379,7 +378,7 @@ void sym_clear_all_valid(void)
for_all_symbols(i, sym)
sym->flags &= ~SYMBOL_VALID;
- sym_change_count++;
+ sym_add_change_count(1);
if (modules_sym)
sym_calc_value(modules_sym);
}
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 2fb0a4fc61d..d777fe85627 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -2135,7 +2135,7 @@ void conf_parse(const char *name)
sym_check_deps(sym);
}
- sym_change_count = 1;
+ sym_set_change_count(1);
}
const char *zconf_tokenname(int token)
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index ab44feb3c60..04a5864c03b 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -504,7 +504,7 @@ void conf_parse(const char *name)
sym_check_deps(sym);
}
- sym_change_count = 1;
+ sym_set_change_count(1);
}
const char *zconf_tokenname(int token)
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index df3b272f7ce..f50a70f550b 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1469,6 +1469,7 @@ sub push_parameter($$$) {
my $param = shift;
my $type = shift;
my $file = shift;
+ my $anon = 0;
my $param_name = $param;
$param_name =~ s/\[.*//;
@@ -1484,9 +1485,20 @@ sub push_parameter($$$) {
$param="void";
$parameterdescs{void} = "no arguments";
}
+ elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
+ # handle unnamed (anonymous) union or struct:
+ {
+ $type = $param;
+ $param = "{unnamed_" . $param. "}";
+ $parameterdescs{$param} = "anonymous\n";
+ $anon = 1;
+ }
+
# warn if parameter has no description
- # (but ignore ones starting with # as these are no parameters
- # but inline preprocessor statements
+ # (but ignore ones starting with # as these are not parameters
+ # but inline preprocessor statements);
+ # also ignore unnamed structs/unions;
+ if (!$anon) {
if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
$parameterdescs{$param_name} = $undescribed;
@@ -1500,6 +1512,7 @@ sub push_parameter($$$) {
" No description found for parameter '$param'\n";
++$warnings;
}
+ }
push @parameterlist, $param;
$parametertypes{$param} = $type;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index e26381e3fc0..47bef62eecd 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -582,9 +582,19 @@ static int strrcmp(const char *s, const char *sub)
* tosec = .init.text | .exit.text | .init.data
* fromsec = .data
* atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
+ *
+ * Pattern 3:
+ * Some symbols belong to init section but still it is ok to reference
+ * these from non-init sections as these symbols don't have any memory
+ * allocated for them and symbol address and value are same. So even
+ * if init section is freed, its ok to reference those symbols.
+ * For ex. symbols marking the init section boundaries.
+ * This pattern is identified by
+ * refsymname = __init_begin, _sinittext, _einittext
**/
static int secref_whitelist(const char *modname, const char *tosec,
- const char *fromsec, const char *atsym)
+ const char *fromsec, const char *atsym,
+ const char *refsymname)
{
int f1 = 1, f2 = 1;
const char **s;
@@ -595,6 +605,14 @@ static int secref_whitelist(const char *modname, const char *tosec,
"_ops",
"_probe",
"_probe_one",
+ "_console",
+ NULL
+ };
+
+ const char *pat3refsym[] = {
+ "__init_begin",
+ "_sinittext",
+ "_einittext",
NULL
};
@@ -628,6 +646,11 @@ static int secref_whitelist(const char *modname, const char *tosec,
if ((strcmp(fromsec, ".pci_fixup") == 0) &&
(strcmp(tosec, ".init.text") == 0))
return 1;
+
+ /* Check for pattern 3 */
+ for (s = pat3refsym; *s; s++)
+ if (strcmp(refsymname, *s) == 0)
+ return 1;
}
return 0;
}
@@ -737,7 +760,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
/* check whitelist - we may ignore it */
if (before &&
secref_whitelist(modname, secname, fromsec,
- elf->strtab + before->st_name))
+ elf->strtab + before->st_name, refsymname))
return;
if (before && after) {
@@ -998,6 +1021,7 @@ static int exit_section_ref_ok(const char *name)
"__bug_table", /* used by powerpc for BUG() */
".exitcall.exit",
".eh_frame",
+ ".parainstructions",
".stab",
"__ex_table",
".fixup",
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 44e9cd47054..65fb5e8ea94 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1120,8 +1120,8 @@ static int file_has_perm(struct task_struct *tsk,
{
struct task_security_struct *tsec = tsk->security;
struct file_security_struct *fsec = file->f_security;
- struct vfsmount *mnt = file->f_vfsmnt;
- struct dentry *dentry = file->f_dentry;
+ struct vfsmount *mnt = file->f_path.mnt;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct avc_audit_data ad;
int rc;
@@ -1581,7 +1581,7 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
static int selinux_bprm_set_security(struct linux_binprm *bprm)
{
struct task_security_struct *tsec;
- struct inode *inode = bprm->file->f_dentry->d_inode;
+ struct inode *inode = bprm->file->f_path.dentry->d_inode;
struct inode_security_struct *isec;
struct bprm_security_struct *bsec;
u32 newsid;
@@ -1621,10 +1621,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
}
AVC_AUDIT_DATA_INIT(&ad, FS);
- ad.u.fs.mnt = bprm->file->f_vfsmnt;
- ad.u.fs.dentry = bprm->file->f_dentry;
+ ad.u.fs.mnt = bprm->file->f_path.mnt;
+ ad.u.fs.dentry = bprm->file->f_path.dentry;
- if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
+ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
newsid = tsec->sid;
if (tsec->sid == newsid) {
@@ -1695,9 +1695,10 @@ static inline void flush_unauthorized_files(struct files_struct * files)
struct tty_struct *tty;
struct fdtable *fdt;
long j = -1;
+ int drop_tty = 0;
mutex_lock(&tty_mutex);
- tty = current->signal->tty;
+ tty = get_current_tty();
if (tty) {
file_list_lock();
file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
@@ -1707,15 +1708,17 @@ static inline void flush_unauthorized_files(struct files_struct * files)
than using file_has_perm, as this particular open
file may belong to another process and we are only
interested in the inode-based check here. */
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
if (inode_has_perm(current, inode,
FILE__READ | FILE__WRITE, NULL)) {
- /* Reset controlling tty. */
- current->signal->tty = NULL;
- current->signal->tty_old_pgrp = 0;
+ drop_tty = 1;
}
}
file_list_unlock();
+
+ /* Reset controlling tty. */
+ if (drop_tty)
+ proc_set_tty(current, NULL);
}
mutex_unlock(&tty_mutex);
@@ -1731,7 +1734,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
j++;
i = j * __NFDBITS;
fdt = files_fdtable(files);
- if (i >= fdt->max_fds || i >= fdt->max_fdset)
+ if (i >= fdt->max_fds)
break;
set = fdt->open_fds->fds_bits[j];
if (!set)
@@ -2417,7 +2420,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
static int selinux_file_permission(struct file *file, int mask)
{
int rc;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
if (!mask) {
/* No permission to check. Existence test. */
@@ -2594,7 +2597,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
switch (cmd) {
case F_SETFL:
- if (!file->f_dentry || !file->f_dentry->d_inode) {
+ if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
err = -EINVAL;
break;
}
@@ -2620,7 +2623,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_SETLK64:
case F_SETLKW64:
#endif
- if (!file->f_dentry || !file->f_dentry->d_inode) {
+ if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
err = -EINVAL;
break;
}
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 161eb571c82..31929e39f5c 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -37,6 +37,11 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
struct avc_audit_data *ad, u8 proto);
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
+
+static inline void selinux_xfrm_notify_policyload(void)
+{
+ atomic_inc(&flow_cache_genid);
+}
#else
static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
struct avc_audit_data *ad)
@@ -55,6 +60,10 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int
*sid = SECSID_NULL;
return 0;
}
+
+static inline void selinux_xfrm_notify_policyload(void)
+{
+}
#endif
static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index cd244419c98..c8bf6e172f6 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -448,7 +448,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
{
- ino_t ino = file->f_dentry->d_inode->i_ino;
+ ino_t ino = file->f_path.dentry->d_inode->i_ino;
char *data;
ssize_t rv;
@@ -805,7 +805,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
goto out;
}
- inode = filep->f_dentry->d_inode;
+ inode = filep->f_path.dentry->d_inode;
cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
if (cur_enforcing < 0) {
ret = cur_enforcing;
@@ -864,7 +864,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
if (new_value)
new_value = 1;
- inode = filep->f_dentry->d_inode;
+ inode = filep->f_path.dentry->d_inode;
bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
length = count;
@@ -965,7 +965,7 @@ static void sel_remove_bools(struct dentry *de)
file_list_lock();
list_for_each(p, &sb->s_files) {
struct file * filp = list_entry(p, struct file, f_u.fu_list);
- struct dentry * dentry = filp->f_dentry;
+ struct dentry * dentry = filp->f_path.dentry;
if (dentry->d_parent != de) {
continue;
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index 0562bacb7b9..2eee0dab524 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -55,6 +55,29 @@ out:
return rc;
}
+/*
+ * Sets both levels in the MLS range of 'dst' to the low level of 'src'.
+ */
+static inline int mls_context_cpy_low(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)
+ goto out;
+
+ dst->range.level[1].sens = src->range.level[0].sens;
+ rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat);
+ if (rc)
+ ebitmap_destroy(&dst->range.level[0].cat);
+out:
+ return rc;
+}
+
static inline int mls_context_cmp(struct context *c1, struct context *c2)
{
if (!selinux_mls_enabled)
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index b4f682dc13f..4a8bab2f3c7 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -270,7 +270,7 @@ int mls_context_to_sid(char oldc,
if (!defcon)
goto out;
- rc = mls_copy_context(context, defcon);
+ rc = mls_context_cpy(context, defcon);
goto out;
}
@@ -401,26 +401,6 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
}
/*
- * 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,
@@ -552,19 +532,19 @@ int mls_compute_sid(struct context *scontext,
case AVTAB_CHANGE:
if (tclass == SECCLASS_PROCESS)
/* Use the process MLS attributes. */
- return mls_copy_context(newcontext, scontext);
+ return mls_context_cpy(newcontext, scontext);
else
/* Use the process effective MLS attributes. */
- return mls_scopy_context(newcontext, scontext);
+ return mls_context_cpy_low(newcontext, scontext);
case AVTAB_MEMBER:
/* Only polyinstantiate the MLS attributes if
the type is being polyinstantiated */
if (newcontext->type != tcontext->type) {
/* Use the process effective MLS attributes. */
- return mls_scopy_context(newcontext, scontext);
+ return mls_context_cpy_low(newcontext, scontext);
} else {
/* Use the related object MLS attributes. */
- return mls_copy_context(newcontext, tcontext);
+ return mls_context_cpy(newcontext, tcontext);
}
default:
return -EINVAL;
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 661d6fc7696..096d1b4ef7f 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -24,26 +24,6 @@
#include "context.h"
#include "policydb.h"
-/*
- * Copies the MLS range from `src' into `dst'.
- */
-static inline int mls_copy_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[l].sens;
- rc = ebitmap_cpy(&dst->range.level[l].cat,
- &src->range.level[l].cat);
- if (rc)
- break;
- }
-
- return rc;
-}
-
int mls_compute_context_len(struct context *context);
void mls_sid_to_context(struct context *context, char **scontext);
int mls_context_isvalid(struct policydb *p, struct context *c);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index bdb7070dd3d..ca9154dc5d8 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1299,6 +1299,7 @@ int security_load_policy(void *data, size_t len)
avc_ss_reset(seqno);
selnl_notify_policyload(seqno);
selinux_netlbl_cache_invalidate();
+ selinux_xfrm_notify_policyload();
return 0;
}
@@ -1354,6 +1355,7 @@ int security_load_policy(void *data, size_t len)
avc_ss_reset(seqno);
selnl_notify_policyload(seqno);
selinux_netlbl_cache_invalidate();
+ selinux_xfrm_notify_policyload();
return 0;
@@ -1853,6 +1855,7 @@ out:
if (!rc) {
avc_ss_reset(seqno);
selnl_notify_policyload(seqno);
+ selinux_xfrm_notify_policyload();
}
return rc;
}
@@ -1916,11 +1919,10 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
newcon.user = context1->user;
newcon.role = context1->role;
newcon.type = context1->type;
- rc = mls_copy_context(&newcon, context2);
+ rc = mls_context_cpy(&newcon, context2);
if (rc)
goto out_unlock;
-
/* Check the validity of the new context. */
if (!policydb_context_isvalid(&policydb, &newcon)) {
rc = convert_context_handle_invalid_context(&newcon);
@@ -2492,9 +2494,9 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
rc = netlbl_socket_setattr(sock, &secattr);
if (rc == 0) {
- spin_lock(&sksec->nlbl_lock);
+ spin_lock_bh(&sksec->nlbl_lock);
sksec->nlbl_state = NLBL_LABELED;
- spin_unlock(&sksec->nlbl_lock);
+ spin_unlock_bh(&sksec->nlbl_lock);
}
netlbl_socket_setsid_return:
@@ -2660,9 +2662,11 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
rcu_read_unlock();
return 0;
}
- lock_sock(sock->sk);
+ local_bh_disable();
+ bh_lock_sock_nested(sock->sk);
rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
- release_sock(sock->sk);
+ bh_unlock_sock(sock->sk);
+ local_bh_enable();
rcu_read_unlock();
return rc;
diff --git a/sound/Kconfig b/sound/Kconfig
index 95949b6806a..9d77300746c 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -93,4 +93,12 @@ endmenu
endif
+config AC97_BUS
+ tristate
+ help
+ This is used to avoid config and link hard dependencies between the
+ sound subsystem and other function drivers completely unrelated to
+ sound although they're sharing the AC97 bus. Concerned drivers
+ should "select" this.
+
endmenu
diff --git a/sound/Makefile b/sound/Makefile
index 5f6bef57e82..9aee54c4882 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -8,6 +8,9 @@ obj-$(CONFIG_DMASOUND) += oss/
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
obj-$(CONFIG_SND_AOA) += aoa/
+# This one must be compilable even if sound is configured out
+obj-$(CONFIG_AC97_BUS) += ac97_bus.o
+
ifeq ($(CONFIG_SND),y)
obj-y += last.o
endif
diff --git a/sound/pci/ac97/ac97_bus.c b/sound/ac97_bus.c
index 66de2c2f155..66de2c2f155 100644
--- a/sound/pci/ac97/ac97_bus.c
+++ b/sound/ac97_bus.c
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h
index aeedda77369..ffd20254ff7 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.h
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h
@@ -9,7 +9,6 @@
#define __SND_AOA_CODEC_ONYX_H
#include <stddef.h>
#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
#include <asm/pmac_low_i2c.h>
#include <asm/prom.h>
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 9de8485ba3f..2cd81fa07ce 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -61,7 +61,6 @@
*/
#include <stddef.h>
#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
#include <asm/pmac_low_i2c.h>
#include <asm/prom.h>
#include <linux/delay.h>
diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig
index c3bc7705c86..50d7021ff67 100644
--- a/sound/aoa/fabrics/Kconfig
+++ b/sound/aoa/fabrics/Kconfig
@@ -1,6 +1,6 @@
config SND_AOA_FABRIC_LAYOUT
tristate "layout-id fabric"
- depends SND_AOA
+ depends on SND_AOA
select SND_AOA_SOUNDBUS
select SND_AOA_SOUNDBUS_I2S
---help---
diff --git a/sound/core/control.c b/sound/core/control.c
index 48ef0a09a7a..0c7bcd62e5b 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1275,7 +1275,7 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
schedule();
remove_wait_queue(&ctl->change_sleep, &wait);
if (signal_pending(current))
- return result > 0 ? result : -ERESTARTSYS;
+ return -ERESTARTSYS;
spin_lock_irq(&ctl->read_lock);
}
kev = snd_kctl_event(ctl->events.next);
diff --git a/sound/core/info.c b/sound/core/info.c
index 0b4aab3225e..54591e2eb6e 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -488,7 +488,7 @@ static long snd_info_entry_ioctl(struct file *file, unsigned int cmd,
static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct snd_info_private_data *data;
struct snd_info_entry *entry;
diff --git a/sound/core/init.c b/sound/core/init.c
index 6152a7554df..a4cc6b155ae 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -361,8 +361,10 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
- if (card->dev)
- device_unregister(card->dev);
+#ifndef CONFIG_SYSFS_DEPRECATED
+ if (card->card_dev)
+ device_unregister(card->card_dev);
+#endif
kfree(card);
return 0;
}
@@ -497,12 +499,14 @@ int snd_card_register(struct snd_card *card)
int err;
snd_assert(card != NULL, return -EINVAL);
- if (!card->dev) {
- card->dev = device_create(sound_class, card->parent, 0,
- "card%i", card->number);
- if (IS_ERR(card->dev))
- card->dev = NULL;
+#ifndef CONFIG_SYSFS_DEPRECATED
+ if (!card->card_dev) {
+ card->card_dev = device_create(sound_class, card->dev, 0,
+ "card%i", card->number);
+ if (IS_ERR(card->card_dev))
+ card->card_dev = NULL;
}
+#endif
if ((err = snd_device_register_all(card)) < 0)
return err;
mutex_lock(&snd_card_mutex);
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index f4c67042e3a..3391f2a9b4d 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1023,7 +1023,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
}
up_read(&mixer->card->controls_rwsem);
if (slot.present != 0) {
- pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL);
+ pslot = kmalloc(sizeof(slot), GFP_KERNEL);
if (! pslot)
return -ENOMEM;
*pslot = slot;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index e0821eb3d85..786a82e6889 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -810,6 +810,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
struct snd_mask sformat_mask;
struct snd_mask mask;
+ if (mutex_lock_interruptible(&runtime->oss.params_lock))
+ return -EINTR;
sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
params = kmalloc(sizeof(*params), GFP_KERNEL);
sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
@@ -1020,6 +1022,7 @@ failure:
kfree(sw_params);
kfree(params);
kfree(sparams);
+ mutex_unlock(&runtime->oss.params_lock);
return err;
}
@@ -1307,14 +1310,17 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
return tmp;
+ mutex_lock(&runtime->oss.params_lock);
while (bytes > 0) {
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
tmp = bytes;
if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
if (tmp > 0) {
- if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp))
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;
+ if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
+ tmp = -EFAULT;
+ goto err;
+ }
}
runtime->oss.buffer_used += tmp;
buf += tmp;
@@ -1325,22 +1331,24 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
runtime->oss.period_ptr += tmp;
runtime->oss.period_ptr %= runtime->oss.period_bytes;
if (runtime->oss.period_ptr == 0 ||
runtime->oss.period_ptr == runtime->oss.buffer_used)
runtime->oss.buffer_used = 0;
- else if ((substream->f_flags & O_NONBLOCK) != 0)
- return xfer > 0 ? xfer : -EAGAIN;
+ else if ((substream->f_flags & O_NONBLOCK) != 0) {
+ tmp = -EAGAIN;
+ goto err;
+ }
}
} else {
tmp = snd_pcm_oss_write2(substream,
(const char __force *)buf,
runtime->oss.period_bytes, 0);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
buf += tmp;
bytes -= tmp;
@@ -1350,7 +1358,12 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
break;
}
}
+ mutex_unlock(&runtime->oss.params_lock);
return xfer;
+
+ err:
+ mutex_unlock(&runtime->oss.params_lock);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}
static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel)
@@ -1397,12 +1410,13 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
return tmp;
+ mutex_lock(&runtime->oss.params_lock);
while (bytes > 0) {
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
if (runtime->oss.buffer_used == 0) {
tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
runtime->oss.period_ptr = tmp;
runtime->oss.buffer_used = tmp;
@@ -1410,8 +1424,10 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
tmp = bytes;
if ((size_t) tmp > runtime->oss.buffer_used)
tmp = runtime->oss.buffer_used;
- if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp))
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;
+ if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) {
+ tmp = -EFAULT;
+ goto err;
+ }
buf += tmp;
bytes -= tmp;
xfer += tmp;
@@ -1420,14 +1436,19 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
runtime->oss.period_bytes, 0);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
buf += tmp;
bytes -= tmp;
xfer += tmp;
}
}
+ mutex_unlock(&runtime->oss.params_lock);
return xfer;
+
+ err:
+ mutex_unlock(&runtime->oss.params_lock);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}
static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1528,6 +1549,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
return err;
format = snd_pcm_oss_format_from(runtime->oss.format);
width = snd_pcm_format_physical_width(format);
+ mutex_lock(&runtime->oss.params_lock);
if (runtime->oss.buffer_used > 0) {
#ifdef OSS_DEBUG
printk("sync: buffer_used\n");
@@ -1537,8 +1559,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
runtime->oss.buffer + runtime->oss.buffer_used,
size);
err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
- if (err < 0)
+ if (err < 0) {
+ mutex_unlock(&runtime->oss.params_lock);
return err;
+ }
} else if (runtime->oss.period_ptr > 0) {
#ifdef OSS_DEBUG
printk("sync: period_ptr\n");
@@ -1548,8 +1572,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
runtime->oss.buffer,
size * 8 / width);
err = snd_pcm_oss_sync1(substream, size);
- if (err < 0)
+ if (err < 0) {
+ mutex_unlock(&runtime->oss.params_lock);
return err;
+ }
}
/*
* The ALSA's period might be a bit large than OSS one.
@@ -1579,6 +1605,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
snd_pcm_lib_writev(substream, buffers, size);
}
}
+ mutex_unlock(&runtime->oss.params_lock);
/*
* finish sync: drain the buffer
*/
@@ -2172,6 +2199,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
runtime->oss.params = 1;
runtime->oss.trigger = 1;
runtime->oss.rate = 8000;
+ mutex_init(&runtime->oss.params_lock);
switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
case SNDRV_MINOR_OSS_PCM_8:
runtime->oss.format = AFMT_U8;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 5ac6e19ccb4..8e018988551 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -640,6 +640,10 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
err = snd_pcm_substream_proc_init(substream);
if (err < 0) {
snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
+ if (prev == NULL)
+ pstr->substream = NULL;
+ else
+ prev->next = NULL;
kfree(substream);
return err;
}
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 0bb142a2853..b336797be4f 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -79,19 +79,17 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
runtime->silence_filled -= frames;
if ((snd_pcm_sframes_t)runtime->silence_filled < 0) {
runtime->silence_filled = 0;
- runtime->silence_start = (ofs + frames) - runtime->buffer_size;
+ runtime->silence_start = new_hw_ptr;
} else {
- runtime->silence_start = ofs - runtime->silence_filled;
+ runtime->silence_start = ofs;
}
- if ((snd_pcm_sframes_t)runtime->silence_start < 0)
- runtime->silence_start += runtime->boundary;
}
frames = runtime->buffer_size - runtime->silence_filled;
}
snd_assert(frames <= runtime->buffer_size, return);
if (frames == 0)
return;
- ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size;
+ ofs = runtime->silence_start % runtime->buffer_size;
while (frames > 0) {
transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 6ea67b16c67..b52e89393fa 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1604,7 +1604,7 @@ static struct file *snd_pcm_file_fd(int fd)
file = fget(fd);
if (!file)
return NULL;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (!S_ISCHR(inode->i_mode) ||
imajor(inode) != snd_major) {
fput(file);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 269c467ca9b..0f055bfcbda 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1385,7 +1385,6 @@ static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
struct snd_rawmidi_substream *substream;
int idx;
- INIT_LIST_HEAD(&stream->substreams);
for (idx = 0; idx < count; idx++) {
substream = kzalloc(sizeof(*substream), GFP_KERNEL);
if (substream == NULL) {
@@ -1440,6 +1439,9 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
rmidi->device = device;
mutex_init(&rmidi->open_mutex);
init_waitqueue_head(&rmidi->open_wait);
+ INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams);
+ INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);
+
if (id != NULL)
strlcpy(rmidi->id, id, sizeof(rmidi->id));
if ((err = snd_rawmidi_alloc_substreams(rmidi,
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 4bffe509f71..a3dc5e01e9f 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -151,7 +151,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
return len;
newlen = len;
if (size_aligned > 0)
- newlen = ((len + size_aligned - 1) / size_aligned) * size_aligned;
+ newlen = roundup(len, size_aligned);
if (count < newlen)
return -EAGAIN;
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index c30669f14ac..cefd228cd2a 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -27,7 +27,7 @@
/* table entries are align to 32 */
#define SGBUF_TBL_ALIGN 32
-#define sgbuf_align_table(tbl) ((((tbl) + SGBUF_TBL_ALIGN - 1) / SGBUF_TBL_ALIGN) * SGBUF_TBL_ALIGN)
+#define sgbuf_align_table(tbl) ALIGN((tbl), SGBUF_TBL_ALIGN)
int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
{
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 282742022de..82a61c67cf3 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -238,7 +238,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
{
int minor;
struct snd_minor *preg;
- struct device *device = NULL;
+ struct device *device = snd_card_get_device_link(card);
snd_assert(name, return -EINVAL);
preg = kmalloc(sizeof *preg, GFP_KERNEL);
@@ -263,8 +263,6 @@ int snd_register_device(int type, struct snd_card *card, int dev,
return minor;
}
snd_minors[minor] = preg;
- if (card)
- device = card->dev;
preg->dev = device_create(sound_class, device, MKDEV(major, minor),
"%s", name);
if (preg->dev)
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index b2fc40aa520..4566df41912 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -106,7 +106,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
int cidx = SNDRV_MINOR_OSS_CARD(minor);
int track2 = -1;
int register1 = -1, register2 = -1;
- struct device *carddev = NULL;
+ struct device *carddev = snd_card_get_device_link(card);
if (card && card->number >= 8)
return 0; /* ignore silently */
@@ -134,8 +134,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
break;
}
- if (card)
- carddev = card->dev;
register1 = register_sound_special_device(f_ops, minor, carddev);
if (register1 != minor)
goto __end;
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7971285dfd5..40ebd2f4405 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -26,11 +26,7 @@ config SND_VX_LIB
config SND_AC97_CODEC
tristate
select SND_PCM
- select SND_AC97_BUS
-
-config SND_AC97_BUS
- tristate
-
+ select AC97_BUS
config SND_DUMMY
tristate "Dummy (/dev/null) soundcard"
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index f50c276caee..7107753b85b 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -143,9 +143,8 @@ static int snd_gf1_mem_find(struct snd_gf1_mem * alloc,
struct snd_gf1_mem_block *pblock;
unsigned int ptr1, ptr2;
- align--;
- if (w_16 && align < 1)
- align = 1;
+ if (w_16 && align < 2)
+ align = 2;
block->flags = w_16 ? SNDRV_GF1_MEM_BLOCK_16BIT : 0;
block->owner = SNDRV_GF1_MEM_OWNER_DRIVER;
block->share = 0;
@@ -165,7 +164,7 @@ static int snd_gf1_mem_find(struct snd_gf1_mem * alloc,
if (pblock->next->ptr < boundary)
ptr2 = pblock->next->ptr;
}
- ptr1 = (pblock->ptr + pblock->size + align) & ~align;
+ ptr1 = ALIGN(pblock->ptr + pblock->size, align);
if (ptr1 >= ptr2)
continue;
size1 = ptr2 - ptr1;
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index c62a9e3d2ae..3094f385216 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -232,7 +232,7 @@ int snd_sbdsp_create(struct snd_card *card,
chip->port = port;
if (request_irq(irq, irq_handler, hardware == SB_HW_ALS4000 ?
- IRQF_DISABLED | IRQF_SHARED : IRQF_DISABLED,
+ IRQF_SHARED : IRQF_DISABLED,
"SoundBlaster", (void *) chip)) {
snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
snd_sbdsp_free(chip);
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index bed329edbdd..78020d832e0 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1068,7 +1068,7 @@ wavefront_send_sample (snd_wavefront_t *dev,
blocksize = max_blksize;
} else {
/* round to nearest 16-byte value */
- blocksize = ((length-written+7)&~0x7);
+ blocksize = ALIGN(length - written, 8);
}
if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 0ffa9970bf0..7cf9913a47b 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -1992,7 +1992,7 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
devc->audio_flags |= DMA_DUPLEX;
}
- portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL);
+ portc = kmalloc(sizeof(ad1848_port_info), GFP_KERNEL);
if(portc==NULL) {
release_region(devc->base, 4);
return -1;
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index b6924c7f148..de40e21bf27 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -408,7 +408,7 @@ static int __init cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_
{
struct address_info *isapnpcfg;
- isapnpcfg=(struct address_info*)kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
+ isapnpcfg = kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
if (!isapnpcfg)
return -ENOMEM;
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 87bd3100aef..80b836e80d9 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -1051,7 +1051,7 @@ static int sq_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE) {
if (write_sq.busy)
- rc = sq_fsync(file, file->f_dentry);
+ rc = sq_fsync(file, file->f_path.dentry);
sq_reset_output() ; /* make sure dma is stopped and all is quiet */
write_sq_release_buffers();
@@ -1217,7 +1217,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
if ((file->f_mode & FMODE_READ) && dmasound.mach.record)
sq_reset_input() ;
if (file->f_mode & FMODE_WRITE) {
- result = sq_fsync(file, file->f_dentry);
+ result = sq_fsync(file, file->f_path.dentry);
sq_reset_output() ;
}
/* if we are the shared resource owner then release them */
diff --git a/sound/oss/dmasound/tas3001c.c b/sound/oss/dmasound/tas3001c.c
index f227c9f688c..2f21a3c0037 100644
--- a/sound/oss/dmasound/tas3001c.c
+++ b/sound/oss/dmasound/tas3001c.c
@@ -50,6 +50,7 @@ struct tas3001c_data_t {
int output_id;
int speaker_id;
struct tas_drce_t drce_state;
+ struct work_struct change;
};
@@ -667,14 +668,13 @@ tas3001c_update_device_parameters(struct tas3001c_data_t *self)
}
static void
-tas3001c_device_change_handler(void *self)
+tas3001c_device_change_handler(struct work_struct *work)
{
- if (self)
- tas3001c_update_device_parameters(self);
+ struct tas3001c_data_t *self;
+ self = container_of(work, struct tas3001c_data_t, change);
+ tas3001c_update_device_parameters(self);
}
-static struct work_struct device_change;
-
static int
tas3001c_output_device_change( struct tas3001c_data_t *self,
int device_id,
@@ -685,7 +685,7 @@ tas3001c_output_device_change( struct tas3001c_data_t *self,
self->output_id=output_id;
self->speaker_id=speaker_id;
- schedule_work(&device_change);
+ schedule_work(&self->change);
return 0;
}
@@ -823,7 +823,7 @@ tas3001c_init(struct i2c_client *client)
tas3001c_write_biquad_shadow(self, i, j,
&tas3001c_eq_unity);
- INIT_WORK(&device_change, tas3001c_device_change_handler, self);
+ INIT_WORK(&self->change, tas3001c_device_change_handler);
return 0;
}
diff --git a/sound/oss/dmasound/tas3004.c b/sound/oss/dmasound/tas3004.c
index 82eaaca2db9..af34fb39bc2 100644
--- a/sound/oss/dmasound/tas3004.c
+++ b/sound/oss/dmasound/tas3004.c
@@ -48,6 +48,7 @@ struct tas3004_data_t {
int output_id;
int speaker_id;
struct tas_drce_t drce_state;
+ struct work_struct change;
};
#define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000)
@@ -914,15 +915,13 @@ tas3004_update_device_parameters(struct tas3004_data_t *self)
}
static void
-tas3004_device_change_handler(void *self)
+tas3004_device_change_handler(struct work_struct *work)
{
- if (!self) return;
-
- tas3004_update_device_parameters((struct tas3004_data_t *)self);
+ struct tas3004_data_t *self;
+ self = container_of(work, struct tas3004_data_t, change);
+ tas3004_update_device_parameters(self);
}
-static struct work_struct device_change;
-
static int
tas3004_output_device_change( struct tas3004_data_t *self,
int device_id,
@@ -933,7 +932,7 @@ tas3004_output_device_change( struct tas3004_data_t *self,
self->output_id=output_id;
self->speaker_id=speaker_id;
- schedule_work(&device_change);
+ schedule_work(&self->change);
return 0;
}
@@ -1112,7 +1111,7 @@ tas3004_init(struct i2c_client *client)
tas3004_write_register(self, TAS3004_REG_MCR2, &mcr2, WRITE_SHADOW);
tas3004_write_register(self, TAS3004_REG_DRC, drce_init, WRITE_SHADOW);
- INIT_WORK(&device_change, tas3004_device_change_handler, self);
+ INIT_WORK(&self->change, tas3004_device_change_handler);
return 0;
}
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
index 49f902f35c2..efcf589d708 100644
--- a/sound/oss/emu10k1/audio.c
+++ b/sound/oss/emu10k1/audio.c
@@ -1139,7 +1139,7 @@ static int emu10k1_audio_open(struct inode *inode, struct file *file)
match:
- wave_dev = (struct emu10k1_wavedevice *) kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
+ wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
if (wave_dev == NULL) {
ERROR();
@@ -1155,7 +1155,7 @@ match:
/* Recording */
struct wiinst *wiinst;
- if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
+ if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
ERROR();
kfree(wave_dev);
return -ENOMEM;
@@ -1211,7 +1211,7 @@ match:
struct woinst *woinst;
int i;
- if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
+ if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
ERROR();
kfree(wave_dev);
return -ENOMEM;
diff --git a/sound/oss/emu10k1/cardmi.c b/sound/oss/emu10k1/cardmi.c
index 0545814cc67..57674f8c8a2 100644
--- a/sound/oss/emu10k1/cardmi.c
+++ b/sound/oss/emu10k1/cardmi.c
@@ -157,7 +157,7 @@ int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *card_mpuin, struct midi_hdr *
midihdr->flags |= MIDIBUF_INQUEUE; /* set */
midihdr->flags &= ~MIDIBUF_DONE; /* clear */
- if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
+ if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
/* Message lost */
return -1;
}
diff --git a/sound/oss/emu10k1/cardmo.c b/sound/oss/emu10k1/cardmo.c
index 5938d31f9e2..a8cc75db3e4 100644
--- a/sound/oss/emu10k1/cardmo.c
+++ b/sound/oss/emu10k1/cardmo.c
@@ -117,7 +117,7 @@ int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihd
midihdr->flags |= MIDIBUF_INQUEUE;
midihdr->flags &= ~MIDIBUF_DONE;
- if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
+ if ((midiq = kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
/* Message lost */
return -1;
}
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 8ac77df8639..cca3dad2bdf 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -58,7 +58,7 @@ static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hd
{
struct midi_hdr *midihdr;
- if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
+ if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
ERROR();
return -EINVAL;
}
@@ -128,7 +128,7 @@ match:
mutex_lock(&card->open_sem);
}
- if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
+ if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
return -EINVAL;
midi_dev->card = card;
@@ -328,7 +328,7 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
- if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
+ if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
return -EINVAL;
midihdr->bufferlength = count;
@@ -490,7 +490,7 @@ int emu10k1_seq_midi_open(int dev, int mode,
DPF(2, "emu10k1_seq_midi_open()\n");
- if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
+ if ((midi_dev = kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL)
return -EINVAL;
midi_dev->card = card;
@@ -540,7 +540,7 @@ int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
card = midi_devs[dev]->devc;
- if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
+ if ((midihdr = kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
return -EINVAL;
midihdr->bufferlength = 1;
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
index cbcaaa34189..6419796c2ed 100644
--- a/sound/oss/emu10k1/mixer.c
+++ b/sound/oss/emu10k1/mixer.c
@@ -194,7 +194,7 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
case SOUND_MIXER_PRIVATE3:
- ctl = (struct mixer_private_ioctl *) kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
+ ctl = kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
if (ctl == NULL)
return -ENOMEM;
diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c
index 784bdd70705..d18286ccc14 100644
--- a/sound/oss/hal2.c
+++ b/sound/oss/hal2.c
@@ -1435,7 +1435,7 @@ static int hal2_init_card(struct hal2_card **phal2, struct hpc3_regs *hpc3)
int ret = 0;
struct hal2_card *hal2;
- hal2 = (struct hal2_card *) kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
+ hal2 = kmalloc(sizeof(struct hal2_card), GFP_KERNEL);
if (!hal2)
return -ENOMEM;
memset(hal2, 0, sizeof(struct hal2_card));
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index e9622054197..2796c0ef985 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1023,7 +1023,7 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */
- mpu401_synth_operations[m] = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+ mpu401_synth_operations[m] = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
if (mpu401_synth_operations[m] == NULL)
{
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index d5146790f5e..24110d63b13 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1007,7 +1007,7 @@ static int dsp_write(const char __user *buf, size_t len)
static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *off)
{
- int minor = iminor(file->f_dentry->d_inode);
+ int minor = iminor(file->f_path.dentry->d_inode);
if (minor == dev.dsp_minor)
return dsp_read(buf, count);
else
@@ -1016,7 +1016,7 @@ static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_
static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
{
- int minor = iminor(file->f_dentry->d_inode);
+ int minor = iminor(file->f_path.dentry->d_inode);
if (minor == dev.dsp_minor)
return dsp_write(buf, count);
else
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
index 4799bc77f98..2e8cfa5481f 100644
--- a/sound/oss/opl3.c
+++ b/sound/oss/opl3.c
@@ -166,7 +166,7 @@ int opl3_detect(int ioaddr, int *osp)
return 0;
}
- devc = (struct opl_devinfo *)kmalloc(sizeof(*devc), GFP_KERNEL);
+ devc = kmalloc(sizeof(*devc), GFP_KERNEL);
if (devc == NULL)
{
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index 440537c7260..07cbacf6382 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -625,7 +625,7 @@ int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_
*/
- detected_devc = (sb_devc *)kmalloc(sizeof(sb_devc), GFP_KERNEL);
+ detected_devc = kmalloc(sizeof(sb_devc), GFP_KERNEL);
if (detected_devc == NULL)
{
printk(KERN_ERR "sb: Can't allocate memory for device information\n");
diff --git a/sound/oss/sb_midi.c b/sound/oss/sb_midi.c
index 2e3bc045cab..8b796704e11 100644
--- a/sound/oss/sb_midi.c
+++ b/sound/oss/sb_midi.c
@@ -173,7 +173,7 @@ void sb_dsp_midi_init(sb_devc * devc, struct module *owner)
return;
}
std_midi_synth.midi_dev = devc->my_mididev = dev;
- midi_devs[dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+ midi_devs[dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
if (midi_devs[dev] == NULL)
{
printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n");
@@ -189,7 +189,7 @@ void sb_dsp_midi_init(sb_devc * devc, struct module *owner)
midi_devs[dev]->devc = devc;
- midi_devs[dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+ midi_devs[dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
if (midi_devs[dev]->converter == NULL)
{
printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n");
diff --git a/sound/oss/sb_mixer.c b/sound/oss/sb_mixer.c
index 238e2cf44b0..fad1a4f25ad 100644
--- a/sound/oss/sb_mixer.c
+++ b/sound/oss/sb_mixer.c
@@ -734,7 +734,7 @@ int sb_mixer_init(sb_devc * devc, struct module *owner)
if (m == -1)
return 0;
- mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
+ mixer_devs[m] = kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
if (mixer_devs[m] == NULL)
{
printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 8fb8e7f9955..a89108cb74e 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -141,7 +141,7 @@ static int get_mixer_levels(void __user * arg)
static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
int ret = -EINVAL;
/*
@@ -174,7 +174,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
int ret = -EINVAL;
lock_kernel();
@@ -393,7 +393,7 @@ static int sound_ioctl(struct inode *inode, struct file *file,
static unsigned int sound_poll(struct file *file, poll_table * wait)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
int dev = iminor(inode);
DEB(printk("sound_poll(dev=%d)\n", dev));
@@ -418,7 +418,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
int dev_class;
unsigned long size;
struct dma_buffparms *dmap = NULL;
- int dev = iminor(file->f_dentry->d_inode);
+ int dev = iminor(file->f_path.dentry->d_inode);
dev_class = dev & 0x0f;
dev >>= 4;
diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c
index d952b2264da..103940fd5b4 100644
--- a/sound/oss/v_midi.c
+++ b/sound/oss/v_midi.c
@@ -183,7 +183,7 @@ static void __init attach_v_midi (struct address_info *hw_config)
return;
}
- m=(struct vmidi_memory *)kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
+ m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
if (m == NULL)
{
printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index c5bf363d32c..26a7c6af95b 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -1267,7 +1267,7 @@ static int __init waveartist_init(wavnc_info *devc)
conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
devc->hw.dma, devc->hw.dma2);
- portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+ portc = kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
if (portc == NULL)
goto nomem;
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
index 77b3482cb13..3c3222122d8 100644
--- a/sound/pci/ac97/Makefile
+++ b/sound/pci/ac97/Makefile
@@ -10,11 +10,9 @@ snd-ac97-codec-objs += ac97_proc.o
endif
snd-ak4531-codec-objs := ak4531_codec.o
-snd-ac97-bus-objs := ac97_bus.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o
obj-$(CONFIG_SND_ENS1370) += snd-ak4531-codec.o
-obj-$(CONFIG_SND_AC97_BUS) += snd-ac97-bus.o
obj-m := $(sort $(obj-m))
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 7abcb10b275..d2994cb4c8c 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -129,9 +129,9 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL },
{ 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL },
{ 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL },
-{ 0x434d4978, 0xffffffff, "CMI9761", patch_cm9761, NULL },
-{ 0x434d4982, 0xffffffff, "CMI9761", patch_cm9761, NULL },
-{ 0x434d4983, 0xffffffff, "CMI9761", patch_cm9761, NULL },
+{ 0x434d4978, 0xffffffff, "CMI9761A", patch_cm9761, NULL },
+{ 0x434d4982, 0xffffffff, "CMI9761B", patch_cm9761, NULL },
+{ 0x434d4983, 0xffffffff, "CMI9761A+", patch_cm9761, NULL },
{ 0x43525900, 0xfffffff8, "CS4297", NULL, NULL },
{ 0x43525910, 0xfffffff8, "CS4297A", patch_cirrus_spdif, NULL },
{ 0x43525920, 0xfffffff8, "CS4298", patch_cirrus_spdif, NULL },
@@ -382,7 +382,7 @@ int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
unsigned short old, new;
old = snd_ac97_read_cache(ac97, reg);
- new = (old & ~mask) | value;
+ new = (old & ~mask) | (value & mask);
change = old != new;
if (change) {
ac97->regs[reg] = new;
@@ -399,7 +399,7 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns
mutex_lock(&ac97->page_mutex);
old = ac97->spec.ad18xx.pcmreg[codec];
- new = (old & ~mask) | value;
+ new = (old & ~mask) | (value & mask);
change = old != new;
if (change) {
mutex_lock(&ac97->reg_mutex);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 15be6ba87c8..e813968e0cf 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -1467,7 +1467,9 @@ static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int
snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C
ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
if (cidx1 >= 0) {
- if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C
+ if (cidx2 < 0)
+ patch_ad1881_chained1(ac97, cidx1, 0);
+ else if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C
patch_ad1881_chained1(ac97, cidx2, 0);
else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C
patch_ad1881_chained1(ac97, cidx1, 0);
@@ -2261,7 +2263,8 @@ int patch_alc655(struct snd_ac97 * ac97)
else { /* ALC655 */
if (ac97->subsystem_vendor == 0x1462 &&
(ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
- ac97->subsystem_device == 0x0161)) /* LG K1 Express */
+ ac97->subsystem_device == 0x0161 || /* LG K1 Express */
+ ac97->subsystem_device == 0x0351)) /* MSI L725 laptop */
val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
else
val |= (1 << 1); /* Pin 47 is spdif input pin */
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index cbf8331c3d3..98970d401be 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -858,7 +858,7 @@ snd_ad1889_free(struct snd_ad1889 *chip)
synchronize_irq(chip->irq);
if (chip->irq >= 0)
- free_irq(chip->irq, (void*)chip);
+ free_irq(chip->irq, chip);
skip_hw:
if (chip->iobase)
@@ -945,7 +945,7 @@ snd_ad1889_create(struct snd_card *card,
spin_lock_init(&chip->lock); /* only now can we call ad1889_free */
if (request_irq(pci->irq, snd_ad1889_interrupt,
- IRQF_DISABLED|IRQF_SHARED, card->driver, (void*)chip)) {
+ IRQF_SHARED, card->driver, chip)) {
printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq);
snd_ad1889_free(chip);
return -EBUSY;
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index a7edd56542d..9327ab2eccb 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -2095,7 +2095,7 @@ static int snd_ali_free(struct snd_ali * codec)
snd_ali_disable_address_interrupt(codec);
if (codec->irq >= 0) {
synchronize_irq(codec->irq);
- free_irq(codec->irq, (void *)codec);
+ free_irq(codec->irq, codec);
}
if (codec->port)
pci_release_regions(codec->pci);
@@ -2192,7 +2192,8 @@ static int __devinit snd_ali_resources(struct snd_ali *codec)
return err;
codec->port = pci_resource_start(codec->pci, 0);
- if (request_irq(codec->pci->irq, snd_ali_card_interrupt, IRQF_DISABLED|IRQF_SHARED, "ALI 5451", (void *)codec)) {
+ if (request_irq(codec->pci->irq, snd_ali_card_interrupt,
+ IRQF_SHARED, "ALI 5451", codec)) {
snd_printk(KERN_ERR "Unable to request irq.\n");
return -EBUSY;
}
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 95f70f3cc37..9f406fbe0d9 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -190,7 +190,7 @@ static int snd_als300_free(struct snd_als300 *chip)
snd_als300_dbgcallenter();
snd_als300_set_irq_flag(chip, IRQ_DISABLE);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
@@ -722,8 +722,8 @@ static int __devinit snd_als300_create(snd_card_t *card,
else
irq_handler = snd_als300_interrupt;
- if (request_irq(pci->irq, irq_handler, IRQF_DISABLED|IRQF_SHARED,
- card->shortname, (void *)chip)) {
+ if (request_irq(pci->irq, irq_handler, IRQF_SHARED,
+ card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_als300_free(chip);
return -EBUSY;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index e3e99f39671..476c3433073 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1583,7 +1583,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
return -EIO;
}
- if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_atiixp_free(chip);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index dc54f2c68ed..cc2e6b9d407 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1256,7 +1256,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card,
return -EIO;
}
- if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED,
card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_atiixp_free(chip);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 6ed5ad59f5b..238154bb7a2 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -198,7 +198,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
}
if ((err = request_irq(pci->irq, vortex_interrupt,
- IRQF_DISABLED | IRQF_SHARED, CARD_NAME_SHORT,
+ IRQF_SHARED, CARD_NAME_SHORT,
chip)) != 0) {
printk(KERN_ERR "cannot grab irq\n");
goto irq_out;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 2414ee63075..43edd2839b5 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1513,7 +1513,7 @@ snd_azf3328_free(struct snd_azf3328 *chip)
__end_hw:
snd_azf3328_free_joystick(chip);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
@@ -1724,7 +1724,8 @@ snd_azf3328_create(struct snd_card *card,
chip->synth_port = pci_resource_start(pci, 3);
chip->mixer_port = pci_resource_start(pci, 4);
- if (request_irq(pci->irq, snd_azf3328_interrupt, IRQF_DISABLED|IRQF_SHARED, card->shortname, (void *)chip)) {
+ if (request_irq(pci->irq, snd_azf3328_interrupt,
+ IRQF_SHARED, card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
err = -EBUSY;
goto out_err;
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index d33a37086df..c3f3da21123 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -699,7 +699,7 @@ static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *nam
SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(chip->pci),
128 * 1024,
- (255 * 4092 + 1023) & ~1023);
+ ALIGN(255 * 4092, 1024));
}
static int __devinit snd_bt87x_create(struct snd_card *card,
@@ -747,7 +747,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card,
snd_bt87x_writel(chip, REG_INT_MASK, 0);
snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
- if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_DISABLED | IRQF_SHARED,
+ if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED,
"Bt87x audio", chip)) {
snd_bt87x_free(chip);
snd_printk(KERN_ERR "cannot grab irq\n");
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 9cb66c59f52..aaac6e5b476 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -590,7 +590,7 @@ struct snd_ca0106 {
struct resource *res_port;
int irq;
- unsigned int revision; /* chip revision */
+ unsigned char revision; /* chip revision */
unsigned int serial; /* serial number */
unsigned short model; /* subsystem id */
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 6fa4a302f7d..f61f052f6d1 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -154,6 +154,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the CA0106 soundcard.");
@@ -161,6 +162,8 @@ module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for the CA0106 soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
+module_param_array(subsystem, uint, NULL, 0444);
+MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
#include "ca0106.h"
@@ -194,6 +197,17 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
.gpio_type = 1,
.i2c_adc = 1,
.spi_dac = 1 } ,
+ /* New Audigy LS. Has a different DAC. */
+ /* SB0570:
+ * CTRL:CA0106-DAT
+ * ADC: WM8775EDS
+ * DAC: WM8768GEDS
+ */
+ { .serial = 0x10111102,
+ .name = "Audigy SE OEM [SB0570a]",
+ .gpio_type = 1,
+ .i2c_adc = 1,
+ .spi_dac = 1 } ,
/* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
/* SB0438
* CTRL:CA0106-DAT
@@ -1046,7 +1060,7 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
// release the irq
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_disable_device(chip->pci);
kfree(chip);
return 0;
@@ -1223,7 +1237,7 @@ static unsigned int i2c_adc_init[][2] = {
{ 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
};
-static int __devinit snd_ca0106_create(struct snd_card *card,
+static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
struct pci_dev *pci,
struct snd_ca0106 **rchip)
{
@@ -1267,8 +1281,7 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
}
if (request_irq(pci->irq, snd_ca0106_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "snd_ca0106",
- (void *)chip)) {
+ IRQF_SHARED, "snd_ca0106", chip)) {
snd_ca0106_free(chip);
printk(KERN_ERR "cannot grab irq\n");
return -EBUSY;
@@ -1283,21 +1296,29 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
pci_set_master(pci);
/* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&chip->revision);
+ pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
#if 1
- printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
+ printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
chip->revision, chip->serial);
#endif
strcpy(card->driver, "CA0106");
strcpy(card->shortname, "CA0106");
for (c = ca0106_chip_details; c->serial; c++) {
- if (c->serial == chip->serial)
+ if (subsystem[dev]) {
+ if (c->serial == subsystem[dev])
+ break;
+ } else if (c->serial == chip->serial)
break;
}
chip->details = c;
+ if (subsystem[dev]) {
+ printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n",
+ c->name, chip->serial, subsystem[dev]);
+ }
+
sprintf(card->longname, "%s at 0x%lx irq %i",
c->name, chip->port, chip->irq);
@@ -1540,7 +1561,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
if (card == NULL)
return -ENOMEM;
- if ((err = snd_ca0106_create(card, pci, &chip)) < 0) {
+ if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 0093cd1f92d..70face7e104 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2198,7 +2198,8 @@ static int _snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol,
val = inb(cm->iobase + args->reg);
else
val = snd_cmipci_read(cm, args->reg);
- change = (val & args->mask) != (ucontrol->value.integer.value[0] ? args->mask : 0);
+ change = (val & args->mask) != (ucontrol->value.integer.value[0] ?
+ args->mask_on : (args->mask & ~args->mask_on));
if (change) {
val &= ~args->mask;
if (ucontrol->value.integer.value[0])
@@ -2862,7 +2863,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
cm->iobase = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_cmipci_interrupt,
- IRQF_DISABLED|IRQF_SHARED, card->driver, cm)) {
+ IRQF_SHARED, card->driver, cm)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cmipci_free(cm);
return -EBUSY;
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 0905fa88129..8e5519de711 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1391,7 +1391,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card,
return -ENOMEM;
}
- if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED,
"CS4281", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cs4281_free(chip);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 2807b9756ef..2ae539b195f 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3867,7 +3867,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card,
}
}
- if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
"CS46XX", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cs46xx_free(chip);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 2441238f200..b8e75ef9c1e 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -320,7 +320,7 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card,
cs5535au->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_cs5535audio_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "CS5535 Audio", cs5535au)) {
+ IRQF_SHARED, "CS5535 Audio", cs5535au)) {
snd_printk("unable to grab IRQ %d\n", pci->irq);
err = -EBUSY;
goto sndfail;
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index e5e88fe54de..047e0b5bf15 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1872,7 +1872,7 @@ static int snd_echo_free(struct echoaudio *chip)
DE_INIT(("Stopped.\n"));
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
if (chip->dsp_registers)
iounmap(chip->dsp_registers);
@@ -1950,8 +1950,8 @@ static __devinit int snd_echo_create(struct snd_card *card,
chip->dsp_registers = (volatile u32 __iomem *)
ioremap_nocache(chip->dsp_registers_phys, sz);
- if (request_irq(pci->irq, snd_echo_interrupt, IRQF_DISABLED | IRQF_SHARED,
- ECHOCARD_NAME, (void *)chip)) {
+ if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
+ ECHOCARD_NAME, chip)) {
snd_echo_free(chip);
snd_printk(KERN_ERR "cannot grab irq\n");
return -EBUSY;
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index e31f0f11e3a..91f5bff66d3 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -213,7 +213,7 @@ static void snd_echo_midi_output_write(unsigned long data)
sent = bytes = 0;
spin_lock_irqsave(&chip->lock, flags);
chip->midi_full = 0;
- if (chip->midi_out && !snd_rawmidi_transmit_empty(chip->midi_out)) {
+ if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
MIDI_OUT_BUFFER_SIZE - 1);
DE_MID(("Try to send %d bytes...\n", bytes));
@@ -264,9 +264,11 @@ static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream
}
} else {
if (chip->tinuse) {
- del_timer(&chip->timer);
chip->tinuse = 0;
+ spin_unlock_irq(&chip->lock);
+ del_timer_sync(&chip->timer);
DE_MID(("Timer removed\n"));
+ return;
}
}
spin_unlock_irq(&chip->lock);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 8bc4ffa6220..972ec40d816 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -759,7 +759,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
free_pm_buffer(emu);
#endif
if (emu->irq >= 0)
- free_irq(emu->irq, (void *)emu);
+ free_irq(emu->irq, emu);
if (emu->port)
pci_release_regions(emu->pci);
if (emu->card_capabilities->ca0151_chip) /* P16V */
@@ -1246,7 +1246,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
}
emu->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_DISABLED|IRQF_SHARED, "EMU10K1", (void *)emu)) {
+ if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED,
+ "EMU10K1", emu)) {
err = -EBUSY;
goto error;
}
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index c46905a1117..2199b42a601 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -235,7 +235,7 @@ struct emu10k1x {
struct resource *res_port;
int irq;
- unsigned int revision; /* chip revision */
+ unsigned char revision; /* chip revision */
unsigned int serial; /* serial number */
unsigned short model; /* subsystem id */
@@ -760,7 +760,7 @@ static int snd_emu10k1x_free(struct emu10k1x *chip)
// release the irq
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
// release the DMA
if (chip->dma_buffer.area) {
@@ -927,8 +927,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card,
}
if (request_irq(pci->irq, snd_emu10k1x_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "EMU10K1X",
- (void *)chip)) {
+ IRQF_SHARED, "EMU10K1X", chip)) {
snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq);
snd_emu10k1x_free(chip);
return -EBUSY;
@@ -943,7 +942,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card,
pci_set_master(pci);
/* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&chip->revision);
+ pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index d2a811f222c..a84f6b21024 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2141,7 +2141,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
return err;
}
ensoniq->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED,
"Ensoniq AudioPCI", ensoniq)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_ensoniq_free(ensoniq);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 1a8d36df4b5..66ac26c5a24 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1508,7 +1508,7 @@ static int es1938_resume(struct pci_dev *pci)
}
if (request_irq(pci->irq, snd_es1938_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "ES1938", chip)) {
+ IRQF_SHARED, "ES1938", chip)) {
printk(KERN_ERR "es1938: unable to grab IRQ %d, "
"disabling device\n", pci->irq);
snd_card_disconnect(card);
@@ -1631,7 +1631,7 @@ static int __devinit snd_es1938_create(struct snd_card *card,
chip->vc_port = pci_resource_start(pci, 2);
chip->mpu_port = pci_resource_start(pci, 3);
chip->game_port = pci_resource_start(pci, 4);
- if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED,
"ES1938", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_es1938_free(chip);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 092da53e146..dc84c189b05 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1337,7 +1337,7 @@ static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size)
struct esm_memory *buf;
struct list_head *p;
- size = ((size + ESM_MEM_ALIGN - 1) / ESM_MEM_ALIGN) * ESM_MEM_ALIGN;
+ size = ALIGN(size, ESM_MEM_ALIGN);
mutex_lock(&chip->memory_mutex);
list_for_each(p, &chip->buf_list) {
buf = list_entry(p, struct esm_memory, list);
@@ -2462,7 +2462,7 @@ static int snd_es1968_free(struct es1968 *chip)
}
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
snd_es1968_free_gameport(chip);
chip->master_switch = NULL;
chip->master_volume = NULL;
@@ -2552,8 +2552,8 @@ static int __devinit snd_es1968_create(struct snd_card *card,
return err;
}
chip->io_port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_DISABLED|IRQF_SHARED,
- "ESS Maestro", (void*)chip)) {
+ if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED,
+ "ESS Maestro", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_es1968_free(chip);
return -EBUSY;
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 77e3d5c1830..b7b361ce3a9 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1395,7 +1395,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
}
chip->port = pci_resource_start(pci, 0);
if ((tea575x_tuner & 0x0010) == 0) {
- if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED,
"FM801", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq);
snd_fm801_free(chip);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 71482c15a85..18bbc87e376 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1367,9 +1367,6 @@ static struct hda_rate_tbl rate_bits[] = {
{ 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
{ 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
- /* not autodetected value */
- { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
-
{ 0 } /* terminator */
};
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 97e9af130b7..1589d2f2917 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -485,8 +485,9 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
return "Front Aux";
return "Aux";
case AC_JACK_MIC_IN:
- if (node->pin_caps &
- (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT))
+ if (pinctl &&
+ (node->pin_caps &
+ (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT)))
*pinctl |= AC_PINCTL_VREF_80;
if ((location & 0x0f) == AC_JACK_LOC_FRONT)
return "Front Mic";
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index e35cfd326df..1a7e82104bb 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -83,6 +83,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH7},"
"{Intel, ESB2},"
"{Intel, ICH8},"
+ "{Intel, ICH9},"
"{ATI, SB450},"
"{ATI, SB600},"
"{ATI, RS600},"
@@ -1380,7 +1381,8 @@ static int __devinit azx_init_stream(struct azx *chip)
static int azx_acquire_irq(struct azx *chip, int do_disconnect)
{
- if (request_irq(chip->pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(chip->pci->irq, azx_interrupt,
+ chip->msi ? 0 : IRQF_SHARED,
"HDA Intel", chip)) {
printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
"disabling device\n", chip->pci->irq);
@@ -1710,6 +1712,8 @@ static struct pci_device_id azx_ids[] = {
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
+ { 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+ { 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
@@ -1717,9 +1721,14 @@ static struct pci_device_id azx_ids[] = {
{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
- { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */
- { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */
- { 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 03f0 */
+ { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
+ { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
+ { 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+ { 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+ { 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+ { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+ { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+ { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index d737f17695a..17df4d0fe13 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -45,7 +45,7 @@ static const char *get_wid_type_name(unsigned int wid_value)
if (names[wid_value])
return names[wid_value];
else
- return "UNKOWN Widget";
+ return "UNKNOWN Widget";
}
static void print_amp_caps(struct snd_info_buffer *buffer,
@@ -88,6 +88,48 @@ static void print_amp_vals(struct snd_info_buffer *buffer,
snd_iprintf(buffer, "\n");
}
+static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
+{
+ static unsigned int rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+ 96000, 176400, 192000, 384000
+ };
+ int i;
+
+ pcm &= AC_SUPPCM_RATES;
+ snd_iprintf(buffer, " rates [0x%x]:", pcm);
+ for (i = 0; i < ARRAY_SIZE(rates); i++)
+ if (pcm & (1 << i))
+ snd_iprintf(buffer, " %d", rates[i]);
+ snd_iprintf(buffer, "\n");
+}
+
+static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
+{
+ static unsigned int bits[] = { 8, 16, 20, 24, 32 };
+ int i;
+
+ pcm = (pcm >> 16) & 0xff;
+ snd_iprintf(buffer, " bits [0x%x]:", pcm);
+ for (i = 0; i < ARRAY_SIZE(bits); i++)
+ if (pcm & (1 << i))
+ snd_iprintf(buffer, " %d", bits[i]);
+ snd_iprintf(buffer, "\n");
+}
+
+static void print_pcm_formats(struct snd_info_buffer *buffer,
+ unsigned int streams)
+{
+ snd_iprintf(buffer, " formats [0x%x]:", streams & 0xf);
+ if (streams & AC_SUPFMT_PCM)
+ snd_iprintf(buffer, " PCM");
+ if (streams & AC_SUPFMT_FLOAT32)
+ snd_iprintf(buffer, " FLOAT");
+ if (streams & AC_SUPFMT_AC3)
+ snd_iprintf(buffer, " AC3");
+ snd_iprintf(buffer, "\n");
+}
+
static void print_pcm_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
@@ -97,8 +139,9 @@ static void print_pcm_caps(struct snd_info_buffer *buffer,
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);
+ print_pcm_rates(buffer, pcm);
+ print_pcm_bits(buffer, pcm);
+ print_pcm_formats(buffer, stream);
}
static const char *get_jack_location(u32 cfg)
@@ -210,7 +253,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
if (! codec->afg)
return;
- snd_iprintf(buffer, "Default PCM: ");
+ snd_iprintf(buffer, "Default PCM:\n");
print_pcm_caps(buffer, codec, codec->afg);
snd_iprintf(buffer, "Default Amp-In caps: ");
print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
@@ -278,7 +321,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
if ((wid_type == AC_WID_AUD_OUT || wid_type == AC_WID_AUD_IN) &&
(wid_caps & AC_WCAP_FORMAT_OVRD)) {
- snd_iprintf(buffer, " PCM: ");
+ snd_iprintf(buffer, " PCM:\n");
print_pcm_caps(buffer, codec, nid);
}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index edd22dec828..076365bc10e 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -794,6 +794,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
{ .modelname = "3stack", .config = AD1986A_3STACK },
{ .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84,
.config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x817f,
+ .config = AD1986A_3STACK }, /* ASUS P5P-L2 */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3,
.config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81cb,
@@ -811,7 +813,7 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc024,
.config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc026,
- .config = AD1986A_LAPTOP_EAPD }, /* Samsung X10-T2300 Culesa */
+ .config = AD1986A_LAPTOP_EAPD }, /* Samsung X11-T2300 Culesa */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1153,
.config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1213,
@@ -822,6 +824,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
.config = AD1986A_LAPTOP_EAPD }, /* ASUS U5F */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1297,
.config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x12b3,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS V1j */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
.config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
{ .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066,
@@ -1640,7 +1644,7 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
spec->num_channel_mode,
&spec->multiout.max_channels);
- if (! err && spec->need_dac_fix)
+ if (err >= 0 && spec->need_dac_fix)
spec->multiout.num_dacs = spec->multiout.max_channels / 2;
return err;
}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index fb961448db1..4e0c3c1b908 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -271,7 +271,7 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
spec->num_channel_mode,
&spec->multiout.max_channels);
- if (! err && spec->need_dac_fix)
+ if (err >= 0 && spec->need_dac_fix)
spec->multiout.num_dacs = spec->multiout.max_channels / 2;
return err;
}
@@ -5070,6 +5070,8 @@ static struct hda_board_config alc883_cfg_tbl[] = {
{ .modelname = "6stack-dig", .config = ALC883_6ST_DIG },
{ .pci_subvendor = 0x1462, .pci_subdevice = 0x6668,
.config = ALC883_6ST_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x7280,
+ .config = ALC883_6ST_DIG }, /* MSI K9A Platinum (MS-7280) */
{ .pci_subvendor = 0x105b, .pci_subdevice = 0x6668,
.config = ALC883_6ST_DIG }, /* Foxconn */
{ .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD },
@@ -5872,6 +5874,8 @@ static struct hda_board_config alc262_cfg_tbl[] = {
{ .modelname = "hp-bpc", .config = ALC262_HP_BPC },
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x280c,
.config = ALC262_HP_BPC }, /* xw4400 */
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x2801,
+ .config = ALC262_HP_BPC }, /* q965 */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014,
.config = ALC262_HP_BPC }, /* xw6400 */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3015,
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index cc87dff1eb5..ed5e45e3596 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -243,7 +243,8 @@ static int si3054_init(struct hda_codec *codec)
if((val&SI3054_MEI_READY) != SI3054_MEI_READY) {
snd_printk(KERN_ERR "si3054: cannot initialize. EXT MID = %04x\n", val);
- return -EACCES;
+ /* let's pray that this is no fatal error */
+ /* return -EACCES; */
}
SET_REG(codec, SI3054_GPIO_POLARITY, 0xffff);
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 8a576b78bee..8ba31cfb904 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2614,7 +2614,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
ice->dmapath_port = pci_resource_start(pci, 2);
ice->profi_port = pci_resource_start(pci, 3);
- if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED,
"ICE1712", ice)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_ice1712_free(ice);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index e9cbfdf3705..3e3a102e6c3 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2253,7 +2253,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
ice->profi_port = pci_resource_start(pci, 1);
if (request_irq(pci->irq, snd_vt1724_interrupt,
- IRQF_DISABLED|IRQF_SHARED, "ICE1724", ice)) {
+ IRQF_SHARED, "ICE1724", ice)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_vt1724_free(ice);
return -EIO;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 9c1bce7afa8..30aaa6092a8 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2509,7 +2509,7 @@ static int intel8x0_resume(struct pci_dev *pci)
}
pci_set_master(pci);
if (request_irq(pci->irq, snd_intel8x0_interrupt,
- IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) {
+ IRQF_SHARED, card->shortname, chip)) {
printk(KERN_ERR "intel8x0: unable to grab IRQ %d, "
"disabling device\n", pci->irq);
snd_card_disconnect(card);
@@ -2887,7 +2887,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
/* request irq after initializaing int_sta_mask, etc */
if (request_irq(pci->irq, snd_intel8x0_interrupt,
- IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) {
+ IRQF_SHARED, card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_intel8x0_free(chip);
return -EBUSY;
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index bd467c50112..09dcf923b54 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1071,7 +1071,7 @@ static int intel8x0m_resume(struct pci_dev *pci)
}
pci_set_master(pci);
if (request_irq(pci->irq, snd_intel8x0_interrupt,
- IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) {
+ IRQF_SHARED, card->shortname, chip)) {
printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "
"disabling device\n", pci->irq);
snd_card_disconnect(card);
@@ -1205,7 +1205,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
}
port_inited:
- if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED,
card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_intel8x0_free(chip);
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index fa8cd8cecc2..345eefeedb3 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2233,7 +2233,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
}
err = request_irq(pci->irq, snd_korg1212_interrupt,
- IRQF_DISABLED|IRQF_SHARED,
+ IRQF_SHARED,
"korg1212", korg1212);
if (err) {
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 8cab342bbaa..6efe6d5ade1 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2377,7 +2377,7 @@ static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma
* shifted list address is aligned.
* list address = (mem address >> 1) >> 7;
*/
- data_bytes = (data_bytes + 255) & ~255;
+ data_bytes = ALIGN(data_bytes, 256);
address = 0x1100 + ((data_bytes/2) * index);
if ((address + (data_bytes/2)) >= 0x1c00) {
@@ -2762,7 +2762,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
- if (request_irq(pci->irq, snd_m3_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_m3_free(chip);
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 216aee5f93e..21386da3bc8 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1066,7 +1066,7 @@ static int snd_mixart_free(struct mixart_mgr *mgr)
/* release irq */
if (mgr->irq >= 0)
- free_irq(mgr->irq, (void *)mgr);
+ free_irq(mgr->irq, mgr);
/* reset board if some firmware was loaded */
if(mgr->dsp_loaded) {
@@ -1319,7 +1319,8 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
pci_resource_len(pci, i));
}
- if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_DISABLED|IRQF_SHARED, CARD_NAME, (void *)mgr)) {
+ if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED,
+ CARD_NAME, mgr)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_mixart_free(mgr);
return -EBUSY;
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 945d21bf187..879e31a9f9c 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -465,7 +465,7 @@ static int snd_nm256_acquire_irq(struct nm256 *chip)
{
mutex_lock(&chip->irq_mutex);
if (chip->irq < 0) {
- if (request_irq(chip->pci->irq, chip->interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED,
chip->card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq);
mutex_unlock(&chip->irq_mutex);
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 533c672ae8f..d97413484ae 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1250,7 +1250,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id
mgr->pci = pci;
mgr->irq = -1;
- if (request_irq(pci->irq, pcxhr_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED,
card_name, mgr)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
pcxhr_free(mgr);
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 56e0c01123e..5e1d5d2b285 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1899,9 +1899,8 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
hwport = (struct riptideport *)chip->port;
UNSET_AIE(hwport);
- if (request_irq
- (pci->irq, snd_riptide_interrupt, IRQF_DISABLED | IRQF_SHARED,
- "RIPTIDE", chip)) {
+ if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED,
+ "RIPTIDE", chip)) {
snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
pci->irq);
snd_riptide_free(chip);
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index dc8d1302e22..6bb7ac650ec 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1373,7 +1373,8 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
return -ENOMEM;
}
- if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_DISABLED | IRQF_SHARED, "RME32", (void *) rme32)) {
+ if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED,
+ "RME32", rme32)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
return -EBUSY;
}
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 106110a89a4..e3304b7ccbc 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1587,7 +1587,8 @@ snd_rme96_create(struct rme96 *rme96)
return -ENOMEM;
}
- if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_DISABLED|IRQF_SHARED, "RME96", (void *)rme96)) {
+ if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED,
+ "RME96", rme96)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
return -EBUSY;
}
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 694aa057ed4..6383987b460 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3516,8 +3516,8 @@ static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
/* Align to bus-space 64K boundary */
- cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
- pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+ cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
+ pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
/* Tell the card where it is */
@@ -4934,13 +4934,14 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
return -EBUSY;
}
- if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_DISABLED|IRQF_SHARED, "hdsp", (void *)hdsp)) {
+ if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
+ "hdsp", hdsp)) {
snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
return -EBUSY;
}
hdsp->irq = pci->irq;
- hdsp->precise_ptr = 1;
+ hdsp->precise_ptr = 0;
hdsp->use_midi_tasklet = 1;
if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 7055d893855..0547f6f04bd 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -3496,8 +3496,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp
hdspm->port + io_extent - 1);
if (request_irq(pci->irq, snd_hdspm_interrupt,
- IRQF_DISABLED | IRQF_SHARED, "hdspm",
- (void *) hdspm)) {
+ IRQF_SHARED, "hdspm", hdspm)) {
snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
return -EBUSY;
}
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index cf0427b4bfd..cc3bdececce 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1827,8 +1827,8 @@ static int __devinit snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
/* Align to bus-space 64K boundary */
- cb_bus = (rme9652->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
- pb_bus = (rme9652->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+ cb_bus = ALIGN(rme9652->capture_dma_buf.addr, 0x10000ul);
+ pb_bus = ALIGN(rme9652->playback_dma_buf.addr, 0x10000ul);
/* Tell the card where it is */
@@ -2500,7 +2500,8 @@ static int __devinit snd_rme9652_create(struct snd_card *card,
return -EBUSY;
}
- if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_DISABLED|IRQF_SHARED, "rme9652", (void *)rme9652)) {
+ if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED,
+ "rme9652", rme9652)) {
snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq);
return -EBUSY;
}
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index f9b8afabda9..9f25d93cbec 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1195,7 +1195,7 @@ static int snd_sonicvibes_free(struct sonicvibes *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)
- free_irq(sonic->irq, (void *)sonic);
+ free_irq(sonic->irq, sonic);
release_and_free_resource(sonic->res_dmaa);
release_and_free_resource(sonic->res_dmac);
pci_release_regions(sonic->pci);
@@ -1257,7 +1257,8 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
sonic->midi_port = pci_resource_start(pci, 3);
sonic->game_port = pci_resource_start(pci, 4);
- if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_DISABLED|IRQF_SHARED, "S3 SonicVibes", (void *)sonic)) {
+ if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,
+ "S3 SonicVibes", sonic)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_sonicvibes_free(sonic);
return -EBUSY;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 1fbc4321122..474f2d451ae 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3380,8 +3380,8 @@ static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
return -ENOMEM;
}
- trident->tlb.entries = (unsigned int*)(((unsigned long)trident->tlb.buffer.area + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
- trident->tlb.entries_dmaaddr = (trident->tlb.buffer.addr + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
+ trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
+ trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
/* allocate shadow TLB page table (virtual addresses) */
trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
if (trident->tlb.shadow_entries == NULL) {
@@ -3608,7 +3608,7 @@ int __devinit snd_trident_create(struct snd_card *card,
}
trident->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_trident_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
"Trident Audio", trident)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_trident_free(trident);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 92b0736c0fd..a572b018807 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2307,7 +2307,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
if (request_irq(pci->irq,
chip_type == TYPE_VIA8233 ?
snd_via8233_interrupt : snd_via686_interrupt,
- IRQF_DISABLED|IRQF_SHARED,
+ IRQF_SHARED,
card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_via82xx_free(chip);
@@ -2366,7 +2366,7 @@ struct dxs_whitelist {
static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
{
- static struct dxs_whitelist whitelist[] = {
+ static struct dxs_whitelist whitelist[] __devinitdata = {
{ .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
{ .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
{ .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
@@ -2427,7 +2427,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
{ .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */
{ } /* terminator */
};
- struct dxs_whitelist *w;
+ const struct dxs_whitelist *w;
unsigned short subsystem_vendor;
unsigned short subsystem_device;
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index feb27c96625..17d6b847585 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1124,7 +1124,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card,
return err;
}
chip->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED,
card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_via82xx_free(chip);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index af49e8aabf5..89f58ea180b 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -169,8 +169,8 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci
for (i = 0; i < 2; i++)
vx->port[i] = pci_resource_start(pci, i + 1);
- if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_DISABLED|IRQF_SHARED,
- CARD_NAME, (void *) chip)) {
+ if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED,
+ CARD_NAME, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_vx222_free(chip);
return -EBUSY;
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 186453f7abe..fd9b7b83a88 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -49,7 +49,6 @@ static long mpu_port[SNDRV_CARDS];
static long joystick_port[SNDRV_CARDS];
#endif
static int rear_switch[SNDRV_CARDS];
-static int rear_swap[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard.");
@@ -67,8 +66,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address");
#endif
module_param_array(rear_switch, bool, NULL, 0444);
MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
-module_param_array(rear_swap, bool, NULL, 0444);
-MODULE_PARM_DESC(rear_swap, "Swap rear channels (must be enabled for correct IEC958 (S/PDIF)) output");
static struct pci_device_id snd_ymfpci_ids[] = {
{ 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */
@@ -298,7 +295,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_mixer(chip, rear_switch[dev], rear_swap[dev])) < 0) {
+ if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index a40c1085fd2..7881944a195 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -910,7 +910,7 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream)
ypcm = runtime->private_data;
ypcm->output_front = 1;
ypcm->output_rear = chip->mode_dup4ch ? 1 : 0;
- ypcm->swap_rear = chip->rear_swap;
+ ypcm->swap_rear = 0;
spin_lock_irq(&chip->reg_lock);
if (ypcm->output_rear) {
ymfpci_open_extension(chip);
@@ -936,6 +936,7 @@ static int snd_ymfpci_playback_spdif_open(struct snd_pcm_substream *substream)
ypcm = runtime->private_data;
ypcm->output_front = 0;
ypcm->output_rear = 1;
+ ypcm->swap_rear = 1;
spin_lock_irq(&chip->reg_lock);
snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2);
@@ -963,6 +964,7 @@ static int snd_ymfpci_playback_4ch_open(struct snd_pcm_substream *substream)
ypcm = runtime->private_data;
ypcm->output_front = 0;
ypcm->output_rear = 1;
+ ypcm->swap_rear = 0;
spin_lock_irq(&chip->reg_lock);
ymfpci_open_extension(chip);
chip->rear_opened++;
@@ -1755,7 +1757,7 @@ static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97)
chip->ac97 = NULL;
}
-int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch, int rear_swap)
+int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
{
struct snd_ac97_template ac97;
struct snd_kcontrol *kctl;
@@ -1767,7 +1769,6 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch, int rea
.read = snd_ymfpci_codec_read,
};
- chip->rear_swap = rear_swap;
if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
return err;
chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus;
@@ -2025,10 +2026,10 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
chip->bank_size_effect = snd_ymfpci_readl(chip, YDSXGR_EFFCTRLSIZE) << 2;
chip->work_size = YDSXG_DEFAULT_WORK_SIZE;
- size = ((playback_ctrl_size + 0x00ff) & ~0x00ff) +
- ((chip->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES + 0x00ff) & ~0x00ff) +
- ((chip->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES + 0x00ff) & ~0x00ff) +
- ((chip->bank_size_effect * 2 * YDSXG_EFFECT_VOICES + 0x00ff) & ~0x00ff) +
+ size = ALIGN(playback_ctrl_size, 0x100) +
+ ALIGN(chip->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES, 0x100) +
+ ALIGN(chip->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES, 0x100) +
+ ALIGN(chip->bank_size_effect * 2 * YDSXG_EFFECT_VOICES, 0x100) +
chip->work_size;
/* work_ptr must be aligned to 256 bytes, but it's already
covered with the kernel page allocation mechanism */
@@ -2043,8 +2044,8 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
chip->bank_base_playback_addr = ptr_addr;
chip->ctrl_playback = (u32 *)ptr;
chip->ctrl_playback[0] = cpu_to_le32(YDSXG_PLAYBACK_VOICES);
- ptr += (playback_ctrl_size + 0x00ff) & ~0x00ff;
- ptr_addr += (playback_ctrl_size + 0x00ff) & ~0x00ff;
+ ptr += ALIGN(playback_ctrl_size, 0x100);
+ ptr_addr += ALIGN(playback_ctrl_size, 0x100);
for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) {
chip->voices[voice].number = voice;
chip->voices[voice].bank = (struct snd_ymfpci_playback_bank *)ptr;
@@ -2055,8 +2056,8 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
ptr_addr += chip->bank_size_playback;
}
}
- ptr = (char *)(((unsigned long)ptr + 0x00ff) & ~0x00ff);
- ptr_addr = (ptr_addr + 0x00ff) & ~0x00ff;
+ ptr = (char *)ALIGN((unsigned long)ptr, 0x100);
+ ptr_addr = ALIGN(ptr_addr, 0x100);
chip->bank_base_capture = ptr;
chip->bank_base_capture_addr = ptr_addr;
for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++)
@@ -2065,8 +2066,8 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
ptr += chip->bank_size_capture;
ptr_addr += chip->bank_size_capture;
}
- ptr = (char *)(((unsigned long)ptr + 0x00ff) & ~0x00ff);
- ptr_addr = (ptr_addr + 0x00ff) & ~0x00ff;
+ ptr = (char *)ALIGN((unsigned long)ptr, 0x100);
+ ptr_addr = ALIGN(ptr_addr, 0x100);
chip->bank_base_effect = ptr;
chip->bank_base_effect_addr = ptr_addr;
for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++)
@@ -2075,8 +2076,8 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
ptr += chip->bank_size_effect;
ptr_addr += chip->bank_size_effect;
}
- ptr = (char *)(((unsigned long)ptr + 0x00ff) & ~0x00ff);
- ptr_addr = (ptr_addr + 0x00ff) & ~0x00ff;
+ ptr = (char *)ALIGN((unsigned long)ptr, 0x100);
+ ptr_addr = ALIGN(ptr_addr, 0x100);
chip->work_base = ptr;
chip->work_base_addr = ptr_addr;
@@ -2153,7 +2154,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
snd_dma_free_pages(&chip->work_ptr);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
release_and_free_resource(chip->res_reg_area);
pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
@@ -2290,7 +2291,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
chip->pci = pci;
chip->irq = -1;
chip->device_id = pci->device;
- pci_read_config_byte(pci, PCI_REVISION_ID, (u8 *)&chip->rev);
+ pci_read_config_byte(pci, PCI_REVISION_ID, &chip->rev);
chip->reg_area_phys = pci_resource_start(pci, 0);
chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
pci_set_master(pci);
@@ -2300,7 +2301,8 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
snd_ymfpci_free(chip);
return -EBUSY;
}
- if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_DISABLED|IRQF_SHARED, "YMFPCI", (void *) chip)) {
+ if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED,
+ "YMFPCI", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_ymfpci_free(chip);
return -EBUSY;
@@ -2322,7 +2324,6 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
return -EIO;
}
- chip->rear_swap = 1;
if ((err = snd_ymfpci_ac3_init(chip)) < 0) {
snd_ymfpci_free(chip);
return err;
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
index 3a181d4c0dc..3304344713a 100644
--- a/sound/sound_firmware.c
+++ b/sound/sound_firmware.c
@@ -19,7 +19,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
printk(KERN_INFO "Unable to load '%s'.\n", fn);
return 0;
}
- l = filp->f_dentry->d_inode->i_size;
+ l = filp->f_path.dentry->d_inode->i_size;
if (l <= 0 || l > 131072)
{
printk(KERN_INFO "Invalid firmware '%s'\n", fn);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index edeb3d3c4c7..f5956d557f7 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1268,7 +1268,7 @@ static struct snd_pcm_hardware snd_cs4231_playback =
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (32*1024),
- .period_bytes_min = 4096,
+ .period_bytes_min = 64,
.period_bytes_max = (32*1024),
.periods_min = 1,
.periods_max = 1024,
@@ -1288,7 +1288,7 @@ static struct snd_pcm_hardware snd_cs4231_capture =
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (32*1024),
- .period_bytes_min = 4096,
+ .period_bytes_min = 64,
.period_bytes_max = (32*1024),
.periods_min = 1,
.periods_max = 1024,
@@ -1796,7 +1796,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id)
snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
spin_unlock_irqrestore(&chip->lock, flags);
- return 0;
+ return IRQ_HANDLED;
}
/*
@@ -1821,7 +1821,6 @@ static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_
if (!(csr & test))
goto out;
err = -EBUSY;
- csr = sbus_readl(base->regs + APCCSR);
test = APC_XINT_CNVA;
if ( base->dir == APC_PLAY )
test = APC_XINT_PNVA;
@@ -1862,17 +1861,16 @@ static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
spin_lock_irqsave(&base->lock, flags);
if (!on) {
- if (base->dir == APC_PLAY) {
- sbus_writel(0, base->regs + base->dir + APCNVA);
- sbus_writel(1, base->regs + base->dir + APCC);
- }
- else
- {
- sbus_writel(0, base->regs + base->dir + APCNC);
- sbus_writel(0, base->regs + base->dir + APCVA);
- }
+ sbus_writel(0, base->regs + base->dir + APCNC);
+ sbus_writel(0, base->regs + base->dir + APCNVA);
+ sbus_writel(0, base->regs + base->dir + APCC);
+ sbus_writel(0, base->regs + base->dir + APCVA);
+
+ /* ACK any APC interrupts. */
+ csr = sbus_readl(base->regs + APCCSR);
+ sbus_writel(csr, base->regs + APCCSR);
}
- udelay(600);
+ udelay(1000);
csr = sbus_readl(base->regs + APCCSR);
shift = 0;
if ( base->dir == APC_PLAY )
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 67202b9eeb7..19bdcc74c96 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2471,7 +2471,13 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
fp->nr_rates = nr_rates;
fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
- unsigned int rate = fp->rate_table[r] = combine_triple(&fmt[idx]);
+ unsigned int rate = combine_triple(&fmt[idx]);
+ /* C-Media CM6501 mislabels its 96 kHz altsetting */
+ if (rate == 48000 && nr_rates == 1 &&
+ chip->usb_id == USB_ID(0x0d8c, 0x0201) &&
+ fp->altsetting == 5 && fp->maxpacksize == 392)
+ rate = 96000;
+ fp->rate_table[r] = rate;
if (rate < fp->rate_min)
fp->rate_min = rate;
else if (rate > fp->rate_max)
@@ -3280,6 +3286,7 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
+ usb_chip[chip->index] = NULL;
kfree(chip);
return 0;
}
@@ -3541,7 +3548,6 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
list_for_each(p, &chip->mixer_list) {
snd_usb_mixer_disconnect(p);
}
- usb_chip[chip->index] = NULL;
mutex_unlock(&register_mutex);
snd_card_free_when_closed(card);
} else {
@@ -3577,8 +3583,7 @@ static int __init snd_usb_audio_init(void)
printk(KERN_WARNING "invalid nrpacks value.\n");
return -EINVAL;
}
- usb_register(&usb_audio_driver);
- return 0;
+ return usb_register(&usb_audio_driver);
}
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index e74eb1bc8d8..7b3bf3545a3 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -1526,7 +1526,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
if (! namelist[i]) {
snd_printk(KERN_ERR "cannot malloc\n");
- while (--i > 0)
+ while (i--)
kfree(namelist[i]);
kfree(namelist);
kfree(cval);
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 367f8a32a66..0a352e46862 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -322,7 +322,7 @@ static void i_usX2Y_urb_complete(struct urb *urb)
usX2Y_error_urb_status(usX2Y, subs, urb);
return;
}
- if (likely(urb->start_frame == usX2Y->wait_iso_frame))
+ if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
subs->completed_urb = urb;
else {
usX2Y_error_sequence(usX2Y, subs, urb);
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 8f3e35e24e7..a5e7bcd7ca2 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -243,7 +243,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
usX2Y_error_urb_status(usX2Y, subs, urb);
return;
}
- if (likely(urb->start_frame == usX2Y->wait_iso_frame))
+ if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
subs->completed_urb = urb;
else {
usX2Y_error_sequence(usX2Y, subs, urb);