summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS26
-rw-r--r--Documentation/CodingStyle21
-rw-r--r--Documentation/cciss.txt4
-rw-r--r--Documentation/dell_rbu.txt18
-rw-r--r--Documentation/dontdiff1
-rw-r--r--Documentation/feature-removal-schedule.txt9
-rw-r--r--Documentation/filesystems/relayfs.txt2
-rw-r--r--Documentation/ia64/mca.txt194
-rw-r--r--Documentation/kdump/kdump.txt11
-rw-r--r--Documentation/oops-tracing.txt25
-rw-r--r--Documentation/pm.txt6
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt124
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl10
-rw-r--r--MAINTAINERS18
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/kernel/osf_sys.c7
-rw-r--r--arch/alpha/kernel/sys_dp264.c41
-rw-r--r--arch/arm/common/locomo.c2
-rw-r--r--arch/arm/configs/enp2611_defconfig182
-rw-r--r--arch/arm/configs/ixdp2400_defconfig182
-rw-r--r--arch/arm/configs/ixdp2401_defconfig182
-rw-r--r--arch/arm/configs/ixdp2800_defconfig182
-rw-r--r--arch/arm/configs/ixdp2801_defconfig182
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/entry-common.S4
-rw-r--r--arch/arm/kernel/semaphore.c2
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c6
-rw-r--r--arch/arm/mach-pxa/Kconfig49
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/corgi.c94
-rw-r--r--arch/arm/mach-pxa/corgi_lcd.c197
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c66
-rw-r--r--arch/arm/mach-pxa/lubbock.c6
-rw-r--r--arch/arm/mach-pxa/poodle.c113
-rw-r--r--arch/arm/mach-pxa/sharpsl.h34
-rw-r--r--arch/arm/mach-pxa/spitz.c380
-rw-r--r--arch/arm/mach-sa1100/collie.c11
-rw-r--r--arch/arm/mach-sa1100/generic.h3
-rw-r--r--arch/arm26/boot/compressed/hw-bse.c74
-rw-r--r--arch/i386/Kconfig5
-rw-r--r--arch/i386/kernel/acpi/earlyquirk.c10
-rw-r--r--arch/i386/kernel/reboot.c7
-rw-r--r--arch/i386/kernel/setup.c4
-rw-r--r--arch/i386/kernel/smpboot.c2
-rw-r--r--arch/i386/kernel/traps.c5
-rw-r--r--arch/i386/lib/Makefile1
-rw-r--r--arch/i386/lib/dec_and_lock.c42
-rw-r--r--arch/ia64/Kconfig5
-rw-r--r--arch/ia64/Makefile12
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c6
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/asm-offsets.c1
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/mca_drv.c114
-rw-r--r--arch/ia64/kernel/mca_drv.h2
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S48
-rw-r--r--arch/ia64/kernel/perfmon.c5
-rw-r--r--arch/ia64/lib/Makefile1
-rw-r--r--arch/ia64/lib/dec_and_lock.c42
-rw-r--r--arch/m32r/Kconfig5
-rw-r--r--arch/mips/Kconfig4
-rw-r--r--arch/mips/kernel/sysirix.c9
-rw-r--r--arch/mips/lib/Makefile2
-rw-r--r--arch/mips/lib/dec_and_lock.c47
-rw-r--r--arch/ppc/Kconfig4
-rw-r--r--arch/ppc/kernel/temp.c1
-rw-r--r--arch/ppc/kernel/time.c1
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S4
-rw-r--r--arch/ppc/lib/Makefile2
-rw-r--r--arch/ppc/lib/dec_and_lock.c38
-rw-r--r--arch/ppc/platforms/chrp_time.c1
-rw-r--r--arch/ppc/syslib/Makefile3
-rw-r--r--arch/ppc/syslib/mpc8xx_devices.c224
-rw-r--r--arch/ppc/syslib/mpc8xx_sys.c61
-rw-r--r--arch/ppc/syslib/open_pic2.c2
-rw-r--r--arch/ppc/syslib/prep_nvram.c1
-rw-r--r--arch/ppc64/Kconfig4
-rw-r--r--arch/ppc64/kernel/asm-offsets.c1
-rw-r--r--arch/ppc64/kernel/entry.S18
-rw-r--r--arch/ppc64/kernel/head.S6
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c2
-rw-r--r--arch/ppc64/kernel/vdso.c15
-rw-r--r--arch/ppc64/lib/Makefile2
-rw-r--r--arch/ppc64/lib/dec_and_lock.c47
-rw-r--r--arch/ppc64/mm/fault.c1
-rw-r--r--arch/s390/defconfig36
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/entry.S2
-rw-r--r--arch/s390/kernel/entry64.S2
-rw-r--r--arch/s390/kernel/reipl_diag.c39
-rw-r--r--arch/s390/kernel/setup.c5
-rw-r--r--arch/s390/kernel/smp.c3
-rw-r--r--arch/sparc64/Kconfig.debug8
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c3
-rw-r--r--arch/sparc64/lib/Makefile2
-rw-r--r--arch/sparc64/lib/dec_and_lock.S80
-rw-r--r--arch/um/Kconfig.i3864
-rw-r--r--arch/um/drivers/mcast_user.c12
-rw-r--r--arch/um/drivers/mconsole_kern.c52
-rw-r--r--arch/um/drivers/mconsole_user.c7
-rw-r--r--arch/um/drivers/pty.c3
-rw-r--r--arch/um/drivers/ubd_user.c75
-rw-r--r--arch/um/drivers/xterm.c6
-rw-r--r--arch/um/include/mconsole.h1
-rw-r--r--arch/um/include/mem_user.h15
-rw-r--r--arch/um/include/os.h5
-rw-r--r--arch/um/kernel/Makefile16
-rw-r--r--arch/um/kernel/helper.c12
-rw-r--r--arch/um/kernel/init_task.c5
-rw-r--r--arch/um/kernel/mem.c16
-rw-r--r--arch/um/kernel/mem_user.c273
-rw-r--r--arch/um/kernel/process_kern.c19
-rw-r--r--arch/um/kernel/skas/include/mode_kern-skas.h2
-rw-r--r--arch/um/kernel/skas/process_kern.c7
-rw-r--r--arch/um/kernel/tempfile.c82
-rw-r--r--arch/um/kernel/tlb.c2
-rw-r--r--arch/um/kernel/tt/include/mode_kern-tt.h2
-rw-r--r--arch/um/kernel/tt/mem_user.c1
-rw-r--r--arch/um/kernel/tt/process_kern.c7
-rw-r--r--arch/um/kernel/um_arch.c5
-rw-r--r--arch/um/kernel/user_util.c12
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/aio.c9
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c8
-rw-r--r--arch/um/os-Linux/elf_aux.c3
-rw-r--r--arch/um/os-Linux/file.c82
-rw-r--r--arch/um/os-Linux/mem.c161
-rw-r--r--arch/um/os-Linux/start_up.c109
-rw-r--r--arch/um/os-Linux/tt.c14
-rw-r--r--arch/x86_64/Kconfig5
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c5
-rw-r--r--arch/x86_64/ia32/syscall32.c6
-rw-r--r--arch/x86_64/kernel/e820.c3
-rw-r--r--arch/x86_64/kernel/io_apic.c9
-rw-r--r--arch/x86_64/kernel/mce.c2
-rw-r--r--arch/x86_64/kernel/nmi.c8
-rw-r--r--arch/x86_64/kernel/setup.c15
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c4
-rw-r--r--arch/x86_64/lib/Makefile2
-rw-r--r--arch/x86_64/lib/dec_and_lock.c40
-rw-r--r--arch/xtensa/Kconfig4
-rw-r--r--drivers/base/attribute_container.c5
-rw-r--r--drivers/base/class.c10
-rw-r--r--drivers/base/firmware_class.c9
-rw-r--r--drivers/base/map.c3
-rw-r--r--drivers/base/platform.c3
-rw-r--r--drivers/block/cciss.c639
-rw-r--r--drivers/block/cciss.h10
-rw-r--r--drivers/block/cciss_cmd.h8
-rw-r--r--drivers/block/cciss_scsi.c69
-rw-r--r--drivers/block/paride/pf.c22
-rw-r--r--drivers/block/pktcdvd.c85
-rw-r--r--drivers/block/scsi_ioctl.c1
-rw-r--r--drivers/bluetooth/hci_usb.c19
-rw-r--r--drivers/bluetooth/hci_usb.h5
-rw-r--r--drivers/char/agp/hp-agp.c2
-rw-r--r--drivers/char/amiserial.c4
-rw-r--r--drivers/char/epca.c84
-rw-r--r--drivers/char/epca.h12
-rw-r--r--drivers/char/hvc_console.c6
-rw-r--r--drivers/char/vt.c5
-rw-r--r--drivers/char/watchdog/Kconfig93
-rw-r--r--drivers/char/watchdog/Makefile7
-rw-r--r--drivers/char/watchdog/i6300esb.c527
-rw-r--r--drivers/char/watchdog/ibmasr.c405
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c2
-rw-r--r--drivers/char/watchdog/mv64x60_wdt.c252
-rw-r--r--drivers/char/watchdog/pcwd_pci.c44
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c2
-rw-r--r--drivers/char/watchdog/sbc8360.c414
-rw-r--r--drivers/char/watchdog/w83977f_wdt.c543
-rw-r--r--drivers/firmware/dell_rbu.c241
-rw-r--r--drivers/hwmon/hdaps.c356
-rw-r--r--drivers/i2c/busses/i2c-keywest.c1
-rw-r--r--drivers/i2c/busses/i2c-pxa.c12
-rw-r--r--drivers/ide/ide-iops.c41
-rw-r--r--drivers/ide/ide-taskfile.c1
-rw-r--r--drivers/ide/pci/cmd64x.c2
-rw-r--r--drivers/ide/pci/hpt34x.c2
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/spitzkbd.c478
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/corgi_ts.c70
-rw-r--r--drivers/isdn/hisax/hfc_pci.c1
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c2
-rw-r--r--drivers/isdn/hisax/st5481.h4
-rw-r--r--drivers/isdn/hisax/st5481_b.c22
-rw-r--r--drivers/isdn/hisax/st5481_d.c26
-rw-r--r--drivers/isdn/hisax/st5481_init.c4
-rw-r--r--drivers/isdn/hisax/st5481_usb.c70
-rw-r--r--drivers/isdn/sc/init.c4
-rw-r--r--drivers/md/raid6.h4
-rw-r--r--drivers/md/raid6algos.c1
-rw-r--r--drivers/md/raid6altivec.uc18
-rw-r--r--drivers/md/raid6test/Makefile27
-rw-r--r--drivers/media/radio/radio-aimslab.c2
-rw-r--r--drivers/media/radio/radio-aztech.c2
-rw-r--r--drivers/media/radio/radio-cadet.c2
-rw-r--r--drivers/media/radio/radio-gemtek.c2
-rw-r--r--drivers/media/radio/radio-rtrack2.c2
-rw-r--r--drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c2
-rw-r--r--drivers/media/radio/radio-terratec.c2
-rw-r--r--drivers/media/radio/radio-typhoon.c2
-rw-r--r--drivers/media/radio/radio-zoltrix.c2
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c7
-rw-r--r--drivers/mtd/maps/sharpsl-flash.c2
-rw-r--r--drivers/mtd/nand/sharpsl.c10
-rw-r--r--drivers/net/8139cp.c46
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/arcnet/com90io.c4
-rw-r--r--drivers/net/bonding/bond_main.c11
-rw-r--r--drivers/net/e100.c4
-rw-r--r--drivers/net/e1000/e1000_main.c1
-rw-r--r--drivers/net/ixgb/ixgb_main.c2
-rw-r--r--drivers/net/s2io.c9
-rw-r--r--drivers/net/sk98lin/skge.c12
-rw-r--r--drivers/net/skge.c98
-rw-r--r--drivers/net/skge.h2
-rw-r--r--drivers/net/spider_net.c4
-rw-r--r--drivers/net/tg3.c108
-rw-r--r--drivers/net/tulip/xircom_cb.c2
-rw-r--r--drivers/net/wan/hdlc_cisco.c2
-rw-r--r--drivers/net/wireless/airo.c5
-rw-r--r--drivers/net/wireless/orinoco_cs.c1
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c4
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c3
-rw-r--r--drivers/pci/pci.c16
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c12
-rw-r--r--drivers/pcmcia/yenta_socket.c13
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/crypto/z90main.c3
-rw-r--r--drivers/s390/net/ctcmain.c41
-rw-r--r--drivers/s390/net/qeth.h4
-rw-r--r--drivers/s390/net/qeth_main.c133
-rw-r--r--drivers/s390/net/qeth_sys.c17
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/scsi/libata-core.c37
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c21
-rw-r--r--drivers/scsi/sata_sis.c4
-rw-r--r--drivers/serial/21285.c2
-rw-r--r--drivers/serial/amba-pl010.c2
-rw-r--r--drivers/serial/amba-pl011.c2
-rw-r--r--drivers/serial/clps711x.c2
-rw-r--r--drivers/serial/mpc52xx_uart.c2
-rw-r--r--drivers/serial/pxa.c4
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_lh7a40x.c2
-rw-r--r--drivers/tc/zs.c2
-rw-r--r--drivers/video/Kconfig3
-rw-r--r--drivers/video/backlight/corgi_bl.c34
-rw-r--r--drivers/video/console/fbcon.c18
-rw-r--r--drivers/video/console/fbcon.h2
-rw-r--r--drivers/video/console/font_10x18.c4
-rw-r--r--drivers/video/console/font_6x11.c4
-rw-r--r--drivers/video/console/font_7x14.c4
-rw-r--r--drivers/video/console/font_8x16.c4
-rw-r--r--drivers/video/console/font_8x8.c4
-rw-r--r--drivers/video/console/font_acorn_8x8.c4
-rw-r--r--drivers/video/console/font_mini_4x6.c4
-rw-r--r--drivers/video/console/font_pearl_8x8.c4
-rw-r--r--drivers/video/console/font_sun12x22.c4
-rw-r--r--drivers/video/console/font_sun8x16.c4
-rw-r--r--drivers/video/console/fonts.c9
-rw-r--r--drivers/video/console/vgacon.c4
-rw-r--r--drivers/video/imxfb.c2
-rw-r--r--drivers/video/matrox/matroxfb_base.c13
-rw-r--r--drivers/video/nvidia/nv_i2c.c11
-rw-r--r--drivers/video/pm3fb.c3
-rw-r--r--drivers/video/savage/savagefb-i2c.c11
-rw-r--r--drivers/video/savage/savagefb.h4
-rw-r--r--drivers/video/savage/savagefb_driver.c11
-rw-r--r--fs/aio.c1
-rw-r--r--fs/compat.c4
-rw-r--r--fs/dcache.c3
-rw-r--r--fs/eventpoll.c40
-rw-r--r--fs/exec.c10
-rw-r--r--fs/fat/file.c37
-rw-r--r--fs/fat/inode.c15
-rw-r--r--fs/file.c10
-rw-r--r--fs/locks.c3
-rw-r--r--fs/namei.c2
-rw-r--r--fs/nfsd/nfs4proc.c24
-rw-r--r--fs/nfsd/nfs4state.c90
-rw-r--r--fs/ntfs/ChangeLog2
-rw-r--r--fs/ntfs/aops.c122
-rw-r--r--fs/ntfs/inode.c9
-rw-r--r--fs/ntfs/malloc.h2
-rw-r--r--fs/ntfs/runlist.c132
-rw-r--r--fs/open.c98
-rw-r--r--fs/proc/array.c3
-rw-r--r--fs/reiserfs/file.c11
-rw-r--r--fs/reiserfs/inode.c16
-rw-r--r--include/asm-alpha/pgtable.h7
-rw-r--r--include/asm-arm/arch-aaec2000/memory.h4
-rw-r--r--include/asm-arm/arch-iop3xx/memory.h2
-rw-r--r--include/asm-arm/arch-ixp2000/ixp2000-regs.h2
-rw-r--r--include/asm-arm/arch-ixp2000/platform.h16
-rw-r--r--include/asm-arm/arch-lh7a40x/memory.h4
-rw-r--r--include/asm-arm/arch-omap/memory.h1
-rw-r--r--include/asm-arm/arch-pxa/akita.h30
-rw-r--r--include/asm-arm/arch-pxa/corgi.h12
-rw-r--r--include/asm-arm/arch-pxa/memory.h4
-rw-r--r--include/asm-arm/arch-pxa/poodle.h25
-rw-r--r--include/asm-arm/arch-pxa/sharpsl.h32
-rw-r--r--include/asm-arm/arch-pxa/spitz.h158
-rw-r--r--include/asm-arm/arch-sa1100/memory.h4
-rw-r--r--include/asm-arm/futex.h2
-rw-r--r--include/asm-arm/hardware/arm_twd.h16
-rw-r--r--include/asm-arm/memory.h15
-rw-r--r--include/asm-arm/pgtable.h5
-rw-r--r--include/asm-arm26/pgtable.h5
-rw-r--r--include/asm-frv/pgtable.h3
-rw-r--r--include/asm-h8300/pgtable.h2
-rw-r--r--include/asm-i386/pgtable.h3
-rw-r--r--include/asm-ia64/pgtable.h4
-rw-r--r--include/asm-ia64/ptrace.h2
-rw-r--r--include/asm-ia64/thread_info.h7
-rw-r--r--include/asm-m32r/pgtable.h3
-rw-r--r--include/asm-m68k/pgtable.h3
-rw-r--r--include/asm-m68knommu/pgtable.h2
-rw-r--r--include/asm-mips/pgtable.h12
-rw-r--r--include/asm-parisc/pgtable.h3
-rw-r--r--include/asm-ppc/irq.h10
-rw-r--r--include/asm-ppc/mpc8xx.h16
-rw-r--r--include/asm-ppc/mv64x60.h8
-rw-r--r--include/asm-ppc/pgtable.h11
-rw-r--r--include/asm-ppc/ppc_sys.h2
-rw-r--r--include/asm-ppc/segment.h1
-rw-r--r--include/asm-ppc/tlbflush.h2
-rw-r--r--include/asm-sh/pgtable.h3
-rw-r--r--include/asm-sh64/pgtable.h3
-rw-r--r--include/asm-um/processor-generic.h1
-rw-r--r--include/asm-um/system-i386.h2
-rw-r--r--include/asm-x86_64/desc.h2
-rw-r--r--include/asm-x86_64/pgtable.h3
-rw-r--r--include/asm-xtensa/pgtable.h6
-rw-r--r--include/linux/audit.h36
-rw-r--r--include/linux/dccp.h59
-rw-r--r--include/linux/fb.h2
-rw-r--r--include/linux/font.h10
-rw-r--r--include/linux/i2c.h5
-rw-r--r--include/linux/if_vlan.h8
-rw-r--r--include/linux/joystick.h24
-rw-r--r--include/linux/kernel.h4
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h14
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_pptp.h332
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h114
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tuple.h7
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_pptp.h11
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h3
-rw-r--r--include/linux/netlink.h1
-rw-r--r--include/linux/nfsd/xdr4.h15
-rw-r--r--include/linux/pci_ids.h52
-rw-r--r--include/linux/pktcdvd.h3
-rw-r--r--include/linux/sched.h11
-rw-r--r--include/linux/security.h5
-rw-r--r--include/linux/tfrc.h35
-rw-r--r--include/linux/videodev2.h109
-rw-r--r--include/net/bluetooth/hci.h11
-rw-r--r--include/net/ip_vs.h3
-rw-r--r--include/sound/core.h8
-rw-r--r--include/sound/cs46xx.h14
-rw-r--r--include/sound/emu10k1.h7
-rw-r--r--include/sound/pcm.h5
-rw-r--r--include/sound/pcm_oss.h3
-rw-r--r--include/sound/trident.h17
-rw-r--r--include/sound/version.h2
-rw-r--r--include/sound/ymfpci.h22
-rw-r--r--include/video/pm3fb.h3
-rw-r--r--include/video/w100fb.h1
-rw-r--r--init/initramfs.c12
-rw-r--r--kernel/audit.c128
-rw-r--r--kernel/auditsc.c327
-rw-r--r--kernel/exit.c6
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/module.c11
-rw-r--r--kernel/sched.c8
-rw-r--r--kernel/sys.c3
-rw-r--r--kernel/timer.c9
-rw-r--r--lib/dec_and_lock.c35
-rw-r--r--mm/Kconfig4
-rw-r--r--mm/mempolicy.c7
-rw-r--r--mm/mmap.c3
-rw-r--r--mm/page_alloc.c3
-rw-r--r--mm/slab.c2
-rw-r--r--mm/vmscan.c4
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/Kconfig3
-rw-r--r--net/bluetooth/hci_event.c33
-rw-r--r--net/bluetooth/rfcomm/sock.c30
-rw-r--r--net/bridge/br_netfilter.c8
-rw-r--r--net/dccp/Makefile2
-rw-r--r--net/dccp/ackvec.c419
-rw-r--r--net/dccp/ackvec.h133
-rw-r--r--net/dccp/ccid.h31
-rw-r--r--net/dccp/ccids/ccid3.c56
-rw-r--r--net/dccp/ccids/ccid3.h23
-rw-r--r--net/dccp/dccp.h91
-rw-r--r--net/dccp/input.c94
-rw-r--r--net/dccp/ipv4.c101
-rw-r--r--net/dccp/minisocks.c19
-rw-r--r--net/dccp/options.c443
-rw-r--r--net/dccp/output.c26
-rw-r--r--net/dccp/proto.c94
-rw-r--r--net/ipv4/fib_trie.c34
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c43
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c16
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c20
-rw-r--r--net/ipv4/netfilter/Kconfig36
-rw-r--r--net/ipv4/netfilter/Makefile5
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c805
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c19
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c327
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c401
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c214
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c223
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c6
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c16
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/tcp_input.c16
-rw-r--r--net/ipv4/tcp_output.c12
-rw-r--r--net/ipv6/mcast.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c52
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c81
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c88
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c73
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c90
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c88
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c83
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/udp.c15
-rw-r--r--net/socket.c3
-rw-r--r--net/sunrpc/svcsock.c83
-rw-r--r--security/Kconfig1
-rw-r--r--security/Makefile2
-rw-r--r--security/inode.c347
-rw-r--r--security/seclvl.c237
-rw-r--r--security/selinux/avc.c4
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--security/selinux/ss/services.c4
-rw-r--r--sound/arm/Kconfig1
-rw-r--r--sound/arm/aaci.c4
-rw-r--r--sound/arm/sa11xx-uda1341.c7
-rw-r--r--sound/core/Kconfig14
-rw-r--r--sound/core/control.c12
-rw-r--r--sound/core/control_compat.c8
-rw-r--r--sound/core/device.c2
-rw-r--r--sound/core/hwdep.c2
-rw-r--r--sound/core/info.c8
-rw-r--r--sound/core/init.c187
-rw-r--r--sound/core/memalloc.c3
-rw-r--r--sound/core/memory.c4
-rw-r--r--sound/core/oss/mixer_oss.c26
-rw-r--r--sound/core/oss/pcm_oss.c17
-rw-r--r--sound/core/oss/pcm_plugin.c2
-rw-r--r--sound/core/pcm.c6
-rw-r--r--sound/core/pcm_lib.c117
-rw-r--r--sound/core/pcm_memory.c4
-rw-r--r--sound/core/pcm_native.c11
-rw-r--r--sound/core/rawmidi.c16
-rw-r--r--sound/core/seq/instr/ainstr_gf1.c2
-rw-r--r--sound/core/seq/instr/ainstr_iw.c6
-rw-r--r--sound/core/seq/oss/seq_oss_init.c2
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c6
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c2
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c4
-rw-r--r--sound/core/seq/oss/seq_oss_timer.c2
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.c2
-rw-r--r--sound/core/seq/seq.c8
-rw-r--r--sound/core/seq/seq_clientmgr.c9
-rw-r--r--sound/core/seq/seq_device.c2
-rw-r--r--sound/core/seq/seq_dummy.c2
-rw-r--r--sound/core/seq/seq_fifo.c2
-rw-r--r--sound/core/seq/seq_instr.c4
-rw-r--r--sound/core/seq/seq_memory.c2
-rw-r--r--sound/core/seq/seq_midi.c2
-rw-r--r--sound/core/seq/seq_midi_event.c2
-rw-r--r--sound/core/seq/seq_ports.c4
-rw-r--r--sound/core/seq/seq_prioq.c2
-rw-r--r--sound/core/seq/seq_queue.c2
-rw-r--r--sound/core/seq/seq_system.c4
-rw-r--r--sound/core/seq/seq_timer.c2
-rw-r--r--sound/core/seq/seq_virmidi.c6
-rw-r--r--sound/core/sound.c15
-rw-r--r--sound/core/timer.c10
-rw-r--r--sound/drivers/Kconfig5
-rw-r--r--sound/drivers/dummy.c8
-rw-r--r--sound/drivers/mpu401/mpu401.c26
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c2
-rw-r--r--sound/drivers/mtpav.c5
-rw-r--r--sound/drivers/opl3/opl3_lib.c2
-rw-r--r--sound/drivers/opl3/opl3_oss.c2
-rw-r--r--sound/drivers/opl4/opl4_lib.c2
-rw-r--r--sound/drivers/serial-u16550.c28
-rw-r--r--sound/drivers/virmidi.c4
-rw-r--r--sound/drivers/vx/vx_core.c2
-rw-r--r--sound/drivers/vx/vx_pcm.c2
-rw-r--r--sound/i2c/cs8427.c2
-rw-r--r--sound/i2c/i2c.c4
-rw-r--r--sound/i2c/l3/uda1341.c6
-rw-r--r--sound/i2c/other/ak4114.c2
-rw-r--r--sound/i2c/other/ak4117.c2
-rw-r--r--sound/i2c/tea6330t.c2
-rw-r--r--sound/isa/Kconfig18
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c2
-rw-r--r--sound/isa/ad1848/ad1848.c37
-rw-r--r--sound/isa/ad1848/ad1848_lib.c2
-rw-r--r--sound/isa/cmi8330.c77
-rw-r--r--sound/isa/cs423x/cs4231.c46
-rw-r--r--sound/isa/cs423x/cs4231_lib.c2
-rw-r--r--sound/isa/cs423x/cs4236.c97
-rw-r--r--sound/isa/es1688/es1688.c61
-rw-r--r--sound/isa/es1688/es1688_lib.c2
-rw-r--r--sound/isa/es18xx.c83
-rw-r--r--sound/isa/gus/gus_main.c2
-rw-r--r--sound/isa/gus/gus_mem_proc.c4
-rw-r--r--sound/isa/gus/gus_pcm.c2
-rw-r--r--sound/isa/gus/gusclassic.c115
-rw-r--r--sound/isa/gus/gusextreme.c49
-rw-r--r--sound/isa/gus/gusmax.c145
-rw-r--r--sound/isa/gus/interwave.c167
-rw-r--r--sound/isa/opl3sa2.c38
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c13
-rw-r--r--sound/isa/sb/emu8000.c2
-rw-r--r--sound/isa/sb/emu8000_pcm.c2
-rw-r--r--sound/isa/sb/sb16.c144
-rw-r--r--sound/isa/sb/sb16_csp.c2
-rw-r--r--sound/isa/sb/sb8.c62
-rw-r--r--sound/isa/sb/sb_common.c2
-rw-r--r--sound/isa/sgalaxy.c65
-rw-r--r--sound/isa/sscape.c22
-rw-r--r--sound/isa/wavefront/wavefront.c5
-rw-r--r--sound/mips/Kconfig1
-rw-r--r--sound/mips/au1x00.c5
-rw-r--r--sound/parisc/harmony.c2
-rw-r--r--sound/pci/Kconfig12
-rw-r--r--sound/pci/Makefile2
-rw-r--r--sound/pci/ac97/ac97_codec.c5
-rw-r--r--sound/pci/ac97/ac97_id.h1
-rw-r--r--sound/pci/ac97/ac97_patch.c24
-rw-r--r--sound/pci/ac97/ak4531_codec.c2
-rw-r--r--sound/pci/ad1889.c1090
-rw-r--r--sound/pci/ad1889.h189
-rw-r--r--sound/pci/ali5451/ali5451.c27
-rw-r--r--sound/pci/als4000.c1
-rw-r--r--sound/pci/atiixp.c4
-rw-r--r--sound/pci/atiixp_modem.c3
-rw-r--r--sound/pci/au88x0/au88x0.c29
-rw-r--r--sound/pci/azt3328.c3
-rw-r--r--sound/pci/bt87x.c13
-rw-r--r--sound/pci/ca0106/ca0106_main.c7
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c18
-rw-r--r--sound/pci/cmipci.c29
-rw-r--r--sound/pci/cs4281.c14
-rw-r--r--sound/pci/cs46xx/cs46xx.c1
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c28
-rw-r--r--sound/pci/emu10k1/emu10k1.c1
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c7
-rw-r--r--sound/pci/emu10k1/emu10k1x.c7
-rw-r--r--sound/pci/emu10k1/emufx.c20
-rw-r--r--sound/pci/emu10k1/emupcm.c10
-rw-r--r--sound/pci/emu10k1/p16v.c4
-rw-r--r--sound/pci/ens1370.c10
-rw-r--r--sound/pci/es1938.c10
-rw-r--r--sound/pci/es1968.c26
-rw-r--r--sound/pci/fm801.c3
-rw-r--r--sound/pci/hda/hda_codec.c6
-rw-r--r--sound/pci/hda/hda_codec.h1
-rw-r--r--sound/pci/hda/hda_generic.c4
-rw-r--r--sound/pci/hda/hda_intel.c93
-rw-r--r--sound/pci/hda/hda_proc.c2
-rw-r--r--sound/pci/hda/patch_analog.c6
-rw-r--r--sound/pci/hda/patch_cmedia.c2
-rw-r--r--sound/pci/hda/patch_realtek.c8
-rw-r--r--sound/pci/hda/patch_si3054.c3
-rw-r--r--sound/pci/hda/patch_sigmatel.c4
-rw-r--r--sound/pci/ice1712/aureon.c2
-rw-r--r--sound/pci/ice1712/ice1712.c9
-rw-r--r--sound/pci/ice1712/ice1724.c9
-rw-r--r--sound/pci/ice1712/juli.c2
-rw-r--r--sound/pci/ice1712/phase.c4
-rw-r--r--sound/pci/ice1712/pontis.c2
-rw-r--r--sound/pci/intel8x0.c91
-rw-r--r--sound/pci/intel8x0m.c64
-rw-r--r--sound/pci/korg1212/korg1212.c3
-rw-r--r--sound/pci/maestro3.c32
-rw-r--r--sound/pci/mixart/mixart.c5
-rw-r--r--sound/pci/nm256/nm256.c20
-rw-r--r--sound/pci/rme32.c65
-rw-r--r--sound/pci/rme96.c86
-rw-r--r--sound/pci/rme9652/hdsp.c9
-rw-r--r--sound/pci/rme9652/hdspm.c13
-rw-r--r--sound/pci/rme9652/rme9652.c8
-rw-r--r--sound/pci/sonicvibes.c10
-rw-r--r--sound/pci/trident/trident.c1
-rw-r--r--sound/pci/trident/trident_main.c4
-rw-r--r--sound/pci/via82xx.c14
-rw-r--r--sound/pci/via82xx_modem.c3
-rw-r--r--sound/pci/vx222/vx222.c1
-rw-r--r--sound/pci/ymfpci/ymfpci.c1
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c6
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c2
-rw-r--r--sound/ppc/Kconfig15
-rw-r--r--sound/ppc/pmac.c3
-rw-r--r--sound/ppc/powermac.c3
-rw-r--r--sound/ppc/tumbler.c23
-rw-r--r--sound/sparc/Kconfig3
-rw-r--r--sound/sparc/amd7930.c5
-rw-r--r--sound/sparc/cs4231.c7
-rw-r--r--sound/sparc/dbri.c234
-rw-r--r--sound/synth/emux/emux.c2
-rw-r--r--sound/synth/emux/emux_seq.c2
-rw-r--r--sound/synth/emux/soundfont.c8
-rw-r--r--sound/synth/util_mem.c2
-rw-r--r--sound/usb/usbaudio.c18
-rw-r--r--sound/usb/usbmidi.c6
-rw-r--r--sound/usb/usbmixer.c10
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c2
629 files changed, 15306 insertions, 7041 deletions
diff --git a/CREDITS b/CREDITS
index f553f8c..a347520 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2211,6 +2211,15 @@ D: OV511 driver
S: (address available on request)
S: USA
+N: Ian McDonald
+E: iam4@cs.waikato.ac.nz
+E: imcdnzl@gmail.com
+W: http://wand.net.nz/~iam4
+W: http://imcdnzl.blogspot.com
+D: DCCP, CCID3
+S: Hamilton
+S: New Zealand
+
N: Patrick McHardy
E: kaber@trash.net
P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80
@@ -2246,19 +2255,12 @@ S: D-90453 Nuernberg
S: Germany
N: Arnaldo Carvalho de Melo
-E: acme@conectiva.com.br
-E: acme@kernel.org
-E: acme@gnu.org
-W: http://bazar2.conectiva.com.br/~acme
-W: http://advogato.org/person/acme
+E: acme@mandriva.com
+E: acme@ghostprotocols.net
+W: http://oops.ghostprotocols.net:81/blog/
P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01
-D: wanrouter hacking
-D: misc Makefile, Config.in, drivers and network stacks fixes
-D: IPX & LLC network stacks maintainer
-D: Cyclom 2X synchronous card driver
-D: wl3501 PCMCIA wireless card driver
-D: i18n for minicom, net-tools, util-linux, fetchmail, etc
-S: Conectiva S.A.
+D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
+S: Mandriva
S: R. Tocantins, 89 - Cristo Rei
S: 80050-430 - Curitiba - Paraná
S: Brazil
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 22e5f90..eb7db3c 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -410,7 +410,26 @@ Kernel messages do not have to be terminated with a period.
Printing numbers in parentheses (%d) adds no value and should be avoided.
- Chapter 13: References
+ Chapter 13: Allocating memory
+
+The kernel provides the following general purpose memory allocators:
+kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API
+documentation for further information about them.
+
+The preferred form for passing a size of a struct is the following:
+
+ p = kmalloc(sizeof(*p), ...);
+
+The alternative form where struct name is spelled out hurts readability and
+introduces an opportunity for a bug when the pointer variable type is changed
+but the corresponding sizeof that is passed to a memory allocator is not.
+
+Casting the return value which is a void pointer is redundant. The conversion
+from void pointer to any other pointer type is guaranteed by the C programming
+language.
+
+
+ Chapter 14: References
The C Programming Language, Second Edition
by Brian W. Kernighan and Dennis M. Ritchie.
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index c8f9a73..68a711f 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -17,7 +17,9 @@ This driver is known to work with the following cards:
* SA P600
* SA P800
* SA E400
- * SA E300
+ * SA P400i
+ * SA E200
+ * SA E200i
If nodes are not already created in the /dev/cciss directory, run as root:
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt
index bcfa5c3..95d7f62 100644
--- a/Documentation/dell_rbu.txt
+++ b/Documentation/dell_rbu.txt
@@ -13,6 +13,8 @@ the BIOS on Dell servers (starting from servers sold since 1999), desktops
and notebooks (starting from those sold in 2005).
Please go to http://support.dell.com register and you can find info on
OpenManage and Dell Update packages (DUP).
+Libsmbios can also be used to update BIOS on Dell systems go to
+http://linux.dell.com/libsmbios/ for details.
Dell_RBU driver supports BIOS update using the monilothic image and packetized
image methods. In case of moniolithic the driver allocates a contiguous chunk
@@ -22,8 +24,8 @@ would place each packet in contiguous physical memory. The driver also
maintains a link list of packets for reading them back.
If the dell_rbu driver is unloaded all the allocated memory is freed.
-The rbu driver needs to have an application which will inform the BIOS to
-enable the update in the next system reboot.
+The rbu driver needs to have an application (as mentioned above)which will
+inform the BIOS to enable the update in the next system reboot.
The user should not unload the rbu driver after downloading the BIOS image
or updating.
@@ -42,9 +44,11 @@ In case of packet mechanism the single memory can be broken in smaller chuks
of contiguous memory and the BIOS image is scattered in these packets.
By default the driver uses monolithic memory for the update type. This can be
-changed to contiguous during the driver load time by specifying the load
+changed to packets during the driver load time by specifying the load
parameter image_type=packet. This can also be changed later as below
echo packet > /sys/devices/platform/dell_rbu/image_type
+Also echoing either mono ,packet or init in to image_type will free up the
+memory allocated by the driver.
Do the steps below to download the BIOS image.
1) echo 1 > /sys/class/firmware/dell_rbu/loading
@@ -53,9 +57,13 @@ Do the steps below to download the BIOS image.
The /sys/class/firmware/dell_rbu/ entries will remain till the following is
done.
-echo -1 > /sys/class/firmware/dell_rbu/loading
-
+echo -1 > /sys/class/firmware/dell_rbu/loading.
Until this step is completed the drivr cannot be unloaded.
+If an user by accident executes steps 1 and 3 above without executing step 2;
+it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
+The entries can be recreated by doing the following
+echo init > /sys/devices/platform/dell_rbu/image_type
+NOTE: echoing init in image_type does not change it original value.
Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
read back the image downloaded. This is useful in case of packet update
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 96bea27..24adfe9 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -55,6 +55,7 @@ aic7*seq.h*
aicasm
aicdb.h*
asm
+asm-offsets.*
asm_offsets.*
autoconf.h*
bbootsect
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 784e08c..b67189a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -17,15 +17,6 @@ Who: Greg Kroah-Hartman <greg@kroah.com>
---------------------------
-What: io_remap_page_range() (macro or function)
-When: September 2005
-Why: Replaced by io_remap_pfn_range() which allows more memory space
- addressabilty (by using a pfn) and supports sparc & sparc64
- iospace as part of the pfn.
-Who: Randy Dunlap <rddunlap@osdl.org>
-
----------------------------
-
What: RAW driver (CONFIG_RAW_DRIVER)
When: December 2005
Why: declared obsolete since kernel 2.6.3
diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
index d24e1b0..d803abe 100644
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -15,7 +15,7 @@ retrieve the data as it becomes available.
The format of the data logged into the channel buffers is completely
up to the relayfs client; relayfs does however provide hooks which
-allow clients to impose some stucture on the buffer data. Nor does
+allow clients to impose some structure on the buffer data. Nor does
relayfs implement any form of data filtering - this also is left to
the client. The purpose is to keep relayfs as simple as possible.
diff --git a/Documentation/ia64/mca.txt b/Documentation/ia64/mca.txt
new file mode 100644
index 0000000..a71cc6a
--- /dev/null
+++ b/Documentation/ia64/mca.txt
@@ -0,0 +1,194 @@
+An ad-hoc collection of notes on IA64 MCA and INIT processing. Feel
+free to update it with notes about any area that is not clear.
+
+---
+
+MCA/INIT are completely asynchronous. They can occur at any time, when
+the OS is in any state. Including when one of the cpus is already
+holding a spinlock. Trying to get any lock from MCA/INIT state is
+asking for deadlock. Also the state of structures that are protected
+by locks is indeterminate, including linked lists.
+
+---
+
+The complicated ia64 MCA process. All of this is mandated by Intel's
+specification for ia64 SAL, error recovery and and unwind, it is not as
+if we have a choice here.
+
+* MCA occurs on one cpu, usually due to a double bit memory error.
+ This is the monarch cpu.
+
+* SAL sends an MCA rendezvous interrupt (which is a normal interrupt)
+ to all the other cpus, the slaves.
+
+* Slave cpus that receive the MCA interrupt call down into SAL, they
+ end up spinning disabled while the MCA is being serviced.
+
+* If any slave cpu was already spinning disabled when the MCA occurred
+ then it cannot service the MCA interrupt. SAL waits ~20 seconds then
+ sends an unmaskable INIT event to the slave cpus that have not
+ already rendezvoused.
+
+* Because MCA/INIT can be delivered at any time, including when the cpu
+ is down in PAL in physical mode, the registers at the time of the
+ event are _completely_ undefined. In particular the MCA/INIT
+ handlers cannot rely on the thread pointer, PAL physical mode can
+ (and does) modify TP. It is allowed to do that as long as it resets
+ TP on return. However MCA/INIT events expose us to these PAL
+ internal TP changes. Hence curr_task().
+
+* If an MCA/INIT event occurs while the kernel was running (not user
+ space) and the kernel has called PAL then the MCA/INIT handler cannot
+ assume that the kernel stack is in a fit state to be used. Mainly
+ because PAL may or may not maintain the stack pointer internally.
+ Because the MCA/INIT handlers cannot trust the kernel stack, they
+ have to use their own, per-cpu stacks. The MCA/INIT stacks are
+ preformatted with just enough task state to let the relevant handlers
+ do their job.
+
+* Unlike most other architectures, the ia64 struct task is embedded in
+ the kernel stack[1]. So switching to a new kernel stack means that
+ we switch to a new task as well. Because various bits of the kernel
+ assume that current points into the struct task, switching to a new
+ stack also means a new value for current.
+
+* Once all slaves have rendezvoused and are spinning disabled, the
+ monarch is entered. The monarch now tries to diagnose the problem
+ and decide if it can recover or not.
+
+* Part of the monarch's job is to look at the state of all the other
+ tasks. The only way to do that on ia64 is to call the unwinder,
+ as mandated by Intel.
+
+* The starting point for the unwind depends on whether a task is
+ running or not. That is, whether it is on a cpu or is blocked. The
+ monarch has to determine whether or not a task is on a cpu before it
+ knows how to start unwinding it. The tasks that received an MCA or
+ INIT event are no longer running, they have been converted to blocked
+ tasks. But (and its a big but), the cpus that received the MCA
+ rendezvous interrupt are still running on their normal kernel stacks!
+
+* To distinguish between these two cases, the monarch must know which
+ tasks are on a cpu and which are not. Hence each slave cpu that
+ switches to an MCA/INIT stack, registers its new stack using
+ set_curr_task(), so the monarch can tell that the _original_ task is
+ no longer running on that cpu. That gives us a decent chance of
+ getting a valid backtrace of the _original_ task.
+
+* MCA/INIT can be nested, to a depth of 2 on any cpu. In the case of a
+ nested error, we want diagnostics on the MCA/INIT handler that
+ failed, not on the task that was originally running. Again this
+ requires set_curr_task() so the MCA/INIT handlers can register their
+ own stack as running on that cpu. Then a recursive error gets a
+ trace of the failing handler's "task".
+
+[1] My (Keith Owens) original design called for ia64 to separate its
+ struct task and the kernel stacks. Then the MCA/INIT data would be
+ chained stacks like i386 interrupt stacks. But that required
+ radical surgery on the rest of ia64, plus extra hard wired TLB
+ entries with its associated performance degradation. David
+ Mosberger vetoed that approach. Which meant that separate kernel
+ stacks meant separate "tasks" for the MCA/INIT handlers.
+
+---
+
+INIT is less complicated than MCA. Pressing the nmi button or using
+the equivalent command on the management console sends INIT to all
+cpus. SAL picks one one of the cpus as the monarch and the rest are
+slaves. All the OS INIT handlers are entered at approximately the same
+time. The OS monarch prints the state of all tasks and returns, after
+which the slaves return and the system resumes.
+
+At least that is what is supposed to happen. Alas there are broken
+versions of SAL out there. Some drive all the cpus as monarchs. Some
+drive them all as slaves. Some drive one cpu as monarch, wait for that
+cpu to return from the OS then drive the rest as slaves. Some versions
+of SAL cannot even cope with returning from the OS, they spin inside
+SAL on resume. The OS INIT code has workarounds for some of these
+broken SAL symptoms, but some simply cannot be fixed from the OS side.
+
+---
+
+The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer
+violations. Unfortunately MCA/INIT start off as massive layer
+violations (can occur at _any_ time) and they build from there.
+
+At least ia64 makes an attempt at recovering from hardware errors, but
+it is a difficult problem because of the asynchronous nature of these
+errors. When processing an unmaskable interrupt we sometimes need
+special code to cope with our inability to take any locks.
+
+---
+
+How is ia64 MCA/INIT different from x86 NMI?
+
+* x86 NMI typically gets delivered to one cpu. MCA/INIT gets sent to
+ all cpus.
+
+* x86 NMI cannot be nested. MCA/INIT can be nested, to a depth of 2
+ per cpu.
+
+* x86 has a separate struct task which points to one of multiple kernel
+ stacks. ia64 has the struct task embedded in the single kernel
+ stack, so switching stack means switching task.
+
+* x86 does not call the BIOS so the NMI handler does not have to worry
+ about any registers having changed. MCA/INIT can occur while the cpu
+ is in PAL in physical mode, with undefined registers and an undefined
+ kernel stack.
+
+* i386 backtrace is not very sensitive to whether a process is running
+ or not. ia64 unwind is very, very sensitive to whether a process is
+ running or not.
+
+---
+
+What happens when MCA/INIT is delivered what a cpu is running user
+space code?
+
+The user mode registers are stored in the RSE area of the MCA/INIT on
+entry to the OS and are restored from there on return to SAL, so user
+mode registers are preserved across a recoverable MCA/INIT. Since the
+OS has no idea what unwind data is available for the user space stack,
+MCA/INIT never tries to backtrace user space. Which means that the OS
+does not bother making the user space process look like a blocked task,
+i.e. the OS does not copy pt_regs and switch_stack to the user space
+stack. Also the OS has no idea how big the user space RSE and memory
+stacks are, which makes it too risky to copy the saved state to a user
+mode stack.
+
+---
+
+How do we get a backtrace on the tasks that were running when MCA/INIT
+was delivered?
+
+mca.c:::ia64_mca_modify_original_stack(). That identifies and
+verifies the original kernel stack, copies the dirty registers from
+the MCA/INIT stack's RSE to the original stack's RSE, copies the
+skeleton struct pt_regs and switch_stack to the original stack, fills
+in the skeleton structures from the PAL minstate area and updates the
+original stack's thread.ksp. That makes the original stack look
+exactly like any other blocked task, i.e. it now appears to be
+sleeping. To get a backtrace, just start with thread.ksp for the
+original task and unwind like any other sleeping task.
+
+---
+
+How do we identify the tasks that were running when MCA/INIT was
+delivered?
+
+If the previous task has been verified and converted to a blocked
+state, then sos->prev_task on the MCA/INIT stack is updated to point to
+the previous task. You can look at that field in dumps or debuggers.
+To help distinguish between the handler and the original tasks,
+handlers have _TIF_MCA_INIT set in thread_info.flags.
+
+The sos data is always in the MCA/INIT handler stack, at offset
+MCA_SOS_OFFSET. You can get that value from mca_asm.h or calculate it
+as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct
+ia64_sal_os_state), with 16 byte alignment for all structures.
+
+Also the comm field of the MCA/INIT task is modified to include the pid
+of the original task, for humans to use. For example, a comm field of
+'MCA 12159' means that pid 12159 was running when the MCA was
+delivered.
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 1f5f7d2..5f08f9c 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -66,11 +66,11 @@ SETUP
c) Enable "/proc/vmcore support" (Optional, in Pseudo filesystems).
CONFIG_PROC_VMCORE=y
d) Disable SMP support and build a UP kernel (Until it is fixed).
- CONFIG_SMP=n
+ CONFIG_SMP=n
e) Enable "Local APIC support on uniprocessors".
- CONFIG_X86_UP_APIC=y
+ CONFIG_X86_UP_APIC=y
f) Enable "IO-APIC support on uniprocessors"
- CONFIG_X86_UP_IOAPIC=y
+ CONFIG_X86_UP_IOAPIC=y
Note: i) Options a) and b) depend upon "Configure standard kernel features
(for small systems)" (under General setup).
@@ -95,6 +95,11 @@ SETUP
hence have memory less than 4GB.
iii) Specify "irqpoll" as command line parameter. This reduces driver
initialization failures in second kernel due to shared interrupts.
+ iv) <root-dev> needs to be specified in a format corresponding to
+ the root device name in the output of mount command.
+ v) If you have built the drivers required to mount root file
+ system as modules in <second-kernel>, then, specify
+ --initrd=<initrd-for-second-kernel>.
5) System reboots into the second kernel when a panic occurs. A module can be
written to force the panic or "ALT-SysRq-c" can be used initiate a crash
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index da71102..66eaaab 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -205,8 +205,8 @@ Phone: 701-234-7556
Tainted kernels:
Some oops reports contain the string 'Tainted: ' after the program
-counter, this indicates that the kernel has been tainted by some
-mechanism. The string is followed by a series of position sensitive
+counter. This indicates that the kernel has been tainted by some
+mechanism. The string is followed by a series of position-sensitive
characters, each representing a particular tainted value.
1: 'G' if all modules loaded have a GPL or compatible license, 'P' if
@@ -214,16 +214,25 @@ characters, each representing a particular tainted value.
MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
insmod as GPL compatible are assumed to be proprietary.
- 2: 'F' if any module was force loaded by insmod -f, ' ' if all
+ 2: 'F' if any module was force loaded by "insmod -f", ' ' if all
modules were loaded normally.
3: 'S' if the oops occurred on an SMP kernel running on hardware that
- hasn't been certified as safe to run multiprocessor.
- Currently this occurs only on various Athlons that are not
- SMP capable.
+ hasn't been certified as safe to run multiprocessor.
+ Currently this occurs only on various Athlons that are not
+ SMP capable.
+
+ 4: 'R' if a module was force unloaded by "rmmod -f", ' ' if all
+ modules were unloaded normally.
+
+ 5: 'M' if any processor has reported a Machine Check Exception,
+ ' ' if no Machine Check Exceptions have occurred.
+
+ 6: 'B' if a page-release function has found a bad page reference or
+ some unexpected page flags.
The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has
-occurred. Tainting is permanent, even if an offending module is
-unloading the tainted value remains to indicate that the kernel is not
+occurred. Tainting is permanent: even if an offending module is
+unloaded, the tainted value remains to indicate that the kernel is not
trustworthy.
diff --git a/Documentation/pm.txt b/Documentation/pm.txt
index cc63ae1..2ea1149 100644
--- a/Documentation/pm.txt
+++ b/Documentation/pm.txt
@@ -38,6 +38,12 @@ system the associated daemon will exit gracefully.
Driver Interface -- OBSOLETE, DO NOT USE!
----------------*************************
+
+Note: pm_register(), pm_access(), pm_dev_idle() and friends are
+obsolete. Please do not use them. Instead you should properly hook
+your driver into the driver model, and use its suspend()/resume()
+callbacks to do this kind of stuff.
+
If you are writing a new driver or maintaining an old driver, it
should include power management support. Without power management
support, a single driver may prevent a system with power management
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index ebfcdf2..13cba95 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -75,7 +75,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
adsp_map - PCM device number maps assigned to the 2st OSS device.
- Default: 1
nonblock_open
- - Don't block opening busy PCM devices.
+ - Don't block opening busy PCM devices. Default: 1
For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
the card #0. Similarly, when adsp_map=0, /dev/adsp will be mapped
@@ -148,6 +148,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module supports up to 8 cards. This module does not support autoprobe
thus main port must be specified!!! Other ports are optional.
+ Module snd-ad1889
+ -----------------
+
+ Module for Analog Devices AD1889 chips.
+
+ ac97_quirk - AC'97 workaround for strange hardware
+ See the description of intel8x0 module for details.
+
+ This module supports up to 8 cards.
+
Module snd-ali5451
------------------
@@ -189,15 +199,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-atiixp
-----------------
- Module for ATI IXP 150/200/250 AC97 controllers.
+ Module for ATI IXP 150/200/250/400 AC97 controllers.
- ac97_clock - AC'97 clock (defalut = 48000)
+ ac97_clock - AC'97 clock (default = 48000)
ac97_quirk - AC'97 workaround for strange hardware
- See the description of intel8x0 module for details.
+ See "AC97 Quirk Option" section below.
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
This module supports up to 8 cards and autoprobe.
+ ATI IXP has two different methods to control SPDIF output. One is
+ over AC-link and another is over the "direct" SPDIF output. The
+ implementation depends on the motherboard, and you'll need to
+ choose the correct one via spdif_aclink module option.
+
Module snd-atiixp-modem
-----------------------
@@ -230,7 +245,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The hardware EQ hardware and SPDIF is only present in the Vortex2 and
Advantage.
- Note: Some ALSA mixer applicactions don't handle the SPDIF samplerate
+ Note: Some ALSA mixer applications don't handle the SPDIF sample rate
control correctly. If you have problems regarding this, try
another ALSA compliant mixer (alsamixer works).
@@ -302,7 +317,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default)
fm_port - 0x388 (default), 0 = disable (default)
- soft_ac3 - Sofware-conversion of raw SPDIF packets (model 033 only)
+ soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only)
(default = 1)
joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
@@ -384,7 +399,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
CS4624/CS4630/CS4280 PCI chips.
- external_amp - Force to enable external amplifer.
+ external_amp - Force to enable external amplifier.
thinkpad - Force to enable Thinkpad's CLKRUN control.
mmap_valid - Support OSS mmap mode (default = 0).
@@ -620,7 +635,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
VIA VT8251/VT8237A
model - force the model name
- position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
+ position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
Module supports up to 8 cards.
@@ -656,6 +671,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
allout 5-jack in back, 2-jack in front, SPDIF out
auto auto-config reading BIOS (default)
+ If the default configuration doesn't work and one of the above
+ matches with your device, report it together with the PCI
+ subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
+ ML (see the section "Links and Addresses").
+
Note 2: If you get click noises on output, try the module option
position_fix=1 or 2. position_fix=1 will use the SD_LPIB
register value without FIFO size correction as the current
@@ -783,20 +803,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ac97_clock - AC'97 codec clock base (0 = auto-detect)
ac97_quirk - AC'97 workaround for strange hardware
- The following strings are accepted:
- default = don't override the default setting
- disable = disable the quirk
- hp_only = use headphone control as master
- swap_hp = swap headphone and master controls
- swap_surround = swap master and surround controls
- ad_sharing = for AD1985, turn on OMS bit and use headphone
- alc_jack = for ALC65x, turn on the jack sense mode
- inv_eapd = inverted EAPD implementation
- mute_led = bind EAPD bit for turning on/off mute LED
- For backward compatibility, the corresponding integer
- value -1, 0, ... are accepted, too.
+ See "AC97 Quirk Option" section below.
buggy_irq - Enable workaround for buggy interrupts on some
- motherboards (default off)
+ motherboards (default yes on nForce chips,
+ otherwise off)
+ buggy_semaphore - Enable workaround for hardwares with buggy
+ semaphores (e.g. on some ASUS laptops)
+ (default off)
Module supports autoprobe and multiple bus-master chips (max 8).
@@ -808,13 +821,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
motherboard has these devices, use the ns558 or snd-mpu401
modules, respectively.
- The ac97_quirk option is used to enable/override the workaround
- for specific devices. Some hardware have swapped output pins
- between Master and Headphone, or Surround. The driver provides
- the auto-detection of known problematic devices, but some might
- be unknown or wrongly detected. In such a case, pass the proper
- value with this option.
-
The power-management is supported.
Module snd-intel8x0m
@@ -966,7 +972,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
with machines with other (most likely CS423x or OPL3SAx) chips,
even though the device is detected in lspci. In such a case, try
other drivers, e.g. snd-cs4232 or snd-opl3sa2. Some has ISA-PnP
- but some doesn't have ISA PnP. You'll need to speicfy isapnp=0
+ but some doesn't have ISA PnP. You'll need to specify isapnp=0
and proper hardware parameters in the case without ISA PnP.
Note: some laptops need a workaround for AC97 RESET. For the
@@ -1302,7 +1308,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
channels
[VIA8233/C, 8235, 8237 only]
ac97_quirk - AC'97 workaround for strange hardware
- See the description of intel8x0 module for details.
+ See "AC97 Quirk Option" section below.
Module supports autoprobe and multiple bus-master chips (max 8).
@@ -1327,16 +1333,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
"lspci -nv").
If dxs_support=5 does not work, try dxs_support=4; if it
doesn't work too, try dxs_support=1. (dxs_support=1 is
- usually for old motherboards. The correct implementated
+ usually for old motherboards. The correct implemented
board should work with 4 or 5.) If it still doesn't
work and the default setting is ok, dxs_support=3 is the
right choice. If the default setting doesn't work at all,
try dxs_support=2 to disable the DXS channels.
In any cases, please let us know the result and the
- subsystem vendor/device ids.
+ subsystem vendor/device ids. See "Links and Addresses"
+ below.
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
- additonally. The mpu_port option is for VIA686 chips only.
+ additionally. The mpu_port option is for VIA686 chips only.
Module snd-via82xx-modem
------------------------
@@ -1398,8 +1405,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module supports up to 8 cards. The module is compiled only when
PCMCIA is supported on kernel.
- To activate the driver via the card manager, you'll need to set
- up /etc/pcmcia/vxpocket.conf. See the sound/pcmcia/vx/vxpocket.c.
+ With the older 2.6.x kernel, to activate the driver via the card
+ manager, you'll need to set up /etc/pcmcia/vxpocket.conf. See the
+ sound/pcmcia/vx/vxpocket.c. 2.6.13 or later kernel requires no
+ longer require a config file.
When the driver is compiled as a module and the hotplug firmware
is supported, the firmware data is loaded via hotplug automatically.
@@ -1411,6 +1420,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: the driver is build only when CONFIG_ISA is set.
+ Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
+ ALSA 1.0.10.
+
Module snd-ymfpci
-----------------
@@ -1436,6 +1448,37 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: the driver is build only when CONFIG_ISA is set.
+AC97 Quirk Option
+=================
+
+The ac97_quirk option is used to enable/override the workaround for
+specific devices on drivers for on-board AC'97 controllers like
+snd-intel8x0. Some hardware have swapped output pins between Master
+and Headphone, or Surround (thanks to confusion of AC'97
+specifications from version to version :-)
+
+The driver provides the auto-detection of known problematic devices,
+but some might be unknown or wrongly detected. In such a case, pass
+the proper value with this option.
+
+The following strings are accepted:
+ - default Don't override the default setting
+ - disable Disable the quirk
+ - hp_only Bind Master and Headphone controls as a single control
+ - swap_hp Swap headphone and master controls
+ - swap_surround Swap master and surround controls
+ - ad_sharing For AD1985, turn on OMS bit and use headphone
+ - alc_jack For ALC65x, turn on the jack sense mode
+ - inv_eapd Inverted EAPD implementation
+ - mute_led Bind EAPD bit for turning on/off mute LED
+
+For backward compatibility, the corresponding integer value -1, 0,
+... are accepted, too.
+
+For example, if "Master" volume control has no effect on your device
+but only "Headphone" does, pass ac97_quirk=hp_only module option.
+
+
Configuring Non-ISAPNP Cards
============================
@@ -1553,6 +1596,8 @@ Proc interfaces (/proc/asound)
- whole-frag write only whole fragments (optimization affecting
playback only)
- no-silence do not fill silence ahead to avoid clicks
+ - buggy-ptr Returns the whitespace blocks in GETOPTR ioctl
+ instead of filled blocks
Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
@@ -1589,9 +1634,14 @@ commands to the snd-page-alloc driver:
use.
-Links
-=====
+Links and Addresses
+===================
ALSA project homepage
http://www.alsa-project.org
+ ALSA Bug Tracking System
+ https://bugtrack.alsa-project.org/bugs/
+
+ ALSA Developers ML
+ mailto:alsa-devel@lists.sourceforge.net
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 0475478..24e8552 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -447,7 +447,7 @@
....
/* allocate a chip-specific data with zero filled */
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -949,7 +949,7 @@
After allocating a card instance via
<function>snd_card_new()</function> (with
<constant>NULL</constant> on the 4th arg), call
- <function>kcalloc()</function>.
+ <function>kzalloc()</function>.
<informalexample>
<programlisting>
@@ -958,7 +958,7 @@
mychip_t *chip;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
.....
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
]]>
</programlisting>
</informalexample>
@@ -1136,7 +1136,7 @@
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1292,7 +1292,7 @@
need to initialize this number as -1 before actual allocation,
since irq 0 is valid. The port address and its resource pointer
can be initialized as null by
- <function>kcalloc()</function> automatically, so you
+ <function>kzalloc()</function> automatically, so you
don't have to take care of resetting them.
</para>
diff --git a/MAINTAINERS b/MAINTAINERS
index a67bf7d..dc8f3ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -370,7 +370,10 @@ W: http://atmelwlandriver.sourceforge.net/
S: Maintained
AUDIT SUBSYSTEM
-L: linux-audit@redhat.com (subscribers-only)
+P: David Woodhouse
+M: dwmw2@infradead.org
+L: linux-audit@redhat.com
+W: http://people.redhat.com/sgrubb/audit/
S: Maintained
AX.25 NETWORK LAYER
@@ -683,6 +686,13 @@ P: Guennadi Liakhovetski
M: g.liakhovetski@gmx.de
S: Maintained
+DCCP PROTOCOL
+P: Arnaldo Carvalho de Melo
+M: acme@mandriva.com
+L: dccp@vger.kernel.org
+W: http://www.wlug.org.nz/DCCP
+S: Maintained
+
DECnet NETWORK LAYER
P: Patrick Caulfield
M: patrick@tykepenguin.com
@@ -2268,12 +2278,6 @@ M: R.E.Wolff@BitWizard.nl
L: linux-kernel@vger.kernel.org ?
S: Supported
-SPX NETWORK LAYER
-P: Jay Schulist
-M: jschlst@samba.org
-L: netdev@vger.kernel.org
-S: Supported
-
SRM (Alpha) environment access
P: Jan-Benedict Glaw
M: jbglaw@lug-owl.de
diff --git a/Makefile b/Makefile
index 4e0d7c6..8cf6bec 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 14
-EXTRAVERSION =-rc1
+EXTRAVERSION =-rc2
NAME=Affluent Albatross
# *DOCUMENTATION*
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 0636116..01fe990d 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -37,6 +37,7 @@
#include <linux/namei.h>
#include <linux/uio.h>
#include <linux/vfs.h>
+#include <linux/rcupdate.h>
#include <asm/fpu.h>
#include <asm/io.h>
@@ -975,6 +976,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;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
@@ -996,8 +998,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
}
}
+ rcu_read_lock();
fdt = files_fdtable(current->files);
- if (n < 0 || n > fdt->max_fdset)
+ max_fdset = fdt->max_fdset;
+ rcu_read_unlock();
+ if (n < 0 || n > max_fdset)
goto out_nofds;
/*
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 9e36b07..d5da6b1 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -395,6 +395,22 @@ clipper_init_irq(void)
*/
static int __init
+isa_irq_fixup(struct pci_dev *dev, int irq)
+{
+ u8 irq8;
+
+ if (irq > 0)
+ return irq;
+
+ /* This interrupt is routed via ISA bridge, so we'll
+ just have to trust whatever value the console might
+ have assigned. */
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
+
+ return irq8 & 0xf;
+}
+
+static int __init
dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[6][5] __initdata = {
@@ -407,25 +423,13 @@ dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{ 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */
};
const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
-
struct pci_controller *hose = dev->sysdata;
int irq = COMMON_TABLE_LOOKUP;
- if (irq > 0) {
+ if (irq > 0)
irq += 16 * hose->index;
- } else {
- /* ??? The Contaq IDE controller on the ISA bridge uses
- "legacy" interrupts 14 and 15. I don't know if anything
- can wind up at the same slot+pin on hose1, so we'll
- just have to trust whatever value the console might
- have assigned. */
-
- u8 irq8;
- pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
- irq = irq8;
- }
- return irq;
+ return isa_irq_fixup(dev, irq);
}
static int __init
@@ -453,7 +457,8 @@ monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{ 24, 24, 25, 26, 27} /* IdSel 15 slot 5 PCI2*/
};
const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5;
- return COMMON_TABLE_LOOKUP;
+
+ return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
}
static u8 __init
@@ -507,7 +512,8 @@ webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{ 47, 47, 46, 45, 44}, /* IdSel 17 slot 3 */
};
const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5;
- return COMMON_TABLE_LOOKUP;
+
+ return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
}
static int __init
@@ -524,14 +530,13 @@ clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{ -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */
};
const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
-
struct pci_controller *hose = dev->sysdata;
int irq = COMMON_TABLE_LOOKUP;
if (irq > 0)
irq += 16 * hose->index;
- return irq;
+ return isa_irq_fixup(dev, irq);
}
static void __init
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 2786f7c..a7bd857 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -551,7 +551,7 @@ struct locomo_save_data {
u16 LCM_SPIMD;
};
-static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level)
+static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct locomo *lchip = dev_get_drvdata(dev);
struct locomo_save_data *save;
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index f67ca01..30e6444 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul 7 16:41:21 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:51:52 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -135,7 +135,6 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -179,6 +178,68 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
# Device Drivers
#
@@ -248,6 +309,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_IXP2000=y
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -334,72 +396,8 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_I2O is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
@@ -509,6 +507,8 @@ CONFIG_DLCI_MAX=8
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -635,7 +635,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
@@ -649,11 +649,28 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -679,30 +696,15 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -770,6 +772,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -812,8 +815,7 @@ CONFIG_RAMFS=y
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 5c6c928..678720f 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul 7 16:49:01 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:01 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
# Device Drivers
#
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_IXP2000=y
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_I2O is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
@@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
@@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -813,8 +816,7 @@ CONFIG_RAMFS=y
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 6dc40f6..38c9a72 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul 7 16:49:08 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:10 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
# Device Drivers
#
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_IXP2000=y
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_I2O is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
@@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
@@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -814,8 +817,7 @@ CONFIG_RAMFS=y
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index d2bb0b7..261e234 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul 7 16:49:20 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:23 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
# Device Drivers
#
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_IXP2000=y
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_I2O is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
@@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
@@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -813,8 +816,7 @@ CONFIG_RAMFS=y
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index 2d6f960..12ef23d 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul 7 16:49:13 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:16 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
-# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PM is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
# Device Drivers
#
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_IXP2000=y
# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_I2O is not set
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
+# Network device support
#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
@@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
@@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
#
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
#
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
@@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -814,8 +817,7 @@ CONFIG_RAMFS=y
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 949ec44..2ad4aa2 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -131,7 +131,7 @@ __syscall_start:
.long sys_wait4
/* 115 */ .long sys_swapoff
.long sys_sysinfo
- .long sys_ipc
+ .long sys_ipc_wrapper
.long sys_fsync
.long sys_sigreturn_wrapper
/* 120 */ .long sys_clone_wrapper
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index db302c6..81d450a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -273,6 +273,10 @@ sys_mbind_wrapper:
str r5, [sp, #4]
b sys_mbind
+sys_ipc_wrapper:
+ str r5, [sp, #4] @ push sixth arg
+ b sys_ipc
+
/*
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
* offset, we return EINVAL.
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index ac423e3..4c31f29 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem)
* registers (r0 to r3 and lr), but not ip, as we use it as a return
* value in some cases..
*/
-asm(" .section .sched.text,\"ax\" \n\
+asm(" .section .sched.text,\"ax\",%progbits \n\
.align 5 \n\
.globl __down_failed \n\
__down_failed: \n\
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ae1fa09..39b06ed 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -123,6 +123,7 @@ static void __init ixdp425_init(void)
platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
}
+#ifdef CONFIG_ARCH_IXDP465
MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
.phys_ram = PHYS_OFFSET,
@@ -134,7 +135,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
.boot_params = 0x0100,
.init_machine = ixdp425_init,
MACHINE_END
+#endif
+#ifdef CONFIG_MACH_IXDP465
MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
.phys_ram = PHYS_OFFSET,
@@ -146,7 +149,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
.boot_params = 0x0100,
.init_machine = ixdp425_init,
MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_PRPMC1100
MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
.phys_ram = PHYS_OFFSET,
@@ -158,6 +163,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
.boot_params = 0x0100,
.init_machine = ixdp425_init,
MACHINE_END
+#endif
/*
* Avila is functionally equivalent to IXDP425 except that it adds
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 405a55f..3e5f69b 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -20,40 +20,66 @@ config ARCH_PXA_IDP
select PXA25x
config PXA_SHARPSL
- bool "SHARP SL-5600 and SL-C7xx Models"
- select PXA25x
+ bool "SHARP Zaurus SL-5600, SL-C7xx and SL-Cxx00 Models"
select SHARP_SCOOP
select SHARP_PARAM
help
Say Y here if you intend to run this kernel on a
- Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi),
- SL-C750 (Shepherd) or a Sharp SL-C760 (Husky)
- handheld computer.
+ Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi),
+ SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita),
+ SL-C3000 (Spitz) or SL-C3100 (Borzoi) handheld computer.
endchoice
+if PXA_SHARPSL
+
+choice
+ prompt "Select target Sharp Zaurus device range"
+
+config PXA_SHARPSL_25x
+ bool "Sharp PXA25x models (SL-5600 and SL-C7xx)"
+ select PXA25x
+
+config PXA_SHARPSL_27x
+ bool "Sharp PXA270 models (SL-Cxx00)"
+ select PXA27x
+
+endchoice
+
+endif
+
endmenu
config MACH_POODLE
bool "Enable Sharp SL-5600 (Poodle) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select SHARP_LOCOMO
config MACH_CORGI
bool "Enable Sharp SL-C700 (Corgi) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_SHEPHERD
bool "Enable Sharp SL-C750 (Shepherd) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select PXA_SHARP_C7xx
config MACH_HUSKY
bool "Enable Sharp SL-C760 (Husky) Support"
- depends PXA_SHARPSL
+ depends PXA_SHARPSL_25x
select PXA_SHARP_C7xx
+config MACH_SPITZ
+ bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
+ depends PXA_SHARPSL_27x
+ select PXA_SHARP_Cxx00
+
+config MACH_BORZOI
+ bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
+ depends PXA_SHARPSL_27x
+ select PXA_SHARP_Cxx00
+
config PXA25x
bool
help
@@ -74,4 +100,9 @@ config PXA_SHARP_C7xx
help
Enable support for all Sharp C7xx models
+config PXA_SHARP_Cxx00
+ bool
+ help
+ Enable common support for Sharp Cxx00 models
+
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 33dae99..f609a0f 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o
+obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o
obj-$(CONFIG_MACH_POODLE) += poodle.o
# Support for blinky lights
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 07b5dd4..be37586 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -41,6 +41,7 @@
#include <asm/hardware/scoop.h>
#include "generic.h"
+#include "sharpsl.h"
/*
@@ -94,14 +95,30 @@ struct platform_device corgissp_device = {
.id = -1,
};
+struct corgissp_machinfo corgi_ssp_machinfo = {
+ .port = 1,
+ .cs_lcdcon = CORGI_GPIO_LCDCON_CS,
+ .cs_ads7846 = CORGI_GPIO_ADS7846_CS,
+ .cs_max1111 = CORGI_GPIO_MAX1111_CS,
+ .clk_lcdcon = 76,
+ .clk_ads7846 = 2,
+ .clk_max1111 = 8,
+};
+
/*
* Corgi Backlight Device
*/
+static struct corgibl_machinfo corgi_bl_machinfo = {
+ .max_intensity = 0x2f,
+ .set_bl_intensity = corgi_bl_set_intensity,
+};
+
static struct platform_device corgibl_device = {
.name = "corgi-bl",
.dev = {
.parent = &corgifb_device.dev,
+ .platform_data = &corgi_bl_machinfo,
},
.id = -1,
};
@@ -119,12 +136,29 @@ static struct platform_device corgikbd_device = {
/*
* Corgi Touch Screen Device
*/
+static struct resource corgits_resources[] = {
+ [0] = {
+ .start = CORGI_IRQ_GPIO_TP_INT,
+ .end = CORGI_IRQ_GPIO_TP_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct corgits_machinfo corgi_ts_machinfo = {
+ .get_hsync_len = corgi_get_hsync_len,
+ .put_hsync = corgi_put_hsync,
+ .wait_hsync = corgi_wait_hsync,
+};
+
static struct platform_device corgits_device = {
.name = "corgi-ts",
.dev = {
.parent = &corgissp_device.dev,
+ .platform_data = &corgi_ts_machinfo,
},
.id = -1,
+ .num_resources = ARRAY_SIZE(corgits_resources),
+ .resource = corgits_resources,
};
@@ -164,13 +198,10 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd)
{
struct pxamci_platform_data* p_d = dev->platform_data;
- if (( 1 << vdd) & p_d->ocr_mask) {
- printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
+ if (( 1 << vdd) & p_d->ocr_mask)
GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
- } else {
- printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
+ else
GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
- }
}
static int corgi_mci_get_ro(struct device *dev)
@@ -225,7 +256,20 @@ static struct platform_device *devices[] __initdata = {
static void __init corgi_init(void)
{
+ /* setup sleep mode values */
+ PWER = 0x00000002;
+ PFER = 0x00000000;
+ PRER = 0x00000002;
+ PGSR0 = 0x0158C000;
+ PGSR1 = 0x00FF0080;
+ PGSR2 = 0x0001C004;
+ /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
+ PCFR |= PCFR_OPDE;
+
+ corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
+
pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
+ pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
pxa_set_udc_info(&udc_info);
pxa_set_mci_info(&corgi_mci_platform_data);
@@ -248,42 +292,14 @@ static void __init fixup_corgi(struct machine_desc *desc,
mi->bank[0].size = (64*1024*1024);
}
-static void __init corgi_init_irq(void)
-{
- pxa_init_irq();
-}
-
-static struct map_desc corgi_io_desc[] __initdata = {
-/* virtual physical length */
-/* { 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */
-/* { 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/ /* SCOOP */
- { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
-};
-
-static void __init corgi_map_io(void)
-{
- pxa_map_io();
- iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc));
-
- /* setup sleep mode values */
- PWER = 0x00000002;
- PFER = 0x00000000;
- PRER = 0x00000002;
- PGSR0 = 0x0158C000;
- PGSR1 = 0x00FF0080;
- PGSR2 = 0x0001C004;
- /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
- PCFR |= PCFR_OPDE;
-}
-
#ifdef CONFIG_MACH_CORGI
MACHINE_START(CORGI, "SHARP Corgi")
.phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
- .map_io = corgi_map_io,
- .init_irq = corgi_init_irq,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
@@ -295,8 +311,8 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
- .map_io = corgi_map_io,
- .init_irq = corgi_init_irq,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
@@ -308,8 +324,8 @@ MACHINE_START(HUSKY, "SHARP Husky")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
- .map_io = corgi_map_io,
- .init_irq = corgi_init_irq,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index deac29c..c5efcd0 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -1,10 +1,14 @@
/*
* linux/drivers/video/w100fb.c
*
- * Corgi LCD Specific Code for ATI Imageon w100 (Wallaby)
+ * Corgi/Spitz LCD Specific Code
*
* Copyright (C) 2005 Richard Purdie
*
+ * Connectivity:
+ * Corgi - LCD to ATI Imageon w100 (Wallaby)
+ * Spitz - LCD to PXA Framebuffer
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -14,9 +18,17 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/device.h>
+#include <linux/module.h>
+#include <asm/mach-types.h>
+#include <asm/arch/akita.h>
#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/sharpsl.h>
+#include <asm/arch/spitz.h>
+#include <asm/hardware/scoop.h>
#include <asm/mach/sharpsl_param.h>
-#include <video/w100fb.h>
+#include "generic.h"
/* Register Addresses */
#define RESCTL_ADRS 0x00
@@ -134,10 +146,10 @@ static void lcdtg_set_common_voltage(u8 base_data, u8 data)
}
/* Set Phase Adjuct */
-static void lcdtg_set_phadadj(struct w100fb_par *par)
+static void lcdtg_set_phadadj(int mode)
{
int adj;
- switch(par->xres) {
+ switch(mode) {
case 480:
case 640:
/* Setting for VGA */
@@ -161,7 +173,7 @@ static void lcdtg_set_phadadj(struct w100fb_par *par)
static int lcd_inited;
-static void lcdtg_hw_init(struct w100fb_par *par)
+static void lcdtg_hw_init(int mode)
{
if (!lcd_inited) {
int comadj;
@@ -215,7 +227,7 @@ static void lcdtg_hw_init(struct w100fb_par *par)
corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
/* Set Phase Adjuct */
- lcdtg_set_phadadj(par);
+ lcdtg_set_phadadj(mode);
/* Initialize for Input Signals from ATI */
corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE
@@ -224,10 +236,10 @@ static void lcdtg_hw_init(struct w100fb_par *par)
lcd_inited=1;
} else {
- lcdtg_set_phadadj(par);
+ lcdtg_set_phadadj(mode);
}
- switch(par->xres) {
+ switch(mode) {
case 480:
case 640:
/* Set Lcd Resolution (VGA) */
@@ -242,7 +254,7 @@ static void lcdtg_hw_init(struct w100fb_par *par)
}
}
-static void lcdtg_suspend(struct w100fb_par *par)
+static void lcdtg_suspend(void)
{
/* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
mdelay(34);
@@ -276,15 +288,30 @@ static void lcdtg_suspend(struct w100fb_par *par)
lcd_inited = 0;
}
-static struct w100_tg_info corgi_lcdtg_info = {
- .change=lcdtg_hw_init,
- .suspend=lcdtg_suspend,
- .resume=lcdtg_hw_init,
-};
/*
* Corgi w100 Frame Buffer Device
*/
+#ifdef CONFIG_PXA_SHARP_C7xx
+
+#include <video/w100fb.h>
+
+static void w100_lcdtg_suspend(struct w100fb_par *par)
+{
+ lcdtg_suspend();
+}
+
+static void w100_lcdtg_init(struct w100fb_par *par)
+{
+ lcdtg_hw_init(par->xres);
+}
+
+
+static struct w100_tg_info corgi_lcdtg_info = {
+ .change = w100_lcdtg_init,
+ .suspend = w100_lcdtg_suspend,
+ .resume = w100_lcdtg_init,
+};
static struct w100_mem_info corgi_fb_mem = {
.ext_cntl = 0x00040003,
@@ -394,3 +421,145 @@ struct platform_device corgifb_device = {
},
};
+#endif
+
+
+/*
+ * Spitz PXA Frame Buffer Device
+ */
+#ifdef CONFIG_PXA_SHARP_Cxx00
+
+#include <asm/arch/pxafb.h>
+
+void spitz_lcd_power(int on)
+{
+ if (on)
+ lcdtg_hw_init(480);
+ else
+ lcdtg_suspend();
+}
+
+#endif
+
+
+/*
+ * Corgi/Spitz Touchscreen to LCD interface
+ */
+static unsigned long (*get_hsync_time)(struct device *dev);
+
+static void inline sharpsl_wait_sync(int gpio)
+{
+ while((GPLR(gpio) & GPIO_bit(gpio)) == 0);
+ while((GPLR(gpio) & GPIO_bit(gpio)) != 0);
+}
+
+#ifdef CONFIG_PXA_SHARP_C7xx
+unsigned long corgi_get_hsync_len(void)
+{
+ if (!get_hsync_time)
+ get_hsync_time = symbol_get(w100fb_get_hsynclen);
+ if (!get_hsync_time)
+ return 0;
+
+ return get_hsync_time(&corgifb_device.dev);
+}
+
+void corgi_put_hsync(void)
+{
+ if (get_hsync_time)
+ symbol_put(w100fb_get_hsynclen);
+}
+
+void corgi_wait_hsync(void)
+{
+ sharpsl_wait_sync(CORGI_GPIO_HSYNC);
+}
+#endif
+
+#ifdef CONFIG_PXA_SHARP_Cxx00
+unsigned long spitz_get_hsync_len(void)
+{
+ if (!get_hsync_time)
+ get_hsync_time = symbol_get(pxafb_get_hsync_time);
+ if (!get_hsync_time)
+ return 0;
+
+ return pxafb_get_hsync_time(&pxafb_device.dev);
+}
+
+void spitz_put_hsync(void)
+{
+ if (get_hsync_time)
+ symbol_put(pxafb_get_hsync_time);
+}
+
+void spitz_wait_hsync(void)
+{
+ sharpsl_wait_sync(SPITZ_GPIO_HSYNC);
+}
+#endif
+
+/*
+ * Corgi/Spitz Backlight Power
+ */
+#ifdef CONFIG_PXA_SHARP_C7xx
+void corgi_bl_set_intensity(int intensity)
+{
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ /* Bits 0-4 are accessed via the SSP interface */
+ corgi_ssp_blduty_set(intensity & 0x1f);
+
+ /* Bit 5 is via SCOOP */
+ if (intensity & 0x0020)
+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+ else
+ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+}
+#endif
+
+
+#if defined(CONFIG_MACH_SPITZ) || defined(CONFIG_MACH_BORZOI)
+void spitz_bl_set_intensity(int intensity)
+{
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ /* Bits 0-4 are accessed via the SSP interface */
+ corgi_ssp_blduty_set(intensity & 0x1f);
+
+ /* Bit 5 is via SCOOP */
+ if (intensity & 0x0020)
+ reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);
+ else
+ set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);
+
+ if (intensity)
+ set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);
+ else
+ reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);
+}
+#endif
+
+#ifdef CONFIG_MACH_AKITA
+void akita_bl_set_intensity(int intensity)
+{
+ if (intensity > 0x10)
+ intensity += 0x10;
+
+ /* Bits 0-4 are accessed via the SSP interface */
+ corgi_ssp_blduty_set(intensity & 0x1f);
+
+ /* Bit 5 is via IO-Expander */
+ if (intensity & 0x0020)
+ akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);
+ else
+ akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);
+
+ if (intensity)
+ akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);
+ else
+ akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);
+}
+#endif
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 366a9bd..0ef4282 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -1,7 +1,7 @@
/*
* SSP control code for Sharp Corgi devices
*
- * Copyright (c) 2004 Richard Purdie
+ * Copyright (c) 2004-2005 Richard Purdie
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,14 +17,16 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/arch/ssp.h>
-#include <asm/arch/corgi.h>
#include <asm/arch/pxa-regs.h>
+#include "sharpsl.h"
static DEFINE_SPINLOCK(corgi_ssp_lock);
static struct ssp_dev corgi_ssp_dev;
static struct ssp_state corgi_ssp_state;
+static struct corgissp_machinfo *ssp_machinfo;
/*
* There are three devices connected to the SSP interface:
@@ -48,12 +50,12 @@ unsigned long corgi_ssp_ads7846_putget(ulong data)
unsigned long ret,flag;
spin_lock_irqsave(&corgi_ssp_lock, flag);
- GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
ssp_write_word(&corgi_ssp_dev,data);
ret = ssp_read_word(&corgi_ssp_dev);
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
return ret;
@@ -66,12 +68,12 @@ unsigned long corgi_ssp_ads7846_putget(ulong data)
void corgi_ssp_ads7846_lock(void)
{
spin_lock(&corgi_ssp_lock);
- GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
}
void corgi_ssp_ads7846_unlock(void)
{
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
spin_unlock(&corgi_ssp_lock);
}
@@ -97,23 +99,27 @@ EXPORT_SYMBOL(corgi_ssp_ads7846_get);
*/
unsigned long corgi_ssp_dac_put(ulong data)
{
- unsigned long flag;
+ unsigned long flag, sscr1 = SSCR1_SPH;
spin_lock_irqsave(&corgi_ssp_lock, flag);
- GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
+ if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi())
+ sscr1 = 0;
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
+ ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon));
ssp_enable(&corgi_ssp_dev);
+ GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
ssp_write_word(&corgi_ssp_dev,data);
/* Read null data back from device to prevent SSP overflow */
ssp_read_word(&corgi_ssp_dev);
+ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
ssp_enable(&corgi_ssp_dev);
- GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
return 0;
@@ -141,9 +147,9 @@ int corgi_ssp_max1111_get(ulong data)
int voltage,voltage1,voltage2;
spin_lock_irqsave(&corgi_ssp_lock, flag);
- GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+ GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
+ ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111));
ssp_enable(&corgi_ssp_dev);
udelay(1);
@@ -161,9 +167,9 @@ int corgi_ssp_max1111_get(ulong data)
voltage2=ssp_read_word(&corgi_ssp_dev);
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
ssp_enable(&corgi_ssp_dev);
- GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
spin_unlock_irqrestore(&corgi_ssp_lock, flag);
if (voltage1 & 0xc0 || voltage2 & 0x3f)
@@ -179,25 +185,31 @@ EXPORT_SYMBOL(corgi_ssp_max1111_get);
/*
* Support Routines
*/
-int __init corgi_ssp_probe(struct device *dev)
+
+void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo)
+{
+ ssp_machinfo = machinfo;
+}
+
+static int __init corgi_ssp_probe(struct device *dev)
{
int ret;
/* Chip Select - Disable All */
- GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
- GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
- GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
- GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
- GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+ GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */
+ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
+ GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */
+ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+ GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
- ret=ssp_init(&corgi_ssp_dev,1);
+ ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port);
if (ret)
printk(KERN_ERR "Unable to register SSP handler!\n");
else {
ssp_disable(&corgi_ssp_dev);
- ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
ssp_enable(&corgi_ssp_dev);
}
@@ -222,9 +234,9 @@ static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
static int corgi_ssp_resume(struct device *dev, u32 level)
{
if (level == RESUME_POWER_ON) {
- GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
- GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
- GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+ GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
+ GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+ GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
ssp_enable(&corgi_ssp_dev);
}
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 923f6eb..1f38033 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -146,6 +146,11 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
// no D+ pullup; lubbock can't connect/disconnect in software
};
+static struct platform_device lub_audio_device = {
+ .name = "pxa2xx-ac97",
+ .id = -1,
+};
+
static struct resource sa1111_resources[] = {
[0] = {
.start = 0x10000000,
@@ -195,6 +200,7 @@ static struct platform_device smc91x_device = {
static struct platform_device *devices[] __initdata = {
&sa1111_device,
+ &lub_audio_device,
&smc91x_device,
};
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 47cfb8b..f256388 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -30,6 +30,8 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/irq.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/udc.h>
#include <asm/arch/poodle.h>
#include <asm/arch/pxafb.h>
@@ -93,6 +95,83 @@ static struct platform_device locomo_device = {
.resource = locomo_resources,
};
+
+/*
+ * MMC/SD Device
+ *
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert/eject.
+ */
+static struct pxamci_platform_data poodle_mci_platform_data;
+
+static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+ int err;
+
+ /* setup GPIO for PXA25x MMC controller */
+ pxa_gpio_mode(GPIO6_MMCCLK_MD);
+ pxa_gpio_mode(GPIO8_MMCCS0_MD);
+ pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN);
+ pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT);
+
+ poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+ err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT,
+ "MMC card detect", data);
+ if (err) {
+ printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+ return -1;
+ }
+
+ set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
+
+ return 0;
+}
+
+static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
+{
+ struct pxamci_platform_data* p_d = dev->platform_data;
+
+ if (( 1 << vdd) & p_d->ocr_mask)
+ GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+ else
+ GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+}
+
+static void poodle_mci_exit(struct device *dev, void *data)
+{
+ free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data);
+}
+
+static struct pxamci_platform_data poodle_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .init = poodle_mci_init,
+ .setpower = poodle_mci_setpower,
+ .exit = poodle_mci_exit,
+};
+
+
+/*
+ * USB Device Controller
+ */
+static void poodle_udc_command(int cmd)
+{
+ switch(cmd) {
+ case PXA2XX_UDC_CMD_CONNECT:
+ GPSR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP);
+ break;
+ case PXA2XX_UDC_CMD_DISCONNECT:
+ GPCR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP);
+ break;
+ }
+}
+
+static struct pxa2xx_udc_mach_info udc_info __initdata = {
+ /* no connect GPIO; poodle can't tell connection status */
+ .udc_command = poodle_udc_command,
+};
+
+
/* PXAFB device */
static struct pxafb_mach_info poodle_fb_info __initdata = {
.pixclock = 144700,
@@ -126,6 +205,15 @@ static void __init poodle_init(void)
{
int ret = 0;
+ /* setup sleep mode values */
+ PWER = 0x00000002;
+ PFER = 0x00000000;
+ PRER = 0x00000002;
+ PGSR0 = 0x00008000;
+ PGSR1 = 0x003F0202;
+ PGSR2 = 0x0001C000;
+ PCFR |= PCFR_OPDE;
+
/* cpu initialize */
/* Pgsr Register */
PGSR0 = 0x0146dd80;
@@ -155,6 +243,9 @@ static void __init poodle_init(void)
GPSR2 = 0x00000000;
set_pxa_fb_info(&poodle_fb_info);
+ pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT);
+ pxa_set_udc_info(&udc_info);
+ pxa_set_mci_info(&poodle_mci_platform_data);
scoop_num = 1;
scoop_devs = &poodle_pcmcia_scoop[0];
@@ -171,32 +262,12 @@ static void __init fixup_poodle(struct machine_desc *desc,
sharpsl_save_param();
}
-static struct map_desc poodle_io_desc[] __initdata = {
- /* virtual physical length */
- { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
-};
-
-static void __init poodle_map_io(void)
-{
- pxa_map_io();
- iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc));
-
- /* setup sleep mode values */
- PWER = 0x00000002;
- PFER = 0x00000000;
- PRER = 0x00000002;
- PGSR0 = 0x00008000;
- PGSR1 = 0x003F0202;
- PGSR2 = 0x0001C000;
- PCFR |= PCFR_OPDE;
-}
-
MACHINE_START(POODLE, "SHARP Poodle")
.phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_poodle,
- .map_io = poodle_map_io,
+ .map_io = pxa_map_io,
.init_irq = pxa_init_irq,
.timer = &pxa_timer,
.init_machine = poodle_init,
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
new file mode 100644
index 0000000..3977a77
--- /dev/null
+++ b/arch/arm/mach-pxa/sharpsl.h
@@ -0,0 +1,34 @@
+/*
+ * SharpSL SSP Driver
+ */
+
+struct corgissp_machinfo {
+ int port;
+ int cs_lcdcon;
+ int cs_ads7846;
+ int cs_max1111;
+ int clk_lcdcon;
+ int clk_ads7846;
+ int clk_max1111;
+};
+
+void corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo);
+
+/*
+ * SharpSL Backlight
+ */
+
+void corgi_bl_set_intensity(int intensity);
+void spitz_bl_set_intensity(int intensity);
+void akita_bl_set_intensity(int intensity);
+
+/*
+ * SharpSL Touchscreen Driver
+ */
+
+unsigned long corgi_get_hsync_len(void);
+unsigned long spitz_get_hsync_len(void);
+void corgi_put_hsync(void);
+void spitz_put_hsync(void);
+void corgi_wait_hsync(void);
+void spitz_wait_hsync(void);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
new file mode 100644
index 0000000..568afe3d
--- /dev/null
+++ b/arch/arm/mach-pxa/spitz.c
@@ -0,0 +1,380 @@
+/*
+ * Support for Sharp SL-Cxx00 Series of PDAs
+ * Models: SL-C3000 (Spitz), SL-C1000 (Akita) and SL-C3100 (Borzoi)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches/lubbock.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/host.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irq.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/akita.h>
+#include <asm/arch/spitz.h>
+#include <asm/arch/sharpsl.h>
+
+#include <asm/mach/sharpsl_param.h>
+#include <asm/hardware/scoop.h>
+
+#include "generic.h"
+#include "sharpsl.h"
+
+/*
+ * Spitz SCOOP Device #1
+ */
+static struct resource spitz_scoop_resources[] = {
+ [0] = {
+ .start = 0x10800000,
+ .end = 0x10800fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct scoop_config spitz_scoop_setup = {
+ .io_dir = SPITZ_SCP_IO_DIR,
+ .io_out = SPITZ_SCP_IO_OUT,
+ .suspend_clr = SPITZ_SCP_SUS_CLR,
+ .suspend_set = SPITZ_SCP_SUS_SET,
+};
+
+struct platform_device spitzscoop_device = {
+ .name = "sharp-scoop",
+ .id = 0,
+ .dev = {
+ .platform_data = &spitz_scoop_setup,
+ },
+ .num_resources = ARRAY_SIZE(spitz_scoop_resources),
+ .resource = spitz_scoop_resources,
+};
+
+/*
+ * Spitz SCOOP Device #2
+ */
+static struct resource spitz_scoop2_resources[] = {
+ [0] = {
+ .start = 0x08800040,
+ .end = 0x08800fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct scoop_config spitz_scoop2_setup = {
+ .io_dir = SPITZ_SCP2_IO_DIR,
+ .io_out = SPITZ_SCP2_IO_OUT,
+ .suspend_clr = SPITZ_SCP2_SUS_CLR,
+ .suspend_set = SPITZ_SCP2_SUS_SET,
+};
+
+struct platform_device spitzscoop2_device = {
+ .name = "sharp-scoop",
+ .id = 1,
+ .dev = {
+ .platform_data = &spitz_scoop2_setup,
+ },
+ .num_resources = ARRAY_SIZE(spitz_scoop2_resources),
+ .resource = spitz_scoop2_resources,
+};
+
+static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = {
+{
+ .dev = &spitzscoop_device.dev,
+ .irq = SPITZ_IRQ_GPIO_CF_IRQ,
+ .cd_irq = SPITZ_IRQ_GPIO_CF_CD,
+ .cd_irq_str = "PCMCIA0 CD",
+},{
+ .dev = &spitzscoop2_device.dev,
+ .irq = SPITZ_IRQ_GPIO_CF2_IRQ,
+ .cd_irq = -1,
+},
+};
+
+
+/*
+ * Spitz SSP Device
+ *
+ * Set the parent as the scoop device because a lot of SSP devices
+ * also use scoop functions and this makes the power up/down order
+ * work correctly.
+ */
+struct platform_device spitzssp_device = {
+ .name = "corgi-ssp",
+ .dev = {
+ .parent = &spitzscoop_device.dev,
+ },
+ .id = -1,
+};
+
+struct corgissp_machinfo spitz_ssp_machinfo = {
+ .port = 2,
+ .cs_lcdcon = SPITZ_GPIO_LCDCON_CS,
+ .cs_ads7846 = SPITZ_GPIO_ADS7846_CS,
+ .cs_max1111 = SPITZ_GPIO_MAX1111_CS,
+ .clk_lcdcon = 520,
+ .clk_ads7846 = 14,
+ .clk_max1111 = 56,
+};
+
+
+/*
+ * Spitz Backlight Device
+ */
+static struct corgibl_machinfo spitz_bl_machinfo = {
+ .max_intensity = 0x2f,
+};
+
+static struct platform_device spitzbl_device = {
+ .name = "corgi-bl",
+ .dev = {
+ .platform_data = &spitz_bl_machinfo,
+ },
+ .id = -1,
+};
+
+
+/*
+ * Spitz Keyboard Device
+ */
+static struct platform_device spitzkbd_device = {
+ .name = "spitz-keyboard",
+ .id = -1,
+};
+
+
+/*
+ * Spitz Touch Screen Device
+ */
+static struct resource spitzts_resources[] = {
+ [0] = {
+ .start = SPITZ_IRQ_GPIO_TP_INT,
+ .end = SPITZ_IRQ_GPIO_TP_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct corgits_machinfo spitz_ts_machinfo = {
+ .get_hsync_len = spitz_get_hsync_len,
+ .put_hsync = spitz_put_hsync,
+ .wait_hsync = spitz_wait_hsync,
+};
+
+static struct platform_device spitzts_device = {
+ .name = "corgi-ts",
+ .dev = {
+ .parent = &spitzssp_device.dev,
+ .platform_data = &spitz_ts_machinfo,
+ },
+ .id = -1,
+ .num_resources = ARRAY_SIZE(spitzts_resources),
+ .resource = spitzts_resources,
+};
+
+
+/*
+ * MMC/SD Device
+ *
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert/eject.
+ */
+
+static struct pxamci_platform_data spitz_mci_platform_data;
+
+static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+ int err;
+
+ /* setup GPIO for PXA27x MMC controller */
+ pxa_gpio_mode(GPIO32_MMCCLK_MD);
+ pxa_gpio_mode(GPIO112_MMCCMD_MD);
+ pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+ pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+ pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+ pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+ pxa_gpio_mode(SPITZ_GPIO_nSD_DETECT | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_nSD_WP | GPIO_IN);
+
+ spitz_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+ err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int, SA_INTERRUPT,
+ "MMC card detect", data);
+ if (err) {
+ printk(KERN_ERR "spitz_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+ return -1;
+ }
+
+ set_irq_type(SPITZ_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
+
+ return 0;
+}
+
+/* Power control is shared with one of the CF slots so we have a mess */
+static void spitz_mci_setpower(struct device *dev, unsigned int vdd)
+{
+ struct pxamci_platform_data* p_d = dev->platform_data;
+
+ unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR);
+
+ if (( 1 << vdd) & p_d->ocr_mask) {
+ /* printk(KERN_DEBUG "%s: on\n", __FUNCTION__); */
+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+ mdelay(2);
+ write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | 0x04);
+ } else {
+ /* printk(KERN_DEBUG "%s: off\n", __FUNCTION__); */
+ write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr & ~0x04);
+
+ if (!(cpr | 0x02)) {
+ mdelay(1);
+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+ }
+ }
+}
+
+static int spitz_mci_get_ro(struct device *dev)
+{
+ return GPLR(SPITZ_GPIO_nSD_WP) & GPIO_bit(SPITZ_GPIO_nSD_WP);
+}
+
+static void spitz_mci_exit(struct device *dev, void *data)
+{
+ free_irq(SPITZ_IRQ_GPIO_nSD_DETECT, data);
+}
+
+static struct pxamci_platform_data spitz_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .init = spitz_mci_init,
+ .get_ro = spitz_mci_get_ro,
+ .setpower = spitz_mci_setpower,
+ .exit = spitz_mci_exit,
+};
+
+
+/*
+ * Spitz PXA Framebuffer
+ */
+static struct pxafb_mach_info spitz_pxafb_info __initdata = {
+ .pixclock = 19231,
+ .xres = 480,
+ .yres = 640,
+ .bpp = 16,
+ .hsync_len = 40,
+ .left_margin = 46,
+ .right_margin = 125,
+ .vsync_len = 3,
+ .upper_margin = 1,
+ .lower_margin = 0,
+ .sync = 0,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act | LCCR0_LDDALT | LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM,
+ .lccr3 = LCCR3_PixRsEdg | LCCR3_OutEnH,
+ .pxafb_lcd_power = spitz_lcd_power,
+};
+
+
+static struct platform_device *devices[] __initdata = {
+ &spitzscoop_device,
+ &spitzssp_device,
+ &spitzkbd_device,
+ &spitzts_device,
+ &spitzbl_device,
+ &spitzbattery_device,
+};
+
+static void __init common_init(void)
+{
+ PMCR = 0x00;
+
+ /* setup sleep mode values */
+ PWER = 0x00000002;
+ PFER = 0x00000000;
+ PRER = 0x00000002;
+ PGSR0 = 0x0158C000;
+ PGSR1 = 0x00FF0080;
+ PGSR2 = 0x0001C004;
+
+ /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
+ PCFR |= PCFR_OPDE;
+
+ corgi_ssp_set_machinfo(&spitz_ssp_machinfo);
+
+ pxa_gpio_mode(SPITZ_GPIO_HSYNC | GPIO_IN);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+ pxa_set_mci_info(&spitz_mci_platform_data);
+ pxafb_device.dev.parent = &spitzssp_device.dev;
+ set_pxa_fb_info(&spitz_pxafb_info);
+}
+
+static void __init spitz_init(void)
+{
+ scoop_num = 2;
+ scoop_devs = &spitz_pcmcia_scoop[0];
+ spitz_bl_machinfo.set_bl_intensity = spitz_bl_set_intensity;
+
+ common_init();
+
+ platform_device_register(&spitzscoop2_device);
+}
+
+static void __init fixup_spitz(struct machine_desc *desc,
+ struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+ sharpsl_save_param();
+ mi->nr_banks = 1;
+ mi->bank[0].start = 0xa0000000;
+ mi->bank[0].node = 0;
+ mi->bank[0].size = (64*1024*1024);
+}
+
+#ifdef CONFIG_MACH_SPITZ
+MACHINE_START(SPITZ, "SHARP Spitz")
+ .phys_ram = 0xa0000000,
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = fixup_spitz,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
+ .init_machine = spitz_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_BORZOI
+MACHINE_START(BORZOI, "SHARP Borzoi")
+ .phys_ram = 0xa0000000,
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = fixup_spitz,
+ .map_io = pxa_map_io,
+ .init_irq = pxa_init_irq,
+ .init_machine = spitz_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 8cb6911..25d6a4e 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -111,12 +111,11 @@ static struct mtd_partition collie_partitions[] = {
static void collie_set_vpp(int vpp)
{
- write_scoop_reg(SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN);
- if (vpp) {
- write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN);
- } else {
- write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
- }
+ write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN);
+ if (vpp)
+ write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN);
+ else
+ write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
}
static struct flash_platform_data collie_flash_data = {
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index 279e3af..f085d68 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -39,3 +39,6 @@ extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops);
struct irda_platform_data;
void sa11x0_set_irda_data(struct irda_platform_data *irda);
+
+struct mcp_plat_data;
+void sa11x0_set_mcp_data(struct mcp_plat_data *data);
diff --git a/arch/arm26/boot/compressed/hw-bse.c b/arch/arm26/boot/compressed/hw-bse.c
deleted file mode 100644
index 3e8f07f..0000000
--- a/arch/arm26/boot/compressed/hw-bse.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Bright Star Engineering Inc.
- *
- * code for readng parameters from the
- * parameter blocks of the boot block
- * flash memory
- *
- */
-
-static int strcmp(const char *s1, const char *s2)
-{
- while (*s1 != '\0' && *s1 == *s2)
- {
- s1++;
- s2++;
- }
-
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
-}
-
-struct pblk_t {
- char type;
- unsigned short size;
-};
-
-static char *bse_getflashparam(char *name) {
- unsigned int esize;
- char *q,*r;
- unsigned char *p,*e;
- struct pblk_t *thepb = (struct pblk_t *) 0x00004000;
- struct pblk_t *altpb = (struct pblk_t *) 0x00006000;
- if (thepb->type&1) {
- if (altpb->type&1) {
- /* no valid param block */
- return (char*)0;
- } else {
- /* altpb is valid */
- struct pblk_t *tmp;
- tmp = thepb;
- thepb = altpb;
- altpb = tmp;
- }
- }
- p = (char*)thepb + sizeof(struct pblk_t);
- e = p + thepb->size;
- while (p < e) {
- q = p;
- esize = *p;
- if (esize == 0xFF) break;
- if (esize == 0) break;
- if (esize > 127) {
- esize = (esize&0x7F)<<8 | p[1];
- q++;
- }
- q++;
- r=q;
- if (*r && ((name == 0) || (!strcmp(name,r)))) {
- while (*q++) ;
- return q;
- }
- p+=esize;
- }
- return (char*)0;
-}
-
-void bse_setup(void) {
- /* extract the linux cmdline from flash */
- char *name=bse_getflashparam("linuxboot");
- char *x = (char *)0xc0000100;
- if (name) {
- while (*name) *x++=*name++;
- }
- *x=0;
-}
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index b22f003..d2703cd 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -908,11 +908,6 @@ config IRQBALANCE
The default yes will allow the kernel to do irq load balancing.
Saying no will keep the kernel from doing irq load balancing.
-config HAVE_DEC_LOCK
- bool
- depends on (SMP || PREEMPT) && X86_CMPXCHG
- default y
-
# turning this on wastes a bunch of space.
# Summit needs it only when NUMA is on
config BOOT_IOREMAP
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index 1ae2aee..f1b9d2a 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -7,7 +7,6 @@
#include <linux/pci.h>
#include <asm/pci-direct.h>
#include <asm/acpi.h>
-#include <asm/apic.h>
static int __init check_bridge(int vendor, int device)
{
@@ -16,15 +15,6 @@ static int __init check_bridge(int vendor, int device)
if (vendor == PCI_VENDOR_ID_NVIDIA) {
acpi_skip_timer_override = 1;
}
-#ifdef CONFIG_X86_LOCAL_APIC
- /*
- * ATI IXP chipsets get double timer interrupts.
- * For now just do this for all ATI chipsets.
- * FIXME: this needs to be checked for the non ACPI case too.
- */
- if (vendor == PCI_VENDOR_ID_ATI)
- disable_timer_pin_1 = 1;
-#endif
return 0;
}
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 1cbb9c0..350ea66 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -11,6 +11,7 @@
#include <linux/mc146818rtc.h>
#include <linux/efi.h>
#include <linux/dmi.h>
+#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <asm/apic.h>
#include <asm/desc.h>
@@ -28,8 +29,6 @@ static int reboot_thru_bios;
#ifdef CONFIG_SMP
static int reboot_cpu = -1;
-/* shamelessly grabbed from lib/vsprintf.c for readability */
-#define is_digit(c) ((c) >= '0' && (c) <= '9')
#endif
static int __init reboot_setup(char *str)
{
@@ -49,9 +48,9 @@ static int __init reboot_setup(char *str)
break;
#ifdef CONFIG_SMP
case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
- if (is_digit(*(str+1))) {
+ if (isdigit(*(str+1))) {
reboot_cpu = (int) (*(str+1) - '0');
- if (is_digit(*(str+2)))
+ if (isdigit(*(str+2)))
reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
}
/* we will leave sorting out the final value
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index dc39ca6..9b8c8a1 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -848,9 +848,7 @@ static void __init parse_cmdline_early (char ** cmdline_p)
#ifdef CONFIG_X86_IO_APIC
else if (!memcmp(from, "acpi_skip_timer_override", 24))
acpi_skip_timer_override = 1;
-#endif
-#ifdef CONFIG_X86_LOCAL_APIC
if (!memcmp(from, "disable_timer_pin_1", 19))
disable_timer_pin_1 = 1;
if (!memcmp(from, "enable_timer_pin_1", 18))
@@ -859,7 +857,7 @@ static void __init parse_cmdline_early (char ** cmdline_p)
/* disable IO-APIC */
else if (!memcmp(from, "noapic", 6))
disable_ioapic_setup();
-#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_X86_IO_APIC */
#endif /* CONFIG_ACPI */
#ifdef CONFIG_X86_LOCAL_APIC
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index c70cd2a..5f0a95d 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -202,7 +202,7 @@ static void __devinit smp_store_cpu_info(int id)
goto valid_k7;
/* If we get here, it's not a certified SMP capable AMD system. */
- tainted |= TAINT_UNSAFE_SMP;
+ add_taint(TAINT_UNSAFE_SMP);
}
valid_k7:
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 09a58cb..431a551 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -807,8 +807,9 @@ void math_error(void __user *eip)
cwd = get_fpu_cwd(task);
swd = get_fpu_swd(task);
switch (swd & ~cwd & 0x3f) {
- case 0x000:
- default:
+ case 0x000: /* No unmasked exception */
+ return;
+ default: /* Multiple exceptions */
break;
case 0x001: /* Invalid Op */
/*
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
index 7b1932d..914933e 100644
--- a/arch/i386/lib/Makefile
+++ b/arch/i386/lib/Makefile
@@ -7,4 +7,3 @@ lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \
bitops.o
lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c
deleted file mode 100644
index 8b81b25..0000000
--- a/arch/i386/lib/dec_and_lock.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * x86 version of "atomic_dec_and_lock()" using
- * the atomic "cmpxchg" instruction.
- *
- * (For CPU's lacking cmpxchg, we use the slow
- * generic version, and this one never even gets
- * compiled).
- */
-
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <asm/atomic.h>
-
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- int counter;
- int newcount;
-
-repeat:
- counter = atomic_read(atomic);
- newcount = counter-1;
-
- if (!newcount)
- goto slow_path;
-
- asm volatile("lock; cmpxchgl %1,%2"
- :"=a" (newcount)
- :"r" (newcount), "m" (atomic->counter), "0" (counter));
-
- /* If the above failed, "eax" will have changed */
- if (newcount != counter)
- goto repeat;
- return 0;
-
-slow_path:
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index ed25d66..945c15a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -298,11 +298,6 @@ config PREEMPT
source "mm/Kconfig"
-config HAVE_DEC_LOCK
- bool
- depends on (SMP || PREEMPT)
- default y
-
config IA32_SUPPORT
bool "Support for Linux/x86 binaries"
help
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 70f8ed2..67932ad 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -82,17 +82,7 @@ unwcheck: vmlinux
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
-archprepare: include/asm-ia64/.offsets.h.stamp
-
-include/asm-ia64/.offsets.h.stamp:
- mkdir -p include/asm-ia64
- [ -s include/asm-ia64/asm-offsets.h ] \
- || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/asm-offsets.h
- touch $@
-
-
-
-CLEAN_FILES += vmlinux.gz bootloader include/asm-ia64/.offsets.h.stamp
+CLEAN_FILES += vmlinux.gz bootloader
boot: lib/lib.a vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 31de70b..a7280d9 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -216,12 +216,6 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
if (!mpnt)
return -ENOMEM;
- if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))
- >> PAGE_SHIFT)) {
- kmem_cache_free(vm_area_cachep, mpnt);
- return -ENOMEM;
- }
-
memset(mpnt, 0, sizeof(*mpnt));
down_write(&current->mm->mmap_sem);
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 28a4529..7e92647 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -899,7 +899,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
if ((err = iosapic_init(phys_addr, gsi_base)))
return err;
-#if CONFIG_ACPI_NUMA
+#ifdef CONFIG_ACPI_NUMA
acpi_map_iosapic(handle, 0, NULL, NULL);
#endif /* CONFIG_ACPI_NUMA */
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index f6a2342..7722565 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -4,6 +4,7 @@
* to extract and format the required data.
*/
+#define ASM_OFFSETS_C 1
#include <linux/config.h>
#include <linux/sched.h>
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index ba0b6a1..0741b066 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -491,7 +491,7 @@ GLOBAL_ENTRY(prefetch_stack)
;;
lfetch.fault [r16], 128
br.ret.sptk.many rp
-END(prefetch_switch_stack)
+END(prefetch_stack)
GLOBAL_ENTRY(execve)
mov r15=__NR_execve // put syscall number in place
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 6e68374..80f83d6 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -84,23 +84,23 @@ mca_page_isolate(unsigned long paddr)
struct page *p;
/* whether physical address is valid or not */
- if ( !ia64_phys_addr_valid(paddr) )
+ if (!ia64_phys_addr_valid(paddr))
return ISOLATE_NG;
/* convert physical address to physical page number */
p = pfn_to_page(paddr>>PAGE_SHIFT);
/* check whether a page number have been already registered or not */
- for( i = 0; i < num_page_isolate; i++ )
- if( page_isolate[i] == p )
+ for (i = 0; i < num_page_isolate; i++)
+ if (page_isolate[i] == p)
return ISOLATE_OK; /* already listed */
/* limitation check */
- if( num_page_isolate == MAX_PAGE_ISOLATE )
+ if (num_page_isolate == MAX_PAGE_ISOLATE)
return ISOLATE_NG;
/* kick pages having attribute 'SLAB' or 'Reserved' */
- if( PageSlab(p) || PageReserved(p) )
+ if (PageSlab(p) || PageReserved(p))
return ISOLATE_NG;
/* add attribute 'Reserved' and register the page */
@@ -139,10 +139,10 @@ mca_handler_bh(unsigned long paddr)
* @peidx: pointer to index of processor error section
*/
-static void
+static void
mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
{
- /*
+ /*
* calculate the start address of
* "struct cpuid_info" and "sal_processor_static_info_t".
*/
@@ -164,7 +164,7 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
}
/**
- * mca_make_slidx - Make index of SAL error record
+ * mca_make_slidx - Make index of SAL error record
* @buffer: pointer to SAL error record
* @slidx: pointer to index of SAL error record
*
@@ -172,12 +172,12 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
* 1 if record has platform error / 0 if not
*/
#define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
- { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
- hl->hdr = ptr; \
- list_add(&hl->list, &(sect)); \
- slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
+ {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
+ hl->hdr = ptr; \
+ list_add(&hl->list, &(sect)); \
+ slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
-static int
+static int
mca_make_slidx(void *buffer, slidx_table_t *slidx)
{
int platform_err = 0;
@@ -214,28 +214,36 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx)
sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
- } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) {
+ } else if (!efi_guidcmp(sp->guid,
+ SAL_PLAT_BUS_ERR_SECT_GUID)) {
platform_err = 1;
LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
} else {
@@ -253,15 +261,16 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx)
* Return value:
* 0 on Success / -ENOMEM on Failure
*/
-static int
+static int
init_record_index_pools(void)
{
int i;
int rec_max_size; /* Maximum size of SAL error records */
int sect_min_size; /* Minimum size of SAL error sections */
/* minimum size table of each section */
- static int sal_log_sect_min_sizes[] = {
- sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t),
+ static int sal_log_sect_min_sizes[] = {
+ sizeof(sal_log_processor_info_t)
+ + sizeof(sal_processor_static_info_t),
sizeof(sal_log_mem_dev_err_info_t),
sizeof(sal_log_sel_dev_err_info_t),
sizeof(sal_log_pci_bus_err_info_t),
@@ -294,7 +303,8 @@ init_record_index_pools(void)
/* - 3 - */
slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
- slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
+ slidx_pool.buffer = (slidx_list_t *)
+ kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
return slidx_pool.buffer ? 0 : -ENOMEM;
}
@@ -308,6 +318,7 @@ init_record_index_pools(void)
* is_mca_global - Check whether this MCA is global or not
* @peidx: pointer of index of processor error section
* @pbci: pointer to pal_bus_check_info_t
+ * @sos: pointer to hand off struct between SAL and OS
*
* Return value:
* MCA_IS_LOCAL / MCA_IS_GLOBAL
@@ -317,11 +328,12 @@ static mca_type_t
is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
struct ia64_sal_os_state *sos)
{
- pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+ pal_processor_state_info_t *psp =
+ (pal_processor_state_info_t*)peidx_psp(peidx);
- /*
+ /*
* PAL can request a rendezvous, if the MCA has a global scope.
- * If "rz_always" flag is set, SAL requests MCA rendezvous
+ * If "rz_always" flag is set, SAL requests MCA rendezvous
* in spite of global MCA.
* Therefore it is local MCA when rendezvous has not been requested.
* Failed to rendezvous, the system must be down.
@@ -381,13 +393,15 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
* @slidx: pointer of index of SAL error record
* @peidx: pointer of index of processor error section
* @pbci: pointer of pal_bus_check_info
+ * @sos: pointer to hand off struct between SAL and OS
*
* Return value:
* 1 on Success / 0 on Failure
*/
static int
-recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_read_error(slidx_table_t *slidx,
+ peidx_table_t *peidx, pal_bus_check_info_t *pbci,
struct ia64_sal_os_state *sos)
{
sal_log_mod_error_info_t *smei;
@@ -453,24 +467,28 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
* @slidx: pointer of index of SAL error record
* @peidx: pointer of index of processor error section
* @pbci: pointer of pal_bus_check_info
+ * @sos: pointer to hand off struct between SAL and OS
*
* Return value:
* 1 on Success / 0 on Failure
*/
static int
-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
+ pal_bus_check_info_t *pbci,
struct ia64_sal_os_state *sos)
{
int status = 0;
- pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+ pal_processor_state_info_t *psp =
+ (pal_processor_state_info_t*)peidx_psp(peidx);
if (psp->bc && pbci->eb && pbci->bsi == 0) {
switch(pbci->type) {
case 1: /* partial read */
case 3: /* full line(cpu) read */
case 9: /* I/O space read */
- status = recover_from_read_error(slidx, peidx, pbci, sos);
+ status = recover_from_read_error(slidx, peidx, pbci,
+ sos);
break;
case 0: /* unknown */
case 2: /* partial write */
@@ -481,7 +499,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
case 8: /* write coalescing transactions */
case 10: /* I/O space write */
case 11: /* inter-processor interrupt message(IPI) */
- case 12: /* interrupt acknowledge or external task priority cycle */
+ case 12: /* interrupt acknowledge or
+ external task priority cycle */
default:
break;
}
@@ -496,6 +515,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
* @slidx: pointer of index of SAL error record
* @peidx: pointer of index of processor error section
* @pbci: pointer of pal_bus_check_info
+ * @sos: pointer to hand off struct between SAL and OS
*
* Return value:
* 1 on Success / 0 on Failure
@@ -509,15 +529,17 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
*/
static int
-recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_processor_error(int platform, slidx_table_t *slidx,
+ peidx_table_t *peidx, pal_bus_check_info_t *pbci,
struct ia64_sal_os_state *sos)
{
- pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+ pal_processor_state_info_t *psp =
+ (pal_processor_state_info_t*)peidx_psp(peidx);
- /*
+ /*
* We cannot recover errors with other than bus_check.
*/
- if (psp->cc || psp->rc || psp->uc)
+ if (psp->cc || psp->rc || psp->uc)
return 0;
/*
@@ -546,10 +568,10 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
* (e.g. a load from poisoned memory)
* This means "there are some platform errors".
*/
- if (platform)
+ if (platform)
return recover_from_platform_error(slidx, peidx, pbci, sos);
- /*
- * On account of strange SAL error record, we cannot recover.
+ /*
+ * On account of strange SAL error record, we cannot recover.
*/
return 0;
}
@@ -557,14 +579,14 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
/**
* mca_try_to_recover - Try to recover from MCA
* @rec: pointer to a SAL error record
+ * @sos: pointer to hand off struct between SAL and OS
*
* Return value:
* 1 on Success / 0 on Failure
*/
static int
-mca_try_to_recover(void *rec,
- struct ia64_sal_os_state *sos)
+mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
{
int platform_err;
int n_proc_err;
@@ -588,7 +610,8 @@ mca_try_to_recover(void *rec,
}
/* Make index of processor error section */
- mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
+ mca_make_peidx((sal_log_processor_info_t*)
+ slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
/* Extract Processor BUS_CHECK[0] */
*((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
@@ -598,7 +621,8 @@ mca_try_to_recover(void *rec,
return 0;
/* Try to recover a processor error */
- return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos);
+ return recover_from_processor_error(platform_err, &slidx, &peidx,
+ &pbci, sos);
}
/*
@@ -611,7 +635,7 @@ int __init mca_external_handler_init(void)
return -ENOMEM;
/* register external mca handlers */
- if (ia64_reg_MCA_extension(mca_try_to_recover)){
+ if (ia64_reg_MCA_extension(mca_try_to_recover)) {
printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
kfree(slidx_pool.buffer);
return -EFAULT;
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index 0227b76..e2f6fa1 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -6,7 +6,7 @@
* Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
*/
/*
- * Processor error section:
+ * Processor error section:
*
* +-sal_log_processor_info_t *info-------------+
* | sal_log_section_hdr_t header; |
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index 2d7e021..3f298ee 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -13,45 +13,45 @@
#include <asm/ptrace.h>
GLOBAL_ENTRY(mca_handler_bhhook)
- invala // clear RSE ?
- ;; //
- cover //
- ;; //
- clrrrb //
+ invala // clear RSE ?
+ ;;
+ cover
+ ;;
+ clrrrb
;;
- alloc r16=ar.pfs,0,2,1,0 // make a new frame
+ alloc r16=ar.pfs,0,2,1,0 // make a new frame
;;
- mov ar.rsc=0
+ mov ar.rsc=0
;;
- mov r13=IA64_KR(CURRENT) // current task pointer
+ mov r13=IA64_KR(CURRENT) // current task pointer
;;
- mov r2=r13
+ mov r2=r13
;;
- addl r22=IA64_RBS_OFFSET,r2
+ addl r22=IA64_RBS_OFFSET,r2
;;
- mov ar.bspstore=r22
+ mov ar.bspstore=r22
;;
- addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
+ addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
;;
- adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+ adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
;;
- st1 [r2]=r0 // clear current->thread.on_ustack flag
- mov loc0=r16
- movl loc1=mca_handler_bh // recovery C function
+ st1 [r2]=r0 // clear current->thread.on_ustack flag
+ mov loc0=r16
+ movl loc1=mca_handler_bh // recovery C function
;;
- mov out0=r8 // poisoned address
- mov b6=loc1
+ mov out0=r8 // poisoned address
+ mov b6=loc1
;;
- mov loc1=rp
+ mov loc1=rp
;;
- ssm psr.i
+ ssm psr.i
;;
- br.call.sptk.many rp=b6 // does not return ...
+ br.call.sptk.many rp=b6 // does not return ...
;;
- mov ar.pfs=loc0
- mov rp=loc1
+ mov ar.pfs=loc0
+ mov rp=loc1
;;
- mov r8=r0
+ mov r8=r0
br.ret.sptk.many rp
;;
END(mca_handler_bhhook)
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 1650353..d71731e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -574,7 +574,7 @@ pfm_protect_ctx_ctxsw(pfm_context_t *x)
return 0UL;
}
-static inline unsigned long
+static inline void
pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
{
spin_unlock(&(x)->ctx_lock);
@@ -2218,12 +2218,13 @@ static void
pfm_free_fd(int fd, struct file *file)
{
struct files_struct *files = current->files;
- struct fdtable *fdt = files_fdtable(files);
+ struct fdtable *fdt;
/*
* there ie no fd_uninstall(), so we do it here
*/
spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
rcu_assign_pointer(fdt->fd[fd], NULL);
spin_unlock(&files->file_lock);
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index 799407e..cb1af59 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -15,7 +15,6 @@ lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o
lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
lib-$(CONFIG_PERFMON) += carta_random.o
lib-$(CONFIG_MD_RAID5) += xor.o
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
AFLAGS___divdi3.o =
AFLAGS___udivdi3.o = -DUNSIGNED
diff --git a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c
deleted file mode 100644
index c7ce92f..0000000
--- a/arch/ia64/lib/dec_and_lock.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2003 Jerome Marchand, Bull S.A.
- * Cleaned up by David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * This file is released under the GPLv2, or at your option any later version.
- *
- * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction. This
- * code is an adaptation of the x86 version of "atomic_dec_and_lock()".
- */
-
-#include <linux/compiler.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-
-/*
- * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock. Both of these
- * operations have to be done atomically, so that the count doesn't drop to zero without
- * acquiring the spinlock first.
- */
-int
-_atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock)
-{
- int old, new;
-
- do {
- old = atomic_read(refcount);
- new = old - 1;
-
- if (unlikely (old == 1)) {
- /* oops, we may be decrementing to zero, do it the slow way... */
- spin_lock(lock);
- if (atomic_dec_and_test(refcount))
- return 1;
- spin_unlock(lock);
- return 0;
- }
- } while (cmpxchg(&refcount->counter, old, new) != old);
- return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 1ef3987e..4d100f3 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -220,11 +220,6 @@ config PREEMPT
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
-config HAVE_DEC_LOCK
- bool
- depends on (SMP || PREEMPT)
- default n
-
config SMP
bool "Symmetric multi-processing support"
---help---
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0eb71ac..4cd724c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1009,10 +1009,6 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
-config HAVE_DEC_LOCK
- bool
- default y
-
#
# Select some configuration options automatically based on user selections.
#
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 4de1556..7ae4af4 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -581,18 +581,13 @@ asmlinkage int irix_brk(unsigned long brk)
}
/*
- * Check if we have enough memory..
+ * Ok, looks good - let it rip.
*/
- if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+ if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) {
ret = -ENOMEM;
goto out;
}
-
- /*
- * Ok, looks good - let it rip.
- */
mm->brk = brk;
- do_brk(oldbrk, newbrk-oldbrk);
ret = 0;
out:
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 21b92b9..0373034 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_copy.o dec_and_lock.o memcpy.o promlib.o \
+lib-y += csum_partial_copy.o memcpy.o promlib.o \
strlen_user.o strncpy_user.o strnlen_user.o
obj-y += iomap.o
diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c
deleted file mode 100644
index fd82c84..0000000
--- a/arch/mips/lib/dec_and_lock.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * MIPS version of atomic_dec_and_lock() using cmpxchg
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * This is an implementation of the notion of "decrement a
- * reference count, and return locked if it decremented to zero".
- *
- * This implementation can be used on any architecture that
- * has a cmpxchg, and where atomic->value is an int holding
- * the value of the atomic (i.e. the high bits aren't used
- * for a lock or anything like that).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- int counter;
- int newcount;
-
- for (;;) {
- counter = atomic_read(atomic);
- newcount = counter - 1;
- if (!newcount)
- break; /* do it the slow way */
-
- newcount = cmpxchg(&atomic->counter, counter, newcount);
- if (newcount == counter)
- return 0;
- }
-
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 347ea28..776941c 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -26,10 +26,6 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
-config HAVE_DEC_LOCK
- bool
- default y
-
config PPC
bool
default y
diff --git a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
index fe8bb63..26bd8ea 100644
--- a/arch/ppc/kernel/temp.c
+++ b/arch/ppc/kernel/temp.c
@@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/init.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/reg.h>
#include <asm/nvram.h>
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index a3c5281..22d7fd1 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -58,7 +58,6 @@
#include <linux/init.h>
#include <linux/profile.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/nvram.h>
#include <asm/cache.h>
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 9353584..17d2db7 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -96,6 +96,9 @@ SECTIONS
*(.init.text)
_einittext = .;
}
+ /* .exit.text is discarded at runtime, not link time,
+ to deal with references from __bug_table */
+ .exit.text : { *(.exit.text) }
.init.data : {
*(.init.data);
__vtop_table_begin = .;
@@ -190,5 +193,6 @@ SECTIONS
/* Sections to be discarded. */
/DISCARD/ : {
*(.exitcall.exit)
+ *(.exit.data)
}
}
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index f1e1fb4..50358e4 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -2,7 +2,7 @@
# Makefile for ppc-specific library files..
#
-obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o
+obj-y := checksum.o string.o strcase.o div64.o
obj-$(CONFIG_8xx) += rheap.o
obj-$(CONFIG_CPM2) += rheap.o
diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c
deleted file mode 100644
index b18f0d9..0000000
--- a/arch/ppc/lib/dec_and_lock.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * This is an implementation of the notion of "decrement a
- * reference count, and return locked if it decremented to zero".
- *
- * This implementation can be used on any architecture that
- * has a cmpxchg, and where atomic->value is an int holding
- * the value of the atomic (i.e. the high bits aren't used
- * for a lock or anything like that).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- int counter;
- int newcount;
-
- for (;;) {
- counter = atomic_read(atomic);
- newcount = counter - 1;
- if (!newcount)
- break; /* do it the slow way */
-
- newcount = cmpxchg(&atomic->counter, counter, newcount);
- if (newcount == counter)
- return 0;
- }
-
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
index 4864a7d..6037ce7 100644
--- a/arch/ppc/platforms/chrp_time.c
+++ b/arch/ppc/platforms/chrp_time.c
@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/bcd.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/nvram.h>
#include <asm/prom.h>
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 8b9b226..b8d08f3 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -34,7 +34,8 @@ ifeq ($(CONFIG_40x),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o
endif
endif
-obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y)
+obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
+ ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
ifeq ($(CONFIG_8xx),y)
obj-$(CONFIG_PCI) += qspan_pci.o i8259.o
endif
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
new file mode 100644
index 0000000..2b5f0e7
--- /dev/null
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -0,0 +1,224 @@
+/*
+ * arch/ppc/syslib/mpc8xx_devices.c
+ *
+ * MPC8xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_8250.h>
+#include <linux/mii.h>
+#include <asm/commproc.h>
+#include <asm/mpc8xx.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+/* We use offsets for IORESOURCE_MEM to do not set dependences at compile time.
+ * They will get fixed up by mach_mpc8xx_fixup
+ */
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC8xx_CPM_FEC1] = {
+ .name = "fsl-cpm-fec",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xe00,
+ .end = 0xe88,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_FEC1,
+ .end = MPC8xx_INT_FEC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_FEC2] = {
+ .name = "fsl-cpm-fec",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0x1e00,
+ .end = 0x1e88,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_FEC2,
+ .end = MPC8xx_INT_FEC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_SCC1] = {
+ .name = "fsl-cpm-scc",
+ .id = 1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xa00,
+ .end = 0xa18,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3c00,
+ .end = 0x3c80,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_SCC1,
+ .end = MPC8xx_INT_SCC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_SCC2] = {
+ .name = "fsl-cpm-scc",
+ .id = 2,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xa20,
+ .end = 0xa38,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3d00,
+ .end = 0x3d80,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_SCC2,
+ .end = MPC8xx_INT_SCC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_SCC3] = {
+ .name = "fsl-cpm-scc",
+ .id = 3,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xa40,
+ .end = 0xa58,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3e00,
+ .end = 0x3e80,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_SCC3,
+ .end = MPC8xx_INT_SCC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_SCC4] = {
+ .name = "fsl-cpm-scc",
+ .id = 4,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xa60,
+ .end = 0xa78,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3f00,
+ .end = 0x3f80,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_SCC4,
+ .end = MPC8xx_INT_SCC4,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_SMC1] = {
+ .name = "fsl-cpm-smc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xa82,
+ .end = 0xa91,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_SMC1,
+ .end = MPC8xx_INT_SMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC8xx_CPM_SMC2] = {
+ .name = "fsl-cpm-smc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .name = "regs",
+ .start = 0xa92,
+ .end = 0xaa1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "interrupt",
+ .start = MPC8xx_INT_SMC2,
+ .end = MPC8xx_INT_SMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+static int __init mach_mpc8xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource (pdev, IMAP_ADDR);
+ return 0;
+}
+
+static int __init mach_mpc8xx_init(void)
+{
+ ppc_sys_device_fixup = mach_mpc8xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc8xx_init);
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
new file mode 100644
index 0000000..a532ccc
--- /dev/null
+++ b/arch/ppc/syslib/mpc8xx_sys.c
@@ -0,0 +1,61 @@
+/*
+ * arch/ppc/platforms/mpc8xx_sys.c
+ *
+ * MPC8xx System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "MPC86X",
+ .mask = 0xFFFFFFFF,
+ .value = 0x00000000,
+ .num_devices = 2,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC8xx_CPM_FEC1,
+ MPC8xx_CPM_SCC1,
+ MPC8xx_CPM_SCC2,
+ MPC8xx_CPM_SCC3,
+ MPC8xx_CPM_SCC4,
+ MPC8xx_CPM_SMC1,
+ MPC8xx_CPM_SMC2,
+ },
+ },
+ {
+ .ppc_sys_name = "MPC885",
+ .mask = 0xFFFFFFFF,
+ .value = 0x00000000,
+ .num_devices = 3,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC8xx_CPM_FEC1,
+ MPC8xx_CPM_FEC2,
+ MPC8xx_CPM_SCC1,
+ MPC8xx_CPM_SCC2,
+ MPC8xx_CPM_SCC3,
+ MPC8xx_CPM_SCC4,
+ MPC8xx_CPM_SMC1,
+ MPC8xx_CPM_SMC2,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index 2e0ea92..9a7e874 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -575,7 +575,7 @@ static void openpic2_cached_disable_irq(u_int irq)
* we need something better to deal with that... Maybe switch to S1 for
* cpufreq changes
*/
-int openpic2_suspend(struct sys_device *sysdev, u32 state)
+int openpic2_suspend(struct sys_device *sysdev, pm_message_t state)
{
int i;
unsigned long flags;
diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c
index 2bcf8a1..8599850 100644
--- a/arch/ppc/syslib/prep_nvram.c
+++ b/arch/ppc/syslib/prep_nvram.c
@@ -15,7 +15,6 @@
#include <linux/ioport.h>
#include <asm/sections.h>
-#include <asm/segment.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/prep_nvram.h>
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index deca68a..c658650 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -28,10 +28,6 @@ config GENERIC_ISA_DMA
bool
default y
-config HAVE_DEC_LOCK
- bool
- default y
-
config EARLY_PRINTK
bool
default y
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 17e35d0..1ff4fa0 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -68,6 +68,7 @@ int main(void)
DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
#endif /* CONFIG_ALTIVEC */
DEFINE(MM, offsetof(struct task_struct, mm));
+ DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size));
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index d133a49..e8c0bbf 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -276,12 +276,22 @@ _GLOBAL(ppc64_rt_sigsuspend)
_GLOBAL(ppc32_rt_sigsuspend)
bl .save_nvgprs
bl .sys32_rt_sigsuspend
- /* If sigsuspend() returns zero, we are going into a signal handler */
70: cmpdi 0,r3,0
- beq .ret_from_except
- /* If it returned -EINTR, we need to return via syscall_exit to set
+ /* If it returned an error, we need to return via syscall_exit to set
the SO bit in cr0 and potentially stop for ptrace. */
- b syscall_exit
+ bne syscall_exit
+ /* If sigsuspend() returns zero, we are going into a signal handler. We
+ may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
+#ifdef CONFIG_AUDIT
+ ld r3,PACACURRENT(r13)
+ ld r4,AUDITCONTEXT(r3)
+ cmpdi 0,r4,0
+ beq .ret_from_except /* No audit_context: Leave immediately. */
+ li r4, 2 /* AUDITSC_FAILURE */
+ li r5,-4 /* It's always -EINTR */
+ bl .audit_syscall_exit
+#endif
+ b .ret_from_except
_GLOBAL(ppc_fork)
bl .save_nvgprs
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 58c3147..72c6104 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -1649,7 +1649,7 @@ _GLOBAL(__secondary_start)
ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
- bne 98f
+ beq 98f /* branch if result is 0 */
mfspr r3,PVR
srwi r3,r3,16
cmpwi r3,0x37 /* SStar */
@@ -1813,7 +1813,7 @@ _STATIC(start_here_multiplatform)
ld r3,0(r3)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */
- bne 98f
+ beq 98f /* branch if result is 0 */
mfspr r3,PVR
srwi r3,r3,16
cmpwi r3,0x37 /* SStar */
@@ -1834,7 +1834,7 @@ _STATIC(start_here_multiplatform)
lwz r3,PLATFORM(r3) /* r3 = platform flags */
/* Test if bit 0 is set (LPAR bit) */
andi. r3,r3,PLATFORM_LPAR
- bne 98f
+ bne 98f /* branch if result is !0 */
LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
sub r6,r6,r26
ld r6,0(r6) /* get the value of _SDR1 */
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index bfadccc..3009701 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -238,8 +238,8 @@ static void __init pSeries_setup_arch(void)
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
- eeh_init();
find_and_init_phbs();
+ eeh_init();
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
index 4777676..efa985f 100644
--- a/arch/ppc64/kernel/vdso.c
+++ b/arch/ppc64/kernel/vdso.c
@@ -224,10 +224,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (vma == NULL)
return -ENOMEM;
- if (security_vm_enough_memory(vdso_pages)) {
- kmem_cache_free(vm_area_cachep, vma);
- return -ENOMEM;
- }
+
memset(vma, 0, sizeof(*vma));
/*
@@ -237,8 +234,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
*/
vdso_base = get_unmapped_area(NULL, vdso_base,
vdso_pages << PAGE_SHIFT, 0, 0);
- if (vdso_base & ~PAGE_MASK)
+ if (vdso_base & ~PAGE_MASK) {
+ kmem_cache_free(vm_area_cachep, vma);
return (int)vdso_base;
+ }
current->thread.vdso_base = vdso_base;
@@ -266,7 +265,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
vma->vm_ops = &vdso_vmops;
down_write(&mm->mmap_sem);
- insert_vm_struct(mm, vma);
+ if (insert_vm_struct(mm, vma)) {
+ up_write(&mm->mmap_sem);
+ kmem_cache_free(vm_area_cachep, vma);
+ return -ENOMEM;
+ }
mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
up_write(&mm->mmap_sem);
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
index 76fbfa9..0b6e967 100644
--- a/arch/ppc64/lib/Makefile
+++ b/arch/ppc64/lib/Makefile
@@ -2,7 +2,7 @@
# Makefile for ppc64-specific library files..
#
-lib-y := checksum.o dec_and_lock.o string.o strcase.o
+lib-y := checksum.o string.o strcase.o
lib-y += copypage.o memcpy.o copyuser.o usercopy.o
# Lock primitives are defined as no-ops in include/linux/spinlock.h
diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c
deleted file mode 100644
index 7b9d4da..0000000
--- a/arch/ppc64/lib/dec_and_lock.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * ppc64 version of atomic_dec_and_lock() using cmpxchg
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * This is an implementation of the notion of "decrement a
- * reference count, and return locked if it decremented to zero".
- *
- * This implementation can be used on any architecture that
- * has a cmpxchg, and where atomic->value is an int holding
- * the value of the atomic (i.e. the high bits aren't used
- * for a lock or anything like that).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- int counter;
- int newcount;
-
- for (;;) {
- counter = atomic_read(atomic);
- newcount = counter - 1;
- if (!newcount)
- break; /* do it the slow way */
-
- newcount = cmpxchg(&atomic->counter, counter, newcount);
- if (newcount == counter)
- return 0;
- }
-
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
index 7fbc68b..be3f25c 100644
--- a/arch/ppc64/mm/fault.c
+++ b/arch/ppc64/mm/fault.c
@@ -38,6 +38,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/kdebug.h>
+#include <asm/siginfo.h>
/*
* Check whether the instruction at regs->nip is a store using
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 0865251..45d44c6 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc4
-# Fri Jul 29 14:49:30 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 16:46:19 2005
#
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -21,6 +21,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
# General setup
#
CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
@@ -33,6 +34,7 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
@@ -94,6 +96,7 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
#
# I/O subsystem configuration
@@ -151,8 +154,8 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-CONFIG_IP_TCPDIAG_IPV6=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
@@ -165,6 +168,11 @@ CONFIG_IPV6=y
# CONFIG_NETFILTER is not set
#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
@@ -217,9 +225,11 @@ CONFIG_NET_CLS_POLICE=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
# CONFIG_PCMCIA is not set
#
@@ -233,6 +243,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
CONFIG_SCSI_PROC_FS=y
@@ -260,6 +271,7 @@ CONFIG_SCSI_LOGGING=y
# CONFIG_SCSI_SPI_ATTRS is not set
CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
#
# SCSI low-level drivers
@@ -280,7 +292,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
# CONFIG_CDROM_PKTCDVD is not set
@@ -384,6 +395,10 @@ CONFIG_EQUALIZER=m
CONFIG_TUN=m
#
+# PHY device support
+#
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -453,10 +468,6 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -465,6 +476,7 @@ CONFIG_INOTIFY=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -485,11 +497,10 @@ CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -533,6 +544,7 @@ CONFIG_SUNRPC=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
#
# Partition Types
@@ -572,6 +584,7 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
@@ -626,5 +639,6 @@ CONFIG_CRYPTO=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index ab1e49d2..8584dd8 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390_ext.o debug.o profile.o irq.o
+ semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o
extra-$(CONFIG_ARCH_S390_31) += head.o
extra-$(CONFIG_ARCH_S390X) += head64.o
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 58fc7fb..9b30f4c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -108,7 +108,7 @@ STACK_SIZE = 1 << STACK_SHIFT
bl BASED(0f)
l %r14,BASED(.Lcleanup_critical)
basr %r14,%r14
- tm 0(%r12),0x01 # retest problem state after cleanup
+ tm 1(%r12),0x01 # retest problem state after cleanup
bnz BASED(1f)
0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ?
slr %r14,%r15
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d0c9ffa..7b9b4a2 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -101,7 +101,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
clc \psworg+8(8),BASED(.Lcritical_start)
jl 0f
brasl %r14,cleanup_critical
- tm 0(%r12),0x01 # retest problem state after cleanup
+ tm 1(%r12),0x01 # retest problem state after cleanup
jnz 1f
0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ?
slgr %r14,%r15
diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c
new file mode 100644
index 0000000..83cb42b
--- /dev/null
+++ b/arch/s390/kernel/reipl_diag.c
@@ -0,0 +1,39 @@
+/*
+ * This file contains the implementation of the
+ * Linux re-IPL support
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Volker Sameske (sameske@de.ibm.com)
+ *
+ */
+
+#include <linux/kernel.h>
+
+static unsigned int reipl_diag_rc1;
+static unsigned int reipl_diag_rc2;
+
+/*
+ * re-IPL the system using the last used IPL parameters
+ */
+void reipl_diag(void)
+{
+ asm volatile (
+ " la %%r4,0\n"
+ " la %%r5,0\n"
+ " diag %%r4,%2,0x308\n"
+ "0:\n"
+ " st %%r4,%0\n"
+ " st %%r5,%1\n"
+ ".section __ex_table,\"a\"\n"
+#ifdef __s390x__
+ " .align 8\n"
+ " .quad 0b, 0b\n"
+#else
+ " .align 4\n"
+ " .long 0b, 0b\n"
+#endif
+ ".previous\n"
+ : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2)
+ : "d" (3) : "cc", "4", "5" );
+}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 5ba5a54..5204778 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -261,8 +261,11 @@ void (*_machine_power_off)(void) = machine_power_off_smp;
* Reboot, halt and power_off routines for non SMP.
*/
extern void reipl(unsigned long devno);
+extern void reipl_diag(void);
static void do_machine_restart_nonsmp(char * __unused)
{
+ reipl_diag();
+
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0);
else
@@ -634,6 +637,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
struct cpuinfo_S390 *cpuinfo;
unsigned long n = (unsigned long) v - 1;
+ preempt_disable();
if (!n) {
seq_printf(m, "vendor_id : IBM/S390\n"
"# processors : %i\n"
@@ -658,6 +662,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpuinfo->cpu_id.ident,
cpuinfo->cpu_id.machine);
}
+ preempt_enable();
return 0;
}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 85222fe..e13c87b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -65,6 +65,7 @@ extern char vmhalt_cmd[];
extern char vmpoff_cmd[];
extern void reipl(unsigned long devno);
+extern void reipl_diag(void);
static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig);
@@ -283,6 +284,8 @@ static void do_machine_restart(void * __unused)
* interrupted by an external interrupt and s390irq
* locks are always held disabled).
*/
+ reipl_diag();
+
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0, NULL);
else
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
index cd8d39fb..af0e941 100644
--- a/arch/sparc64/Kconfig.debug
+++ b/arch/sparc64/Kconfig.debug
@@ -33,14 +33,6 @@ config DEBUG_BOOTMEM
depends on DEBUG_KERNEL
bool "Debug BOOTMEM initialization"
-# We have a custom atomic_dec_and_lock() implementation but it's not
-# compatible with spinlock debugging so we need to fall back on
-# the generic version in that case.
-config HAVE_DEC_LOCK
- bool
- depends on SMP && !DEBUG_SPINLOCK
- default y
-
config MCOUNT
bool
depends on STACK_DEBUG
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index cbb5e59..fb7a537 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -163,9 +163,6 @@ EXPORT_SYMBOL(atomic64_add);
EXPORT_SYMBOL(atomic64_add_ret);
EXPORT_SYMBOL(atomic64_sub);
EXPORT_SYMBOL(atomic64_sub_ret);
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
/* Atomic bit operations. */
EXPORT_SYMBOL(test_and_set_bit);
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index d968aeb..c295806 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,6 +14,4 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
copy_in_user.o user_fixup.o memmove.o \
mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
-
obj-y += iomap.o
diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S
deleted file mode 100644
index 8ee288d..0000000
--- a/arch/sparc64/lib/dec_and_lock.S
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $Id: dec_and_lock.S,v 1.5 2001/11/18 00:12:56 davem Exp $
- * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()"
- * using cas and ldstub instructions.
- *
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
- */
-#include <linux/config.h>
-#include <asm/thread_info.h>
-
- .text
- .align 64
-
- /* CAS basically works like this:
- *
- * void CAS(MEM, REG1, REG2)
- * {
- * START_ATOMIC();
- * if (*(MEM) == REG1) {
- * TMP = *(MEM);
- * *(MEM) = REG2;
- * REG2 = TMP;
- * } else
- * REG2 = *(MEM);
- * END_ATOMIC();
- * }
- */
-
- .globl _atomic_dec_and_lock
-_atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */
-loop1: lduw [%o0], %g2
- subcc %g2, 1, %g7
- be,pn %icc, start_to_zero
- nop
-nzero: cas [%o0], %g2, %g7
- cmp %g2, %g7
- bne,pn %icc, loop1
- mov 0, %g1
-
-out:
- membar #StoreLoad | #StoreStore
- retl
- mov %g1, %o0
-start_to_zero:
-#ifdef CONFIG_PREEMPT
- ldsw [%g6 + TI_PRE_COUNT], %g3
- add %g3, 1, %g3
- stw %g3, [%g6 + TI_PRE_COUNT]
-#endif
-to_zero:
- ldstub [%o1], %g3
- membar #StoreLoad | #StoreStore
- brnz,pn %g3, spin_on_lock
- nop
-loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */
- cmp %g2, %g7
-
- be,pt %icc, out
- mov 1, %g1
- lduw [%o0], %g2
- subcc %g2, 1, %g7
- be,pn %icc, loop2
- nop
- membar #StoreStore | #LoadStore
- stb %g0, [%o1]
-#ifdef CONFIG_PREEMPT
- ldsw [%g6 + TI_PRE_COUNT], %g3
- sub %g3, 1, %g3
- stw %g3, [%g6 + TI_PRE_COUNT]
-#endif
-
- b,pt %xcc, nzero
- nop
-spin_on_lock:
- ldub [%o1], %g3
- membar #LoadLoad
- brnz,pt %g3, spin_on_lock
- nop
- ba,pt %xcc, to_zero
- nop
- nop
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index 8ad156a..5d92cac 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -42,3 +42,7 @@ config ARCH_HAS_SC_SIGNALS
config ARCH_REUSE_HOST_VSYSCALL_AREA
bool
default y
+
+config X86_CMPXCHG
+ bool
+ default y
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 7a0d115..5db136e 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -13,7 +13,6 @@
#include <errno.h>
#include <unistd.h>
-#include <linux/inet.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
@@ -55,7 +54,7 @@ static int mcast_open(void *data)
struct mcast_data *pri = data;
struct sockaddr_in *sin = pri->mcast_addr;
struct ip_mreq mreq;
- int fd = -EINVAL, yes = 1, err = -EINVAL;;
+ int fd, yes = 1, err = 0;
if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
@@ -66,13 +65,14 @@ static int mcast_open(void *data)
if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n",
errno);
- fd = -errno;
+ err = -errno;
goto out;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno);
+ err = -errno;
goto out_close;
}
@@ -81,6 +81,7 @@ static int mcast_open(void *data)
sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno);
+ err = -errno;
goto out_close;
}
@@ -88,12 +89,14 @@ static int mcast_open(void *data)
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno);
+ err = -errno;
goto out_close;
}
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno);
+ err = -errno;
goto out_close;
}
@@ -108,14 +111,15 @@ static int mcast_open(void *data)
"interface on the host.\n");
printk("eth0 should be configured in order to use the "
"multicast transport.\n");
+ err = -errno;
goto out_close;
}
- out:
return fd;
out_close:
os_close_file(fd);
+ out:
return err;
}
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index c190c24..12c9536 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -32,6 +32,7 @@
#include "os.h"
#include "umid.h"
#include "irq_kern.h"
+#include "choose-mode.h"
static int do_unlink_socket(struct notifier_block *notifier,
unsigned long what, void *data)
@@ -276,6 +277,7 @@ void mconsole_proc(struct mc_request *req)
go - continue the UML after a 'stop' \n\
log <string> - make UML enter <string> into the kernel log\n\
proc <file> - returns the contents of the UML's /proc/<file>\n\
+ stack <pid> - returns the stack of the specified pid\n\
"
void mconsole_help(struct mc_request *req)
@@ -479,6 +481,56 @@ void mconsole_sysrq(struct mc_request *req)
}
#endif
+/* Mconsole stack trace
+ * Added by Allan Graves, Jeff Dike
+ * Dumps a stacks registers to the linux console.
+ * Usage stack <pid>.
+ */
+void do_stack(struct mc_request *req)
+{
+ char *ptr = req->request.data;
+ int pid_requested= -1;
+ struct task_struct *from = NULL;
+ struct task_struct *to = NULL;
+
+ /* Would be nice:
+ * 1) Send showregs output to mconsole.
+ * 2) Add a way to stack dump all pids.
+ */
+
+ ptr += strlen("stack");
+ while(isspace(*ptr)) ptr++;
+
+ /* Should really check for multiple pids or reject bad args here */
+ /* What do the arguments in mconsole_reply mean? */
+ if(sscanf(ptr, "%d", &pid_requested) == 0){
+ mconsole_reply(req, "Please specify a pid", 1, 0);
+ return;
+ }
+
+ from = current;
+ to = find_task_by_pid(pid_requested);
+
+ if((to == NULL) || (pid_requested == 0)) {
+ mconsole_reply(req, "Couldn't find that pid", 1, 0);
+ return;
+ }
+ to->thread.saved_task = current;
+
+ switch_to(from, to, from);
+ mconsole_reply(req, "Stack Dumped to console and message log", 0, 0);
+}
+
+void mconsole_stack(struct mc_request *req)
+{
+ /* This command doesn't work in TT mode, so let's check and then
+ * get out of here
+ */
+ CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode",
+ 1, 0),
+ do_stack(req));
+}
+
/* Changed by mconsole_setup, which is __setup, and called before SMP is
* active.
*/
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index fe5afb132..310c1f8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = {
{ "go", mconsole_go, MCONSOLE_INTR },
{ "log", mconsole_log, MCONSOLE_INTR },
{ "proc", mconsole_proc, MCONSOLE_PROC },
+ { "stack", mconsole_stack, MCONSOLE_INTR },
};
/* Initialized in mconsole_init, which is an initcall */
@@ -172,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
if(notify_sock < 0){
notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if(notify_sock < 0){
- printk("mconsole_notify - socket failed, errno = %d\n",
- errno);
err = -errno;
+ printk("mconsole_notify - socket failed, errno = %d\n",
+ err);
}
}
unlock_notify();
@@ -197,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
sizeof(target));
if(n < 0){
- printk("mconsole_notify - sendto failed, errno = %d\n", errno);
err = -errno;
+ printk("mconsole_notify - sendto failed, errno = %d\n", errno);
}
return(err);
}
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index ed84d01..0306a1b 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d,
fd = get_pty();
if(fd < 0){
+ err = -errno;
printk("open_pts : Failed to open pts\n");
- return(-errno);
+ return err;
}
if(data->raw){
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
deleted file mode 100644
index b94d2bc4f..0000000
--- a/arch/um/drivers/ubd_user.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sched.h>
-#include <signal.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/param.h>
-#include "asm/types.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "ubd_user.h"
-#include "os.h"
-#include "cow.h"
-
-#include <endian.h>
-#include <byteswap.h>
-
-void ignore_sigwinch_sig(void)
-{
- signal(SIGWINCH, SIG_IGN);
-}
-
-int start_io_thread(unsigned long sp, int *fd_out)
-{
- int pid, fds[2], err;
-
- err = os_pipe(fds, 1, 1);
- if(err < 0){
- printk("start_io_thread - os_pipe failed, err = %d\n", -err);
- goto out;
- }
-
- kernel_fd = fds[0];
- *fd_out = fds[1];
-
- pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
- NULL);
- if(pid < 0){
- printk("start_io_thread - clone failed : errno = %d\n", errno);
- err = -errno;
- goto out_close;
- }
-
- return(pid);
-
- out_close:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
- kernel_fd = -1;
- *fd_out = -1;
- out:
- return(err);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 93dc191..90e0e5f 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d,
fd = mkstemp(file);
if(fd < 0){
+ err = -errno;
printk("xterm_open : mkstemp failed, errno = %d\n", errno);
- return(-errno);
+ return err;
}
if(unlink(file)){
+ err = -errno;
printk("xterm_open : unlink failed, errno = %d\n", errno);
- return(-errno);
+ return err;
}
os_close_file(fd);
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index cfa368e..b1b512f 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -81,6 +81,7 @@ extern void mconsole_stop(struct mc_request *req);
extern void mconsole_go(struct mc_request *req);
extern void mconsole_log(struct mc_request *req);
extern void mconsole_proc(struct mc_request *req);
+extern void mconsole_stack(struct mc_request *req);
extern int mconsole_get_request(int fd, struct mc_request *req);
extern int mconsole_notify(char *sock_name, int type, const void *data,
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index d6404bb..9fef412 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -51,7 +51,6 @@ extern unsigned long task_size;
extern void check_devanon(void);
extern int init_mem_user(void);
-extern int create_mem_file(unsigned long len);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
extern int init_maps(unsigned long physmem, unsigned long iomem,
@@ -64,20 +63,6 @@ extern unsigned long phys_offset(unsigned long phys);
extern void unmap_physmem(void);
extern void map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
-extern int protect_memory(unsigned long addr, unsigned long len,
- int r, int w, int x, int must_succeed);
extern unsigned long get_kmem_end(void);
-extern void check_tmpexec(void);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 4c36245..583329d 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -157,6 +157,9 @@ extern int os_lock_file(int fd, int excl);
extern void os_early_checks(void);
extern int can_do_skas(void);
+/* mem.c */
+extern int create_mem_file(unsigned long len);
+
/* process.c */
extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
@@ -181,6 +184,8 @@ extern unsigned long long os_usecs(void);
/* tt.c
* for tt mode only (will be deleted in future...)
*/
+extern int protect_memory(unsigned long addr, unsigned long len,
+ int r, int w, int x, int must_succeed);
extern void forward_pending_sigio(int target);
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *));
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 614b8eb..1a0001b 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -1,4 +1,4 @@
-#
+#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
@@ -7,11 +7,11 @@ extra-y := vmlinux.lds
clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
- helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
- physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
- sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \
- tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \
- uaccess_user.o um_arch.o umid.o user_util.o
+ helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \
+ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
+ signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
+ time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
+ umid.o user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,8 +24,8 @@ obj-$(CONFIG_MODE_SKAS) += skas/
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := $(user-objs-y) config.o helper.o main.o tempfile.o time.o \
- tty_log.o umid.o user_util.o
+USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \
+ user_util.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
index f83e1e8..33fb0bd 100644
--- a/arch/um/kernel/helper.c
+++ b/arch/um/kernel/helper.c
@@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
data.fd = fds[1];
pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
if(pid < 0){
- printk("run_helper : clone failed, errno = %d\n", errno);
ret = -errno;
+ printk("run_helper : clone failed, errno = %d\n", errno);
goto out_close;
}
@@ -122,7 +122,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
unsigned long *stack_out, int stack_order)
{
unsigned long stack, sp;
- int pid, status;
+ int pid, status, err;
stack = alloc_stack(stack_order, um_in_interrupt());
if(stack == 0) return(-ENOMEM);
@@ -130,16 +130,18 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
sp = stack + (page_size() << stack_order) - sizeof(void *);
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
if(pid < 0){
+ err = -errno;
printk("run_helper_thread : clone failed, errno = %d\n",
errno);
- return(-errno);
+ return err;
}
if(stack_out == NULL){
CATCH_EINTR(pid = waitpid(pid, &status, 0));
if(pid < 0){
+ err = -errno;
printk("run_helper_thread - wait failed, errno = %d\n",
errno);
- pid = -errno;
+ pid = err;
}
if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
printk("run_helper_thread - thread returned status "
@@ -156,8 +158,8 @@ int helper_wait(int pid)
CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
if(ret < 0){
+ ret = -errno;
printk("helper_wait : waitpid failed, errno = %d\n", errno);
- return(-errno);
}
return(ret);
}
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index cd7c85b..49ed5dd 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -13,6 +13,7 @@
#include "asm/pgtable.h"
#include "user_util.h"
#include "mem_user.h"
+#include "os.h"
static struct fs_struct init_fs = INIT_FS;
struct mm_struct init_mm = INIT_MM(init_mm);
@@ -45,8 +46,8 @@ __attribute__((__section__(".data.init_task"))) =
void unprotect_stack(unsigned long stack)
{
- protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
- 1, 1, 0, 1);
+ os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
+ 1, 1, 0);
}
/*
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 64fa062..ea008b0 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
@@ -19,6 +19,10 @@
#include "mem_user.h"
#include "uml_uaccess.h"
#include "os.h"
+#include "linux/types.h"
+#include "linux/string.h"
+#include "init.h"
+#include "kern_constants.h"
extern char __binary_start;
@@ -368,6 +372,16 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return pte;
}
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
+extern int parse_iomem(char *str, int *add) __init;
+
+__uml_setup("iomem=", parse_iomem,
+"iomem=<name>,<file>\n"
+" Configure <file> as an IO memory region named <name>.\n\n"
+);
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
deleted file mode 100644
index 4a663fd..0000000
--- a/arch/um/kernel/mem_user.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * arch/um/kernel/mem_user.c
- *
- * BRIEF MODULE DESCRIPTION
- * user side memory routines for supporting IO memory inside user mode linux
- *
- * Copyright (C) 2001 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include "kern_util.h"
-#include "user.h"
-#include "user_util.h"
-#include "mem_user.h"
-#include "init.h"
-#include "os.h"
-#include "tempfile.h"
-#include "kern_constants.h"
-
-#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
-
-static int create_tmp_file(unsigned long len)
-{
- int fd, err;
- char zero;
-
- fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
- if(fd < 0) {
- os_print_error(fd, "make_tempfile");
- exit(1);
- }
-
- err = os_mode_fd(fd, 0777);
- if(err < 0){
- os_print_error(err, "os_mode_fd");
- exit(1);
- }
- err = os_seek_file(fd, len);
- if(err < 0){
- os_print_error(err, "os_seek_file");
- exit(1);
- }
- zero = 0;
- err = os_write_file(fd, &zero, 1);
- if(err != 1){
- os_print_error(err, "os_write_file");
- exit(1);
- }
-
- return(fd);
-}
-
-void check_tmpexec(void)
-{
- void *addr;
- int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
- addr = mmap(NULL, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
- printf("Checking PROT_EXEC mmap in /tmp...");
- fflush(stdout);
- if(addr == MAP_FAILED){
- err = errno;
- perror("failed");
- if(err == EPERM)
- printf("/tmp must be not mounted noexec\n");
- exit(1);
- }
- printf("OK\n");
- munmap(addr, UM_KERN_PAGE_SIZE);
-
- os_close_file(fd);
-}
-
-static int have_devanon = 0;
-
-void check_devanon(void)
-{
- int fd;
-
- printk("Checking for /dev/anon on the host...");
- fd = open("/dev/anon", O_RDWR);
- if(fd < 0){
- printk("Not available (open failed with errno %d)\n", errno);
- return;
- }
-
- printk("OK\n");
- have_devanon = 1;
-}
-
-static int create_anon_file(unsigned long len)
-{
- void *addr;
- int fd;
-
- fd = open("/dev/anon", O_RDWR);
- if(fd < 0) {
- os_print_error(fd, "opening /dev/anon");
- exit(1);
- }
-
- addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if(addr == MAP_FAILED){
- perror("mapping physmem file");
- exit(1);
- }
- munmap(addr, len);
-
- return(fd);
-}
-
-int create_mem_file(unsigned long len)
-{
- int err, fd;
-
- if(have_devanon)
- fd = create_anon_file(len);
- else fd = create_tmp_file(len);
-
- err = os_set_exec_close(fd, 1);
- if(err < 0)
- os_print_error(err, "exec_close");
- return(fd);
-}
-
-struct iomem_region *iomem_regions = NULL;
-int iomem_size = 0;
-
-static int __init parse_iomem(char *str, int *add)
-{
- struct iomem_region *new;
- struct uml_stat buf;
- char *file, *driver;
- int fd, err, size;
-
- driver = str;
- file = strchr(str,',');
- if(file == NULL){
- printf("parse_iomem : failed to parse iomem\n");
- goto out;
- }
- *file = '\0';
- file++;
- fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
- if(fd < 0){
- os_print_error(fd, "parse_iomem - Couldn't open io file");
- goto out;
- }
-
- err = os_stat_fd(fd, &buf);
- if(err < 0){
- os_print_error(err, "parse_iomem - cannot stat_fd file");
- goto out_close;
- }
-
- new = malloc(sizeof(*new));
- if(new == NULL){
- perror("Couldn't allocate iomem_region struct");
- goto out_close;
- }
-
- size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
-
- *new = ((struct iomem_region) { .next = iomem_regions,
- .driver = driver,
- .fd = fd,
- .size = size,
- .phys = 0,
- .virt = 0 });
- iomem_regions = new;
- iomem_size += new->size + UM_KERN_PAGE_SIZE;
-
- return(0);
- out_close:
- os_close_file(fd);
- out:
- return(1);
-}
-
-__uml_setup("iomem=", parse_iomem,
-"iomem=<name>,<file>\n"
-" Configure <file> as an IO memory region named <name>.\n\n"
-);
-
-int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
- int must_succeed)
-{
- int err;
-
- err = os_protect_memory((void *) addr, len, r, w, x);
- if(err < 0){
- if(must_succeed)
- panic("protect failed, err = %d", -err);
- else return(err);
- }
- return(0);
-}
-
-#if 0
-/* Debugging facility for dumping stuff out to the host, avoiding the timing
- * problems that come with printf and breakpoints.
- * Enable in case of emergency.
- */
-
-int logging = 1;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[512];
-
-void log(char *fmt, ...)
-{
- va_list ap;
- struct timeval tv;
- struct openflags flags;
-
- if(logging == 0) return;
- if(logging_fd < 0){
- flags = of_create(of_trunc(of_rdwr(OPENFLAGS())));
- logging_fd = os_open_file("log", flags, 0644);
- }
- gettimeofday(&tv, NULL);
- sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec,
- tv.tv_usec);
- va_start(ap, fmt);
- vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
- va_end(ap);
- write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index c23d8a0..39cf568 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -113,8 +113,23 @@ void set_current(void *t)
void *_switch_to(void *prev, void *next, void *last)
{
- return(CHOOSE_MODE(switch_to_tt(prev, next),
- switch_to_skas(prev, next)));
+ struct task_struct *from = prev;
+ struct task_struct *to= next;
+
+ to->thread.prev_sched = from;
+ set_current(to);
+
+ do {
+ current->thread.saved_task = NULL ;
+ CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
+ if(current->thread.saved_task)
+ show_regs(&(current->thread.regs));
+ next= current->thread.saved_task;
+ prev= current;
+ } while(current->thread.saved_task);
+
+ return(current->thread.prev_sched);
+
}
void interrupt_end(void)
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
index e484900..c97a80d 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/kernel/skas/include/mode_kern-skas.h
@@ -11,7 +11,7 @@
#include "asm/ptrace.h"
extern void flush_thread_skas(void);
-extern void *switch_to_skas(void *prev, void *next);
+extern void switch_to_skas(void *prev, void *next);
extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
unsigned long esp);
extern int copy_thread_skas(int nr, unsigned long clone_flags,
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 3d1b227..efe92e8 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -24,7 +24,7 @@
#include "proc_mm.h"
#include "registers.h"
-void *switch_to_skas(void *prev, void *next)
+void switch_to_skas(void *prev, void *next)
{
struct task_struct *from, *to;
@@ -35,16 +35,11 @@ void *switch_to_skas(void *prev, void *next)
if(current->pid == 0)
switch_timers(0);
- to->thread.prev_sched = from;
- set_current(to);
-
switch_threads(&from->thread.mode.skas.switch_buf,
to->thread.mode.skas.switch_buf);
if(current->pid == 0)
switch_timers(1);
-
- return(current->thread.prev_sched);
}
extern void schedule_tail(struct task_struct *prev);
diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c
deleted file mode 100644
index b1674bc..0000000
--- a/arch/um/kernel/tempfile.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/param.h>
-#include "init.h"
-
-/* Modified from create_mem_file and start_debugger */
-static char *tempdir = NULL;
-
-static void __init find_tempdir(void)
-{
- char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
- int i;
- char *dir = NULL;
-
- if(tempdir != NULL) return; /* We've already been called */
- for(i = 0; dirs[i]; i++){
- dir = getenv(dirs[i]);
- if((dir != NULL) && (*dir != '\0'))
- break;
- }
- if((dir == NULL) || (*dir == '\0'))
- dir = "/tmp";
-
- tempdir = malloc(strlen(dir) + 2);
- if(tempdir == NULL){
- fprintf(stderr, "Failed to malloc tempdir, "
- "errno = %d\n", errno);
- return;
- }
- strcpy(tempdir, dir);
- strcat(tempdir, "/");
-}
-
-int make_tempfile(const char *template, char **out_tempname, int do_unlink)
-{
- char tempname[MAXPATHLEN];
- int fd;
-
- find_tempdir();
- if (*template != '/')
- strcpy(tempname, tempdir);
- else
- *tempname = 0;
- strcat(tempname, template);
- fd = mkstemp(tempname);
- if(fd < 0){
- fprintf(stderr, "open - cannot create %s: %s\n", tempname,
- strerror(errno));
- return -1;
- }
- if(do_unlink && (unlink(tempname) < 0)){
- perror("unlink");
- return -1;
- }
- if(out_tempname){
- *out_tempname = strdup(tempname);
- if(*out_tempname == NULL){
- perror("strdup");
- return -1;
- }
- }
- return(fd);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 80ed618..0a562c3 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -307,7 +307,7 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
}
else if(pte_newprot(*pte)){
updated = 1;
- protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
}
addr += PAGE_SIZE;
}
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
index e0ca0e0..2a35b15 100644
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ b/arch/um/kernel/tt/include/mode_kern-tt.h
@@ -11,7 +11,7 @@
#include "asm/ptrace.h"
#include "asm/uaccess.h"
-extern void *switch_to_tt(void *prev, void *next);
+extern void switch_to_tt(void *prev, void *next);
extern void flush_thread_tt(void);
extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
unsigned long esp);
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
index 3085267..03e5898 100644
--- a/arch/um/kernel/tt/mem_user.c
+++ b/arch/um/kernel/tt/mem_user.c
@@ -12,6 +12,7 @@
#include "tt.h"
#include "mem_user.h"
#include "user_util.h"
+#include "os.h"
void remap_data(void *segment_start, void *segment_end, int w)
{
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index a189a2b..0de05a268 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -26,7 +26,7 @@
#include "init.h"
#include "tt.h"
-void *switch_to_tt(void *prev, void *next, void *last)
+int switch_to_tt(void *prev, void *next, void *last)
{
struct task_struct *from, *to, *prev_sched;
unsigned long flags;
@@ -36,8 +36,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
from = prev;
to = next;
- to->thread.prev_sched = from;
-
cpu = from->thread_info->cpu;
if(cpu == 0)
forward_interrupts(to->thread.mode.tt.extern_pid);
@@ -53,7 +51,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
forward_pending_sigio(to->thread.mode.tt.extern_pid);
c = 0;
- set_current(to);
err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
if(err != sizeof(c))
@@ -85,8 +82,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
flush_tlb_all();
local_irq_restore(flags);
-
- return(current->thread.prev_sched);
}
void release_thread_tt(struct task_struct *task)
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 09f6f7c..f0a2759 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -361,11 +361,6 @@ int linux_main(int argc, char **argv)
uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
&host_task_size, &task_size);
- /* Need to check this early because mmapping happens before the
- * kernel is running.
- */
- check_tmpexec();
-
brk_start = (unsigned long) sbrk(0);
CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
/* Increase physical memory size for exec-shield users
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
index 954ff67..a25f3ea 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -109,18 +109,14 @@ int raw(int fd)
int err;
CATCH_EINTR(err = tcgetattr(fd, &tt));
- if (err < 0) {
- printk("tcgetattr failed, errno = %d\n", errno);
- return(-errno);
- }
+ if(err < 0)
+ return -errno;
cfmakeraw(&tt);
CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
- if (err < 0) {
- printk("tcsetattr failed, errno = %d\n", errno);
- return(-errno);
- }
+ if(err < 0)
+ return -errno;
/* XXX tcsetattr could have applied only some changes
* (and cfmakeraw() is a set of changes) */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 7a16624..d15ec2a 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,11 +3,11 @@
# Licensed under the GPL
#
-obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
- tty.o user_syms.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \
+ tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/
-USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
- tty.o
+USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \
+ time.o tt.o tty.o
elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index b04897c..298d563 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -117,6 +117,8 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio)
err = io_submit(ctx, 1, &iocbp);
if(err > 0)
err = 0;
+ else
+ err = -errno;
out:
return err;
@@ -142,7 +144,7 @@ static int aio_thread(void *arg)
"errno = %d\n", errno);
}
else {
- aio = (struct aio_context *) event.data;
+ aio = (struct aio_context *) (long) event.data;
if(update_aio(aio, event.res)){
do_aio(ctx, aio);
continue;
@@ -313,15 +315,16 @@ static int init_aio_26(void)
int err;
if(io_setup(256, &ctx)){
+ err = -errno;
printk("aio_thread failed to initialize context, err = %d\n",
errno);
- return -errno;
+ return err;
}
err = run_helper_thread(aio_thread, NULL,
CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
if(err < 0)
- return -errno;
+ return err;
aio_pid = err;
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 4b83c6c..4ba9b17 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
- int pid, n;
+ int pid, n, err;
sprintf(version_buf, "%d", UML_NET_VERSION);
@@ -105,9 +105,10 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
n = recvmsg(me, &msg, 0);
*used_out = n;
if(n < 0){
+ err = -errno;
printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
errno);
- return(-errno);
+ return err;
}
CATCH_EINTR(waitpid(pid, NULL, 0));
@@ -147,9 +148,10 @@ static int tuntap_open(void *data)
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
+ err = -errno;
printk("TUNSETIFF failed, errno = %d\n", errno);
os_close_file(pri->fd);
- return(-errno);
+ return err;
}
}
else {
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 1399520..e770cb0 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -54,7 +54,8 @@ __init void scan_elf_aux( char **envp)
* a_un, so we have to use a_val, which is
* all that's left.
*/
- elf_aux_platform = (char *) auxv->a_un.a_val;
+ elf_aux_platform =
+ (char *) (long) auxv->a_un.a_val;
break;
case AT_PAGESZ:
page_size = auxv->a_un.a_val;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index fd45bb2..f55773c 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols)
int os_new_tty_pgrp(int fd, int pid)
{
- if(ioctl(fd, TIOCSCTTY, 0) < 0){
- printk("TIOCSCTTY failed, errno = %d\n", errno);
- return(-errno);
- }
+ if(ioctl(fd, TIOCSCTTY, 0) < 0)
+ return -errno;
- if(tcsetpgrp(fd, pid) < 0){
- printk("tcsetpgrp failed, errno = %d\n", errno);
- return(-errno);
- }
+ if(tcsetpgrp(fd, pid) < 0)
+ return -errno;
return(0);
}
@@ -146,18 +142,12 @@ int os_set_slip(int fd)
int disc, sencap;
disc = N_SLIP;
- if(ioctl(fd, TIOCSETD, &disc) < 0){
- printk("Failed to set slip line discipline - "
- "errno = %d\n", errno);
- return(-errno);
- }
+ if(ioctl(fd, TIOCSETD, &disc) < 0)
+ return -errno;
sencap = 0;
- if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
- printk("Failed to set slip encapsulation - "
- "errno = %d\n", errno);
- return(-errno);
- }
+ if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
+ return -errno;
return(0);
}
@@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave)
int flags;
flags = fcntl(master, F_GETFL);
- if(flags < 0) {
- printk("fcntl F_GETFL failed, errno = %d\n", errno);
- return(-errno);
- }
+ if(flags < 0)
+ return errno;
if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
- (fcntl(master, F_SETOWN, os_getpid()) < 0)){
- printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n",
- errno);
- return(-errno);
- }
+ (fcntl(master, F_SETOWN, os_getpid()) < 0))
+ return -errno;
- if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
- printk("fcntl F_SETFL failed, errno = %d\n", errno);
- return(-errno);
- }
+ if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+ return -errno;
return(0);
}
@@ -255,7 +238,7 @@ int os_file_mode(char *file, struct openflags *mode_out)
int os_open_file(char *file, struct openflags flags, int mode)
{
- int fd, f = 0;
+ int fd, err, f = 0;
if(flags.r && flags.w) f = O_RDWR;
else if(flags.r) f = O_RDONLY;
@@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode)
return(-errno);
if(flags.cl && fcntl(fd, F_SETFD, 1)){
+ err = -errno;
os_close_file(fd);
- return(-errno);
+ return err;
}
return(fd);
@@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out)
return(fd);
}
if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
+ err = -errno;
printk("Couldn't get the block size of \"%s\", "
"errno = %d\n", file, errno);
- err = -errno;
os_close_file(fd);
return(err);
}
@@ -473,11 +457,14 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int os_set_fd_async(int fd, int owner)
{
+ int err;
+
/* XXX This should do F_GETFL first */
if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
+ err = -errno;
printk("os_set_fd_async : failed to set O_ASYNC and "
"O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
- return(-errno);
+ return err;
}
#ifdef notdef
if(fcntl(fd, F_SETFD, 1) < 0){
@@ -488,10 +475,11 @@ int os_set_fd_async(int fd, int owner)
if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
(fcntl(fd, F_SETOWN, owner) < 0)){
+ err = -errno;
printk("os_set_fd_async : Failed to fcntl F_SETOWN "
"(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
owner, errno);
- return(-errno);
+ return err;
}
return(0);
@@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking)
if(blocking) flags &= ~O_NONBLOCK;
else flags |= O_NONBLOCK;
- if(fcntl(fd, F_SETFL, flags) < 0){
- printk("Failed to change blocking on fd # %d, errno = %d\n",
- fd, errno);
- return(-errno);
- }
+ if(fcntl(fd, F_SETFL, flags) < 0)
+ return -errno;
+
return(0);
}
@@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
int sock, err;
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (sock < 0){
- printk("create_unix_socket - socket failed, errno = %d\n",
- errno);
- return(-errno);
- }
+ if(sock < 0)
+ return -errno;
if(close_on_exec) {
err = os_set_exec_close(sock, 1);
@@ -628,11 +611,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
snprintf(addr.sun_path, len, "%s", file);
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
- if (err < 0){
- printk("create_listening_socket at '%s' - bind failed, "
- "errno = %d\n", file, errno);
- return(-errno);
- }
+ if(err < 0)
+ return -errno;
return(sock);
}
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
new file mode 100644
index 0000000..8e71eda
--- /dev/null
+++ b/arch/um/os-Linux/mem.c
@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include "kern_util.h"
+#include "user.h"
+#include "user_util.h"
+#include "mem_user.h"
+#include "init.h"
+#include "os.h"
+#include "tempfile.h"
+#include "kern_constants.h"
+
+#include <sys/param.h>
+
+static char *tempdir = NULL;
+
+static void __init find_tempdir(void)
+{
+ char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
+ int i;
+ char *dir = NULL;
+
+ if(tempdir != NULL) return; /* We've already been called */
+ for(i = 0; dirs[i]; i++){
+ dir = getenv(dirs[i]);
+ if((dir != NULL) && (*dir != '\0'))
+ break;
+ }
+ if((dir == NULL) || (*dir == '\0'))
+ dir = "/tmp";
+
+ tempdir = malloc(strlen(dir) + 2);
+ if(tempdir == NULL){
+ fprintf(stderr, "Failed to malloc tempdir, "
+ "errno = %d\n", errno);
+ return;
+ }
+ strcpy(tempdir, dir);
+ strcat(tempdir, "/");
+}
+
+/*
+ * This proc still used in tt-mode
+ * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
+ * So it isn't 'static' yet.
+ */
+int make_tempfile(const char *template, char **out_tempname, int do_unlink)
+{
+ char tempname[MAXPATHLEN];
+ int fd;
+
+ find_tempdir();
+ if (*template != '/')
+ strcpy(tempname, tempdir);
+ else
+ *tempname = 0;
+ strcat(tempname, template);
+ fd = mkstemp(tempname);
+ if(fd < 0){
+ fprintf(stderr, "open - cannot create %s: %s\n", tempname,
+ strerror(errno));
+ return -1;
+ }
+ if(do_unlink && (unlink(tempname) < 0)){
+ perror("unlink");
+ return -1;
+ }
+ if(out_tempname){
+ *out_tempname = strdup(tempname);
+ if(*out_tempname == NULL){
+ perror("strdup");
+ return -1;
+ }
+ }
+ return(fd);
+}
+
+#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
+
+/*
+ * This proc is used in start_up.c
+ * So it isn't 'static'.
+ */
+int create_tmp_file(unsigned long len)
+{
+ int fd, err;
+ char zero;
+
+ fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
+ if(fd < 0) {
+ exit(1);
+ }
+
+ err = fchmod(fd, 0777);
+ if(err < 0){
+ perror("os_mode_fd");
+ exit(1);
+ }
+
+ if (lseek64(fd, len, SEEK_SET) < 0) {
+ perror("os_seek_file");
+ exit(1);
+ }
+
+ zero = 0;
+
+ err = os_write_file(fd, &zero, 1);
+ if(err != 1){
+ errno = -err;
+ perror("os_write_file");
+ exit(1);
+ }
+
+ return(fd);
+}
+
+static int create_anon_file(unsigned long len)
+{
+ void *addr;
+ int fd;
+
+ fd = open("/dev/anon", O_RDWR);
+ if(fd < 0) {
+ perror("opening /dev/anon");
+ exit(1);
+ }
+
+ addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if(addr == MAP_FAILED){
+ perror("mapping physmem file");
+ exit(1);
+ }
+ munmap(addr, len);
+
+ return(fd);
+}
+
+extern int have_devanon;
+
+int create_mem_file(unsigned long len)
+{
+ int err, fd;
+
+ if(have_devanon)
+ fd = create_anon_file(len);
+ else fd = create_tmp_file(len);
+
+ err = os_set_exec_close(fd, 1);
+ if(err < 0){
+ errno = -err;
+ perror("exec_close");
+ }
+ return(fd);
+}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 040cc14..6af8317 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -4,18 +4,22 @@
*/
#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>
+#include <fcntl.h>
#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
#include <setjmp.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <asm/unistd.h>
#include <asm/page.h>
+#include <sys/types.h>
#include "user_util.h"
#include "kern_util.h"
#include "user.h"
@@ -25,6 +29,7 @@
#include "sysdep/sigcontext.h"
#include "irq_user.h"
#include "ptrace_user.h"
+#include "mem_user.h"
#include "time_user.h"
#include "init.h"
#include "os.h"
@@ -32,6 +37,8 @@
#include "choose-mode.h"
#include "mode.h"
#include "tempfile.h"
+#include "kern_constants.h"
+
#ifdef UML_CONFIG_MODE_SKAS
#include "skas.h"
#include "skas_ptrace.h"
@@ -276,9 +283,38 @@ static void __init check_ptrace(void)
check_sysemu();
}
+extern int create_tmp_file(unsigned long len);
+
+static void check_tmpexec(void)
+{
+ void *addr;
+ int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+ addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+ printf("Checking PROT_EXEC mmap in /tmp...");
+ fflush(stdout);
+ if(addr == MAP_FAILED){
+ err = errno;
+ perror("failed");
+ if(err == EPERM)
+ printf("/tmp must be not mounted noexec\n");
+ exit(1);
+ }
+ printf("OK\n");
+ munmap(addr, UM_KERN_PAGE_SIZE);
+
+ close(fd);
+}
+
void os_early_checks(void)
{
check_ptrace();
+
+ /* Need to check this early because mmapping happens before the
+ * kernel is running.
+ */
+ check_tmpexec();
}
static int __init noprocmm_cmd_param(char *str, int* add)
@@ -357,3 +393,72 @@ int can_do_skas(void)
return(0);
}
#endif
+
+int have_devanon = 0;
+
+void check_devanon(void)
+{
+ int fd;
+
+ printk("Checking for /dev/anon on the host...");
+ fd = open("/dev/anon", O_RDWR);
+ if(fd < 0){
+ printk("Not available (open failed with errno %d)\n", errno);
+ return;
+ }
+
+ printk("OK\n");
+ have_devanon = 1;
+}
+
+int __init parse_iomem(char *str, int *add)
+{
+ struct iomem_region *new;
+ struct uml_stat buf;
+ char *file, *driver;
+ int fd, err, size;
+
+ driver = str;
+ file = strchr(str,',');
+ if(file == NULL){
+ printf("parse_iomem : failed to parse iomem\n");
+ goto out;
+ }
+ *file = '\0';
+ file++;
+ fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
+ if(fd < 0){
+ os_print_error(fd, "parse_iomem - Couldn't open io file");
+ goto out;
+ }
+
+ err = os_stat_fd(fd, &buf);
+ if(err < 0){
+ os_print_error(err, "parse_iomem - cannot stat_fd file");
+ goto out_close;
+ }
+
+ new = malloc(sizeof(*new));
+ if(new == NULL){
+ perror("Couldn't allocate iomem_region struct");
+ goto out_close;
+ }
+
+ size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+
+ *new = ((struct iomem_region) { .next = iomem_regions,
+ .driver = driver,
+ .fd = fd,
+ .size = size,
+ .phys = 0,
+ .virt = 0 });
+ iomem_regions = new;
+ iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
+ return(0);
+ out_close:
+ os_close_file(fd);
+ out:
+ return(1);
+}
+
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index 5b047ab..a6db887 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -36,6 +36,20 @@
#include "mode.h"
#include "tempfile.h"
+int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
+ int must_succeed)
+{
+ int err;
+
+ err = os_protect_memory((void *) addr, len, r, w, x);
+ if(err < 0){
+ if(must_succeed)
+ panic("protect failed, err = %d", -err);
+ else return(err);
+ }
+ return(0);
+}
+
/*
*-------------------------
* only for tt mode (will be deleted in future...)
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index e63323e..0969d57 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -277,11 +277,6 @@ source "mm/Kconfig"
config HAVE_ARCH_EARLY_PFN_TO_NID
def_bool y
-config HAVE_DEC_LOCK
- bool
- depends on SMP
- default y
-
config NR_CPUS
int "Maximum number of CPUs (2-256)"
range 2 256
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index c8131f3..d9161e3 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -353,11 +353,6 @@ int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int exec
mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (!mpnt)
return -ENOMEM;
-
- if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
- kmem_cache_free(vm_area_cachep, mpnt);
- return -ENOMEM;
- }
memset(mpnt, 0, sizeof(*mpnt));
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index adbc5f8..3a01329 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -52,17 +52,13 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack)
vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (!vma)
return -ENOMEM;
- if (security_vm_enough_memory(npages)) {
- kmem_cache_free(vm_area_cachep, vma);
- return -ENOMEM;
- }
memset(vma, 0, sizeof(struct vm_area_struct));
/* Could randomize here */
vma->vm_start = VSYSCALL32_BASE;
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_MAYEXEC|VM_MAYWRITE;
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
vma->vm_flags |= mm->def_flags;
vma->vm_page_prot = protection_map[vma->vm_flags & 7];
vma->vm_ops = &syscall32_vm_ops;
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index eb7929e..ab3f87a 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -17,6 +17,8 @@
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/kexec.h>
+#include <linux/module.h>
+
#include <asm/page.h>
#include <asm/e820.h>
#include <asm/proto.h>
@@ -28,6 +30,7 @@ extern char _end[];
* PFN of last memory page.
*/
unsigned long end_pfn;
+EXPORT_SYMBOL(end_pfn);
/*
* end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 522944a..c8eee20 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -299,15 +299,6 @@ void __init check_ioapic(void)
#endif
/* RED-PEN skip them on mptables too? */
return;
- case PCI_VENDOR_ID_ATI:
- /* All timer interrupts on atiixp
- are doubled. Disable one. */
- if (disable_timer_pin_1 == 0) {
- disable_timer_pin_1 = 1;
- printk(KERN_INFO
- "ATI board detected. Disabling timer pin 1.\n");
- }
- return;
}
/* No multi-function device? */
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 969365c..08203b0 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -217,7 +217,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
panicm_found = 1;
}
- tainted |= TAINT_MACHINE_CHECK;
+ add_taint(TAINT_MACHINE_CHECK);
}
/* Never do anything final in the polling timer */
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 4388b8a5..39d445e 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -366,7 +366,7 @@ static void setup_k7_watchdog(void)
| K7_NMI_EVENT;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+ wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
@@ -407,8 +407,8 @@ static int setup_p4_watchdog(void)
wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
- Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
- wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+ Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz * 1000UL / nmi_hz));
+ wrmsrl(MSR_P4_IQ_COUNTER0, -((u64)cpu_khz * 1000 / nmi_hz));
apic_write(APIC_LVTPC, APIC_DM_NMI);
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
return 1;
@@ -506,7 +506,7 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
- wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+ wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
}
}
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 351d8d6..238f73e 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -831,11 +831,26 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
#endif
}
+#define HWCR 0xc0010015
+
static int __init init_amd(struct cpuinfo_x86 *c)
{
int r;
int level;
+#ifdef CONFIG_SMP
+ unsigned long value;
+
+ // Disable TLB flush filter by setting HWCR.FFDIS:
+ // bit 6 of msr C001_0015
+ //
+ // Errata 63 for SH-B3 steppings
+ // Errata 122 for all(?) steppings
+ rdmsrl(HWCR, value);
+ value |= 1 << 6;
+ wrmsrl(HWCR, value);
+#endif
+
/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
clear_bit(0*32+31, &c->x86_capability);
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 68ec030..fd99ddd00 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -178,10 +178,6 @@ EXPORT_SYMBOL(rwsem_down_write_failed_thunk);
EXPORT_SYMBOL(empty_zero_page);
-#ifdef CONFIG_HAVE_DEC_LOCK
-EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
-
EXPORT_SYMBOL(die_chain);
EXPORT_SYMBOL(register_die_notifier);
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
index 6b26a1c..bba5db6 100644
--- a/arch/x86_64/lib/Makefile
+++ b/arch/x86_64/lib/Makefile
@@ -10,5 +10,3 @@ lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
usercopy.o getuser.o putuser.o \
thunk.o clear_page.o copy_page.o bitstr.o bitops.o
lib-y += memcpy.o memmove.o memset.o copy_user.o
-
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/x86_64/lib/dec_and_lock.c b/arch/x86_64/lib/dec_and_lock.c
deleted file mode 100644
index ab43394..0000000
--- a/arch/x86_64/lib/dec_and_lock.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * x86 version of "atomic_dec_and_lock()" using
- * the atomic "cmpxchg" instruction.
- *
- * (For CPU's lacking cmpxchg, we use the slow
- * generic version, and this one never even gets
- * compiled).
- */
-
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- int counter;
- int newcount;
-
-repeat:
- counter = atomic_read(atomic);
- newcount = counter-1;
-
- if (!newcount)
- goto slow_path;
-
- asm volatile("lock; cmpxchgl %1,%2"
- :"=a" (newcount)
- :"r" (newcount), "m" (atomic->counter), "0" (counter));
-
- /* If the above failed, "eax" will have changed */
- if (newcount != counter)
- goto repeat;
- return 0;
-
-slow_path:
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 2b6257b..7e841aa 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -26,10 +26,6 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
-config HAVE_DEC_LOCK
- bool
- default y
-
config GENERIC_HARDIRQS
bool
default y
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 373e7b7..6b2eb6f 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -152,12 +152,13 @@ attribute_container_add_device(struct device *dev,
if (!cont->match(cont, dev))
continue;
- ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL);
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
if (!ic) {
dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
continue;
}
- memset(ic, 0, sizeof(struct internal_container));
+
ic->cont = cont;
class_device_initialize(&ic->classdev);
ic->classdev.dev = get_device(dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d164c32..3b112e3 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -189,12 +189,11 @@ struct class *class_create(struct module *owner, char *name)
struct class *cls;
int retval;
- cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+ cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
- memset(cls, 0x00, sizeof(struct class));
cls->name = name;
cls->owner = owner;
@@ -500,13 +499,13 @@ int class_device_add(struct class_device *class_dev)
/* add the needed attributes to this device */
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
- attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
kobject_del(&class_dev->kobj);
goto register_done;
}
- memset(attr, sizeof(*attr), 0x00);
+
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent->owner;
@@ -577,12 +576,11 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
if (cls == NULL || IS_ERR(cls))
goto error;
- class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+ class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
if (!class_dev) {
retval = -ENOMEM;
goto error;
}
- memset(class_dev, 0x00, sizeof(struct class_device));
class_dev->devt = devt;
class_dev->dev = device;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 5bfa2e9..4acb2c5 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -301,9 +301,9 @@ fw_register_class_device(struct class_device **class_dev_p,
const char *fw_name, struct device *device)
{
int retval;
- struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
+ struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL);
- struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+ struct class_device *class_dev = kzalloc(sizeof(*class_dev),
GFP_KERNEL);
*class_dev_p = NULL;
@@ -313,8 +313,6 @@ fw_register_class_device(struct class_device **class_dev_p,
retval = -ENOMEM;
goto error_kfree;
}
- memset(fw_priv, 0, sizeof (*fw_priv));
- memset(class_dev, 0, sizeof (*class_dev));
init_completion(&fw_priv->completion);
fw_priv->attr_data = firmware_attr_data_tmpl;
@@ -402,14 +400,13 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (!firmware_p)
return -EINVAL;
- *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
+ *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
__FUNCTION__);
retval = -ENOMEM;
goto out;
}
- memset(firmware, 0, sizeof (*firmware));
retval = fw_setup_class_device(firmware, &class_dev, name, device,
hotplug);
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 2f455d8..b449dae 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -135,7 +135,7 @@ retry:
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
- struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+ struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
int i;
if ((p == NULL) || (base == NULL)) {
@@ -144,7 +144,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
return NULL;
}
- memset(base, 0, sizeof(struct probe));
base->dev = 1;
base->range = ~0;
base->get = base_probe;
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3a5f4c9..361e204 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -225,13 +225,12 @@ struct platform_device *platform_device_register_simple(char *name, unsigned int
struct platform_object *pobj;
int retval;
- pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+ pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL);
if (!pobj) {
retval = -ENOMEM;
goto error;
}
- memset(pobj, 0, sizeof(*pobj));
pobj->pdev.name = name;
pobj->pdev.id = id;
pobj->pdev.dev.release = platform_device_release_simple;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 28f2c17..c56f995 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -47,14 +47,14 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.8)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i P600 P800 E400 E300");
+ " SA6i P600 P800 P400 P400i E200 E200i");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -83,12 +83,22 @@ static const struct pci_device_id cciss_pci_device_id[] = {
0x0E11, 0x4091, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
0x103C, 0x3225, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
0x103c, 0x3223, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3231, 0, 0, 0},
+ 0x103c, 0x3234, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3233, 0, 0, 0},
+ 0x103c, 0x3235, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3211, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3212, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3213, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3214, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3215, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -111,8 +121,13 @@ static struct board_type products[] = {
{ 0x40910E11, "Smart Array 6i", &SA5_access},
{ 0x3225103C, "Smart Array P600", &SA5_access},
{ 0x3223103C, "Smart Array P800", &SA5_access},
- { 0x3231103C, "Smart Array E400", &SA5_access},
- { 0x3233103C, "Smart Array E300", &SA5_access},
+ { 0x3234103C, "Smart Array P400", &SA5_access},
+ { 0x3235103C, "Smart Array P400i", &SA5_access},
+ { 0x3211103C, "Smart Array E200i", &SA5_access},
+ { 0x3212103C, "Smart Array E200", &SA5_access},
+ { 0x3213103C, "Smart Array E200i", &SA5_access},
+ { 0x3214103C, "Smart Array E200i", &SA5_access},
+ { 0x3215103C, "Smart Array E200i", &SA5_access},
};
/* How long to wait (in millesconds) for board to go into simple mode */
@@ -140,15 +155,26 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
-static int deregister_disk(struct gendisk *disk);
-static int register_new_disk(ctlr_info_t *h);
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
+static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
+ int withirq, unsigned int *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+ int withirq, unsigned int total_size,
+ unsigned int block_size, InquiryData_struct *inq_buff,
+ drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void start_io( ctlr_info_t *h);
static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
unsigned char *scsi3addr, int cmd_type);
+static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
+ unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
+ int cmd_type);
+
+static void fail_all_cmds(unsigned long ctlr);
#ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
@@ -265,7 +291,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
for(i=0; i<=h->highest_lun; i++) {
drv = &h->drv[i];
- if (drv->block_size == 0)
+ if (drv->heads == 0)
continue;
vol_sz = drv->nr_blocks;
@@ -363,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
return NULL;
memset(c, 0, sizeof(CommandList_struct));
+ c->cmdindex = -1;
+
c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
h->pdev, sizeof(ErrorInfo_struct),
&err_dma_handle);
@@ -393,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
err_dma_handle = h->errinfo_pool_dhandle
+ i*sizeof(ErrorInfo_struct);
h->nr_allocs++;
+
+ c->cmdindex = i;
}
c->busaddr = (__u32) cmd_dma_handle;
@@ -453,6 +483,11 @@ static int cciss_open(struct inode *inode, struct file *filep)
printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
#endif /* CCISS_DEBUG */
+ if (host->busy_initializing)
+ return -EBUSY;
+
+ if (host->busy_initializing || drv->busy_configuring)
+ return -EBUSY;
/*
* Root is allowed to open raw volume zero even if it's not configured
* so array config can still work. Root is also allowed to open any
@@ -796,10 +831,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return(0);
}
case CCISS_DEREGDISK:
- return deregister_disk(disk);
+ return rebuild_lun_table(host, disk);
case CCISS_REGNEWD:
- return register_new_disk(host);
+ return rebuild_lun_table(host, NULL);
case CCISS_PASSTHRU:
{
@@ -1143,48 +1178,323 @@ static int revalidate_allvol(ctlr_info_t *host)
return 0;
}
-static int deregister_disk(struct gendisk *disk)
+/* This function will check the usage_count of the drive to be updated/added.
+ * If the usage_count is zero then the drive information will be updated and
+ * the disk will be re-registered with the kernel. If not then it will be
+ * left alone for the next reboot. The exception to this is disk 0 which
+ * will always be left registered with the kernel since it is also the
+ * controller node. Any changes to disk 0 will show up on the next
+ * reboot.
+*/
+static void cciss_update_drive_info(int ctlr, int drv_index)
+ {
+ ctlr_info_t *h = hba[ctlr];
+ struct gendisk *disk;
+ ReadCapdata_struct *size_buff = NULL;
+ InquiryData_struct *inq_buff = NULL;
+ unsigned int block_size;
+ unsigned int total_size;
+ unsigned long flags = 0;
+ int ret = 0;
+
+ /* if the disk already exists then deregister it before proceeding*/
+ if (h->drv[drv_index].raid_level != -1){
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ h->drv[drv_index].busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ ret = deregister_disk(h->gendisk[drv_index],
+ &h->drv[drv_index], 0);
+ h->drv[drv_index].busy_configuring = 0;
+ }
+
+ /* If the disk is in use return */
+ if (ret)
+ return;
+
+
+ /* Get information about the disk and modify the driver sturcture */
+ size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL)
+ goto mem_msg;
+ inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL)
+ goto mem_msg;
+
+ cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+ &total_size, &block_size);
+ cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
+ inq_buff, &h->drv[drv_index]);
+
+ ++h->num_luns;
+ disk = h->gendisk[drv_index];
+ set_capacity(disk, h->drv[drv_index].nr_blocks);
+
+
+ /* if it's the controller it's already added */
+ if (drv_index){
+ disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+
+ /* Set up queue information */
+ disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
+ blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
+
+ /* This is a hardware imposed limit. */
+ blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
+
+ /* This is a limit in the driver and could be eliminated. */
+ blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
+
+ blk_queue_max_sectors(disk->queue, 512);
+
+ disk->queue->queuedata = hba[ctlr];
+
+ blk_queue_hardsect_size(disk->queue,
+ hba[ctlr]->drv[drv_index].block_size);
+
+ h->drv[drv_index].queue = disk->queue;
+ add_disk(disk);
+ }
+
+freeret:
+ kfree(size_buff);
+ kfree(inq_buff);
+ return;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will find the first index of the controllers drive array
+ * that has a -1 for the raid_level and will return that index. This is
+ * where new drives will be added. If the index to be returned is greater
+ * than the highest_lun index for the controller then highest_lun is set
+ * to this new index. If there are no available indexes then -1 is returned.
+*/
+static int cciss_find_free_drive_index(int ctlr)
{
+ int i;
+
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if (hba[ctlr]->drv[i].raid_level == -1){
+ if (i > hba[ctlr]->highest_lun)
+ hba[ctlr]->highest_lun = i;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* This function will add and remove logical drives from the Logical
+ * drive array of the controller and maintain persistancy of ordering
+ * so that mount points are preserved until the next reboot. This allows
+ * for the removal of logical drives in the middle of the drive array
+ * without a re-ordering of those drives.
+ * INPUT
+ * h = The controller to perform the operations on
+ * del_disk = The disk to remove if specified. If the value given
+ * is NULL then no disk is removed.
+*/
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
+{
+ int ctlr = h->ctlr;
+ int num_luns;
+ ReportLunData_struct *ld_buff = NULL;
+ drive_info_struct *drv = NULL;
+ int return_code;
+ int listlength = 0;
+ int i;
+ int drv_found;
+ int drv_index = 0;
+ __u32 lunid = 0;
unsigned long flags;
+
+ /* Set busy_configuring flag for this operation */
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ if (h->num_luns >= CISS_MAX_LUN){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EINVAL;
+ }
+
+ if (h->busy_configuring){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EBUSY;
+ }
+ h->busy_configuring = 1;
+
+ /* if del_disk is NULL then we are being called to add a new disk
+ * and update the logical drive table. If it is not NULL then
+ * we will check if the disk is in use or not.
+ */
+ if (del_disk != NULL){
+ drv = get_drv(del_disk);
+ drv->busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return_code = deregister_disk(del_disk, drv, 1);
+ drv->busy_configuring = 0;
+ h->busy_configuring = 0;
+ return return_code;
+ } else {
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+ if (ld_buff == NULL)
+ goto mem_msg;
+
+ return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
+ sizeof(ReportLunData_struct), 0, 0, 0,
+ TYPE_CMD);
+
+ if (return_code == IO_OK){
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
+ listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+ } else{ /* reading number of logical volumes failed */
+ printk(KERN_WARNING "cciss: report logical volume"
+ " command failed\n");
+ listlength = 0;
+ goto freeret;
+ }
+
+ num_luns = listlength / 8; /* 8 bytes per entry */
+ if (num_luns > CISS_MAX_LUN){
+ num_luns = CISS_MAX_LUN;
+ printk(KERN_WARNING "cciss: more luns configured"
+ " on controller than can be handled by"
+ " this driver.\n");
+ }
+
+ /* Compare controller drive array to drivers drive array.
+ * Check for updates in the drive information and any new drives
+ * on the controller.
+ */
+ for (i=0; i < num_luns; i++){
+ int j;
+
+ drv_found = 0;
+
+ lunid = (0xff &
+ (unsigned int)(ld_buff->LUN[i][3])) << 24;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][2])) << 16;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ lunid |= 0xff &
+ (unsigned int)(ld_buff->LUN[i][0]);
+
+ /* Find if the LUN is already in the drive array
+ * of the controller. If so then update its info
+ * if not is use. If it does not exist then find
+ * the first free index and add it.
+ */
+ for (j=0; j <= h->highest_lun; j++){
+ if (h->drv[j].LunID == lunid){
+ drv_index = j;
+ drv_found = 1;
+ }
+ }
+
+ /* check if the drive was found already in the array */
+ if (!drv_found){
+ drv_index = cciss_find_free_drive_index(ctlr);
+ if (drv_index == -1)
+ goto freeret;
+
+ }
+ h->drv[drv_index].LunID = lunid;
+ cciss_update_drive_info(ctlr, drv_index);
+ } /* end for */
+ } /* end else */
+
+freeret:
+ kfree(ld_buff);
+ h->busy_configuring = 0;
+ /* We return -1 here to tell the ACU that we have registered/updated
+ * all of the drives that we can and to keep it from calling us
+ * additional times.
+ */
+ return -1;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will deregister the disk and it's queue from the
+ * kernel. It must be called with the controller lock held and the
+ * drv structures busy_configuring flag set. It's parameters are:
+ *
+ * disk = This is the disk to be deregistered
+ * drv = This is the drive_info_struct associated with the disk to be
+ * deregistered. It contains information about the disk used
+ * by the driver.
+ * clear_all = This flag determines whether or not the disk information
+ * is going to be completely cleared out and the highest_lun
+ * reset. Sometimes we want to clear out information about
+ * the disk in preperation for re-adding it. In this case
+ * the highest_lun should be left unchanged and the LunID
+ * should not be cleared.
+*/
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
+ int clear_all)
+{
ctlr_info_t *h = get_host(disk);
- drive_info_struct *drv = get_drv(disk);
- int ctlr = h->ctlr;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
/* make sure logical volume is NOT is use */
- if( drv->usage_count > 1) {
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if(clear_all || (h->gendisk[0] == disk)) {
+ if (drv->usage_count > 1)
return -EBUSY;
}
- drv->usage_count++;
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ else
+ if( drv->usage_count > 0 )
+ return -EBUSY;
- /* invalidate the devices and deregister the disk */
- if (disk->flags & GENHD_FL_UP)
+ /* invalidate the devices and deregister the disk. If it is disk
+ * zero do not deregister it but just zero out it's values. This
+ * allows us to delete disk zero but keep the controller registered.
+ */
+ if (h->gendisk[0] != disk){
+ if (disk->flags & GENHD_FL_UP){
+ blk_cleanup_queue(disk->queue);
del_gendisk(disk);
+ drv->queue = NULL;
+ }
+ }
+
+ --h->num_luns;
+ /* zero out the disk size info */
+ drv->nr_blocks = 0;
+ drv->block_size = 0;
+ drv->heads = 0;
+ drv->sectors = 0;
+ drv->cylinders = 0;
+ drv->raid_level = -1; /* This can be used as a flag variable to
+ * indicate that this element of the drive
+ * array is free.
+ */
+
+ if (clear_all){
/* check to see if it was the last disk */
if (drv == h->drv + h->highest_lun) {
/* if so, find the new hightest lun */
int i, newhighest =-1;
for(i=0; i<h->highest_lun; i++) {
/* if the disk has size > 0, it is available */
- if (h->drv[i].nr_blocks)
+ if (h->drv[i].heads)
newhighest = i;
}
h->highest_lun = newhighest;
-
}
- --h->num_luns;
- /* zero out the disk size info */
- drv->nr_blocks = 0;
- drv->block_size = 0;
- drv->cylinders = 0;
+
drv->LunID = 0;
+ }
return(0);
}
+
static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
size_t size,
unsigned int use_unit_num, /* 0: address the controller,
@@ -1420,8 +1730,10 @@ case CMD_HARDWARE_ERR:
}
}
/* unlock the buffers from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(h, c, 0);
return(return_status);
@@ -1495,164 +1807,6 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
return;
}
-static int register_new_disk(ctlr_info_t *h)
-{
- struct gendisk *disk;
- int ctlr = h->ctlr;
- int i;
- int num_luns;
- int logvol;
- int new_lun_found = 0;
- int new_lun_index = 0;
- int free_index_found = 0;
- int free_index = 0;
- ReportLunData_struct *ld_buff = NULL;
- ReadCapdata_struct *size_buff = NULL;
- InquiryData_struct *inq_buff = NULL;
- int return_code;
- int listlength = 0;
- __u32 lunid = 0;
- unsigned int block_size;
- unsigned int total_size;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- /* if we have no space in our disk array left to add anything */
- if( h->num_luns >= CISS_MAX_LUN)
- return -EINVAL;
-
- ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
- if (ld_buff == NULL)
- goto mem_msg;
- memset(ld_buff, 0, sizeof(ReportLunData_struct));
- size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- goto mem_msg;
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
- if (inq_buff == NULL)
- goto mem_msg;
-
- return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
- sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
-
- if( return_code == IO_OK)
- {
-
- // printk("LUN Data\n--------------------------\n");
-
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
- listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
- } else /* reading number of logical volumes failed */
- {
- printk(KERN_WARNING "cciss: report logical volume"
- " command failed\n");
- listlength = 0;
- goto free_err;
- }
- num_luns = listlength / 8; // 8 bytes pre entry
- if (num_luns > CISS_MAX_LUN)
- {
- num_luns = CISS_MAX_LUN;
- }
-#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
- ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
- ld_buff->LUNListLength[3], num_luns);
-#endif
- for(i=0; i< num_luns; i++)
- {
- int j;
- int lunID_found = 0;
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
- lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
-
- /* check to see if this is a new lun */
- for(j=0; j <= h->highest_lun; j++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking %d %x against %x\n", j,h->drv[j].LunID,
- lunid);
-#endif /* CCISS_DEBUG */
- if (h->drv[j].LunID == lunid)
- {
- lunID_found = 1;
- break;
- }
-
- }
- if( lunID_found == 1)
- continue;
- else
- { /* It is the new lun we have been looking for */
-#ifdef CCISS_DEBUG
- printk("new lun found at %d\n", i);
-#endif /* CCISS_DEBUG */
- new_lun_index = i;
- new_lun_found = 1;
- break;
- }
- }
- if (!new_lun_found)
- {
- printk(KERN_WARNING "cciss: New Logical Volume not found\n");
- goto free_err;
- }
- /* Now find the free index */
- for(i=0; i <CISS_MAX_LUN; i++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking Index %d\n", i);
-#endif /* CCISS_DEBUG */
- if(h->drv[i].LunID == 0)
- {
-#ifdef CCISS_DEBUG
- printk("free index found at %d\n", i);
-#endif /* CCISS_DEBUG */
- free_index_found = 1;
- free_index = i;
- break;
- }
- }
- if (!free_index_found)
- {
- printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
- goto free_err;
- }
-
- logvol = free_index;
- h->drv[logvol].LunID = lunid;
- /* there could be gaps in lun numbers, track hightest */
- if(h->highest_lun < lunid)
- h->highest_lun = logvol;
- cciss_read_capacity(ctlr, logvol, size_buff, 1,
- &total_size, &block_size);
- cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
- inq_buff, &h->drv[logvol]);
- h->drv[logvol].usage_count = 0;
- ++h->num_luns;
- /* setup partitions per disk */
- disk = h->gendisk[logvol];
- set_capacity(disk, h->drv[logvol].nr_blocks);
- /* if it's the controller it's already added */
- if(logvol)
- add_disk(disk);
-freeret:
- kfree(ld_buff);
- kfree(size_buff);
- kfree(inq_buff);
- return (logvol);
-mem_msg:
- printk(KERN_ERR "cciss: out of memory\n");
-free_err:
- logvol = -1;
- goto freeret;
-}
-
static int cciss_revalidate(struct gendisk *disk)
{
ctlr_info_t *h = get_host(disk);
@@ -1859,8 +2013,10 @@ resend_cmd1:
cleanup1:
/* unlock the data buffer from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(info_p, c, 1);
return (status);
}
@@ -2111,7 +2267,11 @@ queue:
/* fill in the request */
drv = creq->rq_disk->private_data;
c->Header.ReplyQueue = 0; // unused in simple mode
- c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag
+ /* got command from pool, so use the command block index instead */
+ /* for direct lookups. */
+ /* The first 2 bits are reserved for controller error reporting. */
+ c->Header.Tag.lower = (c->cmdindex << 3);
+ c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
c->Header.LUN.LogDev.VolId= drv->LunID;
c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
@@ -2186,7 +2346,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
ctlr_info_t *h = dev_id;
CommandList_struct *c;
unsigned long flags;
- __u32 a, a1;
+ __u32 a, a1, a2;
int j;
int start_queue = h->next_to_run;
@@ -2204,10 +2364,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
while((a = h->access.command_completed(h)) != FIFO_EMPTY)
{
a1 = a;
+ if ((a & 0x04)) {
+ a2 = (a >> 3);
+ if (a2 >= NR_CMDS) {
+ printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
+ fail_all_cmds(h->ctlr);
+ return IRQ_HANDLED;
+ }
+
+ c = h->cmd_pool + a2;
+ a = c->busaddr;
+
+ } else {
a &= ~3;
- if ((c = h->cmpQ) == NULL)
- {
- printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
+ if ((c = h->cmpQ) == NULL) {
+ printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
continue;
}
while(c->busaddr != a) {
@@ -2215,6 +2386,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
if (c == h->cmpQ)
break;
}
+ }
/*
* If we've found the command, take it off the
* completion Q and free it
@@ -2634,12 +2806,16 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
- for(i=0; i< hba[cntl_num]->num_luns; i++)
+// for(i=0; i< hba[cntl_num]->num_luns; i++)
+ for(i=0; i < CISS_MAX_LUN; i++)
{
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ if (i < hba[cntl_num]->num_luns){
+ lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
+ << 24;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
+ << 16;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
+ << 8;
lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
hba[cntl_num]->drv[i].LunID = lunid;
@@ -2647,13 +2823,18 @@ static void cciss_getgeometry(int cntl_num)
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i,
- ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2],
- ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
+ ld_buff->LUN[i][0], ld_buff->LUN[i][1],
+ ld_buff->LUN[i][2], ld_buff->LUN[i][3],
+ hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */
cciss_read_capacity(cntl_num, i, size_buff, 0,
&total_size, &block_size);
- cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
- inq_buff, &hba[cntl_num]->drv[i]);
+ cciss_geometry_inquiry(cntl_num, i, 0, total_size,
+ block_size, inq_buff, &hba[cntl_num]->drv[i]);
+ } else {
+ /* initialize raid_level to indicate a free space */
+ hba[cntl_num]->drv[i].raid_level = -1;
+ }
}
kfree(ld_buff);
kfree(size_buff);
@@ -2727,6 +2908,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
i = alloc_cciss_hba();
if(i < 0)
return (-1);
+
+ hba[i]->busy_initializing = 1;
+
if (cciss_pci_init(hba[i], pdev) != 0)
goto clean1;
@@ -2849,6 +3033,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
add_disk(disk);
}
+ hba[i]->busy_initializing = 0;
return(1);
clean4:
@@ -2869,6 +3054,7 @@ clean2:
clean1:
release_io_mem(hba[i]);
free_hba(i);
+ hba[i]->busy_initializing = 0;
return(-1);
}
@@ -2913,9 +3099,10 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
- if (disk->flags & GENHD_FL_UP)
- blk_cleanup_queue(disk->queue);
+ if (disk->flags & GENHD_FL_UP) {
del_gendisk(disk);
+ blk_cleanup_queue(disk->queue);
+ }
}
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
@@ -2964,5 +3151,43 @@ static void __exit cciss_cleanup(void)
remove_proc_entry("cciss", proc_root_driver);
}
+static void fail_all_cmds(unsigned long ctlr)
+{
+ /* If we get here, the board is apparently dead. */
+ ctlr_info_t *h = hba[ctlr];
+ CommandList_struct *c;
+ unsigned long flags;
+
+ printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
+ h->alive = 0; /* the controller apparently died... */
+
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+
+ pci_disable_device(h->pdev); /* Make sure it is really dead. */
+
+ /* move everything off the request queue onto the completed queue */
+ while( (c = h->reqQ) != NULL ) {
+ removeQ(&(h->reqQ), c);
+ h->Qdepth--;
+ addQ (&(h->cmpQ), c);
+ }
+
+ /* Now, fail everything on the completed queue with a HW error */
+ while( (c = h->cmpQ) != NULL ) {
+ removeQ(&h->cmpQ, c);
+ c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+ if (c->cmd_type == CMD_RWREQ) {
+ complete_command(h, c, 0);
+ } else if (c->cmd_type == CMD_IOCTL_PEND)
+ complete(c->waiting);
+#ifdef CONFIG_CISS_SCSI_TAPE
+ else if (c->cmd_type == CMD_SCSI)
+ complete_scsi_command(c, 0, 0);
+#endif
+ }
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ return;
+}
+
module_init(cciss_init);
module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 566587d..ef277ba 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -35,7 +35,13 @@ typedef struct _drive_info_struct
int heads;
int sectors;
int cylinders;
- int raid_level;
+ int raid_level; /* set to -1 to indicate that
+ * the drive is not in use/configured
+ */
+ int busy_configuring; /*This is set when the drive is being removed
+ *to prevent it from being opened or it's queue
+ *from being started.
+ */
} drive_info_struct;
struct ctlr_info
@@ -83,6 +89,7 @@ struct ctlr_info
int nr_allocs;
int nr_frees;
int busy_configuring;
+ int busy_initializing;
/* This element holds the zero based queue number of the last
* queue to be started. It is used for fairness.
@@ -94,6 +101,7 @@ struct ctlr_info
#ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
#endif
+ unsigned char alive;
};
/* Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index a88a888..53fea54 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
#define CMD_MSG_DONE 0x04
#define CMD_MSG_TIMEOUT 0x05
+/* This structure needs to be divisible by 8 for new
+ * indexing method.
+ */
+#define PADSIZE (sizeof(long) - 4)
typedef struct _CommandList_struct {
CommandListHeader_struct Header;
RequestBlock_struct Request;
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
ErrorInfo_struct * err_info; /* pointer to the allocated mem */
int ctlr;
int cmd_type;
+ long cmdindex;
struct _CommandList_struct *prev;
struct _CommandList_struct *next;
struct request * rq;
struct completion *waiting;
int retry_count;
-#ifdef CONFIG_CISS_SCSI_TAPE
void * scsi_cmd;
-#endif
+ char pad[PADSIZE];
} CommandList_struct;
//Configuration Table Structure
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3ca..e183a3e 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
CommandList_struct cmd;
ErrorInfo_struct Err;
__u32 busaddr;
+ __u32 pad;
};
#pragma pack()
@@ -877,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
static int
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
- InquiryData_struct *buf)
+ unsigned char *buf, unsigned char bufsize)
{
int rc;
CommandList_struct *cp;
@@ -900,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
cdb[1] = 0;
cdb[2] = 0;
cdb[3] = 0;
- cdb[4] = sizeof(*buf) & 0xff;
+ cdb[4] = bufsize;
cdb[5] = 0;
rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb,
- 6, (unsigned char *) buf,
- sizeof(*buf), XFER_READ);
+ 6, buf, bufsize, XFER_READ);
if (rc != 0) return rc; /* something went wrong */
@@ -1000,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
that though.
*/
-
+#define OBDR_TAPE_INQ_SIZE 49
+#define OBDR_TAPE_SIG "$DR-10"
ReportLunData_struct *ld_buff;
- InquiryData_struct *inq_buff;
+ unsigned char *inq_buff;
unsigned char scsi3addr[8];
ctlr_info_t *c;
__u32 num_luns=0;
@@ -1020,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
return;
}
memset(ld_buff, 0, reportlunsize);
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
@@ -1051,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
/* for each physical lun, do an inquiry */
if (ld_buff->LUN[i][3] & 0xC0) continue;
- memset(inq_buff, 0, sizeof(InquiryData_struct));
+ memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
- if (cciss_scsi_do_inquiry(hba[cntl_num],
- scsi3addr, inq_buff) != 0)
- {
+ if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
+ (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
/* Inquiry failed (msg printed already) */
devtype = 0; /* so we will skip this device. */
} else /* what kind of device is this? */
- devtype = (inq_buff->data_byte[0] & 0x1f);
+ devtype = (inq_buff[0] & 0x1f);
switch (devtype)
{
+ case 0x05: /* CD-ROM */ {
+
+ /* We don't *really* support actual CD-ROM devices,
+ * just this "One Button Disaster Recovery" tape drive
+ * which temporarily pretends to be a CD-ROM drive.
+ * So we check that the device is really an OBDR tape
+ * device by checking for "$DR-10" in bytes 43-48 of
+ * the inquiry data.
+ */
+ char obdr_sig[7];
+
+ strncpy(obdr_sig, &inq_buff[43], 6);
+ obdr_sig[6] = '\0';
+ if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+ /* Not OBDR device, ignore it. */
+ break;
+ }
+ /* fall through . . . */
case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */
if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
@@ -1126,6 +1144,7 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
int buflen, datalen;
ctlr_info_t *ci;
+ int i;
int cntl_num;
@@ -1136,8 +1155,28 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
cntl_num = ci->ctlr; /* Get our index into the hba[] array */
if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
- buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no);
-
+ buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
+ cntl_num, sh->host_no);
+
+ /* this information is needed by apps to know which cciss
+ device corresponds to which scsi host number without
+ having to open a scsi target device node. The device
+ information is not a duplicate of /proc/scsi/scsi because
+ the two may be out of sync due to scsi hotplug, rather
+ this info is for an app to be able to use to know how to
+ get them back in sync. */
+
+ for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
+ struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
+ buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ sh->host_no, sd->bus, sd->target, sd->lun,
+ sd->devtype,
+ sd->scsi3addr[0], sd->scsi3addr[1],
+ sd->scsi3addr[2], sd->scsi3addr[3],
+ sd->scsi3addr[4], sd->scsi3addr[5],
+ sd->scsi3addr[6], sd->scsi3addr[7]);
+ }
datalen = buflen - offset;
if (datalen < 0) { /* they're reading past EOF. */
datalen = 0;
@@ -1399,7 +1438,7 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
CPQ_TAPE_LOCK(ctlr, flags);
size = sprintf(buffer + *len,
- " Sequential access devices: %d\n\n",
+ "Sequential access devices: %d\n\n",
ccissscsi[ctlr].ndevices);
CPQ_TAPE_UNLOCK(ctlr, flags);
*pos += size; *len += size;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 711d2f3..94af920 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -750,6 +750,14 @@ static int pf_ready(void)
static struct request_queue *pf_queue;
+static void pf_end_request(int uptodate)
+{
+ if (pf_req) {
+ end_request(pf_req, uptodate);
+ pf_req = NULL;
+ }
+}
+
static void do_pf_request(request_queue_t * q)
{
if (pf_busy)
@@ -765,7 +773,7 @@ repeat:
pf_count = pf_req->current_nr_sectors;
if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
- end_request(pf_req, 0);
+ pf_end_request(0);
goto repeat;
}
@@ -780,7 +788,7 @@ repeat:
pi_do_claimed(pf_current->pi, do_pf_write);
else {
pf_busy = 0;
- end_request(pf_req, 0);
+ pf_end_request(0);
goto repeat;
}
}
@@ -798,9 +806,11 @@ static int pf_next_buf(void)
if (!pf_count)
return 1;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- end_request(pf_req, 1);
- pf_count = pf_req->current_nr_sectors;
- pf_buf = pf_req->buffer;
+ pf_end_request(1);
+ if (pf_req) {
+ pf_count = pf_req->current_nr_sectors;
+ pf_buf = pf_req->buffer;
+ }
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
return 1;
}
@@ -810,7 +820,7 @@ static inline void next_request(int success)
unsigned long saved_flags;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- end_request(pf_req, success);
+ pf_end_request(success);
pf_busy = 0;
do_pf_request(pf_queue);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7b83834..7e22a58 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -5,29 +5,41 @@
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
- * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
- * DVD-RW devices (aka an exercise in block layer masturbation)
+ * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and
+ * DVD-RAM devices.
*
+ * Theory of operation:
*
- * TODO: (circa order of when I will fix it)
- * - Only able to write on CD-RW media right now.
- * - check host application code on media and set it in write page
- * - interface for UDF <-> packet to negotiate a new location when a write
- * fails.
- * - handle OPC, especially for -RW media
+ * At the lowest level, there is the standard driver for the CD/DVD device,
+ * typically ide-cd.c or sr.c. This driver can handle read and write requests,
+ * but it doesn't know anything about the special restrictions that apply to
+ * packet writing. One restriction is that write requests must be aligned to
+ * packet boundaries on the physical media, and the size of a write request
+ * must be equal to the packet size. Another restriction is that a
+ * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read
+ * command, if the previous command was a write.
*
- * Theory of operation:
+ * The purpose of the packet writing driver is to hide these restrictions from
+ * higher layers, such as file systems, and present a block device that can be
+ * randomly read and written using 2kB-sized blocks.
+ *
+ * The lowest layer in the packet writing driver is the packet I/O scheduler.
+ * Its data is defined by the struct packet_iosched and includes two bio
+ * queues with pending read and write requests. These queues are processed
+ * by the pkt_iosched_process_queue() function. The write requests in this
+ * queue are already properly aligned and sized. This layer is responsible for
+ * issuing the flush cache commands and scheduling the I/O in a good order.
*
- * We use a custom make_request_fn function that forwards reads directly to
- * the underlying CD device. Write requests are either attached directly to
- * a live packet_data object, or simply stored sequentially in a list for
- * later processing by the kcdrwd kernel thread. This driver doesn't use
- * any elevator functionally as defined by the elevator_s struct, but the
- * underlying CD device uses a standard elevator.
+ * The next layer transforms unaligned write requests to aligned writes. This
+ * transformation requires reading missing pieces of data from the underlying
+ * block device, assembling the pieces to full packets and queuing them to the
+ * packet I/O scheduler.
*
- * This strategy makes it possible to do very late merging of IO requests.
- * A new bio sent to pkt_make_request can be merged with a live packet_data
- * object even if the object is in the data gathering state.
+ * At the top layer there is a custom make_request_fn function that forwards
+ * read requests directly to the iosched queue and puts write requests in the
+ * unaligned write queue. A kernel thread performs the necessary read
+ * gathering to convert the unaligned writes to aligned writes and then feeds
+ * them to the packet I/O scheduler.
*
*************************************************************************/
@@ -100,10 +112,9 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
goto no_bio;
bio_init(bio);
- bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), GFP_KERNEL);
+ bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
if (!bvl)
goto no_bvl;
- memset(bvl, 0, nr_iovecs * sizeof(struct bio_vec));
bio->bi_max_vecs = nr_iovecs;
bio->bi_io_vec = bvl;
@@ -125,10 +136,9 @@ static struct packet_data *pkt_alloc_packet_data(void)
int i;
struct packet_data *pkt;
- pkt = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+ pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL);
if (!pkt)
goto no_pkt;
- memset(pkt, 0, sizeof(struct packet_data));
pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
if (!pkt->w_bio)
@@ -659,7 +669,6 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in
}
offs += CD_FRAMESIZE;
if (offs >= PAGE_SIZE) {
- BUG_ON(offs > PAGE_SIZE);
offs = 0;
p++;
}
@@ -724,12 +733,6 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_set(&pkt->io_wait, 0);
atomic_set(&pkt->io_errors, 0);
- if (pkt->cache_valid) {
- VPRINTK("pkt_gather_data: zone %llx cached\n",
- (unsigned long long)pkt->sector);
- goto out_account;
- }
-
/*
* Figure out which frames we need to read before we can write.
*/
@@ -738,6 +741,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
int num_frames = bio->bi_size / CD_FRAMESIZE;
+ pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
BUG_ON(first_frame < 0);
BUG_ON(first_frame + num_frames > pkt->frames);
for (f = first_frame; f < first_frame + num_frames; f++)
@@ -745,6 +749,12 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
}
spin_unlock(&pkt->lock);
+ if (pkt->cache_valid) {
+ VPRINTK("pkt_gather_data: zone %llx cached\n",
+ (unsigned long long)pkt->sector);
+ goto out_account;
+ }
+
/*
* Schedule reads for missing parts of the packet.
*/
@@ -778,7 +788,6 @@ out_account:
frames_read, (unsigned long long)pkt->sector);
pd->stats.pkt_started++;
pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
- pd->stats.secs_w += pd->settings.size;
}
/*
@@ -794,10 +803,11 @@ static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zo
list_del_init(&pkt->list);
if (pkt->sector != zone)
pkt->cache_valid = 0;
- break;
+ return pkt;
}
}
- return pkt;
+ BUG();
+ return NULL;
}
static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt)
@@ -941,12 +951,10 @@ try_next_bio:
}
pkt = pkt_get_packet_data(pd, zone);
- BUG_ON(!pkt);
pd->current_sector = zone + pd->settings.size;
pkt->sector = zone;
pkt->frames = pd->settings.size >> 2;
- BUG_ON(pkt->frames > PACKET_MAX_SIZE);
pkt->write_size = 0;
/*
@@ -1636,6 +1644,10 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
printk("pktcdvd: detected zero packet size!\n");
pd->settings.size = 128;
}
+ if (pd->settings.size > PACKET_MAX_SECTORS) {
+ printk("pktcdvd: packet size is too big\n");
+ return -ENXIO;
+ }
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -2198,7 +2210,6 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
* No matching packet found. Store the bio in the work queue.
*/
node = mempool_alloc(pd->rb_pool, GFP_NOIO);
- BUG_ON(!node);
node->bio = bio;
spin_lock(&pd->lock);
BUG_ON(pd->bio_queue_size < 0);
@@ -2406,7 +2417,6 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
- BUG_ON(!pd);
switch (cmd) {
/*
@@ -2477,10 +2487,9 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
return -EBUSY;
}
- pd = kmalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
+ pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
if (!pd)
return ret;
- memset(pd, 0, sizeof(struct pktcdvd_device));
pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL);
if (!pd->rb_pool)
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 856c227..079ec34 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -168,6 +168,7 @@ static int verify_command(struct file *file, unsigned char *cmd)
safe_for_write(WRITE_VERIFY_12),
safe_for_write(WRITE_16),
safe_for_write(WRITE_LONG),
+ safe_for_write(WRITE_LONG_2),
safe_for_write(ERASE),
safe_for_write(GPCMD_MODE_SELECT_10),
safe_for_write(MODE_SELECT),
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 67d96b5..57c48bb 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -65,13 +65,15 @@
#endif
static int ignore = 0;
+static int ignore_csr = 0;
+static int ignore_sniffer = 0;
static int reset = 0;
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 2;
#endif
-#define VERSION "2.8"
+#define VERSION "2.9"
static struct usb_driver hci_usb_driver;
@@ -98,6 +100,9 @@ static struct usb_device_id bluetooth_ids[] = {
MODULE_DEVICE_TABLE (usb, bluetooth_ids);
static struct usb_device_id blacklist_ids[] = {
+ /* CSR BlueCore devices */
+ { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
+
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
@@ -836,6 +841,12 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (ignore || id->driver_info & HCI_IGNORE)
return -ENODEV;
+ if (ignore_csr && id->driver_info & HCI_CSR)
+ return -ENODEV;
+
+ if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
+ return -ENODEV;
+
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
return -ENODEV;
@@ -1061,6 +1072,12 @@ module_exit(hci_usb_exit);
module_param(ignore, bool, 0644);
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
+module_param(ignore_csr, bool, 0644);
+MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
+
+module_param(ignore_sniffer, bool, 0644);
+MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
+
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 29936b4..37100a6 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -31,9 +31,10 @@
#define HCI_IGNORE 0x01
#define HCI_RESET 0x02
#define HCI_DIGIANSWER 0x04
-#define HCI_SNIFFER 0x08
-#define HCI_BROKEN_ISOC 0x10
+#define HCI_CSR 0x08
+#define HCI_SNIFFER 0x10
#define HCI_BCM92035 0x20
+#define HCI_BROKEN_ISOC 0x40
#define HCI_MAX_IFACE_NUM 3
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 99762b6..de5d6d2 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -252,7 +252,7 @@ hp_zx1_configure (void)
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
- writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK);
+ writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
readl(hp->ioc_regs+HP_ZX1_IMASK);
writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
readl(hp->ioc_regs+HP_ZX1_IBASE);
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 2a36561..a124f8c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -2053,10 +2053,6 @@ static int __init rs_init(void)
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
- /*
- if(state->port && check_region(state->port,REGION_LENGTH(state)))
- continue;
- */
printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
state->line);
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 58d3738..407708a 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -534,7 +534,7 @@ static void shutdown(struct channel *ch)
unsigned long flags;
struct tty_struct *tty;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
if (!(ch->asyncflags & ASYNC_INITIALIZED))
return;
@@ -618,7 +618,7 @@ static int pc_write(struct tty_struct * tty,
struct channel *ch;
unsigned long flags;
int remain;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
/* ----------------------------------------------------------------
pc_write is primarily called directly by the kernel routine
@@ -685,7 +685,7 @@ static int pc_write(struct tty_struct * tty,
------------------------------------------------------------------- */
dataLen = min(bytesAvailable, dataLen);
- memcpy(ch->txptr + head, buf, dataLen);
+ memcpy_toio(ch->txptr + head, buf, dataLen);
buf += dataLen;
head += dataLen;
amountCopied += dataLen;
@@ -726,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
unsigned int head, tail;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
remain = 0;
@@ -773,7 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
int remain;
unsigned long flags;
struct channel *ch;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
@@ -830,7 +830,7 @@ static void pc_flush_buffer(struct tty_struct *tty)
unsigned int tail;
unsigned long flags;
struct channel *ch;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
@@ -976,7 +976,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
struct channel *ch;
unsigned long flags;
int line, retval, boardnum;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int head;
line = tty->index;
@@ -1041,7 +1041,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
ch->statusflags = 0;
/* Save boards current modem status */
- ch->imodem = bc->mstat;
+ ch->imodem = readb(&bc->mstat);
/* ----------------------------------------------------------------
Set receive head and tail ptrs to each other. This indicates
@@ -1399,10 +1399,10 @@ static void post_fep_init(unsigned int crd)
{ /* Begin post_fep_init */
int i;
- unsigned char *memaddr;
- struct global_data *gd;
+ void __iomem *memaddr;
+ struct global_data __iomem *gd;
struct board_info *bd;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
struct channel *ch;
int shrinkmem = 0, lowwater ;
@@ -1461,7 +1461,7 @@ static void post_fep_init(unsigned int crd)
8 and 64 of these structures.
-------------------------------------------------------------------- */
- bc = (struct board_chan *)(memaddr + CHANSTRUCT);
+ bc = memaddr + CHANSTRUCT;
/* -------------------------------------------------------------------
The below assignment will set gd to point at the BEGINING of
@@ -1470,7 +1470,7 @@ static void post_fep_init(unsigned int crd)
pointer begins at 0xd10.
---------------------------------------------------------------------- */
- gd = (struct global_data *)(memaddr + GLOBAL);
+ gd = memaddr + GLOBAL;
/* --------------------------------------------------------------------
XEPORTS (address 0xc22) points at the number of channels the
@@ -1493,6 +1493,7 @@ static void post_fep_init(unsigned int crd)
for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */
unsigned long flags;
+ u16 tseg, rseg;
ch->brdchan = bc;
ch->mailbox = gd;
@@ -1553,50 +1554,53 @@ static void post_fep_init(unsigned int crd)
shrinkmem = 0;
}
+ tseg = readw(&bc->tseg);
+ rseg = readw(&bc->rseg);
+
switch (bd->type) {
case PCIXEM:
case PCIXRJ:
case PCIXR:
/* Cover all the 2MEG cards */
- ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff);
- ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff);
- ch->txwin = FEPWIN | ((bc->tseg) >> 11);
- ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+ ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
break;
case PCXEM:
case EISAXEM:
/* Cover all the 32K windowed cards */
/* Mask equal to window size - 1 */
- ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff);
- ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff);
- ch->txwin = FEPWIN | ((bc->tseg) >> 11);
- ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+ ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
break;
case PCXEVE:
case PCXE:
- ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff);
- ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9);
- ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff);
- ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 );
+ ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+ ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
break;
case PCXI:
case PC64XE:
- ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4);
- ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4);
+ ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
+ ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
ch->txwin = ch->rxwin = 0;
break;
} /* End switch bd->type */
ch->txbufhead = 0;
- ch->txbufsize = bc->tmax + 1;
+ ch->txbufsize = readw(&bc->tmax) + 1;
ch->rxbufhead = 0;
- ch->rxbufsize = bc->rmax + 1;
+ ch->rxbufsize = readw(&bc->rmax) + 1;
lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
@@ -1718,11 +1722,11 @@ static void epcapoll(unsigned long ignored)
static void doevent(int crd)
{ /* Begin doevent */
- void *eventbuf;
+ void __iomem *eventbuf;
struct channel *ch, *chan0;
static struct tty_struct *tty;
struct board_info *bd;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int tail, head;
int event, channel;
int mstat, lstat;
@@ -1817,7 +1821,7 @@ static void doevent(int crd)
static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
int byte2, int ncmds, int bytecmd)
{ /* Begin fepcmd */
- unchar *memaddr;
+ unchar __iomem *memaddr;
unsigned int head, cmdTail, cmdStart, cmdMax;
long count;
int n;
@@ -2000,7 +2004,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
unsigned int cmdHead;
struct termios *ts;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned mval, hflow, cflag, iflag;
bc = ch->brdchan;
@@ -2010,7 +2014,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
ts = tty->termios;
if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */
cmdHead = readw(&bc->rin);
- bc->rout = cmdHead;
+ writew(cmdHead, &bc->rout);
cmdHead = readw(&bc->tin);
/* Changing baud in mid-stream transmission can be wonderful */
/* ---------------------------------------------------------------
@@ -2116,7 +2120,7 @@ static void receive_data(struct channel *ch)
unchar *rptr;
struct termios *ts = NULL;
struct tty_struct *tty;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
int dataToRead, wrapgap, bytesAvailable;
unsigned int tail, head;
unsigned int wrapmask;
@@ -2154,7 +2158,7 @@ static void receive_data(struct channel *ch)
--------------------------------------------------------------------- */
if (!tty || !ts || !(ts->c_cflag & CREAD)) {
- bc->rout = head;
+ writew(head, &bc->rout);
return;
}
@@ -2270,7 +2274,7 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
static int pc_tiocmget(struct tty_struct *tty, struct file *file)
{
struct channel *ch = (struct channel *) tty->driver_data;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int mstat, mflag = 0;
unsigned long flags;
@@ -2351,7 +2355,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
struct channel *ch = (struct channel *) tty->driver_data;
void __user *argp = (void __user *)arg;
@@ -2633,7 +2637,7 @@ static void pc_start(struct tty_struct *tty)
spin_lock_irqsave(&epca_lock, flags);
/* Just in case output was resumed because of a change in Digi-flow */
if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
globalwinon(ch);
bc = ch->brdchan;
if (ch->statusflags & LOWWAIT)
@@ -2727,7 +2731,7 @@ void digi_send_break(struct channel *ch, int msec)
static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
{ /* Begin setup_empty_event */
- struct board_chan *bc = ch->brdchan;
+ struct board_chan __iomem *bc = ch->brdchan;
globalwinon(ch);
ch->statusflags |= EMPTYWAIT;
diff --git a/drivers/char/epca.h b/drivers/char/epca.h
index 20eeb5a..456d6c8 100644
--- a/drivers/char/epca.h
+++ b/drivers/char/epca.h
@@ -128,17 +128,17 @@ struct channel
unsigned long c_cflag;
unsigned long c_lflag;
unsigned long c_oflag;
- unsigned char *txptr;
- unsigned char *rxptr;
+ unsigned char __iomem *txptr;
+ unsigned char __iomem *rxptr;
unsigned char *tmp_buf;
struct board_info *board;
- struct board_chan *brdchan;
+ struct board_chan __iomem *brdchan;
struct digi_struct digiext;
struct tty_struct *tty;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
struct work_struct tqueue;
- struct global_data *mailbox;
+ struct global_data __iomem *mailbox;
};
struct board_info
@@ -149,8 +149,8 @@ struct board_info
unsigned short numports;
unsigned long port;
unsigned long membase;
- unsigned char __iomem *re_map_port;
- unsigned char *re_map_membase;
+ void __iomem *re_map_port;
+ void __iomem *re_map_membase;
unsigned long memory_seg;
void ( * memwinon ) (struct board_info *, unsigned int) ;
void ( * memwinoff ) (struct board_info *, unsigned int) ;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index cddb789..f921776 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -839,9 +839,6 @@ int __init hvc_init(void)
hvc_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvc_driver, &hvc_ops);
- if (tty_register_driver(hvc_driver))
- panic("Couldn't register hvc console driver\n");
-
/* Always start the kthread because there can be hotplug vty adapters
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
@@ -851,6 +848,9 @@ int __init hvc_init(void)
return -EIO;
}
+ if (tty_register_driver(hvc_driver))
+ panic("Couldn't register hvc console driver\n");
+
return 0;
}
module_init(hvc_init);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1e33cb0..e91268e 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -810,13 +810,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
* from the top and bottom of cursor position
*/
old_origin += (vc->vc_y - new_rows/2) * old_row_size;
- end = old_origin + new_screen_size;
+ end = old_origin + (old_row_size * new_rows);
}
} else
/*
* Cursor near the top, copy contents from the top of buffer
*/
- end = (old_rows > new_rows) ? old_origin + new_screen_size :
+ end = (old_rows > new_rows) ? old_origin +
+ (old_row_size * new_rows) :
vc->vc_scr_end;
update_attr(vc);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index fa789ea..344001b 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -84,6 +84,17 @@ config 977_WATCHDOG
Not sure? It's safe to say N.
+config IXP2000_WATCHDOG
+ tristate "IXP2000 Watchdog"
+ depends on WATCHDOG && ARCH_IXP2000
+ help
+ Say Y here if to include support for the watchdog timer
+ in the Intel IXP2000(2400, 2800, 2850) network processors.
+ This driver can be built as a module by choosing M. The module
+ will be called ixp2000_wdt.
+
+ Say N if you are unsure.
+
config IXP4XX_WATCHDOG
tristate "IXP4xx Watchdog"
depends on WATCHDOG && ARCH_IXP4XX
@@ -100,17 +111,6 @@ config IXP4XX_WATCHDOG
Say N if you are unsure.
-config IXP2000_WATCHDOG
- tristate "IXP2000 Watchdog"
- depends on WATCHDOG && ARCH_IXP2000
- help
- Say Y here if to include support for the watchdog timer
- in the Intel IXP2000(2400, 2800, 2850) network processors.
- This driver can be built as a module by choosing M. The module
- will be called ixp2000_wdt.
-
- Say N if you are unsure.
-
config S3C2410_WATCHDOG
tristate "S3C2410 Watchdog"
depends on WATCHDOG && ARCH_S3C2410
@@ -233,6 +233,16 @@ config IB700_WDT
Most people will say N.
+config IBMASR
+ tristate "IBM Automatic Server Restart"
+ depends on WATCHDOG && X86
+ help
+ This is the driver for the IBM Automatic Server Restart watchdog
+ timer builtin into some eServer xSeries machines.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmasr.
+
config WAFER_WDT
tristate "ICP Wafer 5823 Single Board Computer Watchdog"
depends on WATCHDOG && X86
@@ -243,6 +253,16 @@ config WAFER_WDT
To compile this driver as a module, choose M here: the
module will be called wafer5823wdt.
+config I6300ESB_WDT
+ tristate "Intel 6300ESB Timer/Watchdog"
+ depends on WATCHDOG && X86 && PCI
+ ---help---
+ Hardware driver for the watchdog timer built into the Intel
+ 6300ESB controller hub.
+
+ To compile this driver as a module, choose M here: the
+ module will be called i6300esb.
+
config I8XX_TCO
tristate "Intel i8xx TCO Timer/Watchdog"
depends on WATCHDOG && (X86 || IA64) && PCI
@@ -298,6 +318,19 @@ config 60XX_WDT
You can compile this driver directly into the kernel, or use
it as a module. The module will be called sbc60xxwdt.
+config SBC8360_WDT
+ tristate "SBC8360 Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+
+ This is the driver for the hardware watchdog on the SBC8360 Single
+ Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc8360.ko.
+
+ Most people will say N.
+
config CPU5_WDT
tristate "SMA CPU5 Watchdog"
depends on WATCHDOG && X86
@@ -336,6 +369,19 @@ config W83877F_WDT
Most people will say N.
+config W83977F_WDT
+ tristate "W83977F (PCM-5335) Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the hardware watchdog on the W83977F I/O chip
+ as used in AAEON's PCM-5335 SBC (and likely others). This
+ watchdog simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time.
+
+ To compile this driver as a module, choose M here: the
+ module will be called w83977f_wdt.
+
config MACHZ_WDT
tristate "ZF MachZ Watchdog"
depends on WATCHDOG && X86
@@ -355,6 +401,10 @@ config 8xx_WDT
tristate "MPC8xx Watchdog Timer"
depends on WATCHDOG && 8xx
+config MV64X60_WDT
+ tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
+ depends on WATCHDOG && MV64X60
+
config BOOKE_WDT
tristate "PowerPC Book-E Watchdog Timer"
depends on WATCHDOG && (BOOKE || 4xx)
@@ -362,6 +412,17 @@ config BOOKE_WDT
Please see Documentation/watchdog/watchdog-api.txt for
more information.
+# PPC64 Architecture
+
+config WATCHDOG_RTAS
+ tristate "RTAS watchdog"
+ depends on WATCHDOG && PPC_RTAS
+ help
+ This driver adds watchdog support for the RTAS watchdog.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wdrtas.
+
# MIPS Architecture
config INDYDOG
@@ -430,16 +491,6 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
-# ppc64 RTAS watchdog
-config WATCHDOG_RTAS
- tristate "RTAS watchdog"
- depends on WATCHDOG && PPC_RTAS
- help
- This driver adds watchdog support for the RTAS watchdog.
-
- To compile this driver as a module, choose M here. The module
- will be called wdrtas.
-
#
# ISA-based Watchdog Cards
#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index bc6f5fe..cfd0a39 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -39,22 +39,27 @@ obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
+obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
# PPC64 Architecture
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
# MIPS Architecture
obj-$(CONFIG_INDYDOG) += indydog.o
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
new file mode 100644
index 0000000..93785f1
--- /dev/null
+++ b/drivers/char/watchdog/i6300esb.c
@@ -0,0 +1,527 @@
+/*
+ * i6300esb: Watchdog timer driver for Intel 6300ESB chipset
+ *
+ * (c) Copyright 2004 Google Inc.
+ * (c) Copyright 2005 David Härdeman <david@2gen.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * based on i810-tco.c which is in turn based on softdog.c
+ *
+ * The timer is implemented in the following I/O controller hubs:
+ * (See the intel documentation on http://developer.intel.com.)
+ * 6300ESB chip : document number 300641-003
+ *
+ * 2004YYZZ Ross Biro
+ * Initial version 0.01
+ * 2004YYZZ Ross Biro
+ * Version 0.02
+ * 20050210 David Härdeman <david@2gen.com>
+ * Ported driver to kernel 2.6
+ */
+
+/*
+ * Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Module and version information */
+#define ESB_VERSION "0.03"
+#define ESB_MODULE_NAME "i6300ESB timer"
+#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
+#define PFX ESB_MODULE_NAME ": "
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG 0x60 /* Config register */
+#define ESB_LOCK_REG 0x68 /* WDT lock register */
+
+/* Memory mapped registers */
+#define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */
+#define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */
+#define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */
+#define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */
+#define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */
+#define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */
+#define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */
+
+/* Magic constants */
+#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
+#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */
+
+/* internal variables */
+static void __iomem *BASEADDR;
+static spinlock_t esb_lock; /* Guards the hardware */
+static unsigned long timer_alive;
+static struct pci_dev *esb_pci;
+static unsigned short triggered; /* The status of the watchdog upon boot */
+static char esb_expect_close;
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */
+static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Some i6300ESB specific functions
+ */
+
+/*
+ * Prepare for reloading the timer by unlocking the proper registers.
+ * This is performed by first writing 0x80 followed by 0x86 to the
+ * reload register. After this the appropriate registers can be written
+ * to once before they need to be unlocked again.
+ */
+static inline void esb_unlock_registers(void) {
+ writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
+ writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+}
+
+static void esb_timer_start(void)
+{
+ u8 val;
+
+ /* Enable or Enable + Lock? */
+ val = 0x02 | (nowayout ? 0x01 : 0x00);
+
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
+}
+
+static int esb_timer_stop(void)
+{
+ u8 val;
+
+ spin_lock(&esb_lock);
+ /* First, reset timers as suggested by the docs */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* Then disable the WDT */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
+ spin_unlock(&esb_lock);
+
+ /* Returns 0 if the timer was disabled, non-zero otherwise */
+ return (val & 0x01);
+}
+
+static void esb_timer_keepalive(void)
+{
+ spin_lock(&esb_lock);
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* FIXME: Do we need to flush anything here? */
+ spin_unlock(&esb_lock);
+}
+
+static int esb_timer_set_heartbeat(int time)
+{
+ u32 val;
+
+ if (time < 0x1 || time > (2 * 0x03ff))
+ return -EINVAL;
+
+ spin_lock(&esb_lock);
+
+ /* We shift by 9, so if we are passed a value of 1 sec,
+ * val will be 1 << 9 = 512, then write that to two
+ * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
+ */
+ val = time << 9;
+
+ /* Write timer 1 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER1_REG);
+
+ /* Write timer 2 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER2_REG);
+
+ /* Reload */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+
+ /* FIXME: Do we need to flush everything out? */
+
+ /* Done */
+ heartbeat = time;
+ spin_unlock(&esb_lock);
+ return 0;
+}
+
+static int esb_timer_read (void)
+{
+ u32 count;
+
+ /* This isn't documented, and doesn't take into
+ * acount which stage is running, but it looks
+ * like a 20 bit count down, so we might as well report it.
+ */
+ pci_read_config_dword(esb_pci, 0x64, &count);
+ return (int)count;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int esb_open (struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(0, &timer_alive))
+ return -EBUSY;
+
+ /* Reload and activate timer */
+ esb_timer_keepalive ();
+ esb_timer_start ();
+
+ return nonseekable_open(inode, file);
+}
+
+static int esb_release (struct inode *inode, struct file *file)
+{
+ /* Shut off the timer. */
+ if (esb_expect_close == 42) {
+ esb_timer_stop ();
+ } else {
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ esb_timer_keepalive ();
+ }
+ clear_bit(0, &timer_alive);
+ esb_expect_close = 0;
+ return 0;
+}
+
+static ssize_t esb_write (struct file *file, const char __user *data,
+ size_t len, loff_t * ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* note: just in case someone wrote the magic character
+ * five months ago... */
+ esb_expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for (i = 0; i != len; i++) {
+ char c;
+ if(get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ esb_expect_close = 42;
+ }
+ }
+
+ /* someone wrote to us, we should reload the timer */
+ esb_timer_keepalive ();
+ }
+ return len;
+}
+
+static int esb_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int new_options, retval = -EINVAL;
+ int new_heartbeat;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = ESB_MODULE_NAME,
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof (ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ return put_user (esb_timer_read(), p);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user (triggered, p);
+
+ case WDIOC_KEEPALIVE:
+ esb_timer_keepalive ();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ {
+ if (get_user (new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ esb_timer_stop ();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ esb_timer_keepalive ();
+ esb_timer_start ();
+ retval = 0;
+ }
+
+ return retval;
+ }
+
+ case WDIOC_SETTIMEOUT:
+ {
+ if (get_user(new_heartbeat, p))
+ return -EFAULT;
+
+ if (esb_timer_set_heartbeat(new_heartbeat))
+ return -EINVAL;
+
+ esb_timer_keepalive ();
+ /* Fall */
+ }
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Notify system
+ */
+
+static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT) {
+ /* Turn the WDT off */
+ esb_timer_stop ();
+ }
+
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations esb_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = esb_write,
+ .ioctl = esb_ioctl,
+ .open = esb_open,
+ .release = esb_release,
+};
+
+static struct miscdevice esb_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &esb_fops,
+};
+
+static struct notifier_block esb_notifier = {
+ .notifier_call = esb_notify_sys,
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE. We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id esb_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
+ { 0, }, /* End of list */
+};
+MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
+
+/*
+ * Init & exit routines
+ */
+
+static unsigned char __init esb_getdevice (void)
+{
+ u8 val1;
+ unsigned short val2;
+
+ struct pci_dev *dev = NULL;
+ /*
+ * Find the PCI device
+ */
+
+ for_each_pci_dev(dev) {
+ if (pci_match_id(esb_pci_tbl, dev)) {
+ esb_pci = dev;
+ break;
+ }
+ }
+
+ if (esb_pci) {
+ if (pci_enable_device(esb_pci)) {
+ printk (KERN_ERR PFX "failed to enable device\n");
+ goto err_devput;
+ }
+
+ if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+ printk (KERN_ERR PFX "failed to request region\n");
+ goto err_disable;
+ }
+
+ BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
+ pci_resource_len(esb_pci, 0));
+ if (BASEADDR == NULL) {
+ /* Something's wrong here, BASEADDR has to be set */
+ printk (KERN_ERR PFX "failed to get BASEADDR\n");
+ goto err_release;
+ }
+
+ /*
+ * The watchdog has two timers, it can be setup so that the
+ * expiry of timer1 results in an interrupt and the expiry of
+ * timer2 results in a reboot. We set it to not generate
+ * any interrupts as there is not much we can do with it
+ * right now.
+ *
+ * We also enable reboots and set the timer frequency to
+ * the PCI clock divided by 2^15 (approx 1KHz).
+ */
+ pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
+
+ /* Check that the WDT isn't already locked */
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
+ if (val1 & ESB_WDT_LOCK)
+ printk (KERN_WARNING PFX "nowayout already set\n");
+
+ /* Set the timer to watchdog mode and disable it for now */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
+
+ /* Check if the watchdog was previously triggered */
+ esb_unlock_registers();
+ val2 = readw(ESB_RELOAD_REG);
+ triggered = (val2 & (0x01 << 9) >> 9);
+
+ /* Reset trigger flag and timers */
+ esb_unlock_registers();
+ writew((0x11 << 8), ESB_RELOAD_REG);
+
+ /* Done */
+ return 1;
+
+err_release:
+ pci_release_region(esb_pci, 0);
+err_disable:
+ pci_disable_device(esb_pci);
+err_devput:
+ pci_dev_put(esb_pci);
+ }
+ return 0;
+}
+
+static int __init watchdog_init (void)
+{
+ int ret;
+
+ spin_lock_init(&esb_lock);
+
+ /* Check whether or not the hardware watchdog is there */
+ if (!esb_getdevice () || esb_pci == NULL)
+ return -ENODEV;
+
+ /* Check that the heartbeat value is within it's range ; if not reset to the default */
+ if (esb_timer_set_heartbeat (heartbeat)) {
+ esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
+ printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
+ heartbeat);
+ }
+
+ ret = register_reboot_notifier(&esb_notifier);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ ret);
+ goto err_unmap;
+ }
+
+ ret = misc_register(&esb_miscdev);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_notifier;
+ }
+
+ esb_timer_stop ();
+
+ printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+ BASEADDR, heartbeat, nowayout);
+
+ return 0;
+
+err_notifier:
+ unregister_reboot_notifier(&esb_notifier);
+err_unmap:
+ iounmap(BASEADDR);
+/* err_release: */
+ pci_release_region(esb_pci, 0);
+/* err_disable: */
+ pci_disable_device(esb_pci);
+/* err_devput: */
+ pci_dev_put(esb_pci);
+ return ret;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ esb_timer_stop ();
+
+ /* Deregister */
+ misc_deregister(&esb_miscdev);
+ unregister_reboot_notifier(&esb_notifier);
+ iounmap(BASEADDR);
+ pci_release_region(esb_pci, 0);
+ pci_disable_device(esb_pci);
+ pci_dev_put(esb_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
new file mode 100644
index 0000000..294c474
--- /dev/null
+++ b/drivers/char/watchdog/ibmasr.c
@@ -0,0 +1,405 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+ ASMTYPE_UNKNOWN,
+ ASMTYPE_TOPAZ,
+ ASMTYPE_JASPER,
+ ASMTYPE_PEARL,
+ ASMTYPE_JUNIPER,
+ ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET 4
+#define TOPAZ_ASR_TOGGLE 0x40
+#define TOPAZ_ASR_DISABLE 0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE 0xe04
+#define PEARL_WRITE 0xe06
+#define PEARL_READ 0xe07
+
+#define PEARL_ASR_DISABLE_MASK 0x80 /* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK 0x40 /* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET 0x38
+
+#define JASPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS 0x54b /* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS 0x118e /* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK 0x01 /* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+ unsigned char reg;
+
+ if (asr_type == ASMTYPE_TOPAZ) {
+ /* asr_write_addr == asr_read_addr */
+ reg = inb(asr_read_addr);
+ outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+ asr_read_addr);
+ } else {
+ /*
+ * First make sure the hardware timer is reset by toggling
+ * ASR hardware timer line.
+ */
+ asr_toggle();
+
+ reg = inb(asr_read_addr);
+ outb(reg & ~asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ if (asr_type == ASMTYPE_TOPAZ)
+ /* asr_write_addr == asr_read_addr */
+ outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+ asr_read_addr);
+ else {
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+ unsigned char low, high;
+ const char *type = "";
+
+ asr_length = 1;
+
+ switch (asr_type) {
+ case ASMTYPE_TOPAZ:
+ /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+ outb(0x07, 0x2e);
+ outb(0x07, 0x2f);
+
+ /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x60, 0x2e);
+ high = inb(0x2f);
+
+ /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x61, 0x2e);
+ low = inb(0x2f);
+
+ asr_base = (high << 16) | low;
+ asr_read_addr = asr_write_addr =
+ asr_base + TOPAZ_ASR_REG_OFFSET;
+ asr_length = 5;
+
+ break;
+
+ case ASMTYPE_JASPER:
+ type = "Jaspers ";
+
+ /* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/* spin_lock_irqsave(&pci_config_lock, flags);*/
+
+ /* Select the SuperIO chip in the PCI I/O port register */
+ outl(0x8000f858, 0xcf8);
+
+ /*
+ * Read the base address for the SuperIO chip.
+ * Only the lower 16 bits are valid, but the address is word
+ * aligned so the last bit must be masked off.
+ */
+ asr_base = inl(0xcfc) & 0xfffe;
+
+/* spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+ asr_read_addr = asr_write_addr =
+ asr_base + JASPER_ASR_REG_OFFSET;
+ asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+ asr_length = JASPER_ASR_REG_OFFSET + 1;
+
+ break;
+
+ case ASMTYPE_PEARL:
+ type = "Pearls ";
+ asr_base = PEARL_BASE;
+ asr_read_addr = PEARL_READ;
+ asr_write_addr = PEARL_WRITE;
+ asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+ asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+ asr_length = 4;
+ break;
+
+ case ASMTYPE_JUNIPER:
+ type = "Junipers ";
+ asr_base = JUNIPER_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+ break;
+
+ case ASMTYPE_SPRUCE:
+ type = "Spruce's ";
+ asr_base = SPRUCE_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+ asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+ break;
+ }
+
+ if (!request_region(asr_base, asr_length, "ibmasr")) {
+ printk(KERN_ERR PFX "address %#x already in use\n",
+ asr_base);
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+ return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ asr_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ asr_expect_close = 42;
+ }
+ }
+ asr_toggle();
+ }
+ return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static const struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "IBM ASR"
+ };
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int heartbeat;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ?
+ -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ asr_toggle();
+ return 0;
+
+ /*
+ * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+ * and WDIOC_GETTIMEOUT always returns 256.
+ */
+ case WDIOC_GETTIMEOUT:
+ heartbeat = 256;
+ return put_user(heartbeat, p);
+
+ case WDIOC_SETOPTIONS: {
+ int new_options, retval = -EINVAL;
+
+ if (get_user(new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ asr_disable();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ asr_enable();
+ asr_toggle();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+ if(test_and_set_bit(0, &asr_is_open))
+ return -EBUSY;
+
+ asr_toggle();
+ asr_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+ if (asr_expect_close == 42)
+ asr_disable();
+ else {
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ asr_toggle();
+ }
+ clear_bit(0, &asr_is_open);
+ asr_expect_close = 0;
+ return 0;
+}
+
+static struct file_operations asr_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = asr_write,
+ .ioctl = asr_ioctl,
+ .open = asr_open,
+ .release = asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &asr_fops,
+};
+
+
+struct ibmasr_id {
+ const char *desc;
+ int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+ { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+ { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+ { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+ { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+ { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+ { NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+ struct ibmasr_id *id;
+ int rc;
+
+ for (id = ibmasr_id_table; id->desc; id++) {
+ if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+ asr_type = id->type;
+ break;
+ }
+ }
+
+ if (!asr_type)
+ return -ENODEV;
+
+ rc = misc_register(&asr_miscdev);
+ if (rc < 0) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ return rc;
+ }
+
+ rc = asr_get_base_address();
+ if (rc) {
+ misc_deregister(&asr_miscdev);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+ if (!nowayout)
+ asr_disable();
+
+ misc_deregister(&asr_miscdev);
+
+ release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
index c694eee..75ca84e 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -30,6 +30,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+
+#include <asm/hardware/arm_twd.h>
#include <asm/uaccess.h>
struct mpcore_wdt {
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
new file mode 100644
index 0000000..1436aea
--- /dev/null
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -0,0 +1,252 @@
+/*
+ * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Platform-specific setup code should configure the dog to generate
+ * interrupt or reset as required. This code only enables/disables
+ * and services the watchdog.
+ *
+ * Derived from mpc8xx_wdt.c, with the following copyright.
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/mv64x60.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* MV64x60 WDC (config) register access definitions */
+#define MV64x60_WDC_CTL1_MASK (3 << 24)
+#define MV64x60_WDC_CTL1(val) ((val & 3) << 24)
+#define MV64x60_WDC_CTL2_MASK (3 << 26)
+#define MV64x60_WDC_CTL2(val) ((val & 3) << 26)
+
+/* Flags bits */
+#define MV64x60_WDOG_FLAG_OPENED 0
+#define MV64x60_WDOG_FLAG_ENABLED 1
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *mv64x60_regs;
+static int mv64x60_wdt_timeout;
+
+static void mv64x60_wdt_reg_write(u32 val)
+{
+ /* Allow write only to CTL1 / CTL2 fields, retaining values in
+ * other fields.
+ */
+ u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
+ data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
+ data |= val;
+ writel(data, mv64x60_regs + MV64x60_WDT_WDC);
+}
+
+static void mv64x60_wdt_service(void)
+{
+ /* Write 01 followed by 10 to CTL2 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
+}
+
+static void mv64x60_wdt_handler_disable(void)
+{
+ if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+ }
+}
+
+static void mv64x60_wdt_handler_enable(void)
+{
+ if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+ }
+}
+
+static int mv64x60_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
+ return -EBUSY;
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_enable();
+
+ return 0;
+}
+
+static int mv64x60_wdt_release(struct inode *inode, struct file *file)
+{
+ mv64x60_wdt_service();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+ mv64x60_wdt_handler_disable();
+#endif
+
+ clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
+
+ return 0;
+}
+
+static ssize_t mv64x60_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t * ppos)
+{
+ if (*ppos != file->f_pos)
+ return -ESPIPE;
+
+ if (len)
+ mv64x60_wdt_service();
+
+ return len;
+}
+
+static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int timeout;
+ static struct watchdog_info info = {
+ .options = WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "MV64x60 watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(wdt_status, (int *)arg))
+ return -EFAULT;
+ wdt_status &= ~WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_GETTEMP:
+ return -EOPNOTSUPP;
+
+ case WDIOC_SETOPTIONS:
+ return -EOPNOTSUPP;
+
+ case WDIOC_KEEPALIVE:
+ mv64x60_wdt_service();
+ wdt_status |= WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ return -EOPNOTSUPP;
+
+ case WDIOC_GETTIMEOUT:
+ timeout = mv64x60_wdt_timeout * HZ;
+ if (put_user(timeout, (int *)arg))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static struct file_operations mv64x60_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mv64x60_wdt_write,
+ .ioctl = mv64x60_wdt_ioctl,
+ .open = mv64x60_wdt_open,
+ .release = mv64x60_wdt_release,
+};
+
+static struct miscdevice mv64x60_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mv64x60_wdt_fops,
+};
+
+static int __devinit mv64x60_wdt_probe(struct device *dev)
+{
+ struct platform_device *pd = to_platform_device(dev);
+ struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data;
+ int bus_clk = 133;
+
+ mv64x60_wdt_timeout = 10;
+ if (pdata) {
+ mv64x60_wdt_timeout = pdata->timeout;
+ bus_clk = pdata->bus_clk;
+ }
+
+ mv64x60_regs = mv64x60_get_bridge_vbase();
+
+ writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
+ mv64x60_regs + MV64x60_WDT_WDC);
+
+ return misc_register(&mv64x60_wdt_miscdev);
+}
+
+static int __devexit mv64x60_wdt_remove(struct device *dev)
+{
+ misc_deregister(&mv64x60_wdt_miscdev);
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_disable();
+
+ return 0;
+}
+
+static struct device_driver mv64x60_wdt_driver = {
+ .name = MV64x60_WDT_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv64x60_wdt_probe,
+ .remove = __devexit_p(mv64x60_wdt_remove),
+};
+
+static struct platform_device *mv64x60_wdt_dev;
+
+static int __init mv64x60_wdt_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "MV64x60 watchdog driver\n");
+
+ mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,
+ -1, NULL, 0);
+ if (IS_ERR(mv64x60_wdt_dev)) {
+ ret = PTR_ERR(mv64x60_wdt_dev);
+ goto out;
+ }
+
+ ret = driver_register(&mv64x60_wdt_driver);
+ out:
+ return ret;
+}
+
+static void __exit mv64x60_wdt_exit(void)
+{
+ driver_unregister(&mv64x60_wdt_driver);
+ platform_device_unregister(mv64x60_wdt_dev);
+}
+
+module_init(mv64x60_wdt_init);
+module_exit(mv64x60_wdt_exit);
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("MV64x60 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 2b13afb..5a80adb 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -29,27 +29,29 @@
* Includes, defines, variables, module parameters, ...
*/
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/delay.h> /* For mdelay function */
+#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h> /* For the watchdog specific items */
+#include <linux/notifier.h> /* For notifier support */
+#include <linux/reboot.h> /* For reboot_notifier stuff */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/fs.h> /* For file operations */
+#include <linux/pci.h> /* For pci functions */
+#include <linux/ioport.h> /* For io-port access */
+#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
+
+#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
+#include <asm/io.h> /* For inb/outb/... */
/* Module and version information */
#define WATCHDOG_VERSION "1.01"
-#define WATCHDOG_DATE "15 Mar 2005"
+#define WATCHDOG_DATE "02 Sep 2005"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
@@ -335,12 +337,14 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
- pcipcwd_stop();
+ if (pcipcwd_stop())
+ return -EIO;
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
- pcipcwd_start();
+ if (pcipcwd_start())
+ return -EIO;
retval = 0;
}
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 8b292bf..3625b26 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -464,7 +464,7 @@ static void s3c2410wdt_shutdown(struct device *dev)
static unsigned long wtcon_save;
static unsigned long wtdat_save;
-static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level)
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
{
if (level == SUSPEND_POWER_DOWN) {
/* Save watchdog state, and turn it off. */
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
new file mode 100644
index 0000000..c6cbf80
--- /dev/null
+++ b/drivers/char/watchdog/sbc8360.c
@@ -0,0 +1,414 @@
+/*
+ * SBC8360 Watchdog driver
+ *
+ * (c) Copyright 2005 Webcon, Inc.
+ *
+ * Based on ib700wdt.c, which is based on advantechwdt.c which is based
+ * on acquirewdt.c which is based on wdt.c.
+ *
+ * (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ * Based on advantechwdt.c which is based on acquirewdt.c which
+ * is based on wdt.c.
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ * Based on acquirewdt.c which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ * http://www.redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <alan@redhat.com>
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long sbc8360_is_open;
+static spinlock_t sbc8360_lock;
+static char expect_close;
+
+#define PFX "sbc8360: "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system automatically
+ * and is defined at I/O port 0120H and 0121H. To enable the watchdog timer
+ * and allow the system to reset, write appropriate values from the table
+ * below to I/O port 0120H and 0121H. To disable the timer, write a zero
+ * value to I/O port 0121H for the system to stop the watchdog function.
+ *
+ * The following describes how the timer should be programmed (according to
+ * the vendor documentation)
+ *
+ * Enabling Watchdog:
+ * MOV AX,000AH (enable, phase I)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000BH (enable, phase II)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000nH (set multiplier n, from 1-4)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000mH (set base timer m, from 0-F)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Reset timer:
+ * MOV AX,000mH (same as set base timer, above)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,0000H (a zero value)
+ * MOV DX,0120H
+ * OUT DX,AX
+ *
+ * Watchdog timeout configuration values:
+ * N
+ * M | 1 2 3 4
+ * --|----------------------------------
+ * 0 | 0.5s 5s 50s 100s
+ * 1 | 1s 10s 100s 200s
+ * 2 | 1.5s 15s 150s 300s
+ * 3 | 2s 20s 200s 400s
+ * 4 | 2.5s 25s 250s 500s
+ * 5 | 3s 30s 300s 600s
+ * 6 | 3.5s 35s 350s 700s
+ * 7 | 4s 40s 400s 800s
+ * 8 | 4.5s 45s 450s 900s
+ * 9 | 5s 50s 500s 1000s
+ * A | 5.5s 55s 550s 1100s
+ * B | 6s 60s 600s 1200s
+ * C | 6.5s 65s 650s 1300s
+ * D | 7s 70s 700s 1400s
+ * E | 7.5s 75s 750s 1500s
+ * F | 8s 80s 800s 1600s
+ *
+ * Another way to say the same things is:
+ * For N=1, Timeout = (M+1) * 0.5s
+ * For N=2, Timeout = (M+1) * 5s
+ * For N=3, Timeout = (M+1) * 50s
+ * For N=4, Timeout = (M+1) * 100s
+ *
+ */
+
+static int wd_times[64][2] = {
+ {0, 1}, /* 0 = 0.5s */
+ {1, 1}, /* 1 = 1s */
+ {2, 1}, /* 2 = 1.5s */
+ {3, 1}, /* 3 = 2s */
+ {4, 1}, /* 4 = 2.5s */
+ {5, 1}, /* 5 = 3s */
+ {6, 1}, /* 6 = 3.5s */
+ {7, 1}, /* 7 = 4s */
+ {8, 1}, /* 8 = 4.5s */
+ {9, 1}, /* 9 = 5s */
+ {0xA, 1}, /* 10 = 5.5s */
+ {0xB, 1}, /* 11 = 6s */
+ {0xC, 1}, /* 12 = 6.5s */
+ {0xD, 1}, /* 13 = 7s */
+ {0xE, 1}, /* 14 = 7.5s */
+ {0xF, 1}, /* 15 = 8s */
+ {0, 2}, /* 16 = 5s */
+ {1, 2}, /* 17 = 10s */
+ {2, 2}, /* 18 = 15s */
+ {3, 2}, /* 19 = 20s */
+ {4, 2}, /* 20 = 25s */
+ {5, 2}, /* 21 = 30s */
+ {6, 2}, /* 22 = 35s */
+ {7, 2}, /* 23 = 40s */
+ {8, 2}, /* 24 = 45s */
+ {9, 2}, /* 25 = 50s */
+ {0xA, 2}, /* 26 = 55s */
+ {0xB, 2}, /* 27 = 60s */
+ {0xC, 2}, /* 28 = 65s */
+ {0xD, 2}, /* 29 = 70s */
+ {0xE, 2}, /* 30 = 75s */
+ {0xF, 2}, /* 31 = 80s */
+ {0, 3}, /* 32 = 50s */
+ {1, 3}, /* 33 = 100s */
+ {2, 3}, /* 34 = 150s */
+ {3, 3}, /* 35 = 200s */
+ {4, 3}, /* 36 = 250s */
+ {5, 3}, /* 37 = 300s */
+ {6, 3}, /* 38 = 350s */
+ {7, 3}, /* 39 = 400s */
+ {8, 3}, /* 40 = 450s */
+ {9, 3}, /* 41 = 500s */
+ {0xA, 3}, /* 42 = 550s */
+ {0xB, 3}, /* 43 = 600s */
+ {0xC, 3}, /* 44 = 650s */
+ {0xD, 3}, /* 45 = 700s */
+ {0xE, 3}, /* 46 = 750s */
+ {0xF, 3}, /* 47 = 800s */
+ {0, 4}, /* 48 = 100s */
+ {1, 4}, /* 49 = 200s */
+ {2, 4}, /* 50 = 300s */
+ {3, 4}, /* 51 = 400s */
+ {4, 4}, /* 52 = 500s */
+ {5, 4}, /* 53 = 600s */
+ {6, 4}, /* 54 = 700s */
+ {7, 4}, /* 55 = 800s */
+ {8, 4}, /* 56 = 900s */
+ {9, 4}, /* 57 = 1000s */
+ {0xA, 4}, /* 58 = 1100s */
+ {0xB, 4}, /* 59 = 1200s */
+ {0xC, 4}, /* 60 = 1300s */
+ {0xD, 4}, /* 61 = 1400s */
+ {0xE, 4}, /* 62 = 1500s */
+ {0xF, 4} /* 63 = 1600s */
+};
+
+#define SBC8360_ENABLE 0x120
+#define SBC8360_BASETIME 0x121
+
+static int timeout = 27;
+static int wd_margin = 0xB;
+static int wd_multiplier = 2;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(timeout, int, 27);
+MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Kernel methods.
+ */
+
+/* Activate and pre-configure watchdog */
+static void sbc8360_activate(void)
+{
+ /* Enable the watchdog */
+ outb(0x0A, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ outb(0x0B, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Set timeout multiplier */
+ outb(wd_multiplier, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Nothing happens until first sbc8360_ping() */
+}
+
+/* Kernel pings watchdog */
+static void sbc8360_ping(void)
+{
+ /* Write the base timer register */
+ outb(wd_margin, SBC8360_BASETIME);
+}
+
+/* Userspace pings kernel driver, or requests clean close */
+static ssize_t sbc8360_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+ sbc8360_ping();
+ }
+ return count;
+}
+
+static int sbc8360_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (test_and_set_bit(0, &sbc8360_is_open)) {
+ spin_unlock(&sbc8360_lock);
+ return -EBUSY;
+ }
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Activate and ping once to start the countdown */
+ spin_unlock(&sbc8360_lock);
+ sbc8360_activate();
+ sbc8360_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int sbc8360_close(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (expect_close == 42)
+ outb(0, SBC8360_ENABLE);
+ else
+ printk(KERN_CRIT PFX
+ "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n");
+
+ clear_bit(0, &sbc8360_is_open);
+ expect_close = 0;
+ spin_unlock(&sbc8360_lock);
+ return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT) {
+ /* Disable the SBC8360 Watchdog */
+ outb(0, SBC8360_ENABLE);
+ }
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations sbc8360_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = sbc8360_write,
+ .open = sbc8360_open,
+ .release = sbc8360_close,
+};
+
+static struct miscdevice sbc8360_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &sbc8360_fops,
+};
+
+/*
+ * The SBC8360 needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block sbc8360_notifier = {
+ .notifier_call = sbc8360_notify_sys,
+};
+
+static int __init sbc8360_init(void)
+{
+ int res;
+ unsigned long int mseconds = 60000;
+
+ spin_lock_init(&sbc8360_lock);
+ res = misc_register(&sbc8360_miscdev);
+ if (res) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ goto out_nomisc;
+ }
+
+ if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
+ printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+ SBC8360_ENABLE);
+ res = -EIO;
+ goto out_noenablereg;
+ }
+ if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
+ printk(KERN_ERR PFX
+ "BASETIME method I/O %X is not available.\n",
+ SBC8360_BASETIME);
+ res = -EIO;
+ goto out_nobasetimereg;
+ }
+
+ res = register_reboot_notifier(&sbc8360_notifier);
+ if (res) {
+ printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+ goto out_noreboot;
+ }
+
+ if (timeout < 0 || timeout > 63) {
+ printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+ res = -EINVAL;
+ goto out_noreboot;
+ }
+
+ wd_margin = wd_times[timeout][0];
+ wd_multiplier = wd_times[timeout][1];
+
+ if (wd_multiplier == 1)
+ mseconds = (wd_margin + 1) * 500;
+ else if (wd_multiplier == 2)
+ mseconds = (wd_margin + 1) * 5000;
+ else if (wd_multiplier == 3)
+ mseconds = (wd_margin + 1) * 50000;
+ else if (wd_multiplier == 4)
+ mseconds = (wd_margin + 1) * 100000;
+
+ /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
+ printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+
+ return 0;
+
+ out_noreboot:
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+ out_noenablereg:
+ out_nobasetimereg:
+ misc_deregister(&sbc8360_miscdev);
+ out_nomisc:
+ return res;
+}
+
+static void __exit sbc8360_exit(void)
+{
+ misc_deregister(&sbc8360_miscdev);
+ unregister_reboot_notifier(&sbc8360_notifier);
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+}
+
+module_init(sbc8360_init);
+module_exit(sbc8360_exit);
+
+MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
+MODULE_DESCRIPTION("SBC8360 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of sbc8360.c */
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
new file mode 100644
index 0000000..a7ff64c
--- /dev/null
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -0,0 +1,543 @@
+/*
+ * W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
+ *
+ * (c) Copyright 2005 Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on w83877f_wdt.c by Scott Jennings,
+ * and wdt977.c by Woody Suwalski
+ *
+ * -----------------------
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION "1.00"
+#define WATCHDOG_NAME "W83977F WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT 0x3F0
+#define IO_DATA_PORT (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA 0x87
+#define LOCK_DATA 0xAA
+#define DEVICE_REGISTER 0x07
+
+#define DEFAULT_TIMEOUT 45 /* default timeout in seconds */
+
+static int timeout = DEFAULT_TIMEOUT;
+static int timeoutW; /* timeout in watchdog counter units */
+static unsigned long timer_alive;
+static int testmode;
+static char expect_close;
+static spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt_start(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 has the timeout in watchdog counter units.
+ * F3 is set to enable watchdog LED blink at timeout.
+ * F4 is used to just clear the TIMEOUT'ed state (bit 0).
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /* Set device Aux2 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 as the watchdog output
+ * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
+ * Map GP16 at pin 119.
+ * In test mode watch the bit 0 on F4 to indicate "triggered" or
+ * check watchdog LED on SBC.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ unsigned pin_map;
+
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x0A,IO_DATA_PORT);
+ outb_p(0x2C,IO_INDEX_PORT);
+ pin_map = inb_p(IO_DATA_PORT);
+ pin_map |= 0x10;
+ pin_map &= ~(0x20);
+ outb_p(0x2C,IO_INDEX_PORT);
+ outb_p(pin_map,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+
+ /* Set device Aux1 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "activated.\n");
+
+ return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt_stop(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 is reset to its default value (watchdog timer disabled).
+ * F3 is reset to its default state.
+ * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0xFF,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 (in reg E6) and
+ * Gp13 (in reg E3) as inputs.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "shutdown.\n");
+
+ return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt_keepalive(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to kick watchdog reg F2 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt_set_timeout(int t)
+{
+ int tmrval;
+
+ /*
+ * Convert seconds to watchdog counter time units, rounding up.
+ * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup
+ * value. This information is supplied in the PCM-5335 manual and was
+ * checked by me on a real board. This is a bit strange because W83977f
+ * datasheet says counter unit is in minutes!
+ */
+ if (t < 15)
+ return -EINVAL;
+
+ tmrval = ((t + 15) + 29) / 30;
+
+ if (tmrval > 255)
+ return -EINVAL;
+
+ /*
+ * timeout is the timeout in seconds,
+ * timeoutW is the timeout in watchdog counter units.
+ */
+ timeoutW = tmrval;
+ timeout = (timeoutW * 30) - 15;
+ return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt_get_status(int *status)
+{
+ int new_status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to read watchdog reg F4 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ new_status = inb_p(IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ *status = 0;
+ if (new_status & 1)
+ *status |= WDIOF_CARDRESET;
+
+ return 0;
+}
+
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ /* If the watchdog is alive we don't need to start it again */
+ if( test_and_set_bit(0, &timer_alive) )
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+ /*
+ * Shut off the timer.
+ * Lock it in if it's a module and we set nowayout
+ */
+ if (expect_close == 42)
+ {
+ wdt_stop();
+ clear_bit(0, &timer_alive);
+ } else {
+ wdt_keepalive();
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ }
+ expect_close = 0;
+ return 0;
+}
+
+/*
+ * wdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if(count)
+ {
+ if (!nowayout)
+ {
+ size_t ofs;
+
+ /* note: just in case someone wrote the magic character long ago */
+ expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for(ofs = 0; ofs != count; ofs++)
+ {
+ char c;
+ if (get_user(c, buf + ofs))
+ return -EFAULT;
+ if (c == 'V') {
+ expect_close = 42;
+ }
+ }
+ }
+
+ /* someone wrote to us, we should restart timer */
+ wdt_keepalive();
+ }
+ return count;
+}
+
+/*
+ * wdt_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features.
+ */
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+};
+
+static int wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int status;
+ int new_options, retval = -EINVAL;
+ int new_timeout;
+ union {
+ struct watchdog_info __user *ident;
+ int __user *i;
+ } uarg;
+
+ uarg.i = (int __user *)arg;
+
+ switch(cmd)
+ {
+ default:
+ return -ENOIOCTLCMD;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ wdt_get_status(&status);
+ return put_user(status, uarg.i);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, uarg.i);
+
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user (new_options, uarg.i))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ wdt_stop();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ wdt_start();
+ retval = 0;
+ }
+
+ return retval;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, uarg.i))
+ return -EFAULT;
+
+ if (wdt_set_timeout(new_timeout))
+ return -EINVAL;
+
+ wdt_keepalive();
+ /* Fall */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, uarg.i);
+
+ }
+}
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT)
+ wdt_stop();
+ return NOTIFY_DONE;
+}
+
+static struct file_operations wdt_fops=
+{
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdt_write,
+ .ioctl = wdt_ioctl,
+ .open = wdt_open,
+ .release = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev=
+{
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+
+static int __init w83977f_wdt_init(void)
+{
+ int rc;
+
+ printk(KERN_INFO PFX DRIVER_VERSION);
+
+ spin_lock_init(&spinlock);
+
+ /*
+ * Check that the timeout value is within it's range ;
+ * if not reset to the default
+ */
+ if (wdt_set_timeout(timeout)) {
+ wdt_set_timeout(DEFAULT_TIMEOUT);
+ printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
+ DEFAULT_TIMEOUT);
+ }
+
+ if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+ {
+ printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+ IO_INDEX_PORT);
+ rc = -EIO;
+ goto err_out;
+ }
+
+ rc = misc_register(&wdt_miscdev);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ wdt_miscdev.minor, rc);
+ goto err_out_region;
+ }
+
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ rc);
+ goto err_out_miscdev;
+ }
+
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+ timeout, nowayout, testmode);
+
+ return 0;
+
+err_out_miscdev:
+ misc_deregister(&wdt_miscdev);
+err_out_region:
+ release_region(IO_INDEX_PORT,2);
+err_out:
+ return rc;
+}
+
+static void __exit w83977f_wdt_exit(void)
+{
+ wdt_stop();
+ misc_deregister(&wdt_miscdev);
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(IO_INDEX_PORT,2);
+}
+
+module_init(w83977f_wdt_init);
+module_exit(w83977f_wdt_exit);
+
+MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
+MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 3b865f3..b667823 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -50,7 +50,7 @@
MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_VERSION("2.0");
#define BIOS_SCAN_LIMIT 0xffffffff
#define MAX_IMAGE_LENGTH 16
@@ -65,10 +65,11 @@ static struct _rbu_data {
unsigned long packet_write_count;
unsigned long num_packets;
unsigned long packetsize;
+ int entry_created;
} rbu_data;
-static char image_type[MAX_IMAGE_LENGTH] = "mono";
-module_param_string(image_type, image_type, sizeof(image_type), 0);
+static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
+module_param_string(image_type, image_type, sizeof (image_type), 0);
MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
struct packet_data {
@@ -114,7 +115,7 @@ static int fill_last_packet(void *data, size_t length)
if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
pr_debug("dell_rbu:%s: packet size data "
- "overrun\n", __FUNCTION__);
+ "overrun\n", __FUNCTION__);
return -EINVAL;
}
@@ -146,12 +147,14 @@ static int create_packet(size_t length)
pr_debug("create_packet: packetsize not specified\n");
return -EINVAL;
}
+ spin_unlock(&rbu_data.lock);
+ newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL);
+ spin_lock(&rbu_data.lock);
- newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
if (!newpacket) {
printk(KERN_WARNING
- "dell_rbu:%s: failed to allocate new "
- "packet\n", __FUNCTION__);
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
return -ENOMEM;
}
@@ -160,15 +163,17 @@ static int create_packet(size_t length)
* there is no upper limit on memory
* address for packetized mechanism
*/
- newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL,
- ordernum);
+ spin_unlock(&rbu_data.lock);
+ newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL,
+ ordernum);
+ spin_lock(&rbu_data.lock);
pr_debug("create_packet: newpacket %p\n", newpacket->data);
if (!newpacket->data) {
printk(KERN_WARNING
- "dell_rbu:%s: failed to allocate new "
- "packet\n", __FUNCTION__);
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
kfree(newpacket);
return -ENOMEM;
}
@@ -204,9 +209,8 @@ static int packetize_data(void *data, size_t length)
return rc;
}
-static int
-do_packet_read(char *data, struct list_head *ptemp_list,
- int length, int bytes_read, int *list_read_count)
+static int do_packet_read(char *data, struct list_head *ptemp_list,
+ int length, int bytes_read, int *list_read_count)
{
void *ptemp_buf;
struct packet_data *newpacket = NULL;
@@ -239,7 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list,
return bytes_copied;
}
-static int packet_read_list(char *data, size_t * pread_length)
+static int packet_read_list(char *data, size_t *pread_length)
{
struct list_head *ptemp_list;
int temp_count = 0;
@@ -258,8 +262,7 @@ static int packet_read_list(char *data, size_t * pread_length)
ptemp_list = (&packet_data_head.list)->next;
while (!list_empty(ptemp_list)) {
bytes_copied = do_packet_read(pdest, ptemp_list,
- remaining_bytes, bytes_read,
- &temp_count);
+ remaining_bytes, bytes_read, &temp_count);
remaining_bytes -= bytes_copied;
bytes_read += bytes_copied;
pdest += bytes_copied;
@@ -287,7 +290,7 @@ static void packet_empty_list(void)
ptemp_list = (&packet_data_head.list)->next;
while (!list_empty(ptemp_list)) {
newpacket =
- list_entry(ptemp_list, struct packet_data, list);
+ list_entry(ptemp_list, struct packet_data, list);
pnext_list = ptemp_list->next;
list_del(ptemp_list);
ptemp_list = pnext_list;
@@ -296,8 +299,8 @@ static void packet_empty_list(void)
* to make sure there are no stale RBU packets left in memory
*/
memset(newpacket->data, 0, rbu_data.packetsize);
- free_pages((unsigned long)newpacket->data,
- newpacket->ordernum);
+ free_pages((unsigned long) newpacket->data,
+ newpacket->ordernum);
kfree(newpacket);
}
rbu_data.packet_write_count = 0;
@@ -319,14 +322,13 @@ static void img_update_free(void)
* BIOS image copied in memory.
*/
memset(rbu_data.image_update_buffer, 0,
- rbu_data.image_update_buffer_size);
+ rbu_data.image_update_buffer_size);
if (rbu_data.dma_alloc == 1)
dma_free_coherent(NULL, rbu_data.bios_image_size,
- rbu_data.image_update_buffer,
- dell_rbu_dmaaddr);
+ rbu_data.image_update_buffer, dell_rbu_dmaaddr);
else
- free_pages((unsigned long)rbu_data.image_update_buffer,
- rbu_data.image_update_ordernum);
+ free_pages((unsigned long) rbu_data.image_update_buffer,
+ rbu_data.image_update_ordernum);
/*
* Re-initialize the rbu_data variables after a free
@@ -366,7 +368,7 @@ static int img_update_realloc(unsigned long size)
*/
if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
printk(KERN_ERR "dell_rbu:%s: corruption "
- "check failed\n", __FUNCTION__);
+ "check failed\n", __FUNCTION__);
return -EINVAL;
}
/*
@@ -385,17 +387,16 @@ static int img_update_realloc(unsigned long size)
ordernum = get_order(size);
image_update_buffer =
- (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum);
+ (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
img_buf_phys_addr =
- (unsigned long)virt_to_phys(image_update_buffer);
+ (unsigned long) virt_to_phys(image_update_buffer);
if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
- free_pages((unsigned long)image_update_buffer, ordernum);
+ free_pages((unsigned long) image_update_buffer, ordernum);
ordernum = -1;
image_update_buffer = dma_alloc_coherent(NULL, size,
- &dell_rbu_dmaaddr,
- GFP_KERNEL);
+ &dell_rbu_dmaaddr, GFP_KERNEL);
dma_alloc = 1;
}
@@ -405,13 +406,13 @@ static int img_update_realloc(unsigned long size)
rbu_data.image_update_buffer = image_update_buffer;
rbu_data.image_update_buffer_size = size;
rbu_data.bios_image_size =
- rbu_data.image_update_buffer_size;
+ rbu_data.image_update_buffer_size;
rbu_data.image_update_ordernum = ordernum;
rbu_data.dma_alloc = dma_alloc;
rc = 0;
} else {
pr_debug("Not enough memory for image update:"
- "size = %ld\n", size);
+ "size = %ld\n", size);
rc = -ENOMEM;
}
@@ -438,7 +439,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
if (pos > imagesize) {
retval = 0;
printk(KERN_WARNING "dell_rbu:read_packet_data: "
- "data underrun\n");
+ "data underrun\n");
goto read_rbu_data_exit;
}
@@ -468,11 +469,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
/* check to see if we have something to return */
if ((rbu_data.image_update_buffer == NULL) ||
- (rbu_data.bios_image_size == 0)) {
+ (rbu_data.bios_image_size == 0)) {
pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
- "bios_image_size %lu\n",
- rbu_data.image_update_buffer,
- rbu_data.bios_image_size);
+ "bios_image_size %lu\n",
+ rbu_data.image_update_buffer,
+ rbu_data.bios_image_size);
ret_count = -ENOMEM;
goto read_rbu_data_exit;
}
@@ -497,8 +498,8 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
return ret_count;
}
-static ssize_t
-read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
+static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
{
ssize_t ret_count = 0;
@@ -515,62 +516,20 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
return ret_count;
}
-static ssize_t
-read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
- size_t count)
-{
- int size = 0;
- if (!pos)
- size = sprintf(buffer, "%s\n", image_type);
- return size;
-}
-
-static ssize_t
-write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
- size_t count)
-{
- int rc = count;
- spin_lock(&rbu_data.lock);
-
- if (strlen(buffer) < MAX_IMAGE_LENGTH)
- sscanf(buffer, "%s", image_type);
- else
- printk(KERN_WARNING "dell_rbu: image_type is invalid"
- "max chars = %d, \n incoming str--%s-- \n",
- MAX_IMAGE_LENGTH, buffer);
-
- /* we must free all previous allocations */
- packet_empty_list();
- img_update_free();
-
- spin_unlock(&rbu_data.lock);
- return rc;
-
-}
-
-static struct bin_attribute rbu_data_attr = {
- .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
- .read = read_rbu_data,
-};
-
-static struct bin_attribute rbu_image_type_attr = {
- .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
- .read = read_rbu_image_type,
- .write = write_rbu_image_type,
-};
-
static void callbackfn_rbu(const struct firmware *fw, void *context)
{
int rc = 0;
- if (!fw || !fw->size)
+ if (!fw || !fw->size) {
+ rbu_data.entry_created = 0;
return;
+ }
spin_lock(&rbu_data.lock);
if (!strcmp(image_type, "mono")) {
if (!img_update_realloc(fw->size))
memcpy(rbu_data.image_update_buffer,
- fw->data, fw->size);
+ fw->data, fw->size);
} else if (!strcmp(image_type, "packet")) {
if (!rbu_data.packetsize)
rbu_data.packetsize = fw->size;
@@ -584,14 +543,103 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
spin_unlock(&rbu_data.lock);
rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "dell_rbu", &rbu_device->dev,
- &context, callbackfn_rbu);
+ "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
if (rc)
printk(KERN_ERR
- "dell_rbu:%s request_firmware_nowait failed"
- " %d\n", __FUNCTION__, rc);
+ "dell_rbu:%s request_firmware_nowait failed"
+ " %d\n", __FUNCTION__, rc);
+ else
+ rbu_data.entry_created = 1;
+}
+
+static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int size = 0;
+ if (!pos)
+ size = sprintf(buffer, "%s\n", image_type);
+ return size;
+}
+
+static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int rc = count;
+ int req_firm_rc = 0;
+ int i;
+ spin_lock(&rbu_data.lock);
+ /*
+ * Find the first newline or space
+ */
+ for (i = 0; i < count; ++i)
+ if (buffer[i] == '\n' || buffer[i] == ' ') {
+ buffer[i] = '\0';
+ break;
+ }
+ if (i == count)
+ buffer[count] = '\0';
+
+ if (strstr(buffer, "mono"))
+ strcpy(image_type, "mono");
+ else if (strstr(buffer, "packet"))
+ strcpy(image_type, "packet");
+ else if (strstr(buffer, "init")) {
+ /*
+ * If due to the user error the driver gets in a bad
+ * state where even though it is loaded , the
+ * /sys/class/firmware/dell_rbu entries are missing.
+ * to cover this situation the user can recreate entries
+ * by writing init to image_type.
+ */
+ if (!rbu_data.entry_created) {
+ spin_unlock(&rbu_data.lock);
+ req_firm_rc = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_NOHOTPLUG, "dell_rbu",
+ &rbu_device->dev, &context,
+ callbackfn_rbu);
+ if (req_firm_rc) {
+ printk(KERN_ERR
+ "dell_rbu:%s request_firmware_nowait"
+ " failed %d\n", __FUNCTION__, rc);
+ rc = -EIO;
+ } else
+ rbu_data.entry_created = 1;
+
+ spin_lock(&rbu_data.lock);
+ }
+ } else {
+ printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
+ spin_unlock(&rbu_data.lock);
+ return -EINVAL;
+ }
+
+ /* we must free all previous allocations */
+ packet_empty_list();
+ img_update_free();
+ spin_unlock(&rbu_data.lock);
+
+ return rc;
}
+static struct bin_attribute rbu_data_attr = {
+ .attr = {
+ .name = "data",
+ .owner = THIS_MODULE,
+ .mode = 0444,
+ },
+ .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+ .attr = {
+ .name = "image_type",
+ .owner = THIS_MODULE,
+ .mode = 0644,
+ },
+ .read = read_rbu_image_type,
+ .write = write_rbu_image_type,
+};
+
static int __init dcdrbu_init(void)
{
int rc = 0;
@@ -599,11 +647,11 @@ static int __init dcdrbu_init(void)
init_packet_head();
rbu_device =
- platform_device_register_simple("dell_rbu", -1, NULL, 0);
+ platform_device_register_simple("dell_rbu", -1, NULL, 0);
if (!rbu_device) {
printk(KERN_ERR
- "dell_rbu:%s:platform_device_register_simple "
- "failed\n", __FUNCTION__);
+ "dell_rbu:%s:platform_device_register_simple "
+ "failed\n", __FUNCTION__);
return -EIO;
}
@@ -611,11 +659,12 @@ static int __init dcdrbu_init(void)
sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "dell_rbu", &rbu_device->dev,
- &context, callbackfn_rbu);
+ "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
if (rc)
printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
- " failed %d\n", __FUNCTION__, rc);
+ " failed %d\n", __FUNCTION__, rc);
+ else
+ rbu_data.entry_created = 1;
return rc;
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index eaebfc1..4c56411 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -5,10 +5,10 @@
* Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
*
* The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
- * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis
- * accelerometer and other data, such as the device's temperature.
+ * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic
+ * two-axis accelerometer and other data, such as the device's temperature.
*
- * Based on the document by Mark A. Smith available at
+ * This driver is based on the document by Mark A. Smith available at
* http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
* and error.
*
@@ -36,12 +36,7 @@
#include <asm/io.h>
#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
-#define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */
-
-#define STATE_FRESH 0x50 /* accelerometer data is fresh */
-
-#define REFRESH_ASYNC 0x00 /* do asynchronous refresh */
-#define REFRESH_SYNC 0x01 /* do synchronous refresh */
+#define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */
#define HDAPS_PORT_STATE 0x1611 /* device state */
#define HDAPS_PORT_YPOS 0x1612 /* y-axis position */
@@ -53,7 +48,7 @@
#define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */
#define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */
-#define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */
+#define STATE_FRESH 0x50 /* accelerometer data is fresh */
#define KEYBD_MASK 0x20 /* set if keyboard activity */
#define MOUSE_MASK 0x40 /* set if mouse activity */
@@ -63,12 +58,11 @@
#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
-static struct platform_device *pdev;
-static struct input_dev hdaps_idev;
+#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
+#define HDAPS_INPUT_FUZZ 4 /* input event threshold */
+
static struct timer_list hdaps_timer;
-static unsigned int hdaps_mousedev_threshold = 4;
-static unsigned long hdaps_poll_ms = 50;
-static unsigned int hdaps_mousedev;
+static struct platform_device *pdev;
static unsigned int hdaps_invert;
static u8 km_activity;
static int rest_x;
@@ -81,14 +75,14 @@ static DECLARE_MUTEX(hdaps_sem);
*/
static inline u8 __get_latch(u16 port)
{
- return inb(port) & HDAPS_READ_MASK;
+ return inb(port) & 0xff;
}
/*
- * __check_latch - Check a port latch for a given value. Callers must hold
- * hdaps_sem. Returns zero if the port contains the given value.
+ * __check_latch - Check a port latch for a given value. Returns zero if the
+ * port contains the given value. Callers must hold hdaps_sem.
*/
-static inline unsigned int __check_latch(u16 port, u8 val)
+static inline int __check_latch(u16 port, u8 val)
{
if (__get_latch(port) == val)
return 0;
@@ -99,7 +93,7 @@ static inline unsigned int __check_latch(u16 port, u8 val)
* __wait_latch - Wait up to 100us for a port latch to get a certain value,
* returning zero if the value is obtained. Callers must hold hdaps_sem.
*/
-static unsigned int __wait_latch(u16 port, u8 val)
+static int __wait_latch(u16 port, u8 val)
{
unsigned int i;
@@ -109,59 +103,42 @@ static unsigned int __wait_latch(u16 port, u8 val)
udelay(5);
}
- return -EINVAL;
+ return -EIO;
}
/*
- * __device_refresh - Request a refresh from the accelerometer.
- *
- * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait.
- * Returns zero if successful and nonzero on error.
- *
- * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is
- * not up-to-date. Always returns zero.
- *
- * Callers must hold hdaps_sem.
+ * __device_refresh - request a refresh from the accelerometer. Does not wait
+ * for refresh to complete. Callers must hold hdaps_sem.
*/
-static int __device_refresh(unsigned int sync)
+static void __device_refresh(void)
{
- u8 state;
-
- udelay(100);
-
- state = inb(0x1604);
- if (state == STATE_FRESH)
- return 0;
-
- outb(0x11, 0x1610);
- outb(0x01, 0x161f);
- if (sync == REFRESH_ASYNC)
- return 0;
+ udelay(200);
+ if (inb(0x1604) != STATE_FRESH) {
+ outb(0x11, 0x1610);
+ outb(0x01, 0x161f);
+ }
+}
+/*
+ * __device_refresh_sync - request a synchronous refresh from the
+ * accelerometer. We wait for the refresh to complete. Returns zero if
+ * successful and nonzero on error. Callers must hold hdaps_sem.
+ */
+static int __device_refresh_sync(void)
+{
+ __device_refresh();
return __wait_latch(0x1604, STATE_FRESH);
}
/*
- * __device_complete - Indicate to the accelerometer that we are done reading
+ * __device_complete - indicate to the accelerometer that we are done reading
* data, and then initiate an async refresh. Callers must hold hdaps_sem.
*/
static inline void __device_complete(void)
{
inb(0x161f);
inb(0x1604);
- __device_refresh(REFRESH_ASYNC);
-}
-
-static int __hdaps_readb_one(unsigned int port, u8 *val)
-{
- /* do a sync refresh -- we need to be sure that we read fresh data */
- if (__device_refresh(REFRESH_SYNC))
- return -EIO;
-
- *val = inb(port);
- __device_complete();
-
- return 0;
+ __device_refresh();
}
/*
@@ -174,17 +151,26 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
int ret;
down(&hdaps_sem);
- ret = __hdaps_readb_one(port, val);
- up(&hdaps_sem);
+ /* do a sync refresh -- we need to be sure that we read fresh data */
+ ret = __device_refresh_sync();
+ if (ret)
+ goto out;
+
+ *val = inb(port);
+ __device_complete();
+
+out:
+ up(&hdaps_sem);
return ret;
}
+/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
int *x, int *y)
{
/* do a sync refresh -- we need to be sure that we read fresh data */
- if (__device_refresh(REFRESH_SYNC))
+ if (__device_refresh_sync())
return -EIO;
*y = inw(port2);
@@ -217,11 +203,13 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2,
return ret;
}
-/* initialize the accelerometer */
+/*
+ * hdaps_device_init - initialize the accelerometer. Returns zero on success
+ * and negative error code on failure. Can sleep.
+ */
static int hdaps_device_init(void)
{
- unsigned int total_msecs = INIT_TIMEOUT_MSECS;
- int ret = -ENXIO;
+ int total, ret = -ENXIO;
down(&hdaps_sem);
@@ -231,8 +219,10 @@ static int hdaps_device_init(void)
goto out;
/*
- * The 0x03 value appears to only work on some thinkpads, such as the
- * T42p. Others return 0x01.
+ * Most ThinkPads return 0x01.
+ *
+ * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops
+ * have "inverted" axises.
*
* The 0x02 value occurs when the chip has been previously initialized.
*/
@@ -267,24 +257,23 @@ static int hdaps_device_init(void)
outb(0x01, 0x161f);
if (__wait_latch(0x161f, 0x00))
goto out;
- if (__device_refresh(REFRESH_SYNC))
+ if (__device_refresh_sync())
goto out;
if (__wait_latch(0x1611, 0x00))
goto out;
/* we have done our dance, now let's wait for the applause */
- while (total_msecs > 0) {
- u8 ignored;
+ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+ int x, y;
/* a read of the device helps push it into action */
- __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
+ __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
if (!__wait_latch(0x1611, 0x02)) {
ret = 0;
break;
}
msleep(INIT_WAIT_MSECS);
- total_msecs -= INIT_WAIT_MSECS;
}
out:
@@ -293,96 +282,6 @@ out:
}
-/* Input class stuff */
-
-/*
- * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem.
- */
-static void hdaps_calibrate(void)
-{
- int x, y;
-
- if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
- return;
-
- rest_x = x;
- rest_y = y;
-}
-
-static void hdaps_mousedev_poll(unsigned long unused)
-{
- int x, y;
-
- /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (down_trylock(&hdaps_sem)) {
- mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms));
- return;
- }
-
- if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
- goto out;
-
- x -= rest_x;
- y -= rest_y;
- if (abs(x) > hdaps_mousedev_threshold)
- input_report_rel(&hdaps_idev, REL_X, x);
- if (abs(y) > hdaps_mousedev_threshold)
- input_report_rel(&hdaps_idev, REL_Y, y);
- input_sync(&hdaps_idev);
-
- mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms));
-
-out:
- up(&hdaps_sem);
-}
-
-/*
- * hdaps_mousedev_enable - enable the input class device. Can sleep.
- */
-static void hdaps_mousedev_enable(void)
-{
- down(&hdaps_sem);
-
- /* calibrate the device before enabling */
- hdaps_calibrate();
-
- /* initialize the input class */
- init_input_dev(&hdaps_idev);
- hdaps_idev.dev = &pdev->dev;
- hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT);
- input_register_device(&hdaps_idev);
-
- /* start up our timer */
- init_timer(&hdaps_timer);
- hdaps_timer.function = hdaps_mousedev_poll;
- hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms);
- add_timer(&hdaps_timer);
-
- hdaps_mousedev = 1;
-
- up(&hdaps_sem);
-
- printk(KERN_INFO "hdaps: input device enabled.\n");
-}
-
-/*
- * hdaps_mousedev_disable - disable the input class device. Caller must hold
- * hdaps_sem.
- */
-static void hdaps_mousedev_disable(void)
-{
- down(&hdaps_sem);
- if (hdaps_mousedev) {
- hdaps_mousedev = 0;
- del_timer_sync(&hdaps_timer);
- input_unregister_device(&hdaps_idev);
- }
- up(&hdaps_sem);
-}
-
-
/* Device model stuff */
static int hdaps_probe(struct device *dev)
@@ -412,6 +311,49 @@ static struct device_driver hdaps_driver = {
.resume = hdaps_resume
};
+/* Input class stuff */
+
+static struct input_dev hdaps_idev = {
+ .name = "hdaps",
+ .evbit = { BIT(EV_ABS) },
+ .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
+ .absmin = { [ABS_X] = -256, [ABS_Y] = -256 },
+ .absmax = { [ABS_X] = 256, [ABS_Y] = 256 },
+ .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+ .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+};
+
+/*
+ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+ __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
+}
+
+static void hdaps_mousedev_poll(unsigned long unused)
+{
+ int x, y;
+
+ /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
+ if (down_trylock(&hdaps_sem)) {
+ mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
+ return;
+ }
+
+ if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+ goto out;
+
+ input_report_abs(&hdaps_idev, ABS_X, x - rest_x);
+ input_report_abs(&hdaps_idev, ABS_Y, y - rest_y);
+ input_sync(&hdaps_idev);
+
+ mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
+
+out:
+ up(&hdaps_sem);
+}
+
/* Sysfs Files */
@@ -517,69 +459,6 @@ static ssize_t hdaps_invert_store(struct device *dev,
return count;
}
-static ssize_t hdaps_mousedev_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n", hdaps_mousedev);
-}
-
-static ssize_t hdaps_mousedev_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int enable;
-
- if (sscanf(buf, "%d", &enable) != 1)
- return -EINVAL;
-
- if (enable == 1)
- hdaps_mousedev_enable();
- else if (enable == 0)
- hdaps_mousedev_disable();
- else
- return -EINVAL;
-
- return count;
-}
-
-static ssize_t hdaps_poll_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", hdaps_poll_ms);
-}
-
-static ssize_t hdaps_poll_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int poll;
-
- if (sscanf(buf, "%u", &poll) != 1 || poll == 0)
- return -EINVAL;
- hdaps_poll_ms = poll;
-
- return count;
-}
-
-static ssize_t hdaps_threshold_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%u\n", hdaps_mousedev_threshold);
-}
-
-static ssize_t hdaps_threshold_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int threshold;
-
- if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0)
- return -EINVAL;
- hdaps_mousedev_threshold = threshold;
-
- return count;
-}
-
static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
@@ -588,10 +467,6 @@ static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
-static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store);
-static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store);
-static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show,
- hdaps_threshold_store);
static struct attribute *hdaps_attributes[] = {
&dev_attr_position.attr,
@@ -601,9 +476,6 @@ static struct attribute *hdaps_attributes[] = {
&dev_attr_keyboard_activity.attr,
&dev_attr_mouse_activity.attr,
&dev_attr_calibrate.attr,
- &dev_attr_mousedev.attr,
- &dev_attr_mousedev_threshold.attr,
- &dev_attr_mousedev_poll_ms.attr,
&dev_attr_invert.attr,
NULL,
};
@@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = {
* XXX: We should be able to return nonzero and halt the detection process.
* But there is a bug in dmi_check_system() where a nonzero return from the
* first match will result in a return of failure from dmi_check_system().
- * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make
+ * I fixed this; the patch is 2.6-git. Once in a released tree, we can make
* hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
*/
static int hdaps_dmi_match(struct dmi_system_id *id)
@@ -668,6 +540,7 @@ static int __init hdaps_init(void)
HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
{ .ident = NULL }
};
@@ -696,8 +569,18 @@ static int __init hdaps_init(void)
if (ret)
goto out_device;
- if (hdaps_mousedev)
- hdaps_mousedev_enable();
+ /* initial calibrate for the input device */
+ hdaps_calibrate();
+
+ /* initialize the input class */
+ hdaps_idev.dev = &pdev->dev;
+ input_register_device(&hdaps_idev);
+
+ /* start up our timer for the input device */
+ init_timer(&hdaps_timer);
+ hdaps_timer.function = hdaps_mousedev_poll;
+ hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
+ add_timer(&hdaps_timer);
printk(KERN_INFO "hdaps: driver successfully loaded.\n");
return 0;
@@ -715,8 +598,8 @@ out:
static void __exit hdaps_exit(void)
{
- hdaps_mousedev_disable();
-
+ del_timer_sync(&hdaps_timer);
+ input_unregister_device(&hdaps_idev);
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
platform_device_unregister(pdev);
driver_unregister(&hdaps_driver);
@@ -728,9 +611,6 @@ static void __exit hdaps_exit(void)
module_init(hdaps_init);
module_exit(hdaps_exit);
-module_param_named(mousedev, hdaps_mousedev, bool, 0);
-MODULE_PARM_DESC(mousedev, "enable the input class device");
-
module_param_named(invert, hdaps_invert, bool, 0);
MODULE_PARM_DESC(invert, "invert data along each axis");
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 37b49c2..eff5896 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -611,7 +611,6 @@ create_iface(struct device_node *np, struct device *dev)
for (i=0; i<nchan; i++) {
struct keywest_chan* chan = &iface->channels[i];
- u8 addr;
sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
chan->iface = iface;
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index fdf53ce..44b595d 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -914,19 +914,23 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
return ret;
}
+static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
static struct i2c_algorithm i2c_pxa_algorithm = {
- .name = "PXA-I2C-Algorithm",
- .id = I2C_ALGO_PXA,
.master_xfer = i2c_pxa_xfer,
+ .functionality = i2c_pxa_functionality,
};
static struct pxa_i2c i2c_pxa = {
.lock = SPIN_LOCK_UNLOCKED,
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
.adap = {
- .name = "pxa2xx-i2c",
- .id = I2C_ALGO_PXA,
+ .owner = THIS_MODULE,
.algo = &i2c_pxa_algorithm,
+ .name = "pxa2xx-i2c",
.retries = 5,
},
};
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b443b04..0b0aa4f 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -601,44 +601,15 @@ EXPORT_SYMBOL(ide_wait_stat);
*/
u8 eighty_ninty_three (ide_drive_t *drive)
{
-#if 0
- if (!HWIF(drive)->udma_four)
+ if(HWIF(drive)->udma_four == 0)
+ return 0;
+ if (!(drive->id->hw_config & 0x6000))
return 0;
-
- if (drive->id->major_rev_num) {
- int hssbd = 0;
- int i;
- /*
- * Determine highest Supported SPEC
- */
- for (i=1; i<=15; i++)
- if (drive->id->major_rev_num & (1<<i))
- hssbd++;
-
- switch (hssbd) {
- case 7:
- case 6:
- case 5:
- /* ATA-4 and older do not support above Ultra 33 */
- default:
- return 0;
- }
- }
-
- return ((u8) (
-#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-
-#else
-
- return ((u8) ((HWIF(drive)->udma_four) &&
#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
+ if(!(drive->id->hw_config & 0x4000))
+ return 0;
#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-#endif
+ return 1;
}
EXPORT_SYMBOL(eighty_ninty_three);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index d04f62a..ace8eda 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -500,6 +500,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
}
rq.special = args;
+ args->rq = &rq;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 3de9ab8..3d9c7af 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -608,7 +608,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
#ifdef __i386__
if (dev->resource[PCI_ROM_RESOURCE].start) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
}
#endif
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index bbde462..be334da 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -173,7 +173,7 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
if (cmd & PCI_COMMAND_MEMORY) {
if (pci_resource_start(dev, PCI_ROM_RESOURCE)) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n",
dev->resource[PCI_ROM_RESOURCE].start);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index e55dee3..444f775 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -132,6 +132,17 @@ config KEYBOARD_CORGI
To compile this driver as a module, choose M here: the
module will be called corgikbd.
+config KEYBOARD_SPITZ
+ tristate "Spitz keyboard"
+ depends on PXA_SHARPSL
+ default y
+ help
+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+ SL-C3000 and Sl-C3100 series of PDAs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called spitzkbd.
+
config KEYBOARD_MAPLE
tristate "Maple bus keyboard"
depends on SH_DREAMCAST && MAPLE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index b02eece..9ce0b87 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
new file mode 100644
index 0000000..1714045
--- /dev/null
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -0,0 +1,478 @@
+/*
+ * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on corgikbd.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/spitz.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#define KB_ROWS 7
+#define KB_COLS 11
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(r,c) (((r)<<4) + (c) + 1)
+#define NR_SCANCODES ((KB_ROWS<<4) + 1)
+
+#define HINGE_SCAN_INTERVAL (150) /* ms */
+
+#define SPITZ_KEY_CALENDER KEY_F1
+#define SPITZ_KEY_ADDRESS KEY_F2
+#define SPITZ_KEY_FN KEY_F3
+#define SPITZ_KEY_CANCEL KEY_F4
+#define SPITZ_KEY_EXOK KEY_F5
+#define SPITZ_KEY_EXCANCEL KEY_F6
+#define SPITZ_KEY_EXJOGDOWN KEY_F7
+#define SPITZ_KEY_EXJOGUP KEY_F8
+#define SPITZ_KEY_JAP1 KEY_LEFTALT
+#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL
+#define SPITZ_KEY_SYNC KEY_F9
+#define SPITZ_KEY_MAIL KEY_F10
+#define SPITZ_KEY_OK KEY_F11
+#define SPITZ_KEY_MENU KEY_F12
+
+static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
+ 0, /* 0 */
+ KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */
+ 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
+ KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
+ SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, /* 49-64 */
+ SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */
+ SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */
+ KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */
+};
+
+static int spitz_strobes[] = {
+ SPITZ_GPIO_KEY_STROBE0,
+ SPITZ_GPIO_KEY_STROBE1,
+ SPITZ_GPIO_KEY_STROBE2,
+ SPITZ_GPIO_KEY_STROBE3,
+ SPITZ_GPIO_KEY_STROBE4,
+ SPITZ_GPIO_KEY_STROBE5,
+ SPITZ_GPIO_KEY_STROBE6,
+ SPITZ_GPIO_KEY_STROBE7,
+ SPITZ_GPIO_KEY_STROBE8,
+ SPITZ_GPIO_KEY_STROBE9,
+ SPITZ_GPIO_KEY_STROBE10,
+};
+
+static int spitz_senses[] = {
+ SPITZ_GPIO_KEY_SENSE0,
+ SPITZ_GPIO_KEY_SENSE1,
+ SPITZ_GPIO_KEY_SENSE2,
+ SPITZ_GPIO_KEY_SENSE3,
+ SPITZ_GPIO_KEY_SENSE4,
+ SPITZ_GPIO_KEY_SENSE5,
+ SPITZ_GPIO_KEY_SENSE6,
+};
+
+struct spitzkbd {
+ unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
+ struct input_dev input;
+ char phys[32];
+
+ spinlock_t lock;
+ struct timer_list timer;
+ struct timer_list htimer;
+
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
+
+#define KB_DISCHARGE_DELAY 10
+#define KB_ACTIVATE_DELAY 10
+
+/* Helper functions for reading the keyboard matrix
+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it
+ * requires a function call per GPIO bit which is excessive
+ * when we need to access 11 bits at once, multiple times.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void spitzkbd_discharge_all(void)
+{
+ /* STROBE All HiZ */
+ GPCR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPCR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPCR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPCR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+}
+
+static inline void spitzkbd_activate_all(void)
+{
+ /* STROBE ALL -> High */
+ GPSR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT;
+ GPSR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT;
+ GPSR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT;
+ GPSR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT;
+
+ udelay(KB_DISCHARGE_DELAY);
+
+ /* Clear any interrupts we may have triggered when altering the GPIO lines */
+ GEDR0 = SPITZ_GPIO_G0_SENSE_BIT;
+ GEDR1 = SPITZ_GPIO_G1_SENSE_BIT;
+ GEDR2 = SPITZ_GPIO_G2_SENSE_BIT;
+ GEDR3 = SPITZ_GPIO_G3_SENSE_BIT;
+}
+
+static inline void spitzkbd_activate_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPSR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline void spitzkbd_reset_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPCR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline int spitzkbd_get_row_status(int col)
+{
+ return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02)
+ | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08)
+ | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60);
+}
+
+/*
+ * The spitz keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs)
+{
+ unsigned int row, col, rowd;
+ unsigned long flags;
+ unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0);
+
+ if (spitzkbd_data->suspended)
+ return;
+
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ if (regs)
+ input_regs(&spitzkbd_data->input, regs);
+
+ num_pressed = 0;
+ for (col = 0; col < KB_COLS; col++) {
+ /*
+ * Discharge the output driver capacitatance
+ * in the keyboard matrix. (Yes it is significant..)
+ */
+
+ spitzkbd_discharge_all();
+ udelay(KB_DISCHARGE_DELAY);
+
+ spitzkbd_activate_col(col);
+ udelay(KB_ACTIVATE_DELAY);
+
+ rowd = spitzkbd_get_row_status(col);
+ for (row = 0; row < KB_ROWS; row++) {
+ unsigned int scancode, pressed;
+
+ scancode = SCANCODE(row, col);
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+
+ if (pressed)
+ num_pressed++;
+ }
+ spitzkbd_reset_col(col);
+ }
+
+ spitzkbd_activate_all();
+
+ input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+ input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+
+ if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
+ input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+ spitzkbd_data->suspend_jiffies = jiffies;
+ }
+
+ input_sync(&spitzkbd_data->input);
+
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+}
+
+/*
+ * spitz keyboard interrupt handler.
+ */
+static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->timer)) {
+ /** wait chattering delay **/
+ udelay(20);
+ spitzkbd_scankeyboard(spitzkbd_data, regs);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * spitz timer checking for released keys
+ */
+static void spitzkbd_timer_callback(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ spitzkbd_scankeyboard(spitzkbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate an interrupt.
+ * We debounce the switches and pass them to the input system.
+ */
+
+static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->htimer))
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ return IRQ_HANDLED;
+}
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void spitzkbd_hinge_timer(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ unsigned long state;
+ unsigned long flags;
+
+ state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+ if (state != sharpsl_hinge_state) {
+ hinge_count = 0;
+ sharpsl_hinge_state = state;
+ } else if (hinge_count < HINGE_STABLE_COUNT) {
+ hinge_count++;
+ }
+
+ if (hinge_count >= HINGE_STABLE_COUNT) {
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+ input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+ input_sync(&spitzkbd_data->input);
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+ } else {
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+ }
+}
+
+#ifdef CONFIG_PM
+static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+ spitzkbd->suspended = 1;
+
+ /* Set Strobe lines as inputs - *except* strobe line 0 leave this
+ enabled so we can detect a power button press for resume */
+ for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+ }
+ return 0;
+}
+
+static int spitzkbd_resume(struct device *dev, uint32_t level)
+{
+ if (level == RESUME_POWER_ON) {
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ spitzkbd->suspend_jiffies = jiffies;
+ spitzkbd->suspended = 0;
+ }
+ return 0;
+}
+#else
+#define spitzkbd_suspend NULL
+#define spitzkbd_resume NULL
+#endif
+
+static int __init spitzkbd_probe(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd;
+
+ spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
+ if (!spitzkbd)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev,spitzkbd);
+ strcpy(spitzkbd->phys, "spitzkbd/input0");
+
+ spin_lock_init(&spitzkbd->lock);
+
+ /* Init Keyboard rescan timer */
+ init_timer(&spitzkbd->timer);
+ spitzkbd->timer.function = spitzkbd_timer_callback;
+ spitzkbd->timer.data = (unsigned long) spitzkbd;
+
+ /* Init Hinge Timer */
+ init_timer(&spitzkbd->htimer);
+ spitzkbd->htimer.function = spitzkbd_hinge_timer;
+ spitzkbd->htimer.data = (unsigned long) spitzkbd;
+
+ spitzkbd->suspend_jiffies=jiffies;
+
+ init_input_dev(&spitzkbd->input);
+ spitzkbd->input.private = spitzkbd;
+ spitzkbd->input.name = "Spitz Keyboard";
+ spitzkbd->input.dev = dev;
+ spitzkbd->input.phys = spitzkbd->phys;
+ spitzkbd->input.id.bustype = BUS_HOST;
+ spitzkbd->input.id.vendor = 0x0001;
+ spitzkbd->input.id.product = 0x0001;
+ spitzkbd->input.id.version = 0x0100;
+ spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ spitzkbd->input.keycode = spitzkbd->keycode;
+ spitzkbd->input.keycodesize = sizeof(unsigned char);
+ spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+
+ memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
+ for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
+ set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit);
+ clear_bit(0, spitzkbd->input.keybit);
+ set_bit(SW_0, spitzkbd->input.swbit);
+ set_bit(SW_1, spitzkbd->input.swbit);
+
+ input_register_device(&spitzkbd->input);
+ mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) {
+ pxa_gpio_mode(spitz_senses[i] | GPIO_IN);
+ if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt,
+ SA_INTERRUPT, "Spitzkbd Sense", spitzkbd))
+ printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i);
+ else
+ set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING);
+ }
+
+ /* Set Strobe lines as outputs - set high */
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN);
+
+ request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd);
+
+ set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE);
+
+ printk(KERN_INFO "input: Spitz Keyboard Registered\n");
+
+ return 0;
+}
+
+static int spitzkbd_remove(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++)
+ free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd);
+
+ free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+
+ del_timer_sync(&spitzkbd->htimer);
+ del_timer_sync(&spitzkbd->timer);
+
+ input_unregister_device(&spitzkbd->input);
+
+ kfree(spitzkbd);
+
+ return 0;
+}
+
+static struct device_driver spitzkbd_driver = {
+ .name = "spitz-keyboard",
+ .bus = &platform_bus_type,
+ .probe = spitzkbd_probe,
+ .remove = spitzkbd_remove,
+ .suspend = spitzkbd_suspend,
+ .resume = spitzkbd_resume,
+};
+
+static int __devinit spitzkbd_init(void)
+{
+ return driver_register(&spitzkbd_driver);
+}
+
+static void __exit spitzkbd_exit(void)
+{
+ driver_unregister(&spitzkbd_driver);
+}
+
+module_init(spitzkbd_init);
+module_exit(spitzkbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Spitz Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0489af5..21d55ed 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -24,17 +24,17 @@ config TOUCHSCREEN_BITSY
module will be called h3600_ts_input.
config TOUCHSCREEN_CORGI
- tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+ tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
depends on PXA_SHARPSL
default y
help
Say Y here to enable the driver for the touchscreen on the
- Sharp SL-C7xx series of PDAs.
+ Sharp SL-C7xx and SL-Cxx00 series of PDAs.
If unsure, say N.
To compile this driver as a module, choose M here: the
- module will be called ads7846_ts.
+ module will be called corgi_ts.
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 5d19261..4c7fbe5 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -1,5 +1,5 @@
/*
- * Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models
*
* Copyright (c) 2004-2005 Richard Purdie
*
@@ -19,7 +19,7 @@
#include <linux/slab.h>
#include <asm/irq.h>
-#include <asm/arch/corgi.h>
+#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -47,15 +47,20 @@ struct corgi_ts {
struct ts_event tc;
int pendown;
int power_mode;
+ int irq_gpio;
+ struct corgits_machinfo *machinfo;
};
-#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
-
-#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#ifdef CONFIG_PXA25x
#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x))
#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x))
-
+#endif
+#ifdef CONFIG_PXA27x
+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
+#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x))
+#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x))
+#endif
/* ADS7846 Touch Screen Controller bit definitions */
#define ADSCTRL_PD0 (1u << 0) /* PD0 */
@@ -66,12 +71,11 @@ struct corgi_ts {
#define ADSCTRL_STS (1u << 7) /* Start Bit */
/* External Functions */
-extern unsigned long w100fb_get_hsynclen(struct device *dev);
extern unsigned int get_clk_frequency_khz(int info);
-static unsigned long calc_waittime(void)
+static unsigned long calc_waittime(struct corgi_ts *corgi_ts)
{
- unsigned long hsync_len = w100fb_get_hsynclen(&corgifb_device.dev);
+ unsigned long hsync_len = corgi_ts->machinfo->get_hsync_len();
if (hsync_len)
return get_clk_frequency_khz(0)*1000/hsync_len;
@@ -79,7 +83,8 @@ static unsigned long calc_waittime(void)
return 0;
}
-static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend,
+ unsigned int address, unsigned long wait_time)
{
unsigned long timer1 = 0, timer2, pmnc = 0;
int pos = 0;
@@ -90,7 +95,7 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
PMNC_SET(0x01);
/* polling HSync */
- SyncHS();
+ corgi_ts->machinfo->wait_hsync();
/* get CCNT */
CCNT(timer1);
}
@@ -109,7 +114,7 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
CCNT(timer2);
if (timer2-timer1 > wait_time) {
/* too slow - timeout, try again */
- SyncHS();
+ corgi_ts->machinfo->wait_hsync();
/* get OSCR */
CCNT(timer1);
/* Wait after HSync */
@@ -133,23 +138,23 @@ static int read_xydata(struct corgi_ts *corgi_ts)
/* critical section */
local_irq_save(flags);
corgi_ssp_ads7846_lock();
- wait_time=calc_waittime();
+ wait_time = calc_waittime(corgi_ts);
/* Y-axis */
- sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time);
/* Y-axis */
- sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time);
/* X-axis */
- y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+ y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time);
/* Z1 */
- x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+ x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time);
/* Z2 */
- z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
- z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+ z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time);
+ z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time);
/* Power-Down Enable */
corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -189,9 +194,9 @@ static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
{
- if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+ if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
/* Disable Interrupt */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
if (read_xydata(corgi_ts)) {
corgi_ts->pendown = 1;
new_data(corgi_ts, regs);
@@ -210,7 +215,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->pendown = 0;
}
}
@@ -254,7 +259,7 @@ static int corgits_resume(struct device *dev, uint32_t level)
corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->power_mode = PWR_MODE_ACTIVE;
}
return 0;
@@ -267,6 +272,7 @@ static int corgits_resume(struct device *dev, uint32_t level)
static int __init corgits_probe(struct device *dev)
{
struct corgi_ts *corgi_ts;
+ struct platform_device *pdev = to_platform_device(dev);
if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
return -ENOMEM;
@@ -275,6 +281,14 @@ static int __init corgits_probe(struct device *dev)
memset(corgi_ts, 0, sizeof(struct corgi_ts));
+ corgi_ts->machinfo = dev->platform_data;
+ corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
+
+ if (corgi_ts->irq_gpio < 0) {
+ kfree(corgi_ts);
+ return -ENODEV;
+ }
+
init_input_dev(&corgi_ts->input);
corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
@@ -293,8 +307,7 @@ static int __init corgits_probe(struct device *dev)
corgi_ts->input.id.product = 0x0002;
corgi_ts->input.id.version = 0x0100;
- pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
- pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+ pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
/* Initiaize ADS7846 Difference Reference mode */
corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -313,14 +326,14 @@ static int __init corgits_probe(struct device *dev)
input_register_device(&corgi_ts->input);
corgi_ts->power_mode = PWR_MODE_ACTIVE;
- if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+ if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
input_unregister_device(&corgi_ts->input);
kfree(corgi_ts);
return -EBUSY;
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
@@ -331,8 +344,9 @@ static int corgits_remove(struct device *dev)
{
struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
- free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+ free_irq(corgi_ts->irq_gpio, NULL);
del_timer_sync(&corgi_ts->timer);
+ corgi_ts->machinfo->put_hsync();
input_unregister_device(&corgi_ts->input);
kfree(corgi_ts);
return 0;
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 8337b0f..4866fc3 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -61,6 +61,7 @@ static const PCI_ENTRY id_list[] =
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
+ {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"},
{0, 0, NULL, NULL},
};
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index c6b5bf7..dc334aa 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -611,7 +611,7 @@ static int sedlbauer_event(event_t event, int priority,
} /* sedlbauer_event */
static struct pcmcia_device_id sedlbauer_ids[] = {
- PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c),
+ PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index 0fda5c8..9ffaae7 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter);
#define __debug_variable st5481_debug
#include "hisax_debug.h"
-#ifdef CONFIG_HISAX_DEBUG
-
extern int st5481_debug;
+#ifdef CONFIG_HISAX_DEBUG
+
#define DBG_ISO_PACKET(level,urb) \
if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 2fcd093..0a2536d 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -172,14 +172,18 @@ static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs)
test_and_clear_bit(buf_nr, &b_out->busy);
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- if (b_out->busy == 0) {
- st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
- }
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(4,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ if (b_out->busy == 0) {
+ st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
+ }
+ break;
}
}
@@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode)
bcs->mode = mode;
// Cancel all USB transfers on this B channel
+ b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(b_out->urb[0]);
+ b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(b_out->urb[1]);
b_out->busy = 0;
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 071b1d3..941f702 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -382,16 +382,20 @@ static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs)
test_and_clear_bit(buf_nr, &d_out->busy);
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- if (d_out->busy == 0) {
- st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
- }
- return;
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ break;
+ default:
+ WARN("urb status %d",urb->status);
+ if (d_out->busy == 0) {
+ st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
+ }
+ break;
}
+ return; // Give up
}
FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
@@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter)
adapter->l1m.fsm = &l1fsm;
adapter->l1m.state = ST_L1_F3;
- adapter->l1m.debug = 1;
+ adapter->l1m.debug = st5481_debug & 0x100;
adapter->l1m.userdata = adapter;
adapter->l1m.printdebug = l1m_debug;
FsmInitTimer(&adapter->l1m, &adapter->timer);
adapter->d_out.fsm.fsm = &dout_fsm;
adapter->d_out.fsm.state = ST_DOUT_NONE;
- adapter->d_out.fsm.debug = 1;
+ adapter->d_out.fsm.debug = st5481_debug & 0x100;
adapter->d_out.fsm.userdata = adapter;
adapter->d_out.fsm.printdebug = dout_debug;
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 7aa810d..2cf5d1a 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -43,10 +43,10 @@ static int number_of_leds = 2; /* 2 LEDs on the adpater default */
module_param(number_of_leds, int, 0);
#ifdef CONFIG_HISAX_DEBUG
-static int debug = 0x1;
+static int debug = 0;
module_param(debug, int, 0);
-int st5481_debug;
#endif
+int st5481_debug;
static LIST_HEAD(adapter_list);
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index ab62223..ffd5b2d 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -132,11 +132,15 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs)
struct ctrl_msg *ctrl_msg;
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ break;
}
}
@@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs)
int status;
switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- DBG(1, "urb shutting down with status: %d", urb->status);
- return;
- default:
- WARN("nonzero urb status received: %d", urb->status);
- goto exit;
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ DBG(2, "urb shutting down with status: %d", urb->status);
+ return;
+ default:
+ WARN("nonzero urb status received: %d", urb->status);
+ goto exit;
}
- DBG_PACKET(1, data, INT_PKT_SIZE);
+ DBG_PACKET(2, data, INT_PKT_SIZE);
if (urb->actual_length == 0) {
goto exit;
@@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
struct urb *urb;
u8 *buf;
- DBG(1,"");
+ DBG(2,"");
if ((status = usb_reset_configuration (dev)) < 0) {
WARN("reset_configuration failed,status=%d",status);
@@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter)
DBG(1,"");
// Stop and free Control and Interrupt URBs
- usb_unlink_urb(ctrl->urb);
+ usb_kill_urb(ctrl->urb);
if (ctrl->urb->transfer_buffer)
kfree(ctrl->urb->transfer_buffer);
usb_free_urb(ctrl->urb);
+ ctrl->urb = NULL;
- usb_unlink_urb(intr->urb);
+ usb_kill_urb(intr->urb);
if (intr->urb->transfer_buffer)
kfree(intr->urb->transfer_buffer);
usb_free_urb(intr->urb);
+ ctrl->urb = NULL;
}
/*
@@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev,
spin_lock_init(&urb->lock);
urb->dev=dev;
urb->pipe=pipe;
+ urb->interval = 1;
urb->transfer_buffer=buf;
urb->number_of_packets = num_packets;
urb->transfer_buffer_length=num_packets*packet_size;
@@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
if (urb[j]) {
if (urb[j]->transfer_buffer)
kfree(urb[j]->transfer_buffer);
+ urb[j]->transfer_buffer = NULL;
usb_free_urb(urb[j]);
+ urb[j] = NULL;
}
}
return retval;
@@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2])
int j;
for (j = 0; j < 2; j++) {
- usb_unlink_urb(urb[j]);
+ usb_kill_urb(urb[j]);
if (urb[j]->transfer_buffer)
kfree(urb[j]->transfer_buffer);
usb_free_urb(urb[j]);
+ urb[j] = NULL;
}
}
@@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs)
int len, count, status;
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ break;
}
}
@@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode)
in->mode = mode;
+ in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(in->urb[0]);
+ in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(in->urb[1]);
if (in->mode != L1_MODE_NULL) {
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 40b0df0..1ebed04 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -87,7 +87,7 @@ static int __init sc_init(void)
*/
for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) {
if(!request_region(io[b] + i * 0x400, 1, "sc test")) {
- pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400);
+ pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
io[b] = 0;
break;
} else
@@ -181,7 +181,7 @@ static int __init sc_init(void)
for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) {
pr_debug("Checking RAM address 0x%x...\n", i);
if(request_region(i, SRAM_PAGESIZE, "sc test")) {
- pr_debug(" check_region succeeded\n");
+ pr_debug(" request_region succeeded\n");
model = identify_board(i, io[b]);
release_region(i, SRAM_PAGESIZE);
if (model >= 0) {
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h
index f80ee63..31cbee7 100644
--- a/drivers/md/raid6.h
+++ b/drivers/md/raid6.h
@@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE];
#define __init
#define __exit
#define __attribute_const__ __attribute__((const))
+#define noinline __attribute__((noinline))
#define preempt_enable()
#define preempt_disable()
+#define cpu_has_feature(x) 1
+#define enable_kernel_altivec()
+#define disable_kernel_altivec()
#endif /* __KERNEL__ */
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
index acf386f..51c63c0 100644
--- a/drivers/md/raid6algos.c
+++ b/drivers/md/raid6algos.c
@@ -19,6 +19,7 @@
#include "raid6.h"
#ifndef __KERNEL__
#include <sys/mman.h>
+#include <stdio.h>
#endif
struct raid6_calls raid6_call;
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
index 1de8f03..b9afd35 100644
--- a/drivers/md/raid6altivec.uc
+++ b/drivers/md/raid6altivec.uc
@@ -27,16 +27,20 @@
#ifdef CONFIG_ALTIVEC
#include <altivec.h>
-#include <asm/system.h>
-#include <asm/cputable.h>
+#ifdef __KERNEL__
+# include <asm/system.h>
+# include <asm/cputable.h>
+#endif
/*
- * This is the C data type to use
+ * This is the C data type to use. We use a vector of
+ * signed char so vec_cmpgt() will generate the right
+ * instruction.
*/
-typedef vector unsigned char unative_t;
+typedef vector signed char unative_t;
-#define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
+#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
#define NSIZE sizeof(unative_t)
/*
@@ -108,7 +112,11 @@ int raid6_have_altivec(void);
int raid6_have_altivec(void)
{
/* This assumes either all CPUs have Altivec or none does */
+# ifdef __KERNEL__
return cpu_has_feature(CPU_FTR_ALTIVEC);
+# else
+ return 1;
+# endif
}
#endif
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile
index 5578067..78e0396 100644
--- a/drivers/md/raid6test/Makefile
+++ b/drivers/md/raid6test/Makefile
@@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired
CFLAGS = -I.. -g $(OPTFLAGS)
LD = ld
PERL = perl
+AR = ar
+RANLIB = ranlib
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
@@ -18,18 +20,33 @@ PERL = perl
%.uc: ../%.uc
cp -f $< $@
-all: raid6.o raid6test
+all: raid6.a raid6test
-raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
+raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
raid6int32.o \
raid6mmx.o raid6sse1.o raid6sse2.o \
+ raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \
raid6recov.o raid6algos.o \
raid6tables.o
- $(LD) -r -o $@ $^
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
-raid6test: raid6.o test.c
+raid6test: test.c raid6.a
$(CC) $(CFLAGS) -o raid6test $^
+raid6altivec1.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@
+
+raid6altivec2.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@
+
+raid6altivec4.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@
+
+raid6altivec8.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@
+
raid6int1.c: raid6int.uc ../unroll.pl
$(PERL) ../unroll.pl 1 < raid6int.uc > $@
@@ -52,7 +69,7 @@ raid6tables.c: mktables
./mktables > raid6tables.c
clean:
- rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test
+ rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test
spotless: clean
rm -f *~
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 8b4ad70..877c770 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 013c835..5319a9c 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -26,7 +26,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 53d399b..022913d 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 202bfe6..6418f03 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -17,7 +17,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index c00245d..b2256d6 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -10,7 +10,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 3a464a0..6f03ce4 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -18,7 +18,7 @@
#include <linux/kernel.h> /* __setup */
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/isapnp.h>
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 0732efd..71971e9 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -14,7 +14,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 248d67f..b03573c 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -25,7 +25,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index d7da901..f304f3c 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -31,7 +31,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/proc_fs.h> /* radio card status report */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 342f92d..4c6d6fb 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -28,7 +28,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay, msleep */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index c9106b1..4334744 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -221,9 +221,7 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe,
int err;
/* Put the analog decoder in standby to keep it quiet */
- if (core->tda9887_conf) {
- cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
- }
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
@@ -402,6 +400,9 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
}
+ /* Put the analog decoder in standby to keep it quiet */
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
/* register everything */
return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
index d15da6f..b7f093f 100644
--- a/drivers/mtd/maps/sharpsl-flash.c
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -82,7 +82,7 @@ int __init init_sharpsl(void)
} else if (machine_is_tosa()) {
sharpsl_partitions[0].size=0x006a0000;
sharpsl_partitions[0].offset=0x00160000;
- } else if (machine_is_spitz()) {
+ } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) {
sharpsl_partitions[0].size=0x006b0000;
sharpsl_partitions[0].offset=0x00140000;
} else {
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 9853b87..88b5b5b 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -221,10 +221,16 @@ sharpsl_nand_init(void)
sharpsl_partition_info[1].size=25 * 1024 * 1024;
} else if (machine_is_husky()) {
sharpsl_partition_info[1].size=53 * 1024 * 1024;
- }
+ } else if (machine_is_spitz()) {
+ sharpsl_partition_info[1].size=5 * 1024 * 1024;
+ } else if (machine_is_akita()) {
+ sharpsl_partition_info[1].size=58 * 1024 * 1024;
+ } else if (machine_is_borzoi()) {
+ sharpsl_partition_info[1].size=32 * 1024 * 1024;
+ }
}
- if (machine_is_husky()) {
+ if (machine_is_husky() || machine_is_borzoi()) {
/* Need to use small eraseblock size for backward compatibility */
sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS;
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 34b80de..bc53744 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -353,8 +353,6 @@ struct cp_private {
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
- struct cp_dma_stats *nic_stats;
- dma_addr_t nic_stats_dma;
unsigned rx_tail ____cacheline_aligned;
struct cp_desc *rx_ring;
@@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp)
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
- mem += (CP_RING_BYTES - CP_STATS_SIZE);
- cp->nic_stats = mem;
- cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);
-
return cp_init_rings(cp);
}
@@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp)
pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
cp->rx_ring = NULL;
cp->tx_ring = NULL;
- cp->nic_stats = NULL;
}
static int cp_open (struct net_device *dev)
@@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
struct cp_private *cp = netdev_priv(dev);
+ struct cp_dma_stats *nic_stats;
+ dma_addr_t dma;
int i;
- memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
+ nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma);
+ if (!nic_stats)
+ return;
/* begin NIC statistics dump */
- cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
- cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
+ cpw32(StatsAddr + 4, (u64)dma >> 32);
+ cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats);
cpr32(StatsAddr);
for (i = 0; i < 1000; i++) {
@@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev,
}
cpw32(StatsAddr, 0);
cpw32(StatsAddr + 4, 0);
+ cpr32(StatsAddr);
i = 0;
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
if (i != CP_NUM_STATS)
BUG();
+
+ pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}
static struct ethtool_ops cp_ethtool_ops = {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 54fff9c..96f14ab 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1951,7 +1951,7 @@ config SKGE
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
and related Gigabit Ethernet adapters. It is a new smaller driver
- driver with better performance and more complete ethtool support.
+ with better performance and more complete ethtool support.
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 52c77cb..1f03027 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -160,7 +160,7 @@ static int __init com90io_probe(struct net_device *dev)
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
- BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n",
+ BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
@@ -242,7 +242,7 @@ static int __init com90io_found(struct net_device *dev)
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
- /* Reserve the I/O region - guaranteed to work by check_region */
+ /* Reserve the I/O region */
if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
free_irq(dev->irq, dev);
return -EBUSY;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 94c9f68..90449a0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2879,6 +2879,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
* This target is not on a VLAN
*/
if (rt->u.dst.dev == bond->dev) {
+ ip_rt_put(rt);
dprintk("basa: rtdev == bond->dev: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
@@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
}
if (vlan_id) {
+ ip_rt_put(rt);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
vlan->vlan_ip, vlan_id);
continue;
@@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
bond->dev->name, NIPQUAD(fl.fl4_dst),
rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
}
+ ip_rt_put(rt);
}
}
@@ -5036,6 +5039,14 @@ static int __init bonding_init(void)
return 0;
out_err:
+ /*
+ * rtnl_unlock() will run netdev_run_todo(), putting the
+ * thus-far-registered bonding devices into a state which
+ * unregigister_netdevice() will accept
+ */
+ rtnl_unlock();
+ rtnl_lock();
+
/* free and unregister all bonds that were successfully added */
bond_free_all();
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 25cc20e..fbf1c06 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1387,13 +1387,13 @@ static void e100_update_stats(struct nic *nic)
ns->collisions += nic->tx_collisions;
ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
le32_to_cpu(s->tx_lost_crs);
- ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
nic->rx_over_length_errors;
ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+ ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
le32_to_cpu(s->rx_alignment_errors) +
le32_to_cpu(s->rx_short_frame_errors) +
@@ -1727,12 +1727,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
if(unlikely(!(rfd_status & cb_ok))) {
/* Don't indicate if hardware indicates errors */
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
nic->rx_over_length_errors++;
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else {
nic->net_stats.rx_packets++;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 7c8a0a2..ee687c9 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2544,7 +2544,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.rlec + adapter->stats.mpc +
adapter->stats.cexterr;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 5c55537..89d6d69 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1616,8 +1616,6 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
adapter->stats.icbc +
adapter->stats.ecbc + adapter->stats.mpc;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
-
/* see above
* adapter->net_stats.rx_length_errors = adapter->stats.rlec;
*/
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c829e6a..dd451e0 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -428,7 +428,7 @@ static int init_shared_mem(struct s2io_nic *nic)
DBG_PRINT(INIT_DBG,
"%s: Zero DMA address for TxDL. ", dev->name);
DBG_PRINT(INIT_DBG,
- "Virtual address %llx\n", (u64)tmp_v);
+ "Virtual address %p\n", tmp_v);
tmp_v = pci_alloc_consistent(nic->pdev,
PAGE_SIZE, &tmp_p);
if (!tmp_v) {
@@ -657,9 +657,10 @@ static void free_shared_mem(struct s2io_nic *nic)
mac_control->zerodma_virt_addr,
(dma_addr_t)0);
DBG_PRINT(INIT_DBG,
- "%s: Freeing TxDL with zero DMA addr. ", dev->name);
- DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
- (u64)(mac_control->zerodma_virt_addr));
+ "%s: Freeing TxDL with zero DMA addr. ",
+ dev->name);
+ DBG_PRINT(INIT_DBG, "Virtual address %p\n",
+ mac_control->zerodma_virt_addr);
}
kfree(mac_control->fifos[i].list_info);
}
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 6ee4771..2e72d79 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5216,17 +5216,15 @@ static struct pci_device_id skge_pci_tbl[] = {
{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+/* DLink card does not have valid VPD so this driver gags
+ * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ */
{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
- { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0, }
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index d7c9851..0208258 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.9"
+#define DRV_VERSION "1.0"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
PHY_M_LED_BLINK_RT(BLINK_84MS) |
PHY_M_LEDC_TX_CTRL |
PHY_M_LEDC_DP_CTRL);
-
+
gm_phy_write(hw, port, PHY_MARV_LED_OVER,
PHY_M_LED_MO_RX(MO_LED_OFF) |
(skge->speed == SPEED_100 ?
@@ -876,7 +876,7 @@ static int skge_rx_fill(struct skge_port *skge)
static void skge_link_up(struct skge_port *skge)
{
- skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
netif_carrier_on(skge->netdev);
@@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
{
const u8 zero[8] = { 0 };
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
/* reset the statistics module */
xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
@@ -1021,8 +1023,6 @@ static void bcom_check_link(struct skge_hw *hw, int port)
(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
status = xm_phy_read(hw, port, PHY_BCOM_STAT);
- pr_debug("bcom_check_link status=0x%x\n", status);
-
if ((status & PHY_ST_LSYNC) == 0) {
u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1106,8 +1106,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
};
- pr_debug("bcom_phy_init\n");
-
/* read Id from external PHY (all have the same address) */
id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
@@ -1340,6 +1338,8 @@ static void genesis_stop(struct skge_port *skge)
int port = skge->port;
u32 reg;
+ genesis_reset(hw, port);
+
/* Clear Tx packet arbiter timeout IRQ */
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@@ -1465,7 +1465,6 @@ static void genesis_link_up(struct skge_port *skge)
u16 cmd;
u32 mode, msk;
- pr_debug("genesis_link_up\n");
cmd = xm_read16(hw, port, XM_MMU_CMD);
/*
@@ -1578,7 +1577,6 @@ static void yukon_init(struct skge_hw *hw, int port)
struct skge_port *skge = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv;
- pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
@@ -1677,9 +1675,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* hard reset */
skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@@ -1687,10 +1687,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
- & ~GP_IO_9);
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9;
+ reg &= ~GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* Set hardware config mode */
reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
@@ -1729,7 +1731,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
}
gma_write16(hw, port, GM_GP_CTRL, reg);
- skge_read16(hw, GMAC_IRQ_SRC);
+ skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
yukon_init(hw, port);
@@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port *skge)
struct skge_hw *hw = skge->hw;
int port = skge->port;
- if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
- skge_write32(hw, B2_GP_IO,
- skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
- }
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+ yukon_reset(hw, port);
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ u32 io = skge_read32(hw, B2_GP_IO);
+
+ io |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, io);
+ skge_read32(hw, B2_GP_IO);
+ }
+
/* set GPHY Control reset */
- skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
- skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+ skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1873,10 +1881,8 @@ static void yukon_link_up(struct skge_port *skge)
int port = skge->port;
u16 reg;
- pr_debug("yukon_link_up\n");
-
/* Enable Transmit FIFO Underrun */
- skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@@ -1896,7 +1902,6 @@ static void yukon_link_down(struct skge_port *skge)
int port = skge->port;
u16 ctrl;
- pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
ctrl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2112,7 +2117,6 @@ static int skge_up(struct net_device *dev)
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
- pr_debug("skge_up completed\n");
return 0;
free_rx_ring:
@@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_stop(skge);
+ else
+ yukon_stop(skge);
+
+ hw->intr_mask &= ~portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
RB_RST_SET|RB_DIS_OP_MD);
- if (hw->chip_id == CHIP_ID_GENESIS)
- genesis_stop(skge);
- else
- yukon_stop(skge);
/* Disable Force Sync bit and Enable Alloc bit */
skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct net_device *dev)
u32 mode;
u8 filter[8];
- pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
-
mode = xm_read32(hw, port, XM_MODE);
mode |= XM_MD_ENA_HASH;
if (dev->flags & IFF_PROMISC)
@@ -2530,8 +2537,6 @@ static int skge_poll(struct net_device *dev, int *budget)
unsigned int to_do = min(dev->quota, *budget);
unsigned int work_done = 0;
- pr_debug("skge_poll\n");
-
for (e = ring->to_clean; work_done < to_do; e = e->next) {
struct skge_rx_desc *rd = e->desc;
struct sk_buff *skb;
@@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_hw *hw)
if (hw->chip_id == CHIP_ID_GENESIS) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
} else {
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
@@ -3000,9 +3005,6 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B0_IMSK, hw->intr_mask);
- if (hw->chip_id != CHIP_ID_GENESIS)
- skge_write8(hw, GMAC_IRQ_MSK, 0);
-
spin_lock_bh(&hw->phy_lock);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct pci_dev *pdev)
dev0 = hw->dev[0];
unregister_netdev(dev0);
+ skge_write32(hw, B0_IMSK, 0);
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_pci_clear(hw);
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+
tasklet_kill(&hw->ext_tasklet);
free_irq(pdev->irq, hw);
@@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
if (dev1)
free_netdev(dev1);
free_netdev(dev0);
- skge_write16(hw, B0_LED, LED_STAT_OFF);
+
iounmap(hw->regs);
kfree(hw);
pci_set_drvdata(pdev, NULL);
@@ -3257,7 +3264,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
netif_carrier_off(dev);
- skge_down(dev);
+ if (skge->wol)
+ netif_stop_queue(dev);
+ else
+ skge_down(dev);
}
netif_device_detach(dev);
wol |= skge->wol;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index f1680be..efbf98c 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2008,7 +2008,7 @@ enum {
GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
/* Bits 15.. 2: reserved */
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 4e19220..c796f41 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1817,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_card *card)
/* LEDs active in both modes, autosense prio = fiber */
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
+ /* switch off fibre autoneg */
+ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
+ spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+
phy->def->ops->read_link(phy);
pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
phy->speed, phy->duplex==1 ? "Full" : "Half");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7599f52..81f4aed 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -67,8 +67,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.39"
-#define DRV_MODULE_RELDATE "September 5, 2005"
+#define DRV_MODULE_VERSION "3.40"
+#define DRV_MODULE_RELDATE "September 15, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -3442,31 +3442,47 @@ static void tg3_tx_timeout(struct net_device *dev)
schedule_work(&tp->reset_task);
}
+/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */
+static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
+{
+ u32 base = (u32) mapping & 0xffffffff;
+
+ return ((base > 0xffffdcc0) &&
+ (base + len + 8 < base));
+}
+
static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
- u32 guilty_entry, int guilty_len,
- u32 last_plus_one, u32 *start, u32 mss)
+ u32 last_plus_one, u32 *start,
+ u32 base_flags, u32 mss)
{
struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
- dma_addr_t new_addr;
+ dma_addr_t new_addr = 0;
u32 entry = *start;
- int i;
+ int i, ret = 0;
if (!new_skb) {
- dev_kfree_skb(skb);
- return -1;
+ ret = -1;
+ } else {
+ /* New SKB is guaranteed to be linear. */
+ entry = *start;
+ new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
+ PCI_DMA_TODEVICE);
+ /* Make sure new skb does not cross any 4G boundaries.
+ * Drop the packet if it does.
+ */
+ if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ ret = -1;
+ dev_kfree_skb(new_skb);
+ new_skb = NULL;
+ } else {
+ tg3_set_txd(tp, entry, new_addr, new_skb->len,
+ base_flags, 1 | (mss << 1));
+ *start = NEXT_TX(entry);
+ }
}
- /* New SKB is guaranteed to be linear. */
- entry = *start;
- new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
- PCI_DMA_TODEVICE);
- tg3_set_txd(tp, entry, new_addr, new_skb->len,
- (skb->ip_summed == CHECKSUM_HW) ?
- TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
- *start = NEXT_TX(entry);
-
/* Now clean up the sw ring entries. */
i = 0;
while (entry != last_plus_one) {
@@ -3491,7 +3507,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
dev_kfree_skb(skb);
- return 0;
+ return ret;
}
static void tg3_set_txd(struct tg3 *tp, int entry,
@@ -3517,19 +3533,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
}
-static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
-{
- u32 base = (u32) mapping & 0xffffffff;
-
- return ((base > 0xffffdcc0) &&
- (base + len + 8 < base));
-}
-
static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
dma_addr_t mapping;
- unsigned int i;
u32 len, entry, base_flags, mss;
int would_hit_hwbug;
@@ -3624,7 +3631,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
would_hit_hwbug = 0;
if (tg3_4g_overflow_test(mapping, len))
- would_hit_hwbug = entry + 1;
+ would_hit_hwbug = 1;
tg3_set_txd(tp, entry, mapping, len, base_flags,
(skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
@@ -3648,12 +3655,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
tp->tx_buffers[entry].skb = NULL;
pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
- if (tg3_4g_overflow_test(mapping, len)) {
- /* Only one should match. */
- if (would_hit_hwbug)
- BUG();
- would_hit_hwbug = entry + 1;
- }
+ if (tg3_4g_overflow_test(mapping, len))
+ would_hit_hwbug = 1;
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
tg3_set_txd(tp, entry, mapping, len,
@@ -3669,34 +3672,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (would_hit_hwbug) {
u32 last_plus_one = entry;
u32 start;
- unsigned int len = 0;
-
- would_hit_hwbug -= 1;
- entry = entry - 1 - skb_shinfo(skb)->nr_frags;
- entry &= (TG3_TX_RING_SIZE - 1);
- start = entry;
- i = 0;
- while (entry != last_plus_one) {
- if (i == 0)
- len = skb_headlen(skb);
- else
- len = skb_shinfo(skb)->frags[i-1].size;
- if (entry == would_hit_hwbug)
- break;
-
- i++;
- entry = NEXT_TX(entry);
-
- }
+ start = entry - 1 - skb_shinfo(skb)->nr_frags;
+ start &= (TG3_TX_RING_SIZE - 1);
/* If the workaround fails due to memory/mapping
* failure, silently drop this packet.
*/
- if (tigon3_4gb_hwbug_workaround(tp, skb,
- entry, len,
- last_plus_one,
- &start, mss))
+ if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one,
+ &start, base_flags, mss))
goto out_unlock;
entry = start;
@@ -9271,6 +9255,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
static struct pci_device_id write_reorder_chipsets[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_K8_NB) },
{ },
};
u32 misc_ctrl_reg;
@@ -9285,7 +9271,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
#endif
- /* If we have an AMD 762 chipset, write
+ /* If we have an AMD 762 or K8 chipset, write
* reordering to the mailbox registers done by the host
* controller can cause major troubles. We read back from
* every mailbox register write to force the writes to be
@@ -9532,7 +9518,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->write32_rx_mbox = tg3_write_indirect_mbox;
iounmap(tp->regs);
- tp->regs = 0;
+ tp->regs = NULL;
pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
pci_cmd &= ~PCI_COMMAND_MEMORY;
@@ -10680,7 +10666,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
err_out_iounmap:
if (tp->regs) {
iounmap(tp->regs);
- tp->regs = 0;
+ tp->regs = NULL;
}
err_out_free_dev:
@@ -10705,7 +10691,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
unregister_netdev(dev);
if (tp->regs) {
iounmap(tp->regs);
- tp->regs = 0;
+ tp->regs = NULL;
}
free_netdev(dev);
pci_release_regions(pdev);
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 26cc4f6..60d1e05 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -117,7 +117,7 @@ static int xircom_open(struct net_device *dev);
static int xircom_close(struct net_device *dev);
static void xircom_up(struct xircom_private *card);
static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-#if CONFIG_NET_POLL_CONTROLLER
+#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev);
#endif
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 48c03c1..a01efa6 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
}
skb_reserve(skb, 4);
cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
- data = (cisco_packet*)skb->data;
+ data = (cisco_packet*)(skb->data + 4);
data->type = htonl(type);
data->par1 = htonl(par1);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2be65d3..06998c2 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -6852,7 +6852,10 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
- iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+ /* iwe.u.freq.m containt the channel (starting 1), our
+ * frequency_list array start at index 0...
+ */
+ iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d1fb1ba..bedd7f9f 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -629,6 +629,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+ PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index 8122fe7..b1ba429 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -558,7 +558,7 @@ static int configure_device (struct pci_func *func)
pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
- pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
+ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
return 0;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 0e09476..898f6da 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -2526,7 +2526,6 @@ configure_new_function(struct controller *ctrl, struct pci_func *func,
int cloop;
u8 temp_byte;
u8 class_code;
- u16 temp_word;
u32 rc;
u32 temp_register;
u32 base;
@@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func,
} /* End of base register loop */
/* disable ROM base Address */
- temp_word = 0x00L;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+ rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
/* Set HP parameters (Cache Line Size, Latency Timer) */
rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 783b5ab..91c9903 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -2824,8 +2824,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f
}
#endif
/* Disable ROM base Address */
- temp_word = 0x00L;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+ rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
/* Set HP parameters (Cache Line Size, Latency Timer) */
rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 992db89..259d247 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -309,17 +309,25 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
- /* If we're in D3, force entire word to 0.
+ /* If we're (effectively) in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
- if (dev->current_state >= PCI_D3hot) {
- if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+ switch (dev->current_state) {
+ case PCI_UNKNOWN: /* Boot-up */
+ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
+ && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
need_restore = 1;
+ /* Fall-through: force to D0 */
+ case PCI_D3hot:
+ case PCI_D3cold:
+ case PCI_POWER_ERROR:
pmcsr = 0;
- } else {
+ break;
+ default:
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
pmcsr |= state;
+ break;
}
/* enter specified state */
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 39ba640..80969f7 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -376,6 +376,7 @@ static int ds_open(struct inode *inode, struct file *file)
socket_t i = iminor(inode);
struct pcmcia_socket *s;
user_info_t *user;
+ static int warning_printed = 0;
ds_dbg(0, "ds_open(socket %d)\n", i);
@@ -407,6 +408,17 @@ static int ds_open(struct inode *inode, struct file *file)
s->user = user;
file->private_data = user;
+ if (!warning_printed) {
+ printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
+ "usage.\n");
+ printk(KERN_INFO "pcmcia: This interface will soon be removed from "
+ "the kernel; please expect breakage unless you upgrade "
+ "to new tools.\n");
+ printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
+ "utils/kernel/pcmcia/pcmcia.html for details.\n");
+ warning_printed = 1;
+ }
+
if (s->pcmcia_state.present)
queue_event(user, CS_EVENT_CARD_INSERTION);
return 0;
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index f0997c3..ba4d78e 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1045,7 +1045,18 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
{
struct yenta_socket *socket;
int ret;
-
+
+ /*
+ * If we failed to assign proper bus numbers for this cardbus
+ * controller during PCI probe, its subordinate pci_bus is NULL.
+ * Bail out if so.
+ */
+ if (!dev->subordinate) {
+ printk(KERN_ERR "Yenta: no bus associated with %s! "
+ "(try 'pci=assign-busses')\n", pci_name(dev));
+ return -ENODEV;
+ }
+
socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
if (!socket)
return -ENOMEM;
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index aac83ce..a1c52a6 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.34 $
+ * $Revision: 1.35 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -35,7 +35,7 @@
*/
/* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
(8*sizeof(long)))
static unsigned long bl_dev[__BL_DEV_WORDS];
typedef enum {add, free} range_action;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 6aeef3b..0cb47ec 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -682,9 +682,6 @@ z90crypt_cleanup_module(void)
del_timer(&config_timer);
del_timer(&cleanup_timer);
- if (z90_device_work)
- destroy_workqueue(z90_device_work);
-
destroy_z90crypt();
PRINTKN("Unloaded.\n");
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 96ca863..0db4f57 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
+ * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
*
* CTC / ESCON network driver
*
@@ -37,10 +37,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
*
*/
-
#undef DEBUG
#include <linux/module.h>
#include <linux/init.h>
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
"TX down",
"Restart",
};
-
+
/**
* Events of the channel statemachine
*/
@@ -249,7 +248,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.74 $";
+ char vbuf[] = "$Revision: 1.78 $";
char *version = vbuf;
if (printed)
@@ -334,7 +333,7 @@ static const char *ch_state_names[] = {
"Restarting",
"Not operational",
};
-
+
#ifdef DEBUG
/**
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
@@ -671,7 +670,7 @@ static void
fsm_action_nop(fsm_instance * fi, int event, void *arg)
{
}
-
+
/**
* Actions for channel - statemachines.
*****************************************************************************/
@@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg)
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
}
-
/**
* The statemachine for a channel.
*/
@@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = {
};
static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
-
+
/**
* Functions related to setup and device detection.
*****************************************************************************/
@@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
}
-
+
/**
* Actions for interface - statemachine.
*****************************************************************************/
@@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
int rc = 0;
DBF_TEXT(trace, 5, __FUNCTION__);
+ /* we need to acquire the lock for testing the state
+ * otherwise we can have an IRQ changing the state to
+ * TXIDLE after the test but before acquiring the lock.
+ */
+ spin_lock_irqsave(&ch->collect_lock, saveflags);
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
int l = skb->len + LL_HEADER_LENGTH;
- spin_lock_irqsave(&ch->collect_lock, saveflags);
- if (ch->collect_len + l > ch->max_bufsize - 2)
- rc = -EBUSY;
- else {
+ if (ch->collect_len + l > ch->max_bufsize - 2) {
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+ return -EBUSY;
+ } else {
atomic_inc(&skb->users);
header.length = l;
header.type = skb->protocol;
@@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
int ccw_idx;
struct sk_buff *nskb;
unsigned long hi;
-
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
/**
* Protect skb against beeing free'd by upper
* layers.
@@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
if (!nskb) {
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -ENOMEM;
} else {
memcpy(skb_put(nskb, skb->len),
@@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
*/
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -EBUSY;
}
@@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
}
}
+ ctc_clear_busy(ch->netdev);
return rc;
}
-
+
/**
* Interface API for upper network layers
*****************************************************************************/
@@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
dev->trans_start = jiffies;
if (transmit_skb(privptr->channel[WRITE], skb) != 0)
rc = 1;
- ctc_clear_busy(dev);
return rc;
}
@@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf,
return count;
}
-
static void
ctc_netdev_unregister(struct net_device * dev)
{
@@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
return count;
}
-
static ssize_t
ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 3a02856..2ad4797 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.139 $"
+#define VERSION_QETH_H "$Revision: 1.142 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -1172,7 +1172,7 @@ extern int
qeth_realloc_buffer_pool(struct qeth_card *, int);
extern int
-qeth_set_large_send(struct qeth_card *);
+qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
extern void
qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 79c74f3..86582cf 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
+ * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,14 +29,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/***
- * eye catcher; just for debugging purposes
- */
-void volatile
-qeth_eyecatcher(void)
-{
- return;
-}
#include <linux/config.h>
#include <linux/module.h>
@@ -80,7 +72,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.214 $"
+#define VERSION_QETH_C "$Revision: 1.224 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
queue->card->perf_stats.outbound_do_qdio_start_time;
#endif
if (rc){
- QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO "
- "returned error (%i) on device %s.",
- rc, CARD_DDEV_ID(queue->card));
QETH_DBF_TEXT(trace, 2, "flushbuf");
QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
queue->card->stats.tx_errors += count;
/* this must not happen under normal circumstances. if it
* happens something is really wrong -> recover */
@@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
QETH_DBF_TEXT(trace, 6, "qdouhdl");
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
- QETH_DBF_SPRINTF(trace, 2, "On device %s: "
- "received active check "
- "condition (0x%08x).",
- CARD_BUS_ID(card), status);
- QETH_DBF_TEXT(trace, 2, "chkcond");
+ QETH_DBF_TEXT(trace, 2, "achkcond");
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(trace, 2, "%08x", status);
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
@@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *channel)
static int
qeth_halt_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"haltchs");
- if ((rc = qeth_halt_channel(&card->read)))
- return rc;
- if ((rc = qeth_halt_channel(&card->write)))
- return rc;
- return qeth_halt_channel(&card->data);
+ rc1 = qeth_halt_channel(&card->read);
+ rc2 = qeth_halt_channel(&card->write);
+ rc3 = qeth_halt_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
qeth_clear_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"clearchs");
- if ((rc = qeth_clear_channel(&card->read)))
- return rc;
- if ((rc = qeth_clear_channel(&card->write)))
- return rc;
- return qeth_clear_channel(&card->data);
+ rc1 = qeth_clear_channel(&card->read);
+ rc2 = qeth_clear_channel(&card->write);
+ rc3 = qeth_clear_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
@@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *card)
}
if ((rc = qeth_cm_enable(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_cm_setup(card))){
QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_enable(card))){
QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_setup(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_alloc_qdio_buffers(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_qdio_establish(card))){
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
@@ -3795,12 +3788,16 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
+ int rc;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
+ rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
+ if (rc)
+ return rc;
#ifdef CONFIG_QETH_VLAN
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
((ipv == 6) || card->options.layer2) ) {
@@ -4251,7 +4248,8 @@ out:
}
static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
+ struct sk_buff *skb, int elems)
{
int elements_needed = 0;
@@ -4261,9 +4259,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
if (elements_needed == 0 )
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ skb->len) >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
+ "IP packet (Number=%d / Length=%d). Discarded.\n",
+ (elements_needed+elems), skb->len);
return 0;
}
return elements_needed;
@@ -4275,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
int ipv = 0;
int cast_type;
struct qeth_qdio_out_q *queue;
- struct qeth_hdr *hdr;
+ struct qeth_hdr *hdr = NULL;
int elements_needed = 0;
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
@@ -4337,9 +4336,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
return -EINVAL;
}
} else {
- elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
- if (!elements_needed)
+ int elems = qeth_get_elements_no(card,(void*) hdr, skb,
+ elements_needed);
+ if (!elems)
return -EINVAL;
+ elements_needed += elems;
}
if (card->info.type != QETH_CARD_TYPE_IQD)
@@ -4504,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
QETH_DBF_TEXT(trace,3,"arpstnoe");
- /* TODO: really not supported by GuestLAN? */
+ /*
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan)
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -4681,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, char *udata)
QETH_DBF_TEXT(trace,3,"arpquery");
- /*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
- /*if (card->info.guestlan)
- return -EOPNOTSUPP; */
if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
IPA_ARP_PROCESSING)) {
PRINT_WARN("ARP processing not supported "
@@ -4894,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
QETH_DBF_TEXT(trace,3,"arpadent");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4937,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry
QETH_DBF_TEXT(trace,3,"arprment");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4978,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *card)
QETH_DBF_TEXT(trace,3,"arpflush");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -7038,14 +7032,16 @@ qeth_setrouting_v6(struct qeth_card *card)
}
int
-qeth_set_large_send(struct qeth_card *card)
+qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
{
int rc = 0;
- if (card->dev == NULL)
+ if (card->dev == NULL) {
+ card->options.large_send = type;
return 0;
-
+ }
netif_stop_queue(card->dev);
+ card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
@@ -7066,7 +7062,6 @@ qeth_set_large_send(struct qeth_card *card)
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
break;
}
-
netif_wake_queue(card->dev);
return rc;
}
@@ -8257,7 +8252,6 @@ qeth_init(void)
{
int rc=0;
- qeth_eyecatcher();
PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
version, VERSION_QETH_C, VERSION_QETH_H,
VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
@@ -8338,7 +8332,6 @@ again:
printk("qeth: removed\n");
}
-EXPORT_SYMBOL(qeth_eyecatcher);
module_init(qeth_init);
module_exit(qeth_exit);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 98bedb0..dda105b 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
/*****************************************************************************/
/* */
@@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c
if (!card)
return -EINVAL;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+ return -EPERM;
+ }
if (((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) ||
- (card->info.type != QETH_CARD_TYPE_OSAE))
+ (card->state != CARD_STATE_RECOVER)))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
@@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
if (!card)
return -EINVAL;
-
tmp = strsep((char **) &buf, "\n");
-
if (!strcmp(tmp, "no")){
type = QETH_LARGE_SEND_NO;
} else if (!strcmp(tmp, "EDDP")) {
@@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
}
if (card->options.large_send == type)
return count;
- card->options.large_send = type;
- if ((rc = qeth_set_large_send(card)))
+ if ((rc = qeth_set_large_send(card, type)))
return rc;
-
return count;
}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index dbad7f3..24ed589 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -14,7 +14,7 @@
#include <linux/major.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
-#include <linux/ioport.h> /* request_region, check_region */
+#include <linux/ioport.h> /* request_region */
#include <asm/atomic.h>
#include <asm/ebus.h> /* EBus device */
#include <asm/oplib.h> /* OpenProm Library */
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 5cc53cd..d92273c 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
*
* LOCKING:
* None. (executing in kernel thread context)
+ *
+ * RETURNS:
+ * Non-zero if qc completed, zero otherwise.
*/
-static void ata_pio_complete (struct ata_port *ap)
+static int ata_pio_complete (struct ata_port *ap)
{
struct ata_queued_cmd *qc;
u8 drv_stat;
@@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap)
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
ap->pio_task_state = PIO_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
- return;
+ return 0;
}
}
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
ap->pio_task_state = PIO_ST_ERR;
- return;
+ return 0;
}
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap)
ap->pio_task_state = PIO_ST_IDLE;
ata_poll_qc_complete(qc, drv_stat);
+
+ /* another command may start at this point */
+
+ return 1;
}
@@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
next_sg:
if (unlikely(qc->cursg >= qc->n_elem)) {
- /*
+ /*
* The end of qc->sg is reached and the device expects
* more data to transfer. In order not to overrun qc->sg
* and fulfill length specified in the byte count register,
@@ -2721,7 +2728,7 @@ next_sg:
unsigned int i;
if (words) /* warning if bytes > 1 */
- printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
+ printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
ap->id, bytes);
for (i = 0; i < words; i++)
@@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap)
if (is_atapi_taskfile(&qc->tf)) {
/* no more data to transfer or unsupported ATAPI command */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_IDLE;
-
- ata_poll_qc_complete(qc, status);
+ ap->pio_task_state = PIO_ST_LAST;
return;
}
@@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap)
static void ata_pio_task(void *_data)
{
struct ata_port *ap = _data;
- unsigned long timeout = 0;
+ unsigned long timeout;
+ int qc_completed;
+
+fsm_start:
+ timeout = 0;
+ qc_completed = 0;
switch (ap->pio_task_state) {
case PIO_ST_IDLE:
@@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data)
break;
case PIO_ST_LAST:
- ata_pio_complete(ap);
+ qc_completed = ata_pio_complete(ap);
break;
case PIO_ST_POLL:
@@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data)
}
if (timeout)
- queue_delayed_work(ata_wq, &ap->pio_task,
- timeout);
- else
- queue_work(ata_wq, &ap->pio_task);
+ queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+ else if (!qc_completed)
+ goto fsm_start;
}
static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 3e9b641..23d095d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -201,6 +201,7 @@ int
qla2100_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -215,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha)
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -237,6 +238,7 @@ int
qla2300_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags = 0;
uint32_t cnt;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -302,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha)
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -324,6 +326,7 @@ int
qla24xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
int pcix_cmd_reg, pcie_dctl_reg;
@@ -366,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
}
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index a63f931..b227e51 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -161,7 +161,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
- u32 val, val2;
+ u32 val, val2 = 0;
u8 pmr;
if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
@@ -289,7 +289,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (ent->device != 0x182) {
if ((pmr & SIS_PMR_COMBINED) == 0) {
printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n");
- port2_start=0x64;
+ port2_start = 64;
}
else {
printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n");
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index aec39fb..b5cf394 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -463,7 +463,7 @@ static int __init serial21285_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver serial21285_reg;
+static struct uart_driver serial21285_reg;
static struct console serial21285_console =
{
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 978e124..679e678 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -689,7 +689,7 @@ static int __init pl010_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
static struct console amba_console = {
.name = "ttyAM",
.write = pl010_console_write,
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 5607130..1ff629c 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -701,7 +701,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
return uart_set_options(&uap->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
static struct console amba_console = {
.name = "ttyAMA",
.write = pl011_console_write,
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index d822896..78c1f36 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -525,7 +525,7 @@ static int __init clps711xuart_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver clps711x_reg;
+static struct uart_driver clps711x_reg;
static struct console clps711x_console = {
.name = "ttyCL",
.write = clps711xuart_console_write,
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index a3cd0ee..0585ab2 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -781,7 +781,7 @@ mpc52xx_uart_remove(struct device *dev)
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
+mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index eaa0af8..672b359 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -589,8 +589,8 @@ serial_pxa_type(struct uart_port *port)
#ifdef CONFIG_SERIAL_PXA_CONSOLE
-extern struct uart_pxa_port serial_pxa_ports[];
-extern struct uart_driver serial_pxa_reg;
+static struct uart_pxa_port serial_pxa_ports[];
+static struct uart_driver serial_pxa_reg;
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 1225b14..dd8aed2 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -799,7 +799,7 @@ sa1100_console_setup(struct console *co, char *options)
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver sa1100_reg;
+static struct uart_driver sa1100_reg;
static struct console sa1100_console = {
.name = "ttySA",
.write = sa1100_console_write,
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 8302376..d01dbe5 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -632,7 +632,7 @@ static int __init lh7a40xuart_console_setup (struct console* co, char* options)
return uart_set_options (port, co, baud, parity, bits, flow);
}
-extern struct uart_driver lh7a40x_reg;
+static struct uart_driver lh7a40x_reg;
static struct console lh7a40x_console = {
.name = "ttyAM",
.write = lh7a40xuart_console_write,
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 4382ee6..6bed871 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1683,7 +1683,7 @@ static void __init probe_sccs(void)
#ifndef CONFIG_SERIAL_DEC_CONSOLE
/*
* We're called early and memory managment isn't up, yet.
- * Thus check_region would fail.
+ * Thus request_region would fail.
*/
if (!request_region((unsigned long)
zs_channels[n_channels].control,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 615874e..31ee13e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -753,7 +753,8 @@ config FB_I810_GTF
config FB_I810_I2C
bool "Enable DDC Support"
- depends on FB_I810 && I2C && FB_I810_GTF
+ depends on FB_I810 && FB_I810_GTF
+ select I2C
select I2C_ALGOBIT
help
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 353cb3f..630f2df 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -19,17 +19,18 @@
#include <linux/fb.h>
#include <linux/backlight.h>
-#include <asm/arch-pxa/corgi.h>
-#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/sharpsl.h>
-#define CORGI_MAX_INTENSITY 0x3e
#define CORGI_DEFAULT_INTENSITY 0x1f
-#define CORGI_LIMIT_MASK 0x0b
+#define CORGI_LIMIT_MASK 0x0b
static int corgibl_powermode = FB_BLANK_UNBLANK;
static int current_intensity = 0;
static int corgibl_limit = 0;
+static void (*corgibl_mach_set_intensity)(int intensity);
static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static struct backlight_properties corgibl_data;
static void corgibl_send_intensity(int intensity)
{
@@ -43,18 +44,10 @@ static void corgibl_send_intensity(int intensity)
intensity &= CORGI_LIMIT_MASK;
}
- /* Skip 0x20 as it will blank the display */
- if (intensity >= 0x20)
- intensity++;
-
spin_lock_irqsave(&bl_lock, flags);
- /* Bits 0-4 are accessed via the SSP interface */
- corgi_ssp_blduty_set(intensity & 0x1f);
- /* Bit 5 is via SCOOP */
- if (intensity & 0x0020)
- set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
- else
- reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+
+ corgibl_mach_set_intensity(intensity);
+
spin_unlock_irqrestore(&bl_lock, flags);
}
@@ -113,8 +106,8 @@ static int corgibl_get_power(struct backlight_device *bd)
static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
{
- if (intensity > CORGI_MAX_INTENSITY)
- intensity = CORGI_MAX_INTENSITY;
+ if (intensity > corgibl_data.max_brightness)
+ intensity = corgibl_data.max_brightness;
corgibl_send_intensity(intensity);
current_intensity=intensity;
return 0;
@@ -141,7 +134,6 @@ static struct backlight_properties corgibl_data = {
.owner = THIS_MODULE,
.get_power = corgibl_get_power,
.set_power = corgibl_set_power,
- .max_brightness = CORGI_MAX_INTENSITY,
.get_brightness = corgibl_get_intensity,
.set_brightness = corgibl_set_intensity,
};
@@ -150,12 +142,18 @@ static struct backlight_device *corgi_backlight_device;
static int __init corgibl_probe(struct device *dev)
{
+ struct corgibl_machinfo *machinfo = dev->platform_data;
+
+ corgibl_data.max_brightness = machinfo->max_intensity;
+ corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+
corgi_backlight_device = backlight_device_register ("corgi-bl",
NULL, &corgibl_data);
if (IS_ERR (corgi_backlight_device))
return PTR_ERR (corgi_backlight_device);
corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY);
+ corgibl_limit_intensity(0);
printk("Corgi Backlight Driver Initialized.\n");
return 0;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2e93224..0fc8bb4 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -767,7 +767,7 @@ static const char *fbcon_startup(void)
const char *display_desc = "frame buffer device";
struct display *p = &fb_display[fg_console];
struct vc_data *vc = vc_cons[fg_console].d;
- struct font_desc *font = NULL;
+ const struct font_desc *font = NULL;
struct module *owner;
struct fb_info *info = NULL;
struct fbcon_ops *ops;
@@ -841,7 +841,7 @@ static const char *fbcon_startup(void)
info->var.yres);
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
- vc->vc_font.data = p->fontdata = font->data;
+ vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
}
@@ -941,7 +941,7 @@ static void fbcon_init(struct vc_data *vc, int init)
fb, copy the font from that console */
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -1188,7 +1188,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
return;
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -1687,6 +1687,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
+ if (logo_shown >= 0)
+ goto redraw_down;
switch (p->scrollmode) {
case SCROLL_MOVE:
ops->bmove(vc, info, t, 0, t + count, 0,
@@ -2148,7 +2150,7 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
}
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
- u8 * data, int userfont)
+ const u8 * data, int userfont)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
@@ -2166,7 +2168,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
cnt = FNTCHARCNT(data);
else
cnt = 256;
- vc->vc_font.data = p->fontdata = data;
+ vc->vc_font.data = (void *)(p->fontdata = data);
if ((p->userfont = userfont))
REFCOUNT(data)++;
vc->vc_font.width = w;
@@ -2323,7 +2325,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
tmp->vc_font.width == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
- new_data = fb_display[i].fontdata;
+ new_data = (u8 *)fb_display[i].fontdata;
break;
}
}
@@ -2333,7 +2335,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
- struct font_desc *f;
+ const struct font_desc *f;
if (!name)
f = get_default_font(info->var.xres, info->var.yres);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 08befaf..0738cd6 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -30,7 +30,7 @@ struct display {
/* Filled in by the frame buffer device */
u_short inverse; /* != 0 text black on white as default */
/* Filled in by the low-level console driver */
- u_char *fontdata;
+ const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */
u_short scrollmode; /* Scroll Method */
short yscroll; /* Hardware scrolling */
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
index ff0af96..e6aa0ea 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 9216
-static unsigned char fontdata_10x18[FONTDATAMAX] = {
+static const unsigned char fontdata_10x18[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 0000000000 */
@@ -5132,7 +5132,7 @@ static unsigned char fontdata_10x18[FONTDATAMAX] = {
};
-struct font_desc font_10x18 = {
+const struct font_desc font_10x18 = {
FONT10x18_IDX,
"10x18",
10,
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index c52f129..89976cd 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX (11*256)
-static unsigned char fontdata_6x11[FONTDATAMAX] = {
+static const unsigned char fontdata_6x11[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -3341,7 +3341,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = {
};
-struct font_desc font_vga_6x11 = {
+const struct font_desc font_vga_6x11 = {
VGA6x11_IDX,
"ProFont6x11",
6,
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
index 1fa7fcf..bbf1166 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 3584
-static unsigned char fontdata_7x14[FONTDATAMAX] = {
+static const unsigned char fontdata_7x14[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 0000000 */
@@ -4108,7 +4108,7 @@ static unsigned char fontdata_7x14[FONTDATAMAX] = {
};
-struct font_desc font_7x14 = {
+const struct font_desc font_7x14 = {
FONT7x14_IDX,
"7x14",
7,
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index e6f8dba..74fe86f 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_8x16[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -4621,7 +4621,7 @@ static unsigned char fontdata_8x16[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x16 = {
+const struct font_desc font_vga_8x16 = {
VGA8x16_IDX,
"VGA8x16",
8,
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 57fbe26..26199f8 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2573,7 +2573,7 @@ static unsigned char fontdata_8x8[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x8 = {
+const struct font_desc font_vga_8x8 = {
VGA8x8_IDX,
"VGA8x8",
8,
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index d565505..2d2e396 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -3,7 +3,7 @@
#include <linux/config.h>
#include <linux/font.h>
-static unsigned char acorndata_8x8[] = {
+static const unsigned char acorndata_8x8[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
/* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
/* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
@@ -262,7 +262,7 @@ static unsigned char acorndata_8x8[] = {
/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-struct font_desc font_acorn_8x8 = {
+const struct font_desc font_acorn_8x8 = {
ACORN8x8_IDX,
"Acorn8x8",
8,
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index 593b955..d818234 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -43,7 +43,7 @@ __END__;
#define FONTDATAMAX 1536
-static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
+static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*{*/
/* Char 0: ' ' */
@@ -2147,7 +2147,7 @@ static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*}*/
};
-struct font_desc font_mini_4x6 = {
+const struct font_desc font_mini_4x6 = {
MINI4x6_IDX,
"MINI4x6",
4,
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index 5fa95f1..e646c88 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -13,7 +13,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2577,7 +2577,7 @@ static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
};
-struct font_desc font_pearl_8x8 = {
+const struct font_desc font_pearl_8x8 = {
PEARL8x8_IDX,
"PEARL8x8",
8,
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index c7bd967..ab5eb93 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 11264
-static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
+static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 000000000000 */
@@ -6151,7 +6151,7 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
};
-struct font_desc font_sun_12x22 = {
+const struct font_desc font_sun_12x22 = {
SUN12x22_IDX,
"SUN12x22",
12,
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 2af3ab3..41f910f 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
@@ -261,7 +261,7 @@ static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
-struct font_desc font_sun_8x16 = {
+const struct font_desc font_sun_8x16 = {
SUN8x16_IDX,
"SUN8x16",
8,
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index e79b297..4fd07d9 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -23,7 +23,7 @@
#define NO_FONTS
-static struct font_desc *fonts[] = {
+static const struct font_desc *fonts[] = {
#ifdef CONFIG_FONT_8x8
#undef NO_FONTS
&font_vga_8x8,
@@ -84,7 +84,7 @@ static struct font_desc *fonts[] = {
*
*/
-struct font_desc *find_font(char *name)
+const struct font_desc *find_font(const char *name)
{
unsigned int i;
@@ -108,10 +108,10 @@ struct font_desc *find_font(char *name)
*
*/
-struct font_desc *get_default_font(int xres, int yres)
+const struct font_desc *get_default_font(int xres, int yres)
{
int i, c, cc;
- struct font_desc *f, *g;
+ const struct font_desc *f, *g;
g = NULL;
cc = -10000;
@@ -138,7 +138,6 @@ struct font_desc *get_default_font(int xres, int yres)
return g;
}
-EXPORT_SYMBOL(fonts);
EXPORT_SYMBOL(find_font);
EXPORT_SYMBOL(get_default_font);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 0705cd7..6ef6f77 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1020,7 +1020,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
static int vgacon_resize(struct vc_data *c, unsigned int width,
unsigned int height)
{
- if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES)
+ if (width % 2 || width > ORIG_VIDEO_COLS ||
+ height > (ORIG_VIDEO_LINES * vga_default_font_height)/
+ c->vc_font.height)
return -EINVAL;
if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cabd53c..6c2244c 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -425,7 +425,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi)
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int imxfb_suspend(struct device *dev, u32 state, u32 level)
+static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct imxfb_info *fbi = dev_get_drvdata(dev);
pr_debug("%s\n",__FUNCTION__);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 98e00d8..e02da41 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1285,7 +1285,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
vaddr_t vm;
unsigned int offs;
unsigned int offs2;
- unsigned char store;
+ unsigned char store, orig;
unsigned char bytes[32];
unsigned char* tmp;
@@ -1298,7 +1298,8 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
if (maxSize > 0x2000000) maxSize = 0x2000000;
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+ orig = mga_inb(M_EXTVGA_DATA);
+ mga_outb(M_EXTVGA_DATA, orig | 0x80);
store = mga_readb(vm, 0x1234);
tmp = bytes;
@@ -1323,7 +1324,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
mga_writeb(vm, 0x1234, store);
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+ mga_outb(M_EXTVGA_DATA, orig);
*realSize = offs - 0x100000;
#ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -1858,6 +1859,8 @@ static int initMatrox2(WPMINFO struct board* b){
to yres_virtual * xres_virtual < 2^32 */
}
matroxfb_init_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+ matroxfb_update_fix(PMINFO2);
/* Normalize values (namely yres_virtual) */
matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
@@ -2010,11 +2013,11 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
}
/* not match... */
if (!b->vendor)
- return -1;
+ return -ENODEV;
if (dev > 0) {
/* not requested one... */
dev--;
- return -1;
+ return -ENODEV;
}
pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
if (pci_enable_device(pdev)) {
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index ace484f..12f2884 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -209,10 +209,13 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
if (!edid && conn == 1) {
/* try to get from firmware */
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, fb_firmware_edid(info->device),
- EDID_LENGTH);
+ 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 (out_edid)
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index e0dad94..2e11b60 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -67,6 +67,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
+#include <linux/ctype.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
@@ -2594,7 +2595,7 @@ static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
{
char *next;
- if (!(CHAR_IS_NUM(options[0]))) {
+ if (!(isdigit(options[0]))) {
(*bn) = 0;
return (options);
}
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 959404a..3c98457 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -274,10 +274,13 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
if (!edid) {
/* try to get from firmware */
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, fb_firmware_edid(info->device),
- EDID_LENGTH);
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e) {
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, e, EDID_LENGTH);
+ }
}
if (out_edid)
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index d6f9474..ea17f7e 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,8 +60,6 @@
#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
-#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))
-
/* Chip tags. These are used to group the adapters into
* related families.
*/
@@ -74,8 +72,6 @@ typedef enum {
S3_PROSAVAGE,
S3_SUPERSAVAGE,
S3_SAVAGE2000,
- S3_PROSAVAGEDDR,
- S3_TWISTER,
S3_LAST
} savage_chipset;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index b5ca3ef..7c28545 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1773,8 +1773,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
}
}
- if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
- (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
+ if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly)
par->display_type = DISP_LCD;
else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
par->display_type = DISP_DFP;
@@ -1783,7 +1782,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
/* Check LCD panel parrmation */
- if (par->chip == S3_SAVAGE_MX) {
+ if (par->display_type == DISP_LCD) {
unsigned char cr6b = VGArCR( 0x6b );
int panelX = (VGArSEQ (0x61) +
@@ -1922,15 +1921,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
snprintf (info->fix.id, 16, "ProSavageKM");
break;
case FB_ACCEL_S3TWISTER_P:
- par->chip = S3_TWISTER;
+ par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "TwisterP");
break;
case FB_ACCEL_S3TWISTER_K:
- par->chip = S3_TWISTER;
+ par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "TwisterK");
break;
case FB_ACCEL_PROSAVAGE_DDR:
- par->chip = S3_PROSAVAGEDDR;
+ par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "ProSavageDDR");
break;
case FB_ACCEL_PROSAVAGE_DDRK:
diff --git a/fs/aio.c b/fs/aio.c
index 38f6268..0e11e31 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -562,6 +562,7 @@ static inline void lock_kiocb(struct kiocb *iocb)
static inline void unlock_kiocb(struct kiocb *iocb)
{
kiocbClearLocked(iocb);
+ smp_mb__after_clear_bit();
wake_up_bit(&iocb->ki_flags, KIF_LOCKED);
}
diff --git a/fs/compat.c b/fs/compat.c
index ac3fb9e..a719e15 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -44,6 +44,8 @@
#include <linux/nfsd/syscall.h>
#include <linux/personality.h>
#include <linux/rwsem.h>
+#include <linux/acct.h>
+#include <linux/mm.h>
#include <net/sock.h> /* siocdevprivate_ioctl */
@@ -1487,6 +1489,8 @@ int compat_do_execve(char * filename,
/* execve success */
security_bprm_free(bprm);
+ acct_update_integrals(current);
+ update_mem_hiwater(current);
kfree(bprm);
return retval;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index 7376b612..fb10386 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -102,7 +102,8 @@ static inline void dentry_iput(struct dentry * dentry)
list_del_init(&dentry->d_alias);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
- fsnotify_inoderemove(inode);
+ if (!inode->i_nlink)
+ fsnotify_inoderemove(inode);
if (dentry->d_op && dentry->d_op->d_iput)
dentry->d_op->d_iput(dentry, inode);
else
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 6ab1dd0..403b90a 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -231,8 +231,9 @@ struct ep_pqueue {
static void ep_poll_safewake_init(struct poll_safewake *psw);
static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile);
-static int ep_file_init(struct file *file);
+static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+ struct eventpoll *ep);
+static int ep_alloc(struct eventpoll **pep);
static void ep_free(struct eventpoll *ep);
static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
static void ep_use_epitem(struct epitem *epi);
@@ -501,38 +502,37 @@ void eventpoll_release_file(struct file *file)
asmlinkage long sys_epoll_create(int size)
{
int error, fd;
+ struct eventpoll *ep;
struct inode *inode;
struct file *file;
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
current, size));
- /* Sanity check on the size parameter */
+ /*
+ * Sanity check on the size parameter, and create the internal data
+ * structure ( "struct eventpoll" ).
+ */
error = -EINVAL;
- if (size <= 0)
+ if (size <= 0 || (error = ep_alloc(&ep)) != 0)
goto eexit_1;
/*
* Creates all the items needed to setup an eventpoll file. That is,
* a file structure, and inode and a free file descriptor.
*/
- error = ep_getfd(&fd, &inode, &file);
- if (error)
- goto eexit_1;
-
- /* Setup the file internal data structure ( "struct eventpoll" ) */
- error = ep_file_init(file);
+ error = ep_getfd(&fd, &inode, &file, ep);
if (error)
goto eexit_2;
-
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
current, size, fd));
return fd;
eexit_2:
- sys_close(fd);
+ ep_free(ep);
+ kfree(ep);
eexit_1:
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
current, size, error));
@@ -706,7 +706,8 @@ eexit_1:
/*
* Creates the file descriptor to be used by the epoll interface.
*/
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile)
+static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+ struct eventpoll *ep)
{
struct qstr this;
char name[32];
@@ -756,7 +757,7 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile)
file->f_op = &eventpoll_fops;
file->f_mode = FMODE_READ;
file->f_version = 0;
- file->private_data = NULL;
+ file->private_data = ep;
/* Install the new setup file into the allocated fd. */
fd_install(fd, file);
@@ -777,14 +778,13 @@ eexit_1:
}
-static int ep_file_init(struct file *file)
+static int ep_alloc(struct eventpoll **pep)
{
- struct eventpoll *ep;
+ struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
- if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL)))
+ if (!ep)
return -ENOMEM;
- memset(ep, 0, sizeof(*ep));
rwlock_init(&ep->lock);
init_rwsem(&ep->sem);
init_waitqueue_head(&ep->wq);
@@ -792,9 +792,9 @@ static int ep_file_init(struct file *file)
INIT_LIST_HEAD(&ep->rdllist);
ep->rbr = RB_ROOT;
- file->private_data = ep;
+ *pep = ep;
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n",
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
current, ep));
return 0;
}
diff --git a/fs/exec.c b/fs/exec.c
index 14dd039..a04a575 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -421,11 +421,6 @@ int setup_arg_pages(struct linux_binprm *bprm,
if (!mpnt)
return -ENOMEM;
- if (security_vm_enough_memory(arg_size >> PAGE_SHIFT)) {
- kmem_cache_free(vm_area_cachep, mpnt);
- return -ENOMEM;
- }
-
memset(mpnt, 0, sizeof(*mpnt));
down_write(&mm->mmap_sem);
@@ -745,8 +740,8 @@ static inline int de_thread(struct task_struct *tsk)
}
/*
- * Now there are really no other threads at all,
- * so it's safe to stop telling them to kill themselves.
+ * There may be one thread left which is just exiting,
+ * but it's safe to stop telling the group to kill themselves.
*/
sig->flags = 0;
@@ -785,7 +780,6 @@ no_thread_group:
kmem_cache_free(sighand_cachep, oldsighand);
}
- BUG_ON(!thread_group_empty(current));
BUG_ON(!thread_group_leader(current));
return 0;
}
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 62ffa91..7134403 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -12,39 +12,6 @@
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
-static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
-{
- struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
- int retval;
-
- retval = generic_file_aio_write(iocb, buf, count, pos);
- if (retval > 0) {
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
- MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
- mark_inode_dirty(inode);
-// check the locking rules
-// if (IS_SYNC(inode))
-// fat_sync_inode(inode);
- }
- return retval;
-}
-
-static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
-{
- struct inode *inode = filp->f_dentry->d_inode;
- int retval;
-
- retval = generic_file_writev(filp, iov, nr_segs, ppos);
- if (retval > 0) {
- inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
- MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
- mark_inode_dirty(inode);
- }
- return retval;
-}
-
int fat_generic_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -148,9 +115,9 @@ struct file_operations fat_file_operations = {
.read = do_sync_read,
.write = do_sync_write,
.readv = generic_file_readv,
- .writev = fat_file_writev,
+ .writev = generic_file_writev,
.aio_read = generic_file_aio_read,
- .aio_write = fat_file_aio_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.ioctl = fat_generic_ioctl,
.fsync = file_fsync,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a7cbe68..51b1d15 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -102,6 +102,19 @@ static int fat_prepare_write(struct file *file, struct page *page,
&MSDOS_I(page->mapping->host)->mmu_private);
}
+static int fat_commit_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ struct inode *inode = page->mapping->host;
+ int err = generic_commit_write(file, page, from, to);
+ if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+ mark_inode_dirty(inode);
+ }
+ return err;
+}
+
static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping, block, fat_get_block);
@@ -112,7 +125,7 @@ static struct address_space_operations fat_aops = {
.writepage = fat_writepage,
.sync_page = block_sync_page,
.prepare_write = fat_prepare_write,
- .commit_write = generic_commit_write,
+ .commit_write = fat_commit_write,
.bmap = _fat_bmap
};
diff --git a/fs/file.c b/fs/file.c
index 2127a7b..fd066b2 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -69,13 +69,9 @@ void free_fd_array(struct file **array, int num)
static void __free_fdtable(struct fdtable *fdt)
{
- int fdset_size, fdarray_size;
-
- fdset_size = fdt->max_fdset / 8;
- fdarray_size = fdt->max_fds * sizeof(struct file *);
- free_fdset(fdt->open_fds, fdset_size);
- free_fdset(fdt->close_on_exec, fdset_size);
- free_fd_array(fdt->fd, fdarray_size);
+ 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);
}
diff --git a/fs/locks.c b/fs/locks.c
index c2c09b4..f7daa5f 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -124,6 +124,7 @@
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <linux/time.h>
+#include <linux/rcupdate.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -2205,6 +2206,7 @@ void steal_locks(fl_owner_t from)
lock_kernel();
j = 0;
+ rcu_read_lock();
fdt = files_fdtable(files);
for (;;) {
unsigned long set;
@@ -2222,6 +2224,7 @@ void steal_locks(fl_owner_t from)
set >>= 1;
}
}
+ rcu_read_unlock();
unlock_kernel();
}
EXPORT_SYMBOL(steal_locks);
diff --git a/fs/namei.c b/fs/namei.c
index 21d85f1..043d587 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1048,7 +1048,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
out:
if (unlikely(current->audit_context
&& nd && nd->dentry && nd->dentry->d_inode))
- audit_inode(name, nd->dentry->d_inode);
+ audit_inode(name, nd->dentry->d_inode, flags);
return retval;
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e08edc1..361b400 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -162,7 +162,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
static inline int
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
{
int status;
dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -238,8 +238,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
*/
status = nfsd4_process_open2(rqstp, current_fh, open);
out:
- if (open->op_stateowner)
+ if (open->op_stateowner) {
nfs4_get_stateowner(open->op_stateowner);
+ *replay_owner = open->op_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -809,8 +811,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
break;
case OP_CLOSE:
- op->status = nfsd4_close(rqstp, current_fh, &op->u.close);
- replay_owner = op->u.close.cl_stateowner;
+ op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
break;
case OP_COMMIT:
op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
@@ -831,15 +832,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
break;
case OP_LOCK:
- op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock);
- replay_owner = op->u.lock.lk_stateowner;
+ op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
break;
case OP_LOCKT:
op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
break;
case OP_LOCKU:
- op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku);
- replay_owner = op->u.locku.lu_stateowner;
+ op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
break;
case OP_LOOKUP:
op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
@@ -853,16 +852,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfs_ok;
break;
case OP_OPEN:
- op->status = nfsd4_open(rqstp, current_fh, &op->u.open);
- replay_owner = op->u.open.op_stateowner;
+ op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
break;
case OP_OPEN_CONFIRM:
- op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm);
- replay_owner = op->u.open_confirm.oc_stateowner;
+ op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
break;
case OP_OPEN_DOWNGRADE:
- op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade);
- replay_owner = op->u.open_downgrade.od_stateowner;
+ op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
break;
case OP_PUTFH:
op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b83f8fb..6bbefd0 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -624,7 +624,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
cb->cb_ident = se->se_callback_ident;
return;
out_err:
- printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
+ dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
"will not receive delegations\n",
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
@@ -678,13 +678,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
int status;
char dname[HEXDIR_LEN];
- status = nfserr_inval;
if (!check_name(clname))
- goto out;
+ return nfserr_inval;
status = nfs4_make_rec_clidname(dname, &clname);
if (status)
- goto out;
+ return status;
/*
* XXX The Duplicate Request Cache (DRC) has been checked (??)
@@ -2014,7 +2013,7 @@ STALE_STATEID(stateid_t *stateid)
{
if (stateid->si_boot == boot_time)
return 0;
- printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
+ dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
return 1;
@@ -2275,7 +2274,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
check_replay:
if (seqid == sop->so_seqid - 1) {
- printk("NFSD: preprocess_seqid_op: retransmission?\n");
+ dprintk("NFSD: preprocess_seqid_op: retransmission?\n");
/* indicate replay to calling function */
return NFSERR_REPLAY_ME;
}
@@ -2286,7 +2285,7 @@ check_replay:
}
int
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
{
int status;
struct nfs4_stateowner *sop;
@@ -2320,8 +2319,10 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
nfsd4_create_clid_dir(sop->so_client);
out:
- if (oc->oc_stateowner)
+ if (oc->oc_stateowner) {
nfs4_get_stateowner(oc->oc_stateowner);
+ *replay_owner = oc->oc_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2352,7 +2353,7 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap)
}
int
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
+nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
{
int status;
struct nfs4_stateid *stp;
@@ -2394,8 +2395,10 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
status = nfs_ok;
out:
- if (od->od_stateowner)
+ if (od->od_stateowner) {
nfs4_get_stateowner(od->od_stateowner);
+ *replay_owner = od->od_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2404,7 +2407,7 @@ out:
* nfs4_unlock_state() called after encode
*/
int
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
+nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
{
int status;
struct nfs4_stateid *stp;
@@ -2430,8 +2433,10 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
/* release_state_owner() calls nfsd_close() if needed */
release_state_owner(stp, OPEN_STATE);
out:
- if (close->cl_stateowner)
+ if (close->cl_stateowner) {
nfs4_get_stateowner(close->cl_stateowner);
+ *replay_owner = close->cl_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2500,8 +2505,7 @@ find_stateid(stateid_t *stid, int flags)
(local->st_stateid.si_fileid == f_id))
return local;
}
- } else
- printk("NFSD: find_stateid: ERROR: no state flag\n");
+ }
return NULL;
}
@@ -2624,7 +2628,9 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_is_open_owner = 0;
sop->so_id = current_ownerid++;
sop->so_client = clp;
- sop->so_seqid = lock->lk_new_lock_seqid;
+ /* It is the openowner seqid that will be incremented in encode in the
+ * case of new lockowners; so increment the lock seqid manually: */
+ sop->so_seqid = lock->lk_new_lock_seqid + 1;
sop->so_confirmed = 1;
rp = &sop->so_replay;
rp->rp_status = NFSERR_SERVERFAULT;
@@ -2676,9 +2682,10 @@ check_lock_length(u64 offset, u64 length)
* LOCK operation
*/
int
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
+nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
{
struct nfs4_stateowner *open_sop = NULL;
+ struct nfs4_stateowner *lock_sop = NULL;
struct nfs4_stateid *lock_stp;
struct file *filp;
struct file_lock file_lock;
@@ -2705,19 +2712,19 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
struct nfs4_file *fp;
status = nfserr_stale_clientid;
- if (STALE_CLIENTID(&lock->lk_new_clientid)) {
- printk("NFSD: nfsd4_lock: clientid is stale!\n");
+ if (STALE_CLIENTID(&lock->lk_new_clientid))
goto out;
- }
/* validate and update open stateid and open seqid */
status = nfs4_preprocess_seqid_op(current_fh,
lock->lk_new_open_seqid,
&lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE,
- &open_sop, &open_stp, lock);
+ &lock->lk_stateowner, &open_stp,
+ lock);
if (status)
goto out;
+ open_sop = lock->lk_stateowner;
/* create lockowner and lock stateid */
fp = open_stp->st_file;
strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2727,16 +2734,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* the same file, or should they just be allowed (and
* create new stateids)? */
status = nfserr_resource;
- if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
+ lock_sop = alloc_init_lock_stateowner(strhashval,
+ open_sop->so_client, open_stp, lock);
+ if (lock_sop == NULL)
goto out;
- if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner,
- fp, open_stp)) == NULL) {
- release_stateowner(lock->lk_stateowner);
- lock->lk_stateowner = NULL;
+ lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
+ if (lock_stp == NULL) {
+ release_stateowner(lock_sop);
goto out;
}
- /* bump the open seqid used to create the lock */
- open_sop->so_seqid++;
} else {
/* lock (lock owner + lock stateid) already exists */
status = nfs4_preprocess_seqid_op(current_fh,
@@ -2746,12 +2752,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
&lock->lk_stateowner, &lock_stp, lock);
if (status)
goto out;
+ lock_sop = lock->lk_stateowner;
}
/* lock->lk_stateowner and lock_stp have been created or found */
filp = lock_stp->st_vfs_file;
if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
- printk("NFSD: nfsd4_lock: permission denied!\n");
+ dprintk("NFSD: nfsd4_lock: permission denied!\n");
goto out;
}
@@ -2776,7 +2783,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
status = nfserr_inval;
goto out;
}
- file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
+ file_lock.fl_owner = (fl_owner_t)lock_sop;
file_lock.fl_pid = current->tgid;
file_lock.fl_file = filp;
file_lock.fl_flags = FL_POSIX;
@@ -2832,14 +2839,13 @@ out_destroy_new_stateid:
* An error encountered after instantiation of the new
* stateid has forced us to destroy it.
*/
- if (!seqid_mutating_err(status))
- open_sop->so_seqid--;
-
release_state_owner(lock_stp, LOCK_STATE);
}
out:
- if (lock->lk_stateowner)
+ if (lock->lk_stateowner) {
nfs4_get_stateowner(lock->lk_stateowner);
+ *replay_owner = lock->lk_stateowner;
+ }
nfs4_unlock_state();
return status;
}
@@ -2866,13 +2872,11 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
nfs4_lock_state();
status = nfserr_stale_clientid;
- if (STALE_CLIENTID(&lockt->lt_clientid)) {
- printk("NFSD: nfsd4_lockt: clientid is stale!\n");
+ if (STALE_CLIENTID(&lockt->lt_clientid))
goto out;
- }
if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
- printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
+ dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
if (status == nfserr_symlink)
status = nfserr_inval;
goto out;
@@ -2930,7 +2934,7 @@ out:
}
int
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
+nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
{
struct nfs4_stateid *stp;
struct file *filp = NULL;
@@ -2976,7 +2980,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
file_lock.fl_ops->fl_release_private(&file_lock);
if (status) {
- printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
+ dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
goto out_nfserr;
}
/*
@@ -2986,8 +2990,10 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
out:
- if (locku->lu_stateowner)
+ if (locku->lu_stateowner) {
nfs4_get_stateowner(locku->lu_stateowner);
+ *replay_owner = locku->lu_stateowner;
+ }
nfs4_unlock_state();
return status;
@@ -3036,10 +3042,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
/* XXX check for lease expiration */
status = nfserr_stale_clientid;
- if (STALE_CLIENTID(clid)) {
- printk("NFSD: nfsd4_release_lockowner: clientid is stale!\n");
+ if (STALE_CLIENTID(clid))
return status;
- }
nfs4_lock_state();
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 49eafbd..c7e9237 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -92,6 +92,8 @@ ToDo/Notes:
an octal number to conform to how chmod(1) works, too. Thanks to
Giuseppe Bilotta and Horst von Brand for pointing out the errors of
my ways.
+ - Fix various bugs in the runlist merging code. (Based on libntfs
+ changes by Richard Russon.)
2.1.23 - Implement extension of resident files and make writing safe as well as
many bug fixes, cleanups, and enhancements...
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index b6cc8cf..5e80c07 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -59,39 +59,49 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
unsigned long flags;
struct buffer_head *first, *tmp;
struct page *page;
+ struct inode *vi;
ntfs_inode *ni;
int page_uptodate = 1;
page = bh->b_page;
- ni = NTFS_I(page->mapping->host);
+ vi = page->mapping->host;
+ ni = NTFS_I(vi);
if (likely(uptodate)) {
- s64 file_ofs, initialized_size;
+ loff_t i_size;
+ s64 file_ofs, init_size;
set_buffer_uptodate(bh);
file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) +
bh_offset(bh);
read_lock_irqsave(&ni->size_lock, flags);
- initialized_size = ni->initialized_size;
+ init_size = ni->initialized_size;
+ i_size = i_size_read(vi);
read_unlock_irqrestore(&ni->size_lock, flags);
+ if (unlikely(init_size > i_size)) {
+ /* Race with shrinking truncate. */
+ init_size = i_size;
+ }
/* Check for the current buffer head overflowing. */
- if (file_ofs + bh->b_size > initialized_size) {
- char *addr;
- int ofs = 0;
-
- if (file_ofs < initialized_size)
- ofs = initialized_size - file_ofs;
- addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
- memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs);
+ if (unlikely(file_ofs + bh->b_size > init_size)) {
+ u8 *kaddr;
+ int ofs;
+
+ ofs = 0;
+ if (file_ofs < init_size)
+ ofs = init_size - file_ofs;
+ 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);
flush_dcache_page(page);
- kunmap_atomic(addr, KM_BIO_SRC_IRQ);
}
} else {
clear_buffer_uptodate(bh);
SetPageError(page);
- ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %llu.",
- (unsigned long long)bh->b_blocknr);
+ ntfs_error(ni->vol->sb, "Buffer I/O error, logical block "
+ "0x%llx.", (unsigned long long)bh->b_blocknr);
}
first = page_buffers(page);
local_irq_save(flags);
@@ -124,7 +134,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
if (likely(page_uptodate && !PageError(page)))
SetPageUptodate(page);
} else {
- char *addr;
+ u8 *kaddr;
unsigned int i, recs;
u32 rec_size;
@@ -132,12 +142,12 @@ 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);
- addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+ kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
for (i = 0; i < recs; i++)
- post_read_mst_fixup((NTFS_RECORD*)(addr +
+ post_read_mst_fixup((NTFS_RECORD*)(kaddr +
i * rec_size), rec_size);
+ kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
flush_dcache_page(page);
- kunmap_atomic(addr, KM_BIO_SRC_IRQ);
if (likely(page_uptodate && !PageError(page)))
SetPageUptodate(page);
}
@@ -168,8 +178,11 @@ still_busy:
*/
static int ntfs_read_block(struct page *page)
{
+ loff_t i_size;
VCN vcn;
LCN lcn;
+ s64 init_size;
+ struct inode *vi;
ntfs_inode *ni;
ntfs_volume *vol;
runlist_element *rl;
@@ -180,7 +193,8 @@ static int ntfs_read_block(struct page *page)
int i, nr;
unsigned char blocksize_bits;
- ni = NTFS_I(page->mapping->host);
+ vi = page->mapping->host;
+ ni = NTFS_I(vi);
vol = ni->vol;
/* $MFT/$DATA must have its complete runlist in memory at all times. */
@@ -199,11 +213,28 @@ static int ntfs_read_block(struct page *page)
bh = head = page_buffers(page);
BUG_ON(!bh);
+ /*
+ * We may be racing with truncate. To avoid some of the problems we
+ * now take a snapshot of the various sizes and use those for the whole
+ * of the function. In case of an extending truncate it just means we
+ * may leave some buffers unmapped which are now allocated. This is
+ * not a problem since these buffers will just get mapped when a write
+ * occurs. In case of a shrinking truncate, we will detect this later
+ * on due to the runlist being incomplete and if the page is being
+ * fully truncated, truncate will throw it away as soon as we unlock
+ * it so no need to worry what we do with it.
+ */
iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
read_lock_irqsave(&ni->size_lock, flags);
lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
- zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
+ init_size = ni->initialized_size;
+ i_size = i_size_read(vi);
read_unlock_irqrestore(&ni->size_lock, flags);
+ if (unlikely(init_size > i_size)) {
+ /* Race with shrinking truncate. */
+ init_size = i_size;
+ }
+ zblock = (init_size + blocksize - 1) >> blocksize_bits;
/* Loop through all the buffers in the page. */
rl = NULL;
@@ -366,6 +397,8 @@ handle_zblock:
*/
static int ntfs_readpage(struct file *file, struct page *page)
{
+ loff_t i_size;
+ struct inode *vi;
ntfs_inode *ni, *base_ni;
u8 *kaddr;
ntfs_attr_search_ctx *ctx;
@@ -384,14 +417,17 @@ retry_readpage:
unlock_page(page);
return 0;
}
- ni = NTFS_I(page->mapping->host);
+ vi = page->mapping->host;
+ ni = NTFS_I(vi);
/*
* Only $DATA attributes can be encrypted and only unnamed $DATA
* attributes can be compressed. Index root can have the flags set but
* this means to create compressed/encrypted files, not that the
- * attribute is compressed/encrypted.
+ * attribute is compressed/encrypted. Note we need to check for
+ * AT_INDEX_ALLOCATION since this is the type of both directory and
+ * index inodes.
*/
- if (ni->type != AT_INDEX_ROOT) {
+ if (ni->type != AT_INDEX_ALLOCATION) {
/* If attribute is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
BUG_ON(ni->type != AT_DATA);
@@ -456,7 +492,12 @@ retry_readpage:
read_lock_irqsave(&ni->size_lock, flags);
if (unlikely(attr_len > ni->initialized_size))
attr_len = ni->initialized_size;
+ i_size = i_size_read(vi);
read_unlock_irqrestore(&ni->size_lock, flags);
+ if (unlikely(attr_len > i_size)) {
+ /* Race with shrinking truncate. */
+ attr_len = i_size;
+ }
kaddr = kmap_atomic(page, KM_USER0);
/* Copy the data to the page. */
memcpy(kaddr, (u8*)ctx->attr +
@@ -1341,9 +1382,11 @@ retry_writepage:
* Only $DATA attributes can be encrypted and only unnamed $DATA
* attributes can be compressed. Index root can have the flags set but
* this means to create compressed/encrypted files, not that the
- * attribute is compressed/encrypted.
+ * attribute is compressed/encrypted. Note we need to check for
+ * AT_INDEX_ALLOCATION since this is the type of both directory and
+ * index inodes.
*/
- if (ni->type != AT_INDEX_ROOT) {
+ if (ni->type != AT_INDEX_ALLOCATION) {
/* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
unlock_page(page);
@@ -1379,8 +1422,8 @@ retry_writepage:
unsigned int ofs = i_size & ~PAGE_CACHE_MASK;
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs);
- flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
+ flush_dcache_page(page);
}
/* Handle mst protected attributes. */
if (NInoMstProtected(ni))
@@ -1443,34 +1486,33 @@ retry_writepage:
BUG_ON(PageWriteback(page));
set_page_writeback(page);
unlock_page(page);
- /*
- * Here, we do not need to zero the out of bounds area everytime
- * because the below memcpy() already takes care of the
- * mmap-at-end-of-file requirements. If the file is converted to a
- * non-resident one, then the code path use is switched to the
- * non-resident one where the zeroing happens on each ntfs_writepage()
- * invocation.
- */
attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
i_size = i_size_read(vi);
if (unlikely(attr_len > i_size)) {
+ /* Race with shrinking truncate or a failed truncate. */
attr_len = i_size;
- ctx->attr->data.resident.value_length = cpu_to_le32(attr_len);
+ /*
+ * If the truncate failed, fix it up now. If a concurrent
+ * truncate, we do its job, so it does not have to do anything.
+ */
+ err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
+ attr_len);
+ /* Shrinking cannot fail. */
+ BUG_ON(err);
}
kaddr = kmap_atomic(page, KM_USER0);
/* Copy the data from the page to the mft record. */
memcpy((u8*)ctx->attr +
le16_to_cpu(ctx->attr->data.resident.value_offset),
kaddr, attr_len);
- flush_dcache_mft_record_page(ctx->ntfs_ino);
/* Zero out of bounds area in the page cache page. */
memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
- flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
-
+ flush_dcache_mft_record_page(ctx->ntfs_ino);
+ flush_dcache_page(page);
+ /* We are done with the page. */
end_page_writeback(page);
-
- /* Mark the mft record dirty, so it gets written back. */
+ /* Finally, mark the mft record dirty, so it gets written back. */
mark_mft_record_dirty(ctx->ntfs_ino);
ntfs_attr_put_search_ctx(ctx);
unmap_mft_record(base_ni);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index dc4bbe3..7ec0451 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1166,6 +1166,8 @@ err_out:
*
* Return 0 on success and -errno on error. In the error case, the inode will
* have had make_bad_inode() executed on it.
+ *
+ * Note this cannot be called for AT_INDEX_ALLOCATION.
*/
static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
{
@@ -1242,8 +1244,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
}
}
/*
- * The encryption flag set in an index root just means to
- * compress all files.
+ * The compressed/sparse flag set in an index root just means
+ * to compress all files.
*/
if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
ntfs_error(vi->i_sb, "Found mst protected attribute "
@@ -1319,8 +1321,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"the mapping pairs array.");
goto unm_err_out;
}
- if ((NInoCompressed(ni) || NInoSparse(ni)) &&
- ni->type != AT_INDEX_ROOT) {
+ if (NInoCompressed(ni) || NInoSparse(ni)) {
if (a->data.non_resident.compression_unit != 4) {
ntfs_error(vi->i_sb, "Found nonstandard "
"compression unit (%u instead "
diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h
index 3288bcc..006946e 100644
--- a/fs/ntfs/malloc.h
+++ b/fs/ntfs/malloc.h
@@ -1,7 +1,7 @@
/*
* malloc.h - NTFS kernel memory handling. Part of the Linux-NTFS project.
*
- * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2001-2005 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index f5b2ac9..e2665d0 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -2,7 +2,7 @@
* runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project.
*
* Copyright (c) 2001-2005 Anton Altaparmakov
- * Copyright (c) 2002 Richard Russon
+ * Copyright (c) 2002-2005 Richard Russon
*
* 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
@@ -214,8 +214,8 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
static inline runlist_element *ntfs_rl_append(runlist_element *dst,
int dsize, runlist_element *src, int ssize, int loc)
{
- BOOL right;
- int magic;
+ BOOL right; /* Right end of @src needs merging. */
+ int marker; /* End of the inserted runs. */
BUG_ON(!dst);
BUG_ON(!src);
@@ -236,18 +236,19 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst,
if (right)
__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
- magic = loc + ssize;
+ /* First run after the @src runs that have been inserted. */
+ marker = loc + ssize + 1;
/* Move the tail of @dst out of the way, then copy in @src. */
- ntfs_rl_mm(dst, magic + 1, loc + 1 + right, dsize - loc - 1 - right);
+ ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right));
ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
/* Adjust the size of the preceding hole. */
dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
/* We may have changed the length of the file, so fix the end marker */
- if (dst[magic + 1].lcn == LCN_ENOENT)
- dst[magic + 1].vcn = dst[magic].vcn + dst[magic].length;
+ if (dst[marker].lcn == LCN_ENOENT)
+ dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
return dst;
}
@@ -279,18 +280,17 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst,
static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
int dsize, runlist_element *src, int ssize, int loc)
{
- BOOL left = FALSE;
- BOOL disc = FALSE; /* Discontinuity */
- BOOL hole = FALSE; /* Following a hole */
- int magic;
+ BOOL left = FALSE; /* Left end of @src needs merging. */
+ BOOL disc = FALSE; /* Discontinuity between @dst and @src. */
+ int marker; /* End of the inserted runs. */
BUG_ON(!dst);
BUG_ON(!src);
- /* disc => Discontinuity between the end of @dst and the start of @src.
- * This means we might need to insert a hole.
- * hole => @dst ends with a hole or an unmapped region which we can
- * extend to match the discontinuity. */
+ /*
+ * disc => Discontinuity between the end of @dst and the start of @src.
+ * This means we might need to insert a "not mapped" run.
+ */
if (loc == 0)
disc = (src[0].vcn > 0);
else {
@@ -303,58 +303,49 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
merged_length += src->length;
disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
- if (disc)
- hole = (dst[loc - 1].lcn == LCN_HOLE);
}
-
- /* Space required: @dst size + @src size, less one if we merged, plus
- * one if there was a discontinuity, less one for a trailing hole. */
- dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc - hole);
+ /*
+ * Space required: @dst size + @src size, less one if we merged, plus
+ * one if there was a discontinuity.
+ */
+ dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
if (IS_ERR(dst))
return dst;
/*
* We are guaranteed to succeed from here so can start modifying the
* original runlist.
*/
-
if (left)
__ntfs_rl_merge(dst + loc - 1, src);
-
- magic = loc + ssize - left + disc - hole;
+ /*
+ * First run after the @src runs that have been inserted.
+ * Nominally, @marker equals @loc + @ssize, i.e. location + number of
+ * runs in @src. However, if @left, then the first run in @src has
+ * been merged with one in @dst. And if @disc, then @dst and @src do
+ * not meet and we need an extra run to fill the gap.
+ */
+ marker = loc + ssize - left + disc;
/* Move the tail of @dst out of the way, then copy in @src. */
- ntfs_rl_mm(dst, magic, loc, dsize - loc);
- ntfs_rl_mc(dst, loc + disc - hole, src, left, ssize - left);
+ ntfs_rl_mm(dst, marker, loc, dsize - loc);
+ ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
- /* Adjust the VCN of the last run ... */
- if (dst[magic].lcn <= LCN_HOLE)
- dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length;
+ /* Adjust the VCN of the first run after the insertion... */
+ dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
/* ... and the length. */
- if (dst[magic].lcn == LCN_HOLE || dst[magic].lcn == LCN_RL_NOT_MAPPED)
- dst[magic].length = dst[magic + 1].vcn - dst[magic].vcn;
+ if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
+ dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
- /* Writing beyond the end of the file and there's a discontinuity. */
+ /* Writing beyond the end of the file and there is a discontinuity. */
if (disc) {
- if (hole)
- dst[loc - 1].length = dst[loc].vcn - dst[loc - 1].vcn;
- else {
- if (loc > 0) {
- dst[loc].vcn = dst[loc - 1].vcn +
- dst[loc - 1].length;
- dst[loc].length = dst[loc + 1].vcn -
- dst[loc].vcn;
- } else {
- dst[loc].vcn = 0;
- dst[loc].length = dst[loc + 1].vcn;
- }
- dst[loc].lcn = LCN_RL_NOT_MAPPED;
+ if (loc > 0) {
+ dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
+ dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
+ } else {
+ dst[loc].vcn = 0;
+ dst[loc].length = dst[loc + 1].vcn;
}
-
- magic += hole;
-
- if (dst[magic].lcn == LCN_ENOENT)
- dst[magic].vcn = dst[magic - 1].vcn +
- dst[magic - 1].length;
+ dst[loc].lcn = LCN_RL_NOT_MAPPED;
}
return dst;
}
@@ -385,9 +376,10 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
int dsize, runlist_element *src, int ssize, int loc)
{
- BOOL left = FALSE;
- BOOL right;
- int magic;
+ BOOL left = FALSE; /* Left end of @src needs merging. */
+ BOOL right; /* Right end of @src needs merging. */
+ int tail; /* Start of tail of @dst. */
+ int marker; /* End of the inserted runs. */
BUG_ON(!dst);
BUG_ON(!src);
@@ -396,9 +388,10 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
if (loc > 0)
left = ntfs_are_rl_mergeable(dst + loc - 1, src);
-
- /* Allocate some space. We'll need less if the left, right, or both
- * ends were merged. */
+ /*
+ * Allocate some space. We will need less if the left, right, or both
+ * ends were merged.
+ */
dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right);
if (IS_ERR(dst))
return dst;
@@ -410,17 +403,28 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
if (left)
__ntfs_rl_merge(dst + loc - 1, src);
-
- /* FIXME: What does this mean? (AIA) */
- magic = loc + ssize - left;
+ /*
+ * First run of @dst that needs to be moved out of the way to make
+ * space for the runs to be copied from @src, i.e. the first run of the
+ * tail of @dst.
+ */
+ tail = loc + right + 1;
+ /*
+ * First run after the @src runs that have been inserted, i.e. where
+ * the tail of @dst needs to be moved to.
+ * Nominally, marker equals @loc + @ssize, i.e. location + number of
+ * runs in @src). However, if @left, then the first run in @src has
+ * been merged with one in @dst.
+ */
+ marker = loc + ssize - left;
/* Move the tail of @dst out of the way, then copy in @src. */
- ntfs_rl_mm(dst, magic, loc + right + 1, dsize - loc - right - 1);
+ ntfs_rl_mm(dst, marker, tail, dsize - tail);
ntfs_rl_mc(dst, loc, src, left, ssize - left);
- /* We may have changed the length of the file, so fix the end marker */
- if (dst[magic].lcn == LCN_ENOENT)
- dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length;
+ /* We may have changed the length of the file, so fix the end marker. */
+ if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT)
+ dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
return dst;
}
diff --git a/fs/open.c b/fs/open.c
index 2fac58c..f0d90cf 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -738,52 +738,15 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
return error;
}
-/*
- * Note that while the flag value (low two bits) for sys_open means:
- * 00 - read-only
- * 01 - write-only
- * 10 - read-write
- * 11 - special
- * it is changed into
- * 00 - no permissions needed
- * 01 - read-permission
- * 10 - write-permission
- * 11 - read-write
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-struct file *filp_open(const char * filename, int flags, int mode)
-{
- int namei_flags, error;
- struct nameidata nd;
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
- namei_flags++;
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
- error = open_namei(filename, namei_flags, mode, &nd);
- if (!error)
- return dentry_open(nd.dentry, nd.mnt, flags);
-
- return ERR_PTR(error);
-}
-
-EXPORT_SYMBOL(filp_open);
-
-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ int flags, struct file *f)
{
- struct file * f;
struct inode *inode;
int error;
- error = -ENFILE;
- f = get_empty_filp();
- if (!f)
- goto cleanup_dentry;
f->f_flags = flags;
- f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
+ f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
+ FMODE_PREAD | FMODE_PWRITE;
inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
@@ -828,12 +791,63 @@ cleanup_all:
f->f_vfsmnt = NULL;
cleanup_file:
put_filp(f);
-cleanup_dentry:
dput(dentry);
mntput(mnt);
return ERR_PTR(error);
}
+/*
+ * Note that while the flag value (low two bits) for sys_open means:
+ * 00 - read-only
+ * 01 - write-only
+ * 10 - read-write
+ * 11 - special
+ * it is changed into
+ * 00 - no permissions needed
+ * 01 - read-permission
+ * 10 - write-permission
+ * 11 - read-write
+ * for the internal routines (ie open_namei()/follow_link() etc). 00 is
+ * used by symlinks.
+ */
+struct file *filp_open(const char * filename, int flags, int mode)
+{
+ int namei_flags, error;
+ struct nameidata nd;
+ struct file *f;
+
+ namei_flags = flags;
+ if ((namei_flags+1) & O_ACCMODE)
+ namei_flags++;
+ if (namei_flags & O_TRUNC)
+ namei_flags |= 2;
+
+ error = -ENFILE;
+ f = get_empty_filp();
+ if (f == NULL)
+ return ERR_PTR(error);
+
+ error = open_namei(filename, namei_flags, mode, &nd);
+ if (!error)
+ return __dentry_open(nd.dentry, nd.mnt, flags, f);
+
+ put_filp(f);
+ return ERR_PTR(error);
+}
+EXPORT_SYMBOL(filp_open);
+
+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+{
+ int error;
+ struct file *f;
+
+ error = -ENFILE;
+ f = get_empty_filp();
+ if (f == NULL)
+ return ERR_PTR(error);
+
+ return __dentry_open(dentry, mnt, flags, f);
+}
EXPORT_SYMBOL(dentry_open);
/*
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d88d518..d84eeca 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -74,6 +74,7 @@
#include <linux/file.h>
#include <linux/times.h>
#include <linux/cpuset.h>
+#include <linux/rcupdate.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer)
p->gid, p->egid, p->sgid, p->fsgid);
read_unlock(&tasklist_lock);
task_lock(p);
+ rcu_read_lock();
if (p->files)
fdt = files_fdtable(p->files);
buffer += sprintf(buffer,
"FDSize:\t%d\n"
"Groups:\t",
fdt ? fdt->max_fds : 0);
+ rcu_read_unlock();
group_info = p->group_info;
get_group_info(group_info);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index c9f178f..c20babd 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -667,7 +667,7 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
if (th->t_trans_id) {
int err;
// update any changes we made to blk count
- reiserfs_update_sd(th, inode);
+ mark_inode_dirty(inode);
err =
journal_end(th, inode->i_sb,
JOURNAL_PER_BALANCE_CNT * 3 + 1 +
@@ -855,17 +855,18 @@ static int reiserfs_submit_file_region_for_write(struct reiserfs_transaction_han
if (th->t_trans_id) {
reiserfs_write_lock(inode->i_sb);
- reiserfs_update_sd(th, inode); // And update on-disk metadata
+ // this sets the proper flags for O_SYNC to trigger a commit
+ mark_inode_dirty(inode);
reiserfs_write_unlock(inode->i_sb);
} else
- inode->i_sb->s_op->dirty_inode(inode);
+ mark_inode_dirty(inode);
sd_update = 1;
}
if (th->t_trans_id) {
reiserfs_write_lock(inode->i_sb);
if (!sd_update)
- reiserfs_update_sd(th, inode);
+ mark_inode_dirty(inode);
status = journal_end(th, th->t_super, th->t_blocks_allocated);
if (status)
retval = status;
@@ -1320,7 +1321,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
return err;
}
reiserfs_update_inode_transaction(inode);
- reiserfs_update_sd(&th, inode);
+ mark_inode_dirty(inode);
err = journal_end(&th, inode->i_sb, 1);
if (err) {
reiserfs_write_unlock(inode->i_sb);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 1a8a1bf..d76ee6c 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2639,6 +2639,12 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
}
reiserfs_update_inode_transaction(inode);
inode->i_size = pos;
+ /*
+ * this will just nest into our transaction. It's important
+ * to use mark_inode_dirty so the inode gets pushed around on the
+ * dirty lists, and so that O_SYNC works as expected
+ */
+ mark_inode_dirty(inode);
reiserfs_update_sd(&myth, inode);
update_sd = 1;
ret = journal_end(&myth, inode->i_sb, 1);
@@ -2649,21 +2655,13 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
if (th) {
reiserfs_write_lock(inode->i_sb);
if (!update_sd)
- reiserfs_update_sd(th, inode);
+ mark_inode_dirty(inode);
ret = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
if (ret)
goto out;
}
- /* we test for O_SYNC here so we can commit the transaction
- ** for any packed tails the file might have had
- */
- if (f && (f->f_flags & O_SYNC)) {
- reiserfs_write_lock(inode->i_sb);
- ret = reiserfs_commit_for_inode(inode);
- reiserfs_write_unlock(inode->i_sb);
- }
out:
return ret;
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 22b53e3..8393bf3 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -339,13 +339,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define kern_addr_valid(addr) (1)
#endif
-#define io_remap_page_range(vma, start, busaddr, size, prot) \
-({ \
- void *va = (void __force *)ioremap(busaddr, size); \
- unsigned long pfn = virt_to_phys(va) >> PAGE_SHIFT; \
- remap_pfn_range(vma, start, pfn, size, prot); \
-})
-
#define io_remap_pfn_range(vma, start, pfn, size, prot) \
remap_pfn_range(vma, start, pfn, size, prot)
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
index 681b6a6..79c9081 100644
--- a/include/asm-arm/arch-aaec2000/memory.h
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -64,10 +64,6 @@
#define NODE_MAX_MEM_SHIFT 26
#define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT)
-#else
-
-#define PFN_TO_NID(addr) (0)
-
#endif /* CONFIG_DISCONTIGMEM */
#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
index dc4735c..45351f5 100644
--- a/include/asm-arm/arch-iop3xx/memory.h
+++ b/include/asm-arm/arch-iop3xx/memory.h
@@ -36,6 +36,4 @@
#endif
-#define PFN_TO_NID(addr) (0)
-
#endif
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 75623f8..32aece0 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -370,8 +370,6 @@
#define GLOBAL_REG_BASE (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00)
#define GLOBAL_REG(x) (volatile unsigned long*)(GLOBAL_REG_BASE | (x))
-#define IXP2000_PROD_ID GLOBAL_REG(0x00)
-
#define IXP2000_MAJ_PROD_TYPE_MASK 0x001F0000
#define IXP2000_MAJ_PROD_TYPE_IXP2000 0x00000000
#define IXP2000_MIN_PROD_TYPE_MASK 0x0000FF00
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index c0caf3e..abdcf51 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -31,20 +31,24 @@
#include <asm/system.h> /* Pickup local_irq_ functions */
-static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val)
+static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
{
- volatile unsigned long dummy;
+ unsigned long dummy;
unsigned long flags;
local_irq_save(flags);
- *reg = val;
+ *((volatile unsigned long *)reg) = val;
barrier();
- dummy = *reg;
+ dummy = *((volatile unsigned long *)reg);
local_irq_restore(flags);
}
#else
-#define ixp2000_reg_write(reg, val) (*reg = val)
+static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
+{
+ *((volatile unsigned long *)reg) = val;
+}
#endif /* IXDP2400 || IXDP2401 */
+#define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg))
/*
* Boards may multiplex different devices on the 2nd channel of
@@ -84,7 +88,7 @@ void ixp2000_release_slowport(struct slowport_cfg *);
*/
static inline unsigned ixp2000_has_broken_slowport(void)
{
- unsigned long id = *IXP2000_PROD_ID;
+ unsigned long id = *IXP2000_PRODUCT_ID;
unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK |
IXP2000_MIN_PROD_TYPE_MASK);
return (((id_prod ==
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
index 7e2fea3..c650e6f 100644
--- a/include/asm-arm/arch-lh7a40x/memory.h
+++ b/include/asm-arm/arch-lh7a40x/memory.h
@@ -85,10 +85,6 @@
(((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
# endif
-#else
-
-# define PFN_TO_NID(addr) (0)
-
#endif
#endif
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
index 84f81e3..ef32d61 100644
--- a/include/asm-arm/arch-omap/memory.h
+++ b/include/asm-arm/arch-omap/memory.h
@@ -86,6 +86,5 @@
#endif /* CONFIG_ARCH_OMAP1510 */
-#define PHYS_TO_NID(addr) (0)
#endif
diff --git a/include/asm-arm/arch-pxa/akita.h b/include/asm-arm/arch-pxa/akita.h
new file mode 100644
index 0000000..4a1fbcf
--- /dev/null
+++ b/include/asm-arm/arch-pxa/akita.h
@@ -0,0 +1,30 @@
+/*
+ * Hardware specific definitions for SL-C1000 (Akita)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/* Akita IO Expander GPIOs */
+
+#define AKITA_IOEXP_RESERVED_7 (1 << 7)
+#define AKITA_IOEXP_IR_ON (1 << 6)
+#define AKITA_IOEXP_AKIN_PULLUP (1 << 5)
+#define AKITA_IOEXP_BACKLIGHT_CONT (1 << 4)
+#define AKITA_IOEXP_BACKLIGHT_ON (1 << 3)
+#define AKITA_IOEXP_MIC_BIAS (1 << 2)
+#define AKITA_IOEXP_RESERVED_1 (1 << 1)
+#define AKITA_IOEXP_RESERVED_0 (1 << 0)
+
+/* Direction Bitfield 0=output 1=input */
+#define AKITA_IOEXP_IO_DIR 0
+/* Default Values */
+#define AKITA_IOEXP_IO_OUT (AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP)
+
+void akita_set_ioexp(struct device *dev, unsigned char bitmask);
+void akita_reset_ioexp(struct device *dev, unsigned char bitmask);
+
diff --git a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h
index 4b7aa0b..e554caa 100644
--- a/include/asm-arm/arch-pxa/corgi.h
+++ b/include/asm-arm/arch-pxa/corgi.h
@@ -106,17 +106,5 @@ extern struct platform_device corgiscoop_device;
extern struct platform_device corgissp_device;
extern struct platform_device corgifb_device;
-/*
- * External Functions
- */
-extern unsigned long corgi_ssp_ads7846_putget(unsigned long);
-extern unsigned long corgi_ssp_ads7846_get(void);
-extern void corgi_ssp_ads7846_put(unsigned long data);
-extern void corgi_ssp_ads7846_lock(void);
-extern void corgi_ssp_ads7846_unlock(void);
-extern void corgi_ssp_lcdtg_send (unsigned char adrs, unsigned char data);
-extern void corgi_ssp_blduty_set(int duty);
-extern int corgi_ssp_max1111_get(unsigned long data);
-
#endif /* __ASM_ARCH_CORGI_H */
diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h
index 217a80b..58bad97 100644
--- a/include/asm-arm/arch-pxa/memory.h
+++ b/include/asm-arm/arch-pxa/memory.h
@@ -67,10 +67,6 @@
#define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
-#else
-
-#define PFN_TO_NID(addr) (0)
-
#endif
#endif
diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h
index 58bda9d..6b5ac51 100644
--- a/include/asm-arm/arch-pxa/poodle.h
+++ b/include/asm-arm/arch-pxa/poodle.h
@@ -37,24 +37,25 @@
#define POODLE_GPIO_nSD_DETECT (9)
#define POODLE_GPIO_MAIN_BAT_LOW (13)
#define POODLE_GPIO_BAT_COVER (13)
+#define POODLE_GPIO_USB_PULLUP (20)
#define POODLE_GPIO_ADC_TEMP_ON (21)
#define POODLE_GPIO_BYPASS_ON (36)
#define POODLE_GPIO_CHRG_ON (38)
#define POODLE_GPIO_CHRG_FULL (16)
/* PXA GPIOs */
-#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO0
-#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO1
-#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO4
-#define POODLE_IRQ_GPIO_CO IRQ_GPIO16
-#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO5
-#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO11
-#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO10
-#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO17
-#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO14
-#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO8
-#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO9
-#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO13
+#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO(0)
+#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO(1)
+#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO(4)
+#define POODLE_IRQ_GPIO_CO IRQ_GPIO(16)
+#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO(5)
+#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO(11)
+#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO(10)
+#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO(17)
+#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO(14)
+#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO(8)
+#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9)
+#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(13)
/* SCOOP GPIOs */
#define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11
diff --git a/include/asm-arm/arch-pxa/sharpsl.h b/include/asm-arm/arch-pxa/sharpsl.h
new file mode 100644
index 0000000..311f2bb
--- /dev/null
+++ b/include/asm-arm/arch-pxa/sharpsl.h
@@ -0,0 +1,32 @@
+/*
+ * SharpSL SSP Driver
+ */
+
+unsigned long corgi_ssp_ads7846_putget(unsigned long);
+unsigned long corgi_ssp_ads7846_get(void);
+void corgi_ssp_ads7846_put(unsigned long data);
+void corgi_ssp_ads7846_lock(void);
+void corgi_ssp_ads7846_unlock(void);
+void corgi_ssp_lcdtg_send (unsigned char adrs, unsigned char data);
+void corgi_ssp_blduty_set(int duty);
+int corgi_ssp_max1111_get(unsigned long data);
+
+/*
+ * SharpSL Touchscreen Driver
+ */
+
+struct corgits_machinfo {
+ unsigned long (*get_hsync_len)(void);
+ void (*put_hsync)(void);
+ void (*wait_hsync)(void);
+};
+
+/*
+ * SharpSL Backlight
+ */
+
+struct corgibl_machinfo {
+ int max_intensity;
+ void (*set_bl_intensity)(int intensity);
+};
+
diff --git a/include/asm-arm/arch-pxa/spitz.h b/include/asm-arm/arch-pxa/spitz.h
new file mode 100644
index 0000000..62e1fe4
--- /dev/null
+++ b/include/asm-arm/arch-pxa/spitz.h
@@ -0,0 +1,158 @@
+/*
+ * Hardware specific definitions for SL-Cx000 series of PDAs
+ *
+ * Copyright (c) 2005 Alexander Wykes
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_SPITZ_H
+#define __ASM_ARCH_SPITZ_H 1
+#endif
+
+/* Spitz/Akita GPIOs */
+
+#define SPITZ_GPIO_KEY_INT (0) /* Key Interrupt */
+#define SPITZ_GPIO_RESET (1)
+#define SPITZ_GPIO_nSD_DETECT (9)
+#define SPITZ_GPIO_TP_INT (11) /* Touch Panel interrupt */
+#define SPITZ_GPIO_AK_INT (13) /* Remote Control */
+#define SPITZ_GPIO_ADS7846_CS (14)
+#define SPITZ_GPIO_SYNC (16)
+#define SPITZ_GPIO_MAX1111_CS (20)
+#define SPITZ_GPIO_FATAL_BAT (21)
+#define SPITZ_GPIO_HSYNC (22)
+#define SPITZ_GPIO_nSD_CLK (32)
+#define SPITZ_GPIO_USB_DEVICE (35)
+#define SPITZ_GPIO_USB_HOST (37)
+#define SPITZ_GPIO_USB_CONNECT (41)
+#define SPITZ_GPIO_LCDCON_CS (53)
+#define SPITZ_GPIO_nPCE (54)
+#define SPITZ_GPIO_nSD_WP (81)
+#define SPITZ_GPIO_ON_RESET (89)
+#define SPITZ_GPIO_BAT_COVER (90)
+#define SPITZ_GPIO_CF_CD (94)
+#define SPITZ_GPIO_ON_KEY (95)
+#define SPITZ_GPIO_SWA (97)
+#define SPITZ_GPIO_SWB (96)
+#define SPITZ_GPIO_CHRG_FULL (101)
+#define SPITZ_GPIO_CO (101)
+#define SPITZ_GPIO_CF_IRQ (105)
+#define SPITZ_GPIO_AC_IN (115)
+#define SPITZ_GPIO_HP_IN (116)
+
+/* Spitz Only GPIOs */
+
+#define SPITZ_GPIO_CF2_IRQ (106) /* CF slot1 Ready */
+#define SPITZ_GPIO_CF2_CD (93)
+
+
+/* Spitz/Akita Keyboard Definitions */
+
+#define SPITZ_KEY_STROBE_NUM (11)
+#define SPITZ_KEY_SENSE_NUM (7)
+#define SPITZ_GPIO_G0_STROBE_BIT 0x0f800000
+#define SPITZ_GPIO_G1_STROBE_BIT 0x00100000
+#define SPITZ_GPIO_G2_STROBE_BIT 0x01000000
+#define SPITZ_GPIO_G3_STROBE_BIT 0x00041880
+#define SPITZ_GPIO_G0_SENSE_BIT 0x00021000
+#define SPITZ_GPIO_G1_SENSE_BIT 0x000000d4
+#define SPITZ_GPIO_G2_SENSE_BIT 0x08000000
+#define SPITZ_GPIO_G3_SENSE_BIT 0x00000000
+
+#define SPITZ_GPIO_KEY_STROBE0 88
+#define SPITZ_GPIO_KEY_STROBE1 23
+#define SPITZ_GPIO_KEY_STROBE2 24
+#define SPITZ_GPIO_KEY_STROBE3 25
+#define SPITZ_GPIO_KEY_STROBE4 26
+#define SPITZ_GPIO_KEY_STROBE5 27
+#define SPITZ_GPIO_KEY_STROBE6 52
+#define SPITZ_GPIO_KEY_STROBE7 103
+#define SPITZ_GPIO_KEY_STROBE8 107
+#define SPITZ_GPIO_KEY_STROBE9 108
+#define SPITZ_GPIO_KEY_STROBE10 114
+
+#define SPITZ_GPIO_KEY_SENSE0 12
+#define SPITZ_GPIO_KEY_SENSE1 17
+#define SPITZ_GPIO_KEY_SENSE2 91
+#define SPITZ_GPIO_KEY_SENSE3 34
+#define SPITZ_GPIO_KEY_SENSE4 36
+#define SPITZ_GPIO_KEY_SENSE5 38
+#define SPITZ_GPIO_KEY_SENSE6 39
+
+
+/* Spitz Scoop Device (No. 1) GPIOs */
+/* Suspend States in comments */
+#define SPITZ_SCP_LED_GREEN SCOOP_GPCR_PA11 /* Keep */
+#define SPITZ_SCP_JK_B SCOOP_GPCR_PA12 /* Keep */
+#define SPITZ_SCP_CHRG_ON SCOOP_GPCR_PA13 /* Keep */
+#define SPITZ_SCP_MUTE_L SCOOP_GPCR_PA14 /* Low */
+#define SPITZ_SCP_MUTE_R SCOOP_GPCR_PA15 /* Low */
+#define SPITZ_SCP_CF_POWER SCOOP_GPCR_PA16 /* Keep */
+#define SPITZ_SCP_LED_ORANGE SCOOP_GPCR_PA17 /* Keep */
+#define SPITZ_SCP_JK_A SCOOP_GPCR_PA18 /* Low */
+#define SPITZ_SCP_ADC_TEMP_ON SCOOP_GPCR_PA19 /* Low */
+
+#define SPITZ_SCP_IO_DIR (SPITZ_SCP_LED_GREEN | SPITZ_SCP_JK_B | SPITZ_SCP_CHRG_ON | \
+ SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_LED_ORANGE | \
+ SPITZ_SCP_CF_POWER | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON)
+#define SPITZ_SCP_IO_OUT (SPITZ_SCP_CHRG_ON | SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R)
+#define SPITZ_SCP_SUS_CLR (SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON)
+#define SPITZ_SCP_SUS_SET 0
+
+/* Spitz Scoop Device (No. 2) GPIOs */
+/* Suspend States in comments */
+#define SPITZ_SCP2_IR_ON SCOOP_GPCR_PA11 /* High */
+#define SPITZ_SCP2_AKIN_PULLUP SCOOP_GPCR_PA12 /* Keep */
+#define SPITZ_SCP2_RESERVED_1 SCOOP_GPCR_PA13 /* High */
+#define SPITZ_SCP2_RESERVED_2 SCOOP_GPCR_PA14 /* Low */
+#define SPITZ_SCP2_RESERVED_3 SCOOP_GPCR_PA15 /* Low */
+#define SPITZ_SCP2_RESERVED_4 SCOOP_GPCR_PA16 /* Low */
+#define SPITZ_SCP2_BACKLIGHT_CONT SCOOP_GPCR_PA17 /* Low */
+#define SPITZ_SCP2_BACKLIGHT_ON SCOOP_GPCR_PA18 /* Low */
+#define SPITZ_SCP2_MIC_BIAS SCOOP_GPCR_PA19 /* Low */
+
+#define SPITZ_SCP2_IO_DIR (SPITZ_SCP2_IR_ON | SPITZ_SCP2_AKIN_PULLUP | SPITZ_SCP2_RESERVED_1 | \
+ SPITZ_SCP2_RESERVED_2 | SPITZ_SCP2_RESERVED_3 | SPITZ_SCP2_RESERVED_4 | \
+ SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS)
+
+#define SPITZ_SCP2_IO_OUT (SPITZ_SCP2_IR_ON | SPITZ_SCP2_AKIN_PULLUP | SPITZ_SCP2_RESERVED_1)
+#define SPITZ_SCP2_SUS_CLR (SPITZ_SCP2_RESERVED_2 | SPITZ_SCP2_RESERVED_3 | SPITZ_SCP2_RESERVED_4 | \
+ SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS)
+#define SPITZ_SCP2_SUS_SET (SPITZ_SCP2_IR_ON | SPITZ_SCP2_RESERVED_1)
+
+
+/* Spitz IRQ Definitions */
+
+#define SPITZ_IRQ_GPIO_KEY_INT IRQ_GPIO(SPITZ_GPIO_KEY_INT)
+#define SPITZ_IRQ_GPIO_AC_IN IRQ_GPIO(SPITZ_GPIO_AC_IN)
+#define SPITZ_IRQ_GPIO_AK_INT IRQ_GPIO(SPITZ_GPIO_AK_INT)
+#define SPITZ_IRQ_GPIO_HP_IN IRQ_GPIO(SPITZ_GPIO_HP_IN)
+#define SPITZ_IRQ_GPIO_TP_INT IRQ_GPIO(SPITZ_GPIO_TP_INT)
+#define SPITZ_IRQ_GPIO_SYNC IRQ_GPIO(SPITZ_GPIO_SYNC)
+#define SPITZ_IRQ_GPIO_ON_KEY IRQ_GPIO(SPITZ_GPIO_ON_KEY)
+#define SPITZ_IRQ_GPIO_SWA IRQ_GPIO(SPITZ_GPIO_SWA)
+#define SPITZ_IRQ_GPIO_SWB IRQ_GPIO(SPITZ_GPIO_SWB)
+#define SPITZ_IRQ_GPIO_BAT_COVER IRQ_GPIO(SPITZ_GPIO_BAT_COVER)
+#define SPITZ_IRQ_GPIO_FATAL_BAT IRQ_GPIO(SPITZ_GPIO_FATAL_BAT)
+#define SPITZ_IRQ_GPIO_CO IRQ_GPIO(SPITZ_GPIO_CO)
+#define SPITZ_IRQ_GPIO_CF_IRQ IRQ_GPIO(SPITZ_GPIO_CF_IRQ)
+#define SPITZ_IRQ_GPIO_CF_CD IRQ_GPIO(SPITZ_GPIO_CF_CD)
+#define SPITZ_IRQ_GPIO_CF2_IRQ IRQ_GPIO(SPITZ_GPIO_CF2_IRQ)
+#define SPITZ_IRQ_GPIO_nSD_INT IRQ_GPIO(SPITZ_GPIO_nSD_INT)
+#define SPITZ_IRQ_GPIO_nSD_DETECT IRQ_GPIO(SPITZ_GPIO_nSD_DETECT)
+
+/*
+ * Shared data structures
+ */
+extern struct platform_device spitzscoop_device;
+extern struct platform_device spitzscoop2_device;
+extern struct platform_device spitzssp_device;
+extern struct sharpsl_charger_machinfo spitz_pm_machinfo;
+
+extern void spitz_lcd_power(int on);
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index 32d3d5b..8743ff5 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -99,10 +99,6 @@ __arch_adjust_zones(int node, unsigned long *size, unsigned long *holes)
#define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT)
-#else
-
-#define PFN_TO_NID(addr) (0)
-
#endif
#endif
diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h
index 2cac5ec..9feff4ce 100644
--- a/include/asm-arm/futex.h
+++ b/include/asm-arm/futex.h
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
- int oldval = 0, ret, tem;
+ int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
diff --git a/include/asm-arm/hardware/arm_twd.h b/include/asm-arm/hardware/arm_twd.h
new file mode 100644
index 0000000..131d5b4
--- /dev/null
+++ b/include/asm-arm/hardware/arm_twd.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_HARDWARE_TWD_H
+#define __ASM_HARDWARE_TWD_H
+
+#define TWD_TIMER_LOAD 0x00
+#define TWD_TIMER_COUNTER 0x04
+#define TWD_TIMER_CONTROL 0x08
+#define TWD_TIMER_INTSTAT 0x0C
+
+#define TWD_WDOG_LOAD 0x20
+#define TWD_WDOG_COUNTER 0x24
+#define TWD_WDOG_CONTROL 0x28
+#define TWD_WDOG_INTSTAT 0x2C
+#define TWD_WDOG_RESETSTAT 0x30
+#define TWD_WDOG_DISABLE 0x34
+
+#endif
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index e47bea7..a8a933a 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -160,12 +160,25 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define page_to_pfn(page) \
(( (page) - page_zone(page)->zone_mem_map) \
+ page_zone(page)->zone_start_pfn)
+
#define pfn_to_page(pfn) \
(PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
-#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES)
+
+#define pfn_valid(pfn) \
+ ({ \
+ unsigned int nid = PFN_TO_NID(pfn); \
+ int valid = nid < MAX_NUMNODES; \
+ if (valid) { \
+ pg_data_t *node = NODE_DATA(nid); \
+ valid = (pfn - node->node_start_pfn) < \
+ node->node_spanned_pages; \
+ } \
+ valid; \
+ })
#define virt_to_page(kaddr) \
(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
/*
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 478c49b..366bafb 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -445,12 +445,9 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define HAVE_ARCH_UNMAPPED_AREA
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index 4a0a00d..f602cf5 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -294,12 +294,9 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
#include <asm-generic/pgtable.h>
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index d0a9c2f..473fb4b 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -500,9 +500,6 @@ static inline int pte_file(pte_t pte)
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-h8300/pgtable.h b/include/asm-h8300/pgtable.h
index 69076eb..f6e296f 100644
--- a/include/asm-h8300/pgtable.h
+++ b/include/asm-h8300/pgtable.h
@@ -52,8 +52,6 @@ extern int is_in_rom(unsigned long);
* No page table caches to initialise
*/
#define pgtable_cache_init() do { } while (0)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 47bc1ff..d101ac4 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -431,9 +431,6 @@ extern void noexec_setup(const char *str);
#define kern_addr_valid(addr) (1)
#endif /* CONFIG_FLATMEM */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 2e34c06..3339c7b 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -443,10 +443,6 @@ extern void paging_init (void);
#define pte_to_pgoff(pte) ((pte_val(pte) << 1) >> 3)
#define pgoff_to_pte(off) ((pte_t) { ((off) << 2) | _PAGE_FILE })
-/* XXX is this right? */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index fc54492..a79d1a7 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -57,7 +57,9 @@
#include <linux/config.h>
#include <asm/fpu.h>
+#ifndef ASM_OFFSETS_C
#include <asm/asm-offsets.h>
+#endif
/*
* Base-2 logarithm of number of pages to allocate per task structure
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index cf4a950..171b220 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -5,7 +5,9 @@
#ifndef _ASM_IA64_THREAD_INFO_H
#define _ASM_IA64_THREAD_INFO_H
+#ifndef ASM_OFFSETS_C
#include <asm/asm-offsets.h>
+#endif
#include <asm/processor.h>
#include <asm/ptrace.h>
@@ -51,9 +53,14 @@ struct thread_info {
}, \
}
+#ifndef ASM_OFFSETS_C
/* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
#define alloc_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#else
+#define current_thread_info() ((struct thread_info *) 0)
+#define alloc_thread_info(tsk) ((struct thread_info *) 0)
+#endif
#define free_thread_info(ti) /* nothing */
#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index da805e9..388e5ee 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -378,9 +378,6 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 0c87fc8..add129e 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -141,9 +141,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-m68knommu/pgtable.h b/include/asm-m68knommu/pgtable.h
index e2a69ff..0089305 100644
--- a/include/asm-m68knommu/pgtable.h
+++ b/include/asm-m68knommu/pgtable.h
@@ -56,8 +56,6 @@ extern int is_in_rom(unsigned long);
* No page table caches to initialise.
*/
#define pgtable_cache_init() do { } while (0)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index dbe13da..cbd1672 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -358,16 +358,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);
-static inline int io_remap_page_range(struct vm_area_struct *vma,
- unsigned long vaddr,
- unsigned long paddr,
- unsigned long size,
- pgprot_t prot)
-{
- phys_t phys_addr_high = fixup_bigphys_addr(paddr, size);
- return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
-}
-
static inline int io_remap_pfn_range(struct vm_area_struct *vma,
unsigned long vaddr,
unsigned long pfn,
@@ -378,8 +368,6 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
return remap_pfn_range(vma, vaddr, pfn, size, prot);
}
#else
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index f001bb0..820c6e7 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -498,9 +498,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
#endif /* !__ASSEMBLY__ */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index 5575247..bd96748 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -138,6 +138,16 @@ irq_canonicalize(int irq)
#define SIU_IRQ7 (14)
#define SIU_LEVEL7 (15)
+#define MPC8xx_INT_FEC1 SIU_LEVEL1
+#define MPC8xx_INT_FEC2 SIU_LEVEL3
+
+#define MPC8xx_INT_SCC1 (CPM_IRQ_OFFSET + CPMVEC_SCC1)
+#define MPC8xx_INT_SCC2 (CPM_IRQ_OFFSET + CPMVEC_SCC2)
+#define MPC8xx_INT_SCC3 (CPM_IRQ_OFFSET + CPMVEC_SCC3)
+#define MPC8xx_INT_SCC4 (CPM_IRQ_OFFSET + CPMVEC_SCC4)
+#define MPC8xx_INT_SMC1 (CPM_IRQ_OFFSET + CPMVEC_SMC1)
+#define MPC8xx_INT_SMC2 (CPM_IRQ_OFFSET + CPMVEC_SMC2)
+
/* The internal interrupts we can configure as we see fit.
* My personal preference is CPM at level 2, which puts it above the
* MBX PCI/ISA/IDE interrupts.
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index dc8e598..208a2e1 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -97,6 +97,22 @@ extern unsigned char __res[];
struct pt_regs;
+enum ppc_sys_devices {
+ MPC8xx_CPM_FEC1,
+ MPC8xx_CPM_FEC2,
+ MPC8xx_CPM_I2C,
+ MPC8xx_CPM_SCC1,
+ MPC8xx_CPM_SCC2,
+ MPC8xx_CPM_SCC3,
+ MPC8xx_CPM_SCC4,
+ MPC8xx_CPM_SPI,
+ MPC8xx_CPM_MCC1,
+ MPC8xx_CPM_MCC2,
+ MPC8xx_CPM_SMC1,
+ MPC8xx_CPM_SMC2,
+ MPC8xx_CPM_USB,
+};
+
#endif /* !__ASSEMBLY__ */
#endif /* CONFIG_8xx */
#endif /* __CONFIG_8xx_DEFS */
diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h
index 835930d..75c2ffa 100644
--- a/include/asm-ppc/mv64x60.h
+++ b/include/asm-ppc/mv64x60.h
@@ -119,6 +119,14 @@ extern spinlock_t mv64x60_lock;
#define MV64x60_64BIT_WIN_COUNT 24
+/* Watchdog Platform Device, Driver Data */
+#define MV64x60_WDT_NAME "wdt"
+
+struct mv64x60_wdt_pdata {
+ int timeout; /* watchdog expiry in seconds, default 10 */
+ int bus_clk; /* bus clock in MHz, default 133 */
+};
+
/*
* Define a structure that's used to pass in config information to the
* core routines.
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 92f30b2..eee601b 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -812,15 +812,6 @@ extern void kernel_set_cachemode (unsigned long address, unsigned long size,
#ifdef CONFIG_PHYS_64BIT
extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long paddr, unsigned long size, pgprot_t prot);
-static inline int io_remap_page_range(struct vm_area_struct *vma,
- unsigned long vaddr,
- unsigned long paddr,
- unsigned long size,
- pgprot_t prot)
-{
- phys_addr_t paddr64 = fixup_bigphys_addr(paddr, size);
- return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
-}
static inline int io_remap_pfn_range(struct vm_area_struct *vma,
unsigned long vaddr,
@@ -832,8 +823,6 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
}
#else
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 048f7c8..549f4484 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -27,6 +27,8 @@
#include <asm/mpc83xx.h>
#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
+#elif defined(CONFIG_8xx)
+#include <asm/mpc8xx.h>
#elif defined(CONFIG_PPC_MPC52xx)
#include <asm/mpc52xx.h>
#elif defined(CONFIG_MPC10X_BRIDGE)
diff --git a/include/asm-ppc/segment.h b/include/asm-ppc/segment.h
deleted file mode 100644
index 0f2f742..0000000
--- a/include/asm-ppc/segment.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm/uaccess.h>
diff --git a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h
index 9850f53..9afee4f 100644
--- a/include/asm-ppc/tlbflush.h
+++ b/include/asm-ppc/tlbflush.h
@@ -72,7 +72,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
unsigned long vmaddr)
{ _tlbie(vmaddr); }
-static inline void flush_tlb_range(struct mm_struct *mm,
+static inline void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{ __tlbia(); }
static inline void flush_tlb_kernel_range(unsigned long start,
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index ecb9095..0f4bcaa 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -277,9 +277,6 @@ typedef pte_t *pte_addr_t;
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 78ac6be..51db430 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -482,9 +482,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
#define PageSkip(page) (0)
#define kern_addr_valid(addr) (1)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index b2fc94f..2d24236 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -21,6 +21,7 @@ struct thread_struct {
* copy_thread) to mark that we are begin called from userspace (fork /
* vfork / clone), and reset to 0 after. It is left to 0 when called
* from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */
+ struct task_struct *saved_task;
int forking;
int nsyscalls;
struct pt_regs regs;
diff --git a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h
index ea8381d..c436263 100644
--- a/include/asm-um/system-i386.h
+++ b/include/asm-um/system-i386.h
@@ -3,6 +3,4 @@
#include "asm/system-generic.h"
-#define __HAVE_ARCH_CMPXCHG 1
-
#endif
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index 594e610..68ac3c6 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -8,6 +8,8 @@
#ifndef __ASSEMBLY__
#include <linux/string.h>
+#include <linux/smp.h>
+
#include <asm/segment.h>
#include <asm/mmu.h>
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 1dc110b..2cb4835 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -421,9 +421,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
extern int kern_addr_valid(unsigned long addr);
-#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 883ebc2..987e3b8 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -441,11 +441,11 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte);
/*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#define io_remap_page_range(vma,from,phys,size,prot) \
- remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ remap_pfn_range(vma, from, pfn, size, prot)
/* No page table caches to init */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 68aba0c..b2a2509 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -51,7 +51,8 @@
#define AUDIT_WATCH_LIST 1009 /* List all file/dir watches */
#define AUDIT_SIGNAL_INFO 1010 /* Get info about sender of signal to auditd */
-#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages uninteresting to kernel */
+#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
+#define AUDIT_USER_AVC 1107 /* We filter this differently */
#define AUDIT_LAST_USER_MSG 1199
#define AUDIT_DAEMON_START 1200 /* Daemon startup record */
@@ -75,10 +76,15 @@
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
/* Rule flags */
-#define AUDIT_PER_TASK 0x01 /* Apply rule at task creation (not syscall) */
-#define AUDIT_AT_ENTRY 0x02 /* Apply rule at syscall entry */
-#define AUDIT_AT_EXIT 0x04 /* Apply rule at syscall exit */
-#define AUDIT_PREPEND 0x10 /* Prepend to front of list */
+#define AUDIT_FILTER_USER 0x00 /* Apply rule to user-generated messages */
+#define AUDIT_FILTER_TASK 0x01 /* Apply rule at task creation (not syscall) */
+#define AUDIT_FILTER_ENTRY 0x02 /* Apply rule at syscall entry */
+#define AUDIT_FILTER_WATCH 0x03 /* Apply rule to file system watches */
+#define AUDIT_FILTER_EXIT 0x04 /* Apply rule at syscall exit */
+
+#define AUDIT_NR_FILTERS 5
+
+#define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */
/* Rule actions */
#define AUDIT_NEVER 0 /* Do not build context if rule matches */
@@ -199,6 +205,7 @@ struct audit_sig_info {
struct audit_buffer;
struct audit_context;
struct inode;
+struct netlink_skb_parms;
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
@@ -215,7 +222,7 @@ extern void audit_syscall_entry(struct task_struct *task, int arch,
extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
extern void audit_getname(const char *name);
extern void audit_putname(const char *name);
-extern void audit_inode(const char *name, const struct inode *inode);
+extern void audit_inode(const char *name, const struct inode *inode, unsigned flags);
/* Private API (for audit.c only) */
extern int audit_receive_filter(int type, int pid, int uid, int seq,
@@ -230,6 +237,7 @@ extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern void audit_signal_info(int sig, struct task_struct *t);
+extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -237,7 +245,7 @@ extern void audit_signal_info(int sig, struct task_struct *t);
#define audit_syscall_exit(t,f,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
-#define audit_inode(n,i) do { ; } while (0)
+#define audit_inode(n,i,f) do { ; } while (0)
#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
@@ -246,16 +254,17 @@ extern void audit_signal_info(int sig, struct task_struct *t);
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
+#define audit_filter_user(cb,t) ({ 1; })
#endif
#ifdef CONFIG_AUDIT
/* These are defined in audit.c */
/* Public API */
-extern void audit_log(struct audit_context *ctx, int type,
- const char *fmt, ...)
- __attribute__((format(printf,3,4)));
+extern void audit_log(struct audit_context *ctx, int gfp_mask,
+ int type, const char *fmt, ...)
+ __attribute__((format(printf,4,5)));
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx,int type);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask, int type);
extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
@@ -274,9 +283,10 @@ extern void audit_send_reply(int pid, int seq, int type,
int done, int multi,
void *payload, int size);
extern void audit_log_lost(const char *message);
+extern struct semaphore audit_netlink_sem;
#else
-#define audit_log(c,t,f,...) do { ; } while (0)
-#define audit_log_start(c,t) ({ NULL; })
+#define audit_log(c,g,t,f,...) do { ; } while (0)
+#define audit_log_start(c,g,t) ({ NULL; })
#define audit_log_vformat(b,f,a) do { ; } while (0)
#define audit_log_format(b,f,...) do { ; } while (0)
#define audit_log_end(b) do { ; } while (0)
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 8bf4bac..71fab43 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -4,16 +4,6 @@
#include <linux/types.h>
#include <asm/byteorder.h>
-/* Structure describing an Internet (DCCP) socket address. */
-struct sockaddr_dccp {
- __u16 sdccp_family; /* Address family */
- __u16 sdccp_port; /* Port number */
- __u32 sdccp_addr; /* Internet address */
- __u32 sdccp_service; /* Service */
- /* Pad to size of `struct sockaddr': 16 bytes . */
- __u32 sdccp_pad;
-};
-
/**
* struct dccp_hdr - generic part of DCCP packet header
*
@@ -188,6 +178,11 @@ enum {
/* DCCP socket options */
#define DCCP_SOCKOPT_PACKET_SIZE 1
+#define DCCP_SOCKOPT_SERVICE 2
+#define DCCP_SOCKOPT_CCID_RX_INFO 128
+#define DCCP_SOCKOPT_CCID_TX_INFO 192
+
+#define DCCP_SERVICE_LIST_MAX_LEN 32
#ifdef __KERNEL__
@@ -337,7 +332,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
*/
struct dccp_options {
__u64 dccpo_sequence_window;
- __u8 dccpo_ccid;
+ __u8 dccpo_rx_ccid;
+ __u8 dccpo_tx_ccid;
__u8 dccpo_send_ack_vector;
__u8 dccpo_send_ndp_count;
};
@@ -360,14 +356,8 @@ static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req)
extern struct inet_timewait_death_row dccp_death_row;
-/* Read about the ECN nonce to see why it is 253 */
-#define DCCP_MAX_ACK_VECTOR_LEN 253
-
struct dccp_options_received {
- u32 dccpor_ndp:24,
- dccpor_ack_vector_len:8;
- u32 dccpor_ack_vector_idx:10;
- /* 22 bits hole, try to pack */
+ u32 dccpor_ndp; /* only 24 bits */
u32 dccpor_timestamp;
u32 dccpor_timestamp_echo;
u32 dccpor_elapsed_time;
@@ -382,6 +372,27 @@ enum dccp_role {
DCCP_ROLE_SERVER,
};
+struct dccp_service_list {
+ __u32 dccpsl_nr;
+ __u32 dccpsl_list[0];
+};
+
+#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1)
+
+static inline int dccp_list_has_service(const struct dccp_service_list *sl,
+ const u32 service)
+{
+ if (likely(sl != NULL)) {
+ u32 i = sl->dccpsl_nr;
+ while (i--)
+ if (sl->dccpsl_list[i] == service)
+ return 1;
+ }
+ return 0;
+}
+
+struct dccp_ackvec;
+
/**
* struct dccp_sock - DCCP socket state
*
@@ -402,7 +413,7 @@ enum dccp_role {
* @dccps_packet_size - Set thru setsockopt
* @dccps_role - Role of this sock, one of %dccp_role
* @dccps_ndp_count - number of Non Data Packets since last data packet
- * @dccps_hc_rx_ackpkts - receiver half connection acked packets
+ * @dccps_hc_rx_ackvec - rx half connection ack vector
*/
struct dccp_sock {
/* inet_connection_sock has to be the first member of dccp_sock */
@@ -417,7 +428,8 @@ struct dccp_sock {
__u64 dccps_gss;
__u64 dccps_gsr;
__u64 dccps_gar;
- unsigned long dccps_service;
+ __u32 dccps_service;
+ struct dccp_service_list *dccps_service_list;
struct timeval dccps_timestamp_time;
__u32 dccps_timestamp_echo;
__u32 dccps_packet_size;
@@ -426,7 +438,7 @@ struct dccp_sock {
__u32 dccps_pmtu_cookie;
__u32 dccps_mss_cache;
struct dccp_options dccps_options;
- struct dccp_ackpkts *dccps_hc_rx_ackpkts;
+ struct dccp_ackvec *dccps_hc_rx_ackvec;
void *dccps_hc_rx_ccid_private;
void *dccps_hc_tx_ccid_private;
struct ccid *dccps_hc_rx_ccid;
@@ -443,6 +455,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk)
return (struct dccp_sock *)sk;
}
+static inline int dccp_service_not_initialized(const struct sock *sk)
+{
+ return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE;
+}
+
static inline const char *dccp_role(const struct sock *sk)
{
switch (dccp_sk(sk)->dccps_role) {
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 82e39cd..c698055 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -619,7 +619,7 @@ struct fb_tilemap {
__u32 height; /* height of each tile in scanlines */
__u32 depth; /* color depth of each tile */
__u32 length; /* number of tiles in the map */
- __u8 *data; /* actual tile map: a bitmap array, packed
+ const __u8 *data; /* actual tile map: a bitmap array, packed
to the nearest byte */
};
diff --git a/include/linux/font.h b/include/linux/font.h
index 8fc80a7..53b129f 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -15,9 +15,9 @@
struct font_desc {
int idx;
- char *name;
+ const char *name;
int width, height;
- void *data;
+ const void *data;
int pref;
};
@@ -32,7 +32,7 @@ struct font_desc {
#define ACORN8x8_IDX 8
#define MINI4x6_IDX 9
-extern struct font_desc font_vga_8x8,
+extern const struct font_desc font_vga_8x8,
font_vga_8x16,
font_pearl_8x8,
font_vga_6x11,
@@ -45,11 +45,11 @@ extern struct font_desc font_vga_8x8,
/* Find a font with a specific name */
-extern struct font_desc *find_font(char *name);
+extern const struct font_desc *find_font(const char *name);
/* Get the default font for a specific screen size */
-extern struct font_desc *get_default_font(int xres, int yres);
+extern const struct font_desc *get_default_font(int xres, int yres);
/* Max. length for the name of a predefined font */
#define MAX_FONT_NAME 32
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index be35332..3d49a30 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -230,11 +230,6 @@ struct i2c_adapter {
struct device dev; /* the adapter device */
struct class_device class_dev; /* the class device */
-#ifdef CONFIG_PROC_FS
- /* No need to set this when you initialize the adapter */
- int inode;
-#endif /* def CONFIG_PROC_FS */
-
int nr;
struct list_head clients;
struct list_head list;
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 17d0c0d..eef0876 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -42,8 +42,8 @@ struct hlist_node;
struct vlan_ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
- unsigned short h_vlan_proto; /* Should always be 0x8100 */
- unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */
+ __be16 h_vlan_proto; /* Should always be 0x8100 */
+ __be16 h_vlan_TCI; /* Encapsulates priority and VLAN ID */
unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */
};
@@ -55,8 +55,8 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
}
struct vlan_hdr {
- unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */
- unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */
+ __be16 h_vlan_TCI; /* Encapsulates priority and VLAN ID */
+ __be16 h_vlan_encapsulated_proto; /* packet type ID field (or len) */
};
#define VLAN_VID_MASK 0xfff
diff --git a/include/linux/joystick.h b/include/linux/joystick.h
index 06b9af7..5fd20dd 100644
--- a/include/linux/joystick.h
+++ b/include/linux/joystick.h
@@ -111,29 +111,30 @@ struct js_corr {
#define JS_SET_ALL 8
struct JS_DATA_TYPE {
- __s32 buttons;
- __s32 x;
- __s32 y;
+ int32_t buttons;
+ int32_t x;
+ int32_t y;
};
struct JS_DATA_SAVE_TYPE_32 {
- __s32 JS_TIMEOUT;
- __s32 BUSY;
- __s32 JS_EXPIRETIME;
- __s32 JS_TIMELIMIT;
+ int32_t JS_TIMEOUT;
+ int32_t BUSY;
+ int32_t JS_EXPIRETIME;
+ int32_t JS_TIMELIMIT;
struct JS_DATA_TYPE JS_SAVE;
struct JS_DATA_TYPE JS_CORR;
};
struct JS_DATA_SAVE_TYPE_64 {
- __s32 JS_TIMEOUT;
- __s32 BUSY;
- __s64 JS_EXPIRETIME;
- __s64 JS_TIMELIMIT;
+ int32_t JS_TIMEOUT;
+ int32_t BUSY;
+ int64_t JS_EXPIRETIME;
+ int64_t JS_TIMELIMIT;
struct JS_DATA_TYPE JS_SAVE;
struct JS_DATA_TYPE JS_CORR;
};
+#ifdef __KERNEL__
#if BITS_PER_LONG == 64
#define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64
#elif BITS_PER_LONG == 32
@@ -141,5 +142,6 @@ struct JS_DATA_SAVE_TYPE_64 {
#else
#error Unexpected BITS_PER_LONG
#endif
+#endif
#endif /* _LINUX_JOYSTICK_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 687ba8c..4367ce4 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -307,8 +307,8 @@ struct sysinfo {
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};
-extern void BUILD_BUG(void);
-#define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
+/* Force a compilation error if condition is false */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#ifdef CONFIG_SYSCTL
extern int randomize_va_space;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 7e033e9..bace72a 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -133,11 +133,13 @@ enum ip_conntrack_expect_events {
#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
#include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
/* per conntrack: protocol private data */
union ip_conntrack_proto {
/* insert conntrack proto private data here */
+ struct ip_ct_gre gre;
struct ip_ct_sctp sctp;
struct ip_ct_tcp tcp;
struct ip_ct_icmp icmp;
@@ -148,6 +150,7 @@ union ip_conntrack_expect_proto {
};
/* Add protocol helper include file here */
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
@@ -155,12 +158,20 @@ union ip_conntrack_expect_proto {
/* per conntrack: application helper private data */
union ip_conntrack_help {
/* insert conntrack helper private data (master) here */
+ struct ip_ct_pptp_master ct_pptp_info;
struct ip_ct_ftp_master ct_ftp_info;
struct ip_ct_irc_master ct_irc_info;
};
#ifdef CONFIG_IP_NF_NAT_NEEDED
#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_pptp.h>
+
+/* per conntrack: nat application helper private data */
+union ip_conntrack_nat_help {
+ /* insert nat helper private data here */
+ struct ip_nat_pptp nat_pptp_info;
+};
#endif
#include <linux/types.h>
@@ -223,6 +234,7 @@ struct ip_conntrack
#ifdef CONFIG_IP_NF_NAT_NEEDED
struct {
struct ip_nat_info info;
+ union ip_conntrack_nat_help help;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
int masq_index;
@@ -372,7 +384,7 @@ extern struct ip_conntrack_expect *
__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
extern struct ip_conntrack_expect *
-ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
+ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
extern struct ip_conntrack_tuple_hash *
__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
new file mode 100644
index 0000000..389e385
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
@@ -0,0 +1,332 @@
+/* PPTP constants and structs */
+#ifndef _CONNTRACK_PPTP_H
+#define _CONNTRACK_PPTP_H
+
+/* state of the control session */
+enum pptp_ctrlsess_state {
+ PPTP_SESSION_NONE, /* no session present */
+ PPTP_SESSION_ERROR, /* some session error */
+ PPTP_SESSION_STOPREQ, /* stop_sess request seen */
+ PPTP_SESSION_REQUESTED, /* start_sess request seen */
+ PPTP_SESSION_CONFIRMED, /* session established */
+};
+
+/* state of the call inside the control session */
+enum pptp_ctrlcall_state {
+ PPTP_CALL_NONE,
+ PPTP_CALL_ERROR,
+ PPTP_CALL_OUT_REQ,
+ PPTP_CALL_OUT_CONF,
+ PPTP_CALL_IN_REQ,
+ PPTP_CALL_IN_REP,
+ PPTP_CALL_IN_CONF,
+ PPTP_CALL_CLEAR_REQ,
+};
+
+
+/* conntrack private data */
+struct ip_ct_pptp_master {
+ enum pptp_ctrlsess_state sstate; /* session state */
+
+ /* everything below is going to be per-expectation in newnat,
+ * since there could be more than one call within one session */
+ enum pptp_ctrlcall_state cstate; /* call state */
+ u_int16_t pac_call_id; /* call id of PAC, host byte order */
+ u_int16_t pns_call_id; /* call id of PNS, host byte order */
+
+ /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
+ * and therefore imposes a fixed limit on the number of maps */
+ struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
+};
+
+/* conntrack_expect private member */
+struct ip_ct_pptp_expect {
+ enum pptp_ctrlcall_state cstate; /* call state */
+ u_int16_t pac_call_id; /* call id of PAC */
+ u_int16_t pns_call_id; /* call id of PNS */
+};
+
+
+#ifdef __KERNEL__
+
+#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
+
+#define PPTP_CONTROL_PORT 1723
+
+#define PPTP_PACKET_CONTROL 1
+#define PPTP_PACKET_MGMT 2
+
+#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
+
+struct pptp_pkt_hdr {
+ __u16 packetLength;
+ __u16 packetType;
+ __u32 magicCookie;
+};
+
+/* PptpControlMessageType values */
+#define PPTP_START_SESSION_REQUEST 1
+#define PPTP_START_SESSION_REPLY 2
+#define PPTP_STOP_SESSION_REQUEST 3
+#define PPTP_STOP_SESSION_REPLY 4
+#define PPTP_ECHO_REQUEST 5
+#define PPTP_ECHO_REPLY 6
+#define PPTP_OUT_CALL_REQUEST 7
+#define PPTP_OUT_CALL_REPLY 8
+#define PPTP_IN_CALL_REQUEST 9
+#define PPTP_IN_CALL_REPLY 10
+#define PPTP_IN_CALL_CONNECT 11
+#define PPTP_CALL_CLEAR_REQUEST 12
+#define PPTP_CALL_DISCONNECT_NOTIFY 13
+#define PPTP_WAN_ERROR_NOTIFY 14
+#define PPTP_SET_LINK_INFO 15
+
+#define PPTP_MSG_MAX 15
+
+/* PptpGeneralError values */
+#define PPTP_ERROR_CODE_NONE 0
+#define PPTP_NOT_CONNECTED 1
+#define PPTP_BAD_FORMAT 2
+#define PPTP_BAD_VALUE 3
+#define PPTP_NO_RESOURCE 4
+#define PPTP_BAD_CALLID 5
+#define PPTP_REMOVE_DEVICE_ERROR 6
+
+struct PptpControlHeader {
+ __u16 messageType;
+ __u16 reserved;
+};
+
+/* FramingCapability Bitmap Values */
+#define PPTP_FRAME_CAP_ASYNC 0x1
+#define PPTP_FRAME_CAP_SYNC 0x2
+
+/* BearerCapability Bitmap Values */
+#define PPTP_BEARER_CAP_ANALOG 0x1
+#define PPTP_BEARER_CAP_DIGITAL 0x2
+
+struct PptpStartSessionRequest {
+ __u16 protocolVersion;
+ __u8 reserved1;
+ __u8 reserved2;
+ __u32 framingCapability;
+ __u32 bearerCapability;
+ __u16 maxChannels;
+ __u16 firmwareRevision;
+ __u8 hostName[64];
+ __u8 vendorString[64];
+};
+
+/* PptpStartSessionResultCode Values */
+#define PPTP_START_OK 1
+#define PPTP_START_GENERAL_ERROR 2
+#define PPTP_START_ALREADY_CONNECTED 3
+#define PPTP_START_NOT_AUTHORIZED 4
+#define PPTP_START_UNKNOWN_PROTOCOL 5
+
+struct PptpStartSessionReply {
+ __u16 protocolVersion;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u32 framingCapability;
+ __u32 bearerCapability;
+ __u16 maxChannels;
+ __u16 firmwareRevision;
+ __u8 hostName[64];
+ __u8 vendorString[64];
+};
+
+/* PptpStopReasons */
+#define PPTP_STOP_NONE 1
+#define PPTP_STOP_PROTOCOL 2
+#define PPTP_STOP_LOCAL_SHUTDOWN 3
+
+struct PptpStopSessionRequest {
+ __u8 reason;
+};
+
+/* PptpStopSessionResultCode */
+#define PPTP_STOP_OK 1
+#define PPTP_STOP_GENERAL_ERROR 2
+
+struct PptpStopSessionReply {
+ __u8 resultCode;
+ __u8 generalErrorCode;
+};
+
+struct PptpEchoRequest {
+ __u32 identNumber;
+};
+
+/* PptpEchoReplyResultCode */
+#define PPTP_ECHO_OK 1
+#define PPTP_ECHO_GENERAL_ERROR 2
+
+struct PptpEchoReply {
+ __u32 identNumber;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u16 reserved;
+};
+
+/* PptpFramingType */
+#define PPTP_ASYNC_FRAMING 1
+#define PPTP_SYNC_FRAMING 2
+#define PPTP_DONT_CARE_FRAMING 3
+
+/* PptpCallBearerType */
+#define PPTP_ANALOG_TYPE 1
+#define PPTP_DIGITAL_TYPE 2
+#define PPTP_DONT_CARE_BEARER_TYPE 3
+
+struct PptpOutCallRequest {
+ __u16 callID;
+ __u16 callSerialNumber;
+ __u32 minBPS;
+ __u32 maxBPS;
+ __u32 bearerType;
+ __u32 framingType;
+ __u16 packetWindow;
+ __u16 packetProcDelay;
+ __u16 reserved1;
+ __u16 phoneNumberLength;
+ __u16 reserved2;
+ __u8 phoneNumber[64];
+ __u8 subAddress[64];
+};
+
+/* PptpCallResultCode */
+#define PPTP_OUTCALL_CONNECT 1
+#define PPTP_OUTCALL_GENERAL_ERROR 2
+#define PPTP_OUTCALL_NO_CARRIER 3
+#define PPTP_OUTCALL_BUSY 4
+#define PPTP_OUTCALL_NO_DIAL_TONE 5
+#define PPTP_OUTCALL_TIMEOUT 6
+#define PPTP_OUTCALL_DONT_ACCEPT 7
+
+struct PptpOutCallReply {
+ __u16 callID;
+ __u16 peersCallID;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u16 causeCode;
+ __u32 connectSpeed;
+ __u16 packetWindow;
+ __u16 packetProcDelay;
+ __u32 physChannelID;
+};
+
+struct PptpInCallRequest {
+ __u16 callID;
+ __u16 callSerialNumber;
+ __u32 callBearerType;
+ __u32 physChannelID;
+ __u16 dialedNumberLength;
+ __u16 dialingNumberLength;
+ __u8 dialedNumber[64];
+ __u8 dialingNumber[64];
+ __u8 subAddress[64];
+};
+
+/* PptpInCallResultCode */
+#define PPTP_INCALL_ACCEPT 1
+#define PPTP_INCALL_GENERAL_ERROR 2
+#define PPTP_INCALL_DONT_ACCEPT 3
+
+struct PptpInCallReply {
+ __u16 callID;
+ __u16 peersCallID;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u16 packetWindow;
+ __u16 packetProcDelay;
+ __u16 reserved;
+};
+
+struct PptpInCallConnected {
+ __u16 peersCallID;
+ __u16 reserved;
+ __u32 connectSpeed;
+ __u16 packetWindow;
+ __u16 packetProcDelay;
+ __u32 callFramingType;
+};
+
+struct PptpClearCallRequest {
+ __u16 callID;
+ __u16 reserved;
+};
+
+struct PptpCallDisconnectNotify {
+ __u16 callID;
+ __u8 resultCode;
+ __u8 generalErrorCode;
+ __u16 causeCode;
+ __u16 reserved;
+ __u8 callStatistics[128];
+};
+
+struct PptpWanErrorNotify {
+ __u16 peersCallID;
+ __u16 reserved;
+ __u32 crcErrors;
+ __u32 framingErrors;
+ __u32 hardwareOverRuns;
+ __u32 bufferOverRuns;
+ __u32 timeoutErrors;
+ __u32 alignmentErrors;
+};
+
+struct PptpSetLinkInfo {
+ __u16 peersCallID;
+ __u16 reserved;
+ __u32 sendAccm;
+ __u32 recvAccm;
+};
+
+
+struct pptp_priv_data {
+ __u16 call_id;
+ __u16 mcall_id;
+ __u16 pcall_id;
+};
+
+union pptp_ctrl_union {
+ struct PptpStartSessionRequest sreq;
+ struct PptpStartSessionReply srep;
+ struct PptpStopSessionRequest streq;
+ struct PptpStopSessionReply strep;
+ struct PptpOutCallRequest ocreq;
+ struct PptpOutCallReply ocack;
+ struct PptpInCallRequest icreq;
+ struct PptpInCallReply icack;
+ struct PptpInCallConnected iccon;
+ struct PptpClearCallRequest clrreq;
+ struct PptpCallDisconnectNotify disc;
+ struct PptpWanErrorNotify wanerr;
+ struct PptpSetLinkInfo setlink;
+};
+
+extern int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig,
+ struct ip_conntrack_expect *exp_reply);
+
+extern void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+ struct ip_conntrack_expect *exp);
+#endif /* __KERNEL__ */
+#endif /* _CONNTRACK_PPTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
new file mode 100644
index 0000000..8d090ef
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
@@ -0,0 +1,114 @@
+#ifndef _CONNTRACK_PROTO_GRE_H
+#define _CONNTRACK_PROTO_GRE_H
+#include <asm/byteorder.h>
+
+/* GRE PROTOCOL HEADER */
+
+/* GRE Version field */
+#define GRE_VERSION_1701 0x0
+#define GRE_VERSION_PPTP 0x1
+
+/* GRE Protocol field */
+#define GRE_PROTOCOL_PPTP 0x880B
+
+/* GRE Flags */
+#define GRE_FLAG_C 0x80
+#define GRE_FLAG_R 0x40
+#define GRE_FLAG_K 0x20
+#define GRE_FLAG_S 0x10
+#define GRE_FLAG_A 0x80
+
+#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
+#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
+#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
+#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
+#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
+
+/* GRE is a mess: Four different standards */
+struct gre_hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u16 rec:3,
+ srr:1,
+ seq:1,
+ key:1,
+ routing:1,
+ csum:1,
+ version:3,
+ reserved:4,
+ ack:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u16 csum:1,
+ routing:1,
+ key:1,
+ seq:1,
+ srr:1,
+ rec:3,
+ ack:1,
+ reserved:4,
+ version:3;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+ __u16 protocol;
+};
+
+/* modified GRE header for PPTP */
+struct gre_hdr_pptp {
+ __u8 flags; /* bitfield */
+ __u8 version; /* should be GRE_VERSION_PPTP */
+ __u16 protocol; /* should be GRE_PROTOCOL_PPTP */
+ __u16 payload_len; /* size of ppp payload, not inc. gre header */
+ __u16 call_id; /* peer's call_id for this session */
+ __u32 seq; /* sequence number. Present if S==1 */
+ __u32 ack; /* seq number of highest packet recieved by */
+ /* sender in this session */
+};
+
+
+/* this is part of ip_conntrack */
+struct ip_ct_gre {
+ unsigned int stream_timeout;
+ unsigned int timeout;
+};
+
+#ifdef __KERNEL__
+struct ip_conntrack_expect;
+struct ip_conntrack;
+
+/* structure for original <-> reply keymap */
+struct ip_ct_gre_keymap {
+ struct list_head list;
+
+ struct ip_conntrack_tuple tuple;
+};
+
+/* add new tuple->key_reply pair to keymap */
+int ip_ct_gre_keymap_add(struct ip_conntrack *ct,
+ struct ip_conntrack_tuple *t,
+ int reply);
+
+/* delete keymap entries */
+void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct);
+
+
+/* get pointer to gre key, if present */
+static inline u_int32_t *gre_key(struct gre_hdr *greh)
+{
+ if (!greh->key)
+ return NULL;
+ if (greh->csum || greh->routing)
+ return (u_int32_t *) (greh+sizeof(*greh)+4);
+ return (u_int32_t *) (greh+sizeof(*greh));
+}
+
+/* get pointer ot gre csum, if present */
+static inline u_int16_t *gre_csum(struct gre_hdr *greh)
+{
+ if (!greh->csum)
+ return NULL;
+ return (u_int16_t *) (greh+sizeof(*greh));
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _CONNTRACK_PROTO_GRE_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
index c33f0b5..14dc0f7 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
@@ -28,6 +28,9 @@ union ip_conntrack_manip_proto
struct {
u_int16_t port;
} sctp;
+ struct {
+ u_int16_t key; /* key is 32bit, pptp only uses 16 */
+ } gre;
};
/* The manipulable part of the tuple. */
@@ -61,6 +64,10 @@ struct ip_conntrack_tuple
struct {
u_int16_t port;
} sctp;
+ struct {
+ u_int16_t key; /* key is 32bit,
+ * pptp only uses 16 */
+ } gre;
} u;
/* The protocol. */
diff --git a/include/linux/netfilter_ipv4/ip_nat_pptp.h b/include/linux/netfilter_ipv4/ip_nat_pptp.h
new file mode 100644
index 0000000..eaf66c2
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_nat_pptp.h
@@ -0,0 +1,11 @@
+/* PPTP constants and structs */
+#ifndef _NAT_PPTP_H
+#define _NAT_PPTP_H
+
+/* conntrack private data */
+struct ip_nat_pptp {
+ u_int16_t pns_call_id; /* NAT'ed PNS call id */
+ u_int16_t pac_call_id; /* NAT'ed PAC call id */
+};
+
+#endif /* _NAT_PPTP_H */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 58c72a5..59f70b3 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -455,6 +455,9 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb,
/* Check for an extension */
extern int ip6t_ext_hdr(u8 nexthdr);
+/* find specified header and get offset to it */
+extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ u8 target);
#define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 7bbd259..bdebdc5 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -20,6 +20,7 @@
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
+#define NETLINK_GENERIC 16
#define MAX_LINKS 32
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 4d24d65..8903688 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -438,17 +438,22 @@ extern int nfsd4_process_open1(struct nfsd4_open *open);
extern int nfsd4_process_open2(struct svc_rqst *rqstp,
struct svc_fh *current_fh, struct nfsd4_open *open);
extern int nfsd4_open_confirm(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_confirm *oc);
+ struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
+ struct nfs4_stateowner **);
extern int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_close *close);
+ struct nfsd4_close *close,
+ struct nfs4_stateowner **replay_owner);
extern int nfsd4_open_downgrade(struct svc_rqst *rqstp,
- struct svc_fh *current_fh, struct nfsd4_open_downgrade *od);
+ struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
+ struct nfs4_stateowner **replay_owner);
extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_lock *lock);
+ struct nfsd4_lock *lock,
+ struct nfs4_stateowner **replay_owner);
extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
struct nfsd4_lockt *lockt);
extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
- struct nfsd4_locku *locku);
+ struct nfsd4_locku *locku,
+ struct nfs4_stateowner **replay_owner);
extern int
nfsd4_release_lockowner(struct svc_rqst *rqstp,
struct nfsd4_release_lockowner *rlockowner);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ee0ab7a5..c49d28e 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -447,6 +447,10 @@
#define PCI_DEVICE_ID_CIRRUS_7542 0x1200
#define PCI_DEVICE_ID_CIRRUS_7543 0x1202
#define PCI_DEVICE_ID_CIRRUS_7541 0x1204
+#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
+#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
+#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
+#define PCI_DEVICE_ID_CIRRUS_4281 0x6005
#define PCI_VENDOR_ID_IBM 0x1014
#define PCI_DEVICE_ID_IBM_FIRE_CORAL 0x000a
@@ -487,6 +491,7 @@
#define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060
#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_DEVICE_ID_AMD_K8_NB 0x1100
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
#define PCI_DEVICE_ID_AMD_SCSI 0x2020
@@ -682,7 +687,9 @@
#define PCI_DEVICE_ID_SI_6326 0x6326
#define PCI_DEVICE_ID_SI_7001 0x7001
#define PCI_DEVICE_ID_SI_7012 0x7012
+#define PCI_DEVICE_ID_SI_7013 0x7013
#define PCI_DEVICE_ID_SI_7016 0x7016
+#define PCI_DEVICE_ID_SI_7018 0x7018
#define PCI_VENDOR_ID_HP 0x103c
#define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005
@@ -713,10 +720,12 @@
#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282
#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290
#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301
+#define PCI_DEVICE_ID_HP_CISS 0x3210
#define PCI_DEVICE_ID_HP_CISSA 0x3220
#define PCI_DEVICE_ID_HP_CISSB 0x3222
-#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
#define PCI_DEVICE_ID_HP_CISSC 0x3230
+#define PCI_DEVICE_ID_HP_CISSD 0x3238
+#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
#define PCI_VENDOR_ID_PCTECH 0x1042
#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000
@@ -991,6 +1000,7 @@
#define PCI_DEVICE_ID_BROOKTREE_849A 0x0351
#define PCI_DEVICE_ID_BROOKTREE_878_1 0x036e
#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
+#define PCI_DEVICE_ID_BROOKTREE_879 0x0879
#define PCI_DEVICE_ID_BROOKTREE_8474 0x8474
#define PCI_VENDOR_ID_SIERRA 0x10a8
@@ -1109,6 +1119,9 @@
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
#define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV 0x0005
#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS 0x0083
+#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
+#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
+#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
#define PCI_VENDOR_ID_ASP 0x10cd
#define PCI_DEVICE_ID_ASP_ABP940 0x1200
@@ -1155,10 +1168,13 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064
#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065
#define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066
+#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069
#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085
#define PCI_DEVICE_ID_NVIDIA_NVENET_4 0x0086
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a
#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e
#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0
@@ -1173,6 +1189,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE 0x00d5
#define PCI_DEVICE_ID_NVIDIA_NVENET_3 0x00d6
+#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9
#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
#define PCI_DEVICE_ID_NVIDIA_NVENET_7 0x00df
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1
@@ -1180,6 +1197,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00e4
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5
#define PCI_DEVICE_ID_NVIDIA_NVENET_6 0x00e6
+#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea
#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101
@@ -1230,6 +1248,7 @@
#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4
#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc
+#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM 0x01c1
#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3
#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200
@@ -1334,6 +1353,13 @@
#define PCI_DEVICE_ID_REALTEK_8169 0x8169
#define PCI_VENDOR_ID_XILINX 0x10ee
+#define PCI_DEVICE_ID_RME_DIGI96 0x3fc0
+#define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1
+#define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2
+#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
#define PCI_DEVICE_ID_TURBOPAM 0x4020
#define PCI_VENDOR_ID_TRUEVISION 0x10fa
@@ -1809,6 +1835,14 @@
#define PCI_DEVICE_ID_ESS_ESS1968 0x1968
#define PCI_DEVICE_ID_ESS_AUDIOPCI 0x1969
#define PCI_DEVICE_ID_ESS_ESS1978 0x1978
+#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988
+#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989
+#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990
+#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992
+#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998
+#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999
+#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a
+#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b
#define PCI_VENDOR_ID_SATSAGEM 0x1267
#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016
@@ -1968,6 +2002,9 @@
#define PCI_DEVICE_ID_LMC_SSI 0x0005
#define PCI_DEVICE_ID_LMC_T1 0x0006
+#define PCI_VENDOR_ID_MARIAN 0x1382
+#define PCI_DEVICE_ID_MARIAN_PRODIF_PLUS 0x2048
+
#define PCI_VENDOR_ID_NETGEAR 0x1385
#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a
#define PCI_DEVICE_ID_NETGEAR_GA622 0x622a
@@ -2056,6 +2093,10 @@
#define PCI_VENDOR_ID_TIMEDIA 0x1409
#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168
+#define PCI_VENDOR_ID_ICE 0x1412
+#define PCI_DEVICE_ID_ICE_1712 0x1712
+#define PCI_DEVICE_ID_VT1724 0x1724
+
#define PCI_VENDOR_ID_OXSEMI 0x1415
#define PCI_DEVICE_ID_OXSEMI_12PCI840 0x8403
#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501
@@ -2212,6 +2253,9 @@
#define PCI_VENDOR_ID_INFINICON 0x1820
+#define PCI_VENDOR_ID_SITECOM 0x182d
+#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069
+
#define PCI_VENDOR_ID_TOPSPIN 0x1867
#define PCI_VENDOR_ID_TDI 0x192E
@@ -2536,6 +2580,7 @@
#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191
#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192
#define PCI_DEVICE_ID_INTEL_440MX 0x7195
+#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196
#define PCI_DEVICE_ID_INTEL_82443MX_0 0x7198
#define PCI_DEVICE_ID_INTEL_82443MX_1 0x7199
#define PCI_DEVICE_ID_INTEL_82443MX_2 0x719a
@@ -2642,6 +2687,11 @@
#define PCI_VENDOR_ID_TTTECH 0x0357
#define PCI_DEVICE_ID_TTTECH_MC322 0x000A
+#define PCI_VENDOR_ID_XILINX_RME 0xea60
+#define PCI_DEVICE_ID_RME_DIGI32 0x9896
+#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897
+#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898
+
#define PCI_VENDOR_ID_ARK 0xedd8
#define PCI_DEVICE_ID_ARK_STING 0xa091
#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 4b32bce..2c177e4 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -166,6 +166,9 @@ struct packet_iosched
/*
* 32 buffers of 2048 bytes
*/
+#if (PAGE_SIZE % CD_FRAMESIZE) != 0
+#error "PAGE_SIZE must be a multiple of CD_FRAMESIZE"
+#endif
#define PACKET_MAX_SIZE 32
#define PAGES_PER_PACKET (PACKET_MAX_SIZE * CD_FRAMESIZE / PAGE_SIZE)
#define PACKET_MAX_SECTORS (PACKET_MAX_SIZE * CD_FRAMESIZE >> 9)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 38c8654..49e617f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -121,6 +121,17 @@ extern unsigned long nr_iowait(void);
#define set_task_state(tsk, state_value) \
set_mb((tsk)->state, (state_value))
+/*
+ * set_current_state() includes a barrier so that the write of current->state
+ * is correctly serialised wrt the caller's subsequent test of whether to
+ * actually sleep:
+ *
+ * set_current_state(TASK_UNINTERRUPTIBLE);
+ * if (do_i_need_to_sleep())
+ * schedule();
+ *
+ * If the caller does not need such serialisation then use __set_current_state()
+ */
#define __set_current_state(state_value) \
do { current->state = (state_value); } while (0)
#define set_current_state(state_value) \
diff --git a/include/linux/security.h b/include/linux/security.h
index 55b02e1..0e43460 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1907,6 +1907,11 @@ extern int register_security (struct security_operations *ops);
extern int unregister_security (struct security_operations *ops);
extern int mod_reg_security (const char *name, struct security_operations *ops);
extern int mod_unreg_security (const char *name, struct security_operations *ops);
+extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
+ struct dentry *parent, void *data,
+ struct file_operations *fops);
+extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent);
+extern void securityfs_remove(struct dentry *dentry);
#else /* CONFIG_SECURITY */
diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h
new file mode 100644
index 0000000..7dab783
--- /dev/null
+++ b/include/linux/tfrc.h
@@ -0,0 +1,35 @@
+#ifndef _LINUX_TFRC_H_
+#define _LINUX_TFRC_H_
+/*
+ * include/linux/tfrc.h
+ *
+ * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/types.h>
+
+struct tfrc_rx_info {
+ __u32 tfrcrx_x_recv;
+ __u32 tfrcrx_rtt;
+ __u32 tfrcrx_p;
+};
+
+struct tfrc_tx_info {
+ __u32 tfrctx_x;
+ __u32 tfrctx_x_recv;
+ __u32 tfrctx_x_calc;
+ __u32 tfrctx_rtt;
+ __u32 tfrctx_p;
+ __u32 tfrctx_rto;
+ __u32 tfrctx_ipi;
+};
+
+#endif /* _LINUX_TFRC_H_ */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index f623a33..89a0557 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -60,12 +60,17 @@ enum v4l2_field {
(field) == V4L2_FIELD_SEQ_BT)
enum v4l2_buf_type {
- V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
- V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
- V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
- V4L2_BUF_TYPE_VBI_CAPTURE = 4,
- V4L2_BUF_TYPE_VBI_OUTPUT = 5,
- V4L2_BUF_TYPE_PRIVATE = 0x80,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
+ V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
+ V4L2_BUF_TYPE_VBI_CAPTURE = 4,
+ V4L2_BUF_TYPE_VBI_OUTPUT = 5,
+#if 1
+ /* Experimental Sliced VBI */
+ V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
+ V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7,
+#endif
+ V4L2_BUF_TYPE_PRIVATE = 0x80,
};
enum v4l2_ctrl_type {
@@ -149,20 +154,24 @@ struct v4l2_capability
};
/* Values for 'capabilities' field */
-#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
-#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
-#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
-#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a VBI capture device */
-#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a VBI output device */
-#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
+#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
+#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
+#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
+#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */
+#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */
+#if 1
+#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */
+#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
+#endif
+#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
-#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
-#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
-#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
+#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
+#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
+#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
-#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
-#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
-#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
+#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
+#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
+#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
/*
* V I D E O I M A G E F O R M A T
@@ -809,6 +818,8 @@ struct v4l2_audioout
* Data services API by Michael Schimek
*/
+/* Raw VBI */
+
struct v4l2_vbi_format
{
__u32 sampling_rate; /* in 1 Hz */
@@ -825,6 +836,54 @@ struct v4l2_vbi_format
#define V4L2_VBI_UNSYNC (1<< 0)
#define V4L2_VBI_INTERLACED (1<< 1)
+#if 1
+/* Sliced VBI
+ *
+ * This implements is a proposal V4L2 API to allow SLICED VBI
+ * required for some hardware encoders. It should change without
+ * notice in the definitive implementation.
+ */
+
+struct v4l2_sliced_vbi_format
+{
+ __u16 service_set;
+ /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
+ service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
+ (equals frame lines 313-336 for 625 line video
+ standards, 263-286 for 525 line standards) */
+ __u16 service_lines[2][24];
+ __u32 io_size;
+ __u32 reserved[2]; /* must be zero */
+};
+
+#define V4L2_SLICED_TELETEXT_B (0x0001)
+#define V4L2_SLICED_VPS (0x0400)
+#define V4L2_SLICED_CAPTION_525 (0x1000)
+#define V4L2_SLICED_WSS_625 (0x4000)
+
+#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525)
+#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
+
+struct v4l2_sliced_vbi_cap
+{
+ __u16 service_set;
+ /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
+ service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
+ (equals frame lines 313-336 for 625 line video
+ standards, 263-286 for 525 line standards) */
+ __u16 service_lines[2][24];
+ __u32 reserved[4]; /* must be 0 */
+};
+
+struct v4l2_sliced_vbi_data
+{
+ __u32 id;
+ __u32 field; /* 0: first field, 1: second field */
+ __u32 line; /* 1-23 */
+ __u32 reserved; /* must be 0 */
+ __u8 data[48];
+};
+#endif
/*
* A G G R E G A T E S T R U C T U R E S
@@ -837,10 +896,13 @@ struct v4l2_format
enum v4l2_buf_type type;
union
{
- struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
- struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
- struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
- __u8 raw_data[200]; // user-defined
+ struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
+ struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
+ struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
+#if 1
+ struct v4l2_sliced_vbi_format sliced; // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
+#endif
+ __u8 raw_data[200]; // user-defined
} fmt;
};
@@ -916,6 +978,9 @@ struct v4l2_streamparm
#define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout)
#define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority)
#define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority)
+#if 1
+#define VIDIOC_G_SLICED_VBI_CAP _IOR ('V', 69, struct v4l2_sliced_vbi_cap)
+#endif
/* for compatibility, will go away some day */
#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 371e7d3..fa2d12b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -463,6 +463,17 @@ struct inquiry_info_with_rssi_and_pscan_mode {
__s8 rssi;
} __attribute__ ((packed));
+#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2F
+struct extended_inquiry_info {
+ bdaddr_t bdaddr;
+ __u8 pscan_rep_mode;
+ __u8 pscan_period_mode;
+ __u8 dev_class[3];
+ __u16 clock_offset;
+ __s8 rssi;
+ __u8 data[240];
+} __attribute__ ((packed));
+
#define HCI_EV_CONN_COMPLETE 0x03
struct hci_ev_conn_complete {
__u8 status;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index e426641..06b4235 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -84,6 +84,7 @@
#define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */
#define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */
#define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */
+#define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */
/* Move it to better place one day, for now keep it unique */
#define NFC_IPVS_PROPERTY 0x10000
@@ -739,6 +740,8 @@ enum {
extern struct ip_vs_conn *ip_vs_conn_in_get
(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+extern struct ip_vs_conn *ip_vs_ct_in_get
+(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
extern struct ip_vs_conn *ip_vs_conn_out_get
(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
diff --git a/include/sound/core.h b/include/sound/core.h
index 3dc41fd..26160ad 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -168,6 +168,9 @@ struct _snd_card {
wait_queue_head_t shutdown_sleep;
struct work_struct free_workq; /* for free in workqueue */
struct device *dev;
+#ifdef CONFIG_SND_GENERIC_DRIVER
+ struct snd_generic_device *generic_dev;
+#endif
#ifdef CONFIG_PM
int (*pm_suspend)(snd_card_t *card, pm_message_t state);
@@ -176,9 +179,6 @@ struct _snd_card {
unsigned int power_state; /* power state */
struct semaphore power_lock; /* power lock */
wait_queue_head_t power_sleep;
-#ifdef CONFIG_SND_GENERIC_PM
- struct snd_generic_device *pm_dev; /* for ISA */
-#endif
#endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
@@ -348,6 +348,8 @@ int snd_card_file_remove(snd_card_t *card, struct file *file);
#ifndef snd_card_set_dev
#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
#endif
+/* register a generic device (for ISA, etc) */
+int snd_card_set_generic_dev(snd_card_t *card);
/* device.c */
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index 9b94510..b0c0e19 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -29,19 +29,6 @@
#include "ac97_codec.h"
#include "cs46xx_dsp_spos.h"
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS 0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610 0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612 0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615 0x6004
-#endif
-
/*
* Direct registers
*/
@@ -1715,7 +1702,6 @@ struct _snd_cs46xx {
void (*active_ctrl)(cs46xx_t *, int);
void (*mixer_init)(cs46xx_t *);
- struct pci_dev *acpi_dev;
int acpi_port;
snd_kcontrol_t *eapd_switch; /* for amplifier hack */
int accept_valid; /* accept mmap valid (for OSS) */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 4e3993d..67bf3f1 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -35,13 +35,6 @@
#include <linux/interrupt.h>
#include <asm/io.h>
-#ifndef PCI_VENDOR_ID_CREATIVE
-#define PCI_VENDOR_ID_CREATIVE 0x1102
-#endif
-#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
-#endif
-
/* ------------------- DEFINES -------------------- */
#define EMUPAGESIZE 4096
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index d6361dab..2b23a59 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -903,13 +903,16 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
int snd_pcm_format_linear(snd_pcm_format_t format);
int snd_pcm_format_little_endian(snd_pcm_format_t format);
int snd_pcm_format_big_endian(snd_pcm_format_t format);
-/*
+#if 0 /* just for DocBook */
+/**
* snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
* @format: the format to check
*
* Returns 1 if the given PCM format is CPU-endian, 0 if
* opposite, or a negative error code if endian not specified.
*/
+int snd_pcm_format_cpu_endian(snd_pcm_format_t format);
+#endif /* DocBook */
#ifdef SNDRV_LITTLE_ENDIAN
#define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format)
#else
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 5187285..0b67c9d 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -32,7 +32,8 @@ struct _snd_pcm_oss_setup {
block:1,
nonblock:1,
partialfrag:1,
- nosilence:1;
+ nosilence:1,
+ buggyptr:1;
unsigned int periods;
unsigned int period_size;
snd_pcm_oss_setup_t *next;
diff --git a/include/sound/trident.h b/include/sound/trident.h
index f5254ec..a408d39 100644
--- a/include/sound/trident.h
+++ b/include/sound/trident.h
@@ -33,23 +33,6 @@
//#include "ainstr_gf1.h"
#include "ainstr_simple.h"
-#ifndef PCI_VENDOR_ID_TRIDENT
-#define PCI_VENDOR_ID_TRIDENT 0x1023
-#endif
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_DX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000
-#endif
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_NX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001
-#endif
-
-#ifndef PCI_VENDOR_ID_SI
-#define PCI_VENDOR_ID_SI 0x1039
-#endif
-#ifndef PCI_DEVICE_ID_SI_7018
-#define PCI_DEVICE_ID_SI_7018 0x7018
-#endif
-
#define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX)
#define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX)
#define TRIDENT_DEVICE_ID_SI7018 ((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018)
diff --git a/include/sound/version.h b/include/sound/version.h
index 8d19bfa..ee32af2 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
#define CONFIG_SND_VERSION "1.0.10rc1"
-#define CONFIG_SND_DATE " (Tue Aug 30 05:31:08 2005 UTC)"
+#define CONFIG_SND_DATE " (Mon Sep 12 08:13:09 2005 UTC)"
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 9a3c1e6..c3bccbfd 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -28,28 +28,6 @@
#include "timer.h"
#include <linux/gameport.h>
-#ifndef PCI_VENDOR_ID_YAMAHA
-#define PCI_VENDOR_ID_YAMAHA 0x1073
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_724
-#define PCI_DEVICE_ID_YAMAHA_724 0x0004
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_724F
-#define PCI_DEVICE_ID_YAMAHA_724F 0x000d
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_740
-#define PCI_DEVICE_ID_YAMAHA_740 0x000a
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_740C
-#define PCI_DEVICE_ID_YAMAHA_740C 0x000c
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_744
-#define PCI_DEVICE_ID_YAMAHA_744 0x0010
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_754
-#define PCI_DEVICE_ID_YAMAHA_754 0x0012
-#endif
-
/*
* Direct registers
*/
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 8d3cef5..6f4ea80 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -1142,9 +1142,6 @@
/* do we want accelerated console */
#define PM3FB_USE_ACCEL 1
-/* useful ? */
-#define CHAR_IS_NUM(a) ((((a) >= '0') && ((a) <= '9')) ? 1 : 0)
-
/* for driver debugging ONLY */
/* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */
/* define PM3FB_MASTER_DEBUG 1 */
diff --git a/include/video/w100fb.h b/include/video/w100fb.h
index e6da2d7..677d403 100644
--- a/include/video/w100fb.h
+++ b/include/video/w100fb.h
@@ -19,6 +19,7 @@ struct w100fb_par;
unsigned long w100fb_gpio_read(int port);
void w100fb_gpio_write(int port, unsigned long value);
+unsigned long w100fb_get_hsynclen(struct device *dev);
/* LCD Specific Routines and Config */
struct w100_tg_info {
diff --git a/init/initramfs.c b/init/initramfs.c
index 02c5ce6..0c5d9a3 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -466,6 +466,14 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
extern char __initramfs_start[], __initramfs_end[];
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/initrd.h>
+
+static void __init free_initrd(void)
+{
+ free_initrd_mem(initrd_start, initrd_end);
+ initrd_start = 0;
+ initrd_end = 0;
+}
+
#endif
void __init populate_rootfs(void)
@@ -484,7 +492,7 @@ void __init populate_rootfs(void)
printk(" it is\n");
unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start, 0);
- free_initrd_mem(initrd_start, initrd_end);
+ free_initrd();
return;
}
printk("it isn't (%s); looks like an initrd\n", err);
@@ -493,7 +501,7 @@ void __init populate_rootfs(void)
sys_write(fd, (char *)initrd_start,
initrd_end - initrd_start);
sys_close(fd);
- free_initrd_mem(initrd_start, initrd_end);
+ free_initrd();
}
}
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 7f06997..83096b6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -79,6 +79,8 @@ static int audit_rate_limit;
/* Number of outstanding audit_buffers allowed. */
static int audit_backlog_limit = 64;
+static int audit_backlog_wait_time = 60 * HZ;
+static int audit_backlog_wait_overflow = 0;
/* The identity of the user shutting down the audit system. */
uid_t audit_sig_uid = -1;
@@ -106,18 +108,12 @@ static LIST_HEAD(audit_freelist);
static struct sk_buff_head audit_skb_queue;
static struct task_struct *kauditd_task;
static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
-
-/* There are three lists of rules -- one to search at task creation
- * time, one to search at syscall entry time, and another to search at
- * syscall exit time. */
-static LIST_HEAD(audit_tsklist);
-static LIST_HEAD(audit_entlist);
-static LIST_HEAD(audit_extlist);
+static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
/* The netlink socket is only to be read by 1 CPU, which lets us assume
* that list additions and deletions never happen simultaneously in
* auditsc.c */
-static DECLARE_MUTEX(audit_netlink_sem);
+DECLARE_MUTEX(audit_netlink_sem);
/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
* audit records. Since printk uses a 1024 byte buffer, this buffer
@@ -137,6 +133,7 @@ struct audit_buffer {
struct list_head list;
struct sk_buff *skb; /* formatted skb ready to send */
struct audit_context *ctx; /* NULL or associated context */
+ int gfp_mask;
};
static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
@@ -145,11 +142,6 @@ static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
nlh->nlmsg_pid = pid;
}
-struct audit_entry {
- struct list_head list;
- struct audit_rule rule;
-};
-
static void audit_panic(const char *message)
{
switch (audit_failure)
@@ -233,7 +225,7 @@ static int audit_set_rate_limit(int limit, uid_t loginuid)
{
int old = audit_rate_limit;
audit_rate_limit = limit;
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_rate_limit=%d old=%d by auid=%u",
audit_rate_limit, old, loginuid);
return old;
@@ -243,7 +235,7 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid)
{
int old = audit_backlog_limit;
audit_backlog_limit = limit;
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_backlog_limit=%d old=%d by auid=%u",
audit_backlog_limit, old, loginuid);
return old;
@@ -255,7 +247,7 @@ static int audit_set_enabled(int state, uid_t loginuid)
if (state != 0 && state != 1)
return -EINVAL;
audit_enabled = state;
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_enabled=%d old=%d by auid=%u",
audit_enabled, old, loginuid);
return old;
@@ -269,7 +261,7 @@ static int audit_set_failure(int state, uid_t loginuid)
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
audit_failure = state;
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_failure=%d old=%d by auid=%u",
audit_failure, old, loginuid);
return old;
@@ -281,6 +273,7 @@ int kauditd_thread(void *dummy)
while (1) {
skb = skb_dequeue(&audit_skb_queue);
+ wake_up(&audit_backlog_wait);
if (skb) {
if (audit_pid) {
int err = netlink_unicast(audit_sock, skb, audit_pid, 0);
@@ -290,7 +283,7 @@ int kauditd_thread(void *dummy)
audit_pid = 0;
}
} else {
- printk(KERN_ERR "%s\n", skb->data + NLMSG_SPACE(0));
+ printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
kfree_skb(skb);
}
} else {
@@ -423,7 +416,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (status_get->mask & AUDIT_STATUS_PID) {
int old = audit_pid;
audit_pid = status_get->pid;
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_pid=%d old=%d by auid=%u",
audit_pid, old, loginuid);
}
@@ -435,15 +428,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
- ab = audit_log_start(NULL, msg_type);
- if (!ab)
- break; /* audit_panic has been called */
- audit_log_format(ab,
- "user pid=%d uid=%u auid=%u"
- " msg='%.1024s'",
- pid, uid, loginuid, (char *)data);
- audit_set_pid(ab, pid);
- audit_log_end(ab);
+ if (!audit_enabled && msg_type != AUDIT_USER_AVC)
+ return 0;
+
+ err = audit_filter_user(&NETLINK_CB(skb), msg_type);
+ if (err == 1) {
+ err = 0;
+ ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+ if (ab) {
+ audit_log_format(ab,
+ "user pid=%d uid=%u auid=%u msg='%.1024s'",
+ pid, uid, loginuid, (char *)data);
+ audit_set_pid(ab, pid);
+ audit_log_end(ab);
+ }
+ }
break;
case AUDIT_ADD:
case AUDIT_DEL:
@@ -523,7 +522,7 @@ static int __init audit_init(void)
skb_queue_head_init(&audit_skb_queue);
audit_initialized = 1;
audit_enabled = audit_default;
- audit_log(NULL, AUDIT_KERNEL, "initialized");
+ audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
return 0;
}
__initcall(audit_init);
@@ -561,7 +560,7 @@ static void audit_buffer_free(struct audit_buffer *ab)
}
static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
- int gfp_mask, int type)
+ unsigned int __nocast gfp_mask, int type)
{
unsigned long flags;
struct audit_buffer *ab = NULL;
@@ -587,6 +586,7 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
goto err;
ab->ctx = ctx;
+ ab->gfp_mask = gfp_mask;
nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
nlh->nlmsg_type = type;
nlh->nlmsg_flags = 0;
@@ -606,26 +606,27 @@ err:
* (timestamp,serial) tuple is unique for each syscall and is live from
* syscall entry to syscall exit.
*
- * Atomic values are only guaranteed to be 24-bit, so we count down.
- *
* NOTE: Another possibility is to store the formatted records off the
* audit context (for those records that have a context), and emit them
* all at syscall exit. However, this could delay the reporting of
* significant errors until syscall exit (or never, if the system
* halts). */
+
unsigned int audit_serial(void)
{
- static atomic_t serial = ATOMIC_INIT(0xffffff);
- unsigned int a, b;
+ static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
+ static unsigned int serial = 0;
+
+ unsigned long flags;
+ unsigned int ret;
+ spin_lock_irqsave(&serial_lock, flags);
do {
- a = atomic_read(&serial);
- if (atomic_dec_and_test(&serial))
- atomic_set(&serial, 0xffffff);
- b = atomic_read(&serial);
- } while (b != a - 1);
+ ret = ++serial;
+ } while (unlikely(!ret));
+ spin_unlock_irqrestore(&serial_lock, flags);
- return 0xffffff - b;
+ return ret;
}
static inline void audit_get_stamp(struct audit_context *ctx,
@@ -645,17 +646,43 @@ static inline void audit_get_stamp(struct audit_context *ctx,
* syscall, then the syscall is marked as auditable and an audit record
* will be written at syscall exit. If there is no associated task, tsk
* should be NULL. */
-struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
+
+struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,
+ int type)
{
struct audit_buffer *ab = NULL;
struct timespec t;
unsigned int serial;
+ int reserve;
+ unsigned long timeout_start = jiffies;
if (!audit_initialized)
return NULL;
- if (audit_backlog_limit
- && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) {
+ if (gfp_mask & __GFP_WAIT)
+ reserve = 0;
+ else
+ reserve = 5; /* Allow atomic callers to go up to five
+ entries over the normal backlog limit */
+
+ while (audit_backlog_limit
+ && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
+ if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time
+ && time_before(jiffies, timeout_start + audit_backlog_wait_time)) {
+
+ /* Wait for auditd to drain the queue a little */
+ DECLARE_WAITQUEUE(wait, current);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&audit_backlog_wait, &wait);
+
+ if (audit_backlog_limit &&
+ skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
+ schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies);
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&audit_backlog_wait, &wait);
+ continue;
+ }
if (audit_rate_check())
printk(KERN_WARNING
"audit: audit_backlog=%d > "
@@ -663,10 +690,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
skb_queue_len(&audit_skb_queue),
audit_backlog_limit);
audit_log_lost("backlog limit exceeded");
+ audit_backlog_wait_time = audit_backlog_wait_overflow;
+ wake_up(&audit_backlog_wait);
return NULL;
}
- ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
+ ab = audit_buffer_alloc(ctx, gfp_mask, type);
if (!ab) {
audit_log_lost("out of memory in audit_log_start");
return NULL;
@@ -690,7 +719,7 @@ static inline int audit_expand(struct audit_buffer *ab, int extra)
{
struct sk_buff *skb = ab->skb;
int ret = pskb_expand_head(skb, skb_headroom(skb), extra,
- GFP_ATOMIC);
+ ab->gfp_mask);
if (ret < 0) {
audit_log_lost("out of memory in audit_expand");
return 0;
@@ -809,7 +838,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
audit_log_format(ab, " %s", prefix);
/* We will allow 11 spaces for ' (deleted)' to be appended */
- path = kmalloc(PATH_MAX+11, GFP_KERNEL);
+ path = kmalloc(PATH_MAX+11, ab->gfp_mask);
if (!path) {
audit_log_format(ab, "<no memory>");
return;
@@ -841,7 +870,7 @@ void audit_log_end(struct audit_buffer *ab)
ab->skb = NULL;
wake_up_interruptible(&kauditd_wait);
} else {
- printk("%s\n", ab->skb->data + NLMSG_SPACE(0));
+ printk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0));
}
}
audit_buffer_free(ab);
@@ -850,12 +879,13 @@ void audit_log_end(struct audit_buffer *ab)
/* Log an audit record. This is a convenience function that calls
* audit_log_start, audit_log_vformat, and audit_log_end. It may be
* called in any context. */
-void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
+void audit_log(struct audit_context *ctx, int gfp_mask, int type,
+ const char *fmt, ...)
{
struct audit_buffer *ab;
va_list args;
- ab = audit_log_start(ctx, type);
+ ab = audit_log_start(ctx, gfp_mask, type);
if (ab) {
va_start(args, fmt);
audit_log_vformat(ab, fmt, args);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e75f84e..88696f6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -39,6 +39,9 @@
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
+#include <linux/kthread.h>
+#include <linux/netlink.h>
+#include <linux/compiler.h>
#include <asm/unistd.h>
/* 0 = no checking
@@ -95,6 +98,7 @@ struct audit_names {
uid_t uid;
gid_t gid;
dev_t rdev;
+ unsigned flags;
};
struct audit_aux_data {
@@ -167,9 +171,16 @@ struct audit_context {
/* There are three lists of rules -- one to search at task creation
* time, one to search at syscall entry time, and another to search at
* syscall exit time. */
-static LIST_HEAD(audit_tsklist);
-static LIST_HEAD(audit_entlist);
-static LIST_HEAD(audit_extlist);
+static struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
+ LIST_HEAD_INIT(audit_filter_list[0]),
+ LIST_HEAD_INIT(audit_filter_list[1]),
+ LIST_HEAD_INIT(audit_filter_list[2]),
+ LIST_HEAD_INIT(audit_filter_list[3]),
+ LIST_HEAD_INIT(audit_filter_list[4]),
+#if AUDIT_NR_FILTERS != 5
+#error Fix audit_filter_list initialiser
+#endif
+};
struct audit_entry {
struct list_head list;
@@ -179,9 +190,36 @@ struct audit_entry {
extern int audit_pid;
+/* Copy rule from user-space to kernel-space. Called from
+ * audit_add_rule during AUDIT_ADD. */
+static inline int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
+{
+ int i;
+
+ if (s->action != AUDIT_NEVER
+ && s->action != AUDIT_POSSIBLE
+ && s->action != AUDIT_ALWAYS)
+ return -1;
+ if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
+ return -1;
+ if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
+ return -1;
+
+ d->flags = s->flags;
+ d->action = s->action;
+ d->field_count = s->field_count;
+ for (i = 0; i < d->field_count; i++) {
+ d->fields[i] = s->fields[i];
+ d->values[i] = s->values[i];
+ }
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
+ return 0;
+}
+
/* Check to see if two rules are identical. It is called from
+ * audit_add_rule during AUDIT_ADD and
* audit_del_rule during AUDIT_DEL. */
-static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
+static inline int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
{
int i;
@@ -210,19 +248,37 @@ static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
/* Note that audit_add_rule and audit_del_rule are called via
* audit_receive() in audit.c, and are protected by
* audit_netlink_sem. */
-static inline int audit_add_rule(struct audit_entry *entry,
- struct list_head *list)
+static inline int audit_add_rule(struct audit_rule *rule,
+ struct list_head *list)
{
- if (entry->rule.flags & AUDIT_PREPEND) {
- entry->rule.flags &= ~AUDIT_PREPEND;
+ struct audit_entry *entry;
+
+ /* Do not use the _rcu iterator here, since this is the only
+ * addition routine. */
+ list_for_each_entry(entry, list, list) {
+ if (!audit_compare_rule(rule, &entry->rule)) {
+ return -EEXIST;
+ }
+ }
+
+ if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
+ return -ENOMEM;
+ if (audit_copy_rule(&entry->rule, rule)) {
+ kfree(entry);
+ return -EINVAL;
+ }
+
+ if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
+ entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
list_add_rcu(&entry->list, list);
} else {
list_add_tail_rcu(&entry->list, list);
}
+
return 0;
}
-static void audit_free_rule(struct rcu_head *head)
+static inline void audit_free_rule(struct rcu_head *head)
{
struct audit_entry *e = container_of(head, struct audit_entry, rcu);
kfree(e);
@@ -245,82 +301,82 @@ static inline int audit_del_rule(struct audit_rule *rule,
return 0;
}
}
- return -EFAULT; /* No matching rule */
+ return -ENOENT; /* No matching rule */
}
-/* Copy rule from user-space to kernel-space. Called during
- * AUDIT_ADD. */
-static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
+static int audit_list_rules(void *_dest)
{
+ int pid, seq;
+ int *dest = _dest;
+ struct audit_entry *entry;
int i;
- if (s->action != AUDIT_NEVER
- && s->action != AUDIT_POSSIBLE
- && s->action != AUDIT_ALWAYS)
- return -1;
- if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
- return -1;
+ pid = dest[0];
+ seq = dest[1];
+ kfree(dest);
- d->flags = s->flags;
- d->action = s->action;
- d->field_count = s->field_count;
- for (i = 0; i < d->field_count; i++) {
- d->fields[i] = s->fields[i];
- d->values[i] = s->values[i];
+ down(&audit_netlink_sem);
+
+ /* The *_rcu iterators not needed here because we are
+ always called with audit_netlink_sem held. */
+ for (i=0; i<AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry(entry, &audit_filter_list[i], list)
+ audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
+ &entry->rule, sizeof(entry->rule));
}
- for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
+ audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+
+ up(&audit_netlink_sem);
return 0;
}
int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
uid_t loginuid)
{
- u32 flags;
- struct audit_entry *entry;
+ struct task_struct *tsk;
+ int *dest;
int err = 0;
+ unsigned listnr;
switch (type) {
case AUDIT_LIST:
- /* The *_rcu iterators not needed here because we are
- always called with audit_netlink_sem held. */
- list_for_each_entry(entry, &audit_tsklist, list)
- audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
- &entry->rule, sizeof(entry->rule));
- list_for_each_entry(entry, &audit_entlist, list)
- audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
- &entry->rule, sizeof(entry->rule));
- list_for_each_entry(entry, &audit_extlist, list)
- audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
- &entry->rule, sizeof(entry->rule));
- audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+ /* We can't just spew out the rules here because we might fill
+ * the available socket buffer space and deadlock waiting for
+ * auditctl to read from it... which isn't ever going to
+ * happen if we're actually running in the context of auditctl
+ * trying to _send_ the stuff */
+
+ dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
+ if (!dest)
+ return -ENOMEM;
+ dest[0] = pid;
+ dest[1] = seq;
+
+ tsk = kthread_run(audit_list_rules, dest, "audit_list_rules");
+ if (IS_ERR(tsk)) {
+ kfree(dest);
+ err = PTR_ERR(tsk);
+ }
break;
case AUDIT_ADD:
- if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
- return -ENOMEM;
- if (audit_copy_rule(&entry->rule, data)) {
- kfree(entry);
+ listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
+ if (listnr >= AUDIT_NR_FILTERS)
return -EINVAL;
- }
- flags = entry->rule.flags;
- if (!err && (flags & AUDIT_PER_TASK))
- err = audit_add_rule(entry, &audit_tsklist);
- if (!err && (flags & AUDIT_AT_ENTRY))
- err = audit_add_rule(entry, &audit_entlist);
- if (!err && (flags & AUDIT_AT_EXIT))
- err = audit_add_rule(entry, &audit_extlist);
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
- "auid=%u added an audit rule\n", loginuid);
+
+ err = audit_add_rule(data, &audit_filter_list[listnr]);
+ if (!err)
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u added an audit rule\n", loginuid);
break;
case AUDIT_DEL:
- flags =((struct audit_rule *)data)->flags;
- if (!err && (flags & AUDIT_PER_TASK))
- err = audit_del_rule(data, &audit_tsklist);
- if (!err && (flags & AUDIT_AT_ENTRY))
- err = audit_del_rule(data, &audit_entlist);
- if (!err && (flags & AUDIT_AT_EXIT))
- err = audit_del_rule(data, &audit_extlist);
- audit_log(NULL, AUDIT_CONFIG_CHANGE,
- "auid=%u removed an audit rule\n", loginuid);
+ listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
+ if (listnr >= AUDIT_NR_FILTERS)
+ return -EINVAL;
+
+ err = audit_del_rule(data, &audit_filter_list[listnr]);
+ if (!err)
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u removed an audit rule\n", loginuid);
break;
default:
return -EINVAL;
@@ -384,8 +440,12 @@ static int audit_filter_rules(struct task_struct *tsk,
result = (ctx->return_code == value);
break;
case AUDIT_SUCCESS:
- if (ctx && ctx->return_valid)
- result = (ctx->return_valid == AUDITSC_SUCCESS);
+ if (ctx && ctx->return_valid) {
+ if (value)
+ result = (ctx->return_valid == AUDITSC_SUCCESS);
+ else
+ result = (ctx->return_valid == AUDITSC_FAILURE);
+ }
break;
case AUDIT_DEVMAJOR:
if (ctx) {
@@ -454,7 +514,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
enum audit_state state;
rcu_read_lock();
- list_for_each_entry_rcu(e, &audit_tsklist, list) {
+ list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
rcu_read_unlock();
return state;
@@ -474,20 +534,84 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
struct list_head *list)
{
struct audit_entry *e;
+ enum audit_state state;
+
+ if (audit_pid && tsk->tgid == audit_pid)
+ return AUDIT_DISABLED;
+
+ rcu_read_lock();
+ if (!list_empty(list)) {
+ int word = AUDIT_WORD(ctx->major);
+ int bit = AUDIT_BIT(ctx->major);
+
+ list_for_each_entry_rcu(e, list, list) {
+ if ((e->rule.mask[word] & bit) == bit
+ && audit_filter_rules(tsk, &e->rule, ctx, &state)) {
+ rcu_read_unlock();
+ return state;
+ }
+ }
+ }
+ rcu_read_unlock();
+ return AUDIT_BUILD_CONTEXT;
+}
+
+static int audit_filter_user_rules(struct netlink_skb_parms *cb,
+ struct audit_rule *rule,
+ enum audit_state *state)
+{
+ int i;
+
+ for (i = 0; i < rule->field_count; i++) {
+ u32 field = rule->fields[i] & ~AUDIT_NEGATE;
+ u32 value = rule->values[i];
+ int result = 0;
+
+ switch (field) {
+ case AUDIT_PID:
+ result = (cb->creds.pid == value);
+ break;
+ case AUDIT_UID:
+ result = (cb->creds.uid == value);
+ break;
+ case AUDIT_GID:
+ result = (cb->creds.gid == value);
+ break;
+ case AUDIT_LOGINUID:
+ result = (cb->loginuid == value);
+ break;
+ }
+
+ if (rule->fields[i] & AUDIT_NEGATE)
+ result = !result;
+ if (!result)
+ return 0;
+ }
+ switch (rule->action) {
+ case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
+ case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT; break;
+ case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
+ }
+ return 1;
+}
+
+int audit_filter_user(struct netlink_skb_parms *cb, int type)
+{
+ struct audit_entry *e;
enum audit_state state;
- int word = AUDIT_WORD(ctx->major);
- int bit = AUDIT_BIT(ctx->major);
+ int ret = 1;
rcu_read_lock();
- list_for_each_entry_rcu(e, list, list) {
- if ((e->rule.mask[word] & bit) == bit
- && audit_filter_rules(tsk, &e->rule, ctx, &state)) {
- rcu_read_unlock();
- return state;
+ list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
+ if (audit_filter_user_rules(cb, &e->rule, &state)) {
+ if (state == AUDIT_DISABLED)
+ ret = 0;
+ break;
}
}
rcu_read_unlock();
- return AUDIT_BUILD_CONTEXT;
+
+ return ret; /* Audit by default */
}
/* This should be called with task_lock() held. */
@@ -504,7 +628,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
if (context->in_syscall && !context->auditable) {
enum audit_state state;
- state = audit_filter_syscall(tsk, context, &audit_extlist);
+ state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
if (state == AUDIT_RECORD_CONTEXT)
context->auditable = 1;
}
@@ -679,13 +803,13 @@ static void audit_log_task_info(struct audit_buffer *ab)
up_read(&mm->mmap_sem);
}
-static void audit_log_exit(struct audit_context *context)
+static void audit_log_exit(struct audit_context *context, unsigned int gfp_mask)
{
int i;
struct audit_buffer *ab;
struct audit_aux_data *aux;
- ab = audit_log_start(context, AUDIT_SYSCALL);
+ ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "arch=%x syscall=%d",
@@ -717,7 +841,7 @@ static void audit_log_exit(struct audit_context *context)
for (aux = context->aux; aux; aux = aux->next) {
- ab = audit_log_start(context, aux->type);
+ ab = audit_log_start(context, GFP_KERNEL, aux->type);
if (!ab)
continue; /* audit_panic has been called */
@@ -754,14 +878,14 @@ static void audit_log_exit(struct audit_context *context)
}
if (context->pwd && context->pwdmnt) {
- ab = audit_log_start(context, AUDIT_CWD);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
if (ab) {
audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
audit_log_end(ab);
}
}
for (i = 0; i < context->name_count; i++) {
- ab = audit_log_start(context, AUDIT_PATH);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */
@@ -770,6 +894,8 @@ static void audit_log_exit(struct audit_context *context)
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, context->names[i].name);
}
+ audit_log_format(ab, " flags=%x\n", context->names[i].flags);
+
if (context->names[i].ino != (unsigned long)-1)
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
" ouid=%u ogid=%u rdev=%02x:%02x",
@@ -799,9 +925,11 @@ void audit_free(struct task_struct *tsk)
return;
/* Check for system calls that do not go through the exit
- * function (e.g., exit_group), then free context block. */
- if (context->in_syscall && context->auditable && context->pid != audit_pid)
- audit_log_exit(context);
+ * function (e.g., exit_group), then free context block.
+ * We use GFP_ATOMIC here because we might be doing this
+ * in the context of the idle thread */
+ if (context->in_syscall && context->auditable)
+ audit_log_exit(context, GFP_ATOMIC);
audit_free_context(context);
}
@@ -876,11 +1004,11 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
state = context->state;
if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)
- state = audit_filter_syscall(tsk, context, &audit_entlist);
+ state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
if (likely(state == AUDIT_DISABLED))
return;
- context->serial = audit_serial();
+ context->serial = 0;
context->ctime = CURRENT_TIME;
context->in_syscall = 1;
context->auditable = !!(state == AUDIT_RECORD_CONTEXT);
@@ -903,10 +1031,10 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
/* Not having a context here is ok, since the parent may have
* called __put_task_struct. */
if (likely(!context))
- return;
+ goto out;
- if (context->in_syscall && context->auditable && context->pid != audit_pid)
- audit_log_exit(context);
+ if (context->in_syscall && context->auditable)
+ audit_log_exit(context, GFP_KERNEL);
context->in_syscall = 0;
context->auditable = 0;
@@ -919,9 +1047,9 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
} else {
audit_free_names(context);
audit_free_aux(context);
- audit_zero_context(context, context->state);
tsk->audit_context = context;
}
+ out:
put_task_struct(tsk);
}
@@ -996,7 +1124,7 @@ void audit_putname(const char *name)
/* Store the inode and device from a lookup. Called from
* fs/namei.c:path_lookup(). */
-void audit_inode(const char *name, const struct inode *inode)
+void audit_inode(const char *name, const struct inode *inode, unsigned flags)
{
int idx;
struct audit_context *context = current->audit_context;
@@ -1022,17 +1150,20 @@ void audit_inode(const char *name, const struct inode *inode)
++context->ino_count;
#endif
}
- context->names[idx].ino = inode->i_ino;
- context->names[idx].dev = inode->i_sb->s_dev;
- context->names[idx].mode = inode->i_mode;
- context->names[idx].uid = inode->i_uid;
- context->names[idx].gid = inode->i_gid;
- context->names[idx].rdev = inode->i_rdev;
+ context->names[idx].flags = flags;
+ context->names[idx].ino = inode->i_ino;
+ context->names[idx].dev = inode->i_sb->s_dev;
+ context->names[idx].mode = inode->i_mode;
+ context->names[idx].uid = inode->i_uid;
+ context->names[idx].gid = inode->i_gid;
+ context->names[idx].rdev = inode->i_rdev;
}
void auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial)
{
+ if (!ctx->serial)
+ ctx->serial = audit_serial();
t->tv_sec = ctx->ctime.tv_sec;
t->tv_nsec = ctx->ctime.tv_nsec;
*serial = ctx->serial;
@@ -1044,7 +1175,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
if (task->audit_context) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL, AUDIT_LOGIN);
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
if (ab) {
audit_log_format(ab, "login pid=%d uid=%u "
"old auid=%u new auid=%u",
@@ -1153,7 +1284,7 @@ void audit_signal_info(int sig, struct task_struct *t)
extern pid_t audit_sig_pid;
extern uid_t audit_sig_uid;
- if (unlikely(audit_pid && t->pid == audit_pid)) {
+ if (unlikely(audit_pid && t->tgid == audit_pid)) {
if (sig == SIGTERM || sig == SIGHUP) {
struct audit_context *ctx = current->audit_context;
audit_sig_pid = current->pid;
diff --git a/kernel/exit.c b/kernel/exit.c
index 6d2089a..ee6d8b8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files)
struct fdtable *fdt;
j = 0;
+
+ /*
+ * It is safe to dereference the fd table without RCU or
+ * ->file_lock because this is the last reference to the
+ * files structure.
+ */
fdt = files_fdtable(files);
for (;;) {
unsigned long set;
diff --git a/kernel/fork.c b/kernel/fork.c
index 8149f36..533ce27 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1062,7 +1062,8 @@ static task_t *copy_process(unsigned long clone_flags,
* parent's CPU). This avoids alot of nasty races.
*/
p->cpus_allowed = current->cpus_allowed;
- if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed)))
+ if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) ||
+ !cpu_online(task_cpu(p))))
set_task_cpu(p, smp_processor_id());
/*
diff --git a/kernel/module.c b/kernel/module.c
index 4b39d37..ff5c500 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/elf.h>
@@ -498,7 +499,7 @@ static inline int try_force(unsigned int flags)
{
int ret = (flags & O_TRUNC);
if (ret)
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
return ret;
}
#else
@@ -897,7 +898,7 @@ static int check_version(Elf_Shdr *sechdrs,
if (!(tainted & TAINT_FORCED_MODULE)) {
printk("%s: no version for \"%s\" found: kernel tainted.\n",
mod->name, symname);
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
}
return 1;
}
@@ -1352,7 +1353,7 @@ static void set_license(struct module *mod, const char *license)
if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) {
printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
mod->name, license);
- tainted |= TAINT_PROPRIETARY_MODULE;
+ add_taint(TAINT_PROPRIETARY_MODULE);
}
}
@@ -1610,7 +1611,7 @@ static struct module *load_module(void __user *umod,
modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
/* This is allowed: modprobe --force will invalidate it. */
if (!modmagic) {
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
mod->name);
} else if (!same_magic(modmagic, vermagic)) {
@@ -1739,7 +1740,7 @@ static struct module *load_module(void __user *umod,
(mod->num_gpl_syms && !gplcrcindex)) {
printk(KERN_WARNING "%s: No versions for exported symbols."
" Tainting kernel.\n", mod->name);
- tainted |= TAINT_FORCED_MODULE;
+ add_taint(TAINT_FORCED_MODULE);
}
#endif
diff --git a/kernel/sched.c b/kernel/sched.c
index 81b3a96..1f31a52 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -294,6 +294,10 @@ static inline void prepare_lock_switch(runqueue_t *rq, task_t *next)
static inline void finish_lock_switch(runqueue_t *rq, task_t *prev)
{
+#ifdef CONFIG_DEBUG_SPINLOCK
+ /* this is a valid case when another task releases the spinlock */
+ rq->lock.owner = current;
+#endif
spin_unlock_irq(&rq->lock);
}
@@ -1529,10 +1533,6 @@ static inline void finish_task_switch(runqueue_t *rq, task_t *prev)
* Manfred Spraul <manfred@colorfullife.com>
*/
prev_task_flags = prev->flags;
-#ifdef CONFIG_DEBUG_SPINLOCK
- /* this is a valid case when another task releases the spinlock */
- rq->lock.owner = current;
-#endif
finish_arch_switch(prev);
finish_lock_switch(rq, prev);
if (mm)
diff --git a/kernel/sys.c b/kernel/sys.c
index c80412b..f723522 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1728,8 +1728,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
error = put_user(current->pdeath_signal, (int __user *)arg2);
break;
case PR_GET_DUMPABLE:
- if (current->mm->dumpable)
- error = 1;
+ error = current->mm->dumpable;
break;
case PR_SET_DUMPABLE:
if (arg2 < 0 || arg2 > 2) {
diff --git a/kernel/timer.c b/kernel/timer.c
index f4152fc..3ba10fa 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1151,19 +1151,22 @@ fastcall signed long __sched schedule_timeout(signed long timeout)
out:
return timeout < 0 ? 0 : timeout;
}
-
EXPORT_SYMBOL(schedule_timeout);
+/*
+ * We can use __set_current_state() here because schedule_timeout() calls
+ * schedule() unconditionally.
+ */
signed long __sched schedule_timeout_interruptible(signed long timeout)
{
- set_current_state(TASK_INTERRUPTIBLE);
+ __set_current_state(TASK_INTERRUPTIBLE);
return schedule_timeout(timeout);
}
EXPORT_SYMBOL(schedule_timeout_interruptible);
signed long __sched schedule_timeout_uninterruptible(signed long timeout)
{
- set_current_state(TASK_UNINTERRUPTIBLE);
+ __set_current_state(TASK_UNINTERRUPTIBLE);
return schedule_timeout(timeout);
}
EXPORT_SYMBOL(schedule_timeout_uninterruptible);
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index 2377af0..305a966 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -1,7 +1,41 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/atomic.h>
+#include <asm/system.h>
+#ifdef __HAVE_ARCH_CMPXCHG
+/*
+ * This is an implementation of the notion of "decrement a
+ * reference count, and return locked if it decremented to zero".
+ *
+ * This implementation can be used on any architecture that
+ * has a cmpxchg, and where atomic->value is an int holding
+ * the value of the atomic (i.e. the high bits aren't used
+ * for a lock or anything like that).
+ */
+int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+ int counter;
+ int newcount;
+
+ for (;;) {
+ counter = atomic_read(atomic);
+ newcount = counter - 1;
+ if (!newcount)
+ break; /* do it the slow way */
+
+ newcount = cmpxchg(&atomic->counter, counter, newcount);
+ if (newcount == counter)
+ return 0;
+ }
+
+ spin_lock(lock);
+ if (atomic_dec_and_test(atomic))
+ return 1;
+ spin_unlock(lock);
+ return 0;
+}
+#else
/*
* This is an architecture-neutral, but slow,
* implementation of the notion of "decrement
@@ -33,5 +67,6 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
spin_unlock(lock);
return 0;
}
+#endif
EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/mm/Kconfig b/mm/Kconfig
index 4e9937a..391ffc5 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -29,7 +29,7 @@ config FLATMEM_MANUAL
If unsure, choose this option (Flat Memory) over any other.
config DISCONTIGMEM_MANUAL
- bool "Discontigious Memory"
+ bool "Discontiguous Memory"
depends on ARCH_DISCONTIGMEM_ENABLE
help
This option provides enhanced support for discontiguous
@@ -52,7 +52,7 @@ config SPARSEMEM_MANUAL
memory hotplug systems. This is normal.
For many other systems, this will be an alternative to
- "Discontigious Memory". This option provides some potential
+ "Discontiguous Memory". This option provides some potential
performance benefits, along with decreased code complexity,
but it is newer, and more experimental.
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index afa06e1..9033f08 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -333,8 +333,13 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
if (prev && prev->vm_end < vma->vm_start)
return ERR_PTR(-EFAULT);
if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
+ unsigned long endvma = vma->vm_end;
+ if (endvma > end)
+ endvma = end;
+ if (vma->vm_start > start)
+ start = vma->vm_start;
err = check_pgd_range(vma->vm_mm,
- vma->vm_start, vma->vm_end, nodes);
+ start, endvma, nodes);
if (err) {
first = ERR_PTR(err);
break;
diff --git a/mm/mmap.c b/mm/mmap.c
index 12334ae..8b8e05f 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1993,6 +1993,9 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
__vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent);
if (__vma && __vma->vm_start < vma->vm_end)
return -ENOMEM;
+ if ((vma->vm_flags & VM_ACCOUNT) &&
+ security_vm_enough_memory(vma_pages(vma)))
+ return -ENOMEM;
vma_link(mm, vma, prev, rb_link, rb_parent);
return 0;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c5823c3..ae29033 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -22,6 +22,7 @@
#include <linux/pagemap.h>
#include <linux/bootmem.h>
#include <linux/compiler.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/suspend.h>
#include <linux/pagevec.h>
@@ -117,7 +118,7 @@ static void bad_page(const char *function, struct page *page)
set_page_count(page, 0);
reset_page_mapcount(page);
page->mapping = NULL;
- tainted |= TAINT_BAD_PAGE;
+ add_taint(TAINT_BAD_PAGE);
}
#ifndef CONFIG_HUGETLB_PAGE
diff --git a/mm/slab.c b/mm/slab.c
index 9e876d6..437d338 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -659,7 +659,7 @@ static inline kmem_cache_t *__find_general_cachep(size_t size,
* kmem_cache_create(), or __kmalloc(), before
* the generic caches are initialized.
*/
- BUG_ON(csizep->cs_cachep == NULL);
+ BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
#endif
while (size > csizep->cs_size)
csizep++;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index a740778..0ea71e8 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1258,9 +1258,9 @@ void wakeup_kswapd(struct zone *zone, int order)
pgdat->kswapd_max_order = order;
if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
return;
- if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
+ if (!waitqueue_active(&pgdat->kswapd_wait))
return;
- wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
+ wake_up_interruptible(&pgdat->kswapd_wait);
}
#ifdef CONFIG_PM
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 145f5cd..b748648 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -120,7 +120,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
unsigned short vid;
struct net_device_stats *stats;
unsigned short vlan_TCI;
- unsigned short proto;
+ __be16 proto;
/* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
vlan_TCI = ntohs(vhdr->h_vlan_TCI);
diff --git a/net/Kconfig b/net/Kconfig
index 2bdd562..60f6f32 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -140,6 +140,7 @@ config BRIDGE_NETFILTER
If unsure, say N.
+source "net/netfilter/Kconfig"
source "net/ipv4/netfilter/Kconfig"
source "net/ipv6/netfilter/Kconfig"
source "net/decnet/netfilter/Kconfig"
@@ -206,8 +207,6 @@ config NET_PKTGEN
To compile this code as a module, choose M here: the
module will be called pktgen.
-source "net/netfilter/Kconfig"
-
endmenu
endmenu
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d6da093..b61b4e8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -558,6 +558,35 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_dev_unlock(hdev);
}
+/* Extended Inquiry Result */
+static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct inquiry_data data;
+ struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1);
+ int num_rsp = *((__u8 *) skb->data);
+
+ BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+
+ if (!num_rsp)
+ return;
+
+ hci_dev_lock(hdev);
+
+ for (; num_rsp; num_rsp--) {
+ bacpy(&data.bdaddr, &info->bdaddr);
+ data.pscan_rep_mode = info->pscan_rep_mode;
+ data.pscan_period_mode = info->pscan_period_mode;
+ data.pscan_mode = 0x00;
+ memcpy(data.dev_class, info->dev_class, 3);
+ data.clock_offset = info->clock_offset;
+ data.rssi = info->rssi;
+ info++;
+ hci_inquiry_cache_update(hdev, &data);
+ }
+
+ hci_dev_unlock(hdev);
+}
+
/* Connect Request */
static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
@@ -940,6 +969,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_inquiry_result_with_rssi_evt(hdev, skb);
break;
+ case HCI_EV_EXTENDED_INQUIRY_RESULT:
+ hci_extended_inquiry_result_evt(hdev, skb);
+ break;
+
case HCI_EV_CONN_REQUEST:
hci_conn_request_evt(hdev, skb);
break;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 90e19eb..f49e7e9 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -363,6 +363,11 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
goto done;
}
+ if (sk->sk_type != SOCK_STREAM) {
+ err = -EINVAL;
+ goto done;
+ }
+
write_lock_bh(&rfcomm_sk_list.lock);
if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) {
@@ -393,13 +398,17 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc))
return -EINVAL;
- if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
- return -EBADFD;
+ lock_sock(sk);
- if (sk->sk_type != SOCK_STREAM)
- return -EINVAL;
+ if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
+ err = -EBADFD;
+ goto done;
+ }
- lock_sock(sk);
+ if (sk->sk_type != SOCK_STREAM) {
+ err = -EINVAL;
+ goto done;
+ }
sk->sk_state = BT_CONNECT;
bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr);
@@ -410,6 +419,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
+done:
release_sock(sk);
return err;
}
@@ -428,6 +438,11 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog)
goto done;
}
+ if (sk->sk_type != SOCK_STREAM) {
+ err = -EINVAL;
+ goto done;
+ }
+
if (!rfcomm_pi(sk)->channel) {
bdaddr_t *src = &bt_sk(sk)->src;
u8 channel;
@@ -472,6 +487,11 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
goto done;
}
+ if (sk->sk_type != SOCK_STREAM) {
+ err = -EINVAL;
+ goto done;
+ }
+
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
BT_DBG("sk %p timeo %ld", sk, timeo);
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 2d52fee..d8e36b7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -214,9 +214,11 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
.tos = RT_TOS(iph->tos)} }, .proto = 0};
if (!ip_route_output_key(&rt, &fl)) {
- /* Bridged-and-DNAT'ed traffic doesn't
- * require ip_forwarding. */
- if (((struct dst_entry *)rt)->dev == dev) {
+ /* - Bridged-and-DNAT'ed traffic doesn't
+ * require ip_forwarding.
+ * - Deal with redirected traffic. */
+ if (((struct dst_entry *)rt)->dev == dev ||
+ rt->rt_type == RTN_LOCAL) {
skb->dst = (struct dst_entry *)rt;
goto bridged_dnat;
}
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index fb97bb0..344a8da 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -3,6 +3,8 @@ obj-$(CONFIG_IP_DCCP) += dccp.o
dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \
timer.o
+dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
+
obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
dccp_diag-y := diag.o
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
new file mode 100644
index 0000000..6530283
--- /dev/null
+++ b/net/dccp/ackvec.c
@@ -0,0 +1,419 @@
+/*
+ * net/dccp/ackvec.c
+ *
+ * An implementation of the DCCP protocol
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License;
+ */
+
+#include "ackvec.h"
+#include "dccp.h"
+
+#include <linux/dccp.h>
+#include <linux/skbuff.h>
+
+#include <net/sock.h>
+
+int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
+ int len = av->dccpav_vec_len + 2;
+ struct timeval now;
+ u32 elapsed_time;
+ unsigned char *to, *from;
+
+ dccp_timestamp(sk, &now);
+ elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
+
+ if (elapsed_time != 0)
+ dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
+
+ if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
+ return -1;
+
+ /*
+ * XXX: now we have just one ack vector sent record, so
+ * we have to wait for it to be cleared.
+ *
+ * Of course this is not acceptable, but this is just for
+ * basic testing now.
+ */
+ if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1)
+ return -1;
+
+ DCCP_SKB_CB(skb)->dccpd_opt_len += len;
+
+ to = skb_push(skb, len);
+ *to++ = DCCPO_ACK_VECTOR_0;
+ *to++ = len;
+
+ len = av->dccpav_vec_len;
+ from = av->dccpav_buf + av->dccpav_buf_head;
+
+ /* Check if buf_head wraps */
+ if (av->dccpav_buf_head + len > av->dccpav_vec_len) {
+ const u32 tailsize = (av->dccpav_vec_len - av->dccpav_buf_head);
+
+ memcpy(to, from, tailsize);
+ to += tailsize;
+ len -= tailsize;
+ from = av->dccpav_buf;
+ }
+
+ memcpy(to, from, len);
+ /*
+ * From draft-ietf-dccp-spec-11.txt:
+ *
+ * For each acknowledgement it sends, the HC-Receiver will add an
+ * acknowledgement record. ack_seqno will equal the HC-Receiver
+ * sequence number it used for the ack packet; ack_ptr will equal
+ * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
+ * equal buf_nonce.
+ *
+ * This implemention uses just one ack record for now.
+ */
+ av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
+ av->dccpav_ack_ptr = av->dccpav_buf_head;
+ av->dccpav_ack_ackno = av->dccpav_buf_ackno;
+ av->dccpav_ack_nonce = av->dccpav_buf_nonce;
+ av->dccpav_sent_len = av->dccpav_vec_len;
+
+ dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
+ "ack_ackno=%llu\n",
+ debug_prefix, av->dccpav_sent_len,
+ (unsigned long long)av->dccpav_ack_seqno,
+ (unsigned long long)av->dccpav_ack_ackno);
+ return -1;
+}
+
+struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len,
+ const unsigned int __nocast priority)
+{
+ struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority);
+
+ if (av != NULL) {
+ av->dccpav_buf_len = len;
+ av->dccpav_buf_head =
+ av->dccpav_buf_tail = av->dccpav_buf_len - 1;
+ av->dccpav_buf_ackno =
+ av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU;
+ av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
+ av->dccpav_ack_ptr = 0;
+ av->dccpav_time.tv_sec = 0;
+ av->dccpav_time.tv_usec = 0;
+ av->dccpav_sent_len = av->dccpav_vec_len = 0;
+ }
+
+ return av;
+}
+
+void dccp_ackvec_free(struct dccp_ackvec *av)
+{
+ kfree(av);
+}
+
+static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
+ const unsigned int index)
+{
+ return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK;
+}
+
+static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
+ const unsigned int index)
+{
+ return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
+}
+
+/*
+ * If several packets are missing, the HC-Receiver may prefer to enter multiple
+ * bytes with run length 0, rather than a single byte with a larger run length;
+ * this simplifies table updates if one of the missing packets arrives.
+ */
+static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
+ const unsigned int packets,
+ const unsigned char state)
+{
+ unsigned int gap;
+ signed long new_head;
+
+ if (av->dccpav_vec_len + packets > av->dccpav_buf_len)
+ return -ENOBUFS;
+
+ gap = packets - 1;
+ new_head = av->dccpav_buf_head - packets;
+
+ if (new_head < 0) {
+ if (gap > 0) {
+ memset(av->dccpav_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED,
+ gap + new_head + 1);
+ gap = -new_head;
+ }
+ new_head += av->dccpav_buf_len;
+ }
+
+ av->dccpav_buf_head = new_head;
+
+ if (gap > 0)
+ memset(av->dccpav_buf + av->dccpav_buf_head + 1,
+ DCCP_ACKVEC_STATE_NOT_RECEIVED, gap);
+
+ av->dccpav_buf[av->dccpav_buf_head] = state;
+ av->dccpav_vec_len += packets;
+ return 0;
+}
+
+/*
+ * Implements the draft-ietf-dccp-spec-11.txt Appendix A
+ */
+int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
+ const u64 ackno, const u8 state)
+{
+ /*
+ * Check at the right places if the buffer is full, if it is, tell the
+ * caller to start dropping packets till the HC-Sender acks our ACK
+ * vectors, when we will free up space in dccpav_buf.
+ *
+ * We may well decide to do buffer compression, etc, but for now lets
+ * just drop.
+ *
+ * From Appendix A:
+ *
+ * Of course, the circular buffer may overflow, either when the
+ * HC-Sender is sending data at a very high rate, when the
+ * HC-Receiver's acknowledgements are not reaching the HC-Sender,
+ * or when the HC-Sender is forgetting to acknowledge those acks
+ * (so the HC-Receiver is unable to clean up old state). In this
+ * case, the HC-Receiver should either compress the buffer (by
+ * increasing run lengths when possible), transfer its state to
+ * a larger buffer, or, as a last resort, drop all received
+ * packets, without processing them whatsoever, until its buffer
+ * shrinks again.
+ */
+
+ /* See if this is the first ackno being inserted */
+ if (av->dccpav_vec_len == 0) {
+ av->dccpav_buf[av->dccpav_buf_head] = state;
+ av->dccpav_vec_len = 1;
+ } else if (after48(ackno, av->dccpav_buf_ackno)) {
+ const u64 delta = dccp_delta_seqno(av->dccpav_buf_ackno,
+ ackno);
+
+ /*
+ * Look if the state of this packet is the same as the
+ * previous ackno and if so if we can bump the head len.
+ */
+ if (delta == 1 &&
+ dccp_ackvec_state(av, av->dccpav_buf_head) == state &&
+ (dccp_ackvec_len(av, av->dccpav_buf_head) <
+ DCCP_ACKVEC_LEN_MASK))
+ av->dccpav_buf[av->dccpav_buf_head]++;
+ else if (dccp_ackvec_set_buf_head_state(av, delta, state))
+ return -ENOBUFS;
+ } else {
+ /*
+ * A.1.2. Old Packets
+ *
+ * When a packet with Sequence Number S arrives, and
+ * S <= buf_ackno, the HC-Receiver will scan the table
+ * for the byte corresponding to S. (Indexing structures
+ * could reduce the complexity of this scan.)
+ */
+ u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
+ unsigned int index = av->dccpav_buf_head;
+
+ while (1) {
+ const u8 len = dccp_ackvec_len(av, index);
+ const u8 state = dccp_ackvec_state(av, index);
+ /*
+ * valid packets not yet in dccpav_buf have a reserved
+ * entry, with a len equal to 0.
+ */
+ if (state == DCCP_ACKVEC_STATE_NOT_RECEIVED &&
+ len == 0 && delta == 0) { /* Found our
+ reserved seat! */
+ dccp_pr_debug("Found %llu reserved seat!\n",
+ (unsigned long long)ackno);
+ av->dccpav_buf[index] = state;
+ goto out;
+ }
+ /* len == 0 means one packet */
+ if (delta < len + 1)
+ goto out_duplicate;
+
+ delta -= len + 1;
+ if (++index == av->dccpav_buf_len)
+ index = 0;
+ }
+ }
+
+ av->dccpav_buf_ackno = ackno;
+ dccp_timestamp(sk, &av->dccpav_time);
+out:
+ dccp_pr_debug("");
+ return 0;
+
+out_duplicate:
+ /* Duplicate packet */
+ dccp_pr_debug("Received a dup or already considered lost "
+ "packet: %llu\n", (unsigned long long)ackno);
+ return -EILSEQ;
+}
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
+{
+ if (!dccp_debug)
+ return;
+
+ printk("ACK vector len=%d, ackno=%llu |", len,
+ (unsigned long long)ackno);
+
+ while (len--) {
+ const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
+ const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
+
+ printk("%d,%d|", state, rl);
+ ++vector;
+ }
+
+ printk("\n");
+}
+
+void dccp_ackvec_print(const struct dccp_ackvec *av)
+{
+ dccp_ackvector_print(av->dccpav_buf_ackno,
+ av->dccpav_buf + av->dccpav_buf_head,
+ av->dccpav_vec_len);
+}
+#endif
+
+static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av)
+{
+ /*
+ * As we're keeping track of the ack vector size (dccpav_vec_len) and
+ * the sent ack vector size (dccpav_sent_len) we don't need
+ * dccpav_buf_tail at all, but keep this code here as in the future
+ * we'll implement a vector of ack records, as suggested in
+ * draft-ietf-dccp-spec-11.txt Appendix A. -acme
+ */
+#if 0
+ av->dccpav_buf_tail = av->dccpav_ack_ptr + 1;
+ if (av->dccpav_buf_tail >= av->dccpav_vec_len)
+ av->dccpav_buf_tail -= av->dccpav_vec_len;
+#endif
+ av->dccpav_vec_len -= av->dccpav_sent_len;
+}
+
+void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
+ const u64 ackno)
+{
+ /* Check if we actually sent an ACK vector */
+ if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
+ return;
+
+ if (ackno == av->dccpav_ack_seqno) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+ struct dccp_sock *dp = dccp_sk(sk);
+ const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT rx ack: " : "server rx ack: ";
+#endif
+ dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
+ "ack_ackno=%llu, ACKED!\n",
+ debug_prefix, 1,
+ (unsigned long long)av->dccpav_ack_seqno,
+ (unsigned long long)av->dccpav_ack_ackno);
+ dccp_ackvec_trow_away_ack_record(av);
+ av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
+ }
+}
+
+static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
+ struct sock *sk, u64 ackno,
+ const unsigned char len,
+ const unsigned char *vector)
+{
+ unsigned char i;
+
+ /* Check if we actually sent an ACK vector */
+ if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
+ return;
+ /*
+ * We're in the receiver half connection, so if the received an ACK
+ * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're
+ * not interested.
+ *
+ * Extra explanation with example:
+ *
+ * if we received an ACK vector with ackno 50, it can only be acking
+ * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
+ */
+ /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */
+ if (before48(ackno, av->dccpav_ack_seqno)) {
+ /* dccp_pr_debug_cat("yes\n"); */
+ return;
+ }
+ /* dccp_pr_debug_cat("no\n"); */
+
+ i = len;
+ while (i--) {
+ const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
+ u64 ackno_end_rl;
+
+ dccp_set_seqno(&ackno_end_rl, ackno - rl);
+
+ /*
+ * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl,
+ * av->dccpav_ack_seqno, ackno);
+ */
+ if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) {
+ const u8 state = (*vector &
+ DCCP_ACKVEC_STATE_MASK) >> 6;
+ /* dccp_pr_debug_cat("yes\n"); */
+
+ if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+ struct dccp_sock *dp = dccp_sk(sk);
+ const char *debug_prefix =
+ dp->dccps_role == DCCP_ROLE_CLIENT ?
+ "CLIENT rx ack: " : "server rx ack: ";
+#endif
+ dccp_pr_debug("%sACK vector 0, len=%d, "
+ "ack_seqno=%llu, ack_ackno=%llu, "
+ "ACKED!\n",
+ debug_prefix, len,
+ (unsigned long long)
+ av->dccpav_ack_seqno,
+ (unsigned long long)
+ av->dccpav_ack_ackno);
+ dccp_ackvec_trow_away_ack_record(av);
+ }
+ /*
+ * If dccpav_ack_seqno was not received, no problem
+ * we'll send another ACK vector.
+ */
+ av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
+ break;
+ }
+ /* dccp_pr_debug_cat("no\n"); */
+
+ dccp_set_seqno(&ackno, ackno_end_rl - 1);
+ ++vector;
+ }
+}
+
+int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+ const u8 opt, const u8 *value, const u8 len)
+{
+ if (len > DCCP_MAX_ACKVEC_LEN)
+ return -1;
+
+ /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */
+ dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk,
+ DCCP_SKB_CB(skb)->dccpd_ack_seq,
+ len, value);
+ return 0;
+}
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
new file mode 100644
index 0000000..8ca51c9
--- /dev/null
+++ b/net/dccp/ackvec.h
@@ -0,0 +1,133 @@
+#ifndef _ACKVEC_H
+#define _ACKVEC_H
+/*
+ * net/dccp/ackvec.h
+ *
+ * An implementation of the DCCP protocol
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@mandriva.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+/* Read about the ECN nonce to see why it is 253 */
+#define DCCP_MAX_ACKVEC_LEN 253
+
+#define DCCP_ACKVEC_STATE_RECEIVED 0
+#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6)
+#define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6)
+
+#define DCCP_ACKVEC_STATE_MASK 0xC0 /* 11000000 */
+#define DCCP_ACKVEC_LEN_MASK 0x3F /* 00111111 */
+
+/** struct dccp_ackvec - ack vector
+ *
+ * This data structure is the one defined in the DCCP draft
+ * Appendix A.
+ *
+ * @dccpav_buf_head - circular buffer head
+ * @dccpav_buf_tail - circular buffer tail
+ * @dccpav_buf_ackno - ack # of the most recent packet acknowledgeable in the
+ * buffer (i.e. %dccpav_buf_head)
+ * @dccpav_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked
+ * by the buffer with State 0
+ *
+ * Additionally, the HC-Receiver must keep some information about the
+ * Ack Vectors it has recently sent. For each packet sent carrying an
+ * Ack Vector, it remembers four variables:
+ *
+ * @dccpav_ack_seqno - the Sequence Number used for the packet
+ * (HC-Receiver seqno)
+ * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement.
+ * @dccpav_ack_ackno - the Acknowledgement Number used for the packet
+ * (HC-Sender seqno)
+ * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
+ *
+ * @dccpav_buf_len - circular buffer length
+ * @dccpav_time - the time in usecs
+ * @dccpav_buf - circular buffer of acknowledgeable packets
+ */
+struct dccp_ackvec {
+ unsigned int dccpav_buf_head;
+ unsigned int dccpav_buf_tail;
+ u64 dccpav_buf_ackno;
+ u64 dccpav_ack_seqno;
+ u64 dccpav_ack_ackno;
+ unsigned int dccpav_ack_ptr;
+ unsigned int dccpav_sent_len;
+ unsigned int dccpav_vec_len;
+ unsigned int dccpav_buf_len;
+ struct timeval dccpav_time;
+ u8 dccpav_buf_nonce;
+ u8 dccpav_ack_nonce;
+ u8 dccpav_buf[0];
+};
+
+struct sock;
+struct sk_buff;
+
+#ifdef CONFIG_IP_DCCP_ACKVEC
+extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len,
+ const unsigned int __nocast priority);
+extern void dccp_ackvec_free(struct dccp_ackvec *av);
+
+extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
+ const u64 ackno, const u8 state);
+
+extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
+ struct sock *sk, const u64 ackno);
+extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+ const u8 opt, const u8 *value, const u8 len);
+
+extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb);
+
+static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
+{
+ return av->dccpav_sent_len != av->dccpav_vec_len;
+}
+#else /* CONFIG_IP_DCCP_ACKVEC */
+static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len,
+ const unsigned int __nocast priority)
+{
+ return NULL;
+}
+
+static inline void dccp_ackvec_free(struct dccp_ackvec *av)
+{
+}
+
+static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
+ const u64 ackno, const u8 state)
+{
+ return -1;
+}
+
+static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
+ struct sock *sk, const u64 ackno)
+{
+}
+
+static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+ const u8 opt, const u8 *value, const u8 len)
+{
+ return -1;
+}
+
+static inline int dccp_insert_option_ackvec(const struct sock *sk,
+ const struct sk_buff *skb)
+{
+ return -1;
+}
+
+static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
+{
+ return 0;
+}
+#endif /* CONFIG_IP_DCCP_ACKVEC */
+#endif /* _ACKVEC_H */
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 962f1e9..21e5514 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -14,6 +14,7 @@
*/
#include <net/sock.h>
+#include <linux/compiler.h>
#include <linux/dccp.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -54,6 +55,14 @@ struct ccid {
struct tcp_info *info);
void (*ccid_hc_tx_get_info)(struct sock *sk,
struct tcp_info *info);
+ int (*ccid_hc_rx_getsockopt)(struct sock *sk,
+ const int optname, int len,
+ u32 __user *optval,
+ int __user *optlen);
+ int (*ccid_hc_tx_getsockopt)(struct sock *sk,
+ const int optname, int len,
+ u32 __user *optval,
+ int __user *optlen);
};
extern int ccid_register(struct ccid *ccid);
@@ -177,4 +186,26 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
if (ccid->ccid_hc_tx_get_info != NULL)
ccid->ccid_hc_tx_get_info(sk, info);
}
+
+static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
+ const int optname, int len,
+ u32 __user *optval, int __user *optlen)
+{
+ int rc = -ENOPROTOOPT;
+ if (ccid->ccid_hc_rx_getsockopt != NULL)
+ rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len,
+ optval, optlen);
+ return rc;
+}
+
+static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
+ const int optname, int len,
+ u32 __user *optval, int __user *optlen)
+{
+ int rc = -ENOPROTOOPT;
+ if (ccid->ccid_hc_tx_getsockopt != NULL)
+ rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len,
+ optval, optlen);
+ return rc;
+}
#endif /* _CCID_H */
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 38aa849..aa68e0a 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_rtt = hctx->ccid3hctx_rtt;
}
+static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
+ u32 __user *optval, int __user *optlen)
+{
+ const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ const void *val;
+
+ /* Listen socks doesn't have a private CCID block */
+ if (sk->sk_state == DCCP_LISTEN)
+ return -EINVAL;
+
+ switch (optname) {
+ case DCCP_SOCKOPT_CCID_RX_INFO:
+ if (len < sizeof(hcrx->ccid3hcrx_tfrc))
+ return -EINVAL;
+ len = sizeof(hcrx->ccid3hcrx_tfrc);
+ val = &hcrx->ccid3hcrx_tfrc;
+ break;
+ default:
+ return -ENOPROTOOPT;
+ }
+
+ if (put_user(len, optlen) || copy_to_user(optval, val, len))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
+ u32 __user *optval, int __user *optlen)
+{
+ const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+ const void *val;
+
+ /* Listen socks doesn't have a private CCID block */
+ if (sk->sk_state == DCCP_LISTEN)
+ return -EINVAL;
+
+ switch (optname) {
+ case DCCP_SOCKOPT_CCID_TX_INFO:
+ if (len < sizeof(hctx->ccid3hctx_tfrc))
+ return -EINVAL;
+ len = sizeof(hctx->ccid3hctx_tfrc);
+ val = &hctx->ccid3hctx_tfrc;
+ break;
+ default:
+ return -ENOPROTOOPT;
+ }
+
+ if (put_user(len, optlen) || copy_to_user(optval, val, len))
+ return -EFAULT;
+
+ return 0;
+}
+
static struct ccid ccid3 = {
.ccid_id = 3,
.ccid_name = "ccid3",
@@ -1139,6 +1193,8 @@ static struct ccid ccid3 = {
.ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv,
.ccid_hc_rx_get_info = ccid3_hc_rx_get_info,
.ccid_hc_tx_get_info = ccid3_hc_tx_get_info,
+ .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt,
+ .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt,
};
module_param(ccid3_debug, int, 0444);
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index eb24877..0bde458 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -40,6 +40,7 @@
#include <linux/list.h>
#include <linux/time.h>
#include <linux/types.h>
+#include <linux/tfrc.h>
#define TFRC_MIN_PACKET_SIZE 16
#define TFRC_STD_PACKET_SIZE 256
@@ -93,12 +94,15 @@ struct ccid3_options_received {
* @ccid3hctx_hist - Packet history
*/
struct ccid3_hc_tx_sock {
- u32 ccid3hctx_x;
- u32 ccid3hctx_x_recv;
- u32 ccid3hctx_x_calc;
+ struct tfrc_tx_info ccid3hctx_tfrc;
+#define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x
+#define ccid3hctx_x_recv ccid3hctx_tfrc.tfrctx_x_recv
+#define ccid3hctx_x_calc ccid3hctx_tfrc.tfrctx_x_calc
+#define ccid3hctx_rtt ccid3hctx_tfrc.tfrctx_rtt
+#define ccid3hctx_p ccid3hctx_tfrc.tfrctx_p
+#define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto
+#define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi
u16 ccid3hctx_s;
- u32 ccid3hctx_rtt;
- u32 ccid3hctx_p;
u8 ccid3hctx_state;
u8 ccid3hctx_last_win_count;
u8 ccid3hctx_idle;
@@ -106,19 +110,19 @@ struct ccid3_hc_tx_sock {
struct timer_list ccid3hctx_no_feedback_timer;
struct timeval ccid3hctx_t_ld;
struct timeval ccid3hctx_t_nom;
- u32 ccid3hctx_t_rto;
- u32 ccid3hctx_t_ipi;
u32 ccid3hctx_delta;
struct list_head ccid3hctx_hist;
struct ccid3_options_received ccid3hctx_options_received;
};
struct ccid3_hc_rx_sock {
+ struct tfrc_rx_info ccid3hcrx_tfrc;
+#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_last_counter:48,
ccid3hcrx_state:8,
ccid3hcrx_last_counter:4;
- u32 ccid3hcrx_rtt;
- u32 ccid3hcrx_p;
u32 ccid3hcrx_bytes_recv;
struct timeval ccid3hcrx_tstamp_last_feedback;
struct timeval ccid3hcrx_tstamp_last_ack;
@@ -127,7 +131,6 @@ struct ccid3_hc_rx_sock {
u16 ccid3hcrx_s;
u32 ccid3hcrx_pinv;
u32 ccid3hcrx_elapsed_time;
- u32 ccid3hcrx_x_recv;
};
static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 95c4630b..5871c02 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -17,6 +17,7 @@
#include <net/snmp.h>
#include <net/sock.h>
#include <net/tcp.h>
+#include "ackvec.h"
#ifdef CONFIG_IP_DCCP_DEBUG
extern int dccp_debug;
@@ -258,13 +259,12 @@ extern int dccp_v4_send_reset(struct sock *sk,
extern void dccp_send_close(struct sock *sk, const int active);
struct dccp_skb_cb {
- __u8 dccpd_type;
- __u8 dccpd_reset_code;
- __u8 dccpd_service;
- __u8 dccpd_ccval;
+ __u8 dccpd_type:4;
+ __u8 dccpd_ccval:4;
+ __u8 dccpd_reset_code;
+ __u16 dccpd_opt_len;
__u64 dccpd_seq;
__u64 dccpd_ack_seq;
- int dccpd_opt_len;
};
#define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
@@ -359,6 +359,17 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq)
(dp->dccps_gss -
dp->dccps_options.dccpo_sequence_window + 1));
}
+
+static inline int dccp_ack_pending(const struct sock *sk)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+ return dp->dccps_timestamp_echo != 0 ||
+#ifdef CONFIG_IP_DCCP_ACKVEC
+ (dp->dccps_options.dccpo_send_ack_vector &&
+ dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
+#endif
+ inet_csk_ack_scheduled(sk);
+}
extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb);
extern void dccp_insert_option_elapsed_time(struct sock *sk,
@@ -372,65 +383,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
extern struct socket *dccp_ctl_socket;
-#define DCCP_ACKPKTS_STATE_RECEIVED 0
-#define DCCP_ACKPKTS_STATE_ECN_MARKED (1 << 6)
-#define DCCP_ACKPKTS_STATE_NOT_RECEIVED (3 << 6)
-
-#define DCCP_ACKPKTS_STATE_MASK 0xC0 /* 11000000 */
-#define DCCP_ACKPKTS_LEN_MASK 0x3F /* 00111111 */
-
-/** struct dccp_ackpkts - acknowledgeable packets
- *
- * This data structure is the one defined in the DCCP draft
- * Appendix A.
- *
- * @dccpap_buf_head - circular buffer head
- * @dccpap_buf_tail - circular buffer tail
- * @dccpap_buf_ackno - ack # of the most recent packet acknowledgeable in the
- * buffer (i.e. %dccpap_buf_head)
- * @dccpap_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked
- * by the buffer with State 0
- *
- * Additionally, the HC-Receiver must keep some information about the
- * Ack Vectors it has recently sent. For each packet sent carrying an
- * Ack Vector, it remembers four variables:
- *
- * @dccpap_ack_seqno - the Sequence Number used for the packet
- * (HC-Receiver seqno)
- * @dccpap_ack_ptr - the value of buf_head at the time of acknowledgement.
- * @dccpap_ack_ackno - the Acknowledgement Number used for the packet
- * (HC-Sender seqno)
- * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
- *
- * @dccpap_buf_len - circular buffer length
- * @dccpap_time - the time in usecs
- * @dccpap_buf - circular buffer of acknowledgeable packets
- */
-struct dccp_ackpkts {
- unsigned int dccpap_buf_head;
- unsigned int dccpap_buf_tail;
- u64 dccpap_buf_ackno;
- u64 dccpap_ack_seqno;
- u64 dccpap_ack_ackno;
- unsigned int dccpap_ack_ptr;
- unsigned int dccpap_buf_vector_len;
- unsigned int dccpap_ack_vector_len;
- unsigned int dccpap_buf_len;
- struct timeval dccpap_time;
- u8 dccpap_buf_nonce;
- u8 dccpap_ack_nonce;
- u8 dccpap_buf[0];
-};
-
-extern struct dccp_ackpkts *
- dccp_ackpkts_alloc(unsigned int len,
- const unsigned int __nocast priority);
-extern void dccp_ackpkts_free(struct dccp_ackpkts *ap);
-extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
- u64 ackno, u8 state);
-extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
- struct sock *sk, u64 ackno);
-
extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
static inline suseconds_t timeval_usecs(const struct timeval *tv)
@@ -471,15 +423,4 @@ static inline void timeval_sub_usecs(struct timeval *tv,
}
}
-#ifdef CONFIG_IP_DCCP_DEBUG
-extern void dccp_ackvector_print(const u64 ackno,
- const unsigned char *vector, int len);
-extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap);
-#else
-static inline void dccp_ackvector_print(const u64 ackno,
- const unsigned char *vector,
- int len) { }
-static inline void dccp_ackpkts_print(const struct dccp_ackpkts *ap) { }
-#endif
-
#endif /* _DCCP_H */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index c60bc34..1b6b2cb 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -16,6 +16,7 @@
#include <net/sock.h>
+#include "ackvec.h"
#include "ccid.h"
#include "dccp.h"
@@ -50,7 +51,8 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
return;
}
- dccp_set_state(sk, DCCP_CLOSING);
+ if (sk->sk_state != DCCP_CLOSING)
+ dccp_set_state(sk, DCCP_CLOSING);
dccp_send_close(sk, 0);
}
@@ -59,8 +61,8 @@ static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb)
struct dccp_sock *dp = dccp_sk(sk);
if (dp->dccps_options.dccpo_send_ack_vector)
- dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk,
- DCCP_SKB_CB(skb)->dccpd_ack_seq);
+ dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,
+ DCCP_SKB_CB(skb)->dccpd_ack_seq);
}
static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
@@ -163,37 +165,11 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_event_ack_recv(sk, skb);
- /*
- * FIXME: check ECN to see if we should use
- * DCCP_ACKPKTS_STATE_ECN_MARKED
- */
- if (dp->dccps_options.dccpo_send_ack_vector) {
- struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
-
- if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
- DCCP_SKB_CB(skb)->dccpd_seq,
- DCCP_ACKPKTS_STATE_RECEIVED)) {
- LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
- "packets buffer full!\n");
- ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
- inet_csk_schedule_ack(sk);
- inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
- TCP_DELACK_MIN,
- DCCP_RTO_MAX);
- goto discard;
- }
-
- /*
- * FIXME: this activation is probably wrong, have to study more
- * TCP delack machinery and how it fits into DCCP draft, but
- * for now it kinda "works" 8)
- */
- if (!inet_csk_ack_scheduled(sk)) {
- inet_csk_schedule_ack(sk);
- inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ,
- DCCP_RTO_MAX);
- }
- }
+ if (dp->dccps_options.dccpo_send_ack_vector &&
+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKVEC_STATE_RECEIVED))
+ goto discard;
ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
@@ -383,9 +359,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
}
out_invalid_packet:
- return 1; /* dccp_v4_do_rcv will send a reset, but...
- FIXME: the reset code should be
- DCCP_RESET_CODE_PACKET_ERROR */
+ /* dccp_v4_do_rcv will send a reset */
+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
+ return 1;
}
static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
@@ -432,6 +408,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
struct dccp_hdr *dh, unsigned len)
{
struct dccp_sock *dp = dccp_sk(sk);
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
const int old_state = sk->sk_state;
int queued = 0;
@@ -472,7 +449,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
if (dh->dccph_type == DCCP_PKT_RESET)
goto discard;
- /* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/
+ /* Caller (dccp_v4_do_rcv) will send Reset */
+ dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
return 1;
}
@@ -486,36 +464,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
if (dccp_parse_options(sk, skb))
goto discard;
- if (DCCP_SKB_CB(skb)->dccpd_ack_seq !=
- DCCP_PKT_WITHOUT_ACK_SEQ)
+ if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
dccp_event_ack_recv(sk, skb);
ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
- /*
- * FIXME: check ECN to see if we should use
- * DCCP_ACKPKTS_STATE_ECN_MARKED
- */
- if (dp->dccps_options.dccpo_send_ack_vector) {
- if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
- DCCP_SKB_CB(skb)->dccpd_seq,
- DCCP_ACKPKTS_STATE_RECEIVED))
- goto discard;
- /*
- * FIXME: this activation is probably wrong, have to
- * study more TCP delack machinery and how it fits into
- * DCCP draft, but for now it kinda "works" 8)
- */
- if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno ==
- DCCP_MAX_SEQNO + 1) &&
- !inet_csk_ack_scheduled(sk)) {
- inet_csk_schedule_ack(sk);
- inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
- TCP_DELACK_MIN,
- DCCP_RTO_MAX);
- }
- }
+ if (dp->dccps_options.dccpo_send_ack_vector &&
+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKVEC_STATE_RECEIVED))
+ goto discard;
}
/*
@@ -550,8 +509,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
dh->dccph_type == DCCP_PKT_REQUEST) ||
(sk->sk_state == DCCP_RESPOND &&
dh->dccph_type == DCCP_PKT_DATA)) {
- dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
- DCCP_PKT_SYNC);
+ dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
goto discard;
} else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
dccp_rcv_closereq(sk, skb);
@@ -561,8 +519,14 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
return 0;
}
+ if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) {
+ dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK);
+ goto discard;
+ }
+
switch (sk->sk_state) {
case DCCP_CLOSED:
+ dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
return 1;
case DCCP_REQUESTING:
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 2afaa46..40fe6af 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -23,6 +23,7 @@
#include <net/tcp_states.h>
#include <net/xfrm.h>
+#include "ackvec.h"
#include "ccid.h"
#include "dccp.h"
@@ -246,6 +247,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
dp->dccps_role = DCCP_ROLE_CLIENT;
+ if (dccp_service_not_initialized(sk))
+ return -EPROTO;
+
if (addr_len < sizeof(struct sockaddr_in))
return -EINVAL;
@@ -661,6 +665,16 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
dccp_hdr(skb)->dccph_sport);
}
+static inline int dccp_bad_service_code(const struct sock *sk,
+ const __u32 service)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+
+ if (dp->dccps_service == service)
+ return 0;
+ return !dccp_list_has_service(dp->dccps_service_list, service);
+}
+
int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
struct inet_request_sock *ireq;
@@ -669,13 +683,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
struct dccp_request_sock *dreq;
const __u32 saddr = skb->nh.iph->saddr;
const __u32 daddr = skb->nh.iph->daddr;
+ const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+ __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
struct dst_entry *dst = NULL;
/* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
if (((struct rtable *)skb->dst)->rt_flags &
- (RTCF_BROADCAST | RTCF_MULTICAST))
+ (RTCF_BROADCAST | RTCF_MULTICAST)) {
+ reset_code = DCCP_RESET_CODE_NO_CONNECTION;
goto drop;
+ }
+ 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
@@ -718,9 +741,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
* dccp_create_openreq_child.
*/
dreq = dccp_rsk(req);
- dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq;
- dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
- dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service;
+ dreq->dreq_isr = dcb->dccpd_seq;
+ dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
+ dreq->dreq_service = service;
if (dccp_v4_send_response(sk, req, dst))
goto drop_and_free;
@@ -735,6 +758,7 @@ drop_and_free:
__reqsk_free(req);
drop:
DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+ dcb->dccpd_reset_code = reset_code;
return -1;
}
@@ -1005,7 +1029,6 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
return 0;
reset:
- DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
dccp_v4_ctl_send_reset(skb);
discard:
kfree_skb(skb);
@@ -1090,45 +1113,7 @@ int dccp_v4_rcv(struct sk_buff *skb)
goto discard_it;
dh = dccp_hdr(skb);
-#if 0
- /*
- * Use something like this to simulate some DATA/DATAACK loss to test
- * dccp_ackpkts_add, you'll get something like this on a session that
- * sends 10 DATA/DATAACK packets:
- *
- * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1|
- *
- * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet
- * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets
- * with the same state
- * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet
- *
- * So...
- *
- * 281473596467422 was received
- * 281473596467421 was not received
- * 281473596467420 was received
- * 281473596467419 was not received
- * 281473596467418 was received
- * 281473596467417 was not received
- * 281473596467416 was received
- * 281473596467415 was not received
- * 281473596467414 was received
- * 281473596467413 was received (this one was the 3way handshake
- * RESPONSE)
- *
- */
- if (dh->dccph_type == DCCP_PKT_DATA ||
- dh->dccph_type == DCCP_PKT_DATAACK) {
- static int discard = 0;
- if (discard) {
- discard = 0;
- goto discard_it;
- }
- discard = 1;
- }
-#endif
DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
@@ -1242,11 +1227,9 @@ static int dccp_v4_init_sock(struct sock *sk)
do_gettimeofday(&dp->dccps_epoch);
if (dp->dccps_options.dccpo_send_ack_vector) {
- dp->dccps_hc_rx_ackpkts =
- dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN,
- GFP_KERNEL);
-
- if (dp->dccps_hc_rx_ackpkts == NULL)
+ dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
+ GFP_KERNEL);
+ if (dp->dccps_hc_rx_ackvec == NULL)
return -ENOMEM;
}
@@ -1258,16 +1241,18 @@ static int dccp_v4_init_sock(struct sock *sk)
* setsockopt(CCIDs-I-want/accept). -acme
*/
if (likely(!dccp_ctl_socket_init)) {
- dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid,
+ dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
sk);
- dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid,
+ dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
sk);
if (dp->dccps_hc_rx_ccid == NULL ||
dp->dccps_hc_tx_ccid == NULL) {
ccid_exit(dp->dccps_hc_rx_ccid, sk);
ccid_exit(dp->dccps_hc_tx_ccid, sk);
- dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);
- dp->dccps_hc_rx_ackpkts = NULL;
+ if (dp->dccps_options.dccpo_send_ack_vector) {
+ dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
+ dp->dccps_hc_rx_ackvec = NULL;
+ }
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
return -ENOMEM;
}
@@ -1280,6 +1265,7 @@ static int dccp_v4_init_sock(struct sock *sk)
sk->sk_write_space = dccp_write_space;
dp->dccps_mss_cache = 536;
dp->dccps_role = DCCP_ROLE_UNDEFINED;
+ dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
return 0;
}
@@ -1301,10 +1287,17 @@ static int dccp_v4_destroy_sock(struct sock *sk)
if (inet_csk(sk)->icsk_bind_hash != NULL)
inet_put_port(&dccp_hashinfo, sk);
+ if (dp->dccps_service_list != NULL) {
+ kfree(dp->dccps_service_list);
+ dp->dccps_service_list = NULL;
+ }
+
ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
- dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);
- dp->dccps_hc_rx_ackpkts = NULL;
+ if (dp->dccps_options.dccpo_send_ack_vector) {
+ dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
+ dp->dccps_hc_rx_ackvec = NULL;
+ }
ccid_exit(dp->dccps_hc_rx_ccid, sk);
ccid_exit(dp->dccps_hc_tx_ccid, sk);
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 18461bc..1393461 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -19,6 +19,7 @@
#include <net/xfrm.h>
#include <net/inet_timewait_sock.h>
+#include "ackvec.h"
#include "ccid.h"
#include "dccp.h"
@@ -93,22 +94,24 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
struct inet_connection_sock *newicsk = inet_csk(sk);
struct dccp_sock *newdp = dccp_sk(newsk);
- newdp->dccps_hc_rx_ackpkts = NULL;
- newdp->dccps_role = DCCP_ROLE_SERVER;
- newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
+ newdp->dccps_role = DCCP_ROLE_SERVER;
+ newdp->dccps_hc_rx_ackvec = NULL;
+ newdp->dccps_service_list = NULL;
+ newdp->dccps_service = dreq->dreq_service;
+ newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
do_gettimeofday(&newdp->dccps_epoch);
if (newdp->dccps_options.dccpo_send_ack_vector) {
- newdp->dccps_hc_rx_ackpkts =
- dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN,
- GFP_ATOMIC);
+ newdp->dccps_hc_rx_ackvec =
+ dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
+ GFP_ATOMIC);
/*
* XXX: We're using the same CCIDs set on the parent,
* i.e. sk_clone copied the master sock and left the
* CCID pointers for this child, that is why we do the
* __ccid_get calls.
*/
- if (unlikely(newdp->dccps_hc_rx_ackpkts == NULL))
+ if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
goto out_free;
}
@@ -116,7 +119,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
newsk) != 0 ||
ccid_hc_tx_init(newdp->dccps_hc_tx_ccid,
newsk) != 0)) {
- dccp_ackpkts_free(newdp->dccps_hc_rx_ackpkts);
+ dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk);
ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk);
out_free:
diff --git a/net/dccp/options.c b/net/dccp/options.c
index d4c4242..0a76426 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -18,19 +18,15 @@
#include <linux/kernel.h>
#include <linux/skbuff.h>
+#include "ackvec.h"
#include "ccid.h"
#include "dccp.h"
-static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
- struct sock *sk,
- const u64 ackno,
- const unsigned char len,
- const unsigned char *vector);
-
/* stores the default values for new connection. may be changed with sysctl */
static const struct dccp_options dccpo_default_values = {
.dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW,
- .dccpo_ccid = DCCPF_INITIAL_CCID,
+ .dccpo_rx_ccid = DCCPF_INITIAL_CCID,
+ .dccpo_tx_ccid = DCCPF_INITIAL_CCID,
.dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR,
.dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT,
};
@@ -113,25 +109,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
opt_recv->dccpor_ndp);
break;
case DCCPO_ACK_VECTOR_0:
- if (len > DCCP_MAX_ACK_VECTOR_LEN)
- goto out_invalid_option;
-
+ case DCCPO_ACK_VECTOR_1:
if (pkt_type == DCCP_PKT_DATA)
continue;
- opt_recv->dccpor_ack_vector_len = len;
- opt_recv->dccpor_ack_vector_idx = value - options;
-
- dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n",
- debug_prefix, len,
- (unsigned long long)
- DCCP_SKB_CB(skb)->dccpd_ack_seq);
- dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq,
- value, len);
- dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts,
- sk,
- DCCP_SKB_CB(skb)->dccpd_ack_seq,
- len, value);
+ if (dp->dccps_options.dccpo_send_ack_vector &&
+ dccp_ackvec_parse(sk, skb, opt, value, len))
+ goto out_invalid_option;
break;
case DCCPO_TIMESTAMP:
if (len != 4)
@@ -352,86 +336,6 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
-static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
-{
- struct dccp_sock *dp = dccp_sk(sk);
-#ifdef CONFIG_IP_DCCP_DEBUG
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT TX opt: " : "server TX opt: ";
-#endif
- struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
- int len = ap->dccpap_buf_vector_len + 2;
- struct timeval now;
- u32 elapsed_time;
- unsigned char *to, *from;
-
- dccp_timestamp(sk, &now);
- elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
-
- if (elapsed_time != 0)
- dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
-
- if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
- LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to "
- "insert ACK Vector!\n");
- return;
- }
-
- /*
- * XXX: now we have just one ack vector sent record, so
- * we have to wait for it to be cleared.
- *
- * Of course this is not acceptable, but this is just for
- * basic testing now.
- */
- if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1)
- return;
-
- DCCP_SKB_CB(skb)->dccpd_opt_len += len;
-
- to = skb_push(skb, len);
- *to++ = DCCPO_ACK_VECTOR_0;
- *to++ = len;
-
- len = ap->dccpap_buf_vector_len;
- from = ap->dccpap_buf + ap->dccpap_buf_head;
-
- /* Check if buf_head wraps */
- if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) {
- const unsigned int tailsize = (ap->dccpap_buf_len -
- ap->dccpap_buf_head);
-
- memcpy(to, from, tailsize);
- to += tailsize;
- len -= tailsize;
- from = ap->dccpap_buf;
- }
-
- memcpy(to, from, len);
- /*
- * From draft-ietf-dccp-spec-11.txt:
- *
- * For each acknowledgement it sends, the HC-Receiver will add an
- * acknowledgement record. ack_seqno will equal the HC-Receiver
- * sequence number it used for the ack packet; ack_ptr will equal
- * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
- * equal buf_nonce.
- *
- * This implemention uses just one ack record for now.
- */
- ap->dccpap_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
- ap->dccpap_ack_ptr = ap->dccpap_buf_head;
- ap->dccpap_ack_ackno = ap->dccpap_buf_ackno;
- ap->dccpap_ack_nonce = ap->dccpap_buf_nonce;
- ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len;
-
- dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
- "ack_ackno=%llu\n",
- debug_prefix, ap->dccpap_ack_vector_len,
- (unsigned long long) ap->dccpap_ack_seqno,
- (unsigned long long) ap->dccpap_ack_ackno);
-}
-
void dccp_timestamp(const struct sock *sk, struct timeval *tv)
{
const struct dccp_sock *dp = dccp_sk(sk);
@@ -528,9 +432,8 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
if (!dccp_packet_without_ack(skb)) {
if (dp->dccps_options.dccpo_send_ack_vector &&
- (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
- DCCP_MAX_SEQNO + 1))
- dccp_insert_option_ack_vector(sk, skb);
+ dccp_ackvec_pending(dp->dccps_hc_rx_ackvec))
+ dccp_insert_option_ackvec(sk, skb);
if (dp->dccps_timestamp_echo != 0)
dccp_insert_option_timestamp_echo(sk, skb);
}
@@ -557,331 +460,3 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
}
}
}
-
-struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len,
- const unsigned int __nocast priority)
-{
- struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority);
-
- if (ap != NULL) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- memset(ap->dccpap_buf, 0xFF, len);
-#endif
- ap->dccpap_buf_len = len;
- ap->dccpap_buf_head =
- ap->dccpap_buf_tail =
- ap->dccpap_buf_len - 1;
- ap->dccpap_buf_ackno =
- ap->dccpap_ack_ackno =
- ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
- ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0;
- ap->dccpap_ack_ptr = 0;
- ap->dccpap_time.tv_sec = 0;
- ap->dccpap_time.tv_usec = 0;
- ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0;
- }
-
- return ap;
-}
-
-void dccp_ackpkts_free(struct dccp_ackpkts *ap)
-{
- if (ap != NULL) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len);
-#endif
- kfree(ap);
- }
-}
-
-static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap,
- const unsigned int index)
-{
- return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK;
-}
-
-static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap,
- const unsigned int index)
-{
- return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK;
-}
-
-/*
- * If several packets are missing, the HC-Receiver may prefer to enter multiple
- * bytes with run length 0, rather than a single byte with a larger run length;
- * this simplifies table updates if one of the missing packets arrives.
- */
-static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
- const unsigned int packets,
- const unsigned char state)
-{
- unsigned int gap;
- signed long new_head;
-
- if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len)
- return -ENOBUFS;
-
- gap = packets - 1;
- new_head = ap->dccpap_buf_head - packets;
-
- if (new_head < 0) {
- if (gap > 0) {
- memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED,
- gap + new_head + 1);
- gap = -new_head;
- }
- new_head += ap->dccpap_buf_len;
- }
-
- ap->dccpap_buf_head = new_head;
-
- if (gap > 0)
- memset(ap->dccpap_buf + ap->dccpap_buf_head + 1,
- DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap);
-
- ap->dccpap_buf[ap->dccpap_buf_head] = state;
- ap->dccpap_buf_vector_len += packets;
- return 0;
-}
-
-/*
- * Implements the draft-ietf-dccp-spec-11.txt Appendix A
- */
-int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
- u64 ackno, u8 state)
-{
- /*
- * Check at the right places if the buffer is full, if it is, tell the
- * caller to start dropping packets till the HC-Sender acks our ACK
- * vectors, when we will free up space in dccpap_buf.
- *
- * We may well decide to do buffer compression, etc, but for now lets
- * just drop.
- *
- * From Appendix A:
- *
- * Of course, the circular buffer may overflow, either when the
- * HC-Sender is sending data at a very high rate, when the
- * HC-Receiver's acknowledgements are not reaching the HC-Sender,
- * or when the HC-Sender is forgetting to acknowledge those acks
- * (so the HC-Receiver is unable to clean up old state). In this
- * case, the HC-Receiver should either compress the buffer (by
- * increasing run lengths when possible), transfer its state to
- * a larger buffer, or, as a last resort, drop all received
- * packets, without processing them whatsoever, until its buffer
- * shrinks again.
- */
-
- /* See if this is the first ackno being inserted */
- if (ap->dccpap_buf_vector_len == 0) {
- ap->dccpap_buf[ap->dccpap_buf_head] = state;
- ap->dccpap_buf_vector_len = 1;
- } else if (after48(ackno, ap->dccpap_buf_ackno)) {
- const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno,
- ackno);
-
- /*
- * Look if the state of this packet is the same as the
- * previous ackno and if so if we can bump the head len.
- */
- if (delta == 1 &&
- dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state &&
- (dccp_ackpkts_len(ap, ap->dccpap_buf_head) <
- DCCP_ACKPKTS_LEN_MASK))
- ap->dccpap_buf[ap->dccpap_buf_head]++;
- else if (dccp_ackpkts_set_buf_head_state(ap, delta, state))
- return -ENOBUFS;
- } else {
- /*
- * A.1.2. Old Packets
- *
- * When a packet with Sequence Number S arrives, and
- * S <= buf_ackno, the HC-Receiver will scan the table
- * for the byte corresponding to S. (Indexing structures
- * could reduce the complexity of this scan.)
- */
- u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno);
- unsigned int index = ap->dccpap_buf_head;
-
- while (1) {
- const u8 len = dccp_ackpkts_len(ap, index);
- const u8 state = dccp_ackpkts_state(ap, index);
- /*
- * valid packets not yet in dccpap_buf have a reserved
- * entry, with a len equal to 0.
- */
- if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED &&
- len == 0 && delta == 0) { /* Found our
- reserved seat! */
- dccp_pr_debug("Found %llu reserved seat!\n",
- (unsigned long long) ackno);
- ap->dccpap_buf[index] = state;
- goto out;
- }
- /* len == 0 means one packet */
- if (delta < len + 1)
- goto out_duplicate;
-
- delta -= len + 1;
- if (++index == ap->dccpap_buf_len)
- index = 0;
- }
- }
-
- ap->dccpap_buf_ackno = ackno;
- dccp_timestamp(sk, &ap->dccpap_time);
-out:
- dccp_pr_debug("");
- dccp_ackpkts_print(ap);
- return 0;
-
-out_duplicate:
- /* Duplicate packet */
- dccp_pr_debug("Received a dup or already considered lost "
- "packet: %llu\n", (unsigned long long) ackno);
- return -EILSEQ;
-}
-
-#ifdef CONFIG_IP_DCCP_DEBUG
-void dccp_ackvector_print(const u64 ackno, const unsigned char *vector,
- int len)
-{
- if (!dccp_debug)
- return;
-
- printk("ACK vector len=%d, ackno=%llu |", len,
- (unsigned long long) ackno);
-
- while (len--) {
- const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6;
- const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
-
- printk("%d,%d|", state, rl);
- ++vector;
- }
-
- printk("\n");
-}
-
-void dccp_ackpkts_print(const struct dccp_ackpkts *ap)
-{
- dccp_ackvector_print(ap->dccpap_buf_ackno,
- ap->dccpap_buf + ap->dccpap_buf_head,
- ap->dccpap_buf_vector_len);
-}
-#endif
-
-static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap)
-{
- /*
- * As we're keeping track of the ack vector size
- * (dccpap_buf_vector_len) and the sent ack vector size
- * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but
- * keep this code here as in the future we'll implement a vector of
- * ack records, as suggested in draft-ietf-dccp-spec-11.txt
- * Appendix A. -acme
- */
-#if 0
- ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1;
- if (ap->dccpap_buf_tail >= ap->dccpap_buf_len)
- ap->dccpap_buf_tail -= ap->dccpap_buf_len;
-#endif
- ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len;
-}
-
-void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk,
- u64 ackno)
-{
- /* Check if we actually sent an ACK vector */
- if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
- return;
-
- if (ackno == ap->dccpap_ack_seqno) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- struct dccp_sock *dp = dccp_sk(sk);
- const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx ack: " : "server rx ack: ";
-#endif
- dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
- "ack_ackno=%llu, ACKED!\n",
- debug_prefix, 1,
- (unsigned long long) ap->dccpap_ack_seqno,
- (unsigned long long) ap->dccpap_ack_ackno);
- dccp_ackpkts_trow_away_ack_record(ap);
- ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
- }
-}
-
-static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
- struct sock *sk, u64 ackno,
- const unsigned char len,
- const unsigned char *vector)
-{
- unsigned char i;
-
- /* Check if we actually sent an ACK vector */
- if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
- return;
- /*
- * We're in the receiver half connection, so if the received an ACK
- * vector ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're
- * not interested.
- *
- * Extra explanation with example:
- *
- * if we received an ACK vector with ackno 50, it can only be acking
- * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
- */
- /* dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno); */
- if (before48(ackno, ap->dccpap_ack_seqno)) {
- /* dccp_pr_debug_cat("yes\n"); */
- return;
- }
- /* dccp_pr_debug_cat("no\n"); */
-
- i = len;
- while (i--) {
- const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
- u64 ackno_end_rl;
-
- dccp_set_seqno(&ackno_end_rl, ackno - rl);
-
- /*
- * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl,
- * ap->dccpap_ack_seqno, ackno);
- */
- if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) {
- const u8 state = (*vector &
- DCCP_ACKPKTS_STATE_MASK) >> 6;
- /* dccp_pr_debug_cat("yes\n"); */
-
- if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) {
-#ifdef CONFIG_IP_DCCP_DEBUG
- struct dccp_sock *dp = dccp_sk(sk);
- const char *debug_prefix =
- dp->dccps_role == DCCP_ROLE_CLIENT ?
- "CLIENT rx ack: " : "server rx ack: ";
-#endif
- dccp_pr_debug("%sACK vector 0, len=%d, "
- "ack_seqno=%llu, ack_ackno=%llu, "
- "ACKED!\n",
- debug_prefix, len,
- (unsigned long long)
- ap->dccpap_ack_seqno,
- (unsigned long long)
- ap->dccpap_ack_ackno);
- dccp_ackpkts_trow_away_ack_record(ap);
- }
- /*
- * If dccpap_ack_seqno was not received, no problem
- * we'll send another ACK vector.
- */
- ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
- break;
- }
- /* dccp_pr_debug_cat("no\n"); */
-
- dccp_set_seqno(&ackno, ackno_end_rl - 1);
- ++vector;
- }
-}
diff --git a/net/dccp/output.c b/net/dccp/output.c
index ea6d0e9..4786bdc 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -16,6 +16,7 @@
#include <net/sock.h>
+#include "ackvec.h"
#include "ccid.h"
#include "dccp.h"
@@ -85,7 +86,7 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
switch (dcb->dccpd_type) {
case DCCP_PKT_REQUEST:
dccp_hdr_request(skb)->dccph_req_service =
- dcb->dccpd_service;
+ dp->dccps_service;
break;
case DCCP_PKT_RESET:
dccp_hdr_reset(skb)->dccph_reset_code =
@@ -225,7 +226,6 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo)
err = dccp_wait_for_ccid(sk, skb, timeo);
if (err == 0) {
- const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
const int len = skb->len;
@@ -236,15 +236,7 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo)
inet_csk(sk)->icsk_rto,
DCCP_RTO_MAX);
dcb->dccpd_type = DCCP_PKT_DATAACK;
- /*
- * FIXME: we really should have a
- * dccps_ack_pending or use icsk.
- */
- } else if (inet_csk_ack_scheduled(sk) ||
- dp->dccps_timestamp_echo != 0 ||
- (dp->dccps_options.dccpo_send_ack_vector &&
- ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 &&
- ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1))
+ } else if (dccp_ack_pending(sk))
dcb->dccpd_type = DCCP_PKT_DATAACK;
else
dcb->dccpd_type = DCCP_PKT_DATA;
@@ -270,6 +262,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
struct request_sock *req)
{
struct dccp_hdr *dh;
+ struct dccp_request_sock *dreq;
const int dccp_header_size = sizeof(struct dccp_hdr) +
sizeof(struct dccp_hdr_ext) +
sizeof(struct dccp_hdr_response);
@@ -285,8 +278,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
skb->dst = dst_clone(dst);
skb->csum = 0;
+ dreq = dccp_rsk(req);
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
- DCCP_SKB_CB(skb)->dccpd_seq = dccp_rsk(req)->dreq_iss;
+ DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;
dccp_insert_options(sk, skb);
skb->h.raw = skb_push(skb, dccp_header_size);
@@ -300,8 +294,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
dh->dccph_type = DCCP_PKT_RESPONSE;
dh->dccph_x = 1;
- dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss);
- dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr);
+ dccp_hdr_set_seq(dh, dreq->dreq_iss);
+ dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
+ dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr,
inet_rsk(req)->rmt_addr);
@@ -397,9 +392,6 @@ int dccp_connect(struct sock *sk)
skb_reserve(skb, MAX_DCCP_HEADER);
DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
- /* FIXME: set service to something meaningful, coming
- * from userspace*/
- DCCP_SKB_CB(skb)->dccpd_service = 0;
skb->csum = 0;
skb_set_owner_w(skb, sk);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 18a0e69..a1cfd0e 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -94,7 +94,15 @@ EXPORT_SYMBOL_GPL(dccp_state_name);
static inline int dccp_listen_start(struct sock *sk)
{
- dccp_sk(sk)->dccps_role = DCCP_ROLE_LISTEN;
+ struct dccp_sock *dp = dccp_sk(sk);
+
+ dp->dccps_role = DCCP_ROLE_LISTEN;
+ /*
+ * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE)
+ * before calling listen()
+ */
+ if (dccp_service_not_initialized(sk))
+ return -EPROTO;
return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
}
@@ -202,6 +210,42 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
return -ENOIOCTLCMD;
}
+static int dccp_setsockopt_service(struct sock *sk, const u32 service,
+ char __user *optval, int optlen)
+{
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct dccp_service_list *sl = NULL;
+
+ if (service == DCCP_SERVICE_INVALID_VALUE ||
+ optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32))
+ return -EINVAL;
+
+ if (optlen > sizeof(service)) {
+ sl = kmalloc(optlen, GFP_KERNEL);
+ if (sl == NULL)
+ return -ENOMEM;
+
+ sl->dccpsl_nr = optlen / sizeof(u32) - 1;
+ if (copy_from_user(sl->dccpsl_list,
+ optval + sizeof(service),
+ optlen - sizeof(service)) ||
+ dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) {
+ kfree(sl);
+ return -EFAULT;
+ }
+ }
+
+ lock_sock(sk);
+ dp->dccps_service = service;
+
+ if (dp->dccps_service_list != NULL)
+ kfree(dp->dccps_service_list);
+
+ dp->dccps_service_list = sl;
+ release_sock(sk);
+ return 0;
+}
+
int dccp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen)
{
@@ -218,8 +262,10 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
if (get_user(val, (int __user *)optval))
return -EFAULT;
- lock_sock(sk);
+ if (optname == DCCP_SOCKOPT_SERVICE)
+ return dccp_setsockopt_service(sk, val, optval, optlen);
+ lock_sock(sk);
dp = dccp_sk(sk);
err = 0;
@@ -236,6 +282,37 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
return err;
}
+static int dccp_getsockopt_service(struct sock *sk, int len,
+ u32 __user *optval,
+ int __user *optlen)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+ const struct dccp_service_list *sl;
+ int err = -ENOENT, slen = 0, total_len = sizeof(u32);
+
+ lock_sock(sk);
+ if (dccp_service_not_initialized(sk))
+ goto out;
+
+ if ((sl = dp->dccps_service_list) != NULL) {
+ slen = sl->dccpsl_nr * sizeof(u32);
+ total_len += slen;
+ }
+
+ err = -EINVAL;
+ if (total_len > len)
+ goto out;
+
+ err = 0;
+ if (put_user(total_len, optlen) ||
+ put_user(dp->dccps_service, optval) ||
+ (sl != NULL && copy_to_user(optval + 1, sl->dccpsl_list, slen)))
+ err = -EFAULT;
+out:
+ release_sock(sk);
+ return err;
+}
+
int dccp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -248,8 +325,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
- len = min_t(unsigned int, len, sizeof(int));
- if (len < 0)
+ if (len < sizeof(int))
return -EINVAL;
dp = dccp_sk(sk);
@@ -257,7 +333,17 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
switch (optname) {
case DCCP_SOCKOPT_PACKET_SIZE:
val = dp->dccps_packet_size;
+ len = sizeof(dp->dccps_packet_size);
break;
+ case DCCP_SOCKOPT_SERVICE:
+ return dccp_getsockopt_service(sk, len,
+ (u32 __user *)optval, optlen);
+ case 128 ... 191:
+ return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
+ len, (u32 __user *)optval, optlen);
+ case 192 ... 255:
+ return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname,
+ len, (u32 __user *)optval, optlen);
default:
return -ENOPROTOOPT;
}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 1b63b48..90ae708 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -43,7 +43,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#define VERSION "0.403"
+#define VERSION "0.404"
#include <linux/config.h>
#include <asm/uaccess.h>
@@ -224,7 +224,7 @@ static inline int tkey_mismatch(t_key a, int offset, t_key b)
Consider a node 'n' and its parent 'tp'.
If n is a leaf, every bit in its key is significant. Its presence is
- necessitaded by path compression, since during a tree traversal (when
+ necessitated by path compression, since during a tree traversal (when
searching for a leaf - unless we are doing an insertion) we will completely
ignore all skipped bits we encounter. Thus we need to verify, at the end of
a potentially successful search, that we have indeed been walking the
@@ -836,11 +836,12 @@ static void trie_init(struct trie *t)
#endif
}
-/* readside most use rcu_read_lock currently dump routines
+/* readside must use rcu_read_lock currently dump routines
via get_fa_head and dump */
-static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
+static struct leaf_info *find_leaf_info(struct leaf *l, int plen)
{
+ struct hlist_head *head = &l->list;
struct hlist_node *node;
struct leaf_info *li;
@@ -853,7 +854,7 @@ static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
static inline struct list_head * get_fa_head(struct leaf *l, int plen)
{
- struct leaf_info *li = find_leaf_info(&l->list, plen);
+ struct leaf_info *li = find_leaf_info(l, plen);
if (!li)
return NULL;
@@ -1248,7 +1249,7 @@ err:
}
-/* should be clalled with rcu_read_lock */
+/* should be called with rcu_read_lock */
static inline int check_leaf(struct trie *t, struct leaf *l,
t_key key, int *plen, const struct flowi *flp,
struct fib_result *res)
@@ -1590,7 +1591,7 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
l = fib_find_node(t, key);
- li = find_leaf_info(&l->list, plen);
+ li = find_leaf_info(l, plen);
list_del_rcu(&fa->fa_list);
@@ -1714,7 +1715,6 @@ static int fn_trie_flush(struct fib_table *tb)
t->revision++;
- rcu_read_lock();
for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
found += trie_flush_leaf(t, l);
@@ -1722,7 +1722,6 @@ static int fn_trie_flush(struct fib_table *tb)
trie_leaf_remove(t, ll->key);
ll = l;
}
- rcu_read_unlock();
if (ll && hlist_empty(&ll->list))
trie_leaf_remove(t, ll->key);
@@ -2029,7 +2028,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
iter->tnode = (struct tnode *) n;
iter->trie = t;
iter->index = 0;
- iter->depth = 0;
+ iter->depth = 1;
return n;
}
return NULL;
@@ -2274,11 +2273,12 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "<local>:\n");
else
seq_puts(seq, "<main>:\n");
- } else {
- seq_indent(seq, iter->depth-1);
- seq_printf(seq, " +-- %d.%d.%d.%d/%d\n",
- NIPQUAD(prf), tn->pos);
- }
+ }
+ 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,
+ tn->empty_children);
+
} else {
struct leaf *l = (struct leaf *) n;
int i;
@@ -2287,7 +2287,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
seq_indent(seq, iter->depth);
seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val));
for (i = 32; i >= 0; i--) {
- struct leaf_info *li = find_leaf_info(&l->list, i);
+ struct leaf_info *li = find_leaf_info(l, i);
if (li) {
struct fib_alias *fa;
list_for_each_entry_rcu(fa, &li->falh, fa_list) {
@@ -2383,7 +2383,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
return 0;
for (i=32; i>=0; i--) {
- struct leaf_info *li = find_leaf_info(&l->list, i);
+ struct leaf_info *li = find_leaf_info(l, i);
struct fib_alias *fa;
u32 mask, prefix;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 44607f4..70c44e4 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1603,7 +1603,7 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc)
}
pmc->sources = NULL;
pmc->sfmode = MCAST_EXCLUDE;
- pmc->sfcount[MCAST_EXCLUDE] = 0;
+ pmc->sfcount[MCAST_INCLUDE] = 0;
pmc->sfcount[MCAST_EXCLUDE] = 1;
}
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index e11952e..f828fa2 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -196,6 +196,7 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
if (s_addr==cp->caddr && s_port==cp->cport &&
d_port==cp->vport && d_addr==cp->vaddr &&
+ ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
protocol==cp->protocol) {
/* HIT */
atomic_inc(&cp->refcnt);
@@ -227,6 +228,40 @@ struct ip_vs_conn *ip_vs_conn_in_get
return cp;
}
+/* Get reference to connection template */
+struct ip_vs_conn *ip_vs_ct_in_get
+(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+ unsigned hash;
+ struct ip_vs_conn *cp;
+
+ hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
+
+ ct_read_lock(hash);
+
+ list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
+ if (s_addr==cp->caddr && s_port==cp->cport &&
+ d_port==cp->vport && d_addr==cp->vaddr &&
+ cp->flags & IP_VS_CONN_F_TEMPLATE &&
+ protocol==cp->protocol) {
+ /* HIT */
+ atomic_inc(&cp->refcnt);
+ goto out;
+ }
+ }
+ cp = NULL;
+
+ out:
+ ct_read_unlock(hash);
+
+ IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
+ ip_vs_proto_name(protocol),
+ NIPQUAD(s_addr), ntohs(s_port),
+ NIPQUAD(d_addr), ntohs(d_port),
+ cp?"hit":"not hit");
+
+ return cp;
+}
/*
* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
@@ -367,7 +402,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
atomic_read(&dest->refcnt));
/* Update the connection counters */
- if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+ if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
/* It is a normal connection, so increase the inactive
connection counter because it is in TCP SYNRECV
state (inactive) or other protocol inacive state */
@@ -406,7 +441,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
atomic_read(&dest->refcnt));
/* Update the connection counters */
- if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+ if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
/* It is a normal connection, so decrease the inactconns
or activeconns counter */
if (cp->flags & IP_VS_CONN_F_INACTIVE) {
@@ -467,7 +502,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
/*
* Invalidate the connection template
*/
- if (ct->cport) {
+ if (ct->vport != 65535) {
if (ip_vs_conn_unhash(ct)) {
ct->dport = 65535;
ct->vport = 65535;
@@ -776,7 +811,7 @@ void ip_vs_random_dropentry(void)
ct_write_lock_bh(hash);
list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
- if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT))
+ if (cp->flags & IP_VS_CONN_F_TEMPLATE)
/* connection template */
continue;
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 3ac7eec..981cc32 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -243,10 +243,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
if (ports[1] == svc->port) {
/* Check if a template already exists */
if (svc->port != FTPPORT)
- ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
+ ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
iph->daddr, ports[1]);
else
- ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
+ ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
iph->daddr, 0);
if (!ct || !ip_vs_check_template(ct)) {
@@ -272,14 +272,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
iph->daddr,
ports[1],
dest->addr, dest->port,
- 0,
+ IP_VS_CONN_F_TEMPLATE,
dest);
else
ct = ip_vs_conn_new(iph->protocol,
snet, 0,
iph->daddr, 0,
dest->addr, 0,
- 0,
+ IP_VS_CONN_F_TEMPLATE,
dest);
if (ct == NULL)
return NULL;
@@ -298,10 +298,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
* port zero template: <protocol,caddr,0,vaddr,0,daddr,0>
*/
if (svc->fwmark)
- ct = ip_vs_conn_in_get(IPPROTO_IP, snet, 0,
+ ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0,
htonl(svc->fwmark), 0);
else
- ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
+ ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
iph->daddr, 0);
if (!ct || !ip_vs_check_template(ct)) {
@@ -326,14 +326,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
snet, 0,
htonl(svc->fwmark), 0,
dest->addr, 0,
- 0,
+ IP_VS_CONN_F_TEMPLATE,
dest);
else
ct = ip_vs_conn_new(iph->protocol,
snet, 0,
iph->daddr, 0,
dest->addr, 0,
- 0,
+ IP_VS_CONN_F_TEMPLATE,
dest);
if (ct == NULL)
return NULL;
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 574d1f5..2e5ced3 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -297,16 +297,24 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
p = (char *)buffer + sizeof(struct ip_vs_sync_mesg);
for (i=0; i<m->nr_conns; i++) {
+ unsigned flags;
+
s = (struct ip_vs_sync_conn *)p;
- cp = ip_vs_conn_in_get(s->protocol,
- s->caddr, s->cport,
- s->vaddr, s->vport);
+ flags = ntohs(s->flags);
+ if (!(flags & IP_VS_CONN_F_TEMPLATE))
+ cp = ip_vs_conn_in_get(s->protocol,
+ s->caddr, s->cport,
+ s->vaddr, s->vport);
+ else
+ cp = ip_vs_ct_in_get(s->protocol,
+ s->caddr, s->cport,
+ s->vaddr, s->vport);
if (!cp) {
cp = ip_vs_conn_new(s->protocol,
s->caddr, s->cport,
s->vaddr, s->vport,
s->daddr, s->dport,
- ntohs(s->flags), NULL);
+ flags, NULL);
if (!cp) {
IP_VS_ERR("ip_vs_conn_new failed\n");
return;
@@ -315,11 +323,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
} else if (!cp->dest) {
/* it is an entry created by the synchronization */
cp->state = ntohs(s->state);
- cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED;
+ cp->flags = flags | IP_VS_CONN_F_HASHED;
} /* Note that we don't touch its state and flags
if it is a normal entry. */
- if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) {
+ if (flags & IP_VS_CONN_F_SEQ_MASK) {
opt = (struct ip_vs_sync_conn_options *)&s[1];
memcpy(&cp->in_seq, opt, sizeof(*opt));
p += FULL_CONN_SIZE;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 30aa8e2..3cf9b45 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -51,6 +51,14 @@ config IP_NF_CONNTRACK_EVENTS
IF unsure, say `N'.
+config IP_NF_CONNTRACK_NETLINK
+ tristate 'Connection tracking netlink interface'
+ depends on IP_NF_CONNTRACK && NETFILTER_NETLINK
+ depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+ help
+ This option enables support for a netlink-based userspace interface
+
+
config IP_NF_CT_PROTO_SCTP
tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
depends on IP_NF_CONNTRACK && EXPERIMENTAL
@@ -129,6 +137,22 @@ config IP_NF_AMANDA
To compile it as a module, choose M here. If unsure, say Y.
+config IP_NF_PPTP
+ tristate 'PPTP protocol support'
+ help
+ This module adds support for PPTP (Point to Point Tunnelling
+ Protocol, RFC2637) conncection tracking and NAT.
+
+ If you are running PPTP sessions over a stateful firewall or NAT
+ box, you may want to enable this feature.
+
+ Please note that not all PPTP modes of operation are supported yet.
+ For more info, read top of the file
+ net/ipv4/netfilter/ip_conntrack_pptp.c
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
config IP_NF_QUEUE
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
help
@@ -613,6 +637,12 @@ config IP_NF_NAT_AMANDA
default IP_NF_NAT if IP_NF_AMANDA=y
default m if IP_NF_AMANDA=m
+config IP_NF_NAT_PPTP
+ tristate
+ depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
+ default IP_NF_NAT if IP_NF_PPTP=y
+ default m if IP_NF_PPTP=m
+
# mangle + specific targets
config IP_NF_MANGLE
tristate "Packet mangling"
@@ -774,11 +804,5 @@ config IP_NF_ARP_MANGLE
Allows altering the ARP packet payload: source and destination
hardware and network addresses.
-config IP_NF_CONNTRACK_NETLINK
- tristate 'Connection tracking netlink interface'
- depends on IP_NF_CONNTRACK && NETFILTER_NETLINK
- help
- This option enables support for a netlink-based userspace interface
-
endmenu
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 1ba0db7..3d45d3c 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -6,6 +6,9 @@
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
iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o 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
+ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
+ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
+
# connection tracking
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
@@ -17,6 +20,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
# connection tracking helpers
+obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
@@ -24,6 +28,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
# NAT helpers
+obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 19cba16..c1f82e0 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
/* Just find a expectation corresponding to a tuple. */
struct ip_conntrack_expect *
-ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
+ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
{
struct ip_conntrack_expect *i;
@@ -1143,7 +1143,10 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct,
if (del_timer(&ct->timeout)) {
ct->timeout.expires = jiffies + extra_jiffies;
add_timer(&ct->timeout);
- ip_conntrack_event_cache(IPCT_REFRESH, skb);
+ /* FIXME: We loose some REFRESH events if this function
+ * is called without an skb. I'll fix this later -HW */
+ if (skb)
+ ip_conntrack_event_cache(IPCT_REFRESH, skb);
}
ct_add_counters(ct, ctinfo, skb);
write_unlock_bh(&ip_conntrack_lock);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 1b79ec3..d77d6b3f 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -29,9 +29,9 @@ static char *ftp_buffer;
static DEFINE_SPINLOCK(ip_ftp_lock);
#define MAX_PORTS 8
-static int ports[MAX_PORTS];
+static short ports[MAX_PORTS];
static int ports_c;
-module_param_array(ports, int, &ports_c, 0400);
+module_param_array(ports, short, &ports_c, 0400);
static int loose;
module_param(loose, int, 0600);
@@ -450,7 +450,7 @@ out_update_nl:
}
static struct ip_conntrack_helper ftp[MAX_PORTS];
-static char ftp_names[MAX_PORTS][10];
+static char ftp_names[MAX_PORTS][sizeof("ftp-65535")];
/* Not __exit: called from init() */
static void fini(void)
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
new file mode 100644
index 0000000..79db5b7
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -0,0 +1,805 @@
+/*
+ * ip_conntrack_pptp.c - Version 3.0
+ *
+ * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft. PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * Limitations:
+ * - We blindly assume that control connections are always
+ * established in PNS->PAC direction. This is a violation
+ * of RFFC2673
+ * - We can only support one single call within each session
+ *
+ * TODO:
+ * - testing of incoming PPTP calls
+ *
+ * Changes:
+ * 2002-02-05 - Version 1.3
+ * - Call ip_conntrack_unexpect_related() from
+ * pptp_destroy_siblings() to destroy expectations in case
+ * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
+ * (Philip Craig <philipc@snapgear.com>)
+ * - Add Version information at module loadtime
+ * 2002-02-10 - Version 1.6
+ * - move to C99 style initializers
+ * - remove second expectation if first arrives
+ * 2004-10-22 - Version 2.0
+ * - merge Mandrake's 2.6.x port with recent 2.6.x API changes
+ * - fix lots of linear skb assumptions from Mandrake's port
+ * 2005-06-10 - Version 2.1
+ * - use ip_conntrack_expect_free() instead of kfree() on the
+ * expect's (which are from the slab for quite some time)
+ * 2005-06-10 - Version 3.0
+ * - port helper to post-2.6.11 API changes,
+ * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
+ * 2005-07-30 - Version 3.1
+ * - port helper to 2.6.13 API changes
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+#define IP_CT_PPTP_VERSION "3.1"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
+
+static DEFINE_SPINLOCK(ip_pptp_lock);
+
+int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
+ struct ip_conntrack_expect *expect_reply);
+
+void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+ struct ip_conntrack_expect *exp);
+
+#if 0
+/* PptpControlMessageType names */
+const char *pptp_msg_name[] = {
+ "UNKNOWN_MESSAGE",
+ "START_SESSION_REQUEST",
+ "START_SESSION_REPLY",
+ "STOP_SESSION_REQUEST",
+ "STOP_SESSION_REPLY",
+ "ECHO_REQUEST",
+ "ECHO_REPLY",
+ "OUT_CALL_REQUEST",
+ "OUT_CALL_REPLY",
+ "IN_CALL_REQUEST",
+ "IN_CALL_REPLY",
+ "IN_CALL_CONNECT",
+ "CALL_CLEAR_REQUEST",
+ "CALL_DISCONNECT_NOTIFY",
+ "WAN_ERROR_NOTIFY",
+ "SET_LINK_INFO"
+};
+EXPORT_SYMBOL(pptp_msg_name);
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define SECS *HZ
+#define MINS * 60 SECS
+#define HOURS * 60 MINS
+
+#define PPTP_GRE_TIMEOUT (10 MINS)
+#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS)
+
+static void pptp_expectfn(struct ip_conntrack *ct,
+ struct ip_conntrack_expect *exp)
+{
+ DEBUGP("increasing timeouts\n");
+
+ /* increase timeout of GRE data channel conntrack entry */
+ ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
+ ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
+
+ /* Can you see how rusty this code is, compared with the pre-2.6.11
+ * one? That's what happened to my shiny newnat of 2002 ;( -HW */
+
+ if (!ip_nat_pptp_hook_expectfn) {
+ struct ip_conntrack_tuple inv_t;
+ struct ip_conntrack_expect *exp_other;
+
+ /* obviously this tuple inversion only works until you do NAT */
+ invert_tuplepr(&inv_t, &exp->tuple);
+ DEBUGP("trying to unexpect other dir: ");
+ DUMP_TUPLE(&inv_t);
+
+ exp_other = ip_conntrack_expect_find(&inv_t);
+ if (exp_other) {
+ /* delete other expectation. */
+ DEBUGP("found\n");
+ ip_conntrack_unexpect_related(exp_other);
+ ip_conntrack_expect_put(exp_other);
+ } else {
+ DEBUGP("not found\n");
+ }
+ } else {
+ /* we need more than simple inversion */
+ ip_nat_pptp_hook_expectfn(ct, exp);
+ }
+}
+
+static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
+{
+ struct ip_conntrack_tuple_hash *h;
+ struct ip_conntrack_expect *exp;
+
+ DEBUGP("trying to timeout ct or exp for tuple ");
+ DUMP_TUPLE(t);
+
+ h = ip_conntrack_find_get(t, NULL);
+ if (h) {
+ struct ip_conntrack *sibling = tuplehash_to_ctrack(h);
+ DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+ sibling->proto.gre.timeout = 0;
+ sibling->proto.gre.stream_timeout = 0;
+ /* refresh_acct will not modify counters if skb == NULL */
+ if (del_timer(&sibling->timeout))
+ sibling->timeout.function((unsigned long)sibling);
+ ip_conntrack_put(sibling);
+ return 1;
+ } else {
+ exp = ip_conntrack_expect_find(t);
+ if (exp) {
+ DEBUGP("unexpect_related of expect %p\n", exp);
+ ip_conntrack_unexpect_related(exp);
+ ip_conntrack_expect_put(exp);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/* timeout GRE data connections */
+static void pptp_destroy_siblings(struct ip_conntrack *ct)
+{
+ struct ip_conntrack_tuple t;
+
+ /* Since ct->sibling_list has literally rusted away in 2.6.11,
+ * we now need another way to find out about our sibling
+ * contrack and expects... -HW */
+
+ /* try original (pns->pac) tuple */
+ memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
+ t.dst.protonum = IPPROTO_GRE;
+ t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+ t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+
+ if (!destroy_sibling_or_exp(&t))
+ DEBUGP("failed to timeout original pns->pac ct/exp\n");
+
+ /* try reply (pac->pns) tuple */
+ memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
+ t.dst.protonum = IPPROTO_GRE;
+ t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+ t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+
+ if (!destroy_sibling_or_exp(&t))
+ DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+}
+
+/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
+static inline int
+exp_gre(struct ip_conntrack *master,
+ u_int32_t seq,
+ u_int16_t callid,
+ u_int16_t peer_callid)
+{
+ struct ip_conntrack_tuple inv_tuple;
+ struct ip_conntrack_tuple exp_tuples[] = {
+ /* tuple in original direction, PNS->PAC */
+ { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
+ .u = { .gre = { .key = peer_callid } }
+ },
+ .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
+ .u = { .gre = { .key = callid } },
+ .protonum = IPPROTO_GRE
+ },
+ },
+ /* tuple in reply direction, PAC->PNS */
+ { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
+ .u = { .gre = { .key = callid } }
+ },
+ .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
+ .u = { .gre = { .key = peer_callid } },
+ .protonum = IPPROTO_GRE
+ },
+ }
+ };
+ struct ip_conntrack_expect *exp_orig, *exp_reply;
+ int ret = 1;
+
+ exp_orig = ip_conntrack_expect_alloc(master);
+ if (exp_orig == NULL)
+ goto out;
+
+ exp_reply = ip_conntrack_expect_alloc(master);
+ if (exp_reply == NULL)
+ goto out_put_orig;
+
+ memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple));
+
+ exp_orig->mask.src.ip = 0xffffffff;
+ exp_orig->mask.src.u.all = 0;
+ exp_orig->mask.dst.u.all = 0;
+ exp_orig->mask.dst.u.gre.key = 0xffff;
+ exp_orig->mask.dst.ip = 0xffffffff;
+ exp_orig->mask.dst.protonum = 0xff;
+
+ exp_orig->master = master;
+ exp_orig->expectfn = pptp_expectfn;
+ exp_orig->flags = 0;
+
+ exp_orig->dir = IP_CT_DIR_ORIGINAL;
+
+ /* both expectations are identical apart from tuple */
+ memcpy(exp_reply, exp_orig, sizeof(*exp_reply));
+ memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple));
+
+ exp_reply->dir = !exp_orig->dir;
+
+ if (ip_nat_pptp_hook_exp_gre)
+ ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+ else {
+
+ DEBUGP("calling expect_related PNS->PAC");
+ DUMP_TUPLE(&exp_orig->tuple);
+
+ if (ip_conntrack_expect_related(exp_orig) != 0) {
+ DEBUGP("cannot expect_related()\n");
+ goto out_put_both;
+ }
+
+ DEBUGP("calling expect_related PAC->PNS");
+ DUMP_TUPLE(&exp_reply->tuple);
+
+ if (ip_conntrack_expect_related(exp_reply) != 0) {
+ DEBUGP("cannot expect_related()\n");
+ goto out_unexpect_orig;
+ }
+
+ /* Add GRE keymap entries */
+ if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) {
+ DEBUGP("cannot keymap_add() exp\n");
+ goto out_unexpect_both;
+ }
+
+ invert_tuplepr(&inv_tuple, &exp_reply->tuple);
+ if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) {
+ ip_ct_gre_keymap_destroy(master);
+ DEBUGP("cannot keymap_add() exp_inv\n");
+ goto out_unexpect_both;
+ }
+ ret = 0;
+ }
+
+out_put_both:
+ ip_conntrack_expect_put(exp_reply);
+out_put_orig:
+ ip_conntrack_expect_put(exp_orig);
+out:
+ return ret;
+
+out_unexpect_both:
+ ip_conntrack_unexpect_related(exp_reply);
+out_unexpect_orig:
+ ip_conntrack_unexpect_related(exp_orig);
+ goto out_put_both;
+}
+
+static inline int
+pptp_inbound_pkt(struct sk_buff **pskb,
+ struct tcphdr *tcph,
+ unsigned int nexthdr_off,
+ unsigned int datalen,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct PptpControlHeader _ctlh, *ctlh;
+ unsigned int reqlen;
+ union pptp_ctrl_union _pptpReq, *pptpReq;
+ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+ u_int16_t msg, *cid, *pcid;
+ u_int32_t seq;
+
+ ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+ if (!ctlh) {
+ DEBUGP("error during skb_header_pointer\n");
+ return NF_ACCEPT;
+ }
+ nexthdr_off += sizeof(_ctlh);
+ datalen -= sizeof(_ctlh);
+
+ reqlen = datalen;
+ if (reqlen > sizeof(*pptpReq))
+ reqlen = sizeof(*pptpReq);
+ pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+ if (!pptpReq) {
+ DEBUGP("error during skb_header_pointer\n");
+ return NF_ACCEPT;
+ }
+
+ msg = ntohs(ctlh->messageType);
+ DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+
+ switch (msg) {
+ case PPTP_START_SESSION_REPLY:
+ if (reqlen < sizeof(_pptpReq.srep)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* server confirms new control session */
+ if (info->sstate < PPTP_SESSION_REQUESTED) {
+ DEBUGP("%s without START_SESS_REQUEST\n",
+ pptp_msg_name[msg]);
+ break;
+ }
+ if (pptpReq->srep.resultCode == PPTP_START_OK)
+ info->sstate = PPTP_SESSION_CONFIRMED;
+ else
+ info->sstate = PPTP_SESSION_ERROR;
+ break;
+
+ case PPTP_STOP_SESSION_REPLY:
+ if (reqlen < sizeof(_pptpReq.strep)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* server confirms end of control session */
+ if (info->sstate > PPTP_SESSION_STOPREQ) {
+ DEBUGP("%s without STOP_SESS_REQUEST\n",
+ pptp_msg_name[msg]);
+ break;
+ }
+ if (pptpReq->strep.resultCode == PPTP_STOP_OK)
+ info->sstate = PPTP_SESSION_NONE;
+ else
+ info->sstate = PPTP_SESSION_ERROR;
+ break;
+
+ case PPTP_OUT_CALL_REPLY:
+ if (reqlen < sizeof(_pptpReq.ocack)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* server accepted call, we now expect GRE frames */
+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
+ DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+ break;
+ }
+ if (info->cstate != PPTP_CALL_OUT_REQ &&
+ info->cstate != PPTP_CALL_OUT_CONF) {
+ DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]);
+ break;
+ }
+ if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) {
+ info->cstate = PPTP_CALL_NONE;
+ break;
+ }
+
+ cid = &pptpReq->ocack.callID;
+ pcid = &pptpReq->ocack.peersCallID;
+
+ info->pac_call_id = ntohs(*cid);
+
+ if (htons(info->pns_call_id) != *pcid) {
+ DEBUGP("%s for unknown callid %u\n",
+ pptp_msg_name[msg], ntohs(*pcid));
+ break;
+ }
+
+ DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
+ ntohs(*cid), ntohs(*pcid));
+
+ info->cstate = PPTP_CALL_OUT_CONF;
+
+ seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+ + sizeof(struct PptpControlHeader)
+ + ((void *)pcid - (void *)pptpReq);
+
+ if (exp_gre(ct, seq, *cid, *pcid) != 0)
+ printk("ip_conntrack_pptp: error during exp_gre\n");
+ break;
+
+ case PPTP_IN_CALL_REQUEST:
+ if (reqlen < sizeof(_pptpReq.icack)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* server tells us about incoming call request */
+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
+ DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+ break;
+ }
+ pcid = &pptpReq->icack.peersCallID;
+ DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+ info->cstate = PPTP_CALL_IN_REQ;
+ info->pac_call_id = ntohs(*pcid);
+ break;
+
+ case PPTP_IN_CALL_CONNECT:
+ if (reqlen < sizeof(_pptpReq.iccon)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* server tells us about incoming call established */
+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
+ DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+ break;
+ }
+ if (info->sstate != PPTP_CALL_IN_REP
+ && info->sstate != PPTP_CALL_IN_CONF) {
+ DEBUGP("%s but never sent IN_CALL_REPLY\n",
+ pptp_msg_name[msg]);
+ break;
+ }
+
+ pcid = &pptpReq->iccon.peersCallID;
+ cid = &info->pac_call_id;
+
+ if (info->pns_call_id != ntohs(*pcid)) {
+ DEBUGP("%s for unknown CallID %u\n",
+ pptp_msg_name[msg], ntohs(*cid));
+ break;
+ }
+
+ DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+ info->cstate = PPTP_CALL_IN_CONF;
+
+ /* we expect a GRE connection from PAC to PNS */
+ seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+ + sizeof(struct PptpControlHeader)
+ + ((void *)pcid - (void *)pptpReq);
+
+ if (exp_gre(ct, seq, *cid, *pcid) != 0)
+ printk("ip_conntrack_pptp: error during exp_gre\n");
+
+ break;
+
+ case PPTP_CALL_DISCONNECT_NOTIFY:
+ if (reqlen < sizeof(_pptpReq.disc)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* server confirms disconnect */
+ cid = &pptpReq->disc.callID;
+ DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
+ info->cstate = PPTP_CALL_NONE;
+
+ /* untrack this call id, unexpect GRE packets */
+ pptp_destroy_siblings(ct);
+ break;
+
+ case PPTP_WAN_ERROR_NOTIFY:
+ break;
+
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* I don't have to explain these ;) */
+ break;
+ default:
+ DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
+ ? pptp_msg_name[msg]:pptp_msg_name[0], msg);
+ break;
+ }
+
+
+ if (ip_nat_pptp_hook_inbound)
+ return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
+ pptpReq);
+
+ return NF_ACCEPT;
+
+}
+
+static inline int
+pptp_outbound_pkt(struct sk_buff **pskb,
+ struct tcphdr *tcph,
+ unsigned int nexthdr_off,
+ unsigned int datalen,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo)
+{
+ struct PptpControlHeader _ctlh, *ctlh;
+ unsigned int reqlen;
+ union pptp_ctrl_union _pptpReq, *pptpReq;
+ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+ u_int16_t msg, *cid, *pcid;
+
+ ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+ if (!ctlh)
+ return NF_ACCEPT;
+ nexthdr_off += sizeof(_ctlh);
+ datalen -= sizeof(_ctlh);
+
+ reqlen = datalen;
+ if (reqlen > sizeof(*pptpReq))
+ reqlen = sizeof(*pptpReq);
+ pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+ if (!pptpReq)
+ return NF_ACCEPT;
+
+ msg = ntohs(ctlh->messageType);
+ DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+
+ switch (msg) {
+ case PPTP_START_SESSION_REQUEST:
+ /* client requests for new control session */
+ if (info->sstate != PPTP_SESSION_NONE) {
+ DEBUGP("%s but we already have one",
+ pptp_msg_name[msg]);
+ }
+ info->sstate = PPTP_SESSION_REQUESTED;
+ break;
+ case PPTP_STOP_SESSION_REQUEST:
+ /* client requests end of control session */
+ info->sstate = PPTP_SESSION_STOPREQ;
+ break;
+
+ case PPTP_OUT_CALL_REQUEST:
+ if (reqlen < sizeof(_pptpReq.ocreq)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ /* FIXME: break; */
+ }
+
+ /* client initiating connection to server */
+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
+ DEBUGP("%s but no session\n",
+ pptp_msg_name[msg]);
+ break;
+ }
+ info->cstate = PPTP_CALL_OUT_REQ;
+ /* track PNS call id */
+ cid = &pptpReq->ocreq.callID;
+ DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
+ info->pns_call_id = ntohs(*cid);
+ break;
+ case PPTP_IN_CALL_REPLY:
+ if (reqlen < sizeof(_pptpReq.icack)) {
+ DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+ break;
+ }
+
+ /* client answers incoming call */
+ if (info->cstate != PPTP_CALL_IN_REQ
+ && info->cstate != PPTP_CALL_IN_REP) {
+ DEBUGP("%s without incall_req\n",
+ pptp_msg_name[msg]);
+ break;
+ }
+ if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) {
+ info->cstate = PPTP_CALL_NONE;
+ break;
+ }
+ pcid = &pptpReq->icack.peersCallID;
+ if (info->pac_call_id != ntohs(*pcid)) {
+ DEBUGP("%s for unknown call %u\n",
+ pptp_msg_name[msg], ntohs(*pcid));
+ break;
+ }
+ DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+ /* part two of the three-way handshake */
+ info->cstate = PPTP_CALL_IN_REP;
+ info->pns_call_id = ntohs(pptpReq->icack.callID);
+ break;
+
+ case PPTP_CALL_CLEAR_REQUEST:
+ /* client requests hangup of call */
+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
+ DEBUGP("CLEAR_CALL but no session\n");
+ break;
+ }
+ /* FUTURE: iterate over all calls and check if
+ * call ID is valid. We don't do this without newnat,
+ * because we only know about last call */
+ info->cstate = PPTP_CALL_CLEAR_REQ;
+ break;
+ case PPTP_SET_LINK_INFO:
+ break;
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* I don't have to explain these ;) */
+ break;
+ default:
+ DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?
+ pptp_msg_name[msg]:pptp_msg_name[0], msg);
+ /* unknown: no need to create GRE masq table entry */
+ break;
+ }
+
+ if (ip_nat_pptp_hook_outbound)
+ return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
+ pptpReq);
+
+ return NF_ACCEPT;
+}
+
+
+/* track caller id inside control connection, call expect_related */
+static int
+conntrack_pptp_help(struct sk_buff **pskb,
+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+
+{
+ struct pptp_pkt_hdr _pptph, *pptph;
+ struct tcphdr _tcph, *tcph;
+ u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
+ u_int32_t datalen;
+ int dir = CTINFO2DIR(ctinfo);
+ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+ unsigned int nexthdr_off;
+
+ int oldsstate, oldcstate;
+ int ret;
+
+ /* don't do any tracking before tcp handshake complete */
+ if (ctinfo != IP_CT_ESTABLISHED
+ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
+ DEBUGP("ctinfo = %u, skipping\n", ctinfo);
+ return NF_ACCEPT;
+ }
+
+ nexthdr_off = (*pskb)->nh.iph->ihl*4;
+ tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
+ BUG_ON(!tcph);
+ nexthdr_off += tcph->doff * 4;
+ datalen = tcplen - tcph->doff * 4;
+
+ if (tcph->fin || tcph->rst) {
+ DEBUGP("RST/FIN received, timeouting GRE\n");
+ /* can't do this after real newnat */
+ info->cstate = PPTP_CALL_NONE;
+
+ /* untrack this call id, unexpect GRE packets */
+ pptp_destroy_siblings(ct);
+ }
+
+ pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
+ if (!pptph) {
+ DEBUGP("no full PPTP header, can't track\n");
+ return NF_ACCEPT;
+ }
+ nexthdr_off += sizeof(_pptph);
+ datalen -= sizeof(_pptph);
+
+ /* if it's not a control message we can't do anything with it */
+ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
+ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
+ DEBUGP("not a control packet\n");
+ return NF_ACCEPT;
+ }
+
+ oldsstate = info->sstate;
+ oldcstate = info->cstate;
+
+ spin_lock_bh(&ip_pptp_lock);
+
+ /* FIXME: We just blindly assume that the control connection is always
+ * established from PNS->PAC. However, RFC makes no guarantee */
+ if (dir == IP_CT_DIR_ORIGINAL)
+ /* client -> server (PNS -> PAC) */
+ ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+ ctinfo);
+ else
+ /* server -> client (PAC -> PNS) */
+ ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+ ctinfo);
+ DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
+ oldsstate, info->sstate, oldcstate, info->cstate);
+ spin_unlock_bh(&ip_pptp_lock);
+
+ return ret;
+}
+
+/* control protocol helper */
+static struct ip_conntrack_helper pptp = {
+ .list = { NULL, NULL },
+ .name = "pptp",
+ .me = THIS_MODULE,
+ .max_expected = 2,
+ .timeout = 5 * 60,
+ .tuple = { .src = { .ip = 0,
+ .u = { .tcp = { .port =
+ __constant_htons(PPTP_CONTROL_PORT) } }
+ },
+ .dst = { .ip = 0,
+ .u = { .all = 0 },
+ .protonum = IPPROTO_TCP
+ }
+ },
+ .mask = { .src = { .ip = 0,
+ .u = { .tcp = { .port = 0xffff } }
+ },
+ .dst = { .ip = 0,
+ .u = { .all = 0 },
+ .protonum = 0xff
+ }
+ },
+ .help = conntrack_pptp_help
+};
+
+extern void __exit ip_ct_proto_gre_fini(void);
+extern int __init ip_ct_proto_gre_init(void);
+
+/* ip_conntrack_pptp initialization */
+static int __init init(void)
+{
+ int retcode;
+
+ retcode = ip_ct_proto_gre_init();
+ if (retcode < 0)
+ return retcode;
+
+ DEBUGP(" registering helper\n");
+ if ((retcode = ip_conntrack_helper_register(&pptp))) {
+ printk(KERN_ERR "Unable to register conntrack application "
+ "helper for pptp: %d\n", retcode);
+ ip_ct_proto_gre_fini();
+ return retcode;
+ }
+
+ printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ ip_conntrack_helper_unregister(&pptp);
+ ip_ct_proto_gre_fini();
+ printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
+
+EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);
+EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index d7a8a98..1545741 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -34,7 +34,7 @@
#include <linux/moduleparam.h>
#define MAX_PORTS 8
-static int ports[MAX_PORTS];
+static short ports[MAX_PORTS];
static int ports_c;
static int max_dcc_channels = 8;
static unsigned int dcc_timeout = 300;
@@ -52,7 +52,7 @@ EXPORT_SYMBOL_GPL(ip_nat_irc_hook);
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
MODULE_LICENSE("GPL");
-module_param_array(ports, int, &ports_c, 0400);
+module_param_array(ports, short, &ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of IRC servers");
module_param(max_dcc_channels, int, 0400);
MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
@@ -240,7 +240,7 @@ static int help(struct sk_buff **pskb,
}
static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
-static char irc_names[MAX_PORTS][10];
+static char irc_names[MAX_PORTS][sizeof("irc-65535")];
static void fini(void);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index bb72466..71ef19d 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -23,7 +23,6 @@
#include <linux/inetdevice.h>
#include <linux/in.h>
#include <linux/ip.h>
-#include <linux/udp.h>
#include <net/route.h>
#include <linux/netfilter.h>
@@ -31,6 +30,8 @@
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#define NMBD_PORT 137
+
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
MODULE_LICENSE("GPL");
@@ -44,7 +45,6 @@ static int help(struct sk_buff **pskb,
{
struct ip_conntrack_expect *exp;
struct iphdr *iph = (*pskb)->nh.iph;
- struct udphdr _uh, *uh;
struct rtable *rt = (struct rtable *)(*pskb)->dst;
struct in_device *in_dev;
u_int32_t mask = 0;
@@ -72,20 +72,15 @@ static int help(struct sk_buff **pskb,
if (mask == 0)
goto out;
- uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh);
- BUG_ON(uh == NULL);
-
exp = ip_conntrack_expect_alloc(ct);
if (exp == NULL)
goto out;
- memset(&exp->tuple, 0, sizeof(exp->tuple));
- exp->tuple.src.ip = iph->daddr & mask;
- exp->tuple.dst.ip = iph->saddr;
- exp->tuple.dst.u.udp.port = uh->source;
- exp->tuple.dst.protonum = IPPROTO_UDP;
- memset(&exp->mask, 0, sizeof(exp->mask));
+ exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ exp->tuple.src.u.udp.port = ntohs(NMBD_PORT);
+
exp->mask.src.ip = mask;
+ exp->mask.src.u.udp.port = 0xFFFF;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.udp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
@@ -107,7 +102,7 @@ static struct ip_conntrack_helper helper = {
.src = {
.u = {
.udp = {
- .port = __constant_htons(137),
+ .port = __constant_htons(NMBD_PORT),
}
}
},
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 15aef35..b08a432 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1270,7 +1270,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- exp = ip_conntrack_expect_find_get(&tuple);
+ exp = ip_conntrack_expect_find(&tuple);
if (!exp)
return -ENOENT;
@@ -1318,7 +1318,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
/* bump usage count to 2 */
- exp = ip_conntrack_expect_find_get(&tuple);
+ exp = ip_conntrack_expect_find(&tuple);
if (!exp)
return -ENOENT;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
new file mode 100644
index 0000000..de3cb9d
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -0,0 +1,327 @@
+/*
+ * ip_conntrack_proto_gre.c - Version 3.0
+ *
+ * Connection tracking protocol helper module for GRE.
+ *
+ * GRE is a generic encapsulation protocol, which is generally not very
+ * suited for NAT, as it has no protocol-specific part as port numbers.
+ *
+ * It has an optional key field, which may help us distinguishing two
+ * connections between the same two hosts.
+ *
+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
+ *
+ * PPTP is built on top of a modified version of GRE, and has a mandatory
+ * field called "CallID", which serves us for the same purpose as the key
+ * field in plain GRE.
+ *
+ * Documentation about PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/list.h>
+
+static DEFINE_RWLOCK(ip_ct_gre_lock);
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
+
+#include <linux/netfilter_ipv4/listhelp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
+
+/* shamelessly stolen from ip_conntrack_proto_udp.c */
+#define GRE_TIMEOUT (30*HZ)
+#define GRE_STREAM_TIMEOUT (180*HZ)
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \
+ NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \
+ NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key))
+#else
+#define DEBUGP(x, args...)
+#define DUMP_TUPLE_GRE(x)
+#endif
+
+/* GRE KEYMAP HANDLING FUNCTIONS */
+static LIST_HEAD(gre_keymap_list);
+
+static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
+ const struct ip_conntrack_tuple *t)
+{
+ return ((km->tuple.src.ip == t->src.ip) &&
+ (km->tuple.dst.ip == t->dst.ip) &&
+ (km->tuple.dst.protonum == t->dst.protonum) &&
+ (km->tuple.dst.u.all == t->dst.u.all));
+}
+
+/* look up the source key for a given tuple */
+static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
+{
+ struct ip_ct_gre_keymap *km;
+ u_int32_t key = 0;
+
+ read_lock_bh(&ip_ct_gre_lock);
+ km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
+ struct ip_ct_gre_keymap *, t);
+ if (km)
+ key = km->tuple.src.u.gre.key;
+ read_unlock_bh(&ip_ct_gre_lock);
+
+ DEBUGP("lookup src key 0x%x up key for ", key);
+ DUMP_TUPLE_GRE(t);
+
+ return key;
+}
+
+/* add a single keymap entry, associate with specified master ct */
+int
+ip_ct_gre_keymap_add(struct ip_conntrack *ct,
+ struct ip_conntrack_tuple *t, int reply)
+{
+ struct ip_ct_gre_keymap **exist_km, *km, *old;
+
+ if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
+ DEBUGP("refusing to add GRE keymap to non-pptp session\n");
+ return -1;
+ }
+
+ if (!reply)
+ exist_km = &ct->help.ct_pptp_info.keymap_orig;
+ else
+ exist_km = &ct->help.ct_pptp_info.keymap_reply;
+
+ if (*exist_km) {
+ /* check whether it's a retransmission */
+ old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
+ struct ip_ct_gre_keymap *, t);
+ if (old == *exist_km) {
+ DEBUGP("retransmission\n");
+ return 0;
+ }
+
+ DEBUGP("trying to override keymap_%s for ct %p\n",
+ reply? "reply":"orig", ct);
+ return -EEXIST;
+ }
+
+ km = kmalloc(sizeof(*km), GFP_ATOMIC);
+ if (!km)
+ return -ENOMEM;
+
+ memcpy(&km->tuple, t, sizeof(*t));
+ *exist_km = km;
+
+ DEBUGP("adding new entry %p: ", km);
+ DUMP_TUPLE_GRE(&km->tuple);
+
+ write_lock_bh(&ip_ct_gre_lock);
+ list_append(&gre_keymap_list, km);
+ write_unlock_bh(&ip_ct_gre_lock);
+
+ return 0;
+}
+
+/* destroy the keymap entries associated with specified master ct */
+void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct)
+{
+ DEBUGP("entering for ct %p\n", ct);
+
+ if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
+ DEBUGP("refusing to destroy GRE keymap to non-pptp session\n");
+ return;
+ }
+
+ write_lock_bh(&ip_ct_gre_lock);
+ if (ct->help.ct_pptp_info.keymap_orig) {
+ DEBUGP("removing %p from list\n",
+ ct->help.ct_pptp_info.keymap_orig);
+ list_del(&ct->help.ct_pptp_info.keymap_orig->list);
+ kfree(ct->help.ct_pptp_info.keymap_orig);
+ ct->help.ct_pptp_info.keymap_orig = NULL;
+ }
+ if (ct->help.ct_pptp_info.keymap_reply) {
+ DEBUGP("removing %p from list\n",
+ ct->help.ct_pptp_info.keymap_reply);
+ list_del(&ct->help.ct_pptp_info.keymap_reply->list);
+ kfree(ct->help.ct_pptp_info.keymap_reply);
+ ct->help.ct_pptp_info.keymap_reply = NULL;
+ }
+ write_unlock_bh(&ip_ct_gre_lock);
+}
+
+
+/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
+
+/* invert gre part of tuple */
+static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
+ const struct ip_conntrack_tuple *orig)
+{
+ tuple->dst.u.gre.key = orig->src.u.gre.key;
+ tuple->src.u.gre.key = orig->dst.u.gre.key;
+
+ return 1;
+}
+
+/* gre hdr info to tuple */
+static int gre_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct ip_conntrack_tuple *tuple)
+{
+ struct gre_hdr_pptp _pgrehdr, *pgrehdr;
+ u_int32_t srckey;
+ struct gre_hdr _grehdr, *grehdr;
+
+ /* first only delinearize old RFC1701 GRE header */
+ grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr);
+ if (!grehdr || grehdr->version != GRE_VERSION_PPTP) {
+ /* try to behave like "ip_conntrack_proto_generic" */
+ tuple->src.u.all = 0;
+ tuple->dst.u.all = 0;
+ return 1;
+ }
+
+ /* PPTP header is variable length, only need up to the call_id field */
+ pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
+ if (!pgrehdr)
+ return 1;
+
+ if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
+ DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
+ return 0;
+ }
+
+ tuple->dst.u.gre.key = pgrehdr->call_id;
+ srckey = gre_keymap_lookup(tuple);
+ tuple->src.u.gre.key = srckey;
+
+ return 1;
+}
+
+/* print gre part of tuple */
+static int gre_print_tuple(struct seq_file *s,
+ const struct ip_conntrack_tuple *tuple)
+{
+ return seq_printf(s, "srckey=0x%x dstkey=0x%x ",
+ ntohs(tuple->src.u.gre.key),
+ ntohs(tuple->dst.u.gre.key));
+}
+
+/* print private data for conntrack */
+static int gre_print_conntrack(struct seq_file *s,
+ const struct ip_conntrack *ct)
+{
+ return seq_printf(s, "timeout=%u, stream_timeout=%u ",
+ (ct->proto.gre.timeout / HZ),
+ (ct->proto.gre.stream_timeout / HZ));
+}
+
+/* Returns verdict for packet, and may modify conntrack */
+static int gre_packet(struct ip_conntrack *ct,
+ const struct sk_buff *skb,
+ enum ip_conntrack_info conntrackinfo)
+{
+ /* If we've seen traffic both ways, this is a GRE connection.
+ * Extend timeout. */
+ if (ct->status & IPS_SEEN_REPLY) {
+ ip_ct_refresh_acct(ct, conntrackinfo, skb,
+ ct->proto.gre.stream_timeout);
+ /* Also, more likely to be important, and not a probe. */
+ set_bit(IPS_ASSURED_BIT, &ct->status);
+ } else
+ ip_ct_refresh_acct(ct, conntrackinfo, skb,
+ ct->proto.gre.timeout);
+
+ return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int gre_new(struct ip_conntrack *ct,
+ const struct sk_buff *skb)
+{
+ DEBUGP(": ");
+ DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+ /* initialize to sane value. Ideally a conntrack helper
+ * (e.g. in case of pptp) is increasing them */
+ ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
+ ct->proto.gre.timeout = GRE_TIMEOUT;
+
+ return 1;
+}
+
+/* Called when a conntrack entry has already been removed from the hashes
+ * and is about to be deleted from memory */
+static void gre_destroy(struct ip_conntrack *ct)
+{
+ struct ip_conntrack *master = ct->master;
+ DEBUGP(" entering\n");
+
+ if (!master)
+ DEBUGP("no master !?!\n");
+ else
+ ip_ct_gre_keymap_destroy(master);
+}
+
+/* protocol helper struct */
+static struct ip_conntrack_protocol gre = {
+ .proto = IPPROTO_GRE,
+ .name = "gre",
+ .pkt_to_tuple = gre_pkt_to_tuple,
+ .invert_tuple = gre_invert_tuple,
+ .print_tuple = gre_print_tuple,
+ .print_conntrack = gre_print_conntrack,
+ .packet = gre_packet,
+ .new = gre_new,
+ .destroy = gre_destroy,
+ .me = THIS_MODULE,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
+#endif
+};
+
+/* ip_conntrack_proto_gre initialization */
+int __init ip_ct_proto_gre_init(void)
+{
+ return ip_conntrack_protocol_register(&gre);
+}
+
+void __exit ip_ct_proto_gre_fini(void)
+{
+ struct list_head *pos, *n;
+
+ /* delete all keymap entries */
+ write_lock_bh(&ip_ct_gre_lock);
+ list_for_each_safe(pos, n, &gre_keymap_list) {
+ DEBUGP("deleting keymap %p at module unload time\n", pos);
+ list_del(pos);
+ kfree(pos);
+ }
+ write_unlock_bh(&ip_ct_gre_lock);
+
+ ip_conntrack_protocol_unregister(&gre);
+}
+
+EXPORT_SYMBOL(ip_ct_gre_keymap_add);
+EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index ae3e3e6..d3c7808 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -993,11 +993,11 @@ EXPORT_SYMBOL(ip_ct_refresh_acct);
EXPORT_SYMBOL(ip_conntrack_expect_alloc);
EXPORT_SYMBOL(ip_conntrack_expect_put);
-EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
+EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
EXPORT_SYMBOL(ip_conntrack_expect_related);
EXPORT_SYMBOL(ip_conntrack_unexpect_related);
EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
-EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
EXPORT_SYMBOL(ip_conntrack_tuple_taken);
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index d2b5905..a78736b 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -26,9 +26,9 @@ MODULE_DESCRIPTION("tftp connection tracking helper");
MODULE_LICENSE("GPL");
#define MAX_PORTS 8
-static int ports[MAX_PORTS];
+static short ports[MAX_PORTS];
static int ports_c;
-module_param_array(ports, int, &ports_c, 0400);
+module_param_array(ports, short, &ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of tftp servers");
#if 0
@@ -100,7 +100,7 @@ static int tftp_help(struct sk_buff **pskb,
}
static struct ip_conntrack_helper tftp[MAX_PORTS];
-static char tftp_names[MAX_PORTS][10];
+static char tftp_names[MAX_PORTS][sizeof("tftp-65535")];
static void fini(void)
{
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 1adedb7..c3ea891 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -578,6 +578,8 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
return ret;
}
+EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
+EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
#endif
int __init ip_nat_init(void)
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
new file mode 100644
index 0000000..3cdd068
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -0,0 +1,401 @@
+/*
+ * ip_nat_pptp.c - Version 3.0
+ *
+ * NAT support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft. PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * TODO: - NAT to a unique tuple, not to TCP source port
+ * (needs netfilter tuple reservation)
+ *
+ * Changes:
+ * 2002-02-10 - Version 1.3
+ * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
+ * in local connections (Philip Craig <philipc@snapgear.com>)
+ * - add checks for magicCookie and pptp version
+ * - make argument list of pptp_{out,in}bound_packet() shorter
+ * - move to C99 style initializers
+ * - print version number at module loadtime
+ * 2003-09-22 - Version 1.5
+ * - use SNATed tcp sourceport as callid, since we get called before
+ * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
+ * 2004-10-22 - Version 2.0
+ * - kernel 2.6.x version
+ * 2005-06-10 - Version 3.0
+ * - kernel >= 2.6.11 version,
+ * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_pptp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+#define IP_NAT_PPTP_VERSION "3.0"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
+
+
+#if 0
+extern const char *pptp_msg_name[];
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
+ __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static void pptp_nat_expected(struct ip_conntrack *ct,
+ struct ip_conntrack_expect *exp)
+{
+ struct ip_conntrack *master = ct->master;
+ struct ip_conntrack_expect *other_exp;
+ struct ip_conntrack_tuple t;
+ struct ip_ct_pptp_master *ct_pptp_info;
+ struct ip_nat_pptp *nat_pptp_info;
+
+ ct_pptp_info = &master->help.ct_pptp_info;
+ nat_pptp_info = &master->nat.help.nat_pptp_info;
+
+ /* And here goes the grand finale of corrosion... */
+
+ if (exp->dir == IP_CT_DIR_ORIGINAL) {
+ DEBUGP("we are PNS->PAC\n");
+ /* therefore, build tuple for PAC->PNS */
+ t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
+ t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id);
+ t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+ t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id);
+ t.dst.protonum = IPPROTO_GRE;
+ } else {
+ DEBUGP("we are PAC->PNS\n");
+ /* build tuple for PNS->PAC */
+ t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+ t.src.u.gre.key =
+ htons(master->nat.help.nat_pptp_info.pns_call_id);
+ t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+ t.dst.u.gre.key =
+ htons(master->nat.help.nat_pptp_info.pac_call_id);
+ t.dst.protonum = IPPROTO_GRE;
+ }
+
+ DEBUGP("trying to unexpect other dir: ");
+ DUMP_TUPLE(&t);
+ other_exp = ip_conntrack_expect_find(&t);
+ if (other_exp) {
+ ip_conntrack_unexpect_related(other_exp);
+ ip_conntrack_expect_put(other_exp);
+ DEBUGP("success\n");
+ } else {
+ DEBUGP("not found!\n");
+ }
+
+ ip_nat_follow_master(ct, exp);
+}
+
+/* outbound packets == from PNS to PAC */
+static int
+pptp_outbound_pkt(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq)
+
+{
+ struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
+ struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
+
+ u_int16_t msg, *cid = NULL, new_callid;
+
+ new_callid = htons(ct_pptp_info->pns_call_id);
+
+ switch (msg = ntohs(ctlh->messageType)) {
+ case PPTP_OUT_CALL_REQUEST:
+ cid = &pptpReq->ocreq.callID;
+ /* FIXME: ideally we would want to reserve a call ID
+ * here. current netfilter NAT core is not able to do
+ * this :( For now we use TCP source port. This breaks
+ * multiple calls within one control session */
+
+ /* save original call ID in nat_info */
+ nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
+
+ /* don't use tcph->source since we are at a DSTmanip
+ * hook (e.g. PREROUTING) and pkt is not mangled yet */
+ new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
+
+ /* save new call ID in ct info */
+ ct_pptp_info->pns_call_id = ntohs(new_callid);
+ break;
+ case PPTP_IN_CALL_REPLY:
+ cid = &pptpReq->icreq.callID;
+ break;
+ case PPTP_CALL_CLEAR_REQUEST:
+ cid = &pptpReq->clrreq.callID;
+ break;
+ default:
+ DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
+ (msg <= PPTP_MSG_MAX)?
+ pptp_msg_name[msg]:pptp_msg_name[0]);
+ /* fall through */
+
+ case PPTP_SET_LINK_INFO:
+ /* only need to NAT in case PAC is behind NAT box */
+ case PPTP_START_SESSION_REQUEST:
+ case PPTP_START_SESSION_REPLY:
+ case PPTP_STOP_SESSION_REQUEST:
+ case PPTP_STOP_SESSION_REPLY:
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* no need to alter packet */
+ return NF_ACCEPT;
+ }
+
+ /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
+ * down to here */
+
+ IP_NF_ASSERT(cid);
+
+ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
+ ntohs(*cid), ntohs(new_callid));
+
+ /* mangle packet */
+ if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
+ sizeof(new_callid),
+ (char *)&new_callid,
+ sizeof(new_callid)) == 0)
+ return NF_DROP;
+
+ return NF_ACCEPT;
+}
+
+static int
+pptp_exp_gre(struct ip_conntrack_expect *expect_orig,
+ struct ip_conntrack_expect *expect_reply)
+{
+ struct ip_ct_pptp_master *ct_pptp_info =
+ &expect_orig->master->help.ct_pptp_info;
+ struct ip_nat_pptp *nat_pptp_info =
+ &expect_orig->master->nat.help.nat_pptp_info;
+
+ struct ip_conntrack *ct = expect_orig->master;
+
+ struct ip_conntrack_tuple inv_t;
+ struct ip_conntrack_tuple *orig_t, *reply_t;
+
+ /* save original PAC call ID in nat_info */
+ nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
+
+ /* alter expectation */
+ orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+
+ /* alter expectation for PNS->PAC direction */
+ invert_tuplepr(&inv_t, &expect_orig->tuple);
+ expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id);
+ expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
+ expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
+ inv_t.src.ip = reply_t->src.ip;
+ inv_t.dst.ip = reply_t->dst.ip;
+ inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
+ inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
+
+ if (!ip_conntrack_expect_related(expect_orig)) {
+ DEBUGP("successfully registered expect\n");
+ } else {
+ DEBUGP("can't expect_related(expect_orig)\n");
+ return 1;
+ }
+
+ /* alter expectation for PAC->PNS direction */
+ invert_tuplepr(&inv_t, &expect_reply->tuple);
+ expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id);
+ expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
+ expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
+ inv_t.src.ip = orig_t->src.ip;
+ inv_t.dst.ip = orig_t->dst.ip;
+ inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
+ inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
+
+ if (!ip_conntrack_expect_related(expect_reply)) {
+ DEBUGP("successfully registered expect\n");
+ } else {
+ DEBUGP("can't expect_related(expect_reply)\n");
+ ip_conntrack_unexpect_related(expect_orig);
+ return 1;
+ }
+
+ if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) {
+ DEBUGP("can't register original keymap\n");
+ ip_conntrack_unexpect_related(expect_orig);
+ ip_conntrack_unexpect_related(expect_reply);
+ return 1;
+ }
+
+ if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) {
+ DEBUGP("can't register reply keymap\n");
+ ip_conntrack_unexpect_related(expect_orig);
+ ip_conntrack_unexpect_related(expect_reply);
+ ip_ct_gre_keymap_destroy(ct);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* inbound packets == from PAC to PNS */
+static int
+pptp_inbound_pkt(struct sk_buff **pskb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ struct PptpControlHeader *ctlh,
+ union pptp_ctrl_union *pptpReq)
+{
+ struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
+ u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
+
+ int ret = NF_ACCEPT, rv;
+
+ new_pcid = htons(nat_pptp_info->pns_call_id);
+
+ switch (msg = ntohs(ctlh->messageType)) {
+ case PPTP_OUT_CALL_REPLY:
+ pcid = &pptpReq->ocack.peersCallID;
+ cid = &pptpReq->ocack.callID;
+ break;
+ case PPTP_IN_CALL_CONNECT:
+ pcid = &pptpReq->iccon.peersCallID;
+ break;
+ case PPTP_IN_CALL_REQUEST:
+ /* only need to nat in case PAC is behind NAT box */
+ break;
+ case PPTP_WAN_ERROR_NOTIFY:
+ pcid = &pptpReq->wanerr.peersCallID;
+ break;
+ case PPTP_CALL_DISCONNECT_NOTIFY:
+ pcid = &pptpReq->disc.callID;
+ break;
+ case PPTP_SET_LINK_INFO:
+ pcid = &pptpReq->setlink.peersCallID;
+ break;
+
+ default:
+ DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
+ pptp_msg_name[msg]:pptp_msg_name[0]);
+ /* fall through */
+
+ case PPTP_START_SESSION_REQUEST:
+ case PPTP_START_SESSION_REPLY:
+ case PPTP_STOP_SESSION_REQUEST:
+ case PPTP_STOP_SESSION_REPLY:
+ case PPTP_ECHO_REQUEST:
+ case PPTP_ECHO_REPLY:
+ /* no need to alter packet */
+ return NF_ACCEPT;
+ }
+
+ /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
+ * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
+
+ /* mangle packet */
+ IP_NF_ASSERT(pcid);
+ DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
+ ntohs(*pcid), ntohs(new_pcid));
+
+ rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
+ sizeof(new_pcid), (char *)&new_pcid,
+ sizeof(new_pcid));
+ if (rv != NF_ACCEPT)
+ return rv;
+
+ if (new_cid) {
+ IP_NF_ASSERT(cid);
+ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
+ ntohs(*cid), ntohs(new_cid));
+ rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
+ sizeof(new_cid),
+ (char *)&new_cid,
+ sizeof(new_cid));
+ if (rv != NF_ACCEPT)
+ return rv;
+ }
+
+ /* check for earlier return value of 'switch' above */
+ if (ret != NF_ACCEPT)
+ return ret;
+
+ /* great, at least we don't need to resize packets */
+ return NF_ACCEPT;
+}
+
+
+extern int __init ip_nat_proto_gre_init(void);
+extern void __exit ip_nat_proto_gre_fini(void);
+
+static int __init init(void)
+{
+ int ret;
+
+ DEBUGP("%s: registering NAT helper\n", __FILE__);
+
+ ret = ip_nat_proto_gre_init();
+ if (ret < 0)
+ return ret;
+
+ BUG_ON(ip_nat_pptp_hook_outbound);
+ ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
+
+ BUG_ON(ip_nat_pptp_hook_inbound);
+ ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
+
+ BUG_ON(ip_nat_pptp_hook_exp_gre);
+ ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
+
+ BUG_ON(ip_nat_pptp_hook_expectfn);
+ ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
+
+ printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ DEBUGP("cleanup_module\n" );
+
+ ip_nat_pptp_hook_expectfn = NULL;
+ ip_nat_pptp_hook_exp_gre = NULL;
+ ip_nat_pptp_hook_inbound = NULL;
+ ip_nat_pptp_hook_outbound = NULL;
+
+ ip_nat_proto_gre_fini();
+ /* Make sure noone calls it, meanwhile */
+ synchronize_net();
+
+ printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
new file mode 100644
index 0000000..7c12854
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -0,0 +1,214 @@
+/*
+ * ip_nat_proto_gre.c - Version 2.0
+ *
+ * NAT protocol helper module for GRE.
+ *
+ * GRE is a generic encapsulation protocol, which is generally not very
+ * suited for NAT, as it has no protocol-specific part as port numbers.
+ *
+ * It has an optional key field, which may help us distinguishing two
+ * connections between the same two hosts.
+ *
+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
+ *
+ * PPTP is built on top of a modified version of GRE, and has a mandatory
+ * field called "CallID", which serves us for the same purpose as the key
+ * field in plain GRE.
+ *
+ * Documentation about PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_nat_protocol.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
+ __FUNCTION__, ## args)
+#else
+#define DEBUGP(x, args...)
+#endif
+
+/* is key in given range between min and max */
+static int
+gre_in_range(const struct ip_conntrack_tuple *tuple,
+ enum ip_nat_manip_type maniptype,
+ const union ip_conntrack_manip_proto *min,
+ const union ip_conntrack_manip_proto *max)
+{
+ u_int32_t key;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ key = tuple->src.u.gre.key;
+ else
+ key = tuple->dst.u.gre.key;
+
+ return ntohl(key) >= ntohl(min->gre.key)
+ && ntohl(key) <= ntohl(max->gre.key);
+}
+
+/* generate unique tuple ... */
+static int
+gre_unique_tuple(struct ip_conntrack_tuple *tuple,
+ const struct ip_nat_range *range,
+ enum ip_nat_manip_type maniptype,
+ const struct ip_conntrack *conntrack)
+{
+ static u_int16_t key;
+ u_int16_t *keyptr;
+ unsigned int min, i, range_size;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ keyptr = &tuple->src.u.gre.key;
+ else
+ keyptr = &tuple->dst.u.gre.key;
+
+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+ DEBUGP("%p: NATing GRE PPTP\n", conntrack);
+ min = 1;
+ range_size = 0xffff;
+ } else {
+ min = ntohl(range->min.gre.key);
+ range_size = ntohl(range->max.gre.key) - min + 1;
+ }
+
+ DEBUGP("min = %u, range_size = %u\n", min, range_size);
+
+ for (i = 0; i < range_size; i++, key++) {
+ *keyptr = htonl(min + key % range_size);
+ if (!ip_nat_used_tuple(tuple, conntrack))
+ return 1;
+ }
+
+ DEBUGP("%p: no NAT mapping\n", conntrack);
+
+ return 0;
+}
+
+/* manipulate a GRE packet according to maniptype */
+static int
+gre_manip_pkt(struct sk_buff **pskb,
+ unsigned int iphdroff,
+ const struct ip_conntrack_tuple *tuple,
+ enum ip_nat_manip_type maniptype)
+{
+ struct gre_hdr *greh;
+ struct gre_hdr_pptp *pgreh;
+ struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+ unsigned int hdroff = iphdroff + iph->ihl*4;
+
+ /* pgreh includes two optional 32bit fields which are not required
+ * to be there. That's where the magic '8' comes from */
+ if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8))
+ return 0;
+
+ greh = (void *)(*pskb)->data + hdroff;
+ pgreh = (struct gre_hdr_pptp *) greh;
+
+ /* we only have destination manip of a packet, since 'source key'
+ * is not present in the packet itself */
+ if (maniptype == IP_NAT_MANIP_DST) {
+ /* key manipulation is always dest */
+ switch (greh->version) {
+ case 0:
+ if (!greh->key) {
+ DEBUGP("can't nat GRE w/o key\n");
+ break;
+ }
+ if (greh->csum) {
+ /* FIXME: Never tested this code... */
+ *(gre_csum(greh)) =
+ ip_nat_cheat_check(~*(gre_key(greh)),
+ tuple->dst.u.gre.key,
+ *(gre_csum(greh)));
+ }
+ *(gre_key(greh)) = tuple->dst.u.gre.key;
+ break;
+ case GRE_VERSION_PPTP:
+ DEBUGP("call_id -> 0x%04x\n",
+ ntohl(tuple->dst.u.gre.key));
+ pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key));
+ break;
+ default:
+ DEBUGP("can't nat unknown GRE version\n");
+ return 0;
+ break;
+ }
+ }
+ return 1;
+}
+
+/* print out a nat tuple */
+static unsigned int
+gre_print(char *buffer,
+ const struct ip_conntrack_tuple *match,
+ const struct ip_conntrack_tuple *mask)
+{
+ unsigned int len = 0;
+
+ if (mask->src.u.gre.key)
+ len += sprintf(buffer + len, "srckey=0x%x ",
+ ntohl(match->src.u.gre.key));
+
+ if (mask->dst.u.gre.key)
+ len += sprintf(buffer + len, "dstkey=0x%x ",
+ ntohl(match->src.u.gre.key));
+
+ return len;
+}
+
+/* print a range of keys */
+static unsigned int
+gre_print_range(char *buffer, const struct ip_nat_range *range)
+{
+ if (range->min.gre.key != 0
+ || range->max.gre.key != 0xFFFF) {
+ if (range->min.gre.key == range->max.gre.key)
+ return sprintf(buffer, "key 0x%x ",
+ ntohl(range->min.gre.key));
+ else
+ return sprintf(buffer, "keys 0x%u-0x%u ",
+ ntohl(range->min.gre.key),
+ ntohl(range->max.gre.key));
+ } else
+ return 0;
+}
+
+/* nat helper struct */
+static struct ip_nat_protocol gre = {
+ .name = "GRE",
+ .protonum = IPPROTO_GRE,
+ .manip_pkt = gre_manip_pkt,
+ .in_range = gre_in_range,
+ .unique_tuple = gre_unique_tuple,
+ .print = gre_print,
+ .print_range = gre_print_range,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+ .range_to_nfattr = ip_nat_port_range_to_nfattr,
+ .nfattr_to_range = ip_nat_port_nfattr_to_range,
+#endif
+};
+
+int __init ip_nat_proto_gre_init(void)
+{
+ return ip_nat_protocol_register(&gre);
+}
+
+void __exit ip_nat_proto_gre_fini(void)
+{
+ ip_nat_protocol_unregister(&gre);
+}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 7d38913..9bcb398 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -13,6 +13,7 @@
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/jhash.h>
+#include <linux/bitops.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
@@ -30,7 +31,7 @@
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
-#define CLUSTERIP_VERSION "0.7"
+#define CLUSTERIP_VERSION "0.8"
#define DEBUG_CLUSTERIP
@@ -49,13 +50,14 @@ MODULE_DESCRIPTION("iptables target for CLUSTERIP");
struct clusterip_config {
struct list_head list; /* list of all configs */
atomic_t refcount; /* reference count */
+ atomic_t entries; /* number of entries/rules
+ * referencing us */
u_int32_t clusterip; /* the IP address */
u_int8_t clustermac[ETH_ALEN]; /* the MAC address */
struct net_device *dev; /* device */
u_int16_t num_total_nodes; /* total number of nodes */
- u_int16_t num_local_nodes; /* number of local nodes */
- u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; /* node number array */
+ unsigned long local_nodes; /* node number array */
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *pde; /* proc dir entry */
@@ -66,8 +68,7 @@ struct clusterip_config {
static LIST_HEAD(clusterip_configs);
-/* clusterip_lock protects the clusterip_configs list _AND_ the configurable
- * data within all structurses (num_local_nodes, local_nodes[]) */
+/* clusterip_lock protects the clusterip_configs list */
static DEFINE_RWLOCK(clusterip_lock);
#ifdef CONFIG_PROC_FS
@@ -76,23 +77,48 @@ static struct proc_dir_entry *clusterip_procdir;
#endif
static inline void
-clusterip_config_get(struct clusterip_config *c) {
+clusterip_config_get(struct clusterip_config *c)
+{
atomic_inc(&c->refcount);
}
static inline void
-clusterip_config_put(struct clusterip_config *c) {
- if (atomic_dec_and_test(&c->refcount)) {
+clusterip_config_put(struct clusterip_config *c)
+{
+ if (atomic_dec_and_test(&c->refcount))
+ kfree(c);
+}
+
+/* increase the count of entries(rules) using/referencing this config */
+static inline void
+clusterip_config_entry_get(struct clusterip_config *c)
+{
+ atomic_inc(&c->entries);
+}
+
+/* decrease the count of entries using/referencing this config. If last
+ * entry(rule) is removed, remove the config from lists, but don't free it
+ * yet, since proc-files could still be holding references */
+static inline void
+clusterip_config_entry_put(struct clusterip_config *c)
+{
+ if (atomic_dec_and_test(&c->entries)) {
write_lock_bh(&clusterip_lock);
list_del(&c->list);
write_unlock_bh(&clusterip_lock);
+
dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0);
dev_put(c->dev);
- kfree(c);
+
+ /* In case anyone still accesses the file, the open/close
+ * functions are also incrementing the refcount on their own,
+ * so it's safe to remove the entry even if it's in use. */
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry(c->pde->name, c->pde->parent);
+#endif
}
}
-
static struct clusterip_config *
__clusterip_config_find(u_int32_t clusterip)
{
@@ -111,7 +137,7 @@ __clusterip_config_find(u_int32_t clusterip)
}
static inline struct clusterip_config *
-clusterip_config_find_get(u_int32_t clusterip)
+clusterip_config_find_get(u_int32_t clusterip, int entry)
{
struct clusterip_config *c;
@@ -122,11 +148,24 @@ clusterip_config_find_get(u_int32_t clusterip)
return NULL;
}
atomic_inc(&c->refcount);
+ if (entry)
+ atomic_inc(&c->entries);
read_unlock_bh(&clusterip_lock);
return c;
}
+static void
+clusterip_config_init_nodelist(struct clusterip_config *c,
+ const struct ipt_clusterip_tgt_info *i)
+{
+ int n;
+
+ for (n = 0; n < i->num_local_nodes; n++) {
+ set_bit(i->local_nodes[n] - 1, &c->local_nodes);
+ }
+}
+
static struct clusterip_config *
clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
struct net_device *dev)
@@ -143,11 +182,11 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
c->clusterip = ip;
memcpy(&c->clustermac, &i->clustermac, ETH_ALEN);
c->num_total_nodes = i->num_total_nodes;
- c->num_local_nodes = i->num_local_nodes;
- memcpy(&c->local_nodes, &i->local_nodes, sizeof(c->local_nodes));
+ clusterip_config_init_nodelist(c, i);
c->hash_mode = i->hash_mode;
c->hash_initval = i->hash_initval;
atomic_set(&c->refcount, 1);
+ atomic_set(&c->entries, 1);
#ifdef CONFIG_PROC_FS
/* create proc dir entry */
@@ -171,53 +210,28 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
static int
clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
{
- int i;
-
- write_lock_bh(&clusterip_lock);
- if (c->num_local_nodes >= CLUSTERIP_MAX_NODES
- || nodenum > CLUSTERIP_MAX_NODES) {
- write_unlock_bh(&clusterip_lock);
+ if (nodenum == 0 ||
+ nodenum > c->num_total_nodes)
return 1;
- }
-
- /* check if we alrady have this number in our array */
- for (i = 0; i < c->num_local_nodes; i++) {
- if (c->local_nodes[i] == nodenum) {
- write_unlock_bh(&clusterip_lock);
- return 1;
- }
- }
- c->local_nodes[c->num_local_nodes++] = nodenum;
+ /* check if we already have this number in our bitfield */
+ if (test_and_set_bit(nodenum - 1, &c->local_nodes))
+ return 1;
- write_unlock_bh(&clusterip_lock);
return 0;
}
static int
clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
{
- int i;
-
- write_lock_bh(&clusterip_lock);
-
- if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) {
- write_unlock_bh(&clusterip_lock);
+ if (nodenum == 0 ||
+ nodenum > c->num_total_nodes)
return 1;
- }
- for (i = 0; i < c->num_local_nodes; i++) {
- if (c->local_nodes[i] == nodenum) {
- int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1));
- memmove(&c->local_nodes[i], &c->local_nodes[i+1], size);
- c->num_local_nodes--;
- write_unlock_bh(&clusterip_lock);
- return 0;
- }
- }
+ if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
+ return 0;
- write_unlock_bh(&clusterip_lock);
return 1;
}
@@ -285,25 +299,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
static inline int
clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
{
- int i;
-
- read_lock_bh(&clusterip_lock);
-
- if (config->num_local_nodes == 0) {
- read_unlock_bh(&clusterip_lock);
- return 0;
- }
-
- for (i = 0; i < config->num_local_nodes; i++) {
- if (config->local_nodes[i] == hash) {
- read_unlock_bh(&clusterip_lock);
- return 1;
- }
- }
-
- read_unlock_bh(&clusterip_lock);
-
- return 0;
+ return test_bit(hash - 1, &config->local_nodes);
}
/***********************************************************************
@@ -415,8 +411,26 @@ checkentry(const char *tablename,
/* FIXME: further sanity checks */
- config = clusterip_config_find_get(e->ip.dst.s_addr);
- if (!config) {
+ config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
+ if (config) {
+ if (cipinfo->config != NULL) {
+ /* Case A: This is an entry that gets reloaded, since
+ * it still has a cipinfo->config pointer. Simply
+ * increase the entry refcount and return */
+ if (cipinfo->config != config) {
+ printk(KERN_ERR "CLUSTERIP: Reloaded entry "
+ "has invalid config pointer!\n");
+ return 0;
+ }
+ clusterip_config_entry_get(cipinfo->config);
+ } else {
+ /* Case B: This is a new rule referring to an existing
+ * clusterip config. */
+ cipinfo->config = config;
+ clusterip_config_entry_get(cipinfo->config);
+ }
+ } else {
+ /* Case C: This is a completely new clusterip config */
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
return 0;
@@ -443,10 +457,9 @@ checkentry(const char *tablename,
}
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
}
+ cipinfo->config = config;
}
- cipinfo->config = config;
-
return 1;
}
@@ -455,13 +468,10 @@ static void destroy(void *matchinfo, unsigned int matchinfosize)
{
struct ipt_clusterip_tgt_info *cipinfo = matchinfo;
- /* we first remove the proc entry and then drop the reference
- * count. In case anyone still accesses the file, the open/close
- * functions are also incrementing the refcount on their own */
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(cipinfo->config->pde->name,
- cipinfo->config->pde->parent);
-#endif
+ /* if no more entries are referencing the config, remove it
+ * from the list and destroy the proc entry */
+ clusterip_config_entry_put(cipinfo->config);
+
clusterip_config_put(cipinfo->config);
}
@@ -533,7 +543,7 @@ arp_mangle(unsigned int hook,
/* if there is no clusterip configuration for the arp reply's
* source ip, we don't want to mangle it */
- c = clusterip_config_find_get(payload->src_ip);
+ c = clusterip_config_find_get(payload->src_ip, 0);
if (!c)
return NF_ACCEPT;
@@ -574,56 +584,69 @@ static struct nf_hook_ops cip_arp_ops = {
#ifdef CONFIG_PROC_FS
+struct clusterip_seq_position {
+ unsigned int pos; /* position */
+ unsigned int weight; /* number of bits set == size */
+ unsigned int bit; /* current bit */
+ unsigned long val; /* current value */
+};
+
static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
{
struct proc_dir_entry *pde = s->private;
struct clusterip_config *c = pde->data;
- unsigned int *nodeidx;
-
- read_lock_bh(&clusterip_lock);
- if (*pos >= c->num_local_nodes)
+ unsigned int weight;
+ u_int32_t local_nodes;
+ struct clusterip_seq_position *idx;
+
+ /* FIXME: possible race */
+ local_nodes = c->local_nodes;
+ weight = hweight32(local_nodes);
+ if (*pos >= weight)
return NULL;
- nodeidx = kmalloc(sizeof(unsigned int), GFP_KERNEL);
- if (!nodeidx)
+ idx = kmalloc(sizeof(struct clusterip_seq_position), GFP_KERNEL);
+ if (!idx)
return ERR_PTR(-ENOMEM);
- *nodeidx = *pos;
- return nodeidx;
+ idx->pos = *pos;
+ idx->weight = weight;
+ idx->bit = ffs(local_nodes);
+ idx->val = local_nodes;
+ clear_bit(idx->bit - 1, &idx->val);
+
+ return idx;
}
static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- struct proc_dir_entry *pde = s->private;
- struct clusterip_config *c = pde->data;
- unsigned int *nodeidx = (unsigned int *)v;
+ struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
- *pos = ++(*nodeidx);
- if (*pos >= c->num_local_nodes) {
+ *pos = ++idx->pos;
+ if (*pos >= idx->weight) {
kfree(v);
return NULL;
}
- return nodeidx;
+ idx->bit = ffs(idx->val);
+ clear_bit(idx->bit - 1, &idx->val);
+ return idx;
}
static void clusterip_seq_stop(struct seq_file *s, void *v)
{
kfree(v);
-
- read_unlock_bh(&clusterip_lock);
}
static int clusterip_seq_show(struct seq_file *s, void *v)
{
- struct proc_dir_entry *pde = s->private;
- struct clusterip_config *c = pde->data;
- unsigned int *nodeidx = (unsigned int *)v;
+ struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
- if (*nodeidx != 0)
+ if (idx->pos != 0)
seq_putc(s, ',');
- seq_printf(s, "%u", c->local_nodes[*nodeidx]);
- if (*nodeidx == c->num_local_nodes-1)
+ seq_printf(s, "%u", idx->bit);
+
+ if (idx->pos == idx->weight - 1)
seq_putc(s, '\n');
return 0;
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 2f3e181..275a174 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -90,6 +90,12 @@ masquerade_target(struct sk_buff **pskb,
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
+ /* Source address is 0.0.0.0 - locally generated packet that is
+ * probably not supposed to be masqueraded.
+ */
+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
+ return NF_ACCEPT;
+
mr = targinfo;
rt = (struct rtable *)(*pskb)->dst;
newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index d2e1344..715cb61 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -88,14 +88,18 @@ redirect_target(struct sk_buff **pskb,
newdst = htonl(0x7F000001);
else {
struct in_device *indev;
+ struct in_ifaddr *ifa;
- /* Device might not have an associated in_device. */
- indev = (struct in_device *)(*pskb)->dev->ip_ptr;
- if (indev == NULL || indev->ifa_list == NULL)
- return NF_DROP;
+ newdst = 0;
+
+ rcu_read_lock();
+ indev = __in_dev_get((*pskb)->dev);
+ if (indev && (ifa = indev->ifa_list))
+ newdst = ifa->ifa_local;
+ rcu_read_unlock();
- /* Grab first address on interface. */
- newdst = indev->ifa_list->ifa_local;
+ if (!newdst)
+ return NF_DROP;
}
/* Transfer from original range. */
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 304bb0a..4b0d7e4 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -361,7 +361,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
if (type && code) {
get_user(fl->fl_icmp_type, type);
- __get_user(fl->fl_icmp_code, code);
+ get_user(fl->fl_icmp_code, code);
probed = 1;
}
break;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 29222b96..a7537c7 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -979,14 +979,19 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
if (!before(TCP_SKB_CB(skb)->seq, end_seq))
break;
+ in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
+ !before(end_seq, TCP_SKB_CB(skb)->end_seq);
+
pcount = tcp_skb_pcount(skb);
- if (pcount > 1 &&
- (after(start_seq, TCP_SKB_CB(skb)->seq) ||
- before(end_seq, TCP_SKB_CB(skb)->end_seq))) {
+ if (pcount > 1 && !in_sack &&
+ after(TCP_SKB_CB(skb)->end_seq, start_seq)) {
unsigned int pkt_len;
- if (after(start_seq, TCP_SKB_CB(skb)->seq))
+ in_sack = !after(start_seq,
+ TCP_SKB_CB(skb)->seq);
+
+ if (!in_sack)
pkt_len = (start_seq -
TCP_SKB_CB(skb)->seq);
else
@@ -999,9 +1004,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
fack_count += pcount;
- in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
- !before(end_seq, TCP_SKB_CB(skb)->end_seq);
-
sacked = TCP_SKB_CB(skb)->sacked;
/* Account D-SACK for retransmitted packet. */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index c10e443..5dd6dd7 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -435,6 +435,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
int nsize, old_factor;
u16 flags;
+ BUG_ON(len >= skb->len);
+
nsize = skb_headlen(skb) - len;
if (nsize < 0)
nsize = 0;
@@ -459,9 +461,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
flags = TCP_SKB_CB(skb)->flags;
TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
TCP_SKB_CB(buff)->flags = flags;
- TCP_SKB_CB(buff)->sacked =
- (TCP_SKB_CB(skb)->sacked &
- (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL));
+ TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked;
TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
@@ -499,6 +499,12 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
tcp_skb_pcount(buff);
tp->packets_out -= diff;
+
+ if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
+ tp->sacked_out -= diff;
+ if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+ tp->retrans_out -= diff;
+
if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
tp->lost_out -= diff;
tp->left_out -= diff;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 29fed6e..519899f 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1968,7 +1968,7 @@ static void ip6_mc_clear_src(struct ifmcaddr6 *pmc)
}
pmc->mca_sources = NULL;
pmc->mca_sfmode = MCAST_EXCLUDE;
- pmc->mca_sfcount[MCAST_EXCLUDE] = 0;
+ pmc->mca_sfcount[MCAST_INCLUDE] = 0;
pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1cb8adb..2da514b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1955,6 +1955,57 @@ static void __exit fini(void)
#endif
}
+/*
+ * find specified header up to transport protocol header.
+ * If found target header, the offset to the header is set to *offset
+ * and return 0. otherwise, return -1.
+ *
+ * Notes: - non-1st Fragment Header isn't skipped.
+ * - ESP header isn't skipped.
+ * - The target header may be trancated.
+ */
+int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target)
+{
+ unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+ u8 nexthdr = skb->nh.ipv6h->nexthdr;
+ unsigned int len = skb->len - start;
+
+ while (nexthdr != target) {
+ struct ipv6_opt_hdr _hdr, *hp;
+ unsigned int hdrlen;
+
+ if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE)
+ return -1;
+ hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return -1;
+ if (nexthdr == NEXTHDR_FRAGMENT) {
+ unsigned short _frag_off, *fp;
+ fp = skb_header_pointer(skb,
+ start+offsetof(struct frag_hdr,
+ frag_off),
+ sizeof(_frag_off),
+ &_frag_off);
+ if (fp == NULL)
+ return -1;
+
+ if (ntohs(*fp) & ~0x7)
+ return -1;
+ hdrlen = 8;
+ } else if (nexthdr == NEXTHDR_AUTH)
+ hdrlen = (hp->hdrlen + 2) << 2;
+ else
+ hdrlen = ipv6_optlen(hp);
+
+ nexthdr = hp->nexthdr;
+ len -= hdrlen;
+ start += hdrlen;
+ }
+
+ *offset = start;
+ return 0;
+}
+
EXPORT_SYMBOL(ip6t_register_table);
EXPORT_SYMBOL(ip6t_unregister_table);
EXPORT_SYMBOL(ip6t_do_table);
@@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match);
EXPORT_SYMBOL(ip6t_register_target);
EXPORT_SYMBOL(ip6t_unregister_target);
EXPORT_SYMBOL(ip6t_ext_hdr);
+EXPORT_SYMBOL(ipv6_find_hdr);
module_init(init);
module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index d5b94f1..dde3779 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -48,92 +48,21 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ip_auth_hdr *ah = NULL, _ah;
+ struct ip_auth_hdr *ah, _ah;
const struct ip6t_ah *ahinfo = matchinfo;
- unsigned int temp;
- int len;
- u8 nexthdr;
unsigned int ptr;
unsigned int hdrlen = 0;
- /*DEBUGP("IPv6 AH entered\n");*/
- /* if (opt->auth == 0) return 0;
- * It does not filled on output */
-
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
-
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
-
- DEBUGP("ipv6_ah header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE)
- break;
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP)
- break;
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT)
- hdrlen = 8;
- else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- /* AH -> evaluate */
- if (nexthdr == NEXTHDR_AUTH) {
- temp |= MASK_AH;
- break;
- }
-
-
- /* set the flag */
- switch (nexthdr) {
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
- return 0;
- }
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if (ptr > skb->len) {
- DEBUGP("ipv6_ah: new pointer too large! \n");
- break;
- }
- }
-
- /* AH header not found */
- if (temp != MASK_AH)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0)
return 0;
- if (len < sizeof(struct ip_auth_hdr)){
+ ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
+ if (ah == NULL) {
*hotdrop = 1;
return 0;
}
- ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
- BUG_ON(ah == NULL);
+ hdrlen = (ah->hdrlen + 2) << 2;
DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
DEBUGP("RES %04X ", ah->reserved);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 540925e..c450a63 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb,
struct ipv6_opt_hdr _optsh, *oh;
const struct ip6t_opts *optinfo = matchinfo;
unsigned int temp;
- unsigned int len;
- u8 nexthdr;
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb,
u8 _optlen, *lp = NULL;
unsigned int optlen;
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
-
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
-
- DEBUGP("ipv6_opts header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
- break;
- }
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
- break;
- }
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- /* OPTS -> evaluate */
#if HOPBYHOP
- if (nexthdr == NEXTHDR_HOP) {
- temp |= MASK_HOPOPTS;
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
#else
- if (nexthdr == NEXTHDR_DEST) {
- temp |= MASK_DSTOPTS;
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
#endif
- break;
- }
-
+ return 0;
- /* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
- }
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
- DEBUGP("ipv6_opts: new pointer is too large! \n");
- break;
- }
- }
-
- /* OPTIONS header not found */
-#if HOPBYHOP
- if ( temp != MASK_HOPOPTS ) return 0;
-#else
- if ( temp != MASK_DSTOPTS ) return 0;
-#endif
-
- if (len < (int)sizeof(struct ipv6_opt_hdr)){
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ if (oh == NULL){
*hotdrop = 1;
return 0;
}
- if (len < hdrlen){
+ hdrlen = ipv6_optlen(oh);
+ if (skb->len - ptr < hdrlen){
/* Packet smaller than it's length field */
return 0;
}
- oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
- BUG_ON(oh == NULL);
-
DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
DEBUGP("len %02X %04X %02X ",
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index e39dd23..24bc0cd 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -48,87 +48,22 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ip_esp_hdr _esp, *eh = NULL;
+ struct ip_esp_hdr _esp, *eh;
const struct ip6t_esp *espinfo = matchinfo;
- unsigned int temp;
- int len;
- u8 nexthdr;
unsigned int ptr;
/* Make sure this isn't an evil packet */
/*DEBUGP("ipv6_esp entered \n");*/
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
-
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
- int hdrlen;
-
- DEBUGP("ipv6_esp header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE)
- break;
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
- temp |= MASK_ESP;
- break;
- }
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT)
- hdrlen = 8;
- else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- /* set the flag */
- switch (nexthdr) {
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
- return 0;
- }
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if (ptr > skb->len) {
- DEBUGP("ipv6_esp: new pointer too large! \n");
- break;
- }
- }
-
- /* ESP header not found */
- if (temp != MASK_ESP)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0)
return 0;
- if (len < sizeof(struct ip_esp_hdr)) {
+ eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
+ if (eh == NULL) {
*hotdrop = 1;
return 0;
}
- eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
- BUG_ON(eh == NULL);
-
DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
return (eh != NULL)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4bfa30a..085d5f8 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -48,90 +48,18 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct frag_hdr _frag, *fh = NULL;
+ struct frag_hdr _frag, *fh;
const struct ip6t_frag *fraginfo = matchinfo;
- unsigned int temp;
- int len;
- u8 nexthdr;
unsigned int ptr;
- unsigned int hdrlen = 0;
-
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
-
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
-
- DEBUGP("ipv6_frag header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
- break;
- }
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
- break;
- }
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- /* FRAG -> evaluate */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- temp |= MASK_FRAGMENT;
- break;
- }
-
-
- /* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
- }
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
- DEBUGP("ipv6_frag: new pointer too large! \n");
- break;
- }
- }
-
- /* FRAG header not found */
- if ( temp != MASK_FRAGMENT ) return 0;
-
- if (len < sizeof(struct frag_hdr)){
- *hotdrop = 1;
- return 0;
- }
- fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
- BUG_ON(fh == NULL);
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0)
+ return 0;
+
+ fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
+ if (fh == NULL){
+ *hotdrop = 1;
+ return 0;
+ }
DEBUGP("INFO %04X ", fh->frag_off);
DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 27f3650..1d09485 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb,
struct ipv6_opt_hdr _optsh, *oh;
const struct ip6t_opts *optinfo = matchinfo;
unsigned int temp;
- unsigned int len;
- u8 nexthdr;
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb,
u8 _optlen, *lp = NULL;
unsigned int optlen;
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
-
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
-
- DEBUGP("ipv6_opts header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
- break;
- }
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
- break;
- }
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- /* OPTS -> evaluate */
#if HOPBYHOP
- if (nexthdr == NEXTHDR_HOP) {
- temp |= MASK_HOPOPTS;
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
#else
- if (nexthdr == NEXTHDR_DEST) {
- temp |= MASK_DSTOPTS;
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
#endif
- break;
- }
-
+ return 0;
- /* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
- }
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
- DEBUGP("ipv6_opts: new pointer is too large! \n");
- break;
- }
- }
-
- /* OPTIONS header not found */
-#if HOPBYHOP
- if ( temp != MASK_HOPOPTS ) return 0;
-#else
- if ( temp != MASK_DSTOPTS ) return 0;
-#endif
-
- if (len < (int)sizeof(struct ipv6_opt_hdr)){
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ if (oh == NULL){
*hotdrop = 1;
return 0;
}
- if (len < hdrlen){
+ hdrlen = ipv6_optlen(oh);
+ if (skb->len - ptr < hdrlen){
/* Packet smaller than it's length field */
return 0;
}
- oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
- BUG_ON(oh == NULL);
-
DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
DEBUGP("len %02X %04X %02X ",
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 2bb6700..beb2fd5 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -50,98 +50,29 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ipv6_rt_hdr _route, *rh = NULL;
+ struct ipv6_rt_hdr _route, *rh;
const struct ip6t_rt *rtinfo = matchinfo;
unsigned int temp;
- unsigned int len;
- u8 nexthdr;
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
struct in6_addr *ap, _addr;
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0)
+ return 0;
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
-
- DEBUGP("ipv6_rt header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
- break;
- }
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
- break;
- }
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- /* ROUTING -> evaluate */
- if (nexthdr == NEXTHDR_ROUTING) {
- temp |= MASK_ROUTING;
- break;
- }
-
-
- /* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
- }
-
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
- DEBUGP("ipv6_rt: new pointer is too large! \n");
- break;
- }
- }
-
- /* ROUTING header not found */
- if ( temp != MASK_ROUTING ) return 0;
-
- if (len < (int)sizeof(struct ipv6_rt_hdr)){
+ rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
+ if (rh == NULL){
*hotdrop = 1;
return 0;
}
- if (len < hdrlen){
+ hdrlen = ipv6_optlen(rh);
+ if (skb->len - ptr < hdrlen){
/* Pcket smaller than its length field */
return 0;
}
- rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
- BUG_ON(rh == NULL);
-
DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
DEBUGP("TYPE %04X ", rh->type);
DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5aa3691..a1265a3 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -627,7 +627,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
if (type && code) {
get_user(fl->fl_icmp_type, type);
- __get_user(fl->fl_icmp_code, code);
+ get_user(fl->fl_icmp_code, code);
probed = 1;
}
break;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 69b1468..6001948 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -405,9 +405,8 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
continue;
if (!ipv6_addr_any(&np->rcv_saddr)) {
- if (ipv6_addr_equal(&np->rcv_saddr, loc_addr))
- return s;
- continue;
+ if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr))
+ continue;
}
if(!inet6_mc_check(s, loc_addr, rmt_addr))
continue;
@@ -640,6 +639,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
int tclass = -1;
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
int err;
+ int connected = 0;
/* destination address check */
if (sin6) {
@@ -749,6 +749,7 @@ do_udp_sendmsg:
fl->fl_ip_dport = inet->dport;
daddr = &np->daddr;
fl->fl6_flowlabel = np->flow_label;
+ connected = 1;
}
if (!fl->oif)
@@ -771,6 +772,7 @@ do_udp_sendmsg:
}
if (!(opt->opt_nflen|opt->opt_flen))
opt = NULL;
+ connected = 0;
}
if (opt == NULL)
opt = np->opt;
@@ -788,10 +790,13 @@ do_udp_sendmsg:
ipv6_addr_copy(&final, &fl->fl6_dst);
ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
final_p = &final;
+ connected = 0;
}
- if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
+ if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) {
fl->oif = np->mcast_oif;
+ connected = 0;
+ }
err = ip6_dst_lookup(sk, &dst, fl);
if (err)
@@ -847,7 +852,7 @@ do_append_data:
else if (!corkreq)
err = udp_v6_push_pending_frames(sk, up);
- if (dst)
+ if (dst && connected)
ip6_dst_store(sk, dst,
ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ?
&np->daddr : NULL);
diff --git a/net/socket.c b/net/socket.c
index c699e93..f926447 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1862,7 +1862,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag
if (err < 0)
goto out_freeiov;
}
- err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg));
+ err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT),
+ COMPAT_FLAGS(msg));
if (err)
goto out_freeiov;
if (MSG_CMSG_COMPAT & flags)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 51885b5..30ec3ef 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -512,15 +512,14 @@ svc_sock_setbufsize(struct socket *sock, unsigned int snd, unsigned int rcv)
static void
svc_udp_data_ready(struct sock *sk, int count)
{
- struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
- if (!svsk)
- goto out;
- dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
- svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags));
- set_bit(SK_DATA, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
+ if (svsk) {
+ dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
+ svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags));
+ set_bit(SK_DATA, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
+ }
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible(sk->sk_sleep);
}
@@ -540,7 +539,7 @@ svc_write_space(struct sock *sk)
}
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) {
- printk(KERN_WARNING "RPC svc_write_space: some sleeping on %p\n",
+ dprintk("RPC svc_write_space: someone sleeping on %p\n",
svsk);
wake_up_interruptible(sk->sk_sleep);
}
@@ -692,31 +691,29 @@ svc_udp_init(struct svc_sock *svsk)
static void
svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
{
- struct svc_sock *svsk;
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
dprintk("svc: socket %p TCP (listen) state change %d\n",
- sk, sk->sk_state);
+ sk, sk->sk_state);
- if (sk->sk_state != TCP_LISTEN) {
- /*
- * This callback may called twice when a new connection
- * is established as a child socket inherits everything
- * from a parent LISTEN socket.
- * 1) data_ready method of the parent socket will be called
- * when one of child sockets become ESTABLISHED.
- * 2) data_ready method of the child socket may be called
- * when it receives data before the socket is accepted.
- * In case of 2, we should ignore it silently.
- */
- goto out;
- }
- if (!(svsk = (struct svc_sock *) sk->sk_user_data)) {
- printk("svc: socket %p: no user data\n", sk);
- goto out;
+ /*
+ * This callback may called twice when a new connection
+ * is established as a child socket inherits everything
+ * from a parent LISTEN socket.
+ * 1) data_ready method of the parent socket will be called
+ * when one of child sockets become ESTABLISHED.
+ * 2) data_ready method of the child socket may be called
+ * when it receives data before the socket is accepted.
+ * In case of 2, we should ignore it silently.
+ */
+ if (sk->sk_state == TCP_LISTEN) {
+ if (svsk) {
+ set_bit(SK_CONN, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
+ } else
+ printk("svc: socket %p: no user data\n", sk);
}
- set_bit(SK_CONN, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
+
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible_all(sk->sk_sleep);
}
@@ -727,18 +724,17 @@ svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
static void
svc_tcp_state_change(struct sock *sk)
{
- struct svc_sock *svsk;
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n",
- sk, sk->sk_state, sk->sk_user_data);
+ sk, sk->sk_state, sk->sk_user_data);
- if (!(svsk = (struct svc_sock *) sk->sk_user_data)) {
+ if (!svsk)
printk("svc: socket %p: no user data\n", sk);
- goto out;
+ else {
+ set_bit(SK_CLOSE, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
}
- set_bit(SK_CLOSE, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible_all(sk->sk_sleep);
}
@@ -746,15 +742,14 @@ svc_tcp_state_change(struct sock *sk)
static void
svc_tcp_data_ready(struct sock *sk, int count)
{
- struct svc_sock * svsk;
+ struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
dprintk("svc: socket %p TCP data ready (svsk %p)\n",
- sk, sk->sk_user_data);
- if (!(svsk = (struct svc_sock *)(sk->sk_user_data)))
- goto out;
- set_bit(SK_DATA, &svsk->sk_flags);
- svc_sock_enqueue(svsk);
- out:
+ sk, sk->sk_user_data);
+ if (svsk) {
+ set_bit(SK_DATA, &svsk->sk_flags);
+ svc_sock_enqueue(svsk);
+ }
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
wake_up_interruptible(sk->sk_sleep);
}
diff --git a/security/Kconfig b/security/Kconfig
index dcf04a0..64d3f1e 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -35,6 +35,7 @@ config KEYS_DEBUG_PROC_KEYS
config SECURITY
bool "Enable different security models"
+ depends on SYSFS
help
This allows you to choose different security modules to be
configured into your kernel.
diff --git a/security/Makefile b/security/Makefile
index 197cc2f..8cbbf2f 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -11,7 +11,7 @@ obj-y += commoncap.o
endif
# Object file lists
-obj-$(CONFIG_SECURITY) += security.o dummy.o
+obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
diff --git a/security/inode.c b/security/inode.c
new file mode 100644
index 0000000..a596450
--- /dev/null
+++ b/security/inode.c
@@ -0,0 +1,347 @@
+/*
+ * inode.c - securityfs
+ *
+ * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * Based on fs/debugfs/inode.c which had the following copyright notice:
+ * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2004 IBM Inc.
+ */
+
+/* #define DEBUG */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/security.h>
+
+#define SECURITYFS_MAGIC 0x73636673
+
+static struct vfsmount *mount;
+static int mount_count;
+
+/*
+ * TODO:
+ * I think I can get rid of these default_file_ops, but not quite sure...
+ */
+static ssize_t default_read_file(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return 0;
+}
+
+static ssize_t default_write_file(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+ if (inode->u.generic_ip)
+ file->private_data = inode->u.generic_ip;
+
+ return 0;
+}
+
+static struct file_operations default_file_ops = {
+ .read = default_read_file,
+ .write = default_write_file,
+ .open = default_open,
+};
+
+static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
+{
+ struct inode *inode = new_inode(sb);
+
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ switch (mode & S_IFMT) {
+ default:
+ init_special_inode(inode, mode, dev);
+ break;
+ case S_IFREG:
+ inode->i_fop = &default_file_ops;
+ break;
+ case S_IFDIR:
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ break;
+ }
+ }
+ return inode;
+}
+
+/* SMP-safe */
+static int mknod(struct inode *dir, struct dentry *dentry,
+ int mode, dev_t dev)
+{
+ struct inode *inode;
+ int error = -EPERM;
+
+ if (dentry->d_inode)
+ return -EEXIST;
+
+ inode = get_inode(dir->i_sb, mode, dev);
+ if (inode) {
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ error = 0;
+ }
+ return error;
+}
+
+static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int res;
+
+ mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
+ res = mknod(dir, dentry, mode, 0);
+ if (!res)
+ dir->i_nlink++;
+ return res;
+}
+
+static int create(struct inode *dir, struct dentry *dentry, int mode)
+{
+ mode = (mode & S_IALLUGO) | S_IFREG;
+ return mknod(dir, dentry, mode, 0);
+}
+
+static inline int positive(struct dentry *dentry)
+{
+ return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static int fill_super(struct super_block *sb, void *data, int silent)
+{
+ static struct tree_descr files[] = {{""}};
+
+ return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+}
+
+static struct super_block *get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
+{
+ return get_sb_single(fs_type, flags, data, fill_super);
+}
+
+static struct file_system_type fs_type = {
+ .owner = THIS_MODULE,
+ .name = "securityfs",
+ .get_sb = get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+static int create_by_name(const char *name, mode_t mode,
+ struct dentry *parent,
+ struct dentry **dentry)
+{
+ int error = 0;
+
+ *dentry = NULL;
+
+ /* If the parent is not specified, we create it in the root.
+ * We need the root dentry to do this, which is in the super
+ * block. A pointer to that is in the struct vfsmount that we
+ * have around.
+ */
+ if (!parent ) {
+ if (mount && mount->mnt_sb) {
+ parent = mount->mnt_sb->s_root;
+ }
+ }
+ if (!parent) {
+ pr_debug("securityfs: Ah! can not find a parent!\n");
+ return -EFAULT;
+ }
+
+ down(&parent->d_inode->i_sem);
+ *dentry = lookup_one_len(name, parent, strlen(name));
+ if (!IS_ERR(dentry)) {
+ if ((mode & S_IFMT) == S_IFDIR)
+ error = mkdir(parent->d_inode, *dentry, mode);
+ else
+ error = create(parent->d_inode, *dentry, mode);
+ } else
+ error = PTR_ERR(dentry);
+ up(&parent->d_inode->i_sem);
+
+ return error;
+}
+
+/**
+ * securityfs_create_file - create a file in the securityfs filesystem
+ *
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this paramater is NULL, then the
+ * file will be created in the root of the securityfs filesystem.
+ * @data: a pointer to something that the caller will want to get to later
+ * on. The inode.u.generic_ip pointer will point to this value on
+ * the open() call.
+ * @fops: a pointer to a struct file_operations that should be used for
+ * this file.
+ *
+ * This is the basic "create a file" function for securityfs. It allows for a
+ * wide range of flexibility in createing a file, or a directory (if you
+ * want to create a directory, the securityfs_create_dir() function is
+ * recommended to be used instead.)
+ *
+ * This function will return a pointer to a dentry if it succeeds. This
+ * pointer must be passed to the securityfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.) If an error occurs, NULL will be returned.
+ *
+ * If securityfs is not enabled in the kernel, the value -ENODEV will be
+ * returned. It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *securityfs_create_file(const char *name, mode_t mode,
+ struct dentry *parent, void *data,
+ struct file_operations *fops)
+{
+ struct dentry *dentry = NULL;
+ int error;
+
+ pr_debug("securityfs: creating file '%s'\n",name);
+
+ error = simple_pin_fs("securityfs", &mount, &mount_count);
+ if (error) {
+ dentry = ERR_PTR(error);
+ goto exit;
+ }
+
+ error = create_by_name(name, mode, parent, &dentry);
+ if (error) {
+ dentry = ERR_PTR(error);
+ simple_release_fs(&mount, &mount_count);
+ goto exit;
+ }
+
+ if (dentry->d_inode) {
+ if (fops)
+ dentry->d_inode->i_fop = fops;
+ if (data)
+ dentry->d_inode->u.generic_ip = data;
+ }
+exit:
+ return dentry;
+}
+EXPORT_SYMBOL_GPL(securityfs_create_file);
+
+/**
+ * securityfs_create_dir - create a directory in the securityfs filesystem
+ *
+ * @name: a pointer to a string containing the name of the directory to
+ * create.
+ * @parent: a pointer to the parent dentry for this file. This should be a
+ * directory dentry if set. If this paramater is NULL, then the
+ * directory will be created in the root of the securityfs filesystem.
+ *
+ * This function creates a directory in securityfs with the given name.
+ *
+ * This function will return a pointer to a dentry if it succeeds. This
+ * pointer must be passed to the securityfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.) If an error occurs, NULL will be returned.
+ *
+ * If securityfs is not enabled in the kernel, the value -ENODEV will be
+ * returned. It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
+{
+ return securityfs_create_file(name,
+ S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+ parent, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(securityfs_create_dir);
+
+/**
+ * securityfs_remove - removes a file or directory from the securityfs filesystem
+ *
+ * @dentry: a pointer to a the dentry of the file or directory to be
+ * removed.
+ *
+ * This function removes a file or directory in securityfs that was previously
+ * created with a call to another securityfs function (like
+ * securityfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void securityfs_remove(struct dentry *dentry)
+{
+ struct dentry *parent;
+
+ if (!dentry)
+ return;
+
+ parent = dentry->d_parent;
+ if (!parent || !parent->d_inode)
+ return;
+
+ down(&parent->d_inode->i_sem);
+ if (positive(dentry)) {
+ if (dentry->d_inode) {
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ simple_rmdir(parent->d_inode, dentry);
+ else
+ simple_unlink(parent->d_inode, dentry);
+ dput(dentry);
+ }
+ }
+ up(&parent->d_inode->i_sem);
+ simple_release_fs(&mount, &mount_count);
+}
+EXPORT_SYMBOL_GPL(securityfs_remove);
+
+static decl_subsys(security, NULL, NULL);
+
+static int __init securityfs_init(void)
+{
+ int retval;
+
+ kset_set_kset_s(&security_subsys, kernel_subsys);
+ retval = subsystem_register(&security_subsys);
+ if (retval)
+ return retval;
+
+ retval = register_filesystem(&fs_type);
+ if (retval)
+ subsystem_unregister(&security_subsys);
+ return retval;
+}
+
+static void __exit securityfs_exit(void)
+{
+ simple_release_fs(&mount, &mount_count);
+ unregister_filesystem(&fs_type);
+ subsystem_unregister(&security_subsys);
+}
+
+core_initcall(securityfs_init);
+module_exit(securityfs_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/security/seclvl.c b/security/seclvl.c
index 96b1f21..1caac01 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -119,69 +119,6 @@ MODULE_PARM_DESC(hideHash, "When set to 0, reading seclvl/passwd from sysfs "
} while (0)
/**
- * kobject stuff
- */
-
-struct subsystem seclvl_subsys;
-
-struct seclvl_obj {
- char *name;
- struct list_head slot_list;
- struct kobject kobj;
-};
-
-/**
- * There is a seclvl_attribute struct for each file in sysfs.
- *
- * In our case, we have one of these structs for "passwd" and another
- * for "seclvl".
- */
-struct seclvl_attribute {
- struct attribute attr;
- ssize_t(*show) (struct seclvl_obj *, char *);
- ssize_t(*store) (struct seclvl_obj *, const char *, size_t);
-};
-
-/**
- * When this function is called, one of the files in sysfs is being
- * written to. attribute->store is a function pointer to whatever the
- * struct seclvl_attribute store function pointer points to. It is
- * unique for "passwd" and "seclvl".
- */
-static ssize_t
-seclvl_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t len)
-{
- struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
- struct seclvl_attribute *attribute =
- container_of(attr, struct seclvl_attribute, attr);
- return attribute->store ? attribute->store(obj, buf, len) : -EIO;
-}
-
-static ssize_t
-seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
- struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
- struct seclvl_attribute *attribute =
- container_of(attr, struct seclvl_attribute, attr);
- return attribute->show ? attribute->show(obj, buf) : -EIO;
-}
-
-/**
- * Callback function pointers for show and store
- */
-static struct sysfs_ops seclvlfs_sysfs_ops = {
- .show = seclvl_attr_show,
- .store = seclvl_attr_store,
-};
-
-static struct kobj_type seclvl_ktype = {
- .sysfs_ops = &seclvlfs_sysfs_ops
-};
-
-decl_subsys(seclvl, &seclvl_ktype, NULL);
-
-/**
* The actual security level. Ranges between -1 and 2 inclusive.
*/
static int seclvl;
@@ -213,97 +150,44 @@ static int seclvl_sanity(int reqlvl)
}
/**
- * Called whenever the user reads the sysfs handle to this kernel
- * object
- */
-static ssize_t seclvl_read_file(struct seclvl_obj *obj, char *buff)
-{
- return snprintf(buff, PAGE_SIZE, "%d\n", seclvl);
-}
-
-/**
* security level advancement rules:
* Valid levels are -1 through 2, inclusive.
* From -1, stuck. [ in case compiled into kernel ]
* From 0 or above, can only increment.
*/
-static int do_seclvl_advance(int newlvl)
+static void do_seclvl_advance(void *data, u64 val)
{
- if (newlvl <= seclvl) {
- seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
- "[%d]\n", newlvl);
- return -EINVAL;
- }
+ int ret;
+ int newlvl = (int)val;
+
+ ret = seclvl_sanity(newlvl);
+ if (ret)
+ return;
+
if (newlvl > 2) {
seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
"[%d]\n", newlvl);
- return -EINVAL;
+ return;
}
if (seclvl == -1) {
seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "
"seclvl [%d]\n", seclvl);
- return -EPERM;
+ return;
}
- seclvl = newlvl;
- return 0;
+ seclvl = newlvl; /* would it be more "correct" to set *data? */
+ return;
}
-/**
- * Called whenever the user writes to the sysfs handle to this kernel
- * object (seclvl/seclvl). It expects a single-digit number.
- */
-static ssize_t
-seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count)
+static u64 seclvl_int_get(void *data)
{
- unsigned long val;
- if (count > 2 || (count == 2 && buff[1] != '\n')) {
- seclvl_printk(1, KERN_WARNING, "Invalid value passed to "
- "seclvl: [%s]\n", buff);
- return -EINVAL;
- }
- val = buff[0] - 48;
- if (seclvl_sanity(val)) {
- seclvl_printk(1, KERN_WARNING, "Illegal secure level "
- "requested: [%d]\n", (int)val);
- return -EPERM;
- }
- if (do_seclvl_advance(val)) {
- seclvl_printk(0, KERN_ERR, "Failure advancing security level "
- "to %lu\n", val);
- }
- return count;
+ return *(int *)data;
}
-/* Generate sysfs_attr_seclvl */
-static struct seclvl_attribute sysfs_attr_seclvl =
-__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file,
- seclvl_write_file);
+DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n");
static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
/**
- * Called whenever the user reads the sysfs passwd handle.
- */
-static ssize_t seclvl_read_passwd(struct seclvl_obj *obj, char *buff)
-{
- /* So just how good *is* your password? :-) */
- char tmp[3];
- int i = 0;
- buff[0] = '\0';
- if (hideHash) {
- /* Security through obscurity */
- return 0;
- }
- while (i < SHA1_DIGEST_SIZE) {
- snprintf(tmp, 3, "%02x", hashedPassword[i]);
- strncat(buff, tmp, 2);
- i++;
- }
- strcat(buff, "\n");
- return ((SHA1_DIGEST_SIZE * 2) + 1);
-}
-
-/**
* Converts a block of plaintext of into its SHA1 hashed value.
*
* It would be nice if crypto had a wrapper to do this for us linear
@@ -347,12 +231,15 @@ plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len)
* object. It hashes the password and compares the hashed results.
*/
static ssize_t
-seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
+passwd_write_file(struct file * file, const char __user * buf,
+ size_t count, loff_t *ppos)
{
int i;
unsigned char tmp[SHA1_DIGEST_SIZE];
+ char *page;
int rc;
int len;
+
if (!*passwd && !*sha1_passwd) {
seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
"seclvl module, but neither a plain text "
@@ -363,32 +250,45 @@ seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
"maintainer about this event.\n");
return -EINVAL;
}
- len = strlen(buff);
+
+ if (count < 0 || count >= PAGE_SIZE)
+ return -EINVAL;
+ if (*ppos != 0)
+ return -EINVAL;
+ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ len = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out;
+
+ len = strlen(page);
/* ``echo "secret" > seclvl/passwd'' includes a newline */
- if (buff[len - 1] == '\n') {
+ if (page[len - 1] == '\n')
len--;
- }
/* Hash the password, then compare the hashed values */
- if ((rc = plaintext_to_sha1(tmp, buff, len))) {
+ if ((rc = plaintext_to_sha1(tmp, page, len))) {
seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
"[%d]\n", rc);
return rc;
}
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
- if (hashedPassword[i] != tmp[i]) {
+ if (hashedPassword[i] != tmp[i])
return -EPERM;
- }
}
seclvl_printk(0, KERN_INFO,
"Password accepted; seclvl reduced to 0.\n");
seclvl = 0;
- return count;
+ len = count;
+
+out:
+ free_page((unsigned long)page);
+ return len;
}
-/* Generate sysfs_attr_passwd */
-static struct seclvl_attribute sysfs_attr_passwd =
-__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd,
- seclvl_write_passwd);
+static struct file_operations passwd_file_ops = {
+ .write = passwd_write_file,
+};
/**
* Explicitely disallow ptrace'ing the init process.
@@ -579,9 +479,8 @@ static void seclvl_file_free_security(struct file *filp)
*/
static int seclvl_umount(struct vfsmount *mnt, int flags)
{
- if (current->pid == 1) {
+ if (current->pid == 1)
return 0;
- }
if (seclvl == 2) {
seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure "
"level %d\n", seclvl);
@@ -647,22 +546,34 @@ static int processPassword(void)
}
/**
- * Sysfs registrations
+ * securityfs registrations
*/
-static int doSysfsRegistrations(void)
+struct dentry *dir_ino, *seclvl_ino, *passwd_ino;
+
+static int seclvlfs_register(void)
{
- int rc = 0;
- if ((rc = subsystem_register(&seclvl_subsys))) {
- seclvl_printk(0, KERN_WARNING,
- "Error [%d] registering seclvl subsystem\n", rc);
- return rc;
- }
- sysfs_create_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
+ dir_ino = securityfs_create_dir("seclvl", NULL);
+ if (!dir_ino)
+ return -EFAULT;
+
+ seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,
+ dir_ino, &seclvl, &seclvl_file_ops);
+ if (!seclvl_ino)
+ goto out_deldir;
if (*passwd || *sha1_passwd) {
- sysfs_create_file(&seclvl_subsys.kset.kobj,
- &sysfs_attr_passwd.attr);
+ passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,
+ dir_ino, NULL, &passwd_file_ops);
+ if (!passwd_ino)
+ goto out_delf;
}
return 0;
+
+out_deldir:
+ securityfs_remove(dir_ino);
+out_delf:
+ securityfs_remove(seclvl_ino);
+
+ return -EFAULT;
}
/**
@@ -677,8 +588,6 @@ static int __init seclvl_init(void)
rc = -EINVAL;
goto exit;
}
- sysfs_attr_seclvl.attr.owner = THIS_MODULE;
- sysfs_attr_passwd.attr.owner = THIS_MODULE;
if (initlvl < -1 || initlvl > 2) {
seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "
"[%d].\n", initlvl);
@@ -706,7 +615,7 @@ static int __init seclvl_init(void)
} /* if primary module registered */
secondary = 1;
} /* if we registered ourselves with the security framework */
- if ((rc = doSysfsRegistrations())) {
+ if ((rc = seclvlfs_register())) {
seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
goto exit;
}
@@ -724,12 +633,10 @@ static int __init seclvl_init(void)
*/
static void __exit seclvl_exit(void)
{
- sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
- if (*passwd || *sha1_passwd) {
- sysfs_remove_file(&seclvl_subsys.kset.kobj,
- &sysfs_attr_passwd.attr);
- }
- subsystem_unregister(&seclvl_subsys);
+ securityfs_remove(seclvl_ino);
+ if (*passwd || *sha1_passwd)
+ securityfs_remove(passwd_ino);
+ securityfs_remove(dir_ino);
if (secondary == 1) {
mod_unreg_security(MY_NAME, &seclvl_ops);
} else if (unregister_security(&seclvl_ops)) {
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index cf6020f..12e4fb7 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -242,7 +242,7 @@ void __init avc_init(void)
avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
0, SLAB_PANIC, NULL, NULL);
- audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n");
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n");
}
int avc_get_hash_stats(char *page)
@@ -550,7 +550,7 @@ void avc_audit(u32 ssid, u32 tsid,
return;
}
- ab = audit_log_start(current->audit_context, AUDIT_AVC);
+ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f40c822..6e4937f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3389,7 +3389,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
if (err) {
if (err == -EINVAL) {
- audit_log(current->audit_context, AUDIT_SELINUX_ERR,
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
"SELinux: unrecognized netlink message"
" type=%hu for sclass=%hu\n",
nlh->nlmsg_type, isec->sclass);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 92b89dc..aecdded 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -381,7 +381,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
goto out;
if (context_struct_to_string(tcontext, &t, &tlen) < 0)
goto out;
- audit_log(current->audit_context, AUDIT_SELINUX_ERR,
+ audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
"security_validate_transition: denied for"
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
o, n, t, policydb.p_class_val_to_name[tclass-1]);
@@ -787,7 +787,7 @@ static int compute_sid_handle_invalid_context(
goto out;
if (context_struct_to_string(newcontext, &n, &nlen) < 0)
goto out;
- audit_log(current->audit_context, AUDIT_SELINUX_ERR,
+ audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
"security_compute_sid: invalid context %s"
" for scontext=%s"
" tcontext=%s"
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 2e4a5e0..0864a7c 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -7,6 +7,7 @@ config SND_SA11XX_UDA1341
tristate "SA11xx UDA1341TS driver (iPaq H3600)"
depends on ARCH_SA1100 && SND && L3
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here if you have a Compaq iPaq H3x00 handheld computer
and want to use its Philips UDA 1341 audio chip.
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 9887703..b2d5db2 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -650,7 +650,7 @@ static int aaci_do_resume(snd_card_t *card, unsigned int state)
return 0;
}
-static int aaci_suspend(struct amba_device *dev, u32 state)
+static int aaci_suspend(struct amba_device *dev, pm_message_t state)
{
snd_card_t *card = amba_get_drvdata(dev);
return card ? aaci_do_suspend(card) : 0;
@@ -900,6 +900,8 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
if (ret)
goto out;
+ snd_card_set_dev(aaci->card, &dev->dev);
+
ret = snd_card_register(aaci->card);
if (ret == 0) {
dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 174bc03..6ee9122 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -21,7 +21,7 @@
* merged HAL layer (patches from Brian)
*/
-/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.23 2005/09/09 13:22:34 tiwai Exp $ */
/***************************************************************************************************
*
@@ -918,7 +918,7 @@ static int __init sa11xx_uda1341_init(void)
if (card == NULL)
return -ENOMEM;
- sa11xx_uda1341 = kcalloc(1, sizeof(*sa11xx_uda1341), GFP_KERNEL);
+ sa11xx_uda1341 = kzalloc(sizeof(*sa11xx_uda1341), GFP_KERNEL);
if (sa11xx_uda1341 == NULL)
return -ENOMEM;
spin_lock_init(&chip->s[0].dma_lock);
@@ -946,6 +946,9 @@ static int __init sa11xx_uda1341_init(void)
strcpy(card->shortname, "H3600 UDA1341TS");
sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS");
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto nodev;
+
if ((err = snd_card_register(card)) == 0) {
printk( KERN_INFO "iPAQ audio support initialized\n" );
return 0;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index d1e800b..48cf45c 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -99,6 +99,18 @@ config SND_RTCTIMER
To compile this driver as a module, choose M here: the module
will be called snd-rtctimer.
+config SND_SEQ_RTCTIMER_DEFAULT
+ bool "Use RTC as default sequencer timer"
+ depends on SND_RTCTIMER && SND_SEQUENCER
+ default y
+ help
+ Say Y here to use the RTC timer as the default sequencer
+ timer. This is strongly recommended because it ensures
+ precise MIDI timing even when the system timer runs at less
+ than 1000 Hz.
+
+ If in doubt, say Y.
+
config SND_VERBOSE_PRINTK
bool "Verbose printk"
depends on SND
@@ -128,6 +140,6 @@ config SND_DEBUG_DETECT
Say Y here to enable extra-verbose log messages printed when
detecting devices.
-config SND_GENERIC_PM
+config SND_GENERIC_DRIVER
bool
depends on SND
diff --git a/sound/core/control.c b/sound/core/control.c
index 227f3cf..736edf3 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -69,7 +69,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
err = -EFAULT;
goto __error2;
}
- ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL);
+ ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
if (ctl == NULL) {
err = -ENOMEM;
goto __error;
@@ -162,7 +162,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
goto _found;
}
}
- ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC);
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (ev) {
ev->id = *id;
ev->mask = mask;
@@ -195,7 +195,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
snd_runtime_check(control != NULL, return NULL);
snd_runtime_check(control->count > 0, return NULL);
- kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
+ kctl = kzalloc(sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
if (kctl == NULL)
return NULL;
*kctl = *control;
@@ -521,7 +521,7 @@ static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
{
snd_ctl_card_info_t *info;
- info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
down_read(&snd_ioctl_rwsem);
@@ -929,7 +929,7 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int
return -EINVAL;
}
private_size *= info->count;
- ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL);
+ ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
if (ue == NULL)
return -ENOMEM;
ue->info = *info;
@@ -1185,7 +1185,7 @@ static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *
{
snd_kctl_ioctl_t *pn;
- pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
+ pn = kzalloc(sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
if (pn == NULL)
return -ENOMEM;
pn->fioctl = fcn;
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 7fdabea..207c7de 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -92,7 +92,7 @@ static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_i
struct sndrv_ctl_elem_info *data;
int err;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
@@ -271,7 +271,7 @@ static int snd_ctl_elem_read_user_compat(snd_card_t *card,
struct sndrv_ctl_elem_value *data;
int err, type, count;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -291,7 +291,7 @@ static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file,
struct sndrv_ctl_elem_value *data;
int err, type, count;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -313,7 +313,7 @@ static int snd_ctl_elem_add_compat(snd_ctl_file_t *file,
struct sndrv_ctl_elem_info *data;
int err;
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (! data)
return -ENOMEM;
diff --git a/sound/core/device.c b/sound/core/device.c
index ca00ad7..1f509f5 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -49,7 +49,7 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type,
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
snd_assert(ops != NULL, return -ENXIO);
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
dev->card = card;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 997dd41..9383f12 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -359,7 +359,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
snd_assert(rhwdep != NULL, return -EINVAL);
*rhwdep = NULL;
snd_assert(card != NULL, return -ENXIO);
- hwdep = kcalloc(1, sizeof(*hwdep), GFP_KERNEL);
+ hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
if (hwdep == NULL)
return -ENOMEM;
hwdep->card = card;
diff --git a/sound/core/info.c b/sound/core/info.c
index 7f8bdf7..37024d6 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -295,7 +295,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
goto __error;
}
}
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL) {
err = -ENOMEM;
goto __error;
@@ -304,7 +304,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
switch (entry->content) {
case SNDRV_INFO_CONTENT_TEXT:
if (mode == O_RDONLY || mode == O_RDWR) {
- buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
kfree(data);
err = -ENOMEM;
@@ -323,7 +323,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
data->rbuffer = buffer;
}
if (mode == O_WRONLY || mode == O_RDWR) {
- buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (buffer == NULL) {
if (mode == O_RDWR) {
vfree(data->rbuffer->buffer);
@@ -752,7 +752,7 @@ char *snd_info_get_str(char *dest, char *src, int len)
static snd_info_entry_t *snd_info_create_entry(const char *name)
{
snd_info_entry_t *entry;
- entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (entry == NULL)
return NULL;
entry->name = kstrdup(name, GFP_KERNEL);
diff --git a/sound/core/init.c b/sound/core/init.c
index d72f58f..a570201 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -72,7 +72,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
if (extra_size < 0)
extra_size = 0;
- card = kcalloc(1, sizeof(*card) + extra_size, GFP_KERNEL);
+ card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
if (card == NULL)
return NULL;
if (xid) {
@@ -226,8 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
return 0;
}
-#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
-static void snd_generic_device_unregister(struct snd_generic_device *dev);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+static void snd_generic_device_unregister(snd_card_t *card);
+#else
+#define snd_generic_device_unregister(x) /*NOP*/
#endif
/**
@@ -253,14 +255,7 @@ int snd_card_free(snd_card_t * card)
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
-#ifdef CONFIG_SND_GENERIC_PM
- if (card->pm_dev) {
- snd_generic_device_unregister(card->pm_dev);
- card->pm_dev = NULL;
- }
-#endif
#endif
-
/* wait, until all devices are ready for the free operation */
wait_event(card->shutdown_sleep, card->files == NULL);
@@ -288,6 +283,7 @@ int snd_card_free(snd_card_t * card)
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
+ snd_generic_device_unregister(card);
while (card->s_f_ops) {
s_f_ops = card->s_f_ops;
card->s_f_ops = s_f_ops->next;
@@ -665,6 +661,96 @@ int snd_card_file_remove(snd_card_t *card, struct file *file)
return 0;
}
+#ifdef CONFIG_SND_GENERIC_DRIVER
+/*
+ * generic device without a proper bus using platform_device
+ * (e.g. ISA)
+ */
+struct snd_generic_device {
+ struct platform_device pdev;
+ snd_card_t *card;
+};
+
+#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
+
+#define SND_GENERIC_NAME "snd_generic"
+
+#ifdef CONFIG_PM
+static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
+static int snd_generic_resume(struct device *dev, u32 level);
+#endif
+
+/* initialized in sound.c */
+struct device_driver snd_generic_driver = {
+ .name = SND_GENERIC_NAME,
+ .bus = &platform_bus_type,
+#ifdef CONFIG_PM
+ .suspend = snd_generic_suspend,
+ .resume = snd_generic_resume,
+#endif
+};
+
+void snd_generic_device_release(struct device *dev)
+{
+}
+
+static int snd_generic_device_register(snd_card_t *card)
+{
+ struct snd_generic_device *dev;
+ int err;
+
+ if (card->generic_dev)
+ return 0; /* already registered */
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (! dev) {
+ snd_printk(KERN_ERR "can't allocate generic_device\n");
+ return -ENOMEM;
+ }
+
+ dev->pdev.name = SND_GENERIC_NAME;
+ dev->pdev.id = card->number;
+ dev->pdev.dev.release = snd_generic_device_release;
+ dev->card = card;
+ if ((err = platform_device_register(&dev->pdev)) < 0) {
+ kfree(dev);
+ return err;
+ }
+ card->generic_dev = dev;
+ return 0;
+}
+
+static void snd_generic_device_unregister(snd_card_t *card)
+{
+ struct snd_generic_device *dev = card->generic_dev;
+ if (dev) {
+ platform_device_unregister(&dev->pdev);
+ kfree(dev);
+ card->generic_dev = NULL;
+ }
+}
+
+/**
+ * snd_card_set_generic_dev - assign the generic device to the card
+ * @card: soundcard structure
+ *
+ * Assigns a generic device to the card. This function is provided as the
+ * last resort, for devices without any proper bus. Thus this won't override
+ * the device already assigned to the card.
+ *
+ * Returns zero if successful, or a negative error code.
+ */
+int snd_card_set_generic_dev(snd_card_t *card)
+{
+ int err;
+ if ((err = snd_generic_device_register(card)) < 0)
+ return err;
+ if (! card->dev)
+ snd_card_set_dev(card, &card->generic_dev->pdev.dev);
+ return 0;
+}
+#endif /* CONFIG_SND_GENERIC_DRIVER */
+
#ifdef CONFIG_PM
/**
* snd_power_wait - wait until the power-state is changed.
@@ -730,75 +816,7 @@ int snd_card_set_pm_callback(snd_card_t *card,
return 0;
}
-#ifdef CONFIG_SND_GENERIC_PM
-/*
- * use platform_device for generic power-management without a proper bus
- * (e.g. ISA)
- */
-struct snd_generic_device {
- struct platform_device pdev;
- snd_card_t *card;
-};
-
-#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
-
-#define SND_GENERIC_NAME "snd_generic_pm"
-
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
-static int snd_generic_resume(struct device *dev, u32 level);
-
-static struct device_driver snd_generic_driver = {
- .name = SND_GENERIC_NAME,
- .bus = &platform_bus_type,
- .suspend = snd_generic_suspend,
- .resume = snd_generic_resume,
-};
-
-static int generic_driver_registered;
-
-static void generic_driver_unregister(void)
-{
- if (generic_driver_registered) {
- generic_driver_registered--;
- if (! generic_driver_registered)
- driver_unregister(&snd_generic_driver);
- }
-}
-
-static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
-{
- struct snd_generic_device *dev;
-
- if (! generic_driver_registered) {
- if (driver_register(&snd_generic_driver) < 0)
- return NULL;
- }
- generic_driver_registered++;
-
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
- if (! dev) {
- generic_driver_unregister();
- return NULL;
- }
-
- dev->pdev.name = SND_GENERIC_NAME;
- dev->pdev.id = card->number;
- dev->card = card;
- if (platform_device_register(&dev->pdev) < 0) {
- kfree(dev);
- generic_driver_unregister();
- return NULL;
- }
- return dev;
-}
-
-static void snd_generic_device_unregister(struct snd_generic_device *dev)
-{
- platform_device_unregister(&dev->pdev);
- kfree(dev);
- generic_driver_unregister();
-}
-
+#ifdef CONFIG_SND_GENERIC_DRIVER
/* suspend/resume callbacks for snd_generic platform device */
static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level)
{
@@ -846,13 +864,12 @@ int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*resume)(snd_card_t *),
void *private_data)
{
- card->pm_dev = snd_generic_device_register(card);
- if (! card->pm_dev)
- return -ENOMEM;
- snd_card_set_pm_callback(card, suspend, resume, private_data);
- return 0;
+ int err;
+ if ((err = snd_generic_device_register(card)) < 0)
+ return err;
+ return snd_card_set_pm_callback(card, suspend, resume, private_data);
}
-#endif /* CONFIG_SND_GENERIC_PM */
+#endif /* CONFIG_SND_GENERIC_DRIVER */
#ifdef CONFIG_PCI
int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 39a54a4..91124dd 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -590,7 +590,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
alloced = 0;
pci = NULL;
- while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
+ while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
if (mask > 0 && mask < 0xffffffff) {
if (pci_set_dma_mask(pci, mask) < 0 ||
pci_set_consistent_dma_mask(pci, mask) < 0) {
@@ -604,6 +604,7 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, &dmab) < 0) {
printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+ pci_dev_put(pci);
return (int)count;
}
snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 291b476..8fa888f 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -249,7 +249,7 @@ int __exit snd_memory_info_done(void)
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
{
#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_to_user(dst, (const void*)src, count) ? -EFAULT : 0;
+ return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0;
#else
char buf[256];
while (count) {
@@ -280,7 +280,7 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
{
#if defined(__i386__) || defined(CONFIG_SPARC32)
- return copy_from_user((void*)dst, src, count) ? -EFAULT : 0;
+ return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0;
#else
char buf[256];
while (count) {
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 98fc076..69e1059 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -53,7 +53,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
err = snd_card_file_add(card, file);
if (err < 0)
return err;
- fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
+ fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
if (fmixer == NULL) {
snd_card_file_remove(card, file);
return -ENOMEM;
@@ -517,8 +517,8 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
up_read(&card->controls_rwsem);
return;
}
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -551,8 +551,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
up_read(&card->controls_rwsem);
return;
}
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -612,8 +612,8 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
down_read(&card->controls_rwsem);
if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
return;
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -649,8 +649,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
up_read(&fmixer->card->controls_rwsem);
return;
}
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -768,8 +768,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
snd_ctl_elem_value_t *uctl;
int err, idx;
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
@@ -813,8 +813,8 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
int err;
unsigned int idx;
- uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index a13bd7b..842c28b 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -850,7 +850,9 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer > 0 ? xfer : -EAGAIN;
}
} else {
- tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
+ tmp = snd_pcm_oss_write2(substream,
+ (const char __force *)buf,
+ runtime->oss.period_bytes, 0);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
@@ -926,7 +928,8 @@ static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *bu
xfer += tmp;
runtime->oss.buffer_used -= tmp;
} else {
- tmp = snd_pcm_oss_read2(substream, (char *)buf, runtime->oss.period_bytes, 0);
+ tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
+ runtime->oss.period_bytes, 0);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
@@ -1540,7 +1543,11 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
} else {
delay = snd_pcm_oss_bytes(substream, delay);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+ snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ if (setup && setup->buggyptr)
+ info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+ else
+ info.blocks = (delay + fixup) / runtime->oss.period_bytes;
info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
} else {
delay += fixup;
@@ -1733,7 +1740,7 @@ static int snd_pcm_oss_open_file(struct file *file,
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
*rpcm_oss_file = NULL;
- pcm_oss_file = kcalloc(1, sizeof(*pcm_oss_file), GFP_KERNEL);
+ pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
if (pcm_oss_file == NULL)
return -ENOMEM;
@@ -2347,6 +2354,8 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
template.partialfrag = 1;
} else if (!strcmp(str, "no-silence")) {
template.nosilence = 1;
+ } else if (!strcmp(str, "buggy-ptr")) {
+ template.buggyptr = 1;
}
} while (*str);
if (setup == NULL) {
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6430410..fc23373 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -171,7 +171,7 @@ int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
snd_assert(plug != NULL, return -ENXIO);
snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
- plugin = kcalloc(1, sizeof(*plugin) + extra, GFP_KERNEL);
+ plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
if (plugin == NULL)
return -ENOMEM;
plugin->name = name;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9f4c920..1be470e 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -597,7 +597,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
}
prev = NULL;
for (idx = 0, prev = NULL; idx < substream_count; idx++) {
- substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
+ substream = kzalloc(sizeof(*substream), GFP_KERNEL);
if (substream == NULL)
return -ENOMEM;
substream->pcm = pcm;
@@ -657,7 +657,7 @@ int snd_pcm_new(snd_card_t * card, char *id, int device,
snd_assert(rpcm != NULL, return -EINVAL);
*rpcm = NULL;
snd_assert(card != NULL, return -ENXIO);
- pcm = kcalloc(1, sizeof(*pcm), GFP_KERNEL);
+ pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (pcm == NULL)
return -ENOMEM;
pcm->card = card;
@@ -795,7 +795,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
if (substream == NULL)
return -EAGAIN;
- runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);
+ runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
if (runtime == NULL)
return -ENOMEM;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 0082914..0503980 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -524,6 +524,9 @@ void snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_inte
/**
* snd_interval_div - refine the interval value with division
+ * @a: dividend
+ * @b: divisor
+ * @c: quotient
*
* c = a / b
*
@@ -555,7 +558,11 @@ void snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_inte
/**
* snd_interval_muldivk - refine the interval value
- *
+ * @a: dividend 1
+ * @b: dividend 2
+ * @k: divisor (as integer)
+ * @c: result
+ *
* c = a * b / k
*
* Returns non-zero if the value is changed, zero if not changed.
@@ -582,6 +589,10 @@ void snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
/**
* snd_interval_mulkdiv - refine the interval value
+ * @a: dividend 1
+ * @k: dividend 2 (as integer)
+ * @b: divisor
+ * @c: result
*
* c = a * k / b
*
@@ -618,6 +629,11 @@ void snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
/**
* snd_interval_ratnum - refine the interval value
+ * @i: interval to refine
+ * @rats_count: number of ratnum_t
+ * @rats: ratnum_t array
+ * @nump: pointer to store the resultant numerator
+ * @denp: pointer to store the resultant denominator
*
* Returns non-zero if the value is changed, zero if not changed.
*/
@@ -715,6 +731,11 @@ int snd_interval_ratnum(snd_interval_t *i,
/**
* snd_interval_ratden - refine the interval value
+ * @i: interval to refine
+ * @rats_count: number of ratden_t
+ * @rats: ratden_t array
+ * @nump: pointer to store the resultant numerator
+ * @denp: pointer to store the resultant denominator
*
* Returns non-zero if the value is changed, zero if not changed.
*/
@@ -936,6 +957,11 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
/**
* snd_pcm_hw_constraint_mask
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the mask
+ * @mask: the bitmap mask
+ *
+ * Apply the constraint of the given bitmap mask to a mask parameter.
*/
int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
u_int32_t mask)
@@ -951,6 +977,11 @@ int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t va
/**
* snd_pcm_hw_constraint_mask64
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the mask
+ * @mask: the 64bit bitmap mask
+ *
+ * Apply the constraint of the given bitmap mask to a mask parameter.
*/
int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
u_int64_t mask)
@@ -967,6 +998,10 @@ int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
/**
* snd_pcm_hw_constraint_integer
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the integer constraint
+ *
+ * Apply the constraint of integer to an interval parameter.
*/
int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var)
{
@@ -976,6 +1011,12 @@ int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
/**
* snd_pcm_hw_constraint_minmax
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the range
+ * @min: the minimal value
+ * @max: the maximal value
+ *
+ * Apply the min/max range constraint to an interval parameter.
*/
int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
unsigned int min, unsigned int max)
@@ -999,6 +1040,12 @@ static int snd_pcm_hw_rule_list(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_list
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the list constraint
+ * @l: list
+ *
+ * Apply the list of constraints to an interval parameter.
*/
int snd_pcm_hw_constraint_list(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1027,6 +1074,10 @@ static int snd_pcm_hw_rule_ratnums(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_ratnums
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the ratnums constraint
+ * @r: ratnums_t constriants
*/
int snd_pcm_hw_constraint_ratnums(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1054,6 +1105,10 @@ static int snd_pcm_hw_rule_ratdens(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_ratdens
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the ratdens constraint
+ * @r: ratdens_t constriants
*/
int snd_pcm_hw_constraint_ratdens(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1079,6 +1134,10 @@ static int snd_pcm_hw_rule_msbits(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_msbits
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @width: sample bits width
+ * @msbits: msbits width
*/
int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1101,6 +1160,10 @@ static int snd_pcm_hw_rule_step(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_constraint_step
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the step constraint
+ * @step: step size
*/
int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1126,6 +1189,9 @@ static int snd_pcm_hw_rule_pow2(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *
/**
* snd_pcm_hw_constraint_pow2
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the power-of-2 constraint
*/
int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
unsigned int cond,
@@ -1162,7 +1228,7 @@ static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
}
#if 0
-/**
+/*
* snd_pcm_hw_param_any
*/
int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
@@ -1185,7 +1251,7 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
}
#if 0
-/**
+/*
* snd_pcm_hw_params_any
*
* Fill PARAMS with full configuration space boundaries
@@ -1199,6 +1265,9 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
/**
* snd_pcm_hw_param_value
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the value for field PAR if it's fixed in configuration space
* defined by PARAMS. Return -EINVAL otherwise
@@ -1228,6 +1297,9 @@ static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_value_min
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the minimum value for field PAR.
*/
@@ -1251,6 +1323,9 @@ unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_value_max
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Return the maximum value for field PAR.
*/
@@ -1302,7 +1377,7 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
}
#if 0
-/**
+/*
* snd_pcm_hw_param_setinteger
*
* Inside configuration space defined by PARAMS remove from PAR all
@@ -1347,6 +1422,10 @@ static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_first
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values > minimum. Reduce configuration space accordingly.
@@ -1388,6 +1467,10 @@ static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_last
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values < maximum. Reduce configuration space accordingly.
@@ -1439,6 +1522,11 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_min
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: minimal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values < VAL. Reduce configuration space accordingly.
@@ -1494,6 +1582,11 @@ static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_max
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: maximal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values >= VAL + 1. Reduce configuration space accordingly.
@@ -1565,6 +1658,11 @@ int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_set
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS remove from PAR all
* values != VAL. Reduce configuration space accordingly.
@@ -1599,6 +1697,10 @@ static int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_mask
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: mask to apply
*
* Inside configuration space defined by PARAMS remove from PAR all values
* not contained in MASK. Reduce configuration space accordingly.
@@ -1671,6 +1773,11 @@ static int boundary_nearer(int min, int mindir,
/**
* snd_pcm_hw_param_near
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @best: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
*
* Inside configuration space defined by PARAMS set PAR to the available value
* nearest to VAL. Reduce configuration space accordingly.
@@ -1747,6 +1854,8 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
/**
* snd_pcm_hw_param_choose
+ * @pcm: PCM instance
+ * @params: the hw_params instance
*
* Choose one configuration from configuration space defined by PARAMS
* The configuration chosen is that obtained fixing in this order:
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 9a174fb..b3f5344 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -244,7 +244,7 @@ int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
/**
* snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams)
- * @substream: the pcm substream instance
+ * @pcm: the pcm instance
* @type: DMA type (SNDRV_DMA_TYPE_*)
* @data: DMA type dependant data
* @size: the requested pre-allocation size in bytes
@@ -321,7 +321,7 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
} else {
- dmab = kcalloc(1, sizeof(*dmab), GFP_KERNEL);
+ dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
if (! dmab)
return -ENOMEM;
dmab->dev = substream->dma_buffer.dev;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 03c1715..67abeba 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -859,6 +859,7 @@ static struct action_ops snd_pcm_action_start = {
/**
* snd_pcm_start
+ * @substream: the PCM substream instance
*
* Start all linked streams.
*/
@@ -908,6 +909,8 @@ static struct action_ops snd_pcm_action_stop = {
/**
* snd_pcm_stop
+ * @substream: the PCM substream instance
+ * @state: PCM state after stopping the stream
*
* Try to stop all running streams in the substream group.
* The state of each stream is changed to the given value after that unconditionally.
@@ -919,6 +922,7 @@ int snd_pcm_stop(snd_pcm_substream_t *substream, int state)
/**
* snd_pcm_drain_done
+ * @substream: the PCM substream
*
* Stop the DMA only when the given stream is playback.
* The state is changed to SETUP.
@@ -1040,6 +1044,7 @@ static struct action_ops snd_pcm_action_suspend = {
/**
* snd_pcm_suspend
+ * @substream: the PCM substream
*
* Trigger SUSPEND to all linked streams.
* After this call, all streams are changed to SUSPENDED state.
@@ -1057,6 +1062,7 @@ int snd_pcm_suspend(snd_pcm_substream_t *substream)
/**
* snd_pcm_suspend_all
+ * @pcm: the PCM instance
*
* Trigger SUSPEND to all substreams in the given pcm.
* After this call, all streams are changed to SUSPENDED state.
@@ -1272,6 +1278,9 @@ static struct action_ops snd_pcm_action_prepare = {
/**
* snd_pcm_prepare
+ * @substream: the PCM substream instance
+ *
+ * Prepare the PCM substream to be triggerable.
*/
int snd_pcm_prepare(snd_pcm_substream_t *substream)
{
@@ -1992,7 +2001,7 @@ static int snd_pcm_open_file(struct file *file,
snd_assert(rpcm_file != NULL, return -EINVAL);
*rpcm_file = NULL;
- pcm_file = kcalloc(1, sizeof(*pcm_file), GFP_KERNEL);
+ pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
if (pcm_file == NULL) {
return -ENOMEM;
}
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index edba411..7c20eaf 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -101,7 +101,7 @@ static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
{
snd_rawmidi_runtime_t *runtime;
- if ((runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL)) == NULL)
+ if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
return -ENOMEM;
spin_lock_init(&runtime->lock);
init_waitqueue_head(&runtime->sleep);
@@ -984,7 +984,9 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0);
+ count1 = snd_rawmidi_kernel_read1(substream,
+ (unsigned char __force *)buf,
+ count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
@@ -1107,7 +1109,7 @@ int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count)
/**
* snd_rawmidi_transmit - copy from the buffer to the device
* @substream: the rawmidi substream
- * @buf: the buffer pointer
+ * @buffer: the buffer pointer
* @count: the data size to transfer
*
* Copies data from the buffer to the device and advances the pointer.
@@ -1213,7 +1215,9 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0);
+ count1 = snd_rawmidi_kernel_write1(substream,
+ (unsigned char __force *)buf,
+ count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
@@ -1370,7 +1374,7 @@ static int snd_rawmidi_alloc_substreams(snd_rawmidi_t *rmidi,
INIT_LIST_HEAD(&stream->substreams);
for (idx = 0; idx < count; idx++) {
- substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
+ substream = kzalloc(sizeof(*substream), GFP_KERNEL);
if (substream == NULL)
return -ENOMEM;
substream->stream = direction;
@@ -1413,7 +1417,7 @@ int snd_rawmidi_new(snd_card_t * card, char *id, int device,
snd_assert(rrawmidi != NULL, return -EINVAL);
*rrawmidi = NULL;
snd_assert(card != NULL, return -ENXIO);
- rmidi = kcalloc(1, sizeof(*rmidi), GFP_KERNEL);
+ rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
if (rmidi == NULL)
return -ENOMEM;
rmidi->card = card;
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 32e91c6..207c2c5 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -61,7 +61,7 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
return -EFAULT;
*data += sizeof(xp);
*len -= sizeof(xp);
- wp = kcalloc(1, sizeof(*wp), gfp_mask);
+ wp = kzalloc(sizeof(*wp), gfp_mask);
if (wp == NULL)
return -ENOMEM;
wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 2622b86..b3cee09 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -92,7 +92,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
if (points_size > *len)
return -EINVAL;
- rp = kcalloc(1, sizeof(*rp) + points_size, gfp_mask);
+ rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
if (rp == NULL)
return -ENOMEM;
rp->nattack = le16_to_cpu(rx.nattack);
@@ -139,7 +139,7 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
return -EFAULT;
*data += sizeof(xp);
*len -= sizeof(xp);
- wp = kcalloc(1, sizeof(*wp), gfp_mask);
+ wp = kzalloc(sizeof(*wp), gfp_mask);
if (wp == NULL)
return -ENOMEM;
wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
@@ -273,7 +273,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
snd_seq_iwffff_instr_free(ops, ip, atomic);
return -EINVAL;
}
- lp = kcalloc(1, sizeof(*lp), gfp_mask);
+ lp = kzalloc(sizeof(*lp), gfp_mask);
if (lp == NULL) {
snd_seq_iwffff_instr_free(ops, ip, atomic);
return -ENOMEM;
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index bac4b4f..1ab1cf8 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -193,7 +193,7 @@ snd_seq_oss_open(struct file *file, int level)
int i, rc;
seq_oss_devinfo_t *dp;
- if ((dp = kcalloc(1, sizeof(*dp), GFP_KERNEL)) == NULL) {
+ if ((dp = kzalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc device info\n");
return -ENOMEM;
}
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 9aece6c..f0e95c8 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -76,8 +76,8 @@ snd_seq_oss_midi_lookup_ports(int client)
snd_seq_client_info_t *clinfo;
snd_seq_port_info_t *pinfo;
- clinfo = kcalloc(1, sizeof(*clinfo), GFP_KERNEL);
- pinfo = kcalloc(1, sizeof(*pinfo), GFP_KERNEL);
+ clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
+ pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
if (! clinfo || ! pinfo) {
kfree(clinfo);
kfree(pinfo);
@@ -172,7 +172,7 @@ snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo)
/*
* allocate midi info record
*/
- if ((mdev = kcalloc(1, sizeof(*mdev), GFP_KERNEL)) == NULL) {
+ if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc midi info\n");
return -ENOMEM;
}
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 0a6f2a6..55571e1 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -46,7 +46,7 @@ snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen)
{
seq_oss_readq_t *q;
- if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL) {
+ if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc read queue\n");
return NULL;
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 1a7736c..8257fce 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -103,7 +103,7 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
unsigned long flags;
- if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL) {
+ if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc synth info\n");
return -ENOMEM;
}
@@ -499,7 +499,7 @@ snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_
sysex = dp->synths[dev].sysex;
if (sysex == NULL) {
- sysex = kcalloc(1, sizeof(*sysex), GFP_KERNEL);
+ sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
if (sysex == NULL)
return -ENOMEM;
dp->synths[dev].sysex = sysex;
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index 42ca949..64d594b 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -46,7 +46,7 @@ snd_seq_oss_timer_new(seq_oss_devinfo_t *dp)
{
seq_oss_timer_t *rec;
- rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
+ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (rec == NULL)
return NULL;
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 87f85f7..b203780 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -38,7 +38,7 @@ snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen)
seq_oss_writeq_t *q;
snd_seq_client_pool_t pool;
- if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL)
+ if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL)
return NULL;
q->dp = dp;
q->maxlen = maxlen;
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 7449d2a..24644150 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -43,7 +43,13 @@ int seq_client_load[64] = {[0 ... 63] = -1};
int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
int seq_default_timer_card = -1;
-int seq_default_timer_device = SNDRV_TIMER_GLOBAL_SYSTEM;
+int seq_default_timer_device =
+#ifdef CONFIG_SND_SEQ_RTCTIMER_DEFAULT
+ SNDRV_TIMER_GLOBAL_RTC
+#else
+ SNDRV_TIMER_GLOBAL_SYSTEM
+#endif
+ ;
int seq_default_timer_subdevice = 0;
int seq_default_timer_resolution = 0; /* Hz */
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index d8f76af..a886db9 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -203,7 +203,7 @@ static client_t *seq_create_client1(int client_index, int poolsize)
client_t *client;
/* init client data */
- client = kcalloc(1, sizeof(*client), GFP_KERNEL);
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
if (client == NULL)
return NULL;
client->pool = snd_seq_pool_new(poolsize);
@@ -413,7 +413,9 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
}
count -= sizeof(snd_seq_event_t);
buf += sizeof(snd_seq_event_t);
- err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t));
+ err = snd_seq_expand_var_event(&cell->event, count,
+ (char __force *)buf, 0,
+ sizeof(snd_seq_event_t));
if (err < 0)
break;
result += err;
@@ -1009,7 +1011,8 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t c
}
/* set user space pointer */
event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;
- event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t);
+ event.data.ext.ptr = (char __force *)buf
+ + sizeof(snd_seq_event_t);
len += extlen; /* increment data length */
} else {
#ifdef CONFIG_COMPAT
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 4d80f39..252b527 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -200,7 +200,7 @@ int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize,
if (ops == NULL)
return -ENOMEM;
- dev = kcalloc(1, sizeof(*dev)*2 + argsize, GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
if (dev == NULL) {
unlock_driver(ops);
return -ENOMEM;
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ea945a5..5dd0e6a 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -153,7 +153,7 @@ create_port(int idx, int type)
snd_seq_port_callback_t pcb;
snd_seq_dummy_port_t *rec;
- if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL)
+ if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
return NULL;
rec->client = my_client;
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 3b7647c..4767cfd 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -33,7 +33,7 @@ fifo_t *snd_seq_fifo_new(int poolsize)
{
fifo_t *f;
- f = kcalloc(1, sizeof(*f), GFP_KERNEL);
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL) {
snd_printd("malloc failed for snd_seq_fifo_new() \n");
return NULL;
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 5b40ea2..019d43a 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -53,7 +53,7 @@ static snd_seq_kinstr_t *snd_seq_instr_new(int add_len, int atomic)
{
snd_seq_kinstr_t *instr;
- instr = kcalloc(1, sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+ instr = kzalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
if (instr == NULL)
return NULL;
instr->add_len = add_len;
@@ -77,7 +77,7 @@ snd_seq_kinstr_list_t *snd_seq_instr_list_new(void)
{
snd_seq_kinstr_list_t *list;
- list = kcalloc(1, sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+ list = kzalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
if (list == NULL)
return NULL;
spin_lock_init(&list->lock);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 03acb2d..d4d7d32 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -452,7 +452,7 @@ pool_t *snd_seq_pool_new(int poolsize)
pool_t *pool;
/* create pool block */
- pool = kcalloc(1, sizeof(*pool), GFP_KERNEL);
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
if (pool == NULL) {
snd_printd("seq: malloc failed for pool\n");
return NULL;
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 4374829..b4674ae 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -322,7 +322,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
client = synths[card->number];
if (client == NULL) {
newclient = 1;
- client = kcalloc(1, sizeof(*client), GFP_KERNEL);
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
if (client == NULL) {
up(&register_mutex);
kfree(info);
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 603b637..2dc1aec 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -118,7 +118,7 @@ int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
snd_midi_event_t *dev;
*rdev = NULL;
- dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
if (bufsize > 0) {
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index b976951..57ec31d 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -141,7 +141,7 @@ client_port_t *snd_seq_create_port(client_t *client, int port)
}
/* create a new port */
- new_port = kcalloc(1, sizeof(*new_port), GFP_KERNEL);
+ new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
if (! new_port) {
snd_printd("malloc failed for registering client port\n");
return NULL; /* failure, out of memory */
@@ -488,7 +488,7 @@ int snd_seq_port_connect(client_t *connector,
unsigned long flags;
int exclusive;
- subs = kcalloc(1, sizeof(*subs), GFP_KERNEL);
+ subs = kzalloc(sizeof(*subs), GFP_KERNEL);
if (! subs)
return -ENOMEM;
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index a519732e..cd641bc 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -59,7 +59,7 @@ prioq_t *snd_seq_prioq_new(void)
{
prioq_t *f;
- f = kcalloc(1, sizeof(*f), GFP_KERNEL);
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL) {
snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
return NULL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 98de2e7..5f5c3cb 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -111,7 +111,7 @@ static queue_t *queue_new(int owner, int locked)
{
queue_t *q;
- q = kcalloc(1, sizeof(*q), GFP_KERNEL);
+ q = kzalloc(sizeof(*q), GFP_KERNEL);
if (q == NULL) {
snd_printd("malloc failed for snd_seq_queue_new()\n");
return NULL;
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index e8f0a66..0d9eff8 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -126,8 +126,8 @@ int __init snd_seq_system_client_init(void)
snd_seq_client_info_t *inf;
snd_seq_port_info_t *port;
- inf = kcalloc(1, sizeof(*inf), GFP_KERNEL);
- port = kcalloc(1, sizeof(*port), GFP_KERNEL);
+ inf = kzalloc(sizeof(*inf), GFP_KERNEL);
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
if (! inf || ! port) {
kfree(inf);
kfree(port);
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index a7f76fc..b57a3c0 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -60,7 +60,7 @@ seq_timer_t *snd_seq_timer_new(void)
{
seq_timer_t *tmr;
- tmr = kcalloc(1, sizeof(*tmr), GFP_KERNEL);
+ tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
if (tmr == NULL) {
snd_printd("malloc failed for snd_seq_timer_new() \n");
return NULL;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index a66484b5..e4f512a 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -205,7 +205,7 @@ static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
snd_virmidi_t *vmidi;
unsigned long flags;
- vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
+ vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
if (vmidi == NULL)
return -ENOMEM;
vmidi->substream = substream;
@@ -233,7 +233,7 @@ static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
snd_rawmidi_runtime_t *runtime = substream->runtime;
snd_virmidi_t *vmidi;
- vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
+ vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
if (vmidi == NULL)
return -ENOMEM;
vmidi->substream = substream;
@@ -508,7 +508,7 @@ int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi)
&rmidi)) < 0)
return err;
strcpy(rmidi->name, rmidi->id);
- rdev = kcalloc(1, sizeof(*rdev), GFP_KERNEL);
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (rdev == NULL) {
snd_device_free(card, rmidi);
return -ENOMEM;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 3271e92..9e76bdd 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -328,6 +328,10 @@ int __exit snd_minor_info_done(void)
* INIT PART
*/
+#ifdef CONFIG_SND_GENERIC_DRIVER
+extern struct device_driver snd_generic_driver;
+#endif
+
static int __init alsa_sound_init(void)
{
short controlnum;
@@ -354,6 +358,9 @@ static int __init alsa_sound_init(void)
return -ENOMEM;
}
snd_info_minor_register();
+#ifdef CONFIG_SND_GENERIC_DRIVER
+ driver_register(&snd_generic_driver);
+#endif
for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
#ifndef MODULE
@@ -369,6 +376,9 @@ static void __exit alsa_sound_exit(void)
for (controlnum = 0; controlnum < cards_limit; controlnum++)
devfs_remove("snd/controlC%d", controlnum);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+ driver_unregister(&snd_generic_driver);
+#endif
snd_info_minor_unregister();
snd_info_done();
snd_memory_done();
@@ -416,10 +426,13 @@ EXPORT_SYMBOL(snd_card_register);
EXPORT_SYMBOL(snd_component_add);
EXPORT_SYMBOL(snd_card_file_add);
EXPORT_SYMBOL(snd_card_file_remove);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+EXPORT_SYMBOL(snd_card_set_generic_dev);
+#endif
#ifdef CONFIG_PM
EXPORT_SYMBOL(snd_power_wait);
EXPORT_SYMBOL(snd_card_set_pm_callback);
-#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+#ifdef CONFIG_SND_GENERIC_DRIVER
EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
#endif
#ifdef CONFIG_PCI
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 4104f6e..22b1046 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -98,7 +98,7 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left);
static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer)
{
snd_timer_instance_t *timeri;
- timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
+ timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
if (timeri == NULL)
return NULL;
timeri->owner = kstrdup(owner, GFP_KERNEL);
@@ -764,7 +764,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t *
snd_assert(tid != NULL, return -EINVAL);
snd_assert(rtimer != NULL, return -EINVAL);
*rtimer = NULL;
- timer = kcalloc(1, sizeof(*timer), GFP_KERNEL);
+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
if (timer == NULL)
return -ENOMEM;
timer->tmr_class = tid->dev_class;
@@ -1017,7 +1017,7 @@ static int snd_timer_register_system(void)
return err;
strcpy(timer->name, "system timer");
timer->hw = snd_timer_system;
- priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL) {
snd_timer_free(timer);
return -ENOMEM;
@@ -1202,7 +1202,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
{
snd_timer_user_t *tu;
- tu = kcalloc(1, sizeof(*tu), GFP_KERNEL);
+ tu = kzalloc(sizeof(*tu), GFP_KERNEL);
if (tu == NULL)
return -ENOMEM;
spin_lock_init(&tu->qlock);
@@ -1513,7 +1513,7 @@ static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info
t = tu->timeri->timer;
snd_assert(t != NULL, return -ENXIO);
- info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
info->card = t->card ? t->card->number : -1;
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 3b2bee1..efcb4eb 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -29,6 +29,7 @@ config SND_DUMMY
tristate "Dummy (/dev/null) soundcard"
depends on SND
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include the dummy driver. This driver does
nothing, but emulates various mixer controls and PCM devices.
@@ -44,6 +45,7 @@ config SND_VIRMIDI
depends on SND_SEQUENCER
select SND_TIMER
select SND_RAWMIDI
+ select SND_GENERIC_DRIVER
help
Say Y here to include the virtual MIDI driver. This driver
allows to connect applications using raw MIDI devices to
@@ -59,6 +61,7 @@ config SND_MTPAV
depends on SND
select SND_TIMER
select SND_RAWMIDI
+ select SND_GENERIC_DRIVER
help
To use a MOTU MidiTimePiece AV multiport MIDI adapter
connected to the parallel port, say Y here and make sure that
@@ -72,6 +75,7 @@ config SND_SERIAL_U16550
depends on SND
select SND_TIMER
select SND_RAWMIDI
+ select SND_GENERIC_DRIVER
help
To include support for MIDI serial port interfaces, say Y here
and read <file:Documentation/sound/alsa/serial-u16550.txt>.
@@ -88,6 +92,7 @@ config SND_MPU401
tristate "Generic MPU-401 UART driver"
depends on SND
select SND_MPU401_UART
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for MIDI ports compatible with
the Roland MPU-401 interface in UART mode.
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a61640c..64ef7f6 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -337,7 +337,7 @@ static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
snd_card_dummy_pcm_t *dpcm;
int err;
- dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
+ dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (dpcm == NULL)
return -ENOMEM;
init_timer(&dpcm->timer);
@@ -368,7 +368,7 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
snd_card_dummy_pcm_t *dpcm;
int err;
- dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
+ dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (dpcm == NULL)
return -ENOMEM;
init_timer(&dpcm->timer);
@@ -600,6 +600,10 @@ static int __init snd_card_dummy_probe(int dev)
strcpy(card->driver, "Dummy");
strcpy(card->shortname, "Dummy");
sprintf(card->longname, "Dummy %i", dev + 1);
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __nodev;
+
if ((err = snd_card_register(card)) == 0) {
snd_dummy_cards[dev] = card;
return 0;
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index cb36ecb..54e2ff9 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -77,20 +77,26 @@ static int snd_mpu401_create(int dev, snd_card_t **rcard)
strcat(card->longname, "polled");
}
- if (snd_mpu401_uart_new(card, 0,
- MPU401_HW_MPU401,
- port[dev], 0,
- irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
+ if ((err = snd_mpu401_uart_new(card, 0,
+ MPU401_HW_MPU401,
+ port[dev], 0,
+ irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL)) < 0) {
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
- snd_card_free(card);
- return -ENODEV;
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ goto _err;
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
*rcard = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __devinit snd_mpu401_probe(int dev)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 0f83c52..fe3f921 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -463,7 +463,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
*rrawmidi = NULL;
if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
return err;
- mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
+ mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
if (mpu == NULL) {
snd_device_free(card, rmidi);
return -ENOMEM;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 1280a57..3a25c89 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -688,7 +688,7 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
static mtpav_t *new_mtpav(void)
{
- mtpav_t *ncrd = kcalloc(1, sizeof(*ncrd), GFP_KERNEL);
+ mtpav_t *ncrd = kzalloc(sizeof(*ncrd), GFP_KERNEL);
if (ncrd != NULL) {
spin_lock_init(&ncrd->spinlock);
@@ -757,6 +757,9 @@ static int __init alsa_card_mtpav_init(void)
if (err < 0)
goto __error;
+ if ((err = snd_card_set_generic_dev(mtp_card->card)) < 0)
+ goto __error;
+
err = snd_card_register(mtp_card->card); // don't snd_card_register until AFTER all cards reources done!
//printk("snd_card_register returned %d\n", err);
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index c313e52..1f84d78 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -354,7 +354,7 @@ int snd_opl3_new(snd_card_t *card,
int err;
*ropl3 = NULL;
- opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
+ opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
if (opl3 == NULL)
return -ENOMEM;
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 33da334..21a2b40 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -241,7 +241,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
}
size = sizeof(*put) + sizeof(fm_xinstrument_t);
- put = kcalloc(1, size, GFP_KERNEL);
+ put = kzalloc(size, GFP_KERNEL);
if (put == NULL)
return -ENOMEM;
/* build header */
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 8261464..380c2c7 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -204,7 +204,7 @@ int snd_opl4_create(snd_card_t *card,
if (ropl4)
*ropl4 = NULL;
- opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
+ opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL);
if (!opl4)
return -ENOMEM;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 986df35..416172e 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -779,7 +779,7 @@ static int __init snd_uart16550_create(snd_card_t * card,
int err;
- if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
+ if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL)
return -ENOMEM;
uart->adaptor = adaptor;
uart->card = card;
@@ -928,15 +928,11 @@ static int __init snd_serial_probe(int dev)
base[dev],
adaptor[dev],
droponfull[dev],
- &uart)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &uart)) < 0)
+ goto _err;
- if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0)
+ goto _err;
sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
card->shortname,
@@ -949,12 +945,18 @@ static int __init snd_serial_probe(int dev)
adaptor_names[uart->adaptor],
uart->drop_on_full);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_serial_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_serial_init(void)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 5937711..af12185 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -116,6 +116,10 @@ static int __init snd_card_virmidi_probe(int dev)
strcpy(card->driver, "VirMIDI");
strcpy(card->shortname, "VirMIDI");
sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __nodev;
+
if ((err = snd_card_register(card)) == 0) {
snd_virmidi_cards[dev] = card;
return 0;
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index c6fa5af..4697b1d 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -782,7 +782,7 @@ vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
snd_assert(card && hw && ops, return NULL);
- chip = kcalloc(1, sizeof(*chip) + extra_size, GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "vx_core: no memory\n");
return NULL;
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index d4becf4..c2312d9 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -473,7 +473,7 @@ static int vx_alloc_pipe(vx_core_t *chip, int capture,
return err;
/* initialize the pipe record */
- pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
+ pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
if (! pipe) {
/* release the pipe */
vx_init_rmh(&rmh, CMD_FREE_PIPE);
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index a3fda85..a21f7d5 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -200,7 +200,7 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
return err;
- chip = device->private_data = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
snd_i2c_device_free(device);
return -ENOMEM;
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index e8fa7e1..e4e505b 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -81,7 +81,7 @@ int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master
};
*ri2c = NULL;
- bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL)
return -ENOMEM;
init_MUTEX(&bus->lock_mutex);
@@ -108,7 +108,7 @@ int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char ad
*rdevice = NULL;
snd_assert(bus != NULL, return -EINVAL);
- device = kcalloc(1, sizeof(*device), GFP_KERNEL);
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
if (device == NULL)
return -ENOMEM;
device->addr = addr;
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index e13122f..103a7dc 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -17,7 +17,7 @@
* 2002-05-12 Tomas Kasparek another code cleanup
*/
-/* $Id: uda1341.c,v 1.15 2005/01/03 12:05:20 tiwai Exp $ */
+/* $Id: uda1341.c,v 1.16 2005/09/09 13:22:34 tiwai Exp $ */
#include <sound/driver.h>
#include <linux/module.h>
@@ -670,7 +670,7 @@ int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
snd_assert(card != NULL, return -EINVAL);
- uda1341 = kcalloc(1, sizeof(*uda1341), GFP_KERNEL);
+ uda1341 = kzalloc(sizeof(*uda1341), GFP_KERNEL);
if (uda1341 == NULL)
return -ENOMEM;
@@ -707,7 +707,7 @@ static int uda1341_attach(struct l3_client *clnt)
{
struct uda1341 *uda;
- uda = kcalloc(1, sizeof(*uda), 0, GFP_KERNEL);
+ uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL);
if (!uda)
return -ENOMEM;
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 5adde30..af5eadc 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -92,7 +92,7 @@ int snd_ak4114_create(snd_card_t *card,
.dev_free = snd_ak4114_dev_free,
};
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->lock);
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 0419c433..d51b51d 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -83,7 +83,7 @@ int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *wri
.dev_free = snd_ak4117_dev_free,
};
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->lock);
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 2da8d7f..fd65da6 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -281,7 +281,7 @@ int snd_tea6330t_update_mixer(snd_card_t * card,
u8 default_treble, default_bass;
unsigned char bytes[7];
- tea = kcalloc(1, sizeof(*tea), GFP_KERNEL);
+ tea = kzalloc(sizeof(*tea), GFP_KERNEL);
if (tea == NULL)
return -ENOMEM;
if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 5c39483..5d6c300a 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -6,12 +6,12 @@ menu "ISA devices"
config SND_AD1848_LIB
tristate
select SND_PCM
- select SND_GENERIC_PM
+ select SND_GENERIC_DRIVER
config SND_CS4231_LIB
tristate
select SND_PCM
- select SND_GENERIC_PM
+ select SND_GENERIC_DRIVER
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
@@ -97,6 +97,7 @@ config SND_ES1688
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for ESS AudioDrive ES688 or
ES1688 chips.
@@ -110,7 +111,7 @@ config SND_ES18XX
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
- select SND_GENERIC_PM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for ESS AudioDrive ES18xx chips.
@@ -126,6 +127,7 @@ config SND_GUSCLASSIC
select SND_RAWMIDI
select SND_PCM
select SND_GUS_SYNTH
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Gravis UltraSound Classic
soundcards.
@@ -140,6 +142,7 @@ config SND_GUSEXTREME
select SND_MPU401_UART
select SND_PCM
select SND_GUS_SYNTH
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Gravis UltraSound Extreme
soundcards.
@@ -153,6 +156,7 @@ config SND_GUSMAX
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Gravis UltraSound MAX
soundcards.
@@ -166,7 +170,7 @@ config SND_INTERWAVE
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select ISAPNP
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD InterWave based
soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -181,7 +185,7 @@ config SND_INTERWAVE_STB
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select ISAPNP
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD InterWave based
soundcards with a TEA6330T bass and treble regulator
@@ -224,6 +228,7 @@ config SND_OPTI93X
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for soundcards based on Opti
82C93x chips.
@@ -237,6 +242,7 @@ config SND_SB8
select SND_OPL3_LIB
select SND_RAWMIDI
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Creative Sound Blaster 1.0/
2.0/Pro (8-bit) or 100% compatible soundcards.
@@ -250,6 +256,7 @@ config SND_SB16
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Sound Blaster 16 soundcards
(including the Plug and Play version).
@@ -263,6 +270,7 @@ config SND_SBAWE
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for Sound Blaster AWE soundcards
(including the Plug and Play version).
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index ae86036..27a9dcf 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -591,7 +591,7 @@ int snd_ad1816a_create(snd_card_t *card,
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->irq = -1;
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 8c39934..3ebcc48 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -91,35 +91,36 @@ static int __init snd_card_ad1848_probe(int dev)
irq[dev],
dma1[dev],
thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_ad1848_mixer(chip)) < 0)
+ goto _err;
- if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ad1848_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
strcpy(card->driver, "AD1848");
strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
pcm->name, chip->port, irq[dev], dma1[dev]);
- if (thinkpad[dev]) {
+ if (thinkpad[dev])
strcat(card->longname, " [Thinkpad]");
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_ad1848_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_ad1848_init(void)
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index bc642dc..303861c 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -890,7 +890,7 @@ int snd_ad1848_create(snd_card_t * card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 1fce8b9..5252206 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -438,33 +438,37 @@ static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
/*
*/
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
+#define PFX "cmi8330: "
+
static int __devinit snd_cmi8330_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
snd_card_t *card;
struct snd_cmi8330 *acard;
- unsigned long flags;
int i, err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
+ if (! is_isapnp_selected(dev)) {
if (wssport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify wssport\n");
+ snd_printk(KERN_ERR PFX "specify wssport\n");
return -EINVAL;
}
if (sbport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify sbport\n");
+ snd_printk(KERN_ERR PFX "specify sbport\n");
return -EINVAL;
}
-#ifdef CONFIG_PNP
}
-#endif
+
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_cmi8330));
if (card == NULL) {
- snd_printk("could not get a new card\n");
+ snd_printk(KERN_ERR PFX "could not get a new card\n");
return -ENOMEM;
}
acard = (struct snd_cmi8330 *)card->private_data;
@@ -473,9 +477,8 @@ static int __devinit snd_cmi8330_probe(int dev,
#ifdef CONFIG_PNP
if (isapnp[dev]) {
if ((err = snd_cmi8330_pnp(dev, acard, pcard, pid)) < 0) {
- snd_printk("PnP detection failed\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "PnP detection failed\n");
+ goto _err;
}
snd_card_set_dev(card, &pcard->card->dev);
}
@@ -487,14 +490,13 @@ static int __devinit snd_cmi8330_probe(int dev,
wssdma[dev],
AD1848_HW_DETECT,
&acard->wss)) < 0) {
- snd_printk("(AD1848) device busy??\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
+ goto _err;
}
if (acard->wss->hardware != AD1848_HW_CMI8330) {
- snd_printk("(AD1848) not found during probe\n");
- snd_card_free(card);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
+ err = -ENODEV;
+ goto _err;
}
if ((err = snd_sbdsp_create(card, sbport[dev],
@@ -503,32 +505,26 @@ static int __devinit snd_cmi8330_probe(int dev,
sbdma8[dev],
sbdma16[dev],
SB_HW_AUTO, &acard->sb)) < 0) {
- snd_printk("(SB16) device busy??\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "(SB16) device busy??\n");
+ goto _err;
}
if (acard->sb->hardware != SB_HW_16) {
- snd_printk("(SB16) not found during probe\n");
- snd_card_free(card);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "(SB16) not found during probe\n");
+ goto _err;
}
- spin_lock_irqsave(&acard->wss->reg_lock, flags);
snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]);
- spin_unlock_irqrestore(&acard->wss->reg_lock, flags);
if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
- snd_printk("failed to create mixers\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "failed to create mixers\n");
+ goto _err;
}
if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
- snd_printk("failed to create pcms\n");
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "failed to create pcms\n");
+ goto _err;
}
strcpy(card->driver, "CMI8330/C3D");
@@ -539,16 +535,21 @@ static int __devinit snd_cmi8330_probe(int dev,
wssirq[dev],
wssdma[dev]);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_cmi8330_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
#ifdef CONFIG_PNP
@@ -594,10 +595,8 @@ static int __init alsa_card_cmi8330_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev])
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (snd_cmi8330_probe(dev, NULL, NULL) >= 0)
cards++;
}
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 7640837..9be5416 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -76,15 +76,15 @@ static int __init snd_card_cs4231_probe(int dev)
int err;
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR "specify port\n");
return -EINVAL;
}
if (irq[dev] == SNDRV_AUTO_IRQ) {
- snd_printk("specify irq\n");
+ snd_printk(KERN_ERR "specify irq\n");
return -EINVAL;
}
if (dma1[dev] == SNDRV_AUTO_DMA) {
- snd_printk("specify dma1\n");
+ snd_printk(KERN_ERR "specify dma1\n");
return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -96,15 +96,11 @@ static int __init snd_card_cs4231_probe(int dev)
dma1[dev],
dma2[dev],
CS4231_HW_DETECT,
- 0, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ 0, &chip)) < 0)
+ goto _err;
- if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
strcpy(card->driver, "CS4231");
strcpy(card->shortname, pcm->name);
@@ -113,14 +109,10 @@ static int __init snd_card_cs4231_probe(int dev)
if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
- if ((err = snd_cs4231_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_cs4231_mixer(chip)) < 0)
+ goto _err;
+ if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+ goto _err;
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
@@ -130,14 +122,20 @@ static int __init snd_card_cs4231_probe(int dev)
mpu_irq[dev],
mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0,
NULL) < 0)
- printk(KERN_ERR "cs4231: MPU401 not detected\n");
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ printk(KERN_WARNING "cs4231: MPU401 not detected\n");
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
snd_cs4231_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_cs4231_init(void)
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 3199941..3231825 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -1480,7 +1480,7 @@ static int snd_cs4231_new(snd_card_t * card,
cs4231_t *chip;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->hardware = hardware;
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 39f4eff..d28315d 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -387,6 +387,12 @@ static void snd_card_cs4236_free(snd_card_t *card)
}
}
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -397,20 +403,16 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
opl3_t *opl3;
int err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
+ if (! is_isapnp_selected(dev)) {
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR "specify port\n");
return -EINVAL;
}
if (cport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify cport\n");
+ snd_printk(KERN_ERR "specify cport\n");
return -EINVAL;
}
-#ifdef CONFIG_PNP
}
-#endif
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_cs4236));
if (card == NULL)
@@ -421,8 +423,7 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
if (isapnp[dev]) {
if ((err = snd_card_cs4236_pnp(dev, acard, pcard, pid))<0) {
printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n");
- snd_card_free(card);
- return -ENXIO;
+ goto _err;
}
snd_card_set_dev(card, &pcard->card->dev);
}
@@ -430,8 +431,8 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT)
if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) {
printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
- snd_card_free(card);
- return -ENOMEM;
+ err = -EBUSY;
+ goto _err;
}
#ifdef CS4232
@@ -443,18 +444,14 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
dma2[dev],
CS4231_HW_DETECT,
0,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_mixer(chip)) < 0)
+ goto _err;
#else /* CS4236 */
if ((err = snd_cs4236_create(card,
@@ -465,18 +462,14 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
dma2[dev],
CS4231_HW_DETECT,
0,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4236_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4236_mixer(chip)) < 0)
+ goto _err;
#endif
strcpy(card->driver, pcm->name);
strcpy(card->shortname, pcm->name);
@@ -488,21 +481,17 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
- if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+ goto _err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card,
fm_port[dev], fm_port[dev] + 2,
OPL3_HW_OPL3_CS, 0, &opl3) < 0) {
- printk(KERN_ERR IDENT ": OPL3 not detected\n");
+ printk(KERN_WARNING IDENT ": OPL3 not detected\n");
} else {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
}
@@ -513,17 +502,23 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
mpu_port[dev], 0,
mpu_irq[dev],
mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0)
- printk(KERN_ERR IDENT ": MPU401 not detected\n");
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ printk(KERN_WARNING IDENT ": MPU401 not detected\n");
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_cs4236_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
#ifdef CONFIG_PNP
@@ -569,10 +564,8 @@ static int __init alsa_card_cs423x_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev])
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (snd_card_cs423x_probe(dev, NULL, NULL) >= 0)
cards++;
}
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index c5eaec0..26a7d33 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -70,6 +70,7 @@ MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "es1688: "
static int __init snd_audiodrive_probe(int dev)
{
@@ -89,47 +90,41 @@ static int __init snd_audiodrive_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xmpu_irq = mpu_irq[dev];
xdma = dma8[dev];
if (xdma == SNDRV_AUTO_DMA) {
if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+ err = -EBUSY;
+ goto _err;
}
}
if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
xirq, xmpu_irq, xdma,
- ES1688_HW_AUTO, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_es1688_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ ES1688_HW_AUTO, &chip)) < 0)
+ goto _err;
+
+ if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0)
+ goto _err;
+
+ if ((err = snd_es1688_mixer(chip)) < 0)
+ goto _err;
strcpy(card->driver, "ES1688");
strcpy(card->shortname, pcm->name);
sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma);
if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
- printk(KERN_ERR "es1688: opl3 not detected at 0x%lx\n", chip->port);
+ printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port);
} else {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) {
@@ -137,18 +132,22 @@ static int __init snd_audiodrive_probe(int dev)
chip->mpu_port, 0,
xmpu_irq,
SA_INTERRUPT,
- NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ NULL)) < 0)
+ goto _err;
}
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_audiodrive_cards[dev] = card;
return 0;
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_audiodrive_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 17f68d0..aac8987 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -649,7 +649,7 @@ int snd_es1688_create(snd_card_t * card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->irq = -1;
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 1d832b2..d0ea19f 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1686,7 +1686,7 @@ static int __devinit snd_es18xx_new_device(snd_card_t * card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
@@ -1988,6 +1988,12 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
}
#endif /* CONFIG_PNP */
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -1996,7 +2002,6 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
int xirq, xdma1, xdma2;
snd_card_t *card;
struct snd_audiodrive *acard;
- snd_rawmidi_t *rmidi = NULL;
es18xx_t *chip;
opl3_t *opl3;
int err;
@@ -2019,25 +2024,25 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -2046,10 +2051,8 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
mpu_port[dev],
fm_port[dev],
xirq, xdma1, xdma2,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
sprintf(card->driver, "ES%x", chip->version);
sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version);
@@ -2064,23 +2067,18 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
chip->port,
xirq, xdma1);
- if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_es18xx_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_es18xx_mixer(chip)) < 0)
+ goto _err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
- snd_printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
+ snd_printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
} else {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
}
@@ -2088,25 +2086,28 @@ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
chip->mpu_port, 0,
xirq, 0,
- &rmidi)) < 0) {
- snd_card_free(card);
- return err;
- }
- chip->rmidi = rmidi;
+ &chip->rmidi)) < 0)
+ goto _err;
}
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
/* Power Management */
snd_card_set_isa_pm_callback(card, snd_es18xx_suspend, snd_es18xx_resume, chip);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_audiodrive_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
@@ -2117,10 +2118,8 @@ static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
port[dev] = xport;
res = snd_audiodrive_probe(dev, NULL, NULL);
if (res < 0)
@@ -2177,10 +2176,8 @@ static int __init alsa_card_es18xx_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (snd_audiodrive_probe(dev, NULL, NULL) >= 0)
cards++;
}
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index a636d9c..8f2872f 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -157,7 +157,7 @@ int snd_gus_create(snd_card_t * card,
};
*rgus = NULL;
- gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
+ gus = kzalloc(sizeof(*gus), GFP_KERNEL);
if (gus == NULL)
return -ENOMEM;
gus->gf1.irq = -1;
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
index 886763f..7f96ac2 100644
--- a/sound/isa/gus/gus_mem_proc.c
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -98,7 +98,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
for (idx = 0; idx < 4; idx++) {
if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
- priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
priv->gus = gus;
@@ -115,7 +115,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
}
for (idx = 0; idx < 4; idx++) {
if (gus->gf1.rom_present & (1 << idx)) {
- priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
priv->rom = 1;
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index b75066a..beb0136 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -666,7 +666,7 @@ static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
+ pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL);
if (pcmp == NULL)
return -ENOMEM;
pcmp->gus = gus;
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index a99fa50..39cef38 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -72,40 +72,24 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "gusclassic: "
static int __init snd_gusclassic_detect(snd_gus_card_t * gus)
{
- snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
+ unsigned char d;
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
-
+ }
return 0;
}
@@ -137,25 +121,25 @@ static int __init snd_gusclassic_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -164,47 +148,48 @@ static int __init snd_gusclassic_probe(int dev)
port[dev],
xirq, xdma1, xdma2,
0, channels[dev], pcm_channels[dev],
- 0, &gus)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_gusclassic_detect(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ 0, &gus)) < 0)
+ goto _err;
+
+ if ((err = snd_gusclassic_detect(gus)) < 0)
+ goto _err;
+
snd_gusclassic_init(dev, gus);
- if ((err = snd_gus_initialize(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gus_initialize(gus)) < 0)
+ goto _err;
+
if (gus->max_flag || gus->ess_flag) {
- snd_printdd("GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
- snd_card_free(card);
- return -ENODEV;
- }
- if ((err = snd_gf1_new_mixer(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
+ snd_printk(KERN_ERR PFX "GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
+ err = -ENODEV;
+ goto _err;
}
+
+ if ((err = snd_gf1_new_mixer(gus)) < 0)
+ goto _err;
+
+ if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0)
+ goto _err;
+
if (!gus->ace_flag) {
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ goto _err;
}
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
if (dma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_gusclassic_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_gusclassic_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index bc6fecb..d2e7cb1 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -87,6 +87,7 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "gusextreme: "
static int __init snd_gusextreme_detect(int dev,
snd_card_t * card,
@@ -94,6 +95,7 @@ static int __init snd_gusextreme_detect(int dev,
es1688_t *es1688)
{
unsigned long flags;
+ unsigned char d;
/*
* This is main stuff - enable access to GF1 chip...
@@ -123,36 +125,17 @@ static int __init snd_gusextreme_detect(int dev,
udelay(100);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -EIO;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -EIO;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -EIO;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -EIO;
-#endif
-
+ }
return 0;
}
@@ -205,7 +188,7 @@ static int __init snd_gusextreme_probe(int dev)
xgf1_irq = gf1_irq[dev];
if (xgf1_irq == SNDRV_AUTO_IRQ) {
if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) {
- snd_printk("unable to find a free IRQ for GF1\n");
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ for GF1\n");
err = -EBUSY;
goto out;
}
@@ -213,7 +196,7 @@ static int __init snd_gusextreme_probe(int dev)
xess_irq = irq[dev];
if (xess_irq == SNDRV_AUTO_IRQ) {
if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) {
- snd_printk("unable to find a free IRQ for ES1688\n");
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ for ES1688\n");
err = -EBUSY;
goto out;
}
@@ -226,7 +209,7 @@ static int __init snd_gusextreme_probe(int dev)
xgf1_dma = dma1[dev];
if (xgf1_dma == SNDRV_AUTO_DMA) {
if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) {
- snd_printk("unable to find a free DMA for GF1\n");
+ snd_printk(KERN_ERR PFX "unable to find a free DMA for GF1\n");
err = -EBUSY;
goto out;
}
@@ -234,7 +217,7 @@ static int __init snd_gusextreme_probe(int dev)
xess_dma = dma8[dev];
if (xess_dma == SNDRV_AUTO_DMA) {
if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) {
- snd_printk("unable to find a free DMA for ES1688\n");
+ snd_printk(KERN_ERR PFX "unable to find a free DMA for ES1688\n");
err = -EBUSY;
goto out;
}
@@ -264,7 +247,7 @@ static int __init snd_gusextreme_probe(int dev)
goto out;
if (!gus->ess_flag) {
- snd_printdd("GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
+ snd_printk(KERN_ERR PFX "GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
err = -ENODEV;
goto out;
}
@@ -287,7 +270,7 @@ static int __init snd_gusextreme_probe(int dev)
if (snd_opl3_create(card, es1688->port, es1688->port + 2,
OPL3_HW_OPL3, 0, &opl3) < 0) {
- printk(KERN_ERR "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
+ printk(KERN_ERR PFX "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0)
goto out;
@@ -303,6 +286,10 @@ static int __init snd_gusextreme_probe(int dev)
sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i",
es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma);
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto out;
+
if ((err = snd_card_register(card)) < 0)
goto out;
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 400ff34..0bb44b5 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -82,39 +82,25 @@ struct snd_gusmax {
static snd_card_t *snd_gusmax_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "gusmax: "
static int __init snd_gusmax_detect(snd_gus_card_t * gus)
{
- snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
+ unsigned char d;
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- unsigned char d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
+
return 0;
}
@@ -239,25 +225,25 @@ static int __init snd_gusmax_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -266,31 +252,28 @@ static int __init snd_gusmax_probe(int dev)
-xirq, xdma1, xdma2,
0, channels[dev],
pcm_channels[dev],
- 0, &gus)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_gusmax_detect(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ 0, &gus)) < 0)
+ goto _err;
+
+ if ((err = snd_gusmax_detect(gus)) < 0)
+ goto _err;
+
maxcard->gus_status_reg = gus->gf1.reg_irqstat;
maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
snd_gusmax_init(dev, card, gus);
- if ((err = snd_gus_initialize(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gus_initialize(gus)) < 0)
+ goto _err;
+
if (!gus->max_flag) {
- printk(KERN_ERR "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
- snd_card_free(card);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
+ err = -ENODEV;
+ goto _err;
}
if (request_irq(xirq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) {
- snd_card_free(card);
- printk(KERN_ERR "gusmax: unable to grab IRQ %d\n", xirq);
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
+ err = -EBUSY;
+ goto _err;
}
maxcard->irq = xirq;
@@ -301,50 +284,46 @@ static int __init snd_gusmax_probe(int dev)
CS4231_HWSHARE_IRQ |
CS4231_HWSHARE_DMA1 |
CS4231_HWSHARE_DMA2,
- &cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &cs4231)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+ goto _err;
+
if (pcm_channels[dev] > 0) {
- if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_gusmax_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
+ if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+ goto _err;
}
+ if ((err = snd_gusmax_mixer(cs4231)) < 0)
+ goto _err;
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ goto _err;
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
maxcard->gus = gus;
maxcard->cs4231 = cs4231;
snd_gusmax_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_gusmax_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 46e867d..358cba9 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -73,6 +73,12 @@ static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+#ifdef SNDRV_STB
+#define PFX "interwave-stb: "
+#else
+#define PFX "interwave: "
+#endif
+
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for InterWave soundcard.");
module_param_array(id, charp, NULL, 0444);
@@ -249,38 +255,20 @@ static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
{
unsigned long flags;
unsigned char rev1, rev2;
+ int d;
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- int d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
- snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+ snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
+ }
udelay(160);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
- {
- int d;
-
- if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
- snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
- return -ENODEV;
- }
- }
-#else
- if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+ if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+ snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
return -ENODEV;
-#endif
-
+ }
spin_lock_irqsave(&gus->reg_lock, flags);
rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1);
@@ -686,35 +674,33 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
card->private_free = snd_interwave_free;
#ifdef CONFIG_PNP
if (isapnp[dev]) {
- if (snd_interwave_pnp(dev, iwcard, pcard, pid)) {
- snd_card_free(card);
- return -ENODEV;
- }
+ if ((err = snd_interwave_pnp(dev, iwcard, pcard, pid)) < 0)
+ goto _err;
snd_card_set_dev(card, &pcard->card->dev);
}
#endif
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma2 = dma2[dev];
if (xdma2 == SNDRV_AUTO_DMA) {
if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ err = -EBUSY;
+ goto _err;
}
}
@@ -722,32 +708,28 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
port[dev],
-xirq, xdma1, xdma2,
0, 32,
- pcm_channels[dev], effect[dev], &gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ pcm_channels[dev], effect[dev], &gus)) < 0)
+ goto _err;
+
if ((err = snd_interwave_detect(iwcard, gus, dev
#ifdef SNDRV_STB
, &i2c_bus
#endif
- )) < 0) {
- snd_card_free(card);
- return err;
- }
+ )) < 0)
+ goto _err;
+
iwcard->gus_status_reg = gus->gf1.reg_irqstat;
iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
snd_interwave_init(dev, gus);
snd_interwave_detect_memory(gus);
- if ((err = snd_gus_initialize(gus)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gus_initialize(gus)) < 0)
+ goto _err;
if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {
- snd_card_free(card);
- snd_printk("unable to grab IRQ %d\n", xirq);
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
+ err = -EBUSY;
+ goto _err;
}
iwcard->irq = xirq;
@@ -758,34 +740,28 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
CS4231_HWSHARE_IRQ |
CS4231_HWSHARE_DMA1 |
CS4231_HWSHARE_DMA2,
- &cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &cs4231)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0)
+ goto _err;
+
sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
strcat(pcm->name, " (codec)");
- if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_cs4231_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ goto _err;
+
if (pcm_channels[dev] > 0) {
- if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_interwave_mixer(cs4231)) < 0) {
- snd_card_free(card);
- return err;
+ if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+ goto _err;
}
+ if ((err = snd_interwave_mixer(cs4231)) < 0)
+ goto _err;
+
#ifdef SNDRV_STB
{
snd_ctl_elem_id_t id1, id2;
@@ -795,28 +771,20 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
strcpy(id1.name, "Master Playback Switch");
strcpy(id2.name, id1.name);
id2.index = 1;
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ goto _err;
strcpy(id1.name, "Master Playback Volume");
strcpy(id2.name, id1.name);
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ goto _err;
+ if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0)
+ goto _err;
}
#endif
gus->uart_enable = midi[dev];
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ goto _err;
#ifndef SNDRV_STB
str = "AMD InterWave";
@@ -835,10 +803,11 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
iwcard->cs4231 = cs4231;
iwcard->gus = gus;
@@ -847,6 +816,10 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
else
snd_interwave_legacy[dev++] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __devinit snd_interwave_probe_legacy_port(unsigned long xport)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 75bd6ec..e2d2bab 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -143,6 +143,8 @@ struct snd_opl3sa2 {
static snd_card_t *snd_opl3sa2_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "opl3sa2: "
+
#ifdef CONFIG_PNP
static struct pnp_device_id snd_opl3sa2_pnpbiosids[] = {
@@ -231,7 +233,7 @@ static int __init snd_opl3sa2_detect(opl3sa2_t *chip)
card = chip->card;
port = chip->port;
if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
- snd_printk(KERN_ERR "opl3sa2: can't grab port 0x%lx\n", port);
+ snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
return -EBUSY;
}
// snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a));
@@ -668,6 +670,12 @@ static int snd_opl3sa2_dev_free(snd_device_t *device)
return snd_opl3sa2_free(chip);
}
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __devinit snd_opl3sa2_probe(int dev,
struct pnp_dev *pdev,
struct pnp_card_link *pcard,
@@ -683,34 +691,31 @@ static int __devinit snd_opl3sa2_probe(int dev,
};
int err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
+ if (! is_isapnp_selected(dev)) {
if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify port\n");
+ snd_printk(KERN_ERR PFX "specify port\n");
return -EINVAL;
}
if (wss_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify wss_port\n");
+ snd_printk(KERN_ERR PFX "specify wss_port\n");
return -EINVAL;
}
if (fm_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify fm_port\n");
+ snd_printk(KERN_ERR PFX "specify fm_port\n");
return -EINVAL;
}
if (midi_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify midi_port\n");
+ snd_printk(KERN_ERR PFX "specify midi_port\n");
return -EINVAL;
}
-#ifdef CONFIG_PNP
}
-#endif
+
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
strcpy(card->driver, "OPL3SA2");
strcpy(card->shortname, "Yamaha OPL3-SA2");
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
err = -ENOMEM;
goto __error;
@@ -742,7 +747,7 @@ static int __devinit snd_opl3sa2_probe(int dev,
if ((err = snd_opl3sa2_detect(chip)) < 0)
goto __error;
if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", (void *)chip)) {
- snd_printk(KERN_ERR "opl3sa2: can't grab IRQ %d\n", xirq);
+ snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
err = -ENODEV;
goto __error;
}
@@ -795,6 +800,9 @@ static int __devinit snd_opl3sa2_probe(int dev,
if (dma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __error;
+
if ((err = snd_card_register(card)) < 0)
goto __error;
@@ -852,8 +860,10 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *card,
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
+ if (!enable[dev])
+ continue;
+ if (is_isapnp_selected(dev))
+ continue;
res = snd_opl3sa2_probe(dev, NULL, card, id);
if (res < 0)
return res;
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 411a702..73573cb 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -1038,8 +1038,7 @@ static int snd_opti93x_capture_prepare(snd_pcm_substream_t *substream)
chip->c_dma_size = size;
snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
- OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO,
- (unsigned char)~(OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO));
+ OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO, 0);
snd_dma_program(chip->dma2, runtime->dma_addr, size,
DMA_MODE_READ | DMA_AUTOINIT);
@@ -1274,7 +1273,7 @@ static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
opti93x_t *codec;
*rcodec = NULL;
- codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+ codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (codec == NULL)
return -ENOMEM;
codec->irq = -1;
@@ -1895,8 +1894,8 @@ static void snd_card_opti9xx_free(snd_card_t *card)
}
}
-static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
@@ -1966,6 +1965,10 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
snd_card_free(card);
return error;
}
+ if ((error = snd_card_set_generic_dev(card)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
#ifdef CONFIG_PNP
}
#endif /* CONFIG_PNP */
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 028af40..5375705 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1097,7 +1097,7 @@ snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_d
if (seq_ports <= 0)
return 0;
- hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (hw == NULL)
return -ENOMEM;
spin_lock_init(&hw->reg_lock);
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index db5eb8b..0209790 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -233,7 +233,7 @@ static int emu8k_pcm_open(snd_pcm_substream_t *subs)
emu8k_pcm_t *rec;
snd_pcm_runtime_t *runtime = subs->runtime;
- rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
+ rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (! rec)
return -ENOMEM;
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 60e2c53..7888783 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -351,6 +351,12 @@ static void snd_sb16_free(snd_card_t *card)
}
}
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev) isapnp[dev]
+#else
+#define is_isapnp_selected(dev) 0
+#endif
+
static int __init snd_sb16_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -378,10 +384,8 @@ static int __init snd_sb16_probe(int dev,
card->private_free = snd_sb16_free;
#ifdef CONFIG_PNP
if (isapnp[dev]) {
- if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid)))
+ goto _err;
snd_card_set_dev(card, &pcard->card->dev);
}
#endif
@@ -389,41 +393,37 @@ static int __init snd_sb16_probe(int dev,
xirq = irq[dev];
xdma8 = dma8[dev];
xdma16 = dma16[dev];
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
- if (xirq == SNDRV_AUTO_IRQ) {
- if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
- return -EBUSY;
+ if (! is_isapnp_selected(dev)) {
+ if (xirq == SNDRV_AUTO_IRQ) {
+ if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
+ }
}
- }
- if (xdma8 == SNDRV_AUTO_DMA) {
- if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
- snd_card_free(card);
- snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
- return -EBUSY;
+ if (xdma8 == SNDRV_AUTO_DMA) {
+ if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
+ err = -EBUSY;
+ goto _err;
+ }
}
- }
- if (xdma16 == SNDRV_AUTO_DMA) {
- if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
- snd_card_free(card);
- snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
- return -EBUSY;
+ if (xdma16 == SNDRV_AUTO_DMA) {
+ if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
+ err = -EBUSY;
+ goto _err;
+ }
}
- }
- /* non-PnP FM port address is hardwired with base port address */
- fm_port[dev] = port[dev];
- /* block the 0x388 port to avoid PnP conflicts */
- acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+ /* non-PnP FM port address is hardwired with base port address */
+ fm_port[dev] = port[dev];
+ /* block the 0x388 port to avoid PnP conflicts */
+ acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
#ifdef SNDRV_SBAWE_EMU8000
- /* non-PnP AWE port address is hardwired with base port address */
- awe_port[dev] = port[dev] + 0x400;
+ /* non-PnP AWE port address is hardwired with base port address */
+ awe_port[dev] = port[dev] + 0x400;
#endif
-#ifdef CONFIG_PNP
}
-#endif
if ((err = snd_sbdsp_create(card,
port[dev],
@@ -432,28 +432,20 @@ static int __init snd_sb16_probe(int dev,
xdma8,
xdma16,
SB_HW_AUTO,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
if (chip->hardware != SB_HW_16) {
- snd_card_free(card);
- snd_printdd("SB 16 chip was not detected at 0x%lx\n", port[dev]);
- return -ENODEV;
+ snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]);
+ err = -ENODEV;
+ goto _err;
}
chip->mpu_port = mpu_port[dev];
-#ifdef CONFIG_PNP
- if (!isapnp[dev] && (err = snd_sb16dsp_configure(chip)) < 0) {
-#else
- if ((err = snd_sb16dsp_configure(chip)) < 0) {
-#endif
- snd_card_free(card);
- return -ENXIO;
- }
- if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0)
+ goto _err;
+
+ if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0)
+ goto _err;
strcpy(card->driver,
#ifdef SNDRV_SBAWE_EMU8000
@@ -474,10 +466,8 @@ static int __init snd_sb16_probe(int dev,
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
chip->mpu_port, 0,
- xirq, 0, &chip->rmidi)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ xirq, 0, &chip->rmidi)) < 0)
+ goto _err;
chip->rmidi_callback = snd_mpu401_uart_interrupt;
}
@@ -499,17 +489,13 @@ static int __init snd_sb16_probe(int dev,
#else
int seqdev = 1;
#endif
- if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0)
+ goto _err;
}
}
- if ((err = snd_sbmixer_new(chip)) < 0) {
- snd_card_free(card);
- return -ENXIO;
- }
+ if ((err = snd_sbmixer_new(chip)) < 0)
+ goto _err;
#ifdef CONFIG_SND_SB16_CSP
/* CSP chip on SB16ASP/AWE32 */
@@ -525,11 +511,11 @@ static int __init snd_sb16_probe(int dev,
#endif
#ifdef SNDRV_SBAWE_EMU8000
if (awe_port[dev] > 0) {
- if (snd_emu8000_new(card, 1, awe_port[dev],
- seq_ports[dev], NULL) < 0) {
+ if ((err = snd_emu8000_new(card, 1, awe_port[dev],
+ seq_ports[dev], NULL)) < 0) {
snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]);
- snd_card_free(card);
- return -ENXIO;
+
+ goto _err;
}
}
#endif
@@ -541,15 +527,21 @@ static int __init snd_sb16_probe(int dev,
(mic_agc[dev] ? 0x00 : 0x01));
spin_unlock_irqrestore(&chip->mixer_lock, flags);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
if (pcard)
pnp_set_card_drvdata(pcard, card);
else
snd_sb16_legacy[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_sb16_probe_legacy_port(unsigned long xport)
@@ -560,10 +552,8 @@ static int __init snd_sb16_probe_legacy_port(unsigned long xport)
for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
port[dev] = xport;
res = snd_sb16_probe(dev, NULL, NULL);
if (res < 0)
@@ -621,10 +611,8 @@ static int __init alsa_card_sb16_init(void)
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (is_isapnp_selected(dev))
continue;
-#endif
if (!snd_sb16_probe(dev, NULL, NULL)) {
cards++;
continue;
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index d64790b..7192d4c 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -122,7 +122,7 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
return err;
- if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
+ if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
snd_device_free(chip->card, hw);
return -ENOMEM;
}
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index e2cbc42..c41ac25 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -107,54 +107,47 @@ static int __init snd_sb8_probe(int dev)
dma8[dev],
-1,
SB_HW_AUTO,
- &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &chip)) < 0)
+ goto _err;
+
if (chip->hardware >= SB_HW_16) {
- snd_card_free(card);
if (chip->hardware == SB_HW_ALS100)
- snd_printdd("ALS100 chip detected at 0x%lx, try snd-als100 module\n",
+ snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n",
port[dev]);
else
- snd_printdd("SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
- port[dev]);
- return -ENODEV;
+ snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
+ port[dev]);
+ err = -ENODEV;
+ goto _err;
}
- if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_sbmixer_new(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0)
+ goto _err;
+
+ if ((err = snd_sbmixer_new(chip)) < 0)
+ goto _err;
+
if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
if ((err = snd_opl3_create(card, chip->port + 8, 0,
OPL3_HW_AUTO, 1,
&opl3)) < 0) {
- snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx\n", chip->port + 8);
+ snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8);
}
} else {
if ((err = snd_opl3_create(card, chip->port, chip->port + 2,
OPL3_HW_AUTO, 1,
&opl3)) < 0) {
- snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx-0x%lx\n",
+ snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n",
chip->port, chip->port + 2);
}
}
if (err >= 0) {
- if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+ goto _err;
}
- if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0)
+ goto _err;
strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
strcpy(card->shortname, chip->name);
@@ -162,12 +155,19 @@ static int __init snd_sb8_probe(int dev)
chip->name,
chip->port,
irq[dev], dma8[dev]);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_sb8_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init snd_card_sb8_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 5b6bde2..f0f205a 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -221,7 +221,7 @@ int snd_sbdsp_create(snd_card_t *card,
snd_assert(r_chip != NULL, return -EINVAL);
*r_chip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
spin_lock_init(&chip->reg_lock);
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 17f585b..52f2294d 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -67,6 +67,8 @@ MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+#define PFX "sgalaxy: "
+
/*
*/
@@ -135,7 +137,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
}
#if 0
- snd_printdd("sgalaxy - setting up IRQ/DMA for WSS\n");
+ snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
#endif
/* initialize IRQ for WSS codec */
@@ -160,7 +162,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
static int __init snd_sgalaxy_detect(int dev, int irq, int dma)
{
#if 0
- snd_printdd("sgalaxy - switching to WSS mode\n");
+ snd_printdd(PFX "switching to WSS mode\n");
#endif
/* switch to WSS mode */
@@ -223,11 +225,11 @@ static int __init snd_sgalaxy_probe(int dev)
ad1848_t *chip;
if (sbport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify SB port\n");
+ snd_printk(KERN_ERR PFX "specify SB port\n");
return -EINVAL;
}
if (wssport[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify WSS port\n");
+ snd_printk(KERN_ERR PFX "specify WSS port\n");
return -EINVAL;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -237,46 +239,39 @@ static int __init snd_sgalaxy_probe(int dev)
xirq = irq[dev];
if (xirq == SNDRV_AUTO_IRQ) {
if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ err = -EBUSY;
+ goto _err;
}
}
xdma1 = dma1[dev];
if (xdma1 == SNDRV_AUTO_DMA) {
if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA\n");
- return -EBUSY;
+ snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+ err = -EBUSY;
+ goto _err;
}
}
- if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
+ goto _err;
if ((err = snd_ad1848_create(card, wssport[dev] + 4,
xirq, xdma1,
- AD1848_HW_DETECT, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ AD1848_HW_DETECT, &chip)) < 0)
+ goto _err;
if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
- snd_printdd("sgalaxy - error creating new ad1848 PCM device\n");
- snd_card_free(card);
- return err;
+ snd_printdd(PFX "error creating new ad1848 PCM device\n");
+ goto _err;
}
if ((err = snd_ad1848_mixer(chip)) < 0) {
- snd_printdd("sgalaxy - error creating new ad1848 mixer\n");
- snd_card_free(card);
- return err;
+ snd_printdd(PFX "error creating new ad1848 mixer\n");
+ goto _err;
}
- if (snd_sgalaxy_mixer(chip) < 0) {
- snd_printdd("sgalaxy - the mixer rewrite failed\n");
- snd_card_free(card);
- return err;
+ if ((err = snd_sgalaxy_mixer(chip)) < 0) {
+ snd_printdd(PFX "the mixer rewrite failed\n");
+ goto _err;
}
strcpy(card->driver, "Sound Galaxy");
@@ -284,12 +279,18 @@ static int __init snd_sgalaxy_probe(int dev)
sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
wssport[dev], xirq, xdma1);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
+
snd_sgalaxy_cards[dev] = card;
return 0;
+
+ _err:
+ snd_card_free(card);
+ return err;
}
static int __init alsa_card_sgalaxy_init(void)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 3959ed6..9f6b58c 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1262,11 +1262,6 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
*/
sscape_write(sscape, GA_INTENA_REG, 0x80);
- if ((err = snd_card_register(card)) < 0) {
- printk(KERN_ERR "sscape: Failed to register sound card\n");
- goto _release_card;
- }
-
/*
* Initialize mixer
*/
@@ -1396,6 +1391,13 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
if (ret < 0)
return ret;
snd_card_set_dev(card, &pcard->card->dev);
+
+ if ((ret = snd_card_register(card)) < 0) {
+ printk(KERN_ERR "sscape: Failed to register sound card\n");
+ snd_card_free(card);
+ return ret;
+ }
+
pnp_set_card_drvdata(pcard, card);
++sscape_cards;
++idx;
@@ -1460,6 +1462,16 @@ static int __init sscape_manual_probe(struct params *params)
if (ret < 0)
return ret;
+ if ((ret = snd_card_set_generic_dev(card)) < 0) {
+ snd_card_free(card);
+ return ret;
+ }
+ if ((ret = snd_card_register(card)) < 0) {
+ printk(KERN_ERR "sscape: Failed to register sound card\n");
+ snd_card_free(card);
+ return ret;
+ }
+
sscape_card[sscape_cards] = card;
params++;
sscape_cards++;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 79b0220..0a572e0 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -622,6 +622,11 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
ics2115_port[dev],
ics2115_irq[dev]);
+ if ((err = snd_card_set_generic_dev(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig
index 531f8ba..2433b77 100644
--- a/sound/mips/Kconfig
+++ b/sound/mips/Kconfig
@@ -8,6 +8,7 @@ config SND_AU1X00
depends on (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SND
select SND_PCM
select SND_AC97_CODEC
+ select SND_GENERIC_DRIVER
help
ALSA Sound driver for the Au1x00's AC97 port.
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index c20522b..3f9684f 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -667,6 +667,11 @@ au1000_init(void)
strcpy(au1000->card->shortname, "Au1000-AC97");
sprintf(au1000->card->longname, "AMD Au1000--AC97 ALSA Driver");
+ if ((err = snd_card_set_generic_dev(au1000->card)) < 0) {
+ snd_card_free(au1000->card);
+ return err;
+ }
+
if ((err = snd_card_register(au1000->card)) < 0) {
snd_card_free(au1000->card);
return err;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index d7a8f9f..f560dd8 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -880,6 +880,8 @@ snd_harmony_create(snd_card_t *card,
goto free_and_ret;
}
+ snd_card_set_dev(card, &padev->dev);
+
*rchip = h;
return 0;
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1e458919..a5d593c 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -316,6 +316,18 @@ config SND_YMFPCI
To compile this driver as a module, choose M here: the module
will be called snd-ymfpci.
+config SND_AD1889
+ tristate "Analog Devices AD1889"
+ depends on SND
+ select SND_AC97_CODEC
+ help
+ Say Y here to include support for the integrated AC97 sound
+ device found in particular on the Hewlett-Packard [BCJ]-xxx0
+ class PA-RISC workstations, using the AD1819 codec.
+
+ To compile this as a module, choose M here: the module
+ will be called snd-ad1889.
+
config SND_ALS4000
tristate "Avance Logic ALS4000"
depends on SND && ISA_DMA_API
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index b40575c..42fabfc 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -3,6 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
+snd-ad1889-objs := ad1889.o
snd-als4000-objs := als4000.o
snd-atiixp-objs := atiixp.o
snd-atiixp-modem-objs := atiixp_modem.o
@@ -25,6 +26,7 @@ snd-via82xx-objs := via82xx.o
snd-via82xx-modem-objs := via82xx_modem.o
# Toplevel Module Dependency
+obj-$(CONFIG_SND_AD1889) += snd-ad1889.o
obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 5501f44..e64cb07 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -112,6 +112,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */
{ 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL },
{ 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL },
+{ 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */
{ 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL },
{ 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL },
{ 0x414c4730, 0xffffffff, "ALC101", NULL, NULL },
@@ -1796,7 +1797,7 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
snd_assert(card != NULL, return -EINVAL);
snd_assert(rbus != NULL, return -EINVAL);
- bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL)
return -ENOMEM;
bus->card = card;
@@ -1905,7 +1906,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
}
card = bus->card;
- ac97 = kcalloc(1, sizeof(*ac97), GFP_KERNEL);
+ ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL);
if (ac97 == NULL)
return -ENOMEM;
ac97->private_data = template->private_data;
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
index dadf387..6d73514 100644
--- a/sound/pci/ac97/ac97_id.h
+++ b/sound/pci/ac97/ac97_id.h
@@ -52,6 +52,7 @@
#define AC97_ID_ALC650F 0x414c4723
#define AC97_ID_ALC655 0x414c4760
#define AC97_ID_ALC658 0x414c4780
+#define AC97_ID_ALC658D 0x414c4781
#define AC97_ID_ALC850 0x414c4790
#define AC97_ID_YMF753 0x594d4803
#define AC97_ID_VT1616 0x49434551
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index b584172..045ddc7 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -2134,7 +2134,13 @@ int patch_alc655(ac97_t * ac97)
{
unsigned int val;
- ac97->spec.dev_flags = (ac97->id == 0x414c4780); /* ALC658 */
+ if (ac97->id == AC97_ID_ALC658) {
+ ac97->spec.dev_flags = 1; /* ALC658 */
+ if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
+ ac97->id = AC97_ID_ALC658D;
+ ac97->spec.dev_flags = 2;
+ }
+ }
ac97->build_ops = &patch_alc655_ops;
@@ -2143,10 +2149,15 @@ int patch_alc655(ac97_t * ac97)
/* adjust default values */
val = snd_ac97_read(ac97, 0x7a); /* misc control */
- if (ac97->id == 0x414c4780) /* ALC658 */
+ if (ac97->spec.dev_flags) /* ALC658 */
val &= ~(1 << 1); /* Pin 47 is spdif input pin */
- else /* ALC655 */
- val |= (1 << 1); /* Pin 47 is spdif input pin */
+ else { /* ALC655 */
+ if (ac97->subsystem_vendor == 0x1462 &&
+ ac97->subsystem_device == 0x0131) /* MSI S270 laptop */
+ val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
+ else
+ val |= (1 << 1); /* Pin 47 is spdif input pin */
+ }
val &= ~(1 << 12); /* vref enable */
snd_ac97_write_cache(ac97, 0x7a, val);
/* set default: spdif-in enabled,
@@ -2159,6 +2170,11 @@ int patch_alc655(ac97_t * ac97)
/* full DAC volume */
snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+
+ /* update undocumented bit... */
+ if (ac97->id == AC97_ID_ALC658D)
+ snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
+
return 0;
}
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index f9ce0fd..4032c57 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -357,7 +357,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
snd_assert(rak4531 != NULL, return -EINVAL);
*rak4531 = NULL;
snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
- ak4531 = kcalloc(1, sizeof(*ak4531), GFP_KERNEL);
+ ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
if (ak4531 == NULL)
return -ENOMEM;
*ak4531 = *_ak4531;
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
new file mode 100644
index 0000000..d7d99a2
--- /dev/null
+++ b/sound/pci/ad1889.c
@@ -0,0 +1,1090 @@
+/* Analog Devices 1889 audio driver
+ *
+ * This is a driver for the AD1889 PCI audio chipset found
+ * on the HP PA-RISC [BCJ]-xxx0 workstations.
+ *
+ * Copyright (C) 2004-2005, Kyle McMartin <kyle@parisc-linux.org>
+ * Copyright (C) 2005, Thibaut Varene <varenet@parisc-linux.org>
+ * Based on the OSS AD1889 driver by Randolph Chung <tausq@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO:
+ * Do we need to take care of CCS register?
+ * Maybe we could use finer grained locking (separate locks for pb/cap)?
+ * Wishlist:
+ * Control Interface (mixer) support
+ * Better AC97 support (VSR...)?
+ * PM support
+ * MIDI support
+ * Game Port support
+ * SG DMA support (this will need *alot* of work)
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include <asm/io.h>
+
+#include "ad1889.h"
+#include "ac97/ac97_id.h"
+
+#define AD1889_DRVVER "$Revision: 1.3 $"
+
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>, Thibaut Varene <t-bone@parisc-linux.org>");
+MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1889}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the AD1889 soundcard.");
+
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard.");
+
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable AD1889 soundcard.");
+
+static char *ac97_quirk[SNDRV_CARDS];
+module_param_array(ac97_quirk, charp, NULL, 0444);
+MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+
+#define DEVNAME "ad1889"
+#define PFX DEVNAME ": "
+
+/* let's use the global sound debug interfaces */
+#define ad1889_debug(fmt, arg...) snd_printd(KERN_DEBUG fmt, ## arg)
+
+/* keep track of some hw registers */
+struct ad1889_register_state {
+ u16 reg; /* reg setup */
+ u32 addr; /* dma base address */
+ unsigned long size; /* DMA buffer size */
+};
+
+struct snd_ad1889 {
+ snd_card_t *card;
+ struct pci_dev *pci;
+
+ int irq;
+ unsigned long bar;
+ void __iomem *iobase;
+
+ ac97_t *ac97;
+ ac97_bus_t *ac97_bus;
+ snd_pcm_t *pcm;
+ snd_info_entry_t *proc;
+
+ snd_pcm_substream_t *psubs;
+ snd_pcm_substream_t *csubs;
+
+ /* playback register state */
+ struct ad1889_register_state wave;
+ struct ad1889_register_state ramc;
+
+ spinlock_t lock;
+};
+
+static inline u16
+ad1889_readw(struct snd_ad1889 *chip, unsigned reg)
+{
+ return readw(chip->iobase + reg);
+}
+
+static inline void
+ad1889_writew(struct snd_ad1889 *chip, unsigned reg, u16 val)
+{
+ writew(val, chip->iobase + reg);
+}
+
+static inline u32
+ad1889_readl(struct snd_ad1889 *chip, unsigned reg)
+{
+ return readl(chip->iobase + reg);
+}
+
+static inline void
+ad1889_writel(struct snd_ad1889 *chip, unsigned reg, u32 val)
+{
+ writel(val, chip->iobase + reg);
+}
+
+static inline void
+ad1889_unmute(struct snd_ad1889 *chip)
+{
+ u16 st;
+ st = ad1889_readw(chip, AD_DS_WADA) &
+ ~(AD_DS_WADA_RWAM | AD_DS_WADA_LWAM);
+ ad1889_writew(chip, AD_DS_WADA, st);
+ ad1889_readw(chip, AD_DS_WADA);
+}
+
+static inline void
+ad1889_mute(struct snd_ad1889 *chip)
+{
+ u16 st;
+ st = ad1889_readw(chip, AD_DS_WADA) | AD_DS_WADA_RWAM | AD_DS_WADA_LWAM;
+ ad1889_writew(chip, AD_DS_WADA, st);
+ ad1889_readw(chip, AD_DS_WADA);
+}
+
+static inline void
+ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address)
+{
+ ad1889_writel(chip, AD_DMA_ADCBA, address);
+ ad1889_writel(chip, AD_DMA_ADCCA, address);
+}
+
+static inline void
+ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_ADCBC, count);
+ ad1889_writel(chip, AD_DMA_ADCCC, count);
+}
+
+static inline void
+ad1889_load_adc_interrupt_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_ADCIB, count);
+ ad1889_writel(chip, AD_DMA_ADCIC, count);
+}
+
+static inline void
+ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address)
+{
+ ad1889_writel(chip, AD_DMA_WAVBA, address);
+ ad1889_writel(chip, AD_DMA_WAVCA, address);
+}
+
+static inline void
+ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_WAVBC, count);
+ ad1889_writel(chip, AD_DMA_WAVCC, count);
+}
+
+static inline void
+ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count)
+{
+ ad1889_writel(chip, AD_DMA_WAVIB, count);
+ ad1889_writel(chip, AD_DMA_WAVIC, count);
+}
+
+static void
+ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel)
+{
+ u16 reg;
+
+ if (channel & AD_CHAN_WAV) {
+ /* Disable wave channel */
+ reg = ad1889_readw(chip, AD_DS_WSMC) & ~AD_DS_WSMC_WAEN;
+ ad1889_writew(chip, AD_DS_WSMC, reg);
+ chip->wave.reg = reg;
+
+ /* disable IRQs */
+ reg = ad1889_readw(chip, AD_DMA_WAV);
+ reg &= AD_DMA_IM_DIS;
+ reg &= ~AD_DMA_LOOP;
+ ad1889_writew(chip, AD_DMA_WAV, reg);
+
+ /* clear IRQ and address counters and pointers */
+ ad1889_load_wave_buffer_address(chip, 0x0);
+ ad1889_load_wave_buffer_count(chip, 0x0);
+ ad1889_load_wave_interrupt_count(chip, 0x0);
+
+ /* flush */
+ ad1889_readw(chip, AD_DMA_WAV);
+ }
+
+ if (channel & AD_CHAN_ADC) {
+ /* Disable ADC channel */
+ reg = ad1889_readw(chip, AD_DS_RAMC) & ~AD_DS_RAMC_ADEN;
+ ad1889_writew(chip, AD_DS_RAMC, reg);
+ chip->ramc.reg = reg;
+
+ reg = ad1889_readw(chip, AD_DMA_ADC);
+ reg &= AD_DMA_IM_DIS;
+ reg &= ~AD_DMA_LOOP;
+ ad1889_writew(chip, AD_DMA_ADC, reg);
+
+ ad1889_load_adc_buffer_address(chip, 0x0);
+ ad1889_load_adc_buffer_count(chip, 0x0);
+ ad1889_load_adc_interrupt_count(chip, 0x0);
+
+ /* flush */
+ ad1889_readw(chip, AD_DMA_ADC);
+ }
+}
+
+static inline u16
+snd_ad1889_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+ struct snd_ad1889 *chip = ac97->private_data;
+ return ad1889_readw(chip, AD_AC97_BASE + reg);
+}
+
+static inline void
+snd_ad1889_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+ struct snd_ad1889 *chip = ac97->private_data;
+ ad1889_writew(chip, AD_AC97_BASE + reg, val);
+}
+
+static int
+snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
+{
+ int retry = 400; /* average needs 352 msec */
+
+ while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY)
+ && --retry)
+ mdelay(1);
+ if (!retry) {
+ snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
+ __FUNCTION__);
+ return -EIO;
+ }
+ ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
+
+ return 0;
+}
+
+static int
+snd_ad1889_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int
+snd_ad1889_hw_free(snd_pcm_substream_t *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static snd_pcm_hardware_t snd_ad1889_playback_hw = {
+ .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000, /* docs say 7000, but we're lazy */
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = BUFFER_BYTES_MAX,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = PERIOD_BYTES_MAX,
+ .periods_min = PERIODS_MIN,
+ .periods_max = PERIODS_MAX,
+ /*.fifo_size = 0,*/
+};
+
+static snd_pcm_hardware_t snd_ad1889_capture_hw = {
+ .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000, /* docs say we could to VSR, but we're lazy */
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = BUFFER_BYTES_MAX,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = PERIOD_BYTES_MAX,
+ .periods_min = PERIODS_MIN,
+ .periods_max = PERIODS_MAX,
+ /*.fifo_size = 0,*/
+};
+
+static int
+snd_ad1889_playback_open(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+
+ chip->psubs = ss;
+ rt->hw = snd_ad1889_playback_hw;
+
+ return 0;
+}
+
+static int
+snd_ad1889_capture_open(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+
+ chip->csubs = ss;
+ rt->hw = snd_ad1889_capture_hw;
+
+ return 0;
+}
+
+static int
+snd_ad1889_playback_close(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ chip->psubs = NULL;
+ return 0;
+}
+
+static int
+snd_ad1889_capture_close(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ chip->csubs = NULL;
+ return 0;
+}
+
+static int
+snd_ad1889_playback_prepare(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+ unsigned int size = snd_pcm_lib_buffer_bytes(ss);
+ unsigned int count = snd_pcm_lib_period_bytes(ss);
+ u16 reg;
+
+ ad1889_channel_reset(chip, AD_CHAN_WAV);
+
+ reg = ad1889_readw(chip, AD_DS_WSMC);
+
+ /* Mask out 16-bit / Stereo */
+ reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST);
+
+ if (snd_pcm_format_width(rt->format) == 16)
+ reg |= AD_DS_WSMC_WA16;
+
+ if (rt->channels > 1)
+ reg |= AD_DS_WSMC_WAST;
+
+ /* let's make sure we don't clobber ourselves */
+ spin_lock_irq(&chip->lock);
+
+ chip->wave.size = size;
+ chip->wave.reg = reg;
+ chip->wave.addr = rt->dma_addr;
+
+ ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg);
+
+ /* Set sample rates on the codec */
+ ad1889_writew(chip, AD_DS_WAS, rt->rate);
+
+ /* Set up DMA */
+ ad1889_load_wave_buffer_address(chip, chip->wave.addr);
+ ad1889_load_wave_buffer_count(chip, size);
+ ad1889_load_wave_interrupt_count(chip, count);
+
+ /* writes flush */
+ ad1889_readw(chip, AD_DS_WSMC);
+
+ spin_unlock_irq(&chip->lock);
+
+ ad1889_debug("prepare playback: addr = 0x%x, count = %u, "
+ "size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr,
+ count, size, reg, rt->rate);
+ return 0;
+}
+
+static int
+snd_ad1889_capture_prepare(snd_pcm_substream_t *ss)
+{
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+ unsigned int size = snd_pcm_lib_buffer_bytes(ss);
+ unsigned int count = snd_pcm_lib_period_bytes(ss);
+ u16 reg;
+
+ ad1889_channel_reset(chip, AD_CHAN_ADC);
+
+ reg = ad1889_readw(chip, AD_DS_RAMC);
+
+ /* Mask out 16-bit / Stereo */
+ reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST);
+
+ if (snd_pcm_format_width(rt->format) == 16)
+ reg |= AD_DS_RAMC_AD16;
+
+ if (rt->channels > 1)
+ reg |= AD_DS_RAMC_ADST;
+
+ /* let's make sure we don't clobber ourselves */
+ spin_lock_irq(&chip->lock);
+
+ chip->ramc.size = size;
+ chip->ramc.reg = reg;
+ chip->ramc.addr = rt->dma_addr;
+
+ ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg);
+
+ /* Set up DMA */
+ ad1889_load_adc_buffer_address(chip, chip->ramc.addr);
+ ad1889_load_adc_buffer_count(chip, size);
+ ad1889_load_adc_interrupt_count(chip, count);
+
+ /* writes flush */
+ ad1889_readw(chip, AD_DS_RAMC);
+
+ spin_unlock_irq(&chip->lock);
+
+ ad1889_debug("prepare capture: addr = 0x%x, count = %u, "
+ "size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr,
+ count, size, reg, rt->rate);
+ return 0;
+}
+
+/* this is called in atomic context with IRQ disabled.
+ Must be as fast as possible and not sleep.
+ DMA should be *triggered* by this call.
+ The WSMC "WAEN" bit triggers DMA Wave On/Off */
+static int
+snd_ad1889_playback_trigger(snd_pcm_substream_t *ss, int cmd)
+{
+ u16 wsmc;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ wsmc = ad1889_readw(chip, AD_DS_WSMC);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* enable DMA loop & interrupts */
+ ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT);
+ wsmc |= AD_DS_WSMC_WAEN;
+ /* 1 to clear CHSS bit */
+ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS);
+ ad1889_unmute(chip);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ ad1889_mute(chip);
+ wsmc &= ~AD_DS_WSMC_WAEN;
+ break;
+ default:
+ snd_BUG();
+ return -EINVAL;
+ }
+
+ chip->wave.reg = wsmc;
+ ad1889_writew(chip, AD_DS_WSMC, wsmc);
+ ad1889_readw(chip, AD_DS_WSMC); /* flush */
+
+ /* reset the chip when STOP - will disable IRQs */
+ if (cmd == SNDRV_PCM_TRIGGER_STOP)
+ ad1889_channel_reset(chip, AD_CHAN_WAV);
+
+ return 0;
+}
+
+/* this is called in atomic context with IRQ disabled.
+ Must be as fast as possible and not sleep.
+ DMA should be *triggered* by this call.
+ The RAMC "ADEN" bit triggers DMA ADC On/Off */
+static int
+snd_ad1889_capture_trigger(snd_pcm_substream_t *ss, int cmd)
+{
+ u16 ramc;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ ramc = ad1889_readw(chip, AD_DS_RAMC);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* enable DMA loop & interrupts */
+ ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT);
+ ramc |= AD_DS_RAMC_ADEN;
+ /* 1 to clear CHSS bit */
+ ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ ramc &= ~AD_DS_RAMC_ADEN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ chip->ramc.reg = ramc;
+ ad1889_writew(chip, AD_DS_RAMC, ramc);
+ ad1889_readw(chip, AD_DS_RAMC); /* flush */
+
+ /* reset the chip when STOP - will disable IRQs */
+ if (cmd == SNDRV_PCM_TRIGGER_STOP)
+ ad1889_channel_reset(chip, AD_CHAN_ADC);
+
+ return 0;
+}
+
+/* Called in atomic context with IRQ disabled */
+static snd_pcm_uframes_t
+snd_ad1889_playback_pointer(snd_pcm_substream_t *ss)
+{
+ size_t ptr = 0;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN)))
+ return 0;
+
+ ptr = ad1889_readl(chip, AD_DMA_WAVCA);
+ ptr -= chip->wave.addr;
+
+ snd_assert((ptr >= 0) && (ptr < chip->wave.size), return 0);
+
+ return bytes_to_frames(ss->runtime, ptr);
+}
+
+/* Called in atomic context with IRQ disabled */
+static snd_pcm_uframes_t
+snd_ad1889_capture_pointer(snd_pcm_substream_t *ss)
+{
+ size_t ptr = 0;
+ struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+ if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN)))
+ return 0;
+
+ ptr = ad1889_readl(chip, AD_DMA_ADCCA);
+ ptr -= chip->ramc.addr;
+
+ snd_assert((ptr >= 0) && (ptr < chip->ramc.size), return 0);
+
+ return bytes_to_frames(ss->runtime, ptr);
+}
+
+static snd_pcm_ops_t snd_ad1889_playback_ops = {
+ .open = snd_ad1889_playback_open,
+ .close = snd_ad1889_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ad1889_hw_params,
+ .hw_free = snd_ad1889_hw_free,
+ .prepare = snd_ad1889_playback_prepare,
+ .trigger = snd_ad1889_playback_trigger,
+ .pointer = snd_ad1889_playback_pointer,
+};
+
+static snd_pcm_ops_t snd_ad1889_capture_ops = {
+ .open = snd_ad1889_capture_open,
+ .close = snd_ad1889_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ad1889_hw_params,
+ .hw_free = snd_ad1889_hw_free,
+ .prepare = snd_ad1889_capture_prepare,
+ .trigger = snd_ad1889_capture_trigger,
+ .pointer = snd_ad1889_capture_pointer,
+};
+
+static irqreturn_t
+snd_ad1889_interrupt(int irq,
+ void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long st;
+ struct snd_ad1889 *chip = dev_id;
+
+ st = ad1889_readl(chip, AD_DMA_DISR);
+
+ /* clear ISR */
+ ad1889_writel(chip, AD_DMA_DISR, st);
+
+ st &= AD_INTR_MASK;
+
+ if (unlikely(!st))
+ return IRQ_NONE;
+
+ if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI))
+ ad1889_debug("Unexpected master or target abort interrupt!\n");
+
+ if ((st & AD_DMA_DISR_WAVI) && chip->psubs)
+ snd_pcm_period_elapsed(chip->psubs);
+ if ((st & AD_DMA_DISR_ADCI) && chip->csubs)
+ snd_pcm_period_elapsed(chip->csubs);
+
+ return IRQ_HANDLED;
+}
+
+static void
+snd_ad1889_pcm_free(snd_pcm_t *pcm)
+{
+ struct snd_ad1889 *chip = pcm->private_data;
+ chip->pcm = NULL;
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int __devinit
+snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, snd_pcm_t **rpcm)
+{
+ int err;
+ snd_pcm_t *pcm;
+
+ if (rpcm)
+ *rpcm = NULL;
+
+ err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_ad1889_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_ad1889_capture_ops);
+
+ pcm->private_data = chip;
+ pcm->private_free = snd_ad1889_pcm_free;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, chip->card->shortname);
+
+ chip->pcm = pcm;
+ chip->psubs = NULL;
+ chip->csubs = NULL;
+
+ err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ BUFFER_BYTES_MAX / 2,
+ BUFFER_BYTES_MAX);
+
+ if (err < 0) {
+ snd_printk(KERN_ERR PFX "buffer allocation error: %d\n", err);
+ return err;
+ }
+
+ if (rpcm)
+ *rpcm = pcm;
+
+ return 0;
+}
+
+static void
+snd_ad1889_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+ struct snd_ad1889 *chip = entry->private_data;
+ u16 reg;
+ int tmp;
+
+ reg = ad1889_readw(chip, AD_DS_WSMC);
+ snd_iprintf(buffer, "Wave output: %s\n",
+ (reg & AD_DS_WSMC_WAEN) ? "enabled" : "disabled");
+ snd_iprintf(buffer, "Wave Channels: %s\n",
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+ snd_iprintf(buffer, "Wave Quality: %d-bit linear\n",
+ (reg & AD_DS_WSMC_WA16) ? 16 : 8);
+
+ /* WARQ is at offset 12 */
+ tmp = (reg & AD_DS_WSMC_WARQ) ?
+ (((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
+
+ snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+
+ snd_iprintf(buffer, "Synthesis output: %s\n",
+ reg & AD_DS_WSMC_SYEN ? "enabled" : "disabled");
+
+ /* SYRQ is at offset 4 */
+ tmp = (reg & AD_DS_WSMC_SYRQ) ?
+ (((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
+
+ snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+ reg = ad1889_readw(chip, AD_DS_RAMC);
+ snd_iprintf(buffer, "ADC input: %s\n",
+ (reg & AD_DS_RAMC_ADEN) ? "enabled" : "disabled");
+ snd_iprintf(buffer, "ADC Channels: %s\n",
+ (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
+ snd_iprintf(buffer, "ADC Quality: %d-bit linear\n",
+ (reg & AD_DS_RAMC_AD16) ? 16 : 8);
+
+ /* ACRQ is at offset 4 */
+ tmp = (reg & AD_DS_RAMC_ACRQ) ?
+ (((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
+
+ snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
+
+ snd_iprintf(buffer, "Resampler input: %s\n",
+ reg & AD_DS_RAMC_REEN ? "enabled" : "disabled");
+
+ /* RERQ is at offset 12 */
+ tmp = (reg & AD_DS_RAMC_RERQ) ?
+ (((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4;
+ tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
+
+ snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
+ (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+
+ /* doc says LSB represents -1.5dB, but the max value (-94.5dB)
+ suggests that LSB is -3dB, which is more coherent with the logarithmic
+ nature of the dB scale */
+ reg = ad1889_readw(chip, AD_DS_WADA);
+ snd_iprintf(buffer, "Left: %s, -%d dB\n",
+ (reg & AD_DS_WADA_LWAM) ? "mute" : "unmute",
+ ((reg & AD_DS_WADA_LWAA) >> 8) * 3);
+ reg = ad1889_readw(chip, AD_DS_WADA);
+ snd_iprintf(buffer, "Right: %s, -%d dB\n",
+ (reg & AD_DS_WADA_RWAM) ? "mute" : "unmute",
+ ((reg & AD_DS_WADA_RWAA) >> 8) * 3);
+
+ reg = ad1889_readw(chip, AD_DS_WAS);
+ snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg);
+ reg = ad1889_readw(chip, AD_DS_RES);
+ snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
+}
+
+static void __devinit
+snd_ad1889_proc_init(struct snd_ad1889 *chip)
+{
+ snd_info_entry_t *entry;
+
+ if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
+ snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read);
+}
+
+static struct ac97_quirk ac97_quirks[] = {
+ {
+ .subvendor = 0x11d4, /* AD */
+ .subdevice = 0x1889, /* AD1889 */
+ .codec_id = AC97_ID_AD1819,
+ .name = "AD1889",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ { } /* terminator */
+};
+
+static void __devinit
+snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
+{
+ u16 reg;
+
+ reg = ad1889_readw(chip, AD_AC97_ACIC);
+ reg |= AD_AC97_ACIC_ACRD; /* Reset Disable */
+ ad1889_writew(chip, AD_AC97_ACIC, reg);
+ ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
+ udelay(10);
+ /* Interface Enable */
+ reg |= AD_AC97_ACIC_ACIE;
+ ad1889_writew(chip, AD_AC97_ACIC, reg);
+
+ snd_ad1889_ac97_ready(chip);
+
+ /* Audio Stream Output | Variable Sample Rate Mode */
+ reg = ad1889_readw(chip, AD_AC97_ACIC);
+ reg |= AD_AC97_ACIC_ASOE | AD_AC97_ACIC_VSRM;
+ ad1889_writew(chip, AD_AC97_ACIC, reg);
+ ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
+
+}
+
+static void
+snd_ad1889_ac97_bus_free(ac97_bus_t *bus)
+{
+ struct snd_ad1889 *chip = bus->private_data;
+ chip->ac97_bus = NULL;
+}
+
+static void
+snd_ad1889_ac97_free(ac97_t *ac97)
+{
+ struct snd_ad1889 *chip = ac97->private_data;
+ chip->ac97 = NULL;
+}
+
+static int __devinit
+snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
+{
+ int err;
+ ac97_template_t ac97;
+ static ac97_bus_ops_t ops = {
+ .write = snd_ad1889_ac97_write,
+ .read = snd_ad1889_ac97_read,
+ };
+
+ /* doing that here, it works. */
+ snd_ad1889_ac97_xinit(chip);
+
+ err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
+ if (err < 0)
+ return err;
+
+ chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ ac97.private_free = snd_ad1889_ac97_free;
+ ac97.pci = chip->pci;
+
+ err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
+ if (err < 0)
+ return err;
+
+ snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override);
+
+ return 0;
+}
+
+static int
+snd_ad1889_free(struct snd_ad1889 *chip)
+{
+ if (chip->irq < 0)
+ goto skip_hw;
+
+ spin_lock_irq(&chip->lock);
+
+ ad1889_mute(chip);
+
+ /* Turn off interrupt on count and zero DMA registers */
+ ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC);
+
+ /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */
+ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI);
+ ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */
+
+ spin_unlock_irq(&chip->lock);
+
+ synchronize_irq(chip->irq);
+
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void*)chip);
+
+skip_hw:
+ if (chip->iobase)
+ iounmap(chip->iobase);
+
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+
+ kfree(chip);
+ return 0;
+}
+
+static inline int
+snd_ad1889_dev_free(snd_device_t *device)
+{
+ struct snd_ad1889 *chip = device->device_data;
+ return snd_ad1889_free(chip);
+}
+
+static int __devinit
+snd_ad1889_init(struct snd_ad1889 *chip)
+{
+ ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+ ad1889_readw(chip, AD_DS_CCS); /* flush posted write */
+
+ mdelay(10);
+
+ /* enable Master and Target abort interrupts */
+ ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
+
+ return 0;
+}
+
+static int __devinit
+snd_ad1889_create(snd_card_t *card,
+ struct pci_dev *pci,
+ struct snd_ad1889 **rchip)
+{
+ int err;
+
+ struct snd_ad1889 *chip;
+ static snd_device_ops_t ops = {
+ .dev_free = snd_ad1889_dev_free,
+ };
+
+ *rchip = NULL;
+
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ /* check PCI availability (32bit DMA) */
+ if (pci_set_dma_mask(pci, 0xffffffff) < 0 ||
+ pci_set_consistent_dma_mask(pci, 0xffffffff) < 0) {
+ printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ /* allocate chip specific data with zero-filled memory */
+ if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ card->private_data = chip;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ /* (1) PCI resource allocation */
+ if ((err = pci_request_regions(pci, card->driver)) < 0)
+ goto free_and_ret;
+
+ chip->bar = pci_resource_start(pci, 0);
+ chip->iobase = ioremap_nocache(chip->bar, pci_resource_len(pci, 0));
+ if (chip->iobase == NULL) {
+ printk(KERN_ERR PFX "unable to reserve region.\n");
+ err = -EBUSY;
+ goto free_and_ret;
+ }
+
+ pci_set_master(pci);
+
+ spin_lock_init(&chip->lock); /* only now can we call ad1889_free */
+
+ if (request_irq(pci->irq, snd_ad1889_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, card->driver, (void*)chip)) {
+ printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq);
+ snd_ad1889_free(chip);
+ return -EBUSY;
+ }
+
+ chip->irq = pci->irq;
+ synchronize_irq(chip->irq);
+
+ /* (2) initialization of the chip hardware */
+ if ((err = snd_ad1889_init(chip)) < 0) {
+ snd_ad1889_free(chip);
+ return err;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+ snd_ad1889_free(chip);
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+
+ return 0;
+
+free_and_ret:
+ if (chip)
+ kfree(chip);
+ pci_disable_device(pci);
+
+ return err;
+}
+
+static int __devinit
+snd_ad1889_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ int err;
+ static int devno;
+ snd_card_t *card;
+ struct snd_ad1889 *chip;
+
+ /* (1) */
+ if (devno >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[devno]) {
+ devno++;
+ return -ENOENT;
+ }
+
+ /* (2) */
+ card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0);
+ /* XXX REVISIT: we can probably allocate chip in this call */
+ if (card == NULL)
+ return -ENOMEM;
+
+ strcpy(card->driver, "AD1889");
+ strcpy(card->shortname, "Analog Devices AD1889");
+
+ /* (3) */
+ err = snd_ad1889_create(card, pci, &chip);
+ if (err < 0)
+ goto free_and_ret;
+
+ /* (4) */
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->bar, chip->irq);
+
+ /* (5) */
+ /* register AC97 mixer */
+ err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
+ if (err < 0)
+ goto free_and_ret;
+
+ err = snd_ad1889_pcm_init(chip, 0, NULL);
+ if (err < 0)
+ goto free_and_ret;
+
+ /* register proc interface */
+ snd_ad1889_proc_init(chip);
+
+ /* (6) */
+ err = snd_card_register(card);
+ if (err < 0)
+ goto free_and_ret;
+
+ /* (7) */
+ pci_set_drvdata(pci, card);
+
+ devno++;
+ return 0;
+
+free_and_ret:
+ snd_card_free(card);
+ return err;
+}
+
+static void __devexit
+snd_ad1889_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_device_id snd_ad1889_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, snd_ad1889_ids);
+
+static struct pci_driver ad1889_pci = {
+ .name = "AD1889 Audio",
+ .owner = THIS_MODULE,
+ .id_table = snd_ad1889_ids,
+ .probe = snd_ad1889_probe,
+ .remove = __devexit_p(snd_ad1889_remove),
+};
+
+static int __init
+alsa_ad1889_init(void)
+{
+ return pci_register_driver(&ad1889_pci);
+}
+
+static void __exit
+alsa_ad1889_fini(void)
+{
+ pci_unregister_driver(&ad1889_pci);
+}
+
+module_init(alsa_ad1889_init);
+module_exit(alsa_ad1889_fini);
diff --git a/sound/pci/ad1889.h b/sound/pci/ad1889.h
new file mode 100644
index 0000000..5e6dad5
--- /dev/null
+++ b/sound/pci/ad1889.h
@@ -0,0 +1,189 @@
+/* Analog Devices 1889 audio driver
+ * Copyright (C) 2004, Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef __AD1889_H__
+#define __AD1889_H__
+
+#define AD_DS_WSMC 0x00 /* wave/synthesis channel mixer control */
+#define AD_DS_WSMC_SYEN 0x0004 /* synthesis channel enable */
+#define AD_DS_WSMC_SYRQ 0x0030 /* synth. fifo request point */
+#define AD_DS_WSMC_WA16 0x0100 /* wave channel 16bit select */
+#define AD_DS_WSMC_WAST 0x0200 /* wave channel stereo select */
+#define AD_DS_WSMC_WAEN 0x0400 /* wave channel enable */
+#define AD_DS_WSMC_WARQ 0x3000 /* wave fifo request point */
+
+#define AD_DS_RAMC 0x02 /* resampler/ADC channel mixer control */
+#define AD_DS_RAMC_AD16 0x0001 /* ADC channel 16bit select */
+#define AD_DS_RAMC_ADST 0x0002 /* ADC channel stereo select */
+#define AD_DS_RAMC_ADEN 0x0004 /* ADC channel enable */
+#define AD_DS_RAMC_ACRQ 0x0030 /* ADC fifo request point */
+#define AD_DS_RAMC_REEN 0x0400 /* resampler channel enable */
+#define AD_DS_RAMC_RERQ 0x3000 /* res. fifo request point */
+
+#define AD_DS_WADA 0x04 /* wave channel mix attenuation */
+#define AD_DS_WADA_RWAM 0x0080 /* right wave mute */
+#define AD_DS_WADA_RWAA 0x001f /* right wave attenuation */
+#define AD_DS_WADA_LWAM 0x8000 /* left wave mute */
+#define AD_DS_WADA_LWAA 0x3e00 /* left wave attenuation */
+
+#define AD_DS_SYDA 0x06 /* synthesis channel mix attenuation */
+#define AD_DS_SYDA_RSYM 0x0080 /* right synthesis mute */
+#define AD_DS_SYDA_RSYA 0x001f /* right synthesis attenuation */
+#define AD_DS_SYDA_LSYM 0x8000 /* left synthesis mute */
+#define AD_DS_SYDA_LSYA 0x3e00 /* left synthesis attenuation */
+
+#define AD_DS_WAS 0x08 /* wave channel sample rate */
+#define AD_DS_WAS_WAS 0xffff /* sample rate mask */
+
+#define AD_DS_RES 0x0a /* resampler channel sample rate */
+#define AD_DS_RES_RES 0xffff /* sample rate mask */
+
+#define AD_DS_CCS 0x0c /* chip control/status */
+#define AD_DS_CCS_ADO 0x0001 /* ADC channel overflow */
+#define AD_DS_CCS_REO 0x0002 /* resampler channel overflow */
+#define AD_DS_CCS_SYU 0x0004 /* synthesis channel underflow */
+#define AD_DS_CCS_WAU 0x0008 /* wave channel underflow */
+/* bits 4 -> 7, 9, 11 -> 14 reserved */
+#define AD_DS_CCS_XTD 0x0100 /* xtd delay control (4096 clock cycles) */
+#define AD_DS_CCS_PDALL 0x0400 /* power */
+#define AD_DS_CCS_CLKEN 0x8000 /* clock */
+
+#define AD_DMA_RESBA 0x40 /* RES base address */
+#define AD_DMA_RESCA 0x44 /* RES current address */
+#define AD_DMA_RESBC 0x48 /* RES base count */
+#define AD_DMA_RESCC 0x4c /* RES current count */
+
+#define AD_DMA_ADCBA 0x50 /* ADC base address */
+#define AD_DMA_ADCCA 0x54 /* ADC current address */
+#define AD_DMA_ADCBC 0x58 /* ADC base count */
+#define AD_DMA_ADCCC 0x5c /* ADC current count */
+
+#define AD_DMA_SYNBA 0x60 /* synth base address */
+#define AD_DMA_SYNCA 0x64 /* synth current address */
+#define AD_DMA_SYNBC 0x68 /* synth base count */
+#define AD_DMA_SYNCC 0x6c /* synth current count */
+
+#define AD_DMA_WAVBA 0x70 /* wave base address */
+#define AD_DMA_WAVCA 0x74 /* wave current address */
+#define AD_DMA_WAVBC 0x78 /* wave base count */
+#define AD_DMA_WAVCC 0x7c /* wave current count */
+
+#define AD_DMA_RESIC 0x80 /* RES dma interrupt current byte count */
+#define AD_DMA_RESIB 0x84 /* RES dma interrupt base byte count */
+
+#define AD_DMA_ADCIC 0x88 /* ADC dma interrupt current byte count */
+#define AD_DMA_ADCIB 0x8c /* ADC dma interrupt base byte count */
+
+#define AD_DMA_SYNIC 0x90 /* synth dma interrupt current byte count */
+#define AD_DMA_SYNIB 0x94 /* synth dma interrupt base byte count */
+
+#define AD_DMA_WAVIC 0x98 /* wave dma interrupt current byte count */
+#define AD_DMA_WAVIB 0x9c /* wave dma interrupt base byte count */
+
+#define AD_DMA_ICC 0xffffff /* current byte count mask */
+#define AD_DMA_IBC 0xffffff /* base byte count mask */
+/* bits 24 -> 31 reserved */
+
+/* 4 bytes pad */
+#define AD_DMA_ADC 0xa8 /* ADC dma control and status */
+#define AD_DMA_SYNTH 0xb0 /* Synth dma control and status */
+#define AD_DMA_WAV 0xb8 /* wave dma control and status */
+#define AD_DMA_RES 0xa0 /* Resample dma control and status */
+
+#define AD_DMA_SGDE 0x0001 /* SGD mode enable */
+#define AD_DMA_LOOP 0x0002 /* loop enable */
+#define AD_DMA_IM 0x000c /* interrupt mode mask */
+#define AD_DMA_IM_DIS (~AD_DMA_IM) /* disable */
+#define AD_DMA_IM_CNT 0x0004 /* interrupt on count */
+#define AD_DMA_IM_SGD 0x0008 /* interrupt on SGD flag */
+#define AD_DMA_IM_EOL 0x000c /* interrupt on End of Linked List */
+#define AD_DMA_SGDS 0x0030 /* SGD status */
+#define AD_DMA_SFLG 0x0040 /* SGD flag */
+#define AD_DMA_EOL 0x0080 /* SGD end of list */
+/* bits 8 -> 15 reserved */
+
+#define AD_DMA_DISR 0xc0 /* dma interrupt status */
+#define AD_DMA_DISR_RESI 0x000001 /* resampler channel interrupt */
+#define AD_DMA_DISR_ADCI 0x000002 /* ADC channel interrupt */
+#define AD_DMA_DISR_SYNI 0x000004 /* synthesis channel interrupt */
+#define AD_DMA_DISR_WAVI 0x000008 /* wave channel interrupt */
+/* bits 4, 5 reserved */
+#define AD_DMA_DISR_SEPS 0x000040 /* serial eeprom status */
+/* bits 7 -> 13 reserved */
+#define AD_DMA_DISR_PMAI 0x004000 /* pci master abort interrupt */
+#define AD_DMA_DISR_PTAI 0x008000 /* pci target abort interrupt */
+#define AD_DMA_DISR_PTAE 0x010000 /* pci target abort interrupt enable */
+#define AD_DMA_DISR_PMAE 0x020000 /* pci master abort interrupt enable */
+/* bits 19 -> 31 reserved */
+
+/* interrupt mask */
+#define AD_INTR_MASK (AD_DMA_DISR_RESI|AD_DMA_DISR_ADCI| \
+ AD_DMA_DISR_WAVI|AD_DMA_DISR_SYNI| \
+ AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)
+
+#define AD_DMA_CHSS 0xc4 /* dma channel stop status */
+#define AD_DMA_CHSS_RESS 0x000001 /* resampler channel stopped */
+#define AD_DMA_CHSS_ADCS 0x000002 /* ADC channel stopped */
+#define AD_DMA_CHSS_SYNS 0x000004 /* synthesis channel stopped */
+#define AD_DMA_CHSS_WAVS 0x000008 /* wave channel stopped */
+
+#define AD_GPIO_IPC 0xc8 /* gpio port control */
+#define AD_GPIO_OP 0xca /* gpio output port status */
+#define AD_GPIO_IP 0xcc /* gpio input port status */
+
+#define AD_AC97_BASE 0x100 /* ac97 base register */
+
+#define AD_AC97_RESET 0x100 /* reset */
+
+#define AD_AC97_PWR_CTL 0x126 /* == AC97_POWERDOWN */
+#define AD_AC97_PWR_ADC 0x0001 /* ADC ready status */
+#define AD_AC97_PWR_DAC 0x0002 /* DAC ready status */
+#define AD_AC97_PWR_PR0 0x0100 /* PR0 (ADC) powerdown */
+#define AD_AC97_PWR_PR1 0x0200 /* PR1 (DAC) powerdown */
+
+#define AD_MISC_CTL 0x176 /* misc control */
+#define AD_MISC_CTL_DACZ 0x8000 /* set for zero fill, unset for repeat */
+#define AD_MISC_CTL_ARSR 0x0001 /* set for SR1, unset for SR0 */
+#define AD_MISC_CTL_ALSR 0x0100
+#define AD_MISC_CTL_DLSR 0x0400
+#define AD_MISC_CTL_DRSR 0x0004
+
+#define AD_AC97_SR0 0x178 /* sample rate 0, 0xbb80 == 48K */
+#define AD_AC97_SR0_48K 0xbb80 /* 48KHz */
+#define AD_AC97_SR1 0x17a /* sample rate 1 */
+
+#define AD_AC97_ACIC 0x180 /* ac97 codec interface control */
+#define AD_AC97_ACIC_ACIE 0x0001 /* analog codec interface enable */
+#define AD_AC97_ACIC_ACRD 0x0002 /* analog codec reset disable */
+#define AD_AC97_ACIC_ASOE 0x0004 /* audio stream output enable */
+#define AD_AC97_ACIC_VSRM 0x0008 /* variable sample rate mode */
+#define AD_AC97_ACIC_FSDH 0x0100 /* force SDATA_OUT high */
+#define AD_AC97_ACIC_FSYH 0x0200 /* force sync high */
+#define AD_AC97_ACIC_ACRDY 0x8000 /* analog codec ready status */
+/* bits 10 -> 14 reserved */
+
+
+#define AD_DS_MEMSIZE 512
+#define AD_OPL_MEMSIZE 16
+#define AD_MIDI_MEMSIZE 16
+
+#define AD_WAV_STATE 0
+#define AD_ADC_STATE 1
+#define AD_MAX_STATES 2
+
+#define AD_CHAN_WAV 0x0001
+#define AD_CHAN_ADC 0x0002
+#define AD_CHAN_RES 0x0004
+#define AD_CHAN_SYN 0x0008
+
+
+/* The chip would support 4 GB buffers and 16 MB periods,
+ * but let's not overdo it ... */
+#define BUFFER_BYTES_MAX (256 * 1024)
+#define PERIOD_BYTES_MIN 32
+#define PERIOD_BYTES_MAX (BUFFER_BYTES_MAX / 2)
+#define PERIODS_MIN 2
+#define PERIODS_MAX (BUFFER_BYTES_MAX / PERIOD_BYTES_MIN)
+
+#endif /* __AD1889_H__ */
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 4943299..d683f77 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -78,15 +78,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
* Constants definition
*/
-#ifndef PCI_VENDOR_ID_ALI
-#define PCI_VENDOR_ID_ALI 0x10b9
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_5451
-#define PCI_DEVICE_ID_ALI_5451 0x5451
-#endif
-
-#define DEVICE_ID_ALI5451 ((PCI_VENDOR_ID_ALI<<16)|PCI_DEVICE_ID_ALI_5451)
+#define DEVICE_ID_ALI5451 ((PCI_VENDOR_ID_AL<<16)|PCI_DEVICE_ID_AL_M5451)
#define ALI_CHANNELS 32
@@ -326,13 +318,12 @@ static void ali_read_regs(ali_t *codec, int channel)
static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
{
unsigned int dwVal;
- struct pci_dev *pci_dev = NULL;
+ struct pci_dev *pci_dev;
int i,j;
-
- pci_dev = pci_find_device(vendor, deviceid, pci_dev);
- if (pci_dev == NULL)
- return ;
+ pci_dev = pci_get_device(vendor, deviceid, NULL);
+ if (pci_dev == NULL)
+ return ;
printk("\nM%x PCI CFG\n", deviceid);
printk(" ");
@@ -349,6 +340,7 @@ static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
}
printk("\n");
}
+ pci_dev_put(pci_dev);
}
static void ali_read_ac97regs(ali_t *codec, int secondary)
{
@@ -2116,6 +2108,8 @@ static int snd_ali_free(ali_t * codec)
#ifdef CONFIG_PM
kfree(codec->image);
#endif
+ pci_dev_put(codec->pci_m1533);
+ pci_dev_put(codec->pci_m7101);
kfree(codec);
return 0;
}
@@ -2305,7 +2299,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
codec->chregs.data.ainten = 0x00;
/* M1533: southbridge */
- pci_dev = pci_find_device(0x10b9, 0x1533, NULL);
+ pci_dev = pci_get_device(0x10b9, 0x1533, NULL);
codec->pci_m1533 = pci_dev;
if (! codec->pci_m1533) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n");
@@ -2313,7 +2307,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
return -ENODEV;
}
/* M7101: power management */
- pci_dev = pci_find_device(0x10b9, 0x7101, NULL);
+ pci_dev = pci_get_device(0x10b9, 0x7101, NULL);
codec->pci_m7101 = pci_dev;
if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n");
@@ -2417,6 +2411,7 @@ static void __devexit snd_ali_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ALI 5451",
+ .owner = THIS_MODULE,
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
.remove = __devexit_p(snd_ali_remove),
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index ca28b22..196ec1c 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -770,6 +770,7 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ALS4000",
+ .owner = THIS_MODULE,
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
.remove = __devexit_p(snd_card_als4000_remove),
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 188df08..241eacf 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1453,6 +1453,7 @@ static int snd_atiixp_resume(snd_card_t *card)
atiixp_dma_t *dma = &chip->dmas[i];
if (dma->substream && dma->suspended) {
dma->ops->enable_dma(chip, 1);
+ dma->substream->ops->prepare(dma->substream);
writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
chip->remap_addr + dma->ops->llp_offset);
writel(dma->saved_curptr, chip->remap_addr + dma->ops->dt_cur);
@@ -1530,7 +1531,7 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1644,6 +1645,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ATI IXP AC97 controller",
+ .owner = THIS_MODULE,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 8d20029..8a59598 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1208,7 +1208,7 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1318,6 +1318,7 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ATI IXP MC97 controller",
+ .owner = THIS_MODULE,
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index f6236c6..04b695d 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -79,19 +79,21 @@ static void vortex_fix_agp_bridge(struct pci_dev *via)
static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
{
- struct pci_dev *via;
+ struct pci_dev *via = NULL;
/* autodetect if workarounds are required */
if (fix == 255) {
/* VIA KT133 */
- via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8365_1, NULL);
+ via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8365_1, NULL);
/* VIA Apollo */
if (via == NULL) {
- via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, NULL);
- }
- /* AMD Irongate */
- if (via == NULL) {
- via = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
+ via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C598_1, NULL);
+ /* AMD Irongate */
+ if (via == NULL)
+ via = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
}
if (via) {
printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n");
@@ -101,13 +103,17 @@ static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
} else {
if (fix & 0x1)
vortex_fix_latency(vortex);
- if ((fix & 0x2) && (via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8365_1, NULL)))
+ if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8365_1, NULL)))
vortex_fix_agp_bridge(via);
- if ((fix & 0x4) && (via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, NULL)))
+ if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C598_1, NULL)))
vortex_fix_agp_bridge(via);
- if ((fix & 0x8) && (via = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
+ if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
vortex_fix_agp_bridge(via);
}
+ pci_dev_put(via);
}
// component-destructor
@@ -150,7 +156,7 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
}
pci_set_dma_mask(pci, VORTEX_DMA_MASK);
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -367,6 +373,7 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci)
// pci_driver definition
static struct pci_driver driver = {
.name = CARD_NAME_SHORT,
+ .owner = THIS_MODULE,
.id_table = snd_vortex_ids,
.probe = snd_vortex_probe,
.remove = __devexit_p(snd_vortex_remove),
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 72bba7b..d5261bd 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1345,7 +1345,7 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1511,6 +1511,7 @@ static void __devexit snd_azf3328_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "AZF3328",
+ .owner = THIS_MODULE,
.id_table = snd_azf3328_ids,
.probe = snd_azf3328_probe,
.remove = __devexit_p(snd_azf3328_remove),
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index c5557ea..2236c95 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -59,16 +59,6 @@ module_param(load_all, bool, 0444);
MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards");
-#ifndef PCI_VENDOR_ID_BROOKTREE
-#define PCI_VENDOR_ID_BROOKTREE 0x109e
-#endif
-#ifndef PCI_DEVICE_ID_BROOKTREE_878
-#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
-#endif
-#ifndef PCI_DEVICE_ID_BROOKTREE_879
-#define PCI_DEVICE_ID_BROOKTREE_879 0x0879
-#endif
-
/* register offsets */
#define REG_INT_STAT 0x100 /* interrupt status */
#define REG_INT_MASK 0x104 /* interrupt mask */
@@ -720,7 +710,7 @@ static int __devinit snd_bt87x_create(snd_card_t *card,
if (err < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip) {
pci_disable_device(pci);
return -ENOMEM;
@@ -911,6 +901,7 @@ static struct pci_device_id snd_bt87x_default_ids[] = {
static struct pci_driver driver = {
.name = "Bt87x",
+ .owner = THIS_MODULE,
.id_table = snd_bt87x_ids,
.probe = snd_bt87x_probe,
.remove = __devexit_p(snd_bt87x_remove),
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 7e27bfc..ba07960 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -352,7 +352,7 @@ static int snd_ca0106_pcm_open_playback_channel(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
@@ -419,7 +419,7 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL) {
snd_printk("open_capture_channel: failed epcm alloc\n");
return -ENOMEM;
@@ -1144,7 +1144,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1390,6 +1390,7 @@ MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
// pci_driver definition
static struct pci_driver driver = {
.name = "CA0106",
+ .owner = THIS_MODULE,
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
.remove = __devexit_p(snd_ca0106_remove),
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index b6b8882..c10e4a5 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -482,7 +482,7 @@ static int snd_ca0106_volume_put_feedback(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Front Volume",
+ .name = "Analog Front Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_front,
.put = snd_ca0106_volume_put_analog_front
@@ -490,7 +490,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Center/LFE Volume",
+ .name = "Analog Center/LFE Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_center_lfe,
.put = snd_ca0106_volume_put_analog_center_lfe
@@ -498,7 +498,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Side Volume",
+ .name = "Analog Side Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_unknown,
.put = snd_ca0106_volume_put_analog_unknown
@@ -506,7 +506,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Rear Volume",
+ .name = "Analog Rear Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_rear,
.put = snd_ca0106_volume_put_analog_rear
@@ -514,7 +514,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Front Volume",
+ .name = "SPDIF Front Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_front,
.put = snd_ca0106_volume_put_spdif_front
@@ -522,7 +522,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Center/LFE Volume",
+ .name = "SPDIF Center/LFE Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_center_lfe,
.put = snd_ca0106_volume_put_spdif_center_lfe
@@ -530,7 +530,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Unknown Volume",
+ .name = "SPDIF Unknown Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_unknown,
.put = snd_ca0106_volume_put_spdif_unknown
@@ -538,7 +538,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Rear Volume",
+ .name = "SPDIF Rear Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_spdif_rear,
.put = snd_ca0106_volume_put_spdif_rear
@@ -547,7 +547,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
static snd_kcontrol_new_t snd_ca0106_volume_control_feedback =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "CAPTURE feedback into PLAYBACK",
+ .name = "CAPTURE feedback Playback Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_feedback,
.put = snd_ca0106_volume_put_feedback
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index b098b51..1eb3315 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -79,13 +79,6 @@ module_param_array(joystick_port, int, NULL, 0444);
MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
-#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
-#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
-#endif
-
/*
* CM8x38 registers definition
*/
@@ -348,25 +341,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
/*
- * pci ids
- */
-#ifndef PCI_VENDOR_ID_CMEDIA
-#define PCI_VENDOR_ID_CMEDIA 0x13F6
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A
-#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B
-#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
-#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
-#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
-#endif
-
-/*
* channels for playback / capture
*/
#define CM_CH_PLAY 0
@@ -2801,7 +2775,7 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- cm = kcalloc(1, sizeof(*cm), GFP_KERNEL);
+ cm = kzalloc(sizeof(*cm), GFP_KERNEL);
if (cm == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -3063,6 +3037,7 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "C-Media PCI",
+ .owner = THIS_MODULE,
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
.remove = __devexit_p(snd_cmipci_remove),
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index c7a370d..dc87e01 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -57,17 +57,6 @@ module_param_array(dual_codec, bool, NULL, 0444);
MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
/*
- *
- */
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS 0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4281
-#define PCI_DEVICE_ID_CIRRUS_4281 0x6005
-#endif
-
-/*
* Direct registers
*/
@@ -1394,7 +1383,7 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
*rchip = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2119,6 +2108,7 @@ static int cs4281_resume(snd_card_t *card)
static struct pci_driver driver = {
.name = "CS4281",
+ .owner = THIS_MODULE,
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
.remove = __devexit_p(snd_cs4281_remove),
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index b9fff4e..32b4f84 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -163,6 +163,7 @@ static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Sound Fusion CS46xx",
+ .owner = THIS_MODULE,
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
.remove = __devexit_p(snd_card_cs46xx_remove),
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 4b05215..6e3855b 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1304,7 +1304,7 @@ static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pc
cs46xx_pcm_t * cpcm;
snd_pcm_runtime_t *runtime = substream->runtime;
- cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
+ cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL);
if (cpcm == NULL)
return -ENOMEM;
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
@@ -3525,17 +3525,6 @@ static void amp_voyetra_4294(cs46xx_t *chip, int change)
/*
- * piix4 pci ids
- */
-#ifndef PCI_VENDOR_ID_INTEL
-#define PCI_VENDOR_ID_INTEL 0x8086
-#endif /* PCI_VENDOR_ID_INTEL */
-
-#ifndef PCI_DEVICE_ID_INTEL_82371AB_3
-#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
-#endif /* PCI_DEVICE_ID_INTEL_82371AB_3 */
-
-/*
* Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
* whenever we need to beat on the chip.
*
@@ -3548,7 +3537,7 @@ static void clkrun_hack(cs46xx_t *chip, int change)
{
u16 control, nval;
- if (chip->acpi_dev == NULL)
+ if (!chip->acpi_port)
return;
chip->amplifier += change;
@@ -3571,15 +3560,20 @@ static void clkrun_hack(cs46xx_t *chip, int change)
*/
static void clkrun_init(cs46xx_t *chip)
{
+ struct pci_dev *pdev;
u8 pp;
- chip->acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
- if (chip->acpi_dev == NULL)
+ chip->acpi_port = 0;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+ if (pdev == NULL)
return; /* Not a thinkpad thats for sure */
/* Find the control port */
- pci_read_config_byte(chip->acpi_dev, 0x41, &pp);
+ pci_read_config_byte(pdev, 0x41, &pp);
chip->acpi_port = pp << 8;
+ pci_dev_put(pdev);
}
@@ -3780,7 +3774,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index fc377c4..b0e00f0 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -223,6 +223,7 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "EMU10K1_Audigy",
+ .owner = THIS_MODULE,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
.remove = __devexit_p(snd_card_emu10k1_remove),
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index e69d5b7..e87e842 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -754,12 +754,11 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
- /* Tested by alsa bugtrack user "hus" 12th Sept 2005 */
+ /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
- .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]",
+ .driver = "EMU10K1", .name = "SBLive! Platinum 5.1 [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
- .ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
@@ -865,7 +864,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
+ emu = kzalloc(sizeof(*emu), GFP_KERNEL);
if (emu == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 52c7826..ad15755 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -395,7 +395,7 @@ static int snd_emu10k1x_playback_open(snd_pcm_substream_t *substream)
if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
return err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = chip;
@@ -571,7 +571,7 @@ static int snd_emu10k1x_pcm_open_capture(snd_pcm_substream_t *substream)
if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
return err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
@@ -920,7 +920,7 @@ static int __devinit snd_emu10k1x_create(snd_card_t *card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1615,6 +1615,7 @@ MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
// pci_driver definition
static struct pci_driver driver = {
.name = "EMU10K1X",
+ .owner = THIS_MODULE,
.id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe,
.remove = __devexit_p(snd_emu10k1x_remove),
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 637c555..646b5d9 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -470,7 +470,7 @@ static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr
{
u_int32_t *code;
snd_assert(*ptr < 512, return);
- code = (u_int32_t *)icode->code + (*ptr) * 2;
+ code = (u_int32_t __force *)icode->code + (*ptr) * 2;
set_bit(*ptr, icode->code_valid);
code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
@@ -485,7 +485,7 @@ static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned i
{
u_int32_t *code;
snd_assert(*ptr < 1024, return);
- code = (u_int32_t *)icode->code + (*ptr) * 2;
+ code = (u_int32_t __force *)icode->code + (*ptr) * 2;
set_bit(*ptr, icode->code_valid);
code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
@@ -1036,13 +1036,13 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
spin_lock_init(&emu->fx8010.irq_lock);
INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
- if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||
+ if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL ||
(icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
(controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
}
- gpr_map = (u32 *)icode->gpr_map;
+ gpr_map = (u32 __force *)icode->gpr_map;
icode->tram_data_map = icode->gpr_map + 512;
icode->tram_addr_map = icode->tram_data_map + 256;
@@ -1431,7 +1431,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
__err:
kfree(controls);
if (icode != NULL) {
- kfree((void *)icode->gpr_map);
+ kfree((void __force *)icode->gpr_map);
kfree(icode);
}
return err;
@@ -1503,15 +1503,15 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
spin_lock_init(&emu->fx8010.irq_lock);
INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
- if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
+ if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL)
return -ENOMEM;
if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
(controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
- (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
+ (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
}
- gpr_map = (u32 *)icode->gpr_map;
+ gpr_map = (u32 __force *)icode->gpr_map;
icode->tram_data_map = icode->gpr_map + 256;
icode->tram_addr_map = icode->tram_data_map + 160;
@@ -2032,7 +2032,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
kfree(ipcm);
kfree(controls);
if (icode != NULL) {
- kfree((void *)icode->gpr_map);
+ kfree((void __force *)icode->gpr_map);
kfree(icode);
}
return err;
@@ -2217,7 +2217,7 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
kfree(ipcm);
return res;
case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
- ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
+ ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
if (ipcm == NULL)
return -ENOMEM;
if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 9c35f6d..66ba27a 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1016,7 +1016,7 @@ static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int i;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1049,7 +1049,7 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
int i, err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1094,7 +1094,7 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
emu10k1_pcm_t *epcm;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1130,7 +1130,7 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
emu10k1_pcm_t *epcm;
snd_pcm_runtime_t *runtime = substream->runtime;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
@@ -1170,7 +1170,7 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
int nefx = emu->audigy ? 64 : 32;
int idx;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
return -ENOMEM;
epcm->emu = emu;
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index a169133..d59c7f3 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -178,7 +178,7 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
//snd_printk("epcm kcalloc: %p\n", epcm);
if (epcm == NULL)
@@ -214,7 +214,7 @@ static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int
snd_pcm_runtime_t *runtime = substream->runtime;
int err;
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
//snd_printk("epcm kcalloc: %p\n", epcm);
if (epcm == NULL)
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index f06b95f..bef9a59 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -100,13 +100,6 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
#endif /* SUPPORT_JOYSTICK */
-#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
-#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
-#endif
-#ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
-#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
-#endif
-
/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -1950,7 +1943,7 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
*rensoniq = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
+ ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL);
if (ensoniq == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2394,6 +2387,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = DRIVER_NAME,
+ .owner = THIS_MODULE,
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
.remove = __devexit_p(snd_audiopci_remove),
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index b492777..17fa80c 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -76,13 +76,6 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
#define SUPPORT_JOYSTICK 1
#endif
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS 0x125d
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ES1938
-#define PCI_DEVICE_ID_ESS_ES1938 0x1969
-#endif
-
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
@@ -1501,7 +1494,7 @@ static int __devinit snd_es1938_create(snd_card_t * card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1753,6 +1746,7 @@ static void __devexit snd_es1938_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ESS ES1938 (Solo-1)",
+ .owner = THIS_MODULE,
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
.remove = __devexit_p(snd_es1938_remove),
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 9d7a287..ecdcada 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -160,25 +160,6 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
-/* PCI Dev ID's */
-
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS 0x125D
-#endif
-
-#define PCI_VENDOR_ID_ESS_OLD 0x1285 /* Platform Tech, the people the ESS
- was bought form */
-
-#ifndef PCI_DEVICE_ID_ESS_M2E
-#define PCI_DEVICE_ID_ESS_M2E 0x1978
-#endif
-#ifndef PCI_DEVICE_ID_ESS_M2
-#define PCI_DEVICE_ID_ESS_M2 0x1968
-#endif
-#ifndef PCI_DEVICE_ID_ESS_M1
-#define PCI_DEVICE_ID_ESS_M1 0x0100
-#endif
-
#define NR_APUS 64
#define NR_APU_REGS 16
@@ -1596,7 +1577,7 @@ static int snd_es1968_playback_open(snd_pcm_substream_t *substream)
if (apu1 < 0)
return apu1;
- es = kcalloc(1, sizeof(*es), GFP_KERNEL);
+ es = kzalloc(sizeof(*es), GFP_KERNEL);
if (!es) {
snd_es1968_free_apu_pair(chip, apu1);
return -ENOMEM;
@@ -1641,7 +1622,7 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
return apu2;
}
- es = kcalloc(1, sizeof(*es), GFP_KERNEL);
+ es = kzalloc(sizeof(*es), GFP_KERNEL);
if (!es) {
snd_es1968_free_apu_pair(chip, apu1);
snd_es1968_free_apu_pair(chip, apu2);
@@ -2588,7 +2569,7 @@ static int __devinit snd_es1968_create(snd_card_t * card,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2782,6 +2763,7 @@ static void __devexit snd_es1968_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ES1968 (ESS Maestro)",
+ .owner = THIS_MODULE,
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
.remove = __devexit_p(snd_es1968_remove),
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 36b2f62..e5cfa2a 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1263,7 +1263,7 @@ static int __devinit snd_fm801_create(snd_card_t * card,
*rchip = NULL;
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1462,6 +1462,7 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "FM801",
+ .owner = THIS_MODULE,
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
.remove = __devexit_p(snd_card_fm801_remove),
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 20f7762..3815403 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -288,7 +288,7 @@ static int init_unsol_queue(struct hda_bus *bus)
{
struct hda_bus_unsolicited *unsol;
- unsol = kcalloc(1, sizeof(*unsol), GFP_KERNEL);
+ unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
if (! unsol) {
snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
return -ENOMEM;
@@ -358,7 +358,7 @@ int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
if (busp)
*busp = NULL;
- bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL) {
snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
return -ENOMEM;
@@ -493,7 +493,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
return -EBUSY;
}
- codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+ codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (codec == NULL) {
snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
return -ENOMEM;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 63a29a8..bb53bcf 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -505,6 +505,7 @@ struct hda_pcm_stream {
struct hda_pcm {
char *name;
struct hda_pcm_stream stream[2];
+ unsigned int is_modem; /* modem codec? */
};
/* codec information */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 1229227..5b829a1 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -98,7 +98,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
struct hda_gnode *node;
int nconns;
- node = kcalloc(1, sizeof(*node), GFP_KERNEL);
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL)
return -ENOMEM;
node->nid = nid;
@@ -886,7 +886,7 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
return -ENODEV;
}
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL) {
printk(KERN_ERR "hda_generic: can't allocate spec\n");
return -ENOMEM;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 15107df..9590ece 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
@@ -164,7 +164,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* max buffer size - no h/w limit, you can increase as you like */
#define AZX_MAX_BUF_SIZE (1024*1024*1024)
/* max number of PCM devics per card */
-#define AZX_MAX_PCMS 8
+#define AZX_MAX_AUDIO_PCMS 6
+#define AZX_MAX_MODEM_PCMS 2
+#define AZX_MAX_PCMS (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
/* RIRB int mask: overrun[2], response[0] */
#define RIRB_INT_RESPONSE 0x01
@@ -211,9 +213,10 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* position fix mode */
enum {
- POS_FIX_FIFO,
+ POS_FIX_AUTO,
POS_FIX_NONE,
- POS_FIX_POSBUF
+ POS_FIX_POSBUF,
+ POS_FIX_FIFO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -243,6 +246,7 @@ struct snd_azx_dev {
unsigned int fragsize; /* size of each period in bytes */
unsigned int frags; /* number for period in the play buffer */
unsigned int fifo_size; /* FIFO size */
+ unsigned int last_pos; /* last updated period position */
void __iomem *sd_addr; /* stream descriptor pointer */
@@ -256,6 +260,7 @@ struct snd_azx_dev {
unsigned int opened: 1;
unsigned int running: 1;
+ unsigned int period_updating: 1;
};
/* CORB/RIRB */
@@ -724,11 +729,9 @@ static void azx_init_chip(azx_t *chip)
/* initialize the codec command I/O */
azx_init_cmd_io(chip);
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* program the position buffer */
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
- azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
- }
+ /* program the position buffer */
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+ azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
/* For ATI SB450 azalia HD audio, we need to enable snoop */
if (chip->driver_type == AZX_DRIVER_ATI) {
@@ -763,9 +766,11 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
if (status & azx_dev->sd_int_sta_mask) {
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
if (azx_dev->substream && azx_dev->running) {
+ azx_dev->period_updating = 1;
spin_unlock(&chip->reg_lock);
snd_pcm_period_elapsed(azx_dev->substream);
spin_lock(&chip->reg_lock);
+ azx_dev->period_updating = 0;
}
}
}
@@ -866,11 +871,9 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
/* upper BDL address */
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* enable the position buffer */
- if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
- }
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -1078,6 +1081,7 @@ static int azx_pcm_prepare(snd_pcm_substream_t *substream)
azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
else
azx_dev->fifo_size = 0;
+ azx_dev->last_pos = 0;
return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
azx_dev->format_val, substream);
@@ -1133,6 +1137,26 @@ static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
pos = azx_sd_readl(azx_dev, SD_LPIB);
if (chip->position_fix == POS_FIX_FIFO)
pos += azx_dev->fifo_size;
+ else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) {
+ /* check the validity of DMA position */
+ unsigned int diff = 0;
+ azx_dev->last_pos += azx_dev->fragsize;
+ if (azx_dev->last_pos > pos)
+ diff = azx_dev->last_pos - pos;
+ if (azx_dev->last_pos >= azx_dev->bufsize) {
+ if (pos < azx_dev->fragsize)
+ diff = 0;
+ azx_dev->last_pos = 0;
+ }
+ if (diff > 0 && diff <= azx_dev->fifo_size)
+ pos += azx_dev->fifo_size;
+ else {
+ snd_printdd(KERN_INFO "hda_intel: DMA position fix %d, switching to posbuf\n", diff);
+ chip->position_fix = POS_FIX_POSBUF;
+ pos = *azx_dev->posbuf;
+ }
+ azx_dev->period_updating = 0;
+ }
}
if (pos >= azx_dev->bufsize)
pos = 0;
@@ -1203,12 +1227,33 @@ static int __devinit azx_pcm_create(azx_t *chip)
if ((err = snd_hda_build_pcms(chip->bus)) < 0)
return err;
+ /* create audio PCMs */
pcm_dev = 0;
list_for_each(p, &chip->bus->codec_list) {
codec = list_entry(p, struct hda_codec, list);
for (c = 0; c < codec->num_pcms; c++) {
+ if (codec->pcm_info[c].is_modem)
+ continue; /* create later */
+ if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
+ snd_printk(KERN_ERR SFX "Too many audio PCMs\n");
+ return -EINVAL;
+ }
+ err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+ if (err < 0)
+ return err;
+ pcm_dev++;
+ }
+ }
+
+ /* create modem PCMs */
+ pcm_dev = AZX_MAX_AUDIO_PCMS;
+ list_for_each(p, &chip->bus->codec_list) {
+ codec = list_entry(p, struct hda_codec, list);
+ for (c = 0; c < codec->num_pcms; c++) {
+ if (! codec->pcm_info[c].is_modem)
+ continue; /* already created */
if (pcm_dev >= AZX_MAX_PCMS) {
- snd_printk(KERN_ERR SFX "Too many PCMs\n");
+ snd_printk(KERN_ERR SFX "Too many modem PCMs\n");
return -EINVAL;
}
err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
@@ -1244,8 +1289,7 @@ static int __devinit azx_init_stream(azx_t *chip)
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
azx_dev->bdl_addr = chip->bdl.addr + off;
- if (chip->position_fix == POS_FIX_POSBUF)
- azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+ azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1358,7 +1402,7 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (NULL == chip) {
snd_printk(KERN_ERR SFX "cannot allocate chip\n");
@@ -1437,13 +1481,11 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* allocate memory for the position buffer */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- chip->num_streams * 8, &chip->posbuf)) < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
- goto errout;
- }
+ /* allocate memory for the position buffer */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ chip->num_streams * 8, &chip->posbuf)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ goto errout;
}
/* allocate CORB/RIRB */
if ((err = azx_alloc_cmd_io(chip)) < 0)
@@ -1561,6 +1603,7 @@ MODULE_DEVICE_TABLE(pci, azx_ids);
/* pci_driver definition */
static struct pci_driver driver = {
.name = "HDA Intel",
+ .owner = THIS_MODULE,
.id_table = azx_ids,
.probe = azx_probe,
.remove = __devexit_p(azx_remove),
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index de1217b..08f6a6e 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -207,6 +207,8 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
+ if (! codec->afg)
+ return;
snd_iprintf(buffer, "Default PCM: ");
print_pcm_caps(buffer, codec, codec->afg);
snd_iprintf(buffer, "Default Amp-In caps: ");
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index bceb83a..da6874d 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -465,7 +465,7 @@ static int patch_ad1986a(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -623,7 +623,7 @@ static int patch_ad1983(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -764,7 +764,7 @@ static int patch_ad1981(struct hda_codec *codec)
{
struct ad198x_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 07fb4f5..523c362 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -667,7 +667,7 @@ static int patch_cmi9880(struct hda_codec *codec)
{
struct cmi_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index eeb900a..849b5b5 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1526,6 +1526,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
/* Back 3 jack, front 2 jack (Internal add Aux-In) */
{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
+ { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
@@ -1581,6 +1582,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
@@ -2093,7 +2095,7 @@ static int patch_alc880(struct hda_codec *codec)
int board_config;
int i, err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -2365,7 +2367,7 @@ static int patch_alc260(struct hda_codec *codec)
struct alc_spec *spec;
int board_config;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -2615,7 +2617,7 @@ static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index b0270d1..d014b7b 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -214,6 +214,7 @@ static int si3054_build_pcms(struct hda_codec *codec)
info->name = "Si3054 Modem";
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
+ info->is_modem = 1;
return 0;
}
@@ -282,7 +283,7 @@ static struct hda_codec_ops si3054_patch_ops = {
static int patch_si3054(struct hda_codec *codec)
{
- struct si3054_spec *spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ struct si3054_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
codec->spec = spec;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9d503da..33a8ada 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -919,7 +919,7 @@ static int patch_stac9200(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
@@ -957,7 +957,7 @@ static int patch_stac922x(struct hda_codec *codec)
struct sigmatel_spec *spec;
int err;
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 4405d96..2e0a316 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1796,7 +1796,7 @@ static int __devinit aureon_init(ice1712_t *ice)
}
/* to remeber the register values of CS8415 */
- ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ice->akm)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index b97f50d..a6d9801 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -100,12 +100,6 @@ MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec r
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
-#ifndef PCI_VENDOR_ID_ICE
-#define PCI_VENDOR_ID_ICE 0x1412
-#endif
-#ifndef PCI_DEVICE_ID_ICE_1712
-#define PCI_DEVICE_ID_ICE_1712 0x1712
-#endif
static struct pci_device_id snd_ice1712_ids[] = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */
@@ -2535,7 +2529,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
return -ENXIO;
}
- ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
+ ice = kzalloc(sizeof(*ice), GFP_KERNEL);
if (ice == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2741,6 +2735,7 @@ static void __devexit snd_ice1712_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ICE1712",
+ .owner = THIS_MODULE,
.id_table = snd_ice1712_ids,
.probe = snd_ice1712_probe,
.remove = __devexit_p(snd_ice1712_remove),
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index c7af5e5..c3ce8f9 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -83,12 +83,6 @@ MODULE_PARM_DESC(enable, "Enable ICE1724 soundcard.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
-#ifndef PCI_VENDOR_ID_ICE
-#define PCI_VENDOR_ID_ICE 0x1412
-#endif
-#ifndef PCI_DEVICE_ID_VT1724
-#define PCI_DEVICE_ID_VT1724 0x1724
-#endif
/* Both VT1720 and VT1724 have the same PCI IDs */
static struct pci_device_id snd_vt1724_ids[] = {
@@ -2130,7 +2124,7 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
+ ice = kzalloc(sizeof(*ice), GFP_KERNEL);
if (ice == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2321,6 +2315,7 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "ICE1724",
+ .owner = THIS_MODULE,
.id_table = snd_vt1724_ids,
.probe = snd_vt1724_probe,
.remove = __devexit_p(snd_vt1724_remove),
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 3fb297b..2437876 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -182,7 +182,7 @@ static int __devinit juli_init(ice1712_t *ice)
ice->num_total_dacs = 2;
ice->num_total_adcs = 2;
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index 5bf734b..dcf1e8c 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -122,7 +122,7 @@ static int __devinit phase22_init(ice1712_t *ice)
}
// Initialize analog chips
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -386,7 +386,7 @@ static int __devinit phase28_init(ice1712_t *ice)
ice->num_total_adcs = 2;
// Initialize analog chips
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (!ak)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 25f827d..a5f852b 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -781,7 +781,7 @@ static int __devinit pontis_init(ice1712_t *ice)
ice->num_total_adcs = 2;
/* to remeber the register values */
- ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
if (! ice->akm)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 7b54841..1a96198 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -69,6 +69,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static char *ac97_quirk[SNDRV_CARDS];
+static int buggy_semaphore[SNDRV_CARDS];
static int buggy_irq[SNDRV_CARDS];
static int xbox[SNDRV_CARDS];
@@ -86,6 +87,8 @@ module_param_array(ac97_clock, int, NULL, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
module_param_array(ac97_quirk, charp, NULL, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+module_param_array(buggy_semaphore, bool, NULL, 0444);
+MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores.");
module_param_array(buggy_irq, bool, NULL, 0444);
MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
module_param_array(xbox, bool, NULL, 0444);
@@ -94,62 +97,6 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 c
/*
* Direct registers
*/
-
-#ifndef PCI_DEVICE_ID_INTEL_82801
-#define PCI_DEVICE_ID_INTEL_82801 0x2415
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901
-#define PCI_DEVICE_ID_INTEL_82901 0x2425
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA
-#define PCI_DEVICE_ID_INTEL_82801BA 0x2445
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX
-#define PCI_DEVICE_ID_INTEL_440MX 0x7195
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3
-#define PCI_DEVICE_ID_INTEL_ICH3 0x2485
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4
-#define PCI_DEVICE_ID_INTEL_ICH4 0x24c5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5
-#define PCI_DEVICE_ID_INTEL_ICH5 0x24d5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB_5
-#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_18
-#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_20
-#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB2_14
-#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698
-#endif
-#ifndef PCI_DEVICE_ID_SI_7012
-#define PCI_DEVICE_ID_SI_7012 0x7012
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO 0x01b1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea
-#endif
-
enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
#define ICHREG(x) ICH_REG_##x
@@ -423,6 +370,7 @@ struct _snd_intel8x0 {
unsigned fix_nocache: 1; /* workaround for 440MX */
unsigned buggy_irq: 1; /* workaround for buggy mobos */
unsigned xbox: 1; /* workaround for Xbox AC'97 detection */
+ unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */
int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
unsigned int sdm_saved; /* SDM reg value */
@@ -577,6 +525,9 @@ static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
if ((igetdword(chip, ICHREG(GLOB_STA)) & codec) == 0)
return -EIO;
+ if (chip->buggy_semaphore)
+ return 0; /* just ignore ... */
+
/* Anyone holding a semaphore for 1 msec should be shot... */
time = 100;
do {
@@ -1759,6 +1710,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.type = AC97_TUNE_ALC_JACK
},
{
+ .subvendor = 0x1014,
+ .subdevice = 0x0267,
+ .name = "IBM NetVista A30p", /* AD1981B */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
.subvendor = 0x1028,
.subdevice = 0x00d8,
.name = "Dell Precision 530", /* AD1885 */
@@ -2599,6 +2556,7 @@ struct ich_reg_info {
static int __devinit snd_intel8x0_create(snd_card_t * card,
struct pci_dev *pci,
unsigned long device_type,
+ int buggy_sem,
intel8x0_t ** r_intel8x0)
{
intel8x0_t *chip;
@@ -2646,7 +2604,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2656,6 +2614,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
+ chip->buggy_semaphore = buggy_sem;
if (pci->vendor == PCI_VENDOR_ID_INTEL &&
pci->device == PCI_DEVICE_ID_INTEL_440MX)
@@ -2795,19 +2754,19 @@ static struct shortname_table {
unsigned int id;
const char *s;
} shortnames[] __devinitdata = {
- { PCI_DEVICE_ID_INTEL_82801, "Intel 82801AA-ICH" },
- { PCI_DEVICE_ID_INTEL_82901, "Intel 82901AB-ICH0" },
- { PCI_DEVICE_ID_INTEL_82801BA, "Intel 82801BA-ICH2" },
+ { PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
+ { PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
+ { PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
{ PCI_DEVICE_ID_INTEL_440MX, "Intel 440MX" },
- { PCI_DEVICE_ID_INTEL_ICH3, "Intel 82801CA-ICH3" },
- { PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" },
- { PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
+ { PCI_DEVICE_ID_INTEL_82801CA_5, "Intel 82801CA-ICH3" },
+ { PCI_DEVICE_ID_INTEL_82801DB_5, "Intel 82801DB-ICH4" },
+ { PCI_DEVICE_ID_INTEL_82801EB_5, "Intel ICH5" },
{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
{ PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
{ PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
{ PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" },
{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
- { PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
+ { PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, "NVidia nForce" },
{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
@@ -2860,7 +2819,8 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
}
}
- if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip)) < 0) {
+ if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
+ buggy_semaphore[dev], &chip)) < 0) {
snd_card_free(card);
return err;
}
@@ -2904,6 +2864,7 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Intel ICH",
+ .owner = THIS_MODULE,
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
.remove = __devexit_p(snd_intel8x0_remove),
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index bb758c7..9e2060d 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -73,51 +73,6 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
/*
* Direct registers
*/
-
-#ifndef PCI_DEVICE_ID_INTEL_82801_6
-#define PCI_DEVICE_ID_INTEL_82801_6 0x2416
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901_6
-#define PCI_DEVICE_ID_INTEL_82901_6 0x2426
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA_6
-#define PCI_DEVICE_ID_INTEL_82801BA_6 0x2446
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX_6
-#define PCI_DEVICE_ID_INTEL_440MX_6 0x7196
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3_6
-#define PCI_DEVICE_ID_INTEL_ICH3_6 0x2486
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4_6
-#define PCI_DEVICE_ID_INTEL_ICH4_6 0x24c6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5_6
-#define PCI_DEVICE_ID_INTEL_ICH5_6 0x24d6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_6
-#define PCI_DEVICE_ID_INTEL_ICH6_6 0x266d
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_6
-#define PCI_DEVICE_ID_INTEL_ICH7_6 0x27dd
-#endif
-#ifndef PCI_DEVICE_ID_SI_7013
-#define PCI_DEVICE_ID_SI_7013 0x7013
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP_MODEM 0x01c1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM 0x0069
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM 0x00d9
-#endif
-
-
enum { DEVICE_INTEL, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
#define ICHREG(x) ICH_REG_##x
@@ -1158,7 +1113,7 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1283,18 +1238,18 @@ static struct shortname_table {
unsigned int id;
const char *s;
} shortnames[] __devinitdata = {
- { PCI_DEVICE_ID_INTEL_82801_6, "Intel 82801AA-ICH" },
- { PCI_DEVICE_ID_INTEL_82901_6, "Intel 82901AB-ICH0" },
+ { PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },
+ { PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },
{ PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },
{ PCI_DEVICE_ID_INTEL_440MX_6, "Intel 440MX" },
- { PCI_DEVICE_ID_INTEL_ICH3_6, "Intel 82801CA-ICH3" },
- { PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
- { PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
- { PCI_DEVICE_ID_INTEL_ICH6_6, "Intel ICH6" },
- { PCI_DEVICE_ID_INTEL_ICH7_6, "Intel ICH7" },
+ { PCI_DEVICE_ID_INTEL_82801CA_6, "Intel 82801CA-ICH3" },
+ { PCI_DEVICE_ID_INTEL_82801DB_6, "Intel 82801DB-ICH4" },
+ { PCI_DEVICE_ID_INTEL_82801EB_6, "Intel ICH5" },
+ { PCI_DEVICE_ID_INTEL_ICH6_17, "Intel ICH6" },
+ { PCI_DEVICE_ID_INTEL_ICH7_19, "Intel ICH7" },
{ 0x7446, "AMD AMD768" },
{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
- { PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
+ { PCI_DEVICE_ID_NVIDIA_MCP1_MODEM, "NVidia nForce" },
{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
@@ -1371,6 +1326,7 @@ static void __devexit snd_intel8x0m_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Intel ICH Modem",
+ .owner = THIS_MODULE,
.id_table = snd_intel8x0m_ids,
.probe = snd_intel8x0m_probe,
.remove = __devexit_p(snd_intel8x0m_remove),
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index d2aa9c8..09f9cbe 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2220,7 +2220,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- korg1212 = kcalloc(1, sizeof(*korg1212), GFP_KERNEL);
+ korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL);
if (korg1212 == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2534,6 +2534,7 @@ static void __devexit snd_korg1212_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "korg1212",
+ .owner = THIS_MODULE,
.id_table = snd_korg1212_ids,
.probe = snd_korg1212_probe,
.remove = __devexit_p(snd_korg1212_remove),
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 39b5e7d..2693b6f 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -872,35 +872,6 @@ struct snd_m3 {
/*
* pci ids
*/
-
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS 0x125D
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ALLEGRO_1
-#define PCI_DEVICE_ID_ESS_ALLEGRO_1 0x1988
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ALLEGRO
-#define PCI_DEVICE_ID_ESS_ALLEGRO 0x1989
-#endif
-#ifndef PCI_DEVICE_ID_ESS_CANYON3D_2LE
-#define PCI_DEVICE_ID_ESS_CANYON3D_2LE 0x1990
-#endif
-#ifndef PCI_DEVICE_ID_ESS_CANYON3D_2
-#define PCI_DEVICE_ID_ESS_CANYON3D_2 0x1992
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3
-#define PCI_DEVICE_ID_ESS_MAESTRO3 0x1998
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_1
-#define PCI_DEVICE_ID_ESS_MAESTRO3_1 0x1999
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_HW
-#define PCI_DEVICE_ID_ESS_MAESTRO3_HW 0x199a
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_2
-#define PCI_DEVICE_ID_ESS_MAESTRO3_2 0x199b
-#endif
-
static struct pci_device_id snd_m3_ids[] = {
{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
@@ -2689,7 +2660,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
return -ENXIO;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -2890,6 +2861,7 @@ static void __devexit snd_m3_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Maestro3",
+ .owner = THIS_MODULE,
.id_table = snd_m3_ids,
.probe = snd_m3_probe,
.remove = __devexit_p(snd_m3_remove),
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 6c868d9..1a62c7f 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1004,7 +1004,7 @@ static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int
.dev_free = snd_mixart_chip_dev_free,
};
- mgr->chip[idx] = chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "cannot allocate chip\n");
return -ENOMEM;
@@ -1292,7 +1292,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
/*
*/
- mgr = kcalloc(1, sizeof(*mgr), GFP_KERNEL);
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
if (! mgr) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1424,6 +1424,7 @@ static void __devexit snd_mixart_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Digigram miXart",
+ .owner = THIS_MODULE,
.id_table = snd_mixart_ids,
.probe = snd_mixart_probe,
.remove = __devexit_p(snd_mixart_remove),
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 2bbeb10..5c55a3b 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -259,21 +259,6 @@ struct snd_nm256 {
/*
* PCI ids
*/
-
-#ifndef PCI_VENDOR_ID_NEOMAGIC
-#define PCI_VENDOR_ID_NEOMEGIC 0x10c8
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-#endif
-
-
static struct pci_device_id snd_nm256_ids[] = {
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -840,7 +825,7 @@ static void snd_nm256_setup_stream(nm256_t *chip, nm256_stream_t *s,
runtime->hw = *hw_ptr;
runtime->hw.buffer_bytes_max = s->bufsize;
runtime->hw.period_bytes_max = s->bufsize / 2;
- runtime->dma_area = (void*) s->bufptr;
+ runtime->dma_area = (void __force *) s->bufptr;
runtime->dma_addr = s->bufptr_addr;
runtime->dma_bytes = s->bufsize;
runtime->private_data = s;
@@ -1404,7 +1389,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1683,6 +1668,7 @@ static void __devexit snd_nm256_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "NeoMagic 256",
+ .owner = THIS_MODULE,
.id_table = snd_nm256_ids,
.probe = snd_nm256_probe,
.remove = __devexit_p(snd_nm256_remove),
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 456be39..cd313af 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -192,20 +192,6 @@ MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
#define RME32_PRO_REVISION_WITH_8414 150
-/* PCI vendor/device ID's */
-#ifndef PCI_VENDOR_ID_XILINX_RME
-# define PCI_VENDOR_ID_XILINX_RME 0xea60
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32
-# define PCI_DEVICE_ID_DIGI32 0x9896
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32_PRO
-# define PCI_DEVICE_ID_DIGI32_PRO 0x9897
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32_8
-# define PCI_DEVICE_ID_DIGI32_8 0x9898
-#endif
-
typedef struct snd_rme32 {
spinlock_t lock;
int irq;
@@ -242,11 +228,11 @@ typedef struct snd_rme32 {
} rme32_t;
static struct pci_device_id snd_rme32_ids[] = {
- {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32,
+ {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
- {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32_8,
+ {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
- {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32_PRO,
+ {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{0,}
};
@@ -254,7 +240,7 @@ static struct pci_device_id snd_rme32_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_rme32_ids);
#define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START)
-#define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414)
+#define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414)
static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream);
@@ -541,21 +527,21 @@ static int snd_rme32_playback_setrate(rme32_t * rme32, int rate)
RME32_WCR_FREQ_1;
break;
case 64000:
- if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO)
+ if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)
return -EINVAL;
rme32->wcreg |= RME32_WCR_DS_BM;
rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) &
~RME32_WCR_FREQ_1;
break;
case 88200:
- if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO)
+ if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)
return -EINVAL;
rme32->wcreg |= RME32_WCR_DS_BM;
rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) &
~RME32_WCR_FREQ_0;
break;
case 96000:
- if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO)
+ if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)
return -EINVAL;
rme32->wcreg |= RME32_WCR_DS_BM;
rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) |
@@ -692,7 +678,8 @@ snd_rme32_playback_hw_params(snd_pcm_substream_t * substream,
if (err < 0)
return err;
} else {
- runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+ runtime->dma_area = (void __force *)(rme32->iobase +
+ RME32_IO_DATA_BUFFER);
runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
runtime->dma_bytes = RME32_BUFFER_SIZE;
}
@@ -746,7 +733,8 @@ snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
if (err < 0)
return err;
} else {
- runtime->dma_area = (void *)rme32->iobase + RME32_IO_DATA_BUFFER;
+ runtime->dma_area = (void __force *)rme32->iobase +
+ RME32_IO_DATA_BUFFER;
runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
runtime->dma_bytes = RME32_BUFFER_SIZE;
}
@@ -893,7 +881,7 @@ static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
runtime->hw = snd_rme32_spdif_fd_info;
else
runtime->hw = snd_rme32_spdif_info;
- if (rme32->pci->device == PCI_DEVICE_ID_DIGI32_PRO) {
+ if (rme32->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO) {
runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;
runtime->hw.rate_max = 96000;
}
@@ -1420,8 +1408,8 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
}
/* set up ALSA pcm device for ADAT */
- if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
- (pci->device == PCI_DEVICE_ID_DIGI32_PRO)) {
+ if ((pci->device == PCI_DEVICE_ID_RME_DIGI32) ||
+ (pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO)) {
/* ADAT is not available on DIGI32 and DIGI32 Pro */
rme32->adat_pcm = NULL;
}
@@ -1651,11 +1639,11 @@ snd_rme32_info_inputtype_control(snd_kcontrol_t * kcontrol,
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
switch (rme32->pci->device) {
- case PCI_DEVICE_ID_DIGI32:
- case PCI_DEVICE_ID_DIGI32_8:
+ case PCI_DEVICE_ID_RME_DIGI32:
+ case PCI_DEVICE_ID_RME_DIGI32_8:
uinfo->value.enumerated.items = 3;
break;
- case PCI_DEVICE_ID_DIGI32_PRO:
+ case PCI_DEVICE_ID_RME_DIGI32_PRO:
uinfo->value.enumerated.items = 4;
break;
default:
@@ -1682,11 +1670,11 @@ snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol,
ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32);
switch (rme32->pci->device) {
- case PCI_DEVICE_ID_DIGI32:
- case PCI_DEVICE_ID_DIGI32_8:
+ case PCI_DEVICE_ID_RME_DIGI32:
+ case PCI_DEVICE_ID_RME_DIGI32_8:
items = 3;
break;
- case PCI_DEVICE_ID_DIGI32_PRO:
+ case PCI_DEVICE_ID_RME_DIGI32_PRO:
items = 4;
break;
default:
@@ -1709,11 +1697,11 @@ snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol,
int change, items = 3;
switch (rme32->pci->device) {
- case PCI_DEVICE_ID_DIGI32:
- case PCI_DEVICE_ID_DIGI32_8:
+ case PCI_DEVICE_ID_RME_DIGI32:
+ case PCI_DEVICE_ID_RME_DIGI32_8:
items = 3;
break;
- case PCI_DEVICE_ID_DIGI32_PRO:
+ case PCI_DEVICE_ID_RME_DIGI32_PRO:
items = 4;
break;
default:
@@ -1994,13 +1982,13 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
strcpy(card->driver, "Digi32");
switch (rme32->pci->device) {
- case PCI_DEVICE_ID_DIGI32:
+ case PCI_DEVICE_ID_RME_DIGI32:
strcpy(card->shortname, "RME Digi32");
break;
- case PCI_DEVICE_ID_DIGI32_8:
+ case PCI_DEVICE_ID_RME_DIGI32_8:
strcpy(card->shortname, "RME Digi32/8");
break;
- case PCI_DEVICE_ID_DIGI32_PRO:
+ case PCI_DEVICE_ID_RME_DIGI32_PRO:
strcpy(card->shortname, "RME Digi32 PRO");
break;
}
@@ -2024,6 +2012,7 @@ static void __devexit snd_rme32_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Digi32",
+ .owner = THIS_MODULE,
.id_table = snd_rme32_ids,
.probe = snd_rme32_probe,
.remove = __devexit_p(snd_rme32_remove),
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 9645e90..c495cae 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -200,25 +200,6 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
#define RME96_AD1852_VOL_BITS 14
#define RME96_AD1855_VOL_BITS 10
-/*
- * PCI vendor/device ids, could in the future be defined in <linux/pci.h>,
- * therefore #ifndef is used.
- */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96
-#define PCI_DEVICE_ID_DIGI96 0x3fc0
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8
-#define PCI_DEVICE_ID_DIGI96_8 0x3fc1
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8_PRO
-#define PCI_DEVICE_ID_DIGI96_8_PRO 0x3fc2
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST
-#define PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST 0x3fc3
-#endif
typedef struct snd_rme96 {
spinlock_t lock;
@@ -252,13 +233,13 @@ typedef struct snd_rme96 {
} rme96_t;
static struct pci_device_id snd_rme96_ids[] = {
- { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96,
+ { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
- { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8,
+ { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
- { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8_PRO,
+ { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
- { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST,
+ { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ 0, }
};
@@ -267,12 +248,12 @@ MODULE_DEVICE_TABLE(pci, snd_rme96_ids);
#define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START)
#define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2)
-#define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST)
-#define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PRO || \
- (rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST)
+#define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST)
+#define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO || \
+ (rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST)
#define RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4)
-#define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \
- ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PRO && (rme96)->rev == 2))
+#define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \
+ ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO && (rme96)->rev == 2))
#define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1)
static int
@@ -849,9 +830,9 @@ snd_rme96_setinputtype(rme96_t *rme96,
RME96_WCR_INP_1;
break;
case RME96_INPUT_XLR:
- if ((rme96->pci->device != PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST &&
- rme96->pci->device != PCI_DEVICE_ID_DIGI96_8_PRO) ||
- (rme96->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST &&
+ if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST &&
+ rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) ||
+ (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST &&
rme96->rev > 4))
{
/* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */
@@ -985,7 +966,8 @@ snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
int err, rate, dummy;
- runtime->dma_area = (void *)(rme96->iobase + RME96_IO_PLAY_BUFFER);
+ runtime->dma_area = (void __force *)(rme96->iobase +
+ RME96_IO_PLAY_BUFFER);
runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;
runtime->dma_bytes = RME96_BUFFER_SIZE;
@@ -1037,7 +1019,8 @@ snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
snd_pcm_runtime_t *runtime = substream->runtime;
int err, isadat, rate;
- runtime->dma_area = (void *)(rme96->iobase + RME96_IO_REC_BUFFER);
+ runtime->dma_area = (void __force *)(rme96->iobase +
+ RME96_IO_REC_BUFFER);
runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;
runtime->dma_bytes = RME96_BUFFER_SIZE;
@@ -1615,7 +1598,7 @@ snd_rme96_create(rme96_t *rme96)
rme96->spdif_pcm->info_flags = 0;
/* set up ALSA pcm device for ADAT */
- if (pci->device == PCI_DEVICE_ID_DIGI96) {
+ if (pci->device == PCI_DEVICE_ID_RME_DIGI96) {
/* ADAT is not available on the base model */
rme96->adat_pcm = NULL;
} else {
@@ -1875,14 +1858,14 @@ snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
switch (rme96->pci->device) {
- case PCI_DEVICE_ID_DIGI96:
- case PCI_DEVICE_ID_DIGI96_8:
+ case PCI_DEVICE_ID_RME_DIGI96:
+ case PCI_DEVICE_ID_RME_DIGI96_8:
uinfo->value.enumerated.items = 3;
break;
- case PCI_DEVICE_ID_DIGI96_8_PRO:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
uinfo->value.enumerated.items = 4;
break;
- case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
if (rme96->rev > 4) {
/* PST */
uinfo->value.enumerated.items = 4;
@@ -1912,14 +1895,14 @@ snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96);
switch (rme96->pci->device) {
- case PCI_DEVICE_ID_DIGI96:
- case PCI_DEVICE_ID_DIGI96_8:
+ case PCI_DEVICE_ID_RME_DIGI96:
+ case PCI_DEVICE_ID_RME_DIGI96_8:
items = 3;
break;
- case PCI_DEVICE_ID_DIGI96_8_PRO:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
items = 4;
break;
- case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
if (rme96->rev > 4) {
/* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */
if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) {
@@ -1949,14 +1932,14 @@ snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
int change, items = 3;
switch (rme96->pci->device) {
- case PCI_DEVICE_ID_DIGI96:
- case PCI_DEVICE_ID_DIGI96_8:
+ case PCI_DEVICE_ID_RME_DIGI96:
+ case PCI_DEVICE_ID_RME_DIGI96_8:
items = 3;
break;
- case PCI_DEVICE_ID_DIGI96_8_PRO:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
items = 4;
break;
- case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
if (rme96->rev > 4) {
items = 4;
} else {
@@ -1970,7 +1953,7 @@ snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
val = ucontrol->value.enumerated.item[0] % items;
/* special case for PST */
- if (rme96->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && rme96->rev > 4) {
+ if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) {
if (val == RME96_INPUT_XLR) {
val = RME96_INPUT_ANALOG;
}
@@ -2392,16 +2375,16 @@ snd_rme96_probe(struct pci_dev *pci,
strcpy(card->driver, "Digi96");
switch (rme96->pci->device) {
- case PCI_DEVICE_ID_DIGI96:
+ case PCI_DEVICE_ID_RME_DIGI96:
strcpy(card->shortname, "RME Digi96");
break;
- case PCI_DEVICE_ID_DIGI96_8:
+ case PCI_DEVICE_ID_RME_DIGI96_8:
strcpy(card->shortname, "RME Digi96/8");
break;
- case PCI_DEVICE_ID_DIGI96_8_PRO:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
strcpy(card->shortname, "RME Digi96/8 PRO");
break;
- case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+ case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
pci_read_config_byte(rme96->pci, 8, &val);
if (val < 5) {
strcpy(card->shortname, "RME Digi96/8 PAD");
@@ -2430,6 +2413,7 @@ static void __devexit snd_rme96_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Digi96",
+ .owner = THIS_MODULE,
.id_table = snd_rme96_ids,
.probe = snd_rme96_probe,
.remove = __devexit_p(snd_rme96_remove),
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 6694866..52525eb 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -370,13 +370,6 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
#define UNITY_GAIN 32768
#define MINUS_INFINITY_GAIN 0
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-
/* the size of a substream (1 mono data stream) */
#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
@@ -4899,6 +4892,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
}
if (!(hdsp->state & HDSP_InitializationComplete)) {
+ strcpy(card->shortname, "Hammerfall DSP");
sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
hdsp->port, hdsp->irq);
@@ -5222,6 +5216,7 @@ static void __devexit snd_hdsp_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Hammerfall DSP",
+ .owner = THIS_MODULE,
.id_table = snd_hdsp_ids,
.probe = snd_hdsp_probe,
.remove = __devexit_p(snd_hdsp_remove),
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 5d786d1..fc3f328 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -301,18 +301,6 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define UNITY_GAIN 32768 /* = 65536/2 */
#define MINUS_INFINITY_GAIN 0
-/* PCI info */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-#endif
-
-
/* Number of channels for different Speed Modes */
#define MADI_SS_CHANNELS 64
#define MADI_DS_CHANNELS 32
@@ -3652,6 +3640,7 @@ static void __devexit snd_hdspm_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Hammerfall DSP MADI",
+ .owner = THIS_MODULE,
.id_table = snd_hdspm_ids,
.probe = snd_hdspm_probe,
.remove = __devexit_p(snd_hdspm_remove),
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 8ee4d6f..b600f45 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -120,13 +120,6 @@ MODULE_SUPPORTED_DEVICE("{{RME,Hammerfall},"
#define RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos))
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4
-#endif
-
/* amount of io space we remap for register access. i'm not sure we
even need this much, but 1K is nice round number :)
*/
@@ -2661,6 +2654,7 @@ static void __devexit snd_rme9652_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "RME Digi9652 (Hammerfall)",
+ .owner = THIS_MODULE,
.id_table = snd_rme9652_ids,
.probe = snd_rme9652_probe,
.remove = __devexit_p(snd_rme9652_remove),
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 60ecb2b..1f6c2bf 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -50,13 +50,6 @@ MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
#define SUPPORT_JOYSTICK 1
#endif
-#ifndef PCI_VENDOR_ID_S3
-#define PCI_VENDOR_ID_S3 0x5333
-#endif
-#ifndef PCI_DEVICE_ID_S3_SONICVIBES
-#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00
-#endif
-
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
@@ -1257,7 +1250,7 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card,
return -ENXIO;
}
- sonic = kcalloc(1, sizeof(*sonic), GFP_KERNEL);
+ sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
if (sonic == NULL) {
pci_disable_device(pci);
return -ENOMEM;
@@ -1515,6 +1508,7 @@ static void __devexit snd_sonic_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "S3 SonicVibes",
+ .owner = THIS_MODULE,
.id_table = snd_sonic_ids,
.probe = snd_sonic_probe,
.remove = __devexit_p(snd_sonic_remove),
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 940d531..a8ca8e1 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -177,6 +177,7 @@ static void __devexit snd_trident_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Trident4DWaveAudio",
+ .owner = THIS_MODULE,
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
.remove = __devexit_p(snd_trident_remove),
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index f30d9d9..777da9a 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2960,7 +2960,7 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
.read = snd_trident_codec_read,
};
- uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return -ENOMEM;
@@ -3546,7 +3546,7 @@ int __devinit snd_trident_create(snd_card_t * card,
return -ENXIO;
}
- trident = kcalloc(1, sizeof(*trident), GFP_KERNEL);
+ trident = kzalloc(sizeof(*trident), GFP_KERNEL);
if (trident == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 56c6e52..6db7de6 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -104,14 +104,6 @@ module_param_array(dxs_support, int, NULL, 0444);
MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
-/* pci ids */
-#ifndef PCI_DEVICE_ID_VIA_82C686_5
-#define PCI_DEVICE_ID_VIA_82C686_5 0x3058
-#endif
-#ifndef PCI_DEVICE_ID_VIA_8233_5
-#define PCI_DEVICE_ID_VIA_8233_5 0x3059
-#endif
-
/* revision numbers for via686 */
#define VIA_REV_686_A 0x10
#define VIA_REV_686_B 0x11
@@ -1935,11 +1927,12 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
* DXS channels don't work properly with VRA if MC97 is disabled.
*/
struct pci_dev *pci;
- pci = pci_find_device(0x1106, 0x3068, NULL); /* MC97 */
+ pci = pci_get_device(0x1106, 0x3068, NULL); /* MC97 */
if (pci) {
unsigned char data;
pci_read_config_byte(pci, 0x44, &data);
pci_write_config_byte(pci, 0x44, data | 0x40);
+ pci_dev_put(pci);
}
}
@@ -2065,7 +2058,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) {
+ if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
@@ -2350,6 +2343,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "VIA 82xx Audio",
+ .owner = THIS_MODULE,
.id_table = snd_via82xx_ids,
.probe = snd_via82xx_probe,
.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 5872d43..7eac6f6 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1083,7 +1083,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) {
+ if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
@@ -1207,6 +1207,7 @@ static void __devexit snd_via82xx_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "VIA 82xx Modem",
+ .owner = THIS_MODULE,
.id_table = snd_via82xx_modem_ids,
.probe = snd_via82xx_probe,
.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index dca6bd2..2a7ad9d 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -252,6 +252,7 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Digigram VX222",
+ .owner = THIS_MODULE,
.id_table = snd_vx222_ids,
.probe = snd_vx222_probe,
.remove = __devexit_p(snd_vx222_remove),
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 5b5b624..2e69abe 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -352,6 +352,7 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
static struct pci_driver driver = {
.name = "Yamaha DS-XG PCI",
+ .owner = THIS_MODULE,
.id_table = snd_ymfpci_ids,
.probe = snd_card_ymfpci_probe,
.remove = __devexit_p(snd_card_ymfpci_remove),
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 0548364..27fa523 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -839,7 +839,7 @@ static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm;
- ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
+ ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
return -ENOMEM;
ypcm->chip = chip;
@@ -957,7 +957,7 @@ static int snd_ymfpci_capture_open(snd_pcm_substream_t * substream,
snd_pcm_runtime_t *runtime = substream->runtime;
ymfpci_pcm_t *ypcm;
- ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
+ ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
return -ENOMEM;
ypcm->chip = chip;
@@ -2270,7 +2270,7 @@ int __devinit snd_ymfpci_create(snd_card_t * card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index a2132e3..0208c54 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -151,7 +151,7 @@ pdacf_t *snd_pdacf_create(snd_card_t *card)
{
pdacf_t *chip;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return NULL;
chip->card = card;
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index 75213bf..206b933 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -13,11 +13,24 @@ config SND_POWERMAC
tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
depends on SND && I2C && INPUT && PPC_PMAC
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for the integrated sound device.
To compile this driver as a module, choose M here: the module
will be called snd-powermac.
-endmenu
+config SND_POWERMAC_AUTO_DRC
+ bool "Toggle DRC automatically at headphone/line plug-in"
+ depends on SND_POWERMAC
+ default y
+ help
+ Say Y here to enable the automatic toggle of DRC (dynamic
+ range compression) on Tumbler/Snapper.
+ If this feature is enabled, DRC is turned off when the
+ headphone/line jack is plugged, and turned on when unplugged.
+ Note that you can turn on/off DRC manually even without this
+ option.
+
+endmenu
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index c89e82e..e35b48d 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -988,6 +988,7 @@ static int __init snd_pmac_detect(pmac_t *chip)
case 0x33:
case 0x29:
case 0x24:
+ case 0x5c:
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
chip->model = PMAC_SNAPPER;
chip->can_byte_swap = 0; /* FIXME: check this */
@@ -1159,7 +1160,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
snd_runtime_check(chip_return, return -EINVAL);
*chip_return = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->card = card;
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 231f643..a6d8cbf 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -131,6 +131,9 @@ static int __init snd_pmac_probe(void)
if (enable_beep)
snd_pmac_attach_beep(chip);
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto __error;
+
if ((err = snd_card_register(card)) < 0)
goto __error;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index b94437c..65384af 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -948,7 +948,6 @@ static void device_change_handler(void *self)
msleep(10);
check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
chip->speaker_sw_ctl);
- mix->drc_enable = 0;
} else {
/* unmute speaker, mute others */
check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
@@ -960,20 +959,21 @@ static void device_change_handler(void *self)
if (mix->line_mute.addr != 0)
check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,
chip->lineout_sw_ctl);
- mix->drc_enable = 1;
}
- if (mix->auto_mute_notify) {
+ if (mix->auto_mute_notify)
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->hp_detect_ctl->id);
+
+#ifdef CONFIG_SND_POWERMAC_AUTO_DRC
+ mix->drc_enable = ! (headphone || lineout);
+ if (mix->auto_mute_notify)
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->drc_sw_ctl->id);
- }
-
- /* first set the DRC so the speaker do not explode -ReneR */
if (chip->model == PMAC_TUMBLER)
tumbler_set_drc(mix);
else
snapper_set_drc(mix);
+#endif
/* reset the master volume so the correct amplification is applied */
tumbler_set_master_volume(mix);
@@ -1370,6 +1370,17 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
return err;
+ /* set initial DRC range to 60% */
+ if (chip->model == PMAC_TUMBLER)
+ mix->drc_range = (TAS3001_DRC_MAX * 6) / 10;
+ else
+ mix->drc_range = (TAS3004_DRC_MAX * 6) / 10;
+ mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */
+ if (chip->model == PMAC_TUMBLER)
+ tumbler_set_drc(mix);
+ else
+ snapper_set_drc(mix);
+
#ifdef CONFIG_PM
chip->suspend = tumbler_suspend;
chip->resume = tumbler_resume;
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig
index 25a8a55..09ab138 100644
--- a/sound/sparc/Kconfig
+++ b/sound/sparc/Kconfig
@@ -7,6 +7,7 @@ config SND_SUN_AMD7930
tristate "Sun AMD7930"
depends on SBUS && SND
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD7930 sound device on Sun.
@@ -17,6 +18,7 @@ config SND_SUN_CS4231
tristate "Sun CS4231"
depends on SND
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for CS4231 sound device on Sun.
@@ -27,6 +29,7 @@ config SND_SUN_DBRI
tristate "Sun DBRI"
depends on SND && SBUS
select SND_PCM
+ select SND_GENERIC_DRIVER
help
Say Y here to include support for DBRI sound device on Sun.
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index bd8a850..46d504b 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -967,7 +967,7 @@ static int __init snd_amd7930_create(snd_card_t *card,
int err;
*ramd = NULL;
- amd = kcalloc(1, sizeof(*amd), GFP_KERNEL);
+ amd = kzalloc(sizeof(*amd), GFP_KERNEL);
if (amd == NULL)
return -ENOMEM;
@@ -1088,6 +1088,9 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
if ((err = snd_amd7930_mixer(amd)) < 0)
goto out_err;
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto out_err;
+
if ((err = snd_card_register(card)) < 0)
goto out_err;
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 36f9fe4..2fb27c4 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1915,6 +1915,9 @@ static int cs4231_attach_finish(snd_card_t *card, cs4231_t *chip)
if ((err = snd_cs4231_timer(chip)) < 0)
goto out_err;
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto out_err;
+
if ((err = snd_card_register(card)) < 0)
goto out_err;
@@ -1966,7 +1969,7 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -2080,7 +2083,7 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
int err;
*rchip = NULL;
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 941c7b1..b5c4c15 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -1,6 +1,6 @@
/*
* Driver for DBRI sound chip found on Sparcs.
- * Copyright (C) 2004 Martin Habets (mhabets@users.sourceforge.net)
+ * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net)
*
* Based entirely upon drivers/sbus/audio/dbri.c which is:
* Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -43,6 +43,12 @@
* audio devices. But the SUN HW group decided against it, at least on my
* LX the speakerbox connector has at least 1 pin missing and 1 wrongly
* connected.
+ *
+ * I've tried to stick to the following function naming conventions:
+ * snd_* ALSA stuff
+ * cs4215_* CS4215 codec specfic stuff
+ * dbri_* DBRI high-level stuff
+ * other DBRI low-level stuff
*/
#include <sound/driver.h>
@@ -87,7 +93,7 @@ MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard.");
#define D_DESC (1<<5)
static int dbri_debug = 0;
-module_param(dbri_debug, int, 0444);
+module_param(dbri_debug, int, 0644);
MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
#ifdef DBRI_DEBUG
@@ -320,7 +326,8 @@ typedef struct snd_dbri {
void __iomem *regs; /* dbri HW regs */
int dbri_version; /* 'e' and up is OK */
int dbri_irqp; /* intr queue pointer */
- int wait_seen;
+ int wait_send; /* sequence of command buffers send */
+ int wait_ackd; /* sequence of command buffers acknowledged */
struct dbri_pipe pipes[DBRI_NO_PIPES]; /* DBRI's 32 data pipes */
struct dbri_desc descs[DBRI_NO_DESCS];
@@ -625,16 +632,13 @@ static __u32 reverse_bytes(__u32 b, int len)
Commands are sent to the DBRI by building a list of them in memory,
then writing the address of the first list item to DBRI register 8.
-The list is terminated with a WAIT command, which can generate a
-CPU interrupt if required.
+The list is terminated with a WAIT command, which generates a
+CPU interrupt to signal completion.
Since the DBRI can run in parallel with the CPU, several means of
-synchronization present themselves. The original scheme (Rudolf's)
-was to set a flag when we "cmdlock"ed the DBRI, clear the flag when
-an interrupt signaled completion, and wait on a wait_queue if a routine
-attempted to cmdlock while the flag was set. The problems arose when
-we tried to cmdlock from inside an interrupt handler, which might
-cause scheduling in an interrupt (if we waited), etc, etc
+synchronization present themselves. The method implemented here is close
+to the original scheme (Rudolf's), and uses 2 counters (wait_send and
+wait_ackd) to synchronize the command buffer between the CPU and the DBRI.
A more sophisticated scheme might involve a circular command buffer
or an array of command buffers. A routine could fill one with
@@ -642,70 +646,75 @@ commands and link it onto a list. When a interrupt signaled
completion of the current command buffer, look on the list for
the next one.
-I've decided to implement something much simpler - after each command,
-the CPU waits for the DBRI to finish the command by polling the P bit
-in DBRI register 0. I've tried to implement this in such a way
-that might make implementing a more sophisticated scheme easier.
-
Every time a routine wants to write commands to the DBRI, it must
first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd
-in return. After the commands have been writen, dbri_cmdsend() is
-called with the final pointer value.
+in return. dbri_cmdlock() will block if the previous commands have not
+been completed yet. After this the commands can be written to the buffer,
+and dbri_cmdsend() is called with the final pointer value to send them
+to the DBRI.
*/
+static void dbri_process_interrupt_buffer(snd_dbri_t * dbri);
+
enum dbri_lock_t { NoGetLock, GetLock };
+#define MAXLOOPS 10
static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get)
{
+ int maxloops = MAXLOOPS;
+
#ifndef SMP
if ((get == GetLock) && spin_is_locked(&dbri->lock)) {
printk(KERN_ERR "DBRI: cmdlock called while in spinlock.");
}
#endif
+ /* Delay if previous commands are still being processed */
+ while ((--maxloops) > 0 && (dbri->wait_send != dbri->wait_ackd)) {
+ msleep_interruptible(1);
+ /* If dbri_cmdlock() got called from inside the
+ * interrupt handler, this will do the processing.
+ */
+ dbri_process_interrupt_buffer(dbri);
+ }
+ if (maxloops == 0) {
+ printk(KERN_ERR "DBRI: Chip never completed command buffer %d\n",
+ dbri->wait_send);
+ } else {
+ dprintk(D_CMD, "Chip completed command buffer (%d)\n",
+ MAXLOOPS - maxloops - 1);
+ }
+
/*if (get == GetLock) spin_lock(&dbri->lock); */
return &dbri->dma->cmd[0];
}
-static void dbri_process_interrupt_buffer(snd_dbri_t *);
-
static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd)
{
- int MAXLOOPS = 1000000;
- int maxloops = MAXLOOPS;
volatile s32 *ptr;
+ u32 reg;
for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) {
dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
}
if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) {
- printk("DBRI: Command buffer overflow! (bug in driver)\n");
+ printk(KERN_ERR "DBRI: Command buffer overflow! (bug in driver)\n");
/* Ignore the last part. */
cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3];
}
+ dbri->wait_send++;
+ dbri->wait_send &= 0xffff; /* restrict it to a 16 bit counter. */
*(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
- *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
- dbri->wait_seen = 0;
+ *(cmd++) = DBRI_CMD(D_WAIT, 1, dbri->wait_send);
+
+ /* Set command pointer and signal it is valid. */
sbus_writel(dbri->dma_dvma, dbri->regs + REG8);
- while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P))
- barrier();
- if (maxloops == 0) {
- printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
- dprintk(D_CMD, "DBRI: Chip never completed command buffer\n");
- } else {
- while ((--maxloops) > 0 && (!dbri->wait_seen))
- dbri_process_interrupt_buffer(dbri);
- if (maxloops == 0) {
- printk(KERN_ERR "DBRI: Chip never acked WAIT\n");
- dprintk(D_CMD, "DBRI: Chip never acked WAIT\n");
- } else {
- dprintk(D_CMD, "Chip completed command "
- "buffer (%d)\n", MAXLOOPS - maxloops);
- }
- }
+ reg = sbus_readl(dbri->regs + REG0);
+ reg |= D_P;
+ sbus_writel(reg, dbri->regs + REG0);
/*spin_unlock(&dbri->lock); */
}
@@ -757,10 +766,11 @@ static void dbri_initialize(snd_dbri_t * dbri)
for (n = 0; n < DBRI_NO_PIPES; n++)
dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1;
- /* We should query the openprom to see what burst sizes this
- * SBus supports. For now, just disable all SBus bursts */
+ /* A brute approach - DBRI falls back to working burst size by itself
+ * On SS20 D_S does not work, so do not try so high. */
tmp = sbus_readl(dbri->regs + REG0);
- tmp &= ~(D_G | D_S | D_E);
+ tmp |= D_G | D_E;
+ tmp &= ~D_S;
sbus_writel(tmp, dbri->regs + REG0);
/*
@@ -805,13 +815,13 @@ static void reset_pipe(snd_dbri_t * dbri, int pipe)
volatile int *cmd;
if (pipe < 0 || pipe > 31) {
- printk("DBRI: reset_pipe called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n");
return;
}
sdp = dbri->pipes[pipe].sdp;
if (sdp == 0) {
- printk("DBRI: reset_pipe called on uninitialized pipe\n");
+ printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n");
return;
}
@@ -834,12 +844,12 @@ static void reset_pipe(snd_dbri_t * dbri, int pipe)
static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
{
if (pipe < 0 || pipe > 31) {
- printk("DBRI: setup_pipe called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n");
return;
}
if ((sdp & 0xf800) != sdp) {
- printk("DBRI: setup_pipe called with strange SDP value\n");
+ printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n");
/* sdp &= 0xf800; */
}
@@ -872,13 +882,13 @@ static void link_time_slot(snd_dbri_t * dbri, int pipe,
int nextpipe;
if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) {
- printk
- ("DBRI: link_time_slot called with illegal pipe number\n");
+ printk(KERN_ERR
+ "DBRI: link_time_slot called with illegal pipe number\n");
return;
}
if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) {
- printk("DBRI: link_time_slot called on uninitialized pipe\n");
+ printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n");
return;
}
@@ -960,8 +970,8 @@ static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
int val;
if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) {
- printk
- ("DBRI: unlink_time_slot called with illegal pipe number\n");
+ printk(KERN_ERR
+ "DBRI: unlink_time_slot called with illegal pipe number\n");
return;
}
@@ -1001,22 +1011,22 @@ static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
volatile s32 *cmd;
if (pipe < 16 || pipe > 31) {
- printk("DBRI: xmit_fixed: Illegal pipe number\n");
+ printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) {
- printk("DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
- printk("DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
return;
}
if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
- printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
return;
}
@@ -1036,17 +1046,17 @@ static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
{
if (pipe < 16 || pipe > 31) {
- printk("DBRI: recv_fixed called with illegal pipe number\n");
+ printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n");
return;
}
if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
- printk("DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
return;
}
if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
- printk("DBRI: recv_fixed called on transmit pipe %d\n", pipe);
+ printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe);
return;
}
@@ -1075,12 +1085,12 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
int last_desc = -1;
if (info->pipe < 0 || info->pipe > 15) {
- printk("DBRI: setup_descs: Illegal pipe number\n");
+ printk(KERN_ERR "DBRI: setup_descs: Illegal pipe number\n");
return -2;
}
if (dbri->pipes[info->pipe].sdp == 0) {
- printk("DBRI: setup_descs: Uninitialized pipe %d\n",
+ printk(KERN_ERR "DBRI: setup_descs: Uninitialized pipe %d\n",
info->pipe);
return -2;
}
@@ -1090,20 +1100,20 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
if (streamno == DBRI_PLAY) {
if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) {
- printk("DBRI: setup_descs: Called on receive pipe %d\n",
+ printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n",
info->pipe);
return -2;
}
} else {
if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) {
- printk
- ("DBRI: setup_descs: Called on transmit pipe %d\n",
+ printk(KERN_ERR
+ "DBRI: setup_descs: Called on transmit pipe %d\n",
info->pipe);
return -2;
}
/* Should be able to queue multiple buffers to receive on a pipe */
if (pipe_active(dbri, info->pipe)) {
- printk("DBRI: recv_on_pipe: Called on active pipe %d\n",
+ printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n",
info->pipe);
return -2;
}
@@ -1120,7 +1130,7 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
break;
}
if (desc == DBRI_NO_DESCS) {
- printk("DBRI: setup_descs: No descriptors\n");
+ printk(KERN_ERR "DBRI: setup_descs: No descriptors\n");
return -1;
}
@@ -1165,7 +1175,7 @@ static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
}
if (first_desc == -1 || last_desc == -1) {
- printk("DBRI: setup_descs: Not enough descriptors available\n");
+ printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n");
return -1;
}
@@ -1270,7 +1280,7 @@ static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave,
int divisor = 12288 / clockrate;
if (divisor > 255 || divisor * clockrate != 12288)
- printk("DBRI: illegal bits_per_frame in setup_chi\n");
+ printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n");
*(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
| D_CHI_BPF(bits_per_frame));
@@ -1474,7 +1484,6 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
/* Temporarily mute outputs, and wait 1/8000 sec (125 us)
* to make sure this takes. This avoids clicking noises.
*/
-
cs4215_setdata(dbri, 1);
udelay(125);
@@ -1530,8 +1539,8 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
tmp |= D_C; /* Enable CHI */
sbus_writel(tmp, dbri->regs + REG0);
- for (i = 64; ((dbri->mm.status & 0xe4) != 0x20); --i) {
- udelay(125);
+ for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
+ msleep_interruptible(1);
}
if (i == 0) {
dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n",
@@ -1678,8 +1687,8 @@ buffer and calls dbri_process_one_interrupt() for each interrupt word.
Complicated interrupts are handled by dedicated functions (which
appear first in this file). Any pending interrupts can be serviced by
calling dbri_process_interrupt_buffer(), which works even if the CPU's
-interrupts are disabled. This function is used by dbri_cmdsend()
-to make sure we're synced up with the chip after each command sequence,
+interrupts are disabled. This function is used by dbri_cmdlock()
+to make sure we're synced up with the chip before each command sequence,
even if we're running cli'ed.
*/
@@ -1765,11 +1774,13 @@ DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0);
* Called by main interrupt handler when DBRI signals transmission complete
* on a pipe (interrupt triggered by the B bit in a transmit descriptor).
*
- * Walks through the pipe's list of transmit buffer descriptors, releasing
- * each one's DMA buffer (if present), flagging the descriptor available,
- * and signaling its callback routine (if present), before proceeding
- * to the next one. Stops when the first descriptor is found without
+ * Walks through the pipe's list of transmit buffer descriptors and marks
+ * them as available. Stops when the first descriptor is found without
* TBC (Transmit Buffer Complete) set, or we've run through them all.
+ *
+ * The DMA buffers are not released, but re-used. Since the transmit buffer
+ * descriptors are not clobbered, they can be re-submitted as is. This is
+ * done by the xmit_descs() tasklet above since that could take longer.
*/
static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
@@ -1885,7 +1896,11 @@ static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
}
if (channel == D_INTR_CMD && command == D_WAIT) {
- dbri->wait_seen++;
+ dbri->wait_ackd = val;
+ if (dbri->wait_send != val) {
+ printk(KERN_ERR "Processing wait command %d when %d was send.\n",
+ val, dbri->wait_send);
+ }
return;
}
@@ -1994,8 +2009,7 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
* The only one I've seen is MRR, which will be triggered
* if you let a transmit pipe underrun, then try to CDP it.
*
- * If these things persist, we should probably reset
- * and re-init the chip.
+ * If these things persist, we reset the chip.
*/
if ((++errcnt) % 10 == 0) {
dprintk(D_INT, "Interrupt errors exceeded.\n");
@@ -2094,7 +2108,7 @@ static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
if ((ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params))) < 0) {
- snd_printk(KERN_ERR "malloc_pages failed with %d\n", ret);
+ printk(KERN_ERR "malloc_pages failed with %d\n", ret);
return ret;
}
@@ -2455,8 +2469,7 @@ static int __init snd_dbri_mixer(snd_dbri_t * dbri)
for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
if ((err = snd_ctl_add(card,
- snd_ctl_new1(&dbri_controls[idx],
- dbri))) < 0)
+ snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
return err;
}
@@ -2490,8 +2503,6 @@ static void dbri_debug_read(snd_info_entry_t * entry,
int pipe;
snd_iprintf(buffer, "debug=%d\n", dbri_debug);
- snd_iprintf(buffer, "CHI pipe in=%d, out=%d\n",
- dbri->chi_in_pipe, dbri->chi_out_pipe);
for (pipe = 0; pipe < 32; pipe++) {
if (pipe_active(dbri, pipe)) {
struct dbri_pipe *pptr = &dbri->pipes[pipe];
@@ -2506,18 +2517,6 @@ static void dbri_debug_read(snd_info_entry_t * entry,
}
}
}
-
-static void dbri_debug_write(snd_info_entry_t * entry,
- snd_info_buffer_t * buffer)
-{
- char line[80];
- int i;
-
- if (snd_info_get_line(buffer, line, 80) == 0) {
- sscanf(line, "%d\n", &i);
- dbri_debug = i & 0x3f;
- }
-}
#endif
void snd_dbri_proc(snd_dbri_t * dbri)
@@ -2531,9 +2530,7 @@ void snd_dbri_proc(snd_dbri_t * dbri)
#ifdef DBRI_DEBUG
err = snd_card_proc_new(dbri->card, "debug", &entry);
snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read);
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR; /* Writable for root */
- entry->c.text.write_size = 256;
- entry->c.text.write = dbri_debug_write;
+ entry->mode = S_IFREG | S_IRUGO; /* Readable only. */
#endif
}
@@ -2637,7 +2634,11 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
return -ENOENT;
}
- prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+ err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+ if (err < 0) {
+ printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev);
+ return -ENODEV;
+ }
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(snd_dbri_t));
@@ -2657,26 +2658,20 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
}
dbri = (snd_dbri_t *) card->private_data;
- if ((err = snd_dbri_pcm(dbri)) < 0) {
- snd_dbri_free(dbri);
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_dbri_pcm(dbri)) < 0)
+ goto _err;
- if ((err = snd_dbri_mixer(dbri)) < 0) {
- snd_dbri_free(dbri);
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_dbri_mixer(dbri)) < 0)
+ goto _err;
/* /proc file handling */
snd_dbri_proc(dbri);
- if ((err = snd_card_register(card)) < 0) {
- snd_dbri_free(dbri);
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_set_generic_dev(card)) < 0)
+ goto _err;
+
+ if ((err = snd_card_register(card)) < 0)
+ goto _err;
printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n",
dev, dbri->regs,
@@ -2684,6 +2679,11 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
dev++;
return 0;
+
+ _err:
+ snd_dbri_free(dbri);
+ snd_card_free(card);
+ return err;
}
/* Probe for the dbri chip and then attach the driver. */
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 60d0b2c..9e2b4c0 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -40,7 +40,7 @@ int snd_emux_new(snd_emux_t **remu)
snd_emux_t *emu;
*remu = NULL;
- emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
+ emu = kzalloc(sizeof(*emu), GFP_KERNEL);
if (emu == NULL)
return -ENOMEM;
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index e41b28d..8ccd33f 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -146,7 +146,7 @@ snd_emux_create_port(snd_emux_t *emu, char *name,
int i, type, cap;
/* Allocate structures for this channel */
- if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
+ if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
snd_printk("no memory\n");
return NULL;
}
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 901a7db..d0925ea 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -266,7 +266,7 @@ newsf(snd_sf_list_t *sflist, int type, char *name)
}
/* not found -- create a new one */
- sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
+ sf = kzalloc(sizeof(*sf), GFP_KERNEL);
if (sf == NULL)
return NULL;
sf->id = sflist->fonts_size;
@@ -346,7 +346,7 @@ sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
{
snd_sf_zone_t *zp;
- if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
+ if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
return NULL;
zp->next = sf->zones;
sf->zones = zp;
@@ -377,7 +377,7 @@ sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
{
snd_sf_sample_t *sp;
- if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
+ if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
return NULL;
sp->next = sf->samples;
@@ -1362,7 +1362,7 @@ snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
{
snd_sf_list_t *sflist;
- if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
+ if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
return NULL;
init_MUTEX(&sflist->presets_mutex);
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index 8b131a1..5f75bf3 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -38,7 +38,7 @@ snd_util_memhdr_new(int memsize)
{
snd_util_memhdr_t *hdr;
- hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
+ hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
if (hdr == NULL)
return NULL;
hdr->size = memsize;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index bfbec58..d5ae2055 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1439,9 +1439,11 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
static snd_pcm_hardware_t snd_usb_playback =
{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
.buffer_bytes_max = (256*1024),
.period_bytes_min = 64,
.period_bytes_max = (128*1024),
@@ -1451,9 +1453,11 @@ static snd_pcm_hardware_t snd_usb_playback =
static snd_pcm_hardware_t snd_usb_capture =
{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
.buffer_bytes_max = (256*1024),
.period_bytes_min = 64,
.period_bytes_max = (128*1024),
@@ -3132,7 +3136,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
return -ENOMEM;
}
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_card_free(card);
return -ENOMEM;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 93dedde..e0d0365 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -841,7 +841,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
int length;
rep->in = NULL;
- ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
if (!ep)
return -ENOMEM;
ep->umidi = umidi;
@@ -913,7 +913,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
void* buffer;
rep->out = NULL;
- ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
if (!ep)
return -ENOMEM;
ep->umidi = umidi;
@@ -1537,7 +1537,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
int out_ports, in_ports;
int i, err;
- umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
+ umidi = kzalloc(sizeof(*umidi), GFP_KERNEL);
if (!umidi)
return -ENOMEM;
umidi->chip = chip;
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index fa7056f..c3c08c9 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -824,7 +824,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
if (check_ignored_ctl(state, unitid, control))
return;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return;
@@ -997,7 +997,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
if (check_ignored_ctl(state, unitid, 0))
return;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval)
return;
@@ -1244,7 +1244,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
continue;
if (check_ignored_ctl(state, unitid, valinfo->control))
continue;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
@@ -1430,7 +1430,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
if (check_ignored_ctl(state, unitid, 0))
return 0;
- cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+ cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
@@ -1945,7 +1945,7 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
strcpy(chip->card->mixername, "USB Mixer");
- mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
+ mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
if (!mixer)
return -ENOMEM;
mixer->chip = chip;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 62dfd28..0f09e0d 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -957,7 +957,7 @@ static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int c
for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
- usX2Y_substream[i] = kcalloc(1, sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
+ usX2Y_substream[i] = kzalloc(sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
if (NULL == usX2Y_substream[i]) {
snd_printk(KERN_ERR "cannot malloc\n");
return -ENOMEM;
OpenPOWER on IntegriCloud